Files
dvcp_v2_webapp/project/biaopin/AppReportAiWill/components/Detail.vue
2024-02-29 17:03:54 +08:00

756 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<ai-detail class="reportAtWillDetail" v-loading="isLoading">
<template #title>
<ai-title title="详情" isShowBack isShowBottomBorder @onBackClick="cancel(false)">
<template #rightBtn>
<div class="title-btns">
<el-button type="primary" icon="iconfont iconPerson_Transfered" @click="isShowForward = true" v-if="detail.rightType == 2">指派事件</el-button>
<el-button type="primary" icon="iconfont iconRegister" @click="handelClick" v-if="detail.rightType < 3 && detail.rightType != null">处理事件</el-button>
<!-- <el-button type="primary" icon="iconfont iconRegister" @click="isShowTalk = true" v-if="detail.eventStatus < 2">事件研判</el-button>
<el-button type="primary" icon="iconfont iconRegister" @click="isShowMediate = true" v-if="detail.eventStatus < 2">矛盾调解</el-button> -->
</div>
</template>
</ai-title>
</template>
<template #content>
<div class="detail-content__wrapper">
<div class="detail-content__wrapper--left">
<ai-card title="基础信息">
<template #content>
<ai-wrapper>
<ai-info-item label="上报人员" :value="detail.name"></ai-info-item>
<ai-info-item label="当前状态" :value="dict.getLabel('weiyangEventStatus', detail.eventStatus)"></ai-info-item>
<ai-info-item label="联系方式">{{ detail.phone }}</ai-info-item>
<ai-info-item label="上报时间">{{ detail.createTime }}</ai-info-item>
<ai-info-item label="事件类型">{{ detail.groupName }}</ai-info-item>
<ai-info-item label="事件来源" :value="dict.getLabel('weiyangEventType', detail.type)"></ai-info-item>
<ai-info-item label="事件描述" isLine>{{ detail.content }}</ai-info-item>
<ai-info-item label="现场照片" isLine>
<ai-uploader :instance="instance" disabled v-model="detail.files"></ai-uploader>
</ai-info-item>
<ai-info-item label="所属网格">{{ detail.girdName }}</ai-info-item>
<ai-info-item label="事件位置" isLine>
<div id="map" style="width: 500px; height: 280px;"></div>
</ai-info-item>
</ai-wrapper>
</template>
</ai-card>
<ai-card title="事件研判" v-if="detail.judgeName">
<template #content>
<ai-wrapper>
<ai-info-item label="当事人姓名" :value="detail.judgeName"></ai-info-item>
<ai-info-item label="联系电话" :value="detail.judgePhone"></ai-info-item>
<ai-info-item label="性别" :value="dict.getLabel('sex', detail.judgeSex)"></ai-info-item>
<ai-info-item label="家庭住址" isLine>{{ detail.judgeAddress }}</ai-info-item>
<ai-info-item label="排查内容" isLine>
<span v-for="(item, index) in detail.judgeRiskList" :key="index">
<span v-if="index > 0">,</span>{{dict.getLabel('weiyangRisk', item)}}
</span>
</ai-info-item>
</ai-wrapper>
</template>
</ai-card>
<ai-card title="调解信息" v-if="detail.mediateAreaName">
<template #content>
<ai-wrapper>
<ai-info-item label="调解主体" :value="detail.mediateAreaName"></ai-info-item>
<ai-info-item label="涉及金额" :value="detail.mediateAmount"></ai-info-item>
<ai-info-item label="调解员" :value="detail.mediatePerson"></ai-info-item>
<ai-info-item label="参加人">{{ detail.mediateMember || '无'}}</ai-info-item>
<ai-info-item label="调解时间" :value="detail.mediateDate"></ai-info-item>
<ai-info-item label="调处思路、措施及主要过程" isLine>{{ detail.mediateInfo }}</ai-info-item>
<ai-info-item label="调处结果">调解成功</ai-info-item>
</ai-wrapper>
</template>
</ai-card>
<ai-evaluation v-if="!!detail.id" :bid="detail.id" :info.sync="evaluation"/>
</div>
<div class="rightZone">
<ai-card title="办理进度">
<template #content>
<el-steps direction="vertical" :active="1">
<el-step
v-for="(item, i) in process"
:key="i"
:title="item.systemExplain"
:description="item.doTime">
<template #title>
<h2 class="step-title" style="font-weight: 500; font-size: 14px;">
{{ item.systemExplain }}
</h2>
</template>
<template #description>
<p style="color: #888; margin: 0 4px 10px 0; font-size: 14px;">{{ item.doTime }}</p>
<div style="color: #444;margin-bottom: 10px;" v-if="item.doExplain">{{ item.doExplain }}</div>
<ai-uploader :instance="instance" disabled v-model="item.files"></ai-uploader>
</template>
</el-step>
</el-steps>
</template>
</ai-card>
</div>
</div>
<ai-dialog
:visible.sync="isShowAdd"
width="800px"
title="事件处理"
@closed="onClose"
@onConfirm="handleEvent('form')">
<el-form class="ai-form" label-width="120px" :model="form" ref="form">
<el-form-item label="事件分类" prop="groupId" style="width: 100%;" :rules="[{ required: true, message: '请选择事件分类' }]">
<ai-select
v-model="form.groupId"
placeholder="请选择事件分类"
:selectList="dictList">
</ai-select>
</el-form-item>
<el-form-item label="处理结果" prop="eventStatus" style="width: 100%;" :rules="[{ required: true, message: '请选择处理结果' }]">
<el-radio-group v-model="form.eventStatus">
<el-radio label="3">已办结</el-radio>
<el-radio label="4">已拒绝</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="处理意见" prop="content" style="width: 100%;" :rules="[{ required: true, message: '请输入处理意见' }]">
<el-input type="textarea" :rows="5" :maxlength="500" v-model="form.content" clearable placeholder="请输入处理意见" show-word-limit></el-input>
</el-form-item>
<el-form-item label="图片" prop="files" style="width: 100%;">
<ai-uploader
:instance="instance"
isShowTip
v-model="form.files"
:limit="9">
</ai-uploader>
</el-form-item>
</el-form>
</ai-dialog>
<ai-dialog
:visible.sync="isShowTalk"
width="800px"
title="事件研判"
@closed="onClose"
@onConfirm="handleEvent('talkForm')">
<el-form class="ai-form" label-width="120px" :model="talkForm" ref="talkForm">
<el-form-item label="户主姓名" prop="judgeName" :rules="[{ required: true, message: '请输入户主姓名', trigger: 'blur' }]">
<el-input type="input" size="small" :maxlength="50" v-model="talkForm.judgeName" clearable placeholder="请输入户主姓名"></el-input>
</el-form-item>
<el-form-item label="性别" prop="judgeSex" :rules="[{ required: true, message: '请选择性别', trigger: 'blur' }]">
<ai-select
v-model="talkForm.judgeSex"
placeholder="请选择性别"
:selectList="dict.getDict('sex')">
</ai-select>
</el-form-item>
<el-form-item label="联系电话" prop="judgePhone" :rules="[{required: true, message: '请输入联系电话', trigger: 'blur'}]">
<el-input type="input" size="small" v-model="talkForm.judgePhone" clearable placeholder="请输入联系电话" maxlength="30" show-word-limit></el-input>
</el-form-item>
<el-form-item label="家庭住址" prop="judgeAddress" style="width: 100%;" :rules="[{required: true, message: '请输入家庭住址', trigger: 'blur'}]">
<el-input type="input" size="small" v-model="talkForm.judgeAddress" clearable placeholder="请输入家庭住址" maxlength="30" show-word-limit></el-input>
</el-form-item>
<el-form-item label="排查内容" prop="judgeRiskList" style="width: 100%;" :rules="[{required: true, message: '请选择排查内容', trigger: 'blur'}]">
<el-checkbox-group v-model="talkForm.judgeRiskList">
<el-checkbox label="1">经入户走访排查不存在相关风险指标的或经走访排查已现场化解纠纷的家庭户</el-checkbox>
<el-checkbox label="2">夫妻婆媳亲子兄弟邻里等家庭成员关系不和睦经常因某一事件或问题发生争吵但未出现暴力行为当事双方能理性表达诉求愿意寻求帮助化解纠纷</el-checkbox>
<el-checkbox label="3">家庭成员之间关系紧张引发过暴力行为或有家暴性侵投诉但情节轻微</el-checkbox>
<el-checkbox label="4">财产处置意见分歧较大纠纷激化引发过暴力行为但情节轻微</el-checkbox>
<el-checkbox label="5">当事人有酗酒滋事性格孤僻性格偏执或有暴力倾向</el-checkbox>
<el-checkbox label="6">有非访缠访闹访以及反复越级上访人员</el-checkbox>
<el-checkbox label="7">其它纠纷积怨时间较长存在明显风险隐患</el-checkbox>
<el-checkbox label="8">拟解除婚姻(恋爱 )关系一方当事人不同意且情绪激动扬言采取过激行为的</el-checkbox>
<el-checkbox label="9">家庭暴力已经造成人身伤害当事人态度恶劣的受害人及其亲属面临人身安全威胁有可能引发民转刑案件</el-checkbox>
<el-checkbox label="10">经济债务财产处置等纠纷久拖不决存在心理失衡仇恨情结悲观厌世已发生暴力冲突或扬言采取暴力行为</el-checkbox>
<el-checkbox label="11">存在遗弃或虐待家庭成员重婚及其它疑难复杂的家庭纠纷</el-checkbox>
<el-checkbox label="12">邻里纠纷经多次调解仍未化解.积怨较深已发生暴力冲突</el-checkbox>
<el-checkbox label="13">有严重不良行为未成年人</el-checkbox>
<el-checkbox label="14">其它可能引发重大案()</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
</ai-dialog>
<ai-dialog
:visible.sync="isShowMediate"
width="800px"
title="矛盾调解"
@closed="onClose"
@onConfirm="handleEvent('mediateForm')">
<el-form class="ai-form" label-width="120px" :model="mediateForm" ref="mediateForm">
<el-form-item label="调解主体" prop="mediateAreaId" style="width: 100%;" :rules="[{ required: true, message: '请输入调解主体', trigger: 'blur' }]">
<ai-area-select clearable @fullname="v => mediateForm.mediateAreaName = v" always-show :instance="instance" v-model="mediateForm.mediateAreaId"></ai-area-select>
</el-form-item>
<el-form-item label="调解员" prop="mediatePerson" :rules="[{ required: true, message: '请输入调解员', trigger: 'blur' }]">
<el-input type="input" size="small" :maxlength="50" v-model="mediateForm.mediatePerson" clearable placeholder="请输入调解员"></el-input>
</el-form-item>
<el-form-item label="调解时间" prop="mediateDate" :rules="[{ required: true, message: '请选择调解时间', trigger: 'blur' }]">
<el-date-picker size="small" v-model="mediateForm.mediateDate" type="date" placeholder="请选择调解时间" value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
<el-form-item label="金额" prop="mediateAmount" :rules="[{ required: true, message: '请输入金额', trigger: 'blur' }]">
<el-input type="input" size="small" :maxlength="50" v-model="mediateForm.mediateAmount" clearable placeholder="请输入金额"></el-input>
</el-form-item>
<el-form-item label="参与人" prop="mediateMember" :rules="[{ required: true, message: '请输入参与人', trigger: 'blur' }]">
<el-input type="input" size="small" :maxlength="50" v-model="mediateForm.mediateMember" clearable placeholder="请输入参与人"></el-input>
</el-form-item>
<el-form-item label="调处思路、措施及主要过程" prop="mediateInfo" style="width: 100%;" :rules="[{ required: true, message: '请输入调处思路、措施及主要过程', trigger: 'blur' }]">
<el-input type="textarea" :rows="5" :maxlength="500" v-model="mediateForm.mediateInfo" clearable placeholder="请输入调处思路、措施及主要过程" show-word-limit></el-input>
</el-form-item>
</el-form>
</ai-dialog>
<ai-dialog
:visible.sync="isShowForward"
width="800px"
@close="onClose"
title="事件指派"
@onConfirm="onForwardConfirm">
<el-form class="ai-form" label-width="120px" :model="forwardForm" ref="forwardForm">
<el-form-item label="转交" prop="name" style="width: 100%;" :rules="[{ required: true, message: '请选择网格员或网格' }]">
<el-input disabled size="small" v-model="forwardForm.name" clearable placeholder="请选择网格员或网格">
<template slot="append">
<el-button @click="getGirdList().then(()=>isShowUser=true )">选择</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="办理意见" prop="content" style="width: 100%;" :rules="[{ required: true, message: '请输入办理意见' }]">
<el-input type="textarea" :rows="5" :maxlength="500" v-model="forwardForm.content" clearable placeholder="请输入办理意见" show-word-limit></el-input>
</el-form-item>
<el-form-item label="图片" prop="files" style="width: 100%;">
<ai-uploader
:instance="instance"
v-model="forwardForm.files"
isShowTip
:limit="9">
</ai-uploader>
</el-form-item>
</el-form>
</ai-dialog>
<ai-dialog
:visible.sync="isShowUser"
width="800px"
title="选择网格或网格员"
@onConfirm="onConfirm">
<div class="grid-wrapper">
<el-input
style="margin-bottom: 10px;"
size="small"
placeholder="请输入网格名称/网格员姓名/网格员电话"
v-model="name" @change="$refs.tree.filter(name)"
suffix-icon="iconfont iconSearch">
</el-input>
<el-tree
:filter-node-method="filterNode"
ref="tree"
:props="defaultProps"
node-key="id"
:data="tree"
highlight-current
@current-change="onTreeChange">
<div class="tree-container" slot-scope="{ data }">
<div class="tree-container__user">
<div class="tree-user__item">
<span>{{ data.isUser ? `${data.name}-${data.phone}` : data.girdName }}</span>
</div>
</div>
</div>
</el-tree>
</div>
</ai-dialog>
</template>
</ai-detail>
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader'
import {mapState} from 'vuex'
export default {
name: 'Detail',
props: ['dict', 'instance'],
data() {
return {
forwardForm: {
content: '',
girdId: '',
girdName: '',
girdMemberId: '',
girdMemberName: '',
name: ''
},
isLoading: true,
name: '',
detail: {},
isShowUser: false,
eventList: [],
isShowAdd: false,
userList: [],
processList: [],
dictList: [],
defaultProps: {
label: 'girdName'
},
isShowForward: false,
tree: [],
gridInfo: {},
form: {
files: [],
groupId: '',
groupName: '',
content: [],
eventStatus: '2'
},
evaluation: {},
isShowTalk: false,
talkForm: {
judgeName: '',
judgeSex: '',
judgePhone: '',
judgeAddress: '',
judgeRiskList: []
},
isShowMediate: false,
mediateForm: {
mediateAreaId: '',
mediateAreaName: '',
mediatePerson: '',
mediateDate: '',
mediateAmount: '',
mediateMember: '',
mediateInfo: ''
}
}
},
computed: {
...mapState(['user']),
process: v => [v.evaluation.id ? {
systemExplain: `${v.evaluation.createUserName}完成评价 (${v.evaluation.score}星评价)`,
doTime: v.evaluation.createTime,
doExplain: v.evaluation.rateText
} : null, v.processList].flat().filter(Boolean)
},
created() {
this.getDict()
this.dict.load('weiyangEventStatus', 'sex', 'weiyangRisk', 'weiyangEventType').then(() => {
this.getDetail()
})
},
methods: {
getDetail() {
this.instance.post('/app/appclapeventinfoweiyang/queryDetailById', null, {
params: {id: this.$route.query.id}
}).then(res => {
if (res?.data) {
this.detail = res.data
this.processList = res.data.processList
this.form.groupId = res.data.groupId
if(this.detail.judgeRisk) {
this.detail.judgeRiskList = this.detail.judgeRisk.split(',')
}
this.$nextTick(() => {
this.initMap()
})
this.isLoading = false
}
}).catch(() => {
this.isLoading = false
})
},
getGirdList() {
return this.instance.post(`/app/appgirdinfo/listAllByTop`).then(res => {
if (res?.data) {
return this.tree = this.formatList([res.data])
}
})
},
handelClick() {
if(this.detail.rightType == 0) {
this.isShowAdd = true
}
if(this.detail.rightType == 1) {
this.isShowTalk = true
}
if(this.detail.rightType == 2) {
this.mediateForm.mediateAreaId = this.user.areaId
this.mediateForm.mediateAreaName = this.user.areaName
this.isShowMediate = true
}
},
onClose() {
this.form.files = []
this.form.groupId = ''
this.form.groupName = ''
this.form.content = ''
this.form.eventStatus = ''
this.forwardForm.content = ''
this.forwardForm.girdId = ''
this.forwardForm.girdName = ''
this.forwardForm.girdMemberId = ''
this.forwardForm.girdMemberName = ''
this.forwardForm.name = ''
this.isShowAdd = false
this.isShowTalk = false
this.isShowMediate = false
this.mediateForm = {
mediateAreaId: '',
mediateAreaName: '',
mediatePerson: '',
mediateDate: '',
mediateAmount: '',
mediateMember: '',
mediateInfo: ''
}
this.talkForm = {
judgeName: '',
judgeSex: '',
judgePhone: '',
judgeAddress: '',
judgeRiskList: []
}
},
formatList(list) {
for (let item of list) {
item.children = [item.girdList, item.girdMemberList?.map(e => ({
...e, isUser: true, girdName: item.girdName,
girdId: item.id
})) || []].flat()
if (item.girdList?.length > 0) {
this.formatList(item.girdList)
}
}
return list
},
filterNode(value, data) {
if (!value) return true
return (data.girdName && data.girdName.indexOf(value) !== -1) || (data.name && data.name.indexOf(value) !== -1) || (data.name && data.phone.indexOf(value) !== -1)
},
onTreeChange(e) {
this.gridInfo = e
},
onForwardConfirm() {
this.$refs.forwardForm.validate(v => {
if (v) {
this.instance.post('/app/appclapeventinfoweiyang/transfer', {
...this.forwardForm,
id: this.$route.query.id
}).then(res => {
if (res?.code == 0) {
this.isShowForward = false
this.getDetail()
this.$message.success('转交成功!')
}
})
}
})
},
onConfirm() {
if (this.gridInfo.userId) {
this.forwardForm.girdId = this.gridInfo.girdId
this.forwardForm.girdName = this.gridInfo.girdName
this.forwardForm.girdMemberId = this.gridInfo.id
this.forwardForm.girdMemberName = this.gridInfo.name
} else {
this.forwardForm.girdId = this.gridInfo.id
}
this.forwardForm.girdName = this.gridInfo.girdName
this.forwardForm.name = `${this.gridInfo.girdName}${this.gridInfo.name ? '-' + this.gridInfo.name : ''}`
this.isShowUser = false
},
getDict() {
this.instance.post(`/app/appclapeventgroupweiyang/list?current=1&size=100000`).then(res => {
if (res.code == 0) {
this.dictList = res.data.records.map(v => {
return {
dictValue: v.id,
dictName: v.groupName
}
})
}
})
},
close() {
this.$confirm('确定关闭该事件?').then(() => {
this.instance.post(`/app/appclapeventinfoweiyang/delete?ids=${this.$route.query.id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
},
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
},
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
let center = [lng, lat]
AMapLoader.load({
key: 'b553334ba34f7ac3cd09df9bc8b539dc',
version: '2.0'
}).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)
})
},
handleEvent(refName) {
this.$refs[refName].validate(v => {
if (v) {
var form = {}
var url = `/app/appclapeventinfoweiyang/finish`
if(this.detail.rightType == 0) {
form = {...this.form}
form.groupName = this.dictList.filter(v => v.dictValue === this.form.groupId)[0].dictName
}
if(this.detail.rightType == 1) {
form = {...this.talkForm}
form.judgeRisk = this.talkForm.judgeRiskList.join(',')
url = `/app/appclapeventinfoweiyang/judge`
}
if(this.detail.rightType == 2) {
form = {...this.mediateForm}
form.eventStatus = '3'
}
this.instance.post(url, {
...form,
id: this.$route.query.id
}).then(res => {
if (res?.code == 0) {
this.onClose()
this.getDetail()
this.$message.success('处理成功!')
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.reportAtWillDetail {
height: 100%;
.grid-wrapper {
min-height: 360px;
}
.title-btns {
display: flex;
align-items: center;
}
:deep( .el-tree ) {
background: transparent;
.el-tree-node__expand-icon.is-leaf {
color: transparent !important;
}
.el-tree-node__content > .el-tree-node__expand-icon {
padding: 4px;
}
.el-tree-node__content {
height: 32px;
}
.el-tree__empty-text {
color: #222;
font-size: 14px;
}
.el-tree-node__children .el-tree-node__content {
height: 32px;
}
.el-tree-node__content:hover {
background: #E8EFFF;
color: #222222;
border-radius: 2px;
}
.is-current > .el-tree-node__content {
&:hover {
background: #2266FF;
color: #fff;
}
background: #2266FF;
span {
color: #fff;
}
}
}
.el-steps {
:deep( .el-step__icon ) {
font-size: 12px;
color: #555555;
border-color: #d0d4dc;
}
:deep( .el-step__head.is-finish ) {
.el-step__icon.is-text {
border: none;
color: #fff;
font-size: 12px;
background: #2266ff;
}
}
: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;
}
}
}
:deep( .report-dialog ) {
.el-select {
width: 100%;
}
}
:deep( .el-step__head.is-process ) {
color: #555;
border-color: #555;
}
:deep( .is-finish h2 ) {
color: #2266ff;
}
.step-title {
color: #555;
}
.detail-content__wrapper {
display: flex;
width: 100%;
flex-wrap: wrap;
.detail-content__wrapper--left {
flex: 1;
margin-right: 20px;
}
}
: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;
}
}
}
: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>