607 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			607 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | ||
|   <section class="reportAtWillDetail">
 | ||
|     <ai-detail>
 | ||
|       <template #title>
 | ||
|         <ai-title
 | ||
|           title="事件详情"
 | ||
|           isShowBack
 | ||
|           isShowBottomBorder
 | ||
|           @onBackClick="$emit('back')">
 | ||
|           <template #rightBtn>
 | ||
|             <template v-if="hasHandled">
 | ||
|               <el-button
 | ||
|                 icon="iconfont iconRepulsebeifen"
 | ||
|                 v-if="
 | ||
|                   report.permissions('app_appreportatwillinfo_edit') &&
 | ||
|                     detail.publicityStatus == 0
 | ||
|                 "
 | ||
|                 @click="handlePublic(detail)"
 | ||
|                 >公示事件
 | ||
|               </el-button>
 | ||
|               <el-button
 | ||
|                 icon="iconfont iconRepulse"
 | ||
|                 v-if="
 | ||
|                   report.permissions('app_appreportatwillinfo_edit') &&
 | ||
|                     detail.publicityStatus == 1
 | ||
|                 "
 | ||
|                 @click="handlePublic(detail)"
 | ||
|               >
 | ||
|                 取消公示
 | ||
|               </el-button>
 | ||
|             </template>
 | ||
|             <template v-else>
 | ||
|               <ai-wechat-selecter :isMultiple="false" :instance="report.instance" v-model="userList" @change="v => handleAppoint(v, detail)">
 | ||
|                 <el-button
 | ||
|                   icon="iconfont iconPerson_Transfered"
 | ||
|                   v-if="report.permissions('app_appreportatwillinfo_edit')"
 | ||
|                   >指派人员
 | ||
|                 </el-button>
 | ||
|               </ai-wechat-selecter>
 | ||
|               <el-button
 | ||
|                 type="primary"
 | ||
|                 icon="iconfont iconRegister"
 | ||
|                 @click="dialogShow"
 | ||
|                 v-if="report.permissions('app_appreportatwillinfo_edit')"
 | ||
|                 >处理事件
 | ||
|               </el-button>
 | ||
|               <el-button
 | ||
|                 type="primary"
 | ||
|                 icon="iconfont iconClock"
 | ||
|                 @click.once="handleUrge"
 | ||
|                 v-if="
 | ||
|                   report.permissions('app_appreportatwillinfo_edit') &&
 | ||
|                     !!detail.assignUserId &&
 | ||
|                     detail.handleFlow.some(e => e.assignUserId == user.info.id)
 | ||
|                 "
 | ||
|               >
 | ||
|                 短信催办
 | ||
|               </el-button>
 | ||
|             </template>
 | ||
|           </template>
 | ||
|         </ai-title>
 | ||
|       </template>
 | ||
| 
 | ||
|       <!-- 详情 -->
 | ||
|       <template #content>
 | ||
|         <div class="detail-content__wrapper">
 | ||
|           <ai-card class="detail-content__wrapper--left" title="基础信息">
 | ||
|             <template #content>
 | ||
|               <ai-wrapper :columnsNumber="1">
 | ||
|                 <ai-info-item label="处理状态">
 | ||
|                   <span
 | ||
|                     :style="{
 | ||
|                       color: detail.status === '0' ? '#F79300' : '#222'
 | ||
|                     }"
 | ||
|                     >{{
 | ||
|                       report.dict.getLabel(
 | ||
|                         'reportAtWillHandleStatus',
 | ||
|                         detail.status
 | ||
|                       )
 | ||
|                     }}</span
 | ||
|                   >
 | ||
|                 </ai-info-item>
 | ||
|                 <ai-info-item label="上报时间">{{
 | ||
|                   detail.createTime
 | ||
|                 }}</ai-info-item>
 | ||
|                 <ai-info-item label="区域">{{ detail.areaName }}</ai-info-item>
 | ||
