<template>
|
<view class="content">
|
<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">
|
<view class="flex1" v-if="time">
|
{{ time }}
|
</view>
|
<view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
|
请选择问题发生的时间
|
</view>
|
<image src="/static/Appeal/left.png" class="w-19 h-19" mode=""></image>
|
</view>
|
</view>
|
</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="flex1" v-if="problemType">
|
{{ problemType }}
|
</view>
|
<view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
|
请选择问题类型
|
</view>
|
<image src="/static/Appeal/left.png" class="w-19 h-19" mode=""></image>
|
</view>
|
</view>
|
<view class="card flex a-center h-108 j-between">
|
<text class="w-108 fs-27 font-bold mr-85">群众姓名</text>
|
<input v-model="name" placeholder-style="color: rgba(0,0,0,0.3);font-size:27rpx;"
|
class="uni-input flex1" placeholder="请输入群众姓名" />
|
|
</view>
|
<view class="card flex a-center h-108 j-between">
|
<text class="w-108 fs-27 font-bold mr-85">联系电话</text>
|
<input v-model="contactNumber" type="number" placeholder-style="color: rgba(0,0,0,0.3);font-size:27rpx;"
|
class="uni-input flex1" maxlength="11" placeholder="请输入群众联系电话" />
|
|
</view>
|
<view class="card flex min-108 a-center j-between" @click="goTopagelocation()">
|
<text class="w-108 fs-27 font-bold mr-85">发生地点</text>
|
<view class=" flex a-center j-between flex1">
|
|
<view class="flex1 address line2" v-if="location">
|
{{ location }}
|
</view>
|
<view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
|
请选择问题发生具体地点
|
</view>
|
<image src="/static/Appeal/left.png" class="w-19 h-19" mode=""></image>
|
</view>
|
</view>
|
<view class="card flex a-center h-108 j-between">
|
<text class="w-108 fs-27 font-bold mr-85">详细地址</text>
|
<input v-model="detailedAddress" placeholder-style="color: rgba(0,0,0,0.3);font-size:27rpx;"
|
class="uni-input flex1" placeholder="请输入详细地址描述" />
|
</view>
|
<view class="mt-35">
|
<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">
|
<image src="/static/Appeal/yuyin.png" class="w-30 h-30 mr-11" mode=""></image>
|
<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;"
|
class="h-94 pl-31 flex1" placeholder="请输入问题标题" />
|
</view> -->
|
<textarea name="" v-model="descriptionContent" id="" cols="30" placeholder="请输入问题描述内容"
|
placeholder-style="color: rgba(0, 0, 0, 0.30);font-size:27rpx;" rows="10"></textarea>
|
</view>
|
</view>
|
<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">
|
<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"
|
mode=""></image>
|
<image class="w-19 h-19 ml-35" @click="deletimg(item)" src="/static/Appeal/trash.png"
|
mode="">
|
</image>
|
</view>
|
</view>
|
<image src="/static/Appeal/add.png" class="w-140 h-140" mode="" @click="uploadImg"></image>
|
</view>
|
</view>
|
<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">
|
<video :controls="false" :show-center-play-btn="false" :src="item" class="w-140 h-140"
|
mode=""></video>
|
<view class="img-icon">
|
<image class="w-19 h-19" @click="gotoPage(item)" src="/static/Appeal/amplify.png" mode="">
|
</image>
|
<image class="w-19 h-19 ml-35" @click="deletvideo(item)" src="/static/Appeal/trash.png"
|
mode=""></image>
|
</view>
|
</view>
|
<image src="/static/Appeal/add.png" class="w-140 h-140" mode="" @click="uploadVideo"></image>
|
</view>
|
</view>
|
</view>
|
<view class="footer">
|
<view class="cancel" @click="submit(1)">
|
问题上报
|
</view>
|
<view class="cancel" @click="submit(2)">
|
办理结果录入
|
</view>
|
<view class="ok" @click="submit(3)">
|
保存
|
</view>
|
</view>
|
<u-datetime-picker :show="showDate" v-model="value1" mode="date" :closeOnClickOverlay="true"
|
@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 voiceInputPopup from '@/components/voiceInputPopup.vue'
|
import {
|
mapActions,
|
mapState
|
} from "vuex";
|
|
export default {
|
components: {
|
voiceInputPopup
|
},
|
data() {
|
return {
|
showList: false,
|
showDate: false,
|
value1: Number(new Date()),
|
columns: [
|
['医疗', '教育', '就业', '住房', '养老']
|
],
|
time: '',
|
problemType: '',
|
name: '',
|
contactNumber: '',
|
detailedAddress: '',
|
descriptionTitle: '',
|
descriptionContent: '',
|
videoContent: [],
|
latitude: '',
|
longitude: '',
|
location: '',
|
images: [],
|
videos: [],
|
voiceFile: '', //语音文件多个逗号拼接
|
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);
|
},
|
onPausePlaying(index) {
|
this.videoContent[index].playing = false;
|
this.pausePlaying(this.videoContent[index].url);
|
},
|
voiceInput() {
|
this.voiceInputShow = true;
|
},
|
closeVoiceInput() {
|
this.voiceInputShow = false;
|
},
|
submitVoiceInput(e) {
|
console.log('eeeeeeeeeeeeeeeeeee', e)
|
this.videoContent.push({
|
url: e.url,
|
data: e.data,
|
playing: false
|
});
|
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}`
|
})
|
},
|
getproblem() {
|
getproblem().then((resp => {
|
|
this.columns = [resp.data.map(item => {
|
return item.name
|
})]
|
}))
|
},
|
async submit(type) {
|
if (this.videoContent.length > 0) {
|
uni.showLoading({
|
title: '正在上传语音文件...'
|
});
|
|
const uploadPromises = this.videoContent.map(item => {
|
return new Promise((resolve, reject) => {
|
console.log('item.data', item.data)
|
// uni.chooseAudio({
|
// success: (res)=> {
|
// console.log(res.tempFilePaths[0]);
|
// uni.uploadFile({
|
// url: config.imageUrl,
|
// filePath: res.tempFilePaths[0], // 使用 Blob 数据
|
// name: 'file',
|
// header: {
|
// // 'Content-Type': 'multipart/form-data',
|
// 'Authorization': uni.getStorageSync('token')
|
// },
|
// success: (uploadFileRes) => {
|
// const response = JSON.parse(uploadFileRes.data);
|
// if (response.code === 200) {
|
// resolve(response.data);
|
// } else {
|
// reject(new Error('上传失败'));
|
// }
|
// },
|
// fail: (error) => {
|
// reject(error);
|
// }
|
// });
|
// }
|
// });
|
uni.uploadFile({
|
url: config.imageUrl,
|
file: item.data, // 使用 Blob 数据
|
name: 'file',
|
header: {
|
// 'Content-Type': 'multipart/form-data',
|
'Authorization': uni.getStorageSync('token')
|
},
|
success: (uploadFileRes) => {
|
const response = JSON.parse(uploadFileRes.data);
|
if (response.code === 200) {
|
resolve(response.data);
|
} else {
|
reject(new Error('上传失败'));
|
}
|
},
|
fail: (error) => {
|
reject(error);
|
}
|
});
|
});
|
});
|
|
try {
|
const uploadedUrls = await Promise.all(uploadPromises);
|
this.voiceFile = uploadedUrls.join(',');
|
console.log('this.voiceFile', this.voiceFile)
|
uni.hideLoading();
|
} catch (error) {
|
uni.hideLoading();
|
uni.showToast({
|
title: '语音文件上传失败',
|
icon: 'error'
|
});
|
return;
|
}
|
}
|
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(','),
|
voiceFile: this.voiceFile,
|
}
|
// 问题上报
|
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()
|
console.log('res.tempFilePaths[0]', res.tempFilePaths[0])
|
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
|
}
|
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;
|
}
|
|
.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;
|
}
|
}
|
|
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;
|
}
|
}
|
|
/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;
|
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;
|
}
|
}
|
</style>
|