Commit df7a87f2 by wuchao

回访计划

parent c390e525
...@@ -121,67 +121,6 @@ export const getKeyPersonUser = (param) => { ...@@ -121,67 +121,6 @@ export const getKeyPersonUser = (param) => {
}) })
} }
// ===== 回访记录(办理)模块 =====
// 列表
export const findVisitRecordList = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/findVisitRecordList',
method: 'post',
data: param
})
}
// 获取本次评分统计数据
export const getScoreStatistics = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonStatistics/getScoreStatistics',
method: 'post',
data: param
})
}
// 详情(含基本信息、计划信息、历史记录)
export const getVisitRecordDetail = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/getVisitRecordDetail',
method: 'post',
data: param
})
}
// 新增回访记录
export const insertVisitRecord = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/insertVisitRecord',
method: 'post',
data: param
})
}
// 获取回访按钮权限
export const getVisitButtonPower = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/getVisitButtonPower',
method: 'post',
data: param
})
}
// 历史回访记录分页
export const selectVisitHistoryPage = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/selectVisitHistoryPage',
method: 'post',
data: param
})
}
// 待办统计(正常/临期)
export const getPendingStats = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/getPendingStats',
method: 'post',
data: param
})
}
// ===== 按钮可见权限配置 ===== // ===== 按钮可见权限配置 =====
// 列表(来源于字典 page_button,并合并已配置的可见部门) // 列表(来源于字典 page_button,并合并已配置的可见部门)
export const selectPageButtonPowerList = (param) => { export const selectPageButtonPowerList = (param) => {
...@@ -380,3 +319,45 @@ export const getDualDetail = (param) => { ...@@ -380,3 +319,45 @@ export const getDualDetail = (param) => {
data: param data: param
}) })
} }
// ===== 回访记录办理 =====
// 查询回访记录列表
export const findVisitRecordList = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/findVisitRecordList',
method: 'post',
data: param
})
}
// 获取人员信息(用于回访)
export const getPersonInfoForVisit = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/getPersonInfoForVisit',
method: 'post',
data: param
})
}
// 保存回访记录
export const saveVisitRecord = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/saveVisitRecord',
method: 'post',
data: param
})
}
// 查询回访历史(分页)
export const selectVisitHistoryPage = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/selectVisitHistoryPage',
method: 'post',
data: param
})
}
// 查询回访记录详情
export const getVisitRecordDetail = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyPersonVisitRecord/getVisitRecordDetail',
method: 'post',
data: param
})
}
...@@ -576,6 +576,14 @@ const buildFilters = { ...@@ -576,6 +576,14 @@ const buildFilters = {
forward: () => ({ name: '', card_no: '', city_id: '', area_id: '', street_id: '', community_id: '', push_status: '' }) forward: () => ({ name: '', card_no: '', city_id: '', area_id: '', street_id: '', community_id: '', push_status: '' })
} }
// 身份证号统一转码、规整(去除所有空白并大写),避免查询、筛选不生效
function normalizeCardNo (val) {
if (!val) return ''
const s = String(val).replace(/\s+/g, '').trim()
if (!s) return ''
return s.toUpperCase()
}
export default { export default {
name: 'key-person-dual-index', name: 'key-person-dual-index',
props: { props: {
...@@ -816,7 +824,15 @@ export default { ...@@ -816,7 +824,15 @@ export default {
const api = apiMap[tab] const api = apiMap[tab]
if (!api) return if (!api) return
this.loading[tab] = true this.loading[tab] = true
const params = Object.assign({}, this.filters[tab], { sys_type: this.currentCategory }) // 统一处理身份证号(空白 -> 删除,末位 X -> 大写),避免查询/筛选失败
const rawFilters = this.filters[tab] || {}
const normalizedCardNo = normalizeCardNo(rawFilters.card_no)
const params = Object.assign(
{},
rawFilters,
{ card_no: normalizedCardNo, cardNo: normalizedCardNo },
{ sys_type: this.currentCategory }
)
const payload = Object.assign({}, this.pagers[tab], { params }) const payload = Object.assign({}, this.pagers[tab], { params })
api(payload).then(ret => { api(payload).then(ret => {
if (ret.data && ret.data.errcode === 0) { if (ret.data && ret.data.errcode === 0) {
...@@ -926,10 +942,16 @@ export default { ...@@ -926,10 +942,16 @@ export default {
if (pageNo !== undefined && pageNo !== null) { if (pageNo !== undefined && pageNo !== null) {
this.pushModal.personPager.pageNo = pageNo this.pushModal.personPager.pageNo = pageNo
} }
const normalizedCardNo = normalizeCardNo(this.pushModal.personFilters.card_no)
const payload = { const payload = {
pageNo: this.pushModal.personPager.pageNo, pageNo: this.pushModal.personPager.pageNo,
pageSize: this.pushModal.personPager.pageSize, pageSize: this.pushModal.personPager.pageSize,
params: Object.assign({}, this.pushModal.personFilters, { sys_type: this.currentCategory }) params: Object.assign(
{},
this.pushModal.personFilters,
{ card_no: normalizedCardNo, cardNo: normalizedCardNo },
{ sys_type: this.currentCategory }
)
} }
this.pushModal.personLoading = true this.pushModal.personLoading = true
getDualPersonOptions(payload).then(ret => { getDualPersonOptions(payload).then(ret => {
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
<Form :label-width="100"> <Form :label-width="100">
<FormItem label="风险等级"><Input :value="renderRatingType(detail.rating_type)" disabled /></FormItem> <FormItem label="风险等级"><Input :value="renderRatingType(detail.rating_type)" disabled /></FormItem>
<FormItem label="回访人"><Input :value="detail.visit_user || '-'" disabled /></FormItem> <FormItem label="回访人"><Input :value="detail.visit_user || '-'" disabled /></FormItem>
<FormItem label="回访部门"><Input :value="detail.visit_user_company || '-'" disabled /></FormItem>
<FormItem label="回访时间"><Input :value="formatDateTime(detail.visit_time)" disabled /></FormItem> <FormItem label="回访时间"><Input :value="formatDateTime(detail.visit_time)" disabled /></FormItem>
<FormItem label="回访记录"><Input type="textarea" :rows="4" :value="detail.visit_record || '-'" disabled /></FormItem> <FormItem label="回访记录"><Input type="textarea" :rows="4" :value="detail.visit_record || '-'" disabled /></FormItem>
<FormItem label="回访图片"> <FormItem label="回访图片">
...@@ -44,9 +43,8 @@ ...@@ -44,9 +43,8 @@
<div> <div>
<Form :label-width="100"> <Form :label-width="100">
<FormItem label="风险等级"><Input :value="renderRatingType(recordModal.data.rating_type)" disabled /></FormItem> <FormItem label="风险等级"><Input :value="renderRatingType(recordModal.data.rating_type)" disabled /></FormItem>
<FormItem label="回访时间"><Input :value="recordModal.data.visit_time || '-'" disabled /></FormItem> <FormItem label="回访时间"><Input :value="formatDateTime(recordModal.data.visit_time)" disabled /></FormItem>
<FormItem label="回访人"><Input :value="recordModal.data.visit_user || recordModal.data.do_user_name || recordModal.data.operator_name || recordModal.data.create_user_name || '-'" disabled /></FormItem> <FormItem label="回访人"><Input :value="recordModal.data.visit_user || recordModal.data.do_user_name || recordModal.data.operator_name || recordModal.data.create_user_name || '-'" disabled /></FormItem>
<FormItem label="回访部门"><Input :value="recordModal.data.visit_user_company || '-'" disabled /></FormItem>
<FormItem label="回访记录"><Input type="textarea" :rows="4" :value="recordModal.data.visit_record || '-'" disabled /></FormItem> <FormItem label="回访记录"><Input type="textarea" :rows="4" :value="recordModal.data.visit_record || '-'" disabled /></FormItem>
<FormItem label="回访图片"> <FormItem label="回访图片">
<div class="img-list"> <div class="img-list">
...@@ -87,11 +85,9 @@ export default { ...@@ -87,11 +85,9 @@ export default {
page: { pageNo: 1, pageSize: 10, totalRecord: 0 }, page: { pageNo: 1, pageSize: 10, totalRecord: 0 },
visitHistoryColumns: [ visitHistoryColumns: [
{ title: '风险等级', key: 'rating_type', align: 'center', width: 120, render: (h, { row }) => h('span', this.renderRatingType(row.rating_type)) }, { title: '风险等级', key: 'rating_type', align: 'center', width: 120, render: (h, { row }) => h('span', this.renderRatingType(row.rating_type)) },
{ title: '回访人', key: 'visit_user', align: 'center', width: 120 },
{ title: '回访部门', key: 'visit_user_company', align: 'center', width: 180 },
{ title: '回访时间', key: 'visit_time', align: 'center', width: 180, render: (h, { row }) => h('span', this.formatDateTime(row.visit_time)) }, { title: '回访时间', key: 'visit_time', align: 'center', width: 180, render: (h, { row }) => h('span', this.formatDateTime(row.visit_time)) },
{ title: '回访状态', key: 'do_status', align: 'center', width: 120, render: (h, { row }) => h('span', this.renderVisitStatus(row.do_status)) }, { title: '回访人', key: 'visit_user', align: 'center', width: 120 },
{ title: '操作', key: 'action', align: 'center', width: 100, render: (h, { row }) => (String(row.do_status) === '2' ? h('span', '') : h('Button', { props: { type: 'primary', size: 'small' }, on: { click: () => this.openRecord(row) } }, '查看')) } { title: '操作', key: 'action', align: 'center', width: 100, render: (h, { row }) => h('Button', { props: { type: 'primary', size: 'small' }, on: { click: () => this.openRecord(row) } }, '详情') }
], ],
ratingTypeOptions: [], ratingTypeOptions: [],
nationMap: {}, nationMap: {},
...@@ -142,7 +138,11 @@ export default { ...@@ -142,7 +138,11 @@ export default {
this.fetchHistory({ key_person_id: this.key_person_id, order_by: 'visit_time desc' }) this.fetchHistory({ key_person_id: this.key_person_id, order_by: 'visit_time desc' })
}, },
fetchHistory (extraParams) { fetchHistory (extraParams) {
const params = Object.assign({}, extraParams) const params = Object.assign(
{},
extraParams,
{ rating_dict_type: String(this.rating_dict_type || '') }
)
const payload = { params, pageNo: this.page.pageNo, pageSize: this.page.pageSize } const payload = { params, pageNo: this.page.pageNo, pageSize: this.page.pageSize }
selectVisitHistoryPage(payload).then((ret) => { selectVisitHistoryPage(payload).then((ret) => {
if (ret && ret.data && ret.data.errcode === 0) { if (ret && ret.data && ret.data.errcode === 0) {
......
<template> <template>
<div class="contradiction-div"> <div class="visit-record-wrapper">
<div class="search-div"> <div class="search-div">
<Row type="flex"> <Row type="flex" :gutter="16" class="mb10">
<Col span="4"> <Col span="4">
<span>姓名:</span> <span>姓名:</span>
<Input v-model="filters.name" placeholder="请输入" style="width: 65%" /> <Input v-model="filters.name" placeholder="请输入" style="width: 65%" />
</Col> </Col>
<Col span="4"> <Col span="4">
<span>身份证号:</span> <span>身份证号:</span>
<Input v-model="filters.card_no" placeholder="请输入" style="width: 55%" /> <Input v-model="filters.card_no" placeholder="请输入" style="width: 65%" />
</Col> </Col>
<Col span="4"> <Col span="4">
<span>选择市:</span> <span>选择市:</span>
<Select v-model="filters.city_id" clearable style="width: 55%" @on-change="changeArea('2', filters.city_id)"> <Select v-model="filters.city_id" clearable style="width: 65%" @on-change="handleFilterCascade('city', $event)">
<Option v-for="c in cityList" :key="c.parent_id" :value="c.parent_id">{{ c.name }}</Option> <Option v-for="c in cityOptions" :key="c.parent_id" :value="c.parent_id">{{ c.name }}</Option>
</Select> </Select>
</Col> </Col>
<Col span="4"> <Col span="4">
<span>选择区:</span> <span>选择区:</span>
<Select v-model="filters.area_id" clearable style="width: 55%" @on-change="changeArea('3', filters.area_id)"> <Select v-model="filters.area_id" clearable style="width: 65%" @on-change="handleFilterCascade('area', $event)">
<Option v-for="c in areaList" :key="c.parent_id" :value="c.parent_id">{{ c.name }}</Option> <Option v-for="c in areaState.areaList" :key="c.parent_id" :value="c.parent_id">{{ c.name }}</Option>
</Select> </Select>
</Col> </Col>
<Col span="4"> <Col span="4">
<span>选择街道:</span> <span>选择街道:</span>
<Select v-model="filters.street_id" clearable style="width: 55%" @on-change="changeArea('4', filters.street_id)"> <Select v-model="filters.street_id" clearable style="width: 65%" @on-change="handleFilterCascade('street', $event)">
<Option v-for="c in streetList" :key="c.parent_id" :value="c.parent_id">{{ c.name }}</Option> <Option v-for="c in areaState.streetList" :key="c.parent_id" :value="c.parent_id">{{ c.name }}</Option>
</Select> </Select>
</Col> </Col>
<Col span="4"> <Col span="4">
<span>选择社区:</span> <span>选择社区:</span>
<Select v-model="filters.community_id" clearable style="width: 55%"> <Select v-model="filters.community_id" clearable style="width: 65%">
<Option v-for="c in communityList" :key="c.parent_id" :value="c.parent_id">{{ c.name }}</Option> <Option v-for="c in areaState.communityList" :key="c.parent_id" :value="c.parent_id">{{ c.name }}</Option>
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row type="flex" style="margin-top: 15px"> <Row type="flex" :gutter="16" class="mb10">
<Col span="4"> <Col span="4">
<span>办理状态:</span> <span>风险等级:</span>
<Select v-model="filters.do_status" style="width: 49%"> <Select v-model="filters.rating_level" clearable style="width: 65%">
<Option value="0">待办</Option> <Option v-for="opt in ratingLevelOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option>
<Option value="1">已办</Option>
<Option value="2">超期未办</Option>
</Select>
</Col>
<Col span="4">
<span>是否临期:</span>
<Select v-model="filters.is_overdue" clearable style="width: 49%">
<Option value="1"></Option>
<Option value="0"></Option>
</Select> </Select>
</Col> </Col>
<Col span="4"> <Col span="4">
<span>风险等级</span> <span>回访状态</span>
<Select v-model="filters.rating_type" clearable style="width: 55%"> <Select v-model="filters.visit_status" clearable style="width: 65%">
<Option v-for="opt in ratingTypeOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option> <Option v-for="opt in visitStatusOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option>
</Select> </Select>
</Col> </Col>
<Col style="text-align: right"> <Col span="8" class="text-right">
<Button type="primary" @click="search" style="margin-right: 10px">搜索</Button> <Button type="primary" class="mr10" @click="handleSearch">搜索</Button>
<Button type="primary" @click="reset">重置</Button> <Button @click="handleReset">重置</Button>
<Button style="margin-left: 10px;" @click="$router.go(-1)" v-if="this.$route.query.do_status">返回重点人员统计</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
<Table border :loading="loading" :columns="columns" :data="tableData">
<div class="pending-stats"> <template slot="rating_level" slot-scope="{ row }">
<span v-if="false">正常待办:{{ statsPending.normal }}</span> <span>{{ renderRatingLevel(row.rating_level) }}</span>
<span>临期待办:{{ statsPending.nearDue }}</span> </template>
</div> <template slot="visit_status" slot-scope="{ row }">
<span>{{ renderVisitStatus(row.visit_status) }}</span>
<Table border :loading="tableLoading" :columns="tableColumns" :data="tableData"> </template>
<template slot="action" slot-scope="{ row }"> <template slot="action" slot-scope="{ row }">
<Button v-if="canShowVisit(row) && String(row.do_status) === '0'" type="primary" size="small" style="margin-right:6px" @click="openVisitModal(row)">回访</Button> <Button size="small" type="primary" class="mr5" @click="openVisitModal(row)">回访</Button>
<Button v-if="hasHistory(row)" type="info" size="small" @click="openHistoryModal(row)">查看历史</Button> <Button size="small" @click="openHistoryModal(row)">回访历史</Button>
</template> </template>
</Table> </Table>
<Page class="page_style" :total="params.totalRecord" :current="params.pageNo" :page-size="params.pageSize" show-total show-sizer @on-change="changePageNo" @on-page-size-change="size" /> <Page
class="page_style"
:total="pager.totalRecord"
:current="pager.pageNo"
:page-size="pager.pageSize"
show-total
show-sizer
@on-change="pageChange"
@on-page-size-change="sizeChange"
/>
<!-- 回访弹窗(参照样式:基本信息 + 计划信息 + 历史回访信息 + 填写回访记录) --> <!-- 回访弹窗 -->
<Modal v-model="visitModal.visible" title="回访办理" width="900"> <Modal v-model="visitModal.visible" title="回访" width="800" :mask-closable="false">
<div> <div v-if="visitModal.loading">
<Spin fix></Spin>
</div>
<div v-else>
<h4 class="section-title">人员基本信息</h4> <h4 class="section-title">人员基本信息</h4>
<Form :label-width="100" inline class="info-form"> <Form :label-width="120" inline class="info-form">
<FormItem label="姓名"> <FormItem label="姓名"><Input :value="visitModal.personInfo.name || '-'" disabled style="width: 220px" /></FormItem>
<Input :value="detail.name || '-'" disabled style="width: 220px" /> <FormItem label="身份证号"><Input :value="visitModal.personInfo.card_no || '-'" disabled style="width: 220px" /></FormItem>
</FormItem> <FormItem label="联系方式"><Input :value="visitModal.personInfo.phone || '-'" disabled style="width: 220px" /></FormItem>
<FormItem label="性别"> <FormItem label="风险等级"><Input :value="renderRatingLevel(visitModal.personInfo.rating_level) || '-'" disabled style="width: 220px" /></FormItem>
<Input :value="renderSex(detail.sex)" disabled style="width: 220px" /> <FormItem label="市(州)"><Input :value="visitModal.personInfo.city_name || '-'" disabled style="width: 220px" /></FormItem>
</FormItem> <FormItem label="县(市、区)"><Input :value="visitModal.personInfo.area_name || '-'" disabled style="width: 220px" /></FormItem>
<FormItem label="身份证号"> <FormItem label="街道(乡镇)"><Input :value="visitModal.personInfo.street_name || '-'" disabled style="width: 220px" /></FormItem>
<Input :value="detail.card_no || '-'" disabled style="width: 220px" /> <FormItem label="社区(村)"><Input :value="visitModal.personInfo.community_name || '-'" disabled style="width: 220px" /></FormItem>
</FormItem>
<FormItem label="民族">
<Input :value="renderFolk(detail.folk) || '-'" disabled style="width: 220px" />
</FormItem>
<FormItem label="本人联系方式">
<Input :value="detail.phone || '-'" disabled style="width: 220px" />
</FormItem>
<FormItem label="现住址" style="width: 100%">
<Input :value="`${detail.city || '-'} / ${detail.area || '-'} / ${detail.street || '-'} / ${detail.community || '-'}`" disabled />
</FormItem>
</Form> </Form>
<h4 class="section-title">计划信息</h4> <h4 class="section-title">回访信息</h4>
<Form :label-width="100" inline class="info-form"> <Form ref="visitForm" :model="visitModal.form" :rules="visitModal.rules" :label-width="120">
<FormItem label="计划名称"> <FormItem label="回访时间" prop="visit_time" required>
<Input :value="detail.plan_name || '-'" disabled style="width: 220px" /> <DatePicker
</FormItem> v-model="visitModal.form.visit_time"
<FormItem label="计划类别"> type="datetime"
<Input :value="detail.plan_type || '-'" disabled style="width: 220px" /> format="yyyy-MM-dd HH:mm:ss"
</FormItem> placeholder="请选择回访时间"
<FormItem label="重点人员类别"> style="width: 100%"
<Input :value="renderRatingDictType(currentCategory || filters.rating_dict_type)" disabled style="width: 220px" /> />
</FormItem> </FormItem>
<FormItem label="风险等级"> <FormItem label="回访记录" prop="visit_record" required>
<Input :value="renderRatingType(detail.record_rating_type || detail.rating_type)" disabled style="width: 220px" /> <Input type="textarea" :rows="4" v-model="visitModal.form.visit_record" placeholder="请输入回访记录" />
</FormItem> </FormItem>
<FormItem label="计划开始日期"> <FormItem label="上传图片">
<Input :value="formatDate(detail.plan_start_data)" disabled style="width: 220px" />
</FormItem>
<FormItem label="计划结束日期">
<Input :value="formatDate(detail.plan_end_data)" disabled style="width: 220px" />
</FormItem>
<FormItem label="剩余天数">
<Input :value="renderRemainDays(detail.remain_days)" disabled style="width: 220px" />
</FormItem>
</Form>
<h4 class="section-title">填写回访记录</h4>
<Form :model="visitForm" ref="visitForm" :label-width="100" :rules="visitRules">
<FormItem label="回访时间" prop="visit_time">
<DatePicker type="datetime" format="yyyy-MM-dd HH:mm:ss" :value="visitForm.visit_time" @on-change="onVisitTimeChange" style="width: 220px" placeholder="选择时间" />
</FormItem>
<FormItem label="回访记录" prop="visit_record">
<Input type="textarea" :rows="4" v-model="visitForm.visit_record" placeholder="请输入" />
</FormItem>
<FormItem label="回访图片">
<Upload <Upload
:show-upload-list="false" ref="upload"
:before-upload="beforeUploadVisitImg" :action="uploadAction"
:format="['jpg','jpeg','png']" :headers="uploadHeaders"
accept=".jpg,.jpeg,.png" :on-success="handleUploadSuccess"
:max-size="4096"> :on-remove="handleUploadRemove"
:on-error="handleUploadError"
:before-upload="beforeUpload"
:file-list="visitModal.form.visit_img_list"
multiple
accept="image/*"
>
<Button icon="ios-cloud-upload-outline">上传图片</Button> <Button icon="ios-cloud-upload-outline">上传图片</Button>
</Upload> </Upload>
<div class="img-list"> <div style="color: #999; font-size: 12px; margin-top: 8px;">支持多张图片上传,单张图片不超过5MB</div>
<img v-for="(img,idx) in visitForm.imgs" :key="idx" :src="img" style="width:80px;height:80px;margin-right:8px" />
</div>
</FormItem> </FormItem>
</Form> </Form>
</div> </div>
<div slot="footer"> <div slot="footer">
<Button @click="visitModal.visible=false">取消</Button> <Button @click="visitModal.visible=false">取消</Button>
<Poptip confirm title="确认保存?" placement="top" transfer @on-ok="submitVisit"> <Button type="primary" :loading="visitModal.submitting" :disabled="visitModal.loading" @click="submitVisit">保存</Button>
<Button type="primary" :loading="visitModal.submitting">保存</Button>
</Poptip>
</div> </div>
</Modal> </Modal>
<VisitHistoryModal ref="historyModal" <!-- 回访历史弹窗 -->
:rating_dict_type="String(currentCategory || filters.rating_dict_type || '')" <VisitHistoryModal
:key_person_id="historyParams.key_person_id" ref="historyModal"
:jl_key_person_visit_record_id="historyParams.current_record_id" /> :rating_dict_type="currentRatingDictType"
:key_person_id="historyModal.key_person_id"
/>
</div> </div>
</template> </template>
<script> <script>
import { findVisitRecordList, getVisitRecordDetail, insertVisitRecord, getVisitButtonPower, getPendingStats } from '@/api/key-person' import { selectCityList } from '@/api/contradiction'
import { getCardNoById, uploadFile, selectCityList } from '@/api/contradiction' import { getDictList, uploadPic } from '@/api/common'
import { getDictList } from '@/api/common' import {
import { findMZList } from '@/api/peopleInfo' findVisitRecordList,
import { mapState } from 'vuex' getPersonInfoForVisit,
saveVisitRecord,
selectCurrentUserInfo
} from '@/api/key-person'
import VisitHistoryModal from './components/VisitHistoryModal.vue' import VisitHistoryModal from './components/VisitHistoryModal.vue'
const createVisitForm = () => ({
key_person_id: '',
key_person_visit_id: '',
rating_dict_type: '',
sys_type_office_label: '',
sys_type_office_value: '',
plan_name: '',
plan_type: '',
rating_type: '',
visit_time: '',
visit_record: '',
visit_img_list: []
})
// 身份证号统一转码(移除空白并大写),避免查询条件失效
const normalizeCardNo = (val) => {
if (!val) return ''
const cleaned = String(val).replace(/\s+/g, '').trim()
if (!cleaned) return ''
return cleaned.toUpperCase()
}
export default { export default {
name: 'key-person-visit-record-index', name: 'key-person-visit-record-index',
props: { category: { type: String, default: '' } }, components: {
VisitHistoryModal
},
props: {
// 重点人员类别(rating_dict_type),对应sys_type
category: {
type: String,
default: ''
}
},
data () { data () {
return { return {
tableLoading: false,
tableData: [],
cardNoCache: {},
cityList: [],
areaList: [],
streetList: [],
communityList: [],
ratingTypeOptions: [],
mzList: [],
nationMap: {},
ratingDictTypeOptions: [
{ label: '刑满释放人员', value: '2' },
{ label: '严重精神障碍患者', value: '3' },
{ label: '重点未成年人', value: '6' }
],
filters: { filters: {
rating_dict_type: '',
name: '', name: '',
card_no: '', card_no: '',
city_id: '', city_id: '',
area_id: '', area_id: '',
street_id: '', street_id: '',
community_id: '', community_id: '',
do_status: '0', rating_level: '',
rating_type: '', visit_status: ''
is_overdue: ''
}, },
params: { pageNo: 1, pageSize: 10, totalRecord: 0 }, cityOptions: [],
statsPending: { normal: 0, nearDue: 0 }, areaState: {
tableColumns: [ areaList: [],
{ type: 'index', title: '序号', align: 'center', width: 80 }, streetList: [],
{ title: '市(州)', key: 'city_name', align: 'center', width: 100 }, communityList: []
{ title: '县(市、区)', key: 'area_name', align: 'center', width: 100 }, },
{ title: '街道(乡镇)', key: 'street_name', align: 'center', width: 120 }, ratingLevelOptions: [],
{ title: '社区(村)', key: 'community_name', align: 'center', width: 120 }, visitStatusOptions: [],
{ title: '姓名', key: 'name', align: 'center', width: 100 }, loading: false,
{ title: '身份证号', key: 'card_no', align: 'center', width: 220, render: (h, { row }) => h('span', this.getDecryptedCardNo(row.key_person_id, row.card_no)) }, tableData: [],
{ title: '联系方式', key: 'phone', align: 'center', width: 180 }, columns: [
{ title: '计划开始日期', key: 'plan_start_data', align: 'center', width: 140, render: (h, { row }) => h('span', this.formatDate(row.plan_start_data)) }, { type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '计划结束日期', key: 'plan_end_data', align: 'center', width: 140, render: (h, { row }) => h('span', this.formatDate(row.plan_end_data)) }, { title: '市(州)', key: 'city_name', align: 'center' },
{ title: '剩余办理天数', key: 'remain_days', align: 'center', width: 120, render: (h, { row }) => h('span', this.renderRemainDays(row.remain_days)) }, { title: '县(市、区)', key: 'area_name', align: 'center' },
{ title: '是否临期', key: 'is_overdue', align: 'center', width: 100, render: (h, { row }) => h('span', (String(row.is_overdue) === '1') ? '是' : '否') }, { title: '街道(乡镇)', key: 'street_name', align: 'center' },
{ title: '风险等级', key: 'rating_type', align: 'center', width: 120, render: (h, { row }) => h('span', this.renderRatingType(row.rating_type)) }, { title: '社区(村)', key: 'community_name', align: 'center' },
{ title: '办理状态', key: 'do_status', align: 'center', width: 120, render: (h, { row }) => h('span', this.renderDoStatus(row.do_status)) }, { title: '姓名', key: 'name', align: 'center' },
{ title: '操作', slot: 'action', align: 'center', width: 200, fixed: 'right' } { title: '身份证号', key: 'card_no', align: 'center' },
{ title: '联系方式', key: 'phone', align: 'center' },
{ title: '风险等级', key: 'rating_level', align: 'center', slot: 'rating_level' },
{ title: '回访状态', key: 'visit_status', align: 'center', slot: 'visit_status' },
{ title: '操作', key: 'action', align: 'center', width: 180, slot: 'action' }
], ],
visitModal: { visible: false, submitting: false }, pager: {
historyModal: { visible: false }, pageNo: 1,
historyParams: { pageNo: 1, pageSize: 10, totalRecord: 0, key_person_id: '', current_record_id: '' }, pageSize: 10,
recordModal: { visible: false, data: {} }, totalRecord: 0
detail: {},
visitButtonPower: {},
visitForm: { key_person_id: '', key_person_visit_id: '', id: '', visit_time: '', visit_record: '', imgs: [] },
visitRules: {
visit_time: [{ required: true, message: '请选择回访时间', trigger: 'change' }],
visit_record: [{ required: true, message: '请输入回访记录', trigger: 'blur' }]
}, },
historyData: [], visitModal: {
visitHistoryColumns: [] visible: false,
} loading: false,
}, submitting: false,
components: { VisitHistoryModal }, personInfo: {},
computed: { form: createVisitForm(),
...mapState({ userInfo: state => state.user.userInfo || {} }), rules: {
currentCategory () { visit_time: [{ required: true, message: '请选择回访时间', trigger: 'change' }],
const route = this.$route || {} visit_record: [{ required: true, message: '请输入回访记录', trigger: 'blur' }]
const q = (route.query || {}) }
const p = (route.params || {}) },
const fromRoute = q.category || q.rating_dict_type || p.category || p.rating_dict_type || '' historyModal: {
const fromProp = this.category || '' key_person_id: ''
return String(fromProp || fromRoute || '') },
}, currentRatingDictType: '',
recordModalImgs () { uploadAction: '/api/uc/mzsc/uploadService/uploadPic',
const data = this.recordModal && this.recordModal.data ? this.recordModal.data : {} uploadHeaders: {}
const img = data.img
if (!img) return []
if (Array.isArray(img)) return img.filter(Boolean)
if (typeof img === 'string') return img.split(',').map(s => s.trim()).filter(Boolean)
return []
} }
}, },
created () { created () {
this.filters.rating_dict_type = this.currentCategory || '' this.init()
this.loadRatingLevelDict()
// 读取 URL 参数中的 do_status / is_overdue,并赋值到筛选项
this.applyUrlFilterParams(false)
this.fetchVisitButtonPower().then(() => this.init())
this.loadNationDict()
// 载入市级下拉
selectCityList({}).then((res) => {
if (res && res.data && res.data.errcode === 0) {
this.cityList = res.data.data || []
}
})
},
watch: {
category () { this.applyDefaultCategory(true) },
'$route.query.category' () { this.applyDefaultCategory(true) },
'$route.query.rating_dict_type' () { this.applyDefaultCategory(true) },
// 监听 URL 参数变化,同步到筛选项并刷新
'$route.query.do_status' () { this.applyUrlFilterParams(true) },
'$route.query.is_overdue' () { this.applyUrlFilterParams(true) }
}, },
methods: { methods: {
applyUrlFilterParams (triggerInit) { async init () {
const q = (this.$route && this.$route.query) || {} await this.loadCityOptions()
const hasVal = (v) => v !== undefined && v !== null && String(v) !== '' await this.loadDicts()
let changed = false this.loadList()
if (hasVal(q.do_status)) {
this.filters.do_status = String(q.do_status)
changed = true
}
if (hasVal(q.is_overdue)) {
this.filters.is_overdue = String(q.is_overdue)
changed = true
}
if (triggerInit && changed) this.changePageNo(1)
}, },
fetchVisitButtonPower () { async loadCityOptions () {
const payload = {} try {
return getVisitButtonPower(payload).then((ret) => { const res = await selectCityList({ parent_id: '0' })
if (ret && ret.data && ret.data.errcode === 0) { if (res.data && res.data.errcode === 0) {
this.visitButtonPower = ret.data.data || {} this.cityOptions = res.data.data || []
} else {
this.visitButtonPower = {}
} }
}).catch(() => { this.visitButtonPower = {} }) } catch (e) {
}, console.error('加载城市列表失败', e)
applyDefaultCategory (triggerInit) { }
const cat = this.currentCategory || ''
this.filters.rating_dict_type = cat
if (triggerInit) this.changePageNo(1)
}, },
loadRatingLevelDict () { async loadDicts () {
getDictList({ type: 'rating_level' }).then((ret) => { // 加载风险等级字典
if (ret.data && ret.data.errcode === 0) { try {
const results = ret.data.data && ret.data.data.results ? ret.data.data.results : [] const res = await getDictList({ type: 'rating_level' })
this.ratingTypeOptions = results.map(it => ({ label: it.label || it.name, value: it.value || it.dictValue })) if (res && res.data && res.data.errcode === 0) {
const results = res.data.data && res.data.data.results ? res.data.data.results : []
this.ratingLevelOptions = results.map(it => ({
label: it.label || it.name,
value: it.value || it.dictValue
}))
} }
}) } catch (e) {
}, console.error('加载风险等级字典失败', e)
async changeArea (level, id) { }
// 清空当前及以下级联的值与列表 // 加载回访状态字典
const chain = ['', 'city_id', 'area_id', 'street_id', 'community_id'] try {
const lists = ['', 'cityList', 'areaList', 'streetList', 'communityList'] const res = await getDictList({ type: 'visit_status' })
const lv = Number(level) if (res && res.data && res.data.errcode === 0) {
if (lv > 1 && !id) { const results = res.data.data && res.data.data.results ? res.data.data.results : []
for (let i = lv; i < chain.length; i++) { this.visitStatusOptions = results.map(it => ({
this.$set(this.filters, chain[i], '') label: it.label || it.name,
this[lists[i]] = [] value: it.value || it.dictValue
}))
} }
return } catch (e) {
console.error('加载回访状态字典失败', e)
} }
if (lv === 2) { },
// 选择市 -> 加载区 handleFilterCascade (level, value) {
const ret = await selectCityList({ parent_id: id }) if (level === 'city') {
const data = (ret && ret.data && ret.data.data) || [] this.filters.city_id = value
this.areaList = data
// 级联清空下级
this.filters.area_id = '' this.filters.area_id = ''
this.filters.street_id = '' this.filters.street_id = ''
this.filters.community_id = '' this.filters.community_id = ''
this.streetList = [] this.areaState.areaList = []
this.communityList = [] this.areaState.streetList = []
} else if (lv === 3) { this.areaState.communityList = []
// 选择区 -> 加载街道 if (!value) return
const ret = await selectCityList({ parent_id: id }) selectCityList({ parent_id: value }).then(res => {
const data = (ret && ret.data && ret.data.data) || [] if (res.data && res.data.errcode === 0) {
this.streetList = data this.areaState.areaList = res.data.data || []
}
})
} else if (level === 'area') {
this.filters.area_id = value
this.filters.street_id = '' this.filters.street_id = ''
this.filters.community_id = '' this.filters.community_id = ''
this.communityList = [] this.areaState.streetList = []
} else if (lv === 4) { this.areaState.communityList = []
// 选择街道 -> 加载社区 if (!value) return
const ret = await selectCityList({ parent_id: id }) selectCityList({ parent_id: value }).then(res => {
const data = (ret && ret.data && ret.data.data) || [] if (res.data && res.data.errcode === 0) {
this.communityList = data this.areaState.streetList = res.data.data || []
}
})
} else if (level === 'street') {
this.filters.street_id = value
this.filters.community_id = '' this.filters.community_id = ''
this.areaState.communityList = []
if (!value) return
selectCityList({ parent_id: value }).then(res => {
if (res.data && res.data.errcode === 0) {
this.areaState.communityList = res.data.data || []
}
})
} }
}, },
loadNationDict () { handleSearch () {
findMZList().then((ret) => { this.pager.pageNo = 1
if (ret && ret.data && ret.data.errcode === 0) { this.loadList()
const list = ret.data.data || []
this.mzList = list
const map = {}
list.forEach(it => {
if (it && (it.mzcode || it.value)) {
map[String(it.mzcode || it.value)] = it.mzname || it.label || it.name
}
})
this.nationMap = map
}
})
}, },
init () { handleReset () {
this.tableLoading = true this.filters = {
const enforced = Object.assign({}, this.filters, { rating_dict_type: this.currentCategory || this.filters.rating_dict_type || '' }) name: '',
const query = Object.assign({ params: enforced }, this.params) card_no: '',
findVisitRecordList(query).then((ret) => { city_id: '',
if (ret.data.errcode === 0) { area_id: '',
this.params.totalRecord = ret.data.data.totalRecord street_id: '',
this.tableData = ret.data.data.results community_id: '',
// 异步补全身份证号明文(按需加载) rating_level: '',
this.prefetchCardNos(this.tableData) visit_status: ''
} else { }
this.$Notice.error({ title: '查询失败!', desc: ret.data.errmsg }) this.areaState = {
} areaList: [],
}).finally(() => { this.tableLoading = false }) streetList: [],
// 同步刷新顶部统计:按当前筛选条件统计待办(正常/临期)数量 communityList: []
this.fetchPendingStats(enforced) }
this.pager.pageNo = 1
this.loadList()
}, },
async fetchPendingStats (baseFilters) { async loadList () {
// 新接口一次返回 { normal, nearDue } this.loading = true
const payload = Object.assign({}, baseFilters, { do_status: '0' })
try { try {
const ret = await getPendingStats(payload) // 调用 selectCurrentUserInfo 来重置用户信息并自动填充 area_id
if (ret && ret.data && ret.data.errcode === 0 && ret.data.data) { // 这个 API 后端会调用 DataScopeUtil.resetUser(),根据 company_grade 和 area_id 联合确定匹配哪个字段
const d = ret.data.data let userInfoParams = {}
this.statsPending.normal = Number(d.normal) || 0 try {
this.statsPending.nearDue = Number(d.nearDue) || 0 const userInfoRes = await selectCurrentUserInfo({})
if (userInfoRes && userInfoRes.data && userInfoRes.data.errcode === 0) {
userInfoParams = userInfoRes.data.data || {}
}
} catch (e) {
console.error('获取用户信息失败', e)
// 即使获取用户信息失败,也继续执行查询
}
const normalizedCardNo = normalizeCardNo(this.filters.card_no)
const params = {
...this.filters,
card_no: normalizedCardNo,
cardNo: normalizedCardNo,
pageNo: this.pager.pageNo,
pageSize: this.pager.pageSize,
// 将重置后的用户信息合并到参数中
...userInfoParams
}
// 如果传入了category(重点人员类别),则转换为sys_type传给后端
if (this.category) {
params.sys_type = this.category
}
const res = await findVisitRecordList(params)
if (res && res.data && res.data.errcode === 0) {
const page = res.data.data || { results: [], totalRecord: 0 }
this.tableData = page.results || []
this.pager.totalRecord = page.totalRecord || 0
} else { } else {
this.statsPending.normal = 0 this.$Message.error((res.data && res.data.errmsg) || '查询失败')
this.statsPending.nearDue = 0 this.tableData = []
this.pager.totalRecord = 0
} }
} catch (e) { } catch (e) {
this.statsPending.normal = 0 console.error('查询列表失败', e)
this.statsPending.nearDue = 0 this.$Message.error('查询列表失败')
} this.tableData = []
}, this.pager.totalRecord = 0
extractCountFromStatsResponse (ret) { } finally {
if (!ret || !ret.data) return 0 this.loading = false
if (ret.data.errcode !== 0) return 0
const d = ret.data.data
if (d == null) return 0
// 兼容多种后端返回结构
const possible = [
d.count,
d.total,
d.totalRecord,
d.value,
Array.isArray(d.results) ? d.results.length : undefined
]
const num = possible.find(v => typeof v === 'number')
if (typeof num === 'number') return num
const strNum = possible.find(v => typeof v === 'string')
return Number(strNum) || 0
},
async prefetchCardNos (rows) {
// 批量拉取明文,接口是逐个查;缓存到本地 map,渲染器读取
const ids = (rows || []).map(r => r.key_person_id).filter(Boolean)
const uniq = Array.from(new Set(ids))
for (const id of uniq) {
if (this.cardNoCache[id]) continue
try {
const ret = await getCardNoById({ id })
if (ret && ret.data && ret.data.errcode === 0) {
const real = (ret.data.data && ret.data.data.cardno) || ''
this.$set(this.cardNoCache, id, real)
}
} catch (e) {}
} }
}, },
getDecryptedCardNo (id, fallback) { pageChange (pageNo) {
const cache = this.cardNoCache || {} this.pager.pageNo = pageNo
if (!id) return fallback || '-' this.loadList()
return cache[id] || fallback || '-'
}, },
formatDate (val) { sizeChange (pageSize) {
if (!val) return '-' this.pager.pageSize = pageSize
const d = new Date(val) this.pager.pageNo = 1
if (Number.isNaN(d.getTime())) { this.loadList()
const m = /^\d{4}-\d{2}-\d{2}/.exec(String(val))
return m ? m[0] : String(val)
}
const y = d.getFullYear()
const mm = String(d.getMonth() + 1).padStart(2, '0')
const dd = String(d.getDate()).padStart(2, '0')
return `${y}-${mm}-${dd}`
}, },
formatDateTime (val) { renderRatingLevel (val) {
if (!val) return '-' if (!val) return '-'
const d = new Date(val) const found = this.ratingLevelOptions.find(it => it.value === val)
if (Number.isNaN(d.getTime())) { return found ? found.label : val
const m = /^(\d{4}-\d{2}-\d{2})[ T]?(\d{2}:\d{2}:\d{2})?/.exec(String(val))
if (m) {
return `${m[1]}${m[2] ? ' ' + m[2] : ' 00:00:00'}`
}
return String(val)
}
const y = d.getFullYear()
const mm = String(d.getMonth() + 1).padStart(2, '0')
const dd = String(d.getDate()).padStart(2, '0')
const HH = String(d.getHours()).padStart(2, '0')
const MM = String(d.getMinutes()).padStart(2, '0')
const SS = String(d.getSeconds()).padStart(2, '0')
return `${y}-${mm}-${dd} ${HH}:${MM}:${SS}`
}, },
renderVisitStatus (val) { renderVisitStatus (val) {
const s = String(val)
if (s === '2') return '超期未回访'
if (s === '1') return '已回访'
return '待回访'
},
renderDoStatus (val) {
const s = String(val)
if (s === '2') return '超期未办'
if (s === '1') return '已办'
return '待办'
},
search () { this.changePageNo(1) },
reset () {
this.filters = { rating_dict_type: this.currentCategory || '', name: '', card_no: '', city_id: '', area_id: '', street_id: '', community_id: '', do_status: '0', rating_type: '', is_overdue: '' }
this.changePageNo(1)
},
size (pageSize) { this.params.pageSize = pageSize; this.changePageNo(1) },
changePageNo (pageNo) { this.params.pageNo = pageNo; this.init() },
sizeHistory (pageSize) { this.historyParams.pageSize = pageSize; this.changeHistoryPageNo(1) },
changeHistoryPageNo (pageNo) { this.historyParams.pageNo = pageNo; this.loadHistoryPage() },
renderSex (s) { return s === '1' ? '男' : s === '2' ? '女' : '-' },
renderRatingType (val) {
const found = this.ratingTypeOptions.find(it => it.value === val)
return found ? found.label : val || '-'
},
renderRatingDictType (val) {
const found = this.ratingDictTypeOptions.find(it => String(it.value) === String(val))
return found ? found.label : val || '-'
},
renderFolk (val) {
if (val === null || val === undefined || val === '') return '-' if (val === null || val === undefined || val === '') return '-'
const s = String(val) const s = String(val)
const name = this.nationMap && this.nationMap[s] const found = this.visitStatusOptions.find(it => it.value === s)
return name || s return found ? found.label : (s === '0' ? '无待访' : s === '1' ? '正常待访' : s === '2' ? '临期待访' : s === '3' ? '超期待访' : s)
},
renderRemainDays (val) {
if (val === null || val === undefined || val === '') return '-'
const n = Number(val)
if (Number.isNaN(n)) return String(val)
return String(Math.max(0, n))
},
hasHistory (row) {
const s = String(row && row.do_status)
// 待办(0)、已办(1)、超期未办(2) 都应当可以查看历史
return s === '0' || s === '1' || s === '2'
}, },
canShowVisit (row) { async openVisitModal (row) {
const isAdmin = (this.userInfo.login_name === 'admin') this.visitModal.visible = true
const power = this.visitButtonPower || {} this.visitModal.loading = true
const type = String(row.sys_type || '') const nextForm = createVisitForm()
if (isAdmin) return true nextForm.key_person_id = row.person_id
if (type === '2') return !!power['rucs_visit'] nextForm.key_person_visit_id = row.key_person_visit_id || row.visit_plan_id || ''
if (type === '3') return !!power['psmd_visit'] nextForm.rating_dict_type = row.rating_dict_type
if (type === '6') return !!power['km_visit'] nextForm.sys_type_office_label = row.sys_type_office_label || ''
return false nextForm.sys_type_office_value = row.sys_type_office_value || ''
}, nextForm.plan_name = row.plan_name || ''
openVisitModal (row) { nextForm.plan_type = row.plan_type || ''
this.detail = {} nextForm.rating_type = row.plan_rating_type || row.rating_level || ''
this.visitForm = { key_person_id: row.key_person_id, key_person_visit_id: row.key_person_visit_id || row.key_person_visit_id, id: row.id || row.visit_record_id || '', visit_time: '', visit_record: '', imgs: [] } nextForm.visit_time = this.formatDateTime(new Date())
getVisitRecordDetail({ id: row.id || row.visit_record_id, rating_dict_type: String(row.sys_type || this.currentCategory || this.filters.rating_dict_type || '') }).then((ret) => { this.$set(this.visitModal, 'form', nextForm)
if (ret.data.errcode === 0) { this.currentRatingDictType = row.rating_dict_type || ''
const d = ret.data.data || {} try {
// 计划信息展示补充:取当前计划记录中的字段 const visitParams = { person_id: row.person_id, rating_dict_type: row.rating_dict_type }
this.detail = Object.assign({}, d, { // 如果传入了category(重点人员类别),则转换为sys_type传给后端
record_rating_type: (row && row.rating_type) || d.rating_type, if (this.category) {
plan_name: (row && row.plan_name) || d.plan_name, visitParams.sys_type = this.category
plan_type: (row && row.plan_type) || d.plan_type, } else if (row.sys_type) {
plan_start_data: (row && row.plan_start_data) || d.plan_start_data, // 如果row中有sys_type,也传入
plan_end_data: (row && row.plan_end_data) || d.plan_end_data, visitParams.sys_type = row.sys_type
remain_days: (row && row.remain_days) || d.remain_days }
}) const res = await getPersonInfoForVisit(visitParams)
this.visitForm.key_person_visit_id = this.detail.key_person_visit_id || this.visitForm.key_person_visit_id if (res && res.data && res.data.errcode === 0) {
this.visitForm.id = this.detail.id || this.visitForm.id || this.detail.current_visit_record_id this.visitModal.personInfo = res.data.data || {}
// 历史回访信息
this.historyData = ((this.detail.history) || []).map(it => ({
rating_type: it.rating_type,
visit_user: it.visit_user,
visit_user_company: it.visit_user_company,
visit_time: it.visit_time,
visit_record: it.visit_record,
img: it.img,
do_status: it.do_status
}))
this.visitModal.visible = true
this.$nextTick(() => { this.$refs.visitForm && this.$refs.visitForm.clearValidate() })
} else { } else {
this.$Notice.error({ title: '加载详情失败', desc: ret.data.errmsg }) this.$Message.error((res.data && res.data.errmsg) || '获取人员信息失败')
} }
}) } catch (e) {
}, console.error('获取人员信息失败', e)
openHistoryModal (row) { this.$Message.error('获取人员信息失败')
// 通过回访记录主键展示:显示本次回访信息 + 历史按现有逻辑 } finally {
this.historyParams.key_person_id = row.key_person_id this.visitModal.loading = false
this.historyParams.current_record_id = row.id || row.visit_record_id this.$nextTick(this.clearVisitFormValidate)
this.$nextTick(() => { this.$refs.historyModal && this.$refs.historyModal.open() }) }
}, },
async beforeUploadVisitImg (file) { beforeUpload (file) {
const name = (file && file.name) || '' const isValidType = file.type.startsWith('image/')
const lower = name.toLowerCase() const isLt5M = file.size / 1024 / 1024 < 5
const validExt = /(\.jpg|\.jpeg|\.png)$/i.test(lower) if (!isValidType) {
const validMime = file && (file.type === 'image/jpeg' || file.type === 'image/png') this.$Message.error('只能上传图片文件!')
if (!(validExt || validMime)) { return false
this.$Message.error('仅支持 jpg/jpeg/png 格式图片') }
if (!isLt5M) {
this.$Message.error('图片大小不能超过5MB!')
return false return false
} }
// 本地预览占位 // 使用自定义上传
let previewIndex = -1 this.uploadFile(file)
return false
},
async uploadFile (file) {
const formData = new FormData()
formData.append('file', file)
try { try {
await new Promise((resolve) => { const res = await uploadPic(formData)
const reader = new FileReader() if (res && res.data && res.data.errcode === 0) {
reader.onload = (e) => { const url = res.data.data || res.data.url
this.visitForm.imgs.push(e.target.result) if (url) {
previewIndex = this.visitForm.imgs.length - 1 this.visitModal.form.visit_img_list.push({
resolve() name: file.name,
url: url,
status: 'finished'
})
this.$Message.success('上传成功')
} }
reader.readAsDataURL(file)
})
// 构建上传表单并调用通用上传服务
const formdata = new FormData()
formdata.append('file', file)
formdata.append('fileName', file.name)
const meta = { business_type: 'jlEvent' }
formdata.append('json', JSON.stringify(meta))
const ret = await uploadFile(formdata, meta)
if (ret && ret.data && ret.data.errcode === 0 && ret.data.data) {
const d = ret.data.data
const url = d.url || (`/api/ac/jilinsscgsdp/uploadService/getObsObject?uuid=${d.uuid}&&suffix=${d.suffix}`)
this.$set(this.visitForm.imgs, previewIndex, url)
} else { } else {
// 失败回滚预览 this.$Message.error((res.data && res.data.errmsg) || '上传失败')
if (previewIndex > -1) this.visitForm.imgs.splice(previewIndex, 1)
this.$Notice.error({ title: '上传失败', desc: (ret && ret.data && ret.data.errmsg) || '' })
} }
} catch (e) { } catch (e) {
if (previewIndex > -1) this.visitForm.imgs.splice(previewIndex, 1) console.error('上传失败', e)
this.$Notice.error({ title: '上传失败' }) this.$Message.error('上传失败')
} }
// 阻止组件默认上传
return false
}, },
submitVisit () { handleUploadSuccess (response, file, fileList) {
this.$refs.visitForm.validate((valid) => { // 不使用默认上传,已在beforeUpload中处理
if (!valid) return },
this.visitModal.submitting = true handleUploadRemove (file, fileList) {
if (!this.visitForm.id) { this.visitModal.form.visit_img_list = fileList
this.$Notice.error({ title: '保存失败', desc: '缺少回访记录主键,请刷新后重试' }) },
this.visitModal.submitting = false handleUploadError (error, file, fileList) {
return console.error('图片上传失败', error)
const message = (error && (error.message || error.errMsg)) || '图片上传失败'
this.$Message.error(message)
},
async submitVisit () {
const formRef = this.$refs.visitForm
if (!formRef) {
this.$Message.warning('表单尚未加载完成,请稍后再试')
return
}
formRef.validate(async (valid) => {
console.log('submitVisit', valid)
if (!valid) {
return false
}
const visitTimeStr = this.normalizeVisitTimeValue(this.visitModal.form.visit_time)
if (!visitTimeStr) {
this.$Message.error('请选择有效的回访时间')
return false
} }
const payload = { const visitRecord = (this.visitModal.form.visit_record || '').trim()
key_person_id: this.visitForm.key_person_id, if (!visitRecord) {
key_person_visit_id: this.visitForm.key_person_visit_id, this.$Message.error('请输入回访记录')
id: this.visitForm.id, return false
plan_name: this.detail.plan_name,
plan_type: this.detail.plan_type,
rating_type: this.detail.record_rating_type || this.detail.rating_type,
plan_start_data: this.detail.plan_start_data,
plan_end_data: this.detail.plan_end_data,
visit_time: this.visitForm.visit_time,
visit_record: this.visitForm.visit_record,
img: (this.visitForm.imgs || []).join(',')
} }
insertVisitRecord(payload).then((ret) => { this.visitModal.form.visit_record = visitRecord
if (ret.data && ret.data.errcode === 0) { this.visitModal.submitting = true
this.$Notice.success({ title: '保存成功' }) try {
const visitImg = this.visitModal.form.visit_img_list.map(item => item.url || (item.response && item.response.data && item.response.data.url) || (item.response && item.response.data)).filter(Boolean).join(',')
const params = {
key_person_id: this.visitModal.form.key_person_id,
key_person_visit_id: this.visitModal.form.key_person_visit_id,
rating_dict_type: this.visitModal.form.rating_dict_type,
sys_type_office_label: this.visitModal.form.sys_type_office_label,
sys_type_office_value: this.visitModal.form.sys_type_office_value,
plan_name: this.visitModal.form.plan_name,
plan_type: this.visitModal.form.plan_type,
rating_type: this.visitModal.form.rating_type,
visit_time: visitTimeStr,
visit_record: this.visitModal.form.visit_record,
visit_img: visitImg
}
const res = await saveVisitRecord(params)
if (res && res.data && res.data.errcode === 0) {
this.$Message.success('保存成功')
this.visitModal.visible = false this.visitModal.visible = false
this.init() this.loadList()
} else { } else {
this.$Notice.error({ title: '保存失败', desc: (ret && ret.data && ret.data.errmsg) || '' }) this.$Message.error((res.data && res.data.errmsg) || '保存失败')
} }
}).finally(() => { this.visitModal.submitting = false }) } catch (e) {
console.error('保存回访记录失败', e)
this.$Message.error('保存回访记录失败')
} finally {
this.visitModal.submitting = false
}
})
},
openHistoryModal (row) {
this.historyModal.key_person_id = row.person_id
this.currentRatingDictType = row.rating_dict_type || ''
// 等待 props 更新到子组件后再打开弹窗,避免首次点击时 key_person_id 还是旧值
this.$nextTick(() => {
if (this.$refs.historyModal && typeof this.$refs.historyModal.open === 'function') {
this.$refs.historyModal.open()
}
}) })
}, },
onVisitTimeChange (val) { formatDateTime (date) {
// DatePicker on-change returns formatted string per format if (!date) return ''
this.visitForm.visit_time = val || '' const d = date instanceof Date ? new Date(date.getTime()) : new Date(date)
// proactively clear error once value selected if (Number.isNaN(d.getTime())) return String(date)
if (val && this.$refs.visitForm) this.$refs.visitForm.validateField('visit_time') return this.formatDateSegments(d)
},
formatDateSegments (d) {
const y = d.getFullYear()
const mm = String(d.getMonth() + 1).padStart(2, '0')
const dd = String(d.getDate()).padStart(2, '0')
const HH = String(d.getHours()).padStart(2, '0')
const MM = String(d.getMinutes()).padStart(2, '0')
const SS = String(d.getSeconds()).padStart(2, '0')
return `${y}-${mm}-${dd} ${HH}:${MM}:${SS}`
},
clearVisitFormValidate () {
const visitFormRef = this.$refs.visitForm
if (!visitFormRef) return
if (typeof visitFormRef.clearValidate === 'function') {
visitFormRef.clearValidate()
return
}
if (visitFormRef.fields && Array.isArray(visitFormRef.fields)) {
visitFormRef.fields.forEach(field => {
if (!field) return
field.validateState = ''
field.validateMessage = ''
})
}
},
normalizeVisitTimeValue (value) {
if (!value && value !== 0) return ''
if (value instanceof Date) {
return Number.isNaN(value.getTime()) ? '' : this.formatDateSegments(value)
}
if (typeof value === 'number' && !Number.isNaN(value)) {
const fromNumber = new Date(value)
return Number.isNaN(fromNumber.getTime()) ? '' : this.formatDateSegments(fromNumber)
}
if (typeof value === 'string') {
const trimmed = value.trim()
if (!trimmed) return ''
const direct = new Date(trimmed)
if (!Number.isNaN(direct.getTime())) return this.formatDateSegments(direct)
const withSlash = new Date(trimmed.replace(/-/g, '/'))
if (!Number.isNaN(withSlash.getTime())) return this.formatDateSegments(withSlash)
const match = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/)
if (match) {
const [, y, m, d, hh = '00', mm = '00', ss = '00'] = match
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
return ''
}
if (value && typeof value === 'object' && typeof value.valueOf === 'function') {
const timestamp = value.valueOf()
if (!Number.isNaN(timestamp)) {
const fromValue = new Date(timestamp)
return Number.isNaN(fromValue.getTime()) ? '' : this.formatDateSegments(fromValue)
}
}
return ''
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.contradiction-div { padding: 10px; } .visit-record-wrapper {
.contradiction-div .search-div { width: 100%; padding: 15px; border: 1px solid skyblue; background-color: azure; margin-bottom: 15px; } padding: 16px;
.page_style { margin-top: 10px; text-align: right; } }
.grid { display: grid; grid-template-columns: repeat(4, 1fr); grid-gap: 10px; margin-bottom: 12px; } .search-div {
.section-title { margin: 10px 0; font-weight: 600; } background: #fff;
.info-form { margin-bottom: 8px; } padding: 16px;
.img-list { margin-top: 8px; } margin-bottom: 16px;
::v-deep .history table { }
width: 100% !important; .mb10 {
border-collapse: collapse; margin-bottom: 10px;
}
.text-right {
text-align: right;
}
.page_style {
margin-top: 16px;
text-align: right;
}
.section-title {
margin: 16px 0 12px 0;
font-weight: 600;
font-size: 14px;
color: #333;
}
.info-form {
margin-bottom: 16px;
} }
</style> </style>
...@@ -13,6 +13,12 @@ ...@@ -13,6 +13,12 @@
</Select> </Select>
</Col> </Col>
<Col span="4"> <Col span="4">
<span>部门类型:</span>
<Select v-model="filters.sys_type_office_value" clearable style="width: 55%" placeholder="请选择">
<Option v-for="opt in officeTypeOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option>
</Select>
</Col>
<Col span="4">
<span>启用状态:</span> <span>启用状态:</span>
<Select v-model="filters.status" clearable style="width: 55%" placeholder="请选择"> <Select v-model="filters.status" clearable style="width: 55%" placeholder="请选择">
<Option v-for="opt in statusOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option> <Option v-for="opt in statusOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option>
...@@ -30,6 +36,9 @@ ...@@ -30,6 +36,9 @@
<template slot-scope="{ row }" slot="rating_dict_type"> <template slot-scope="{ row }" slot="rating_dict_type">
<span>{{ renderRatingDictType(row.rating_dict_type) }}</span> <span>{{ renderRatingDictType(row.rating_dict_type) }}</span>
</template> </template>
<template slot-scope="{ row }" slot="sys_type_office_label">
<span>{{ row.sys_type_office_label || '-' }}</span>
</template>
<template slot-scope="{ row }" slot="rating_type"> <template slot-scope="{ row }" slot="rating_type">
<span>{{ renderRatingType(row.rating_type) }}</span> <span>{{ renderRatingType(row.rating_type) }}</span>
</template> </template>
...@@ -56,12 +65,16 @@ ...@@ -56,12 +65,16 @@
@on-page-size-change="size" @on-page-size-change="size"
/> />
<Modal v-model="planModal.visible" :title="planModal.title" width="520"> <Modal v-model="planModal.visible" :title="planModal.title" width="520" @on-visible-change="handleModalVisibleChange">
<Form :model="planModel" ref="planForm" :rules="planRules" :label-width="100"> <Form :model="planModel" ref="planForm" :rules="planRules" :label-width="100">
<FormItem label="重点人员类别" prop="rating_dict_type"> <FormItem label="重点人员类别" prop="rating_dict_type">
<Input :value="renderRatingDictType(planModel.rating_dict_type)" disabled /> <Input :value="renderRatingDictType(planModel.rating_dict_type)" disabled />
</FormItem> </FormItem>
<FormItem label="部门类型" prop="sys_type_office_value">
<Select v-model="planModel.sys_type_office_value" placeholder="请选择部门类型" @on-change="handleOfficeTypeChange">
<Option v-for="opt in officeTypeOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option>
</Select>
</FormItem>
<FormItem label="计划名称" prop="plan_name"> <FormItem label="计划名称" prop="plan_name">
<Input v-model="planModel.plan_name" placeholder="请输入计划名称" /> <Input v-model="planModel.plan_name" placeholder="请输入计划名称" />
</FormItem> </FormItem>
...@@ -123,6 +136,7 @@ export default { ...@@ -123,6 +136,7 @@ export default {
], ],
ratingDictTypeMap: {}, ratingDictTypeMap: {},
ratingTypeOptions: [], ratingTypeOptions: [],
officeTypeOptions: [],
statusOptions: [ statusOptions: [
{ label: '启用', value: '1' }, { label: '启用', value: '1' },
{ label: '停用', value: '2' } { label: '停用', value: '2' }
...@@ -131,6 +145,7 @@ export default { ...@@ -131,6 +145,7 @@ export default {
rating_dict_type: '', rating_dict_type: '',
plan_name: '', plan_name: '',
rating_type: '', rating_type: '',
sys_type_office_value: '',
status: '' status: ''
}, },
params: { params: {
...@@ -141,6 +156,7 @@ export default { ...@@ -141,6 +156,7 @@ export default {
tableColumns: [ tableColumns: [
{ type: 'index', title: '序号', align: 'center', width: 80 }, { type: 'index', title: '序号', align: 'center', width: 80 },
{ title: '重点人员类别', slot: 'rating_dict_type', align: 'center' }, { title: '重点人员类别', slot: 'rating_dict_type', align: 'center' },
{ title: '部门类型', slot: 'sys_type_office_label', align: 'center', width: 120 },
{ title: '计划名称', key: 'plan_name', align: 'center' }, { title: '计划名称', key: 'plan_name', align: 'center' },
{ title: '计划类别', key: 'plan_type', align: 'center' }, { title: '计划类别', key: 'plan_type', align: 'center' },
{ title: '风险等级', slot: 'rating_type', align: 'center', width: 120 }, { title: '风险等级', slot: 'rating_type', align: 'center', width: 120 },
...@@ -157,6 +173,8 @@ export default { ...@@ -157,6 +173,8 @@ export default {
planModel: { planModel: {
id: '', id: '',
rating_dict_type: '', rating_dict_type: '',
sys_type_office_label: '',
sys_type_office_value: '',
plan_name: '', plan_name: '',
plan_type: '', plan_type: '',
rating_type: '', rating_type: '',
...@@ -167,6 +185,7 @@ export default { ...@@ -167,6 +185,7 @@ export default {
}, },
planRules: { planRules: {
rating_dict_type: [{ required: true, message: '请选择重点人员类别', trigger: 'change' }], rating_dict_type: [{ required: true, message: '请选择重点人员类别', trigger: 'change' }],
sys_type_office_value: [{ required: true, message: '请选择部门类型', trigger: 'change' }],
plan_name: [{ required: true, message: '请输入计划名称', trigger: 'blur' }], plan_name: [{ required: true, message: '请输入计划名称', trigger: 'blur' }],
rating_type: [{ required: true, message: '请选择风险等级', trigger: 'change' }], rating_type: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
status: [{ required: true, message: '请选择状态', trigger: 'change' }], status: [{ required: true, message: '请选择状态', trigger: 'change' }],
...@@ -208,6 +227,7 @@ export default { ...@@ -208,6 +227,7 @@ export default {
created () { created () {
this.filters.rating_dict_type = this.currentCategory || '' this.filters.rating_dict_type = this.currentCategory || ''
this.loadRatingLevelDict() this.loadRatingLevelDict()
this.loadOfficeTypeDict()
this.init() this.init()
}, },
watch: { watch: {
...@@ -254,6 +274,25 @@ export default { ...@@ -254,6 +274,25 @@ export default {
} }
}) })
}, },
loadOfficeTypeDict () {
getDictList({ type: 'sys_type_office' }).then((ret) => {
if (ret.data && ret.data.errcode === 0) {
const results = ret.data.data && ret.data.data.results ? ret.data.data.results : []
// ensure structure: [{ label, value }]
this.officeTypeOptions = results.map(it => ({ label: it.label || it.name, value: it.value || it.dictValue }))
} else {
this.$Notice.error({ title: '加载部门类型失败!', desc: (ret.data && ret.data.errmsg) || '' })
}
})
},
handleOfficeTypeChange (value) {
const selected = this.officeTypeOptions.find(it => it.value === value)
if (selected) {
this.planModel.sys_type_office_label = selected.label
} else {
this.planModel.sys_type_office_label = ''
}
},
search () { search () {
this.changePageNo(1) this.changePageNo(1)
}, },
...@@ -261,6 +300,7 @@ export default { ...@@ -261,6 +300,7 @@ export default {
this.filters.rating_dict_type = this.currentCategory || '' this.filters.rating_dict_type = this.currentCategory || ''
this.filters.plan_name = '' this.filters.plan_name = ''
this.filters.rating_type = '' this.filters.rating_type = ''
this.filters.sys_type_office_value = ''
this.filters.status = '' this.filters.status = ''
this.changePageNo(1) this.changePageNo(1)
}, },
...@@ -284,17 +324,54 @@ export default { ...@@ -284,17 +324,54 @@ export default {
const found = this.statusOptions.find(it => it.value === val) const found = this.statusOptions.find(it => it.value === val)
return found ? found.label : val || '-' return found ? found.label : val || '-'
}, },
handleModalVisibleChange (visible) {
if (visible) {
// 弹窗打开时,清除所有验证状态(字段值已在 openAddModal/openEditModal 中设置)
this.$nextTick(() => {
if (this.$refs.planForm && typeof this.$refs.planForm.resetFields === 'function') {
// iView Form 的 resetFields 会清除验证状态,但会重置字段值
// 为了不影响编辑模式的数据,这里只清除验证提示(通过移除错误类)
const formItems = this.$refs.planForm.$el.querySelectorAll('.ivu-form-item-error')
formItems.forEach(item => {
item.classList.remove('ivu-form-item-error')
})
}
})
}
},
openAddModal () { openAddModal () {
this.planModal.title = '新增回访计划' this.planModal.title = '新增回访计划'
this.planModel = { id: '', rating_dict_type: this.currentCategory || '', plan_name: '', plan_type: '', rating_type: '', status: '2', visit_start_day: null, visit_end_day: null, overdue_warning_day: null } // 确保从路由参数或props中获取最新的类别值(重新计算以确保获取最新值)
const route = this.$route || {}
const q = (route.query || {})
const p = (route.params || {})
const fromRoute = q.category || q.rating_dict_type || p.category || p.rating_dict_type || ''
const fromProp = this.category || ''
const category = String(fromProp || fromRoute || '')
// 先重置表单数据,确保重点人员类别有值
this.planModel = { id: '', rating_dict_type: category, sys_type_office_label: '', sys_type_office_value: '', plan_name: '', plan_type: '', rating_type: '', status: '2', visit_start_day: null, visit_end_day: null, overdue_warning_day: null }
// 打开弹窗
this.planModal.visible = true this.planModal.visible = true
this.$nextTick(() => this.$refs.planForm && this.$refs.planForm.clearValidate()) // 打开弹窗后清除验证,但保留重点人员类别值
this.$nextTick(() => {
if (this.$refs.planForm && typeof this.$refs.planForm.resetFields === 'function') {
// 保存当前的重点人员类别值
const savedCategory = this.planModel.rating_dict_type
// 清除验证状态(resetFields 会重置字段值,所以需要重新设置)
this.$refs.planForm.resetFields()
// 重新设置重点人员类别,确保显示正确
this.planModel.rating_dict_type = savedCategory || category
}
})
}, },
openEditModal (row) { openEditModal (row) {
this.planModal.title = '修改回访计划' this.planModal.title = '修改回访计划'
// 先设置表单数据
this.planModel = { this.planModel = {
id: row.id, id: row.id,
rating_dict_type: row.rating_dict_type, rating_dict_type: row.rating_dict_type,
sys_type_office_label: row.sys_type_office_label || '',
sys_type_office_value: row.sys_type_office_value || '',
plan_name: row.plan_name, plan_name: row.plan_name,
plan_type: row.plan_type, plan_type: row.plan_type,
rating_type: row.rating_type, rating_type: row.rating_type,
...@@ -303,8 +380,19 @@ export default { ...@@ -303,8 +380,19 @@ export default {
visit_end_day: row.visit_end_day, visit_end_day: row.visit_end_day,
overdue_warning_day: row.overdue_warning_day overdue_warning_day: row.overdue_warning_day
} }
// 打开弹窗前先清除验证(编辑模式不清除字段值,只清除验证状态)
this.$nextTick(() => {
if (this.$refs.planForm && this.$refs.planForm.$el) {
// 手动清除验证提示(移除错误类)
const formItems = this.$refs.planForm.$el.querySelectorAll('.ivu-form-item-error')
if (formItems && formItems.length > 0) {
formItems.forEach(item => {
item.classList.remove('ivu-form-item-error')
})
}
}
})
this.planModal.visible = true this.planModal.visible = true
this.$nextTick(() => this.$refs.planForm && this.$refs.planForm.clearValidate())
}, },
submitPlan () { submitPlan () {
this.$refs['planForm'].validate((valid) => { this.$refs['planForm'].validate((valid) => {
...@@ -324,28 +412,29 @@ export default { ...@@ -324,28 +412,29 @@ export default {
this.planModal.submitting = false this.planModal.submitting = false
}) })
} }
// 若设置为启用,需保证同一风险等级仅存在一个启用配置 // 若设置为启用,需保证同一部门、同一类别、同一风险等级仅存在一个启用配置
// 注意:允许同一组合存在多条记录,但只能有一条启用状态
if (String(this.planModel.status) === '1') { if (String(this.planModel.status) === '1') {
const params = { const enabledParams = {
params: { params: {
rating_dict_type: this.planModel.rating_dict_type || this.currentCategory || '', rating_dict_type: this.planModel.rating_dict_type || this.currentCategory || '',
rating_type: this.planModel.rating_type, rating_type: this.planModel.rating_type,
sys_type_office_value: this.planModel.sys_type_office_value,
status: '1' status: '1'
}, },
pageNo: 1, pageNo: 1,
pageSize: 1 pageSize: 1
} }
findPersonVisitList(params).then((ret) => { findPersonVisitList(enabledParams).then((ret2) => {
if (ret && ret.data && ret.data.errcode === 0) { if (ret2 && ret2.data && ret2.data.errcode === 0) {
const list = (ret.data.data && ret.data.data.results) || [] const enabledList = (ret2.data.data && ret2.data.data.results) || []
const exist = list.find(it => String(it.id) !== String(this.planModel.id)) const enabledExist = enabledList.find(it => String(it.id) !== String(this.planModel.id))
if (exist) { if (enabledExist) {
this.$Notice.error({ title: '保存失败!', desc: '同一风险等级已存在启用的回访计划,请先停用后再新增/启用。' }) this.$Notice.error({ title: '保存失败!', desc: '同一部门、同一类别、同一风险等级已存在启用的回访计划,请先停用后再新增/启用。' })
return return
} }
doSave() doSave()
} else { } else {
// 查询失败时,兜底允许保存,避免误伤;后端仍可校验
doSave() doSave()
} }
}).catch(() => { doSave() }) }).catch(() => { doSave() })
...@@ -355,10 +444,15 @@ export default { ...@@ -355,10 +444,15 @@ export default {
}) })
}, },
toggleStatus (row, status) { toggleStatus (row, status) {
// 若要启用,需确保同一风险等级没有其他启用项 // 若要启用,需确保同一部门、同一类别、同一风险等级没有其他启用项
if (String(status) === '1') { if (String(status) === '1') {
const params = { const params = {
params: { rating_dict_type: row.rating_dict_type, rating_type: row.rating_type, status: '1' }, params: {
rating_dict_type: row.rating_dict_type,
rating_type: row.rating_type,
sys_type_office_value: row.sys_type_office_value,
status: '1'
},
pageNo: 1, pageNo: 1,
pageSize: 1 pageSize: 1
} }
...@@ -367,10 +461,10 @@ export default { ...@@ -367,10 +461,10 @@ export default {
const list = (ret.data.data && ret.data.data.results) || [] const list = (ret.data.data && ret.data.data.results) || []
const exist = list.find(it => String(it.id) !== String(row.id)) const exist = list.find(it => String(it.id) !== String(row.id))
if (exist) { if (exist) {
this.$Notice.error({ title: '操作失败!', desc: '同一风险等级只能存在一个启用配置,请先停用已启用项。' }) this.$Notice.error({ title: '操作失败!', desc: '同一部门、同一类别、同一风险等级只能存在一个启用配置,请先停用已启用项。' })
return return
} }
const payload = { id: row.id, status, rating_dict_type: row.rating_dict_type, rating_type: row.rating_type } const payload = { id: row.id, status, rating_dict_type: row.rating_dict_type, rating_type: row.rating_type, sys_type_office_value: row.sys_type_office_value }
updatePersonVisitStatus(payload).then((ret2) => { updatePersonVisitStatus(payload).then((ret2) => {
if (ret2.data.errcode === 0) { if (ret2.data.errcode === 0) {
this.$Notice.success({ title: '操作成功' }) this.$Notice.success({ title: '操作成功' })
...@@ -381,7 +475,7 @@ export default { ...@@ -381,7 +475,7 @@ export default {
}) })
} else { } else {
// 查询失败,兜底直接尝试操作(后端仍应校验) // 查询失败,兜底直接尝试操作(后端仍应校验)
const payload = { id: row.id, status, rating_dict_type: row.rating_dict_type, rating_type: row.rating_type } const payload = { id: row.id, status, rating_dict_type: row.rating_dict_type, rating_type: row.rating_type, sys_type_office_value: row.sys_type_office_value }
updatePersonVisitStatus(payload).then((ret2) => { updatePersonVisitStatus(payload).then((ret2) => {
if (ret2.data.errcode === 0) { if (ret2.data.errcode === 0) {
this.$Notice.success({ title: '操作成功' }) this.$Notice.success({ title: '操作成功' })
...@@ -392,7 +486,7 @@ export default { ...@@ -392,7 +486,7 @@ export default {
}) })
} }
}).catch(() => { }).catch(() => {
const payload = { id: row.id, status, rating_dict_type: row.rating_dict_type, rating_type: row.rating_type } const payload = { id: row.id, status, rating_dict_type: row.rating_dict_type, rating_type: row.rating_type, sys_type_office_value: row.sys_type_office_value }
updatePersonVisitStatus(payload).then((ret2) => { updatePersonVisitStatus(payload).then((ret2) => {
if (ret2.data.errcode === 0) { if (ret2.data.errcode === 0) {
this.$Notice.success({ title: '操作成功' }) this.$Notice.success({ title: '操作成功' })
...@@ -404,7 +498,7 @@ export default { ...@@ -404,7 +498,7 @@ export default {
}) })
return return
} }
const payload = { id: row.id, status, rating_dict_type: row.rating_dict_type, rating_type: row.rating_type } const payload = { id: row.id, status, rating_dict_type: row.rating_dict_type, rating_type: row.rating_type, sys_type_office_value: row.sys_type_office_value }
updatePersonVisitStatus(payload).then((ret) => { updatePersonVisitStatus(payload).then((ret) => {
if (ret.data.errcode === 0) { if (ret.data.errcode === 0) {
this.$Notice.success({ title: '操作成功' }) this.$Notice.success({ title: '操作成功' })
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论