|                 <ai-info-item label="地点">{{ detail.address }}</ai-info-item>
 | ||
|                 <ai-info-item label="事件位置">
 | ||
|                   <div id="map" style="width: 400px; height: 240px;"></div>
 | ||
|                 </ai-info-item>
 | ||
|                 <ai-info-item label="事件描述">{{
 | ||
|                   detail.explain
 | ||
|                 }}</ai-info-item>
 | ||
|                 <ai-info-item label="现场照片">
 | ||
|                   <ai-uploader
 | ||
|                     :instance="instance"
 | ||
|                     disabled
 | ||
|                     v-model="detail.files"
 | ||
|                   ></ai-uploader>
 | ||
|                 </ai-info-item>
 | ||
|               </ai-wrapper>
 | ||
|             </template>
 | ||
|           </ai-card>
 | ||
| 
 | ||
|           <div class="rightZone">
 | ||
|             <ai-card title="处理结果">
 | ||
|               <template #content>
 | ||
|                 <ai-wrapper :columnsNumber="1" label-width="60px">
 | ||
|                   <!-- <ai-info-item label="处理人员">{{ detail.handleUserName }}</ai-info-item>
 | ||
|                   <ai-info-item label="处理结果">{{ detail.handleResult || '-' }}</ai-info-item> -->
 | ||
|                   <ai-info-item label="上报类型">{{
 | ||
|                     dict.getLabel('atWillReportType', detail.reportType)
 | ||
|                   }}</ai-info-item>
 | ||
|                   <ai-info-item label="事件类型">{{
 | ||
|                     detail.ruleName || '-'
 | ||
|                   }}</ai-info-item>
 | ||
|                   <ai-info-item label="信用积分"
 | ||
|                     ><span style="color: #2266FF;">{{
 | ||
|                       detail.integral > 0
 | ||
|                         ? '+' + detail.integral
 | ||
|                         : detail.integral
 | ||
|                     }}</span></ai-info-item
 | ||
|                   >
 | ||
|                   <ai-info-item label="处理结果">{{
 | ||
|                     detail.handleResult || '-'
 | ||
|                   }}</ai-info-item>
 | ||
|                   <ai-info-item label="现场照片">
 | ||
|                     <div class="imgs" v-viewer="{ movable: true }">
 | ||
|                       <img
 | ||
|                         :src="item.url"
 | ||
|                         v-for="(item, index) in detail.handleFiles"
 | ||
|                         :key="index"
 | ||
|                       />
 | ||
|                     </div>
 | ||
|                   </ai-info-item>
 | ||
|                 </ai-wrapper>
 | ||
|               </template>
 | ||
|             </ai-card>
 | ||
|             <ai-card title="处理记录">
 | ||
|               <template #content>
 | ||
|                 <el-steps direction="vertical" :active="1">
 | ||
|                   <el-step
 | ||
|                     v-for="(step, i) in handleLogs"
 | ||
|                     :key="i"
 | ||
|                     :title="step.title"
 | ||
|                     :description="step.description"
 | ||
|                   >
 | ||
|                     <template #title>
 | ||
|                       <h2
 | ||
|                         class="step-title"
 | ||
|                         style="font-weight: 500; font-size: 14px;"
 | ||
|                       >
 | ||
|                         {{ step.title }}
 | ||
|                       </h2>
 | ||
|                     </template>
 | ||
|                     <template #description>
 | ||
|                       <p
 | ||
|                         style="color: #888; margin: 0 4px 10px 0; font-size: 14px;"
 | ||
|                       >
 | ||
|                         {{ step.description }}
 | ||
|                       </p>
 | ||
|                     </template>
 | ||
|                   </el-step>
 | ||
|                 </el-steps>
 | ||
|               </template>
 | ||
|             </ai-card>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|       </template>
 | ||
|     </ai-detail>
 | ||
|     
 | ||
|     <ai-dialog
 | ||
|       class="report-dialog"
 | ||
