医疗预约系统中的录音与图片上传功能实现:Vue3+Uniapp 实战

发布于:2025-07-12 ⋅ 阅读:(16) ⋅ 点赞:(0)

在移动医疗应用开发中,实现便捷的多媒体交互功能对于提升用户体验至关重要。本文将详细介绍如何在医疗预约系统中集成录音和图片上传功能,结合 Vue3 和 Uniapp 框架,打造流畅的患者就诊记录交互体验。

功能概述

我们实现的医疗记录页面包含以下核心功能:

  • 就诊人信息管理与切换
  • 就诊详情展示
  • 图片上传功能
  • 录音录制与上传功能
  • 预约确认流程

下面我们将重点解析图片上传和录音功能的实现细节,这两个功能是提升医疗记录丰富性的关键。 

界面设计与布局

首先来看整体界面结构,我们采用了分区设计,将不同功能模块清晰分离:

<template>
	<div class="medical-record-container">
		<!-- 就诊人信息区域 -->
		<div class="patient-info">
			<!-- 就诊人信息内容 -->
		</div>
		
		<!-- 就诊详情区域 -->
		<div class="visit-details">
			<!-- 就诊详情内容 -->
			
			<!-- 录音播放区域 -->
			<div class="detail-item">
				<span class="label">录音</span>
				<span class="value" style="display: flex;align-items: center;gap: 10px;" @click="playAudio">
					<uv-icon size="28" color="rgb(42,130,228)" name="play-circle-fill"></uv-icon> {{ audioDuration || '00:00' }}
				</span>
			</div>
			
			<!-- 添加图片、录音按钮区域 -->
			<div class="action-btns">
				<div class="action-btn" @click="openPopups" style="border-right: 1px solid #ddd;">添加图片</div>
				<div class="action-btn" @click="openPopupes">添加录音</div>
			</div>
		</div>
		
		<!-- 文字描述输入区域 -->
		<div class="desc-section">
			<!-- 文字描述内容 -->
		</div>
		
		<!-- 费用及确认区域 -->
		<div class="footer">
			<!-- 费用及确认按钮 -->
		</div>
		
		<!-- 图片上传弹窗 -->
		<uv-popup ref="popups" mode="bottom">
			<!-- 图片上传组件 -->
		</uv-popup>
		
		<!-- 录音弹窗 -->
		<uv-popup ref="popupes" mode="bottom">
			<!-- 录音组件 -->
		</uv-popup>
	</div>
</template>

界面设计遵循了医疗应用的专业性与易用性原则,采用清晰的视觉层级和直观的交互方式,让用户能够轻松完成图片和录音的添加操作。 

图片上传功能实现

图片上传功能允许用户添加医疗相关的图片资料,如检查报告、处方等,实现代码如下:

// 图片上传相关状态
const fileList1 = ref([]);
const imgurl = ref('');

// 打开图片上传弹窗
const openPopups = () => {
	popups.value?.open();
};

// 删除图片
const deletePic = (event) => {
	fileList1.value.splice(event.index, 1);
};

// 选择图片后处理
const afterRead = async (event) => {
	// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
	let lists = [].concat(event.file);
	let fileListLen = fileList1.value.length;

	lists.map((item) => {
		fileList1.value.push({
			...item,
			status: 'uploading',
			message: '上传中'
		});
	});

	for (let i = 0; i < lists.length; i++) {
		const result = await uploadFilePromise(lists[i].url);
		let item = fileList1.value[fileListLen];
		fileList1.value.splice(fileListLen, 1, Object.assign(item, {
			status: 'success',
			message: '',
			url: result
		}));
		fileListLen++;
	}
};

// 上传文件Promise封装
const uploadFilePromise = (urls) => {
	return new Promise((resolve, reject) => {
		uni.uploadFile({
			url: 'https://yiliao.kuxia.top/pc/Fileimg/file',
			filePath: urls,
			name: 'file',
			formData: {
				user: 'test'
			},
			success: (res) => {
				setTimeout(() => {
					const response = JSON.parse(res.data);
					resolve(response.data.url);
					imgurl.value = response.data.url;
				}, 1000);
			},
			fail: (err) => {
				reject(err);
			}
		});
	});
};

图片上传流程设计考虑了以下几点:

  1. 使用弹窗形式展示上传界面,不占用主界面空间
  2. 实现了上传进度显示,提升用户体验
  3. 支持图片删除操作,方便用户纠错
  4. 通过 Promise 封装上传过程,便于异步流程控制

录音功能实现

录音功能是医疗记录中的重要补充,能够记录医生的口头医嘱或患者的症状描述,实现代码如下:

// 录音相关状态和变量
const audioDuration = ref('00:00');
const isRecording = ref(false);
const recorderManager = ref(null);
const audioPath = ref('');
const recordTime = ref(0);
const recordTimer = ref(null);
const audioUploaded = ref(false);
const audioUrl = ref('');

// 初始化录音管理器
const initRecorder = () => {
	recorderManager.value = uni.getRecorderManager();

	recorderManager.value.onStart(() => {
		console.log('录音开始');
		isRecording.value = true;
		startRecordTimer();
	});

	recorderManager.value.onStop((res) => {
		console.log('录音结束', res);
		isRecording.value = false;
		stopRecordTimer();
		audioPath.value = res.tempFilePath;
		// 更新显示的录音时长
		updateAudioDuration(res.duration);
	});

	recorderManager.value.onError((err) => {
		console.error('录音失败:', err);
		isRecording.value = false;
		stopRecordTimer();
		uni.showToast({
			title: '录音失败',
			icon: 'none'
		});
	});
};

// 开始录音计时器
const startRecordTimer = () => {
	recordTime.value = 0;
	recordTimer.value = setInterval(() => {
		recordTime.value++;
		updateAudioDuration(recordTime.value * 1000);
	}, 1000);
};

// 停止录音计时器
const stopRecordTimer = () => {
	if (recordTimer.value) {
		clearInterval(recordTimer.value);
		recordTimer.value = null;
	}
};

// 更新录音时长显示
const updateAudioDuration = (durationMs) => {
	const durationSec = Math.floor(durationMs / 1000);
	const minutes = Math.floor(durationSec / 60).toString().padStart(2, '0');
	const seconds = (durationSec % 60).toString().padStart(2, '0');
	audioDuration.value = `${minutes}:${seconds}`;
};

// 点击录音按钮事件
const toggleRecord = () => {
	if (isRecording.value) {
		// 停止录音
		recorderManager.value.stop();
	} else {
		// 开始录音
		recorderManager.value.start({
			format: 'mp3',
			duration: 600000, // 最长10分钟
			sampleRate: 44100,
			numberOfChannels: 1,
			encodeBitRate: 192000
		});
		audioUploaded.value = false;
	}
};

// 确认上传录音
const confirmUpload = async () => {
	if (!audioPath.value) {
		uni.showToast({
			title: '请先录制音频',
			icon: 'none'
		});
		return;
	}

	try {
		uni.showLoading({
			title: '上传中...'
		});

		// 上传录音文件
		const uploadedUrl = await uploadAudioFile(audioPath.value);

		uni.showToast({
			title: '上传成功',
			icon: 'success'
		});

		audioUploaded.value = true;
		audioUrl.value = uploadedUrl;
		popupes.value?.close();

	} catch (error) {
		console.error('上传失败:', error);
		uni.showToast({
			title: '上传失败',
			icon: 'none'
		});
	} finally {
		uni.hideLoading();
	}
};

// 播放录音
const playAudio = () => {
	if (!audioPath.value) {
		uni.showToast({
			title: '暂无录音',
			icon: 'none'
		});
		return;
	}

	const innerAudioContext = uni.createInnerAudioContext();
	innerAudioContext.src = audioPath.value;
	innerAudioContext.play();

	innerAudioContext.onError((res) => {
		console.error('播放失败:', res);
		uni.showToast({
			title: '播放失败',
			icon: 'none'
		});
	});
};

录音功能的设计亮点:

  1. 直观的录音时长显示,采用分:秒格式
  2. 录音状态清晰可见,通过颜色变化提示用户
  3. 完整的错误处理机制,确保录音过程稳定
  4. 支持录音播放功能,方便用户确认录音内容

数据提交与预约确认

最后,我们需要将所有信息(包括文字描述、图片和录音)提交到服务器,完成预约流程:

const confirm = async () => {
	if (!visitdata.value?.card) {
		uni.showToast({
			title: '请选择就诊人',
			icon: 'none'
		});
		return;
	}

	try {
		console.log({
			user_id: uni.getStorageSync('userInfo').id,
			card: visitdata.value.card,
			depart_id: department.value?.id,
			doctor_id: doctor_id,
			price: doctor.value?.doctorInfo?.money,
			trends: desc.value,
			img: imgurl.value,
			audio: audioUrl.value,
			status: 1,
			create_time: time_date,
			time: time_value,
		});

		const res = await addRegister({
			// 提交的数据包括图片和录音的URL
			user_id: uni.getStorageSync('userInfo').id,
			card: visitdata.value.card,
			depart_id: department.value?.id,
			doctor_id: doctor_id,
			price: doctor.value?.doctorInfo?.money,
			trends: desc.value,
			img: imgurl.value,
			audio: audioUrl.value,
			status: 1,
			create_time: time_date,
			time: time_value,
		});

		console.log(res);

		if (res.code == 1) {
			// 显示成功提示弹窗
			successModal.value.open();
		} else {
			uni.showToast({
				title: res.msg,
				icon: 'none'
			});
		}
	} catch (err) {
		console.log(err);
		uni.showToast({
			title: '预约失败',
			icon: 'none'
		});
	}
};

总结与优化建议

本文实现的图片和录音上传功能,为医疗预约系统增添了丰富的多媒体交互能力。在实际应用中,还可以考虑以下优化方向:

  1. 实现图片压缩功能,减少上传流量和时间
  2. 增加录音转文字功能,提高记录的可搜索性
  3. 支持多图上传和多段录音,满足复杂医疗场景需求
  4. 实现上传中断后的断点续传功能

通过这些功能的实现,医疗应用能够更好地服务于医患双方,提高医疗记录的完整性和准确性,为远程医疗和复诊提供更全面的参考资料。 

 


网站公告

今日签到

点亮在社区的每一天
去签到