Commit d1888f3e authored by 沈翠玲's avatar 沈翠玲

客户管理

parent ee79a169
......@@ -22,4 +22,8 @@ export const getContractPage = (params) => {
// 保存合同
export const saveContract = (data) => {
return request.post('/Contract/saveContract', data);
};
// 合同批量审核
export const flowStatusByIds = (data) => {
return request.get('/Contract/flowStatusByIds', data);
};
\ No newline at end of file
......@@ -25,11 +25,41 @@
:rules="rules"
>
<el-row :gutter="20">
<template v-if="form.financeFlowStatus">
<el-col :span="12">
<el-form-item label="财务审核意见:" prop="name">
{{form.financeRepairOpinion}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="财务审核状态:" prop="name">
{{form.financeFlowStatus
? FlowStatus?.find((v) => v.value === form.financeFlowStatus)?.label
: ''}}
</el-form-item>
</el-col>
</template>
<template v-if="form.legalFlowStatus">
<el-col :span="12">
<el-form-item label="法务审核意见:" prop="name">
{{form.legalRepairOpinion}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="法务审核状态:" prop="name">
{{form.legalFlowStatus
? FlowStatus?.find((v) => v.value === form.legalFlowStatus)?.label
: ''}}
</el-form-item>
</el-col>
</template>
<el-col :span="12">
<el-form-item label="合同编号:" prop="name">
<el-input
v-model="form.contractNo"
:disabled="!showEdit"
:disabled="currentRow"
placeholder="请输入"
/>
</el-form-item>
......@@ -62,7 +92,7 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="身份证号:" prop="code">
<el-form-item class="w-full" label="身份证号:" prop="idCard">
<el-input
v-model="form.idCard"
:disabled="!showEdit"
......@@ -71,7 +101,7 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="缴费形式:" prop="name">
<el-form-item class="w-full" label="缴费形式:" prop="paymentForm">
<el-select v-model="form.paymentForm" placeholder="请选择" :disabled="!showEdit">
<el-option
v-for="item in PaymentForm"
......@@ -87,6 +117,7 @@
<el-form-item class="w-full" label="服务费总额:" prop="code">
<el-input
v-model="form.serviceFeeTotal"
type="number"
:disabled="!showEdit"
placeholder="请输入"
/>
......@@ -101,7 +132,7 @@
/>
</el-form-item>
</el-col>
<el-col :span="12">
<!-- <el-col :span="12">
<el-form-item class="w-full" label="合同状态:" prop="name">
<el-select v-model="form.contractStatus" placeholder="请选择" :disabled="!showEdit">
<el-option
......@@ -113,7 +144,7 @@
/>
</el-select>
</el-form-item>
</el-col>
</el-col> -->
<el-col :span="24">
<el-form-item class="w-full" label="合同附件" prop="code">
<el-upload
......@@ -139,13 +170,13 @@
alt=""
>
<span class="el-upload-list__item-actions">
<!-- <span
<span
class="el-upload-list__item-delete"
>
<el-icon @click="handleRemove1(file)">
<Delete />
</el-icon>
</span> -->
</span>
<span
class="el-upload-list__item-preview"
>
......@@ -184,19 +215,31 @@
const downloadfile = inject('download');
import { useUserStore } from '@/stores/modules/user';
const showModal = ref(false);
const { PaymentForm, ContractStatus } = useDict("PaymentForm", "ContractStatus");
const { PaymentForm, ContractStatus, FlowStatus } = useDict("PaymentForm", "ContractStatus", "FlowStatus");
const emits = defineEmits(['success']);
const currentRow = ref(null);
const formRef = ref()
const currentIndex = ref(null);
const props = defineProps({
mergerCase: String,
returnConfig: Array,
returnData: Array
});
const rules = ref({
idCard: [
{ required: true, message: '请填写证件号码', trigger: 'blur' },
{
pattern: /(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)/,
message: '证件号码格式有误!',
trigger: 'blur'
}
],
paymentForm: { required: true, message: '请填写证件号码', trigger: 'blur' }
});
const userStore = useUserStore();
const envs = getAppEnvConfig();
const url = envs.VITE_GLOB_API_URL_PREFIX + '/sys/upload';
const form = reactive({
const form = ref({
contractNo: '',
contractSignBody: '',
businessName: '',
......@@ -205,7 +248,15 @@
serviceFeeTotal: '',
serviceTerm: '',
contractScanFile: '',
contractStatus: '',
contractStatus: 'created',
"financeRepairUser": null,
"financeFlowStatus": null,
"financeRepairOpinion": null,
"financeRepairTime": null,
"legalRepairUser": null,
"legalFlowStatus": null,
"legalRepairOpinion": null,
"legalRepairTime": null,
contractScanFileList: []
});
const handlePictureCardPreview = (uploadFile) => {
......@@ -218,7 +269,7 @@
};
const handleFileSuccess1 = (response, file, fileList) => {
if (file.uid) {
const item = form.contractScanFileList.find((v) => v.uid === file.uid);
const item = form.value.contractScanFileList.find((v) => v.uid === file.uid);
item.url = envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + response.message;
}
};
......@@ -226,8 +277,8 @@
return new URL(`@/assets/images/file.svg`, import.meta.url).href;
}
const handleRemove1 = (uploadFile, uploadFiles) => {
const index = form.images.findIndex((v) => v.name === uploadFile.name);
form.images.splice(index, 1);
const index = form.value.contractScanFileList.findIndex((v) => v.name === uploadFile.name);
form.value.contractScanFileList.splice(index, 1);
};
const updataIf = (e) => {
if (e.fileName) {
......@@ -245,31 +296,35 @@
}
}
const submitForm = async () => {
// if(!form.bank && form.bank !== 0) {
// if(!form.value.bank && form.value.bank !== 0) {
// return ElMessage.warning({
// message: '请填写发卡银行',
// plain: true,
// });
// }
// if(!form.quota && form.quota !== 0) {
// if(!form.value.quota && form.value.quota !== 0) {
// return ElMessage.warning({
// message: '请填写授信额度',
// plain: true,
// });
// }
let images = JSON.parse(JSON.stringify(form.contractScanFileList.map((v) => v.url)));
await formRef.value.validate();
let images = JSON.parse(JSON.stringify(form.value.contractScanFileList.map((v) => v.url)));
images = images.map((v) => {
return v.replace(envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/', '');
});
const params = JSON.parse(JSON.stringify({
...form,
...form.value,
contractScanFile: images.join(','),
user:userStore.userInfo
contractFile: images.join(','),
user:{
username: userStore.userInfo?.username
}
}))
delete params.contractScanFileList
saveContract(params).then(res => {
if(res.success) {
return ElMessage.success({
ElMessage.success({
message: '保存成功',
plain: true,
});
......@@ -284,32 +339,45 @@
emits('success', form, currentIndex.value, 'del');
showModal.value = false;
}
const openModal = (row, index) => {
const openModal = (row, edit) => {
if (row) {
showEdit.value = false
form = JSON.parse(JSON.stringify(row))
const arr = form.contractScanFileList.split(',')
form.contractScanFileList = arr
form.value = JSON.parse(JSON.stringify(row))
const arr = form.value.contractScanFile.split(',')
form.value.contractScanFileList = arr
? arr.map((v) => ({
name: v.slice(v.lastIndexOf('/') + 1, v.length),
url: envs.VITE_GLOB_API_URL_PREFIX + '/sys/static/' + v,
}))
: [];
if (edit) {
showEdit.value = true
} else {
showEdit.value = false
}
} else {
showEdit.value = true
form.contractNo = ''
form.contractSignBody = ''
form.businessName = ''
form.customerName = ''
form.paymentForm = ''
form.serviceFeeTotal = ''
form.serviceTerm = ''
form.contractScanFile = ''
form.contractStatus = ''
form.contractScanFileList = []
form.value = {
contractNo: '',
contractSignBody: '',
businessName: '',
customerName: '',
paymentForm: '',
serviceFeeTotal: '',
serviceTerm: '',
contractScanFile: '',
contractStatus: 'created',
"financeRepairUser": null,
"financeFlowStatus": null,
"financeRepairOpinion": null,
"financeRepairTime": null,
"legalRepairUser": null,
"legalFlowStatus": null,
"legalRepairOpinion": null,
"legalRepairTime": null,
contractScanFileList: []
}
}
currentRow.value = row
currentIndex.value = index
showModal.value = true;
};
defineExpose({
......@@ -333,7 +401,7 @@
padding-left: 5px;
&.label {
text-align: center;
background: rgb(222, 233, 244);
background: #dfeaf5;
width: 175px;
color: #000;
}
......
<template>
<div class="table-box">
<div class=" bg-white pt-2 pl-2">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane
:label="item.label"
:name="item.value"
v-for="(item, index) in ContractStatus"
:key="index"
>
<template #label>
<div>
{{item.label}}
<!-- <span style="font-size: 20px; font-weight: bold;">{{item.msg}}</span> -->
</div>
</template>
</el-tab-pane>
</el-tabs>
</div>
<ProTable ref="proTable" :config="config" :api="getContractPage" :paramCallback="paramCallback" :selectdList="selectdList">
<template #left_buttons>
<el-button type="primary" @click="addConstant()">新建合同</el-button>
......@@ -9,25 +26,105 @@
ref="addModelRef"
@success="query"
></addModel>
<vxe-modal
resize
v-model="showModal"
:title="currentType === 'finance' ? '财务审批' : '法务审批'"
height="482"
width="550"
show-footer
esc-closable
>
<div class="w-full px-3 h-full overflow-auto flex-col flex mytable">
<el-form
ref="formRef"
:model="form"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="合同编号:" prop="name">
{{form.contractNo}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="合同签订主体:" prop="code">
{{form.contractSignBody}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="业务名称:" prop="code">
{{form.businessName}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="客户名称:" prop="code">
{{form.customerName}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="身份证号:" prop="idCard">
{{form.idCard}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="服务费总额:" prop="code">
{{form.serviceFeeTotal}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="服务期限:" prop="code">
{{form.serviceTerm}}
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="审核意见:" prop="name">
<el-input
v-model="form.financeRepairOpinion" v-if="currentType === 'finance'" type="textarea"
placeholder="请输入"
/>
<el-input
v-model="form.legalRepairOpinion" v-else type="textarea"
placeholder="请输入"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<el-button type="default" @click="showModal = false">取消</el-button>
<el-button type="danger" @click="submitForm('fail')">拒绝</el-button>
<el-button type="primary" @click="submitForm('pass')">审批通过</el-button>
</template>
</vxe-modal>
</div>
</template>
<script setup lang="jsx" name="platformManage">
import { ref, reactive, onMounted } from 'vue';
import { ref, reactive, onMounted, computed } from 'vue';
import { Plus, Delete, Edit, Setting } from '@element-plus/icons-vue';
import { getContractPage } from '@/api/customer';
import { getContractPage, flowStatusByIds } from '@/api/customer';
import { ElMessageBox, ElMessage, ElButton, ElTag } from 'element-plus';
import { useRouter } from 'vue-router';
import addModel from './components/addModel.vue';
import { useDict } from '@/hooks/useDict';
const { PaymentForm, ContractStatus } = useDict("PaymentForm", "ContractStatus");
import { useAuthStore } from '@/stores/modules/auth';
const activeName = ref('created');
const { authButtonListGet } = useAuthStore(); // 获取用户权限列表
const { PaymentForm, ContractStatus, FlowStatus } = useDict("PaymentForm", "ContractStatus", "FlowStatus");
const addModelRef = ref()
const proTable = ref(null);
const selectdList = ref([]);
const form = ref()
const showModal = ref(false)
const currentType = ref();
const onCheckboxChange = (row) => {
selectdList.value = row.records;
};
const router = useRouter();
const query = () => proTable.value?.search();
const paramCallback = (param) => {
const obj = JSON.parse(JSON.stringify(param));
......@@ -36,6 +133,7 @@
if (obj['createTime'][1]) obj['createTimeEnd'] = obj['createTime'][1];
delete obj['createTime'];
}
obj['contractStatus'] = activeName.value;
return obj;
};
const onCheckboxAll = (flag) => {
......@@ -45,27 +143,51 @@
selectdList.value = [];
}
};
const addConstant = (row) => {
addModelRef.value.openModal(row
const addConstant = (row, edit = false) => {
addModelRef.value.openModal(row, edit
);
};
const config = reactive({
const apply = (row, type) => {
currentType.value = type
form.value = row
showModal.value = true
}
const submitForm = (type) => {
const param = {
ids: form.value.id
}
if (currentType.value === 'finance') {
param['financeRepairOpinion'] = form.value.financeRepairOpinion
param['financeFlowStatus'] = type
} else {
param['legalRepairOpinion'] = form.value.legalRepairOpinion
param['legalFlowStatus'] = type
}
flowStatusByIds(param).then(res => {
if(res.success) {
ElMessage.success({
message: '审核成功',
plain: true,
});
showModal.value = false
query()
}
})
}
const handleClick = () => {
setTimeout(() => {
query();
}, 300);
};
const config = computed(() => {
return {
onCheckboxChange: onCheckboxChange,
onCheckboxAll: onCheckboxAll,
columns: [
// { type: 'checkbox', width: 60,fixed: 'left' },
{ field: 'id', title: '档案编号', slots: {
default: ({ row, rowIndex }) => {
return (
<>
{rowIndex + 1}
</>
);
},
}
{ field: 'id', title: '档案编号', type: 'seq',width: 80
},
{ field: 'id', title: '合同编号', search: { labelWidth: 85, el: 'input' }, slots: {
{ field: 'id', title: '合同编号', width: 140, search: { labelWidth: 85, el: 'input' }, slots: {
default: ({ row, rowIndex }) => {
return (
<>
......@@ -83,15 +205,17 @@
{
field: 'contractSignBody',
title: '合同签订主体',
width: 120,
search: { labelWidth: 85, el: 'input' }
},
{
field: 'businessName',
title: '业务名称',
width: 120,
search: { el: 'input',labelWidth: 85, props: { clearable: true } },
},
{ field: 'customerName', title: '客户名称', search: { labelWidth: 85, el: 'input' } },
{ field: 'idCard', title: '身份证号', search: { labelWidth: 85, el: 'input' } },
{ field: 'customerName', title: '客户名称',width: 100, search: { labelWidth: 85, el: 'input' } },
{ field: 'idCard', title: '身份证号',width: 150, search: { labelWidth: 85, el: 'input' } },
{
field: 'paymentForm',
title: '缴费形式',
......@@ -111,10 +235,10 @@
},
},
},
{ field: 'serviceFeeTotal', title: '服务费总额', search: { labelWidth: 85, el: 'input' } },
{ field: 'serviceTerm', title: '服务期限', search: { labelWidth: 85, el: 'input' } },
{ field: 'contractScanFile', title: '合同扫描件', search: { labelWidth: 85, el: 'input' } },
{ field: 'createTime', title: '创建日期', search: {
{ field: 'serviceFeeTotal', title: '服务费总额',width: 100, search: { labelWidth: 85, el: 'input' } },
{ field: 'serviceTerm', title: '服务期限', width: 100,search: { labelWidth: 85, el: 'input' } },
// { field: 'contractScanFile', title: '合同扫描件', search: { labelWidth: 85, el: 'input' } },
{ field: 'createTime', title: '创建日期', width: 140, search: {
el: 'date-picker',
labelWidth: 85,
props: { type: 'daterange', valueFormat: 'YYYY-MM-DD' },
......@@ -135,22 +259,58 @@
);
},
}, },
{ field: 'remark', title: '操作', fixed: 'right',
{ field: 'financeFlowStatus', title: '财务审核状态', showOverflow: 'tooltip',
width: 80,
enum: FlowStatus,
fieldNames: { label: 'label', value: 'value' },
slots: {
default: ({ row }) => {
return (
<>
{row.financeFlowStatus
? FlowStatus.value?.find((v) => v.value === row.financeFlowStatus)?.label
: ''}
</>
);
},
}, },
{ field: 'legalFlowStatus', title: '法务审核状态', showOverflow: 'tooltip',
width: 80,
enum: FlowStatus,
fieldNames: { label: 'label', value: 'value' },
slots: {
default: ({ row }) => {
return (
<>
{row.legalFlowStatus
? FlowStatus.value?.find((v) => v.value === row.legalFlowStatus)?.label
: ''}
</>
);
},
}, },
{ field: 'remark', title: '操作', fixed: 'right',width: 160,visible: activeName.value !== 'completed',
slots: {
default({ row }) {
return (
<>
<ElButton type="primary" link onClick={() => addConstant(row)}>
<ElButton type="primary" link onClick={() => addConstant(row, true)} disabled={row.legalFlowStatus=== 'pass' && row.financeFlowStatus === 'pass'}>
修改
</ElButton>
<ElButton type="primary" link onClick={() => apply(row, 'finance')} v-show={authButtonListGet.includes('finance_apply')} disabled={row.legalFlowStatus || row.financeFlowStatus === 'pass'}>
财务审批
</ElButton>
<ElButton type="primary" link onClick={() => apply(row, 'legal')} v-show={authButtonListGet.includes('legal_apply')} disabled={row.financeFlowStatus !== 'pass' || row.legalFlowStatus === 'pass'}>
法务审批
</ElButton>
</>
);
},
}, },
],
};
});
const query = () => proTable.value?.search();
onMounted(() => {
query();
......
......@@ -296,7 +296,7 @@ td {
padding-left: 5px;
&.label {
text-align: center;
background: rgb(222, 233, 244);
background: #dfeaf5;
font-weight: bold;
color: #000;
width: 175px;
......
......@@ -322,7 +322,7 @@ td {
padding-left: 5px;
&.label {
text-align: center;
background: rgb(222, 233, 244);
background: #dfeaf5;
width: 175px;
color: #000;
}
......
......@@ -218,7 +218,7 @@
</div>
</div>
<div>
<el-button type="primary" @click="pushCreditcard()">新建信用卡</el-button>
<el-button type="primary" @click="pushCreditcard({})">新建信用卡</el-button>
</div>
</div>
<vxe-grid v-bind="cardConfig" />
......@@ -247,7 +247,7 @@
</div>
</div>
<div>
<el-button type="primary" @click="pushCredit()">新建网贷&信用贷</el-button>
<el-button type="primary" @click="pushCredit({})">新建网贷&信用贷</el-button>
</div>
</div>
</template>
......@@ -411,12 +411,12 @@ const CreditcardRef = ref();
const creditArr = ref([]);
const cardSUM = computed(() => cardConfig.data.reduce((pre, cur) => pre + Number(cur.debt),0));
const creditSUM = computed(() => creditArr.value.reduce((pre, cur) => pre + Number(cur.debt),0));
const pushCreditcard = (row, index) => {
CreditcardRef.value.openModal(row, index
const pushCreditcard = ({row, rowIndex}) => {
CreditcardRef.value.openModal(row, rowIndex
);
};
const pushCredit = (row, index) => {
CreditRef.value.openModal(row, index
const pushCredit = ({row, rowIndex}) => {
CreditRef.value.openModal(row, rowIndex
);
};
const handleQuery = () => {
......@@ -504,6 +504,7 @@ onBeforeMount(async () => {
})
const cardConfig = reactive({
align: 'center',
onCellClick: pushCreditcard,
minHeight: 250,
rowConfig: {
height: 40,
......@@ -516,12 +517,7 @@ const cardConfig = reactive({
default: ({ row, rowIndex }) => {
return (
<>
<div
onClick={() => pushCreditcard(row, rowIndex)}
className=" text-blue-400 cursor-pointer inline-block"
>
{rowIndex + 1}
</div>
{rowIndex + 1}
</>
);
},
......@@ -614,18 +610,14 @@ const cardConfig = reactive({
toolbarConfig: { enabled: false },
});
const creditConfig = reactive({
onCellClick: pushCredit,
minHeight: 200,
columns: [
{ type: 'seq', width: 60, title: '序号', slots: {
default: ({ row, rowIndex }) => {
return (
<>
<div
onClick={() => pushCredit(row, rowIndex)}
className=" text-blue-400 cursor-pointer inline-block"
>
{rowIndex + 1}
</div>
{rowIndex + 1}
</>
);
},
......@@ -717,7 +709,7 @@ td {
padding-left: 5px;
&.label {
text-align: center;
background: rgb(222, 233, 244);
background: #dfeaf5;
color: #000;
}
}
......@@ -737,7 +729,7 @@ td {
@media print {
.label {
text-align: center;
background: rgb(222, 233, 244);
background: #dfeaf5;
color: #000;
}
}
......
......@@ -115,7 +115,7 @@ td {
text-align: center;
&.label {
-webkit-print-color-adjust: exact;
background-color: rgb(222, 233, 244);
background-color: #dfeaf5;
font-weight: 400 !important;
}
}
......
......@@ -122,7 +122,7 @@ td {
text-align: center;
&.label {
-webkit-print-color-adjust: exact;
background-color: rgb(222, 233, 244);
background-color: #dfeaf5;
font-weight: 400 !important;
}
}
......
......@@ -121,7 +121,7 @@ td {
text-align: center;
&.label {
-webkit-print-color-adjust: exact;
background-color: rgb(222, 233, 244);
background-color: #dfeaf5;
font-weight: 400 !important;
}
}
......
......@@ -118,7 +118,7 @@ td {
color: #000;
&.label {
-webkit-print-color-adjust: exact;
background-color: rgb(222, 233, 244);
background-color: #dfeaf5;
font-weight: 400 !important;
}
}
......
......@@ -59,26 +59,16 @@
query: { id: 44 }, //这里不能直接写成 query: JSON.stringify(item)
});
};
const onCellClick = ({ row, rowIndex }) => {
pushCustomer(row)
}
const config = reactive({
onCheckboxChange: onCheckboxChange,
onCheckboxAll: onCheckboxAll,
onCellClick: onCellClick,
columns: [
{ type: 'checkbox', width: 60,fixed: 'left' },
{ field: 'id', title: '客户ID', slots: {
default: ({ row, rowIndex }) => {
return (
<>
<div
onClick={() => pushCustomer(row)}
className=" text-blue-400 cursor-pointer inline-block"
>
{row.id}
</div>
</>
);
},
}
},
{ field: 'name', title: '客户名称', search: { labelWidth: 85, el: 'input' } },
{
field: 'createTime',
title: '创建日期',
......@@ -93,7 +83,6 @@
title: '创建人',
search: { el: 'input',labelWidth: 85, props: { clearable: true } },
},
{ field: 'name', title: '客户名称', search: { labelWidth: 85, el: 'input' } },
{ field: 'idCard', title: '身份证号', search: { labelWidth: 85, el: 'input' } },
{ field: 'phone', title: '手机', search: { labelWidth: 85, el: 'input' } },
{ field: 'email', title: '电子邮箱', search: { labelWidth: 85, el: 'input' } },
......
......@@ -464,7 +464,7 @@ td {
padding-left: 5px;
&.label {
text-align: center;
background: rgb(222, 233, 244);
background: #dfeaf5;
color: #000;
}
&.header {
......
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