|       :visible.sync="dialog"
 | ||
|       width="800px"
 | ||
|       title="处理事件"
 | ||
|       @closed="form = {}"
 | ||
|       @onConfirm="handleEvent"
 | ||
|     >
 | ||
|       <el-form
 | ||
|         size="small"
 | ||
|         label-width="100px"
 | ||
|         label-suffix=":"
 | ||
|         :rules="rules"
 | ||
|         :model="form"
 | ||
|         ref="handleForm"
 | ||
|       >
 | ||
|         <el-form-item label="上报类型" prop="reportType">
 | ||
|           <ai-select
 | ||
|             style="width: 100%"
 | ||
|             v-model="form.reportType"
 | ||
|             @change="onChange"
 | ||
|             placeholder="请选择上报类型"
 | ||
|             :selectList="dict.getDict('atWillReportType')"
 | ||
|           >
 | ||
|           </ai-select>
 | ||
|         </el-form-item>
 | ||
|         <el-form-item label="事件类型" prop="ruleId">
 | ||
|           <el-select
 | ||
|             v-model="form.ruleId"
 | ||
|             placeholder="请选择事件类型"
 | ||
|             size="small"
 | ||
|           >
 | ||
|             <el-option
 | ||
|               v-for="(item, index) in eventList"
 | ||
|               :key="index"
 | ||
|               :label="item.ruleName"
 | ||
|               :value="item.id"
 | ||
|             >
 | ||
|               <span style="float: left">{{ item.ruleName }}</span>
 | ||
|               <span style="float: right; color: #8492a6; font-size: 13px"
 | ||
|                 >积分{{ item.integral }}</span
 | ||
|               >
 | ||
|             </el-option>
 | ||
|           </el-select>
 | ||
|         </el-form-item>
 | ||
|         <el-form-item label="处理结果" prop="handleResult">
 | ||
|           <el-input
 | ||
|             type="textarea"
 | ||
|             :rows="5"
 | ||
|             maxlength="200"
 | ||
|             v-model="form.handleResult"
 | ||
|             clearable
 | ||
|             placeholder="请输入处理结果"
 | ||
|             show-word-limit
 | ||
|           />
 | ||
|         </el-form-item>
 | ||
|         <el-form-item label="图片" prop="handleFiles">
 | ||
|           <ai-uploader
 | ||
|             :instance="instance"
 | ||
|             v-model="form.handleFiles"
 | ||
|             :limit="9"
 | ||
|             isShowTip
 | ||
|           ></ai-uploader>
 | ||
|         </el-form-item>
 | ||
|       </el-form>
 | ||
|     </ai-dialog>
 | ||
|   </section>
 | ||
| </template>
 | ||
| 
 | ||
| <script>
 | ||
| import AMapLoader from '@amap/amap-jsapi-loader'
 | ||
| import { mapState } from 'vuex'
 | ||
| 
 | ||
| export default {
 | ||
|   name: 'reportAtWillDetail',
 | ||
| 
 | ||
|   props: ['dict', 'instance', 'permissions', 'id'],
 | ||
| 
 | ||
|   computed: {
 | ||
|     ...mapState(['user']),
 | ||
|     hasHandled() {
 | ||
|       return this.detail.status == 1
 | ||
|     },
 | ||
|     handleLogs() {
 | ||
|       let starter = {
 | ||
|           title: `收到用户(${this.detail.nickName})上报的事件信息,等待处理。`,
 | ||
|           description: this.detail.createTime
 | ||
|         },
 | ||
|         handleUser = [],
 | ||
|         process =
 | ||
|           this.detail.handleFlow?.map(e => ({
 | ||
|             title: `${e.assignUserName} 查看了信息,并分配了${e.handleUserName}处理任务。`,
 | ||
|             description: e.assignTime
 | ||
|           })) || []
 | ||
|       this.detail.status == 1 &&
 | ||
|         this.detail.handleUserName &&
 | ||
|         handleUser.push({
 | ||
|           title: `${this.detail.handleUserName}反馈了处理结果。`,
 | ||
|           description: this.detail.handleTime
 | ||
|         })
 | ||
|       return [starter, ...process, ...handleUser]
 | ||
|     },
 | ||
|     rules() {
 | ||
|       return {
 | ||
|         handleResult: [{ required: true, message: '请填写处理结果' }],
 | ||
|         ruleId: [{ required: true, message: '请选择事件类型' }],
 | ||
|         reportType: [{ required: true, message: '请选择上报类型' }]
 | ||
|       }
 | ||
|     }
 | ||
|   },
 | ||
|   data() {
 | ||
|     return {
 | ||
|       detail: {},
 | ||
|       eventList: [],
 | ||
|       dialog: false,
 | ||
|       userList: [],
 | ||
|       form: {
 | ||
|         ruleId: '',
 | ||
|         handleFiles: [],
 | ||
|         reportType: ''
 | ||
|       }
 | ||
|     }
 | ||
|   },
 | ||
|   created() {
 | ||
|     this.dict
 | ||
|       .load(
 | ||
|         'reportAtWillPublicityStatus',
 | ||
|         'reportAtWillHandleStatus',
 | ||
|         'atWillReportType'
 | ||
|       )
 | ||
|       .then(() => {
 | ||
|         this.getDetail()
 | ||
|       })
 | ||
|   },
 | ||
|   methods: {
 | ||
|     getDetail() {
 | ||
|       this.id &&
 | ||
|         this.report.instance
 | ||
|           .post('/app/appreportatwillinfo/queryDetailById', null, {
 | ||
|             params: { id: this.id }
 | ||
|           })
 | ||
|           .then(res => {
 | ||
|             if (res?.data) {
 | ||
|               this.detail = res.data
 | ||
| 
 | ||
|               this.$nextTick(() => {
 | ||
|                 this.initMap()
 | ||
|               })
 | ||
|             }
 | ||
|           })
 | ||
|     },
 | ||
| 
 | ||
|     onChange(e) {
 | ||
|       this.instance
 | ||
|         .post(
 | ||
|           `/app/appvillagerintegralrule/list?size=1000&classification=${e}&ruleStatus=1`
 | ||
|         )
 | ||
|         .then(res => {
 | ||
|           if (res.code === 0) {
 | ||
|             this.form.ruleId = ''
 | ||
|             this.eventList = res.data.records
 | ||
|           }
 | ||
|         })
 | ||
|     },
 | ||
| 
 | ||
|     initMap() {
 | ||
|       let { lng, lat } = this.detail,
 | ||
|         center = [lng, lat]
 | ||
|       lng &&
 | ||
|         lat &&
 | ||
|         AMapLoader.load({
 | ||
|           key: '54a02a43d9828a8f9cd4f26fe281e74e',
 | ||
|           version: '2.0' // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
 | ||
|         })
 | ||
|           .then(AMap => {
 | ||
|             let map = new AMap.Map('map', {
 | ||
|               center,
 | ||
|               zoom: 14
 | ||
|             })
 | ||
|             let marker = new AMap.Marker({
 | ||
|               position: new AMap.LngLat(lng, lat),
 | ||
|               title: this.detail.address
 | ||
|             })
 | ||
|             map.add(marker)
 | ||
|           })
 | ||
|           .catch(e => {
 | ||
|           })
 | ||
|     },
 | ||
|     handlePublic(ev) {
 | ||
|       this.$confirm(
 | ||
|         `是否对该事件${ev.publicityStatus == 0 ? '进行公示' : '取消公示'}`
 | ||
|       )
 | ||
|         .then(() => {
 | ||
|           this.report.instance
 | ||
|             .post('/app/appreportatwillinfo/publicity', null, {
 | ||
|               params: { id: ev.id }
 | ||
|             })
 | ||
|             .then(res => {
 | ||
|               if (res?.code == 0) {
 | ||
|                 this.$message.success('操作成功!')
 | ||
|                 this.$emit('back')
 | ||
|               }
 | ||
|             })
 | ||
|         })
 | ||
|         .catch(() => 0)
 | ||
|     },
 | ||
|     handleAppoint(person, row) {
 | ||
|       this.report.instance
 | ||
|         .post('/app/appreportatwillinfo/assign', {
 | ||
|           handleUserId: person?.[0].id,
 | ||
|           handleUserName: person?.[0].name + ' ' + person?.[0].phone,
 | ||
|           infoId: row.id
 | ||
|         })
 | ||
|         .then(res => {
 | ||
|           this.userList = []
 | ||
|           if (res?.code == 0) {
 | ||
|             this.$message.success('指派成功!')
 | ||
|             this.$emit('back')
 | ||
|           }
 | ||
|         }).catch(() => {
 | ||
|         this.userList = []
 | ||
|       })
 | ||
|     },
 | ||
|     handleUrge() {
 | ||
|       this.$confirm('是否要进行短信催办?')
 | ||
|         .then(() => {
 | ||
|           this.report.instance
 | ||
|             .post('/app/appreportatwillinfo/urging')
 | ||
|             .then(res => {
 | ||
|               if (res?.code == 0) {
 | ||
|                 this.$message.success('催办成功!')
 | ||
|                 this.$emit('back')
 | ||
|               }
 | ||
|             })
 | ||
|         })
 | ||
|         .catch(() => 0)
 | ||
|     },
 | ||
|     handleEvent() {
 | ||
|       this.$refs.handleForm.validate(v => {
 | ||
|         if (v) {
 | ||
|           this.report.instance
 | ||
|             .post('/app/appreportatwillinfo/handle', {
 | ||
|               ...this.detail,
 | ||
|               ...this.form
 | ||
|             })
 | ||
|             .then(res => {
 | ||
|               if (res?.code == 0) {
 | ||
|                 this.$message.success('处理成功!')
 | ||
|                 this.$emit('back')
 | ||
|               }
 | ||
|             })
 | ||
|         }
 | ||
|       })
 | ||
|     },
 | ||
|     handleUpload({ file }) {
 | ||
|       if (file) {
 | ||
|         let formData = new FormData()
 | ||
|         formData.append('file', file)
 | ||
|         this.report.instance.post('/admin/file/add', formData).then(res => {
 | ||
|           if (res?.data) {
 | ||
|             let fileInfos = res.data?.[0]?.split(';')
 | ||
|             this.form.handleFiles?.push({
 | ||
|               id: fileInfos[1],
 | ||
|               accessUrl: fileInfos[0],
 | ||
|               filename: file.name,
 | ||
|               size: file.size
 | ||
|             }) ||
 | ||
|               (this.form.handleFiles = [
 | ||
|                 {
 | ||
|                   id: fileInfos[1],
 | ||
|                   accessUrl: fileInfos[0],
 | ||
|                   filename: file.name,
 | ||
|                   size: file.size
 | ||
|                 }
 | ||
|               ])
 | ||
|           }
 | ||
|         })
 | ||
|       }
 | ||
|     },
 | ||
|     handleUploadRemove(file) {
 | ||
|       let index = this.form.handleFiles.findIndex(e => e.id == file.id)
 | ||
|       index > -1 && this.form.handleFiles.splice(index, 1)
 | ||
|     },
 | ||
|     dialogShow() {
 | ||
|       this.dialog = true
 | ||
|       this.form.reportType = this.detail.reportType
 | ||
|       this.onChange(this.detail.reportType)
 | ||
|     }
 | ||
|   },
 | ||
|   inject: ['report']
 | ||
| }
 | ||
