Commit 140521ef authored by 沈翠玲's avatar 沈翠玲

我的案件和我的待办

parent 8c506804
......@@ -45,7 +45,11 @@
import { getAppEnvConfig } from '@/utils/env';
import { getTrackRecord } from '@/api/property';
import { batchSave } from '@/api/audit';
import { useUserStore } from '@/stores/modules/user';
const envs = getAppEnvConfig();
const { userInfo } = useUserStore();
import { reactive, ref } from 'vue';
const downloadfile = inject('download');
......@@ -101,6 +105,9 @@
const callMode = ref('');
const paramCallback = (param) => {
const obj = JSON.parse(JSON.stringify(param));
if (userInfo.id) {
obj['createBy'] = userInfo.id
}
obj['auditStatus'] = activeName.value;
if (obj['trackTime']) {
if (obj['trackTime'][0]) obj['trackTimeBegin'] = obj['trackTime'][0];
......@@ -314,7 +321,7 @@
field: 'status',
title: '超时状态',
width: 100,
search: { el: 'select', props: { clearable: true } },
search: { el: 'select', props: { clearable: true }, labelWidth: 78 },
slots: {
default: ({ row }) => {
return (
......@@ -373,7 +380,6 @@
width: 80,
visible:
activeName.value === 'audit' ||
activeName.value === 'complete' ||
activeName.value === 'rejected'
? true
: false,
......@@ -387,14 +393,6 @@
</ElButton>
</>
);
} else {
return (
<>
<ElButton type="primary" onClick={() => callTelephone(row, 'audit')}>
审核
</ElButton>
</>
);
}
},
},
......
<template>
<el-drawer
v-model="showModal"
title="拨打跟进记录"
:size="850"
@close="showModal = false"
direction="rtl"
:before-close="onHide"
>
<div class="h-full flex-col flex mydrawer pb-2">
<div>
<p class="font-bold mb-2">联系人信息:</p>
<div class="flex justify-between">
<div>
<span class="text-gray-400">姓名:</span>
<span>{{ currentInfo.guarantor.name }}</span>
</div>
<div>
<span class="text-gray-400">与案人关系:</span>
<span>{{ currentInfo.guarantor.kinship }}</span>
</div>
<div>
<span class="text-gray-400">联系号码:</span>
<span>{{ currentInfo.guarantor.phone }}</span>
</div>
<div>
<span class="text-gray-400">号码状态:</span>
<span>
<el-radio-group v-model="currentInfo.guarantor.status" disabled>
<el-radio value="N">无效</el-radio>
<el-radio value="Y">有效</el-radio>
</el-radio-group>
</span>
</div>
</div>
</div>
<div>
<ProTable :config="config" :data="tabledata" :showPagination="false" :showToolBar="false">
<template #table_top>
<p class="font-bold">关联案件:</p>
</template>
</ProTable>
</div>
<div class="flex">
<div class="mt-3 pr-8 w-1/2">
<p class="font-bold mb-2">跟进信息:</p>
<el-form
ref="formRef"
inline
:model="form"
:rules="rules"
label-width="110px"
label-position="left"
>
<el-row>
<el-col :span="24">
<el-form-item class="w-full" label="跟进时间:" prop="name">
<el-date-picker
v-model="form.trackTime"
disabled
class="w-full"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetime"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item class="w-full" label="下次跟进时间:" prop="code">
<div>
<el-date-picker
v-model="form.nextTime"
disabled
class="w-full"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetime"
/>
<div>
<el-button size="small" disabled @click="changeLastTime('tomorrow')"
>明天</el-button
>
<el-button size="small" disabled @click="changeLastTime('tomorrowDay')"
>后天</el-button
>
<el-button size="small" disabled @click="changeLastTime('tomorrow2Day')"
>2天后</el-button
>
</div>
</div>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item
class="w-full"
style="display: block"
label="跟进结果:"
prop="name"
label-position="top"
>
<el-tabs v-model="resuleObj.label" class="w-full">
<el-tab-pane
:label="item.label"
:name="item.label"
v-for="(item, index) in tabObj"
:key="`tab${index}`"
>
<el-button
size="small"
:type="resuleObj.childrenlabel === item1.value ? 'primary' : null"
plain
v-for="(item1, index1) in item.children"
:key="`tabchild${index1}`"
disabled
@click="resuleObj.childrenlabel = item1.value"
>{{ item1.label }}</el-button
>
</el-tab-pane>
</el-tabs>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item class="w-full" style="display: block" label="跟进状态:" prop="code">
<el-button
size="small"
style="margin-left: 0"
class="mr-2 mb-2"
disabled
:type="form.phoneResultStatus === item1.value ? 'primary' : null"
plain
v-for="(item1, index1) in statusArr"
:key="`btn${index1}`"
@click="form.phoneResultStatus = item1.value"
>{{ item1.label }}</el-button
>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item class="w-full" label="跟进备注:" prop="code" style="display: block">
<el-input
v-model="form.remark"
class="w-full"
disabled
:rows="2"
type="textarea"
placeholder="请输入"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="w-1/2">
<p class="font-bold mb-2 mt-2">跟进附件:</p>
<el-form inline :model="form" :rules="rules" label-width="110px" label-position="left">
<el-form-item class="w-full" label="通话录音:" prop="code">
<el-icon>
<Download
v-for="(item, index) in form.voices"
:key="index"
@click="download(item)"
/>
</el-icon>
<el-upload
class="avatar-uploader"
:action="url"
:on-success="handleFileSuccess"
:on-remove="handleRemove"
:disabled="props.mode !== 'handle'"
:auto-upload="true"
>
<el-button type="primary" plain :icon="Upload" :disabled="props.mode !== 'handle'"
>上传录音文件</el-button
>
</el-upload>
<!-- 进度条 -->
<!-- <el-progress v-if="progressFlag" :percentage="loadProgress" /> -->
</el-form-item>
<el-form-item label="微信图片附件:" prop="code" class="w-full">
<el-upload
:action="url"
list-type="picture-card"
v-model:file-list="form.images"
class="mypicture"
:on-preview="handlePictureCardPreview"
:on-success="handleFileSuccess1"
:disabled="props.mode !== 'handle'"
:on-remove="handleRemove1"
>
<div class="text-center">
<el-icon><Plus /></el-icon>
<div>微信相关附件</div>
</div>
</el-upload>
</el-form-item>
<el-form-item label="短信图片附件:" prop="code" class="w-full">
<el-upload
:action="url"
list-type="picture-card"
class="mypicture"
v-model:file-list="form.notes"
:disabled="props.mode !== 'handle'"
:on-preview="handlePictureCardPreview"
:on-success="handleFileSuccess2"
:on-remove="handleRemove2"
>
<div class="text-center">
<el-icon><Plus /></el-icon>
<div>短信相关附件</div>
</div>
</el-upload>
</el-form-item>
<el-form-item label="其他图片附件:" prop="code" class="w-full">
<el-upload
:action="url"
list-type="picture-card"
v-model:file-list="form.others"
:disabled="props.mode !== 'handle'"
class="mypicture"
:on-preview="handlePictureCardPreview"
:on-success="handleFileSuccess3"
:on-remove="handleRemove3"
>
<div class="text-center">
<el-icon><Plus /></el-icon>
<div>其他相关附件</div>
</div>
</el-upload>
</el-form-item>
</el-form>
</div>
</div>
</div>
<template #footer>
<div style="flex: auto">
<el-button @click="showModal = false">取消</el-button>
<el-button type="primary" @click="submitForm" v-if="props.mode === 'handle'"
>确定</el-button
>
<template v-else>
<el-button type="primary" @click="submitForm('passed')">通过</el-button>
<el-button type="danger" @click="submitForm('rejected')">拒绝</el-button>
</template>
</div>
</template>
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
</el-drawer>
</template>
<script setup lang="jsx" name="reduceDrawer">
import dayjs from 'dayjs';
import { computed, inject } from 'vue';
import { reactive, ref } from 'vue';
import { ElInputNumber, ElMessage } from 'element-plus';
import { Upload, Download } from '@element-plus/icons-vue';
import { getAppEnvConfig } from '@/utils/env';
import { saveTrackRecord } from '@/api/property';
import { auditAudit } from '@/api/audit';
const envs = getAppEnvConfig();
const downloadfile = inject('download');
const url = envs.VITE_GLOB_API_URL_PREFIX + '/sys/upload';
const showModal = ref(false);
const editFirst = ref(false);
const tabledata = ref([]);
const progressFlag = ref(false);
const loadProgress = ref(0);
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
const props = defineProps({
mode: String,
});
const emits = defineEmits(['success']);
const tabObj = [
{
label: '本人可联',
children: [
{ label: '接通后挂断', value: 'hang_up' },
{ label: '接通有实质进展', value: 'progress' },
],
},
{
label: '联系人可联',
children: [
{ label: '接通有效转告', value: 'pass_on' },
{ label: '接通拒绝转告', value: 'no_pass' },
{ label: '接听后挂断', value: 'Hang_up_after_answering' },
{ label: '接通无应答', value: 'No_response_when_connected' },
{ label: '称与债人无关', value: 'Claims_unrelated_to_creditors' },
{ label: '称非本人', value: 'Claiming_not_to_be_myself' },
],
},
{
label: '未接听',
children: [
{ label: '无人接听', value: 'no_answer' },
{ label: '关机', value: 'Shutdown' },
{ label: '空号', value: 'dead_number' },
{ label: '占线/忙音/正在通话中', value: 'Busy' },
{ label: '停机', value: 'closing_down' },
{ label: '机器人回复', value: 'Robot_reply' },
],
},
{
label: '非电联',
children: [
{ label: '微信', value: 'WeChat' },
{ label: '短信', value: 'short_message' },
{ label: 'QQ', value: 'QQ' },
{ label: '飞书', value: 'fly' },
{ label: '钉钉', value: 'DING' },
],
},
];
const resuleObj = reactive({
label: '本人可联',
childrenlabel: null,
});
const form = reactive({
sum: 0,
images: [],
notes: [],
phoneResultStatus: '',
others: [],
voices: [],
remark: '',
trackTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
nextTime: null,
});
const currentInfo = ref({ name: 0, kinship: 0, phone: 0, status: '' });
const onHide = (done) => {
done();
};
const statusArr = [
{
label: '后续再跟进',
value: 'later',
},
{
label: '承诺还款',
value: 'Promise_Repayment',
},
{
label: '暂无还款意愿',
value: 'No_Repay',
},
{
label: '要求停催',
value: 'Stop_Urging',
},
{
label: '情绪激动抗拒',
value: 'resistance',
},
{
label: '拒绝还款',
value: 'Refuse_Repayment',
},
{
label: '已还款',
value: 'Repaired',
},
{
label: '代履行还款',
value: 'repayment_others',
},
];
const selectdList = ref([]);
const onCheckboxChange = (row) => {
selectdList.value = row.records;
};
const handleRemove = (uploadFile, uploadFiles) => {
const index = form.voices.findIndex((v) => v.name === uploadFile.name);
form.voices.splice(index, 1);
};
const handlePictureCardPreview = (uploadFile) => {
dialogImageUrl.value = uploadFile.url;
dialogVisible.value = true;
};
const changeLastTime = (day) => {
if (day === 'tomorrow') {
form.nextTime = dayjs().add(1, 'day').format('YYYY-MM-DD HH:mm:ss');
} else if (day === 'tomorrowDay') {
form.nextTime = dayjs().add(2, 'day').format('YYYY-MM-DD HH:mm:ss');
} else {
form.nextTime = dayjs().add(3, 'day').format('YYYY-MM-DD HH:mm:ss');
}
};
const handleFileSuccess = (response, file, fileList) => {
if (file.uid) {
const item = form.voices.find((v) => v.uid === file.uid);
item.url = envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + response.message;
}
};
const handleFileSuccess1 = (response, file, fileList) => {
if (file.uid) {
const item = form.images.find((v) => v.uid === file.uid);
item.url = envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + response.message;
}
};
const handleRemove1 = (uploadFile, uploadFiles) => {
const index = form.images.findIndex((v) => v.name === uploadFile.name);
form.images.splice(index, 1);
};
const handleFileSuccess2 = (response, file, fileList) => {
// console.log(response, file);
if (file.uid) {
const item = form.notes.find((v) => v.uid === file.uid);
item.url = envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + response.message;
}
};
const handleRemove2 = (uploadFile, uploadFiles) => {
const index = form.notes.findIndex((v) => v.name === uploadFile.name);
form.notes.splice(index, 1);
};
const handleFileSuccess3 = (response, file, fileList) => {
if (file.uid) {
const item = form.others.find((v) => v.uid === file.uid);
item.url = envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + response.message;
}
};
const download = (item) => {
const name = item.slice(item.lastIndexOf('/') + 1, item.length);
downloadfile(envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + item, {}, name);
};
const handleRemove3 = (uploadFile, uploadFiles) => {
const index = form.others.findIndex((v) => v.name === uploadFile.name);
form.others.splice(index, 1);
};
const config = reactive({
minHeight: 200,
columns: [
// { type: 'checkbox', width: 50 },
{
field: 'caseId',
title: '案件ID',
showOverflow: 'tooltip',
},
{
field: 'product',
showOverflow: 'tooltip',
title: '产品',
},
{
field: 'loanPlatform.name',
showOverflow: 'tooltip',
title: '借款机构',
},
{
field: 'commissionAmount',
showOverflow: 'tooltip',
title: '委案金额',
},
{
field: 'sumReductionAmount',
showOverflow: 'tooltip',
title: '累计减免金额',
},
{
field: 'sumRepayAmount',
showOverflow: 'tooltip',
title: '累计还款金额',
},
{
field: 'remainingAmount',
showOverflow: 'tooltip',
title: '剩余待还金额',
},
],
onCheckboxChange: onCheckboxChange,
toolbarConfig: { enabled: false },
});
const openModal = (info) => {
showModal.value = true;
currentInfo.value = info;
form.trackTime = info.trackTime;
form.remark = info.remark;
form.phoneResultStatus = info.phoneResultStatus;
resuleObj.childrenlabel = info.followStatus;
form.nextTime = info.nextTime;
form.notes = info.notes
? info.notes.map((v) => ({
name: v.slice(v.lastIndexOf('/') + 1, v.length),
url: envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + v,
}))
: [];
form.voices = info.voices
? info.voices.map((v) => ({
name: v.slice(v.lastIndexOf('/') + 1, v.length),
url: envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + v,
}))
: [];
form.images = info.images
? info.images.map((v) => ({
name: v.slice(v.lastIndexOf('/') + 1, v.length),
url: envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + v,
}))
: [];
form.others = info.others
? info.others.map((v) => ({
name: v.slice(v.lastIndexOf('/') + 1, v.length),
url: envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + v,
}))
: [];
tabledata.value = info.loans;
console.log('formform', form);
};
const submitForm = (type) => {
let voices = JSON.parse(JSON.stringify(form.voices.map((v) => v.url)));
let images = JSON.parse(JSON.stringify(form.images.map((v) => v.url)));
let notes = JSON.parse(JSON.stringify(form.notes.map((v) => v.url)));
let others = JSON.parse(JSON.stringify(form.others.map((v) => v.url)));
voices = voices.map((v) => {
return v.replace(envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/', '');
});
images = images.map((v) => {
return v.replace(envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/', '');
});
notes = notes.map((v) => {
return v.replace(envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/', '');
});
others = others.map((v) => {
return v.replace(envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/', '');
});
saveTrackRecord({
loans: tabledata.value,
id: currentInfo.value.id,
guarantor: currentInfo.value.guarantor,
trackTime: form.trackTime,
nextTime: form.nextTime,
phoneResultStatus: form.phoneResultStatus,
auditStatus: type === 'rejected' ? 'rejected' : type === 'passed' ? 'passed' : 'complete',
followStatus: resuleObj.childrenlabel,
remark: form.remark,
voices: voices.length > 0 ? voices : null,
images: images.length > 0 ? images : null,
notes: notes.length > 0 ? notes : null,
others: others.length > 0 ? others : null,
}).then((res) => {
if (res.success) {
ElMessage.success({
message: '保存成功',
plain: true,
});
showModal.value = false;
emits('success');
}
});
};
defineExpose({
openModal,
});
</script>
<style lang="scss" scoped>
.mydrawer {
:deep(.card) {
padding: 0;
border: none;
}
:deep(.el-date-editor) {
width: 100%;
}
.el-form-item {
margin-right: 0;
}
}
.mypicture {
:deep(.el-upload--picture-card) {
width: 80px;
height: 80px;
}
:deep(.el-upload-list__item) {
width: 80px;
height: 80px;
}
:deep(.el-upload--picture-card) {
font-size: 12px;
}
}
</style>
<template>
<div class="card content-box">
<span class="text"> 稽核任务 🍓🍇🍈🍉</span>
<div class="table-box">
<div>
<ProTable
:config="config"
ref="caseLRef"
:api="getTrackRecord"
:paramCallback="paramCallback"
>
<template #table_top>
<div>
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane
:label="item.label"
:name="item.value"
v-for="(item, index) in auditStatusOpt"
:key="index"
></el-tab-pane>
</el-tabs>
</div>
</template>
<!-- 表格 header 按钮 -->
<template #left_buttons>
<el-button
type="primary"
@click="audit"
:disabled="!selectdList || selectdList.length === 0"
>发起稽核</el-button
>
</template>
</ProTable>
</div>
<callDrawer ref="callDrawerRef" @success="query()" :mode="callMode"></callDrawer>
<el-image-viewer :url-list="srcList" v-if="RefImage" @close="RefImage = false" />
</div>
</template>
<script setup name="systemLog"></script>
<script setup name="case-audit" lang="jsx">
import { Download } from '@element-plus/icons-vue';
import { inject } from 'vue';
import { computed } from 'vue';
import callDrawer from './components/callDrawer.vue';
import { ElMessageBox, ElButton, ElTag } from 'element-plus';
import { onMounted } from 'vue';
import { getAppEnvConfig } from '@/utils/env';
import { getTrackRecord } from '@/api/property';
import { batchSave } from '@/api/audit';
import { useUserStore } from '@/stores/modules/user';
const { userInfo } = useUserStore();
const envs = getAppEnvConfig();
import { reactive, ref } from 'vue';
const downloadfile = inject('download');
const allocationModalRef = ref();
const caseLRef = ref();
const selectdList = ref([]);
const callDrawerRef = ref();
const srcList = ref([]);
const RefImage = ref(false);
const onCheckboxChange = (row) => {
selectdList.value = row.records;
};
const followStatusOpt = [
{ label: '接通后挂断', value: 'hang_up' },
{ label: '接通有实质进展', value: 'progress' },
{ label: '接通有效转告', value: 'pass_on' },
{ label: '接通拒绝转告', value: 'no_pass' },
{ label: '接听后挂断', value: 'Hang_up_after_answering' },
{ label: '接通无应答', value: 'No_response_when_connected' },
{ label: '称与债人无关', value: 'Claims_unrelated_to_creditors' },
{ label: '称非本人', value: 'Claiming_not_to_be_myself' },
{ label: '无人接听', value: 'no_answer' },
{ label: '关机', value: 'Shutdown' },
{ label: '空号', value: 'dead_number' },
{ label: '占线/忙音/正在通话中', value: 'Busy' },
{ label: '停机', value: 'closing_down' },
{ label: '机器人回复', value: 'Robot_reply' },
{ label: '微信', value: 'WeChat' },
{ label: '短信', value: 'short_message' },
{ label: 'QQ', value: 'QQ' },
{ label: '飞书', value: 'fly' },
{ label: '钉钉', value: 'DING' },
];
const phoneResultStatusOpt = [
{ label: '后续再跟进', value: 'later' },
{ label: '承诺还款', value: 'Promise_Repayment' },
{ label: '暂无还款意愿', value: 'No_Repay' },
{ label: '要求停催', value: 'Stop_Urging' },
{ label: '情绪激动抗拒', value: 'resistance' },
{ label: '拒绝还款', value: 'Refuse_Repayment' },
{ label: '已还款', value: 'Repaired' },
{ label: '代履行还款', value: 'repayment_others' },
];
const auditStatusOpt = [
{ label: '未稽核', value: 'un_audit' },
{ label: '稽核中', value: 'audit' },
{ label: '已拒绝', value: 'rejected' },
{ label: '已完成', value: 'complete' },
{ label: '稽核通过', value: 'passed' },
];
const activeName = ref('un_audit');
const callMode = ref('');
const paramCallback = (param) => {
const obj = JSON.parse(JSON.stringify(param));
obj['auditStatus'] = activeName.value;
if (userInfo.id) {
obj['createBy'] = userInfo.id
}
if (obj['trackTime']) {
if (obj['trackTime'][0]) obj['trackTimeBegin'] = obj['trackTime'][0];
if (obj['trackTime'][1]) obj['trackTimeEnd'] = obj['trackTime'][1];
delete obj['trackTime'];
}
if (obj['nextTime']) {
if (obj['nextTime'][0]) obj['nextTrackTimeBegin'] = obj['nextTime'][0];
if (obj['nextTime'][1]) obj['nextTrackTimeEnd'] = obj['nextTime'][1];
delete obj['nextTime'];
}
// obj['voices'] = 'Y'
// obj['images'] = 'Y'
// obj['notes'] = 'Y'
// obj['others'] = 'Y'
return obj;
};
const callTelephone = (row, type) => {
callMode.value = type;
callDrawerRef.value.openModal(JSON.parse(JSON.stringify(row)));
};
const handleClick = () => {
setTimeout(() => {
query();
}, 300);
};
const config = computed(() => {
return {
rowStyle ({ row }) {
if (row.auditDesc === 'time_out') {
return {
backgroundColor: 'rgb(242,217,217)'
}
}
},
columns: [
{ type: 'checkbox', title: '', width: 40 },
{ field: 'id', title: '跟进记录ID', showOverflow: 'tooltip', width: 90 },
{
field: 'caseId',
title: '案件ID',
showOverflow: 'tooltip',
width: 80,
search: { el: 'input', props: { clearable: true }, labelWidth: 78 },
slots: {
default: ({ row }) => {
return <>{Array.from(new Set(row.loans.map((v) => v.caseId))).join(',')}</>;
},
},
},
{
field: 'trackTime',
title: '跟进日期',
showOverflow: 'tooltip',
width: 100,
search: {
el: 'date-picker',
props: { type: 'daterange', valueFormat: 'YYYY-MM-DD' },
labelWidth: 78,
},
},
{
field: 'nextTime',
title: '下次跟进时间',
showOverflow: 'tooltip',
width: 110,
search: {
el: 'date-picker',
props: { type: 'daterange', valueFormat: 'YYYY-MM-DD' },
labelWidth: 78,
},
},
{
field: 'guarantor.name',
title: '联系人姓名',
showOverflow: 'tooltip',
width: 110,
search: { el: 'input', props: { clearable: true }, key: 'guarantorName', labelWidth: 78 },
},
{
field: 'guarantor.phone',
title: '联系人号码',
showOverflow: 'tooltip',
width: 110,
search: {
el: 'input',
props: { clearable: true },
key: 'guarantorPhone',
labelWidth: 78,
},
labelWidth: 78,
},
{
field: 'followStatus',
title: '拨打跟进结果',
showOverflow: 'tooltip',
width: 120,
enum: followStatusOpt,
search: {
el: 'select',
props: { filterable: true, multiple: true, 'collapse-tags': true },
labelWidth: 78,
defaultValue: [
'progress',
'pass_on',
'no_pass',
'Claims_unrelated_to_creditors',
'Claiming_not_to_be_myself',
],
},
fieldNames: { label: 'label', value: 'value' },
slots: {
default: ({ row }) => {
return (
<>
{row.followStatus
? followStatusOpt.find((v) => v.value === row.followStatus).label
: ''}
</>
);
},
},
},
{
field: 'phoneResultStatus',
title: '拨打处置状态',
showOverflow: 'tooltip',
width: 120,
enum: phoneResultStatusOpt,
search: { el: 'select', props: { filterable: true }, labelWidth: 78 },
fieldNames: { label: 'label', value: 'value' },
slots: {
default: ({ row }) => {
return (
<>
{row.phoneResultStatus
? phoneResultStatusOpt.find((v) => v.value === row.phoneResultStatus).label
: ''}
</>
);
},
},
},
{
field: 'trackRecord.auditStatus',
title: '稽核状态',
showOverflow: 'tooltip',
width: 80,
slots: {
default: ({ row }) => {
return (
<>
{row.auditStatus
? auditStatusOpt.find((v) => v.value === row.auditStatus).label
: ''}
</>
);
},
},
},
{
field: 'remark',
title: '备注',
showOverflow: 'tooltip',
width: 80,
search: { el: 'input', props: { clearable: true }, labelWidth: 78 },
},
{
field: 'voices',
title: '通话录音',
showOverflow: 'tooltip',
width: 80,
slots: {
default: ({ row, rowIndex }) => {
if (row.voices && row.voices.length > 0) {
return (
<>
{row.voices.map((item, index) => (
<el-icon>
<Download onClick={() => download(row)} />
</el-icon>
))}
</>
);
}
},
},
},
{
field: 'code',
title: '微信图片附件',
showOverflow: 'tooltip',
width: 100,
slots: {
default: ({ row, rowIndex }) => {
if (row.images && row.images.length > 0) {
return (
<>
<div className="flex justify-center">
<ElButton onClick={() => preview(row, 'images')} link type="primary">
查看
</ElButton>
</div>
</>
);
}
},
},
},
{
field: 'status',
title: '超时状态',
width: 100,
search: { el: 'select', props: { clearable: true }, labelWidth: 78 },
slots: {
default: ({ row }) => {
return (
<ElTag type={row.auditDesc == 'time_out' ? 'danger' : 'primary'}>
{row.auditDesc == 'time_out' ? '已超时' : '正常'}
</ElTag>
);
},
},
},
{
field: 'code',
title: '短信图片附件',
showOverflow: 'tooltip',
width: 100,
slots: {
default: ({ row, rowIndex }) => {
if (row.notes && row.notes.length > 0) {
return (
<>
<div className="flex justify-center">
<ElButton onClick={() => preview(row, 'notes')} link type="primary">
查看
</ElButton>
</div>
</>
);
}
},
},
},
{
field: 'code',
title: '其他图片附件',
showOverflow: 'tooltip',
width: 100,
slots: {
default: ({ row, rowIndex }) => {
if (row.others && row.others.length > 0) {
return (
<>
<div className="flex justify-center">
<ElButton onClick={() => preview(row, 'others')} link type="primary">
查看
</ElButton>
</div>
</>
);
}
},
},
},
{
field: 'code',
title: '操作',
width: 80,
visible:
activeName.value === 'audit' ||
activeName.value === 'rejected'
? true
: false,
slots: {
default: ({ row, rowIndex }) => {
if (activeName.value === 'audit' || activeName.value === 'rejected') {
return (
<>
<ElButton type="primary" onClick={() => callTelephone(row, 'handle')}>
处理
</ElButton>
</>
);
}
},
},
},
],
onCheckboxChange: onCheckboxChange,
};
});
const preview = (item, type) => {
const list = [];
item[type].forEach((v) => {
list.push(envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + v);
});
RefImage.value = true;
srcList.value = list;
};
const download = (item) => {
const name = item.slice(item.lastIndexOf('/') + 1, item.length);
downloadfile(envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + item, {}, name);
};
const audit = async (row) => {
const list = caseLRef.value.element.getCheckboxRecords();
if (!list.length) return;
await ElMessageBox.confirm('是否确认发起稽核勾选项?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
});
const ids = list.map((v) => v.id).join(',');
await batchSave({ ids: ids });
ElMessage({
type: 'success',
message: '稽核成功!',
plain: true,
});
query();
};
const query = () => caseLRef.value?.search();
onMounted(() => {
query();
});
</script>
<template>
<div class="card content-box">
<span class="text"> 我的案件 🍓🍇🍈🍉</span>
<div class="table-box">
<div class="table-inner">
<ProTable :config="config" ref="caseLRef" :api="getCreditPage" :paramCallback="paramCallback">
<!-- <ProTable :config="config" ref="caseLRef" :data="data"> -->
<!-- <template #table_top>
<div class="topgrp">
<div class="topbox">
<div class="topinner">
<p>统计值</p>
<p>111</p>
</div>
</div>
</div>
</template> -->
</ProTable>
</div>
</div>
</template>
<script setup name="systemLog"></script>
<script setup name="case-manage" lang="jsx">
import { useRouter } from 'vue-router';
import { reactive, ref } from 'vue';
import { getCreditPage } from '@/api/property';
const caseLRef = ref();
import { onMounted } from 'vue';
import { useUserStore } from '@/stores/modules/user';
const { userInfo } = useUserStore();
const router = useRouter();
const onCellClick = (row) => {
router.push({
path: '/property/case-detail',
query: { id: row.id }, //这里不能直接写成 query: JSON.stringify(item)
});
};
const paramCallback = (param) => {
const obj = JSON.parse(JSON.stringify(param));
if (userInfo.id) {
obj['cpe'] = userInfo.id
}
return obj;
};
const followStatusOpt = [
{ label: '接通后挂断', value: 'hang_up' },
{ label: '接通有实质进展', value: 'progress' },
{ label: '接通有效转告', value: 'pass_on' },
{ label: '接通拒绝转告', value: 'no_pass' },
{ label: '接听后挂断', value: 'Hang_up_after_answering' },
{ label: '接通无应答', value: 'No_response_when_connected' },
{ label: '称与债人无关', value: 'Claims_unrelated_to_creditors' },
{ label: '称非本人', value: 'Claiming_not_to_be_myself' },
{ label: '无人接听', value: 'no_answer' },
{ label: '关机', value: 'Shutdown' },
{ label: '空号', value: 'dead_number' },
{ label: '占线/忙音/正在通话中', value: 'Busy' },
{ label: '停机', value: 'closing_down' },
{ label: '机器人回复', value: 'Robot_reply' },
{ label: '微信', value: 'WeChat' },
{ label: '短信', value: 'short_message' },
{ label: 'QQ', value: 'QQ' },
{ label: '飞书', value: 'fly' },
{ label: '钉钉', value: 'DING' },
];
const phoneResultStatusOpt = [
{ label: '后续再跟进', value: 'later' },
{ label: '承诺还款', value: 'Promise_Repayment' },
{ label: '暂无还款意愿', value: 'No_Repay' },
{ label: '要求停催', value: 'Stop_Urging' },
{ label: '情绪激动抗拒', value: 'resistance' },
{ label: '拒绝还款', value: 'Refuse_Repayment' },
{ label: '已还款', value: 'Repaired' },
{ label: '代履行还款', value: 'repayment_others' },
];
const caseStatusOpt = [
{ label: '正常', value: 'normal' },
{ label: '撤案', value: 'withdraw' },
{ label: '留案', value: 'stay' },
];
const config = reactive({
columns: [
{
field: 'caseId',
title: '案件ID',
search: { el: 'input', labelWidth: 80 },
width: 190,
slots: {
default: ({ row, rowIndex }) => {
return (
<>
<div
onClick={() => onCellClick(row)}
className=" text-blue-400 underline cursor-pointer"
>
{row.caseId}
</div>
</>
);
},
},
},
{
field: 'loanPlatform.name',
title: '借款机构',
width: 100,
search: { el: 'input', props: { clearable: true }, key: 'payOrg', labelWidth: 80 },
},
{
field: 'manageOrg.orgName',
title: '资管公司',
width: 100,
search: { el: 'input', props: { clearable: true }, key: 'manageOrg', labelWidth: 80 },
},
{
field: 'borrower.name',
title: '借款人姓名',
width: 120,
search: {
el: 'input',
key: 'borrowerName',
props: { clearable: true },
labelWidth: 80,
},
},
{
field: 'borrower.idCard',
title: '身份证',
width: 140,
search: {
el: 'input',
props: { clearable: true },
key: 'borrowerIdCard',
labelWidth: 80,
},
},
{
field: 'borrower.phone',
title: '手机号',
width: 140,
search: {
el: 'input',
props: { clearable: true },
key: 'borrowerPhone',
labelWidth: 80,
},
},
{
field: 'discount',
title: '折扣',
width: 80,
},
{
field: 'commissionAmount',
title: '委案金额',
width: 80,
search: { el: 'input', props: { clearable: true }, labelWidth: 80 },
},
{
field: 'sumRepayAmount',
title: '累计还款金额',
width: 100,
search: { el: 'input', props: { clearable: true }, labelWidth: 80 },
},
{
field: 'sumReductionAmount',
title: '累计减免金额',
width: 100,
search: { el: 'input', props: { clearable: true }, labelWidth: 80 },
},
{
field: 'remainingAmount',
title: '剩余待还金额',
width: 100,
search: { el: 'input', props: { clearable: true }, labelWidth: 80 },
},
{
field: 'cpeDate',
title: '分派CPE日期',
width: 130,
search: {
el: 'date-picker',
props: { type: 'date', valueFormat: 'YYYY-MM-DD' },
labelWidth: 80,
},
},
{
field: 'principalBalance',
title: '本金余额',
width: 80,
search: { el: 'input', props: { clearable: true }, labelWidth: 80 },
},
{
field: 'debitInterest',
title: '欠息额',
width: 80,
search: { el: 'input', props: { clearable: true }, labelWidth: 80 },
},
{
field: 'commission',
title: '手续费',
width: 80,
search: { el: 'input', props: { clearable: true }, labelWidth: 80 },
},
{
field: 'followStatus',
title: '跟进结果',
width: 80,
enum: followStatusOpt,
search: { el: 'select', props: { filterable: true }, labelWidth: 80 },
fieldNames: { label: 'label', value: 'value' },
slots: {
default: ({ row }) => {
return (
<>
{row.followStatus
? followStatusOpt.find((v) => v.value === row.followStatus).label
: ''}
</>
);
},
},
},
{
field: 'phoneResultStatus',
title: '跟进状态',
width: 80,
enum: phoneResultStatusOpt,
search: { el: 'select', props: { filterable: true }, labelWidth: 80 },
fieldNames: { label: 'label', value: 'value' },
slots: {
default: ({ row }) => {
return (
<>
{row.phoneResultStatus
? phoneResultStatusOpt.find((v) => v.value === row.phoneResultStatus).label
: ''}
</>
);
},
},
},
{
field: 'caseStatus',
title: '案件状态',
width: 80,
enum: caseStatusOpt,
search: { el: 'select', props: { filterable: true }, labelWidth: 80 },
fieldNames: { label: 'label', value: 'value' },
slots: {
default: ({ row }) => {
return (
<>
{row.caseStatus ? caseStatusOpt.find((v) => v.value === row.caseStatus).label : ''}
</>
);
},
},
},
],
});
const query = () => caseLRef.value?.search();
onMounted(() => {
query();
});
</script>
<style lang="scss" scoped>
.table-inner {
width: 100%;
:deep(.topgrp) {
display: flex;
margin-bottom: 8px;
.topbox {
margin-right: 10px;
background: rgba(0, 0, 0, 0.02);
border-radius: 16px;
width: 146px;
height: 97px;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
p:nth-child(1) {
font-size: 14px;
color: rgba(0, 0, 0, 0.45);
}
}
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment