From c3c8a7bfa080808136fe2da590e760ba7cb98f9e Mon Sep 17 00:00:00 2001
From: 董国庆 <364620639@qq.com>
Date: 星期一, 19 五月 2025 10:10:43 +0800
Subject: [PATCH] 新增弹窗

---
 H5/pages/Appeal/Appeal.vue |  735 +++++++++++++++++++++++++++++++-------------------------
 1 files changed, 405 insertions(+), 330 deletions(-)

diff --git a/H5/pages/Appeal/Appeal.vue b/H5/pages/Appeal/Appeal.vue
index b5b3d4e..9275f7f 100644
--- a/H5/pages/Appeal/Appeal.vue
+++ b/H5/pages/Appeal/Appeal.vue
@@ -3,10 +3,10 @@
 		<view class="main">
 			<view class="card  flex a-center h-108 j-between">
 				<text class="w-108 fs-27 font-bold mr-85">发生时间</text>
-				<view class=" flex a-center j-between flex1" @click="showDate=true">
+				<view class=" flex a-center j-between flex1" @click="showDate = true">
 					<view class=" flex a-center j-between flex1">
 						<view class="flex1" v-if="time">
-							{{time}}
+							{{ time }}
 						</view>
 						<view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
 							请选择问题发生的时间
@@ -17,10 +17,10 @@
 			</view>
 			<view class="card  flex a-center h-108 j-between">
 				<text class="w-108 fs-27 font-bold mr-85">问题类型</text>
-				<view class=" flex a-center j-between flex1" @click="showList=true">
+				<view class=" flex a-center j-between flex1" @click="showList = true">
 
 					<view class="flex1" v-if="problemType">
-						{{problemType}}
+						{{ problemType }}
 					</view>
 					<view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
 						请选择问题类型
@@ -45,7 +45,7 @@
 				<view class=" flex a-center j-between flex1">
 
 					<view class="flex1 address line2" v-if="location">
-						{{location}}
+						{{ location }}
 					</view>
 					<view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
 						请选择问题发生具体地点
@@ -59,7 +59,29 @@
 					class="uni-input flex1" placeholder="请输入详细地址描述" />
 			</view>
 			<view class="mt-35">
-				<text class="w-108 fs-27 font-bold mr-85">问题描述</text>
+				<view class="flex a-center j-between">
+					<text class="w-108 fs-27 font-bold mr-85">问题描述</text>
+					<view class="flex a-center" @click="voiceInput">
+
+						<text class="fs-23 red">语音输入</text>
+					</view>
+				</view>
+				<view v-for="item, index in videoContent" :key="index">
+					<view class="pl-19 pr-19 pb-17 pt-17 flex j-between a-center br-8 pink">
+						<view class="flex1">
+							<text class="fs-27 font-bold">语音文件{{ index + 1 }}</text>
+						</view>
+						<view class="flex j-between a-center">
+							<image src="/static/Appeal/delete.png" class="w-27 h-27 mr-38" mode=""></image>
+
+							<image src="/static/Appeal/open.png" class="w-27 h-27" mode="" v-if="!item.playing"
+								@click.stop="onPlayRecording(index)"></image>
+							<image src="/static/Appeal/pause.png" class="w-27 h-27" mode="" v-else
+								@click.stop="onPausePlaying(index)"></image>
+						</view>
+
+					</view>
+				</view>
 				<view class="bg mt-27 fs-27">
 					<!-- <view class="h-94 " style="border-bottom: 2rpx solid rgba(0, 10, 26, 0.07);">
 						<input v-model="descriptionTitle" placeholder-style="color: rgba(0,0,0,0.3);font-size:27rpx;"
@@ -72,7 +94,7 @@
 			<view class="mt-35">
 				<text class="w-108 fs-27 font-bold mr-85">上传图片</text>
 				<view class="mt-27 flex a-center flex" style="flex-wrap: wrap;">
-					<view class="img mr-15" v-for="item,index in images" :key="index">
+					<view class="img mr-15" v-for="item, index in images" :key="index">
 						<image :src="item" class="w-140 h-140" mode=""></image>
 						<view class="img-icon">
 							<image class="w-19 h-19" @click="previewImage(index)" src="/static/Appeal/amplify.png"
@@ -88,7 +110,7 @@
 			<view class="mt-35">
 				<text class="w-108 fs-27 font-bold mr-85">上传视频</text>
 				<view class="mt-27 flex a-center flex" style="flex-wrap: wrap;">
-					<view class="img mr-15" v-for="item,index in videos" :key="index">
+					<view class="img mr-15" v-for="item, index in videos" :key="index">
 						<video :controls="false" :show-center-play-btn="false" :src="item" class="w-140 h-140"
 							mode=""></video>
 						<view class="img-icon">
@@ -117,363 +139,416 @@
 			@confirm="confirmone" @close="close" @cancel="cancel"></u-datetime-picker>
 		<u-picker :show="showList" :columns="columns" @confirm="confirmtwo" :closeOnClickOverlay="true" @close="close"
 			@cancel="cancel"></u-picker>
+		<!-- 语音输入弹窗 -->
+		<voiceInputPopup :show="voiceInputShow" @update:show="voiceInputShow = $event" @close="closeVoiceInput"
+			@submit="submitVoiceInput" />
 	</view>
 </template>
 
 <script>
-	import dayjs from '@/uni_modules/uview-ui/libs/util/dayjs.js';
-	import {
-		save,
-		getproblem
-	} from './service.js'
-	import config from '@/config/index.js'
+import dayjs from '@/uni_modules/uview-ui/libs/util/dayjs.js';
+import {
+	save,
+	getproblem
+} from './service.js'
+import config from '@/config/index.js'
+import voiceInputPopup from '@/components/voiceInputPopup.vue'
+import {
+		mapActions,
+		mapState
+	} from "vuex";
 