| </script>
 | ||
| 
 | ||
| <style lang="scss" scoped>
 | ||
| .reportAtWillDetail {
 | ||
|   height: 100%;
 | ||
| 
 | ||
|   .el-steps {
 | ||
|     ::v-deep .el-step__icon {
 | ||
|       font-size: 12px;
 | ||
|       color: #555555;
 | ||
|       border-color: #d0d4dc;
 | ||
|     }
 | ||
| 
 | ||
|     ::v-deep .el-step__head.is-finish {
 | ||
|       .el-step__icon.is-text {
 | ||
|         border: none;
 | ||
|         color: #fff;
 | ||
|         font-size: 12px;
 | ||
|         background: #2266ff;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     ::v-deep .el-step__line {
 | ||
|       background-color: #d0d4dc;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   .imgs {
 | ||
|     font-size: 0;
 | ||
| 
 | ||
|     img {
 | ||
|       width: 108px;
 | ||
|       height: 108px;
 | ||
|       margin-right: 4px;
 | ||
|       margin-bottom: 4px;
 | ||
|       cursor: pointer;
 | ||
|       user-select: none;
 | ||
| 
 | ||
|       &:hover {
 | ||
|         opacity: 0.8;
 | ||
|       }
 | ||
| 
 | ||
|       &:nth-of-type(2n) {
 | ||
|         margin-right: 0;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   ::v-deep .report-dialog {
 | ||
|     .el-select {
 | ||
|       width: 100%;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   ::v-deep .ailist-title {
 | ||
|     .el-button {
 | ||
|       margin-left: 0 !important;
 | ||
|     }
 | ||
|   }
 | ||
|   ::v-deep .el-step__head.is-process {
 | ||
|     color: #555;
 | ||
|     border-color: #555;
 | ||
|   }
 | ||
| 
 | ||
|   ::v-deep .is-finish h2 {
 | ||
|     color: #2266ff;
 | ||
|   }
 | ||
| 
 | ||
|   .step-title {
 | ||
|     color: #555;
 | ||
|   }
 | ||
| 
 | ||
|   .detail-content__wrapper {
 | ||
|     display: flex;
 | ||
|     width: 100%;
 | ||
| 
 | ||
|     .detail-content__wrapper--left {
 | ||
|       flex: 1;
 | ||
|       margin-right: 20px;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   ::v-deep .ai-detail__content {
 | ||
|     background: #f3f6f9;
 | ||
| 
 | ||
|     .ai-detail__content--wrapper {
 | ||
|       display: flex;
 | ||
|       gap: 16px;
 | ||
|       width: 100%;
 | ||
|       max-width: 100%;
 | ||
|       padding: 16px;
 | ||
|       box-sizing: border-box;
 | ||
| 
 | ||
|       & > .el-card {
 | ||
|         flex: 1;
 | ||
|         min-width: 0;
 | ||
|       }
 | ||
| 
 | ||
|       .rightZone {
 | ||
|         width: 400px;
 | ||
|         flex-shrink: 0;
 | ||
|         display: flex;
 | ||
|         flex-direction: column;
 | ||
|         gap: 16px;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   ::v-deep .el-card {
 | ||
|     .el-card__header {
 | ||
|       padding: 12px 16px;
 | ||
|       font-weight: bold;
 | ||
|     }
 | ||
| 
 | ||
|     .el-card__body {
 | ||
|       padding: 8px;
 | ||
|     }
 | ||
| 
 | ||
|     #amap {
 | ||
|       width: 466px;
 | ||
|       height: 232px;
 | ||
|     }
 | ||
| 
 | ||
|     .el-steps {
 | ||
|       margin-left: 8px;
 | ||
|     }
 | ||
| 
 | ||
|     .imgFormItem > .el-form-item__content {
 | ||
|       display: flex;
 | ||
|       gap: 16px;
 | ||
|       flex-wrap: wrap;
 | ||
| 
 | ||
|       &:before {
 | ||
|         content: none;
 | ||
|       }
 | ||
| 
 | ||
|       .el-image__inner {
 | ||
|         width: 82px;
 | ||
|         height: 82px;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| </style>
 |