-	export default {
-		data() {
-			return {
-				showList: false,
-				showDate: false,
-				value1: Number(new Date()),
-				columns: [
-					['医疗', '教育', '就业', '住房', '养老']
-				],
-				time: '',
-				problemType: '',
-				name: '',
-				contactNumber: '',
-				location: '',
-				detailedAddress: '',
-				descriptionTitle: '',
-				descriptionContent: '',
-				latitude: '',
-				longitude: '',
-				images: [],
-				videos: [],
-				userInfo: uni.getStorageSync('userInfo'), //个人信息
-			};
+export default {
+	components: {
+		voiceInputPopup
+	},
+	data() {
+		return {
+			showList: false,
+			showDate: false,
+			value1: Number(new Date()),
+			columns: [
+				['医疗', '教育', '就业', '住房', '养老']
+			],
+			time: '',
+			problemType: '',
+			name: '',
+			contactNumber: '',
+			location: '',
+			detailedAddress: '',
+			descriptionTitle: '',
+			descriptionContent: '',
+			videoContent: [
+				{ url: 'xxx1', playing: false },
+				{ url: 'xxx2', playing: false }
+			],
+			latitude: '',
+			longitude: '',
+			images: [],
+			videos: [],
+			userInfo: uni.getStorageSync('userInfo'), //个人信息
+			voiceInputShow: false,
+		};
+	},
+	computed: {
+		...mapState(["playFlag"]),
+	},
+	onReady() {
+		uni.setNavigationBarTitle({
+			title: '诉求录入'
+		})
+	},
+	onLoad() {
+		this.getproblem()
+		this.time = dayjs().format('YYYY-MM-DD')
+	},
+	
+	methods: {
+		...mapActions(["playRecording", "pausePlaying"]),
+		onPlayRecording(index) {
+			// 先处理本地播放状态
+			this.videoContent.forEach((item, i) => {
+				item.playing = i === index;
+			});
+			// 调用store的播放方法,传url
+			this.playRecording(this.videoContent[index].url);
 		},
-		onReady() {
-			uni.setNavigationBarTitle({
-				title: '诉求录入'
+		onPausePlaying(index) {
+			this.videoContent[index].playing = false;
+			this.pausePlaying(this.videoContent[index].url);
+		},
+		voiceInput() {
+			this.voiceInputShow = true;
+		},
+		closeVoiceInput() {
+			this.voiceInputShow = false;
+		},
+		submitVoiceInput(e) {
+			this.videoContent.push(e);
+			this.voiceInputShow = false;
+		},
+		previewImage(index) {
+			uni.previewImage({
+				urls: this.images,
+				current: this.images[index],
+				longPressActions: {
+					itemList: ['发送给朋友', '保存图片', '收藏'],
+					success: function (data) {
+
+					},
+					fail: function (err) {
+
+					}
+				}
+			});
+		},
+		deletimg(e) {
+			this.images = this.images.filter(item => item != e)
+
+		},
+		deletvideo(e) {
+			this.videos = this.videos.filter(item => item != e)
+		},
+		gotoPage(e) {
+			uni.navigateTo({
+				url: `/pages/work-detail/maxVideo?url=${e}`
 			})
 		},
-		onLoad() {
-			this.getproblem()
-			this.time = dayjs().format('YYYY-MM-DD')
+		getproblem() {
+			getproblem().then((resp => {
+
+				this.columns = [resp.data.map(item => {
+					return item.name
+				})]
+			}))
 		},
-		methods: {
-			previewImage(index) {
-				uni.previewImage({
-					urls: this.images,
-					current: this.images[index],
-					longPressActions: {
-						itemList: ['发送给朋友', '保存图片', '收藏'],
-						success: function(data) {
+		submit(type) {
+			const preciseRegex = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
+			if (!this.time) {
+				uni.showToast({
+					title: '请选择时间',
+					icon: 'none'
+				})
+				return
 
+			} else if (!this.problemType) {
+				uni.showToast({
+					title: '请选择问题类型',
+					icon: 'none'
+				})
+				return
+			} else if (!this.name) {
+				uni.showToast({
+					title: '请输入群众姓名',
+					icon: 'none'
+				})
+				return
+			} else if (!this.contactNumber) {
+				uni.showToast({
+					title: '请输入联系电话',
+					icon: 'none'
+				})
+				return
+			} else if (!preciseRegex.test(this.contactNumber)) {
+				uni.showToast({
+					title: '请输入正确的手机号',
+					icon: 'none'
+				})
+				return
+			} else if (!this.location) {
+				uni.showToast({
+					title: '请选择地点',
+					icon: 'none'
+				})
+				return
+			} else if (!this.detailedAddress) {
+				uni.showToast({
+					title: '请输入详细地址',
+					icon: 'none'
+				})
+				return
+			}
+			const data = {
+				time: this.time,
+				problemType: this.problemType,
+				name: this.name,
+				contactNumber: this.contactNumber,
+				location: this.location,
+				latitude: this.latitude,
+				longitude: this.longitude,
+				detailedAddress: this.detailedAddress,
+				descriptionContent: this.descriptionContent,
+				images: this.images.join(','),
+				videos: this.videos.join(','),
+			}
+			// 问题上报
+			if (type == 1) {
+				uni.navigateTo({
+					url: `/pages/problemReporting/problemReporting?data=${JSON.stringify(data)}`
+				})
+				return
+			}
+			// 办理结果录入
+			if (type == 2) {
+				uni.navigateTo({
+					url: `/pages/result-entry/index?data=${JSON.stringify(data)}`
+				})
+				return
+			}
+			// 添加
+			if (type == 3) {
+				save(data).then(resp => {
+					if (resp.code == 200) {
+						uni.showToast({
+							title: '保存成功',
+							icon: 'none'
+						})
+						setTimeout(() => {
+							uni.navigateBack()
+						}, 1500)
+					}
+				})
+			}
+		},
+		confirmone(e) {
+
+			this.time = dayjs(e.value).format('YYYY-MM-DD')
+			this.showDate = false
+		},
+		confirmtwo(e) {
+
+			this.problemType = e.value[0]
+			this.showList = false
+		},
+		cancel() {
+			this.showDate = false
+			this.showList = false
+		},
+		close(e) {
+			this.showDate = false
+			this.showList = false
+		},
+		goTopagelocation() {
+
+			uni.navigateTo({
+				url: '/pages/location/location'
+			})
+		},
+		uploadImg() {
+			uni.chooseImage({
+				count: 1, //默认9
+				sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+				sourceType: ['album'], //从相册选择
+				success: (res) => {
+
+					uni.showLoading()
+					uni.uploadFile({
+						url: config.imageUrl,
+						filePath: res.tempFilePaths[0],
+						name: 'file',
+						header: {
+							'Authorization': uni.getStorageSync('token')
 						},
-						fail: function(err) {
+						success: (uploadFileRes) => {
 
-						}
-					}
-				});
-			},
-			deletimg(e) {
-				this.images = this.images.filter(item => item != e)
-
-			},
-			deletvideo(e) {
-				this.videos = this.videos.filter(item => item != e)
-			},
-			gotoPage(e) {
-				uni.navigateTo({
-					url: `/pages/work-detail/maxVideo?url=${e}`
-				})
-			},
-			getproblem() {
-				getproblem().then((resp => {
-
-					this.columns = [resp.data.map(item => {
-						return item.name
-					})]
-				}))
-			},
-			submit(type) {
-				const preciseRegex = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
-				if (!this.time) {
-					uni.showToast({
-						title: '请选择时间',
-						icon: 'none'
-					})
-					return
-
-				} else if (!this.problemType) {
-					uni.showToast({
-						title: '请选择问题类型',
-						icon: 'none'
-					})
-					return
-				} else if (!this.name) {
-					uni.showToast({
-						title: '请输入群众姓名',
-						icon: 'none'
-					})
-					return
-				} else if (!this.contactNumber) {
-					uni.showToast({
-						title: '请输入联系电话',
-						icon: 'none'
-					})
-					return
-				} else if (!preciseRegex.test(this.contactNumber)) {
-					uni.showToast({
-						title: '请输入正确的手机号',
-						icon: 'none'
-					})
-					return
-				} else if (!this.location) {
-					uni.showToast({
-						title: '请选择地点',
-						icon: 'none'
-					})
-					return
-				} else if (!this.detailedAddress) {
-					uni.showToast({
-						title: '请输入详细地址',
-						icon: 'none'
-					})
-					return
-				}
-				const data = {
-					time: this.time,
-					problemType: this.problemType,
-					name: this.name,
-					contactNumber: this.contactNumber,
-					location: this.location,
-					latitude: this.latitude,
-					longitude: this.longitude,
-					detailedAddress: this.detailedAddress,
-					descriptionContent: this.descriptionContent,
-					images: this.images.join(','),
-					videos: this.videos.join(','),
-				}
-				// 问题上报
-				if (type == 1) {
-					uni.navigateTo({
-						url: `/pages/problemReporting/problemReporting?data=${JSON.stringify(data)}`
-					})
-					return
-				}
-				// 办理结果录入
-				if (type == 2) {
-					uni.navigateTo({
-						url: `/pages/result-entry/index?data=${JSON.stringify(data)}`
-					})
-					return
-				}
-				// 添加
-				if (type == 3) {
-					save(data).then(resp => {
-						if (resp.code == 200) {
+							this.images = [...this.images, JSON.parse(uploadFileRes.data).data]
+							uni.hideLoading()
+						},
+						fail: () => {
+							uni.hideLoading()
 							uni.showToast({
-								title: '保存成功',
-								icon: 'none'
+								title: '上传失败',
+								icon: 'error'
 							})
-							setTimeout(() => {
-								uni.navigateBack()
-							}, 1500)
 						}
 					})
 				}
-			},
-			confirmone(e) {
-
-				this.time = dayjs(e.value).format('YYYY-MM-DD')
-				this.showDate = false
-			},
-			confirmtwo(e) {
-
-				this.problemType = e.value[0]
-				this.showList = false
-			},
-			cancel() {
-				this.showDate = false
-				this.showList = false
-			},
-			close(e) {
-				this.showDate = false
-				this.showList = false
-			},
-			goTopagelocation() {
-
-				uni.navigateTo({
-					url: '/pages/location/location'
-				})
-			},
-			uploadImg() {
-				uni.chooseImage({
-					count: 1, //默认9
-					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
-					sourceType: ['album'], //从相册选择
-					success: (res) => {
-
-						uni.showLoading()
-						uni.uploadFile({
-							url: config.imageUrl,
-							filePath: res.tempFilePaths[0],
-							name: 'file',
-							header: {
-								'Authorization': uni.getStorageSync('token')
-							},
-							success: (uploadFileRes) => {
-
-								this.images = [...this.images, JSON.parse(uploadFileRes.data).data]
-								uni.hideLoading()
-							},
-							fail: () => {
-								uni.hideLoading()
-								uni.showToast({
-									title: '上传失败',
-									icon: 'error'
-								})
-							}
+			});
+		},
+		uploadVideo() {
+			uni.chooseVideo({
+				count: 1, //默认9
+				sourceType: ['camera', 'album'],
+				success: (res) => {
+					const videoExtensions = /\.(mp4|avi|rmvb)$/i;
+					if (!videoExtensions.test(res.name)) {
+						uni.showToast({
+							title: '请上传mp4, avi, rmvb格式的视频',
+							icon: 'none',
+							duration: 3000
 						})
+						return
 					}
-				});
-			},
-			uploadVideo() {
-				uni.chooseVideo({
-					count: 1, //默认9
-					sourceType: ['camera', 'album'],
-					success: (res) => {
-						const videoExtensions = /\.(mp4|avi|rmvb)$/i;
-						if (!videoExtensions.test(res.name)) {
+					uni.showLoading()
+					uni.uploadFile({
+						url: config.imageUrl,
+						filePath: res.tempFilePath,
+						name: 'file',
+						header: {
+							'Authorization': uni.getStorageSync('token')
+						},
+						success: (uploadFileRes) => {
+
+							this.videos = [...this.videos, JSON.parse(uploadFileRes.data).data]
+							uni.hideLoading()
+						},
+						fail: () => {
+							uni.hideLoading()
 							uni.showToast({
-								title: '请上传mp4, avi, rmvb格式的视频',
-								icon: 'none',
-								duration: 3000
+								title: '上传失败',
+								icon: 'error'
 							})
-							return
 						}
-						uni.showLoading()
-						uni.uploadFile({
-							url: config.imageUrl,
-							filePath: res.tempFilePath,
-							name: 'file',
-							header: {
-								'Authorization': uni.getStorageSync('token')
-							},
-							success: (uploadFileRes) => {
-
-								this.videos = [...this.videos, JSON.parse(uploadFileRes.data).data]
-								uni.hideLoading()
-							},
-							fail: () => {
-								uni.hideLoading()
-								uni.showToast({
-									title: '上传失败',
-									icon: 'error'
-								})
-							}
-						})
-					}
-				});
-			},
-		}
+					})
+				}
+			});
+		},
 	}
+}
 </script>
 
 <style lang="scss" scoped>
-	.min-108 {
-		min-height: 108rpx;
+.min-108 {
+	min-height: 108rpx;
+}
+
+.red {
+	color: rgba(255, 73, 72, 1);
+}
+
+.pink {
+	background: #FFF1F4;
+	border-radius: 8rpx;
+	margin-top: 19rpx;
+}
+
+.card {
+	border-bottom: 2rpx solid rgba(0, 10, 26, 0.07);
+}
+
+.bg {
+	background: #F8F8F8;
+}
+
+.content {
+	padding: 38rpx 31rpx 162rpx 31rpx;
+
+	.main {
+		padding: 0 27rpx 48rpx 27rpx;
+		background: #FFFFFF;
+		box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
+		border-radius: 19rpx;
 	}
+}
 
-	.card {
-		border-bottom: 2rpx solid rgba(0, 10, 26, 0.07);
+textarea {
+	padding: 27rpx 31rpx 27rpx 31rpx;
+	font-weight: 500;
+}
+
+.img {
+	position: relative;
+
+	.img-icon {
+		height: 140rpx;
+		line-height: 140rpx;
+		position: absolute;
+		top: 0rpx;
+		left: 35rpx;
 	}
+}
 
-	.bg {
-		background: #F8F8F8;
-	}
+/deep/.u-popup__content {
+	border-radius: 16rpx 16rpx 0rpx 0rpx;
+}
 
-	.content {
-		padding: 38rpx 31rpx 162rpx 31rpx;
+/deep/ .u-toolbar {
+	border-bottom: 2rpx solid RGBA(243, 243, 243, 1);
+}
 
-		.main {
-			padding: 0 27rpx 48rpx 27rpx;
-			background: #FFFFFF;
-			box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
-			border-radius: 19rpx;
-		}
-	}
+/deep/ .u-toolbar__wrapper__cancel {
+	font-weight: 400;
+	font-size: 30rpx;
+	color: #FF4948 !important;
+}
 
-	textarea {
-		padding: 27rpx 31rpx 27rpx 31rpx;
-		font-weight: 500;
-	}
+/deep/ .u-toolbar__wrapper__confirm {
+	font-weight: 400;
+	font-size: 30rpx;
+	color: #FF4948 !important;
+}
 
-	.img {
-		position: relative;
+.footer {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	box-shadow: 0rpx -4rpx 27rpx 0rpx rgba(0, 0, 0, 0.08);
+	width: calc(100% - 20rpx);
+	background-color: #fff;
+	display: flex;
+	gap: 27rpx;
+	padding: 33rpx 10rpx;
 
-		.img-icon {
-			height: 140rpx;
-			line-height: 140rpx;
-			position: absolute;
-			top: 0rpx;
-			left: 35rpx;
-		}
-	}
-
-	/deep/.u-popup__content {
-		border-radius: 16rpx 16rpx 0rpx 0rpx;
-	}
-
-	/deep/ .u-toolbar {
-		border-bottom: 2rpx solid RGBA(243, 243, 243, 1);
-	}
-
-	/deep/ .u-toolbar__wrapper__cancel {
-		font-weight: 400;
-		font-size: 30rpx;
-		color: #FF4948 !important;
-	}
-
-	/deep/ .u-toolbar__wrapper__confirm {
-		font-weight: 400;
-		font-size: 30rpx;
-		color: #FF4948 !important;
-	}
-
-	.footer {
-		position: fixed;
-		bottom: 0;
-		left: 0;
-		box-shadow: 0rpx -4rpx 27rpx 0rpx rgba(0, 0, 0, 0.08);
-		width: calc(100% - 20rpx);
-		background-color: #fff;
+	.cancel {
+		width: 331rpx;
+		height: 77rpx;
+		border: 2rpx solid rgba(252, 141, 85, 1);
+		border-radius: 38rpx;
 		display: flex;
-		gap: 27rpx;
-		padding: 33rpx 10rpx;
-
-		.cancel {
-			width: 331rpx;
-			height: 77rpx;
-			border: 2rpx solid rgba(252, 141, 85, 1);
-			border-radius: 38rpx;
-			display: flex;
-			align-items: center;
-			justify-content: center;
-			color: #FF4948;
-		}
-
-		.ok {
-			width: 331rpx;
-			height: 77rpx;
-			background: linear-gradient(270deg, #FC8D55 0%, #FF4948 100%);
-			border-radius: 48rpx;
-			display: flex;
-			align-items: center;
-			justify-content: center;
-			color: #FFFFFF;
-		}
+		align-items: center;
+		justify-content: center;
+		color: #FF4948;
 	}
+
+	.ok {
+		width: 331rpx;
+		height: 77rpx;
+		background: linear-gradient(270deg, #FC8D55 0%, #FF4948 100%);
+		border-radius: 48rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		color: #FFFFFF;
+	}
+}
 </style>
\ No newline at end of file

--
Gitblit v1.7.1