@ -0,0 +1,36 @@ |
|||||||
|
import axios from '@/utils/request'; |
||||||
|
|
||||||
|
export const accessStrategyGovernmentBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyGovernmentBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
export const accessStrategyGovernmentBlacklistSave = async (data: Record<string, any>[]): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyGovernmentBlacklist/saveOrUpdate`, data)).data; |
||||||
|
|
||||||
|
export const accessStrategyEnterpriseBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyEnterpriseBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
export const accessStrategyEnterpriseBlacklistSave = async (data: Record<string, any>[]): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyEnterpriseBlacklist/saveOrUpdate`, data)).data; |
||||||
|
|
||||||
|
export const accessStrategyAntiFraudStrategyFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyAntiFraudStrategy/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
export const accessStrategyAntiFraudStrategySave = async (data: Record<string, any>[]): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyAntiFraudStrategy/saveOrUpdate`, data)).data; |
||||||
|
|
||||||
|
export const accessStrategyBusinessBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyBusinessBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
export const accessStrategyBusinessBlacklistSave = async (data: Record<string, any>[]): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyBusinessBlacklist/saveOrUpdate`, data)).data; |
||||||
|
|
||||||
|
export const accessStrategyCreditBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyCreditBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
export const accessStrategyCreditBlacklistSave = async (data: Record<string, any>[]): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyCreditBlacklist/saveOrUpdate`, data)).data; |
||||||
|
|
||||||
|
export const accessStrategyInlineBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyInlineBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
export const accessStrategyInlineBlacklistSave = async (data: Record<string, any>[]): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyInlineBlacklist/saveOrUpdate`, data)).data; |
||||||
|
|
||||||
|
export const accessStrategyNegativeIndustryStrategyFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyNegativeIndustryStrategy/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
export const accessStrategyNegativeIndustryStrategySave = async (data: Record<string, any>[]): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyNegativeIndustryStrategy/saveOrUpdate`, data)).data; |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 1016 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 922 B |
After Width: | Height: | Size: 960 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 392 B |
After Width: | Height: | Size: 437 B |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1013 B |
@ -0,0 +1,257 @@ |
|||||||
|
<template> |
||||||
|
<el-table class="c-table" |
||||||
|
:data="form" |
||||||
|
:max-height="height" |
||||||
|
border> |
||||||
|
<el-table-column prop="name" |
||||||
|
label="进入黑名单指标" |
||||||
|
min-width="150" |
||||||
|
align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="本人进黑名单规则" |
||||||
|
min-width="250" |
||||||
|
align="center"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<!-- 大病报销 || 贫困户 --> |
||||||
|
<div v-if="row.stRecordId == 161 || row.stRecordId == 164" |
||||||
|
class="flex items-center"> |
||||||
|
<span class="whitespace-nowrap">{{ row?.recordChildren[row.span ? 1 : 0]?.name }}</span> |
||||||
|
<div class="w-[90px] "> |
||||||
|
<el-select class="mx-2" |
||||||
|
v-model="row.symbol"> |
||||||
|
<el-option v-for="item in symbols" |
||||||
|
:key="item" |
||||||
|
:label="item.name" |
||||||
|
:value="item.name" /> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
<el-input class="w-[80px]" |
||||||
|
v-model="row.num"></el-input> |
||||||
|
<span class="ml-2 whitespace-nowrap">万元</span> |
||||||
|
</div> |
||||||
|
<!-- 大龄未婚 --> |
||||||
|
<div v-else-if="row.stRecordId == 167" |
||||||
|
class="flex items-center"> |
||||||
|
<template v-if="row.span"> |
||||||
|
<span class="whitespace-nowrap">且近一年</span> |
||||||
|
<div class="w-[90px] "> |
||||||
|
<el-select class="mx-2" |
||||||
|
v-model="row.had"> |
||||||
|
<el-option value="有" /> |
||||||
|
<el-option value="无" /> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
<span class="ml-2 whitespace-nowrap">缴纳过社保或公积金</span> |
||||||
|
</template> |
||||||
|
<template v-else> |
||||||
|
<span class="whitespace-nowrap">未婚,且年龄</span> |
||||||
|
<div class="w-[90px] "> |
||||||
|
<el-select class="mx-2" |
||||||
|
v-model="row.symbol"> |
||||||
|
<el-option v-for="item in symbols" |
||||||
|
:key="item" |
||||||
|
:label="item.name" |
||||||
|
:value="item.name" /> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
<el-input class="w-[80px]" |
||||||
|
v-model="row.num"></el-input> |
||||||
|
<span class="ml-2 whitespace-nowrap">,</span> |
||||||
|
<el-select class="w-[80px] ml-2" |
||||||
|
v-model="row.had"> |
||||||
|
<el-option value="有" /> |
||||||
|
<el-option value="无" /> |
||||||
|
</el-select> |
||||||
|
<span class="ml-2 whitespace-nowrap">固定资产</span> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
<span v-else>{{ '命中' + row.name }}</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="配偶拒入标准同本人" |
||||||
|
width="160" |
||||||
|
align="center"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-checkbox v-model="row.personalHitBlacklist"></el-checkbox> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
|
||||||
|
<div class="flex justify-end"> |
||||||
|
<div class="submit" |
||||||
|
@click="submit">确认完成配置</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { ref, computed, watch, onMounted } from 'vue'; |
||||||
|
import { ElMessage } from 'element-plus'; |
||||||
|
import { accessStrategyGovernmentBlacklistFind, accessStrategyGovernmentBlacklistSave } from '@/api/model'; |
||||||
|
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment'; |
||||||
|
import type { TableColumnCtx } from 'element-plus'; |
||||||
|
import { useRouter, useRoute } from 'vue-router'; |
||||||
|
import { handleId } from '@/utils/common'; |
||||||
|
import Cookies from 'js-cookie'; |
||||||
|
|
||||||
|
const emit = defineEmits(['getList']); |
||||||
|
|
||||||
|
const router = useRouter(); |
||||||
|
const route = useRoute(); |
||||||
|
const id = computed(() => +route.query.id); |
||||||
|
const form = ref<Record<string, any>[]>([]); |
||||||
|
const height = window.innerHeight - 270; |
||||||
|
const symbols = <Record<string, any>[]>[ |
||||||
|
{ |
||||||
|
name: '>=', |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '<', |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '>', |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '==', |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '<=', |
||||||
|
}, |
||||||
|
]; |
||||||
|
// 配置项 |
||||||
|
const getConfig = async () => { |
||||||
|
const { process } = await getProcessInformationBasedOnRoles(150); |
||||||
|
const result = []; |
||||||
|
process.map((e) => { |
||||||
|
let temp = { |
||||||
|
checkpointId: 1, |
||||||
|
projectId: 1, |
||||||
|
name: e.name, |
||||||
|
recordChildren: e.recordChildren, |
||||||
|
isRule: isRule(e.id) ? 1 : 0, |
||||||
|
corporateMajorityHitRejected: false, |
||||||
|
mateHitRejected: false, |
||||||
|
otherFamilyMembersHitRejected: false, |
||||||
|
parentsHitRejected: false, |
||||||
|
personalHitBlacklist: false, |
||||||
|
symbol: '>=', |
||||||
|
had: '', |
||||||
|
num: '', |
||||||
|
ruleOne: '', |
||||||
|
ruleTwo: '', |
||||||
|
stRecordId: e.id, |
||||||
|
}; |
||||||
|
result.push(temp); |
||||||
|
if (isRule(e.id)) { |
||||||
|
temp = JSON.parse(JSON.stringify(temp)); |
||||||
|
temp.span = 1; |
||||||
|
result.push(temp); |
||||||
|
} |
||||||
|
}); |
||||||
|
form.value = result; |
||||||
|
}; |
||||||
|
// 详情 |
||||||
|
const getDetail = async () => { |
||||||
|
if (id.value) { |
||||||
|
try { |
||||||
|
const { data } = await accessStrategyGovernmentBlacklistFind(1, 1); |
||||||
|
// info.value = data; |
||||||
|
getConfig(); |
||||||
|
} finally { |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
watch( |
||||||
|
() => route.query, |
||||||
|
() => { |
||||||
|
// getDetail(); |
||||||
|
getConfig(); |
||||||
|
}, |
||||||
|
{ |
||||||
|
immediate: true, |
||||||
|
}, |
||||||
|
); |
||||||
|
|
||||||
|
// 判断是否是3个有输入框的指标 |
||||||
|
const isRule = (rule: number): boolean => { |
||||||
|
return rule === 161 || rule === 164 || rule === 167; |
||||||
|
}; |
||||||
|
interface SpanMethodProps { |
||||||
|
row: Record<string, any>; |
||||||
|
column: TableColumnCtx<Record<string, any>>; |
||||||
|
rowIndex: number; |
||||||
|
columnIndex: number; |
||||||
|
} |
||||||
|
onMounted(() => {}); |
||||||
|
// 提交 |
||||||
|
const submit = async () => { |
||||||
|
let param = JSON.parse(JSON.stringify(form.value)); |
||||||
|
param.map((e, i) => { |
||||||
|
e.corporateMajorityHitRejected = +e.corporateMajorityHitRejected; |
||||||
|
e.mateHitRejected = +e.mateHitRejected; |
||||||
|
e.otherFamilyMembersHitRejected = +e.otherFamilyMembersHitRejected; |
||||||
|
e.parentsHitRejected = +e.parentsHitRejected; |
||||||
|
e.personalHitBlacklist = +e.personalHitBlacklist; |
||||||
|
if (e.stRecordId == 161 || e.stRecordId == 164) { |
||||||
|
if (e.span) { |
||||||
|
// 这里是合并表格,详情那里多加了一行,这里数据要放到一行去 |
||||||
|
param[i - 1].ruleTwo = e.symbol + e.num; |
||||||
|
} else { |
||||||
|
e.ruleOne = e.symbol + e.num; |
||||||
|
} |
||||||
|
} else if (e.stRecordId == 167) { |
||||||
|
if (e.span) { |
||||||
|
// 这里是合并表格,详情那里多加了一行,这里数据要放到一行去 |
||||||
|
param[i - 1].ruleTwo = e.had; |
||||||
|
} else { |
||||||
|
e.ruleOne = e.symbol + e.num + ',' + e.had; |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
param = param.filter((e) => !e.span); |
||||||
|
const recordParam = JSON.parse(JSON.stringify(param)); |
||||||
|
param.map((e) => { |
||||||
|
delete e.recordChildren; |
||||||
|
}); |
||||||
|
const { message } = await accessStrategyGovernmentBlacklistSave(recordParam); |
||||||
|
// addRecord(param, message); |
||||||
|
|
||||||
|
ElMessage.success('提交成功!'); |
||||||
|
emit('getList', 1); |
||||||
|
}; |
||||||
|
// 新增判分记录 |
||||||
|
const addRecord = async (data: Record<string, any>, newId: number) => { |
||||||
|
const preIds = `1,${Cookies.get('sand-level')},42,${newId}`; // 1,关卡id,角色(这个页面是风控经理策略) |
||||||
|
const rule = <Record<string, any>[]>[]; |
||||||
|
|
||||||
|
data.map((e, i) => { |
||||||
|
if (e.stRecordId == 161 || e.stRecordId == 164) { |
||||||
|
e.recordChildren.map((n, j) => { |
||||||
|
rule.push(handleId(n.id, e.subjectId, j ? e.ruleTwo : e.ruleOne, preIds + ',' + e.id + ',' + n.id, 5)); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
const temp = []; |
||||||
|
e.personalHitBlacklist && temp.push(300); |
||||||
|
e.mateHitRejected && temp.push(301); |
||||||
|
e.parentsHitRejected && temp.push(302); |
||||||
|
e.otherFamilyMembersHitRejected && temp.push(303); |
||||||
|
e.corporateMajorityHitRejected && temp.push(304); |
||||||
|
rule.push(handleId(e.id, e.subjectId, temp.join(), preIds + ',' + e.id, 1)); |
||||||
|
}); |
||||||
|
|
||||||
|
await addOperation({ |
||||||
|
parentId: preIds, |
||||||
|
lcJudgmentRuleReq: rule, |
||||||
|
projectId: 1, |
||||||
|
}); |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import url(../../../styles/form.scss); |
||||||
|
.c-table { |
||||||
|
:deep(.el-input__inner) { |
||||||
|
@apply px-2; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -1,532 +0,0 @@ |
|||||||
<template> |
|
||||||
<div> |
|
||||||
<el-tabs v-model="curTab" |
|
||||||
@tab-click="tabChange"> |
|
||||||
<el-tab-pane :label="id ? '产品要素' : '新增产品'" |
|
||||||
name="tab1"> |
|
||||||
<div v-if="info" |
|
||||||
class="audit"> |
|
||||||
<div class="line"> |
|
||||||
<span class="field">审批意见:</span> |
|
||||||
<span class="status">{{ getStatus(+info?.status) }}</span> |
|
||||||
</div> |
|
||||||
<div class="line"> |
|
||||||
<span class="field">意见描述:</span> |
|
||||||
{{ info.opinionDescription }} |
|
||||||
</div> |
|
||||||
<p class="mb-2 text-sm text-[#333] text-right">审查日期:{{ info.approvalTime }}</p> |
|
||||||
<p class="mb-2 text-sm text-[#333] text-right">审查员:公瑾</p> |
|
||||||
</div> |
|
||||||
|
|
||||||
<el-form ref="formRef" |
|
||||||
:model="form" |
|
||||||
:rules="rules" |
|
||||||
label-width="100px" |
|
||||||
label-suffix=":" |
|
||||||
class="form" |
|
||||||
status-icon> |
|
||||||
<el-form-item label="产品定义" |
|
||||||
prop="productDefinition"> |
|
||||||
<el-input type="textarea" |
|
||||||
placeholder="用一段话简单介绍一下这个产品或者描述产品的设计理念。例如:本产品根据个人客户的信用状况,为其提供的一种短期融资便利产品,借款人可在额度金额内可循环周转使用贷款。" |
|
||||||
maxlength="200" |
|
||||||
v-model="form.productDefinition"></el-input> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="产品名称" |
|
||||||
prop="productName"> |
|
||||||
<el-input placeholder="取个有吸引力的产品名,限20字。" |
|
||||||
maxlength="20" |
|
||||||
v-model="form.productName"></el-input> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="产品币种" |
|
||||||
prop="productCurrency"> |
|
||||||
<el-select v-model="form.productCurrency" |
|
||||||
placeholder="请选择"> |
|
||||||
<el-option label="人民币" |
|
||||||
:value="1" /> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="贷款对象" |
|
||||||
required> |
|
||||||
<div class="flex-1"> |
|
||||||
<!-- 企业 --> |
|
||||||
<template v-if="form.productType"> |
|
||||||
<div class="flex items-center"> |
|
||||||
<span class="mr-3 text-[#333] text-sm">企业类型</span> |
|
||||||
<el-select v-model="form.productObject" |
|
||||||
placeholder="请选择"> |
|
||||||
<el-option v-for="(item, i) in config.find((e: any) => e.name === '企业产品-贷款对象')?.recordChildren[0]?.subject?.itemList" |
|
||||||
:key="i" |
|
||||||
:label="item.options" |
|
||||||
:value="item.itemId" /> |
|
||||||
</el-select> |
|
||||||
</div> |
|
||||||
<div class="flex items-center mt-4"> |
|
||||||
<span class="mr-3 text-[#333] text-sm">借款人年龄</span> |
|
||||||
<div class="num-inputs ml-7"> |
|
||||||
<el-input placeholder="最小年龄" |
|
||||||
v-model.number="form.minimumAge"></el-input> |
|
||||||
<span class="split">-</span> |
|
||||||
<el-input placeholder="最大年龄" |
|
||||||
v-model.number="form.maximumAge"></el-input> |
|
||||||
<span class="unit">周岁</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
<!-- 个人 --> |
|
||||||
<template v-else> |
|
||||||
<p class="field-name">选择本产品的贷款对象。</p> |
|
||||||
<div class="flex items-center mb-2"> |
|
||||||
<el-checkbox class="mt-1" |
|
||||||
v-model="form.age" |
|
||||||
label="年龄" /> |
|
||||||
<div v-if="form.age" |
|
||||||
class="num-inputs ml-7"> |
|
||||||
<el-input placeholder="最小年龄" |
|
||||||
v-model.number="form.minimumAge"></el-input> |
|
||||||
<span class="split">-</span> |
|
||||||
<el-input placeholder="最大年龄" |
|
||||||
v-model.number="form.maximumAge"></el-input> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div class="flex items-center mb-2"> |
|
||||||
<el-checkbox v-model="form.edu" |
|
||||||
label="学历要求"></el-checkbox> |
|
||||||
<el-checkbox-group v-if="form.edu" |
|
||||||
class="mt-2 ml-5" |
|
||||||
v-model="form.educationalRequirements"> |
|
||||||
<el-checkbox v-for="(item, i) in config.find((e: any) => e.name === '个人产品-贷款对象')?.recordChildren[1]?.subject?.itemList" |
|
||||||
:key="i" |
|
||||||
:label="item.itemId">{{ item.options }}</el-checkbox> |
|
||||||
</el-checkbox-group> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="flex items-center mb-2"> |
|
||||||
<el-checkbox v-model="form.curWL" |
|
||||||
label="工作年限"></el-checkbox> |
|
||||||
<el-checkbox-group v-if="form.curWL" |
|
||||||
class="mt-2 ml-5" |
|
||||||
v-model="form.currentWorkingLife"> |
|
||||||
<el-checkbox v-for="(item, i) in config.find((e: any) => e.name === '个人产品-贷款对象')?.recordChildren[2]?.subject?.itemList" |
|
||||||
:key="i" |
|
||||||
:label="item.itemId">{{ item.options }}</el-checkbox> |
|
||||||
</el-checkbox-group> |
|
||||||
</div> |
|
||||||
<el-checkbox v-model="form.providentFundAndSocialSecurity" |
|
||||||
label="公积金/社保"></el-checkbox> |
|
||||||
</template> |
|
||||||
</div> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="贷款用途" |
|
||||||
prop="loanPurpose" |
|
||||||
:rules="[ |
|
||||||
{ required: true, message: '请选择贷款用途', trigger: 'change' }, |
|
||||||
{ |
|
||||||
asyncValidator: async (rule, value, callback) => { |
|
||||||
if (value === 107 && !form.otherPurposesOfLoan) { |
|
||||||
callback('请输入其他贷款用途') |
|
||||||
} else { |
|
||||||
callback() |
|
||||||
} |
|
||||||
}, |
|
||||||
}, |
|
||||||
]"> |
|
||||||
<div class="flex-1"> |
|
||||||
<p class="field-name">选择本产品贷款资金的用途。</p> |
|
||||||
<el-radio-group v-model="form.loanPurpose"> |
|
||||||
<template v-if="form.productType"> |
|
||||||
<el-radio v-for="(item, i) in config.find((e: any) => e.name === '企业产品-贷款用途')?.subject?.itemList" |
|
||||||
:key="i" |
|
||||||
:label="item.itemId">{{ item.options }}</el-radio> |
|
||||||
</template> |
|
||||||
<template v-else> |
|
||||||
<el-radio v-for="(item, i) in config.find((e: any) => e.name === '个人产品-贷款用途')?.recordChildren" |
|
||||||
:key="i" |
|
||||||
:label="item.id">{{ item.name }}</el-radio> |
|
||||||
</template> |
|
||||||
</el-radio-group> |
|
||||||
<el-input v-if="form?.loanPurpose === 107" |
|
||||||
class="w-[300px] ml-5" |
|
||||||
placeholder="请描述其他贷款用途可用于哪些方面。" |
|
||||||
maxlength="10" |
|
||||||
v-model="form.otherPurposesOfLoan"></el-input> |
|
||||||
</div> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="担保方式" |
|
||||||
prop="bankGuaranteeTypeIds" |
|
||||||
:rules="[ |
|
||||||
{ required: true, message: '请选择担保方式', trigger: 'change' }, |
|
||||||
{ |
|
||||||
asyncValidator: async (rule, value, callback) => { |
|
||||||
if (value.includes(110) && !value.find((e: any) => e > 22 && e < 33)) { |
|
||||||
callback('请选择抵押物') |
|
||||||
} else if (value.includes(111) && !value.find((e: any) => e > 32 && e < 38)) { |
|
||||||
callback('请选择质押贷') |
|
||||||
} else { |
|
||||||
callback() |
|
||||||
} |
|
||||||
}, |
|
||||||
}, |
|
||||||
]"> |
|
||||||
<div class="flex-1"> |
|
||||||
<p class="field-name">选择本产品的担保种类。</p> |
|
||||||
<div v-for="(item, i) in config.find((e: any) => e.name === '担保方式')?.recordChildren" |
|
||||||
:key="i" |
|
||||||
class="mb-2"> |
|
||||||
<el-checkbox-group v-model="form.bankGuaranteeTypeIds"> |
|
||||||
<el-checkbox :label="item.id">{{ item.name }}</el-checkbox> |
|
||||||
<el-checkbox v-show="(item.id === 110 && form.bankGuaranteeTypeIds.includes(110)) || (item.id === 111 && form.bankGuaranteeTypeIds.includes(111))" |
|
||||||
v-for="(child, j) in item?.subject?.itemList" |
|
||||||
:key="j" |
|
||||||
:label="child.itemId">{{ child.options }}</el-checkbox> |
|
||||||
</el-checkbox-group> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="贷款额度" |
|
||||||
prop="minimumLoan" |
|
||||||
:rules="[ |
|
||||||
{ required: true, message: '请输入贷款额度', trigger: 'blur' }, |
|
||||||
{ |
|
||||||
asyncValidator: async (rule, value, callback) => { |
|
||||||
const max = form.loanCeiling |
|
||||||
if (isNaN(value) || value < 0 || max === '' || isNaN(max) || max < 0 || value > max) { |
|
||||||
callback('请输入合理的贷款额度') |
|
||||||
} else { |
|
||||||
callback() |
|
||||||
} |
|
||||||
}, |
|
||||||
}, |
|
||||||
]"> |
|
||||||
<div class="flex-1"> |
|
||||||
<div class="num-inputs"> |
|
||||||
<el-input placeholder="最小额度" |
|
||||||
min="0" |
|
||||||
v-model.number="form.minimumLoan"></el-input> |
|
||||||
<span class="split">-</span> |
|
||||||
<el-input placeholder="最高额度" |
|
||||||
min="0" |
|
||||||
v-model.number="form.loanCeiling"></el-input> |
|
||||||
<span class="unit">万元</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="贷款利率" |
|
||||||
prop="minimumAprOnLoan" |
|
||||||
:rules="[ |
|
||||||
{ required: true, message: '请输入贷款利率', trigger: 'blur' }, |
|
||||||
{ |
|
||||||
asyncValidator: async (rule, value, callback) => { |
|
||||||
const max = form.maximumAnnualInterestRate |
|
||||||
if (isNaN(value) || value < 0 || max === '' || isNaN(max) || max < 0 || value > max) { |
|
||||||
callback('请输入合理的贷款利率') |
|
||||||
} else { |
|
||||||
callback() |
|
||||||
} |
|
||||||
}, |
|
||||||
}, |
|
||||||
]"> |
|
||||||
<div class="flex-1"> |
|
||||||
<div class="num-inputs"> |
|
||||||
<el-input placeholder="最小年利率" |
|
||||||
min="0" |
|
||||||
v-model.number="form.minimumAprOnLoan"></el-input> |
|
||||||
<span class="split">-</span> |
|
||||||
<el-input placeholder="最高年利率" |
|
||||||
min="0" |
|
||||||
v-model.number="form.maximumAnnualInterestRate"></el-input> |
|
||||||
<span class="unit">%</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="贷款期限" |
|
||||||
prop="minimumTermOfLoan" |
|
||||||
:rules="[ |
|
||||||
{ required: true, message: '请输入贷款期限', trigger: 'blur' }, |
|
||||||
{ |
|
||||||
asyncValidator: async (rule, value, callback) => { |
|
||||||
const max = form.maximumTermOfLoan |
|
||||||
if (isNaN(value) || value < 0 || max === '' || isNaN(max) || max < 0 || value > max) { |
|
||||||
callback('请输入合理的贷款期限') |
|
||||||
} else { |
|
||||||
callback() |
|
||||||
} |
|
||||||
}, |
|
||||||
}, |
|
||||||
]"> |
|
||||||
<div class="flex-1"> |
|
||||||
<div class="num-inputs"> |
|
||||||
<el-input placeholder="最小期限" |
|
||||||
min="0" |
|
||||||
v-model.number="form.minimumTermOfLoan"></el-input> |
|
||||||
<span class="split">-</span> |
|
||||||
<el-input placeholder="最大期限" |
|
||||||
min="0" |
|
||||||
v-model.number="form.maximumTermOfLoan"></el-input> |
|
||||||
<span class="unit">月</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="还款方式" |
|
||||||
prop="modeRepayment"> |
|
||||||
<div class="flex-1"> |
|
||||||
<p class="field-name">选择本产品可以选择的还款方式。</p> |
|
||||||
<el-checkbox-group v-model="form.modeRepayment"> |
|
||||||
<el-checkbox v-for="(item, i) in config.find((e: any) => e.name === '还款方式')?.subject?.itemList" |
|
||||||
:key="i" |
|
||||||
:label="item.itemId">{{ item.options }}</el-checkbox> |
|
||||||
</el-checkbox-group> |
|
||||||
</div> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="提前还款" |
|
||||||
prop="whetherToSupportEarlyRepayment"> |
|
||||||
<div class="flex-1 flex items-center"> |
|
||||||
<el-switch v-model="form.whetherToSupportEarlyRepayment" /> |
|
||||||
<p class="tips ml-4">本产品是否支持提前还款。</p> |
|
||||||
</div> |
|
||||||
</el-form-item> |
|
||||||
<div class="flex justify-end"> |
|
||||||
<div class="submit" |
|
||||||
@click="submit(formRef)">完成,提交风控经理</div> |
|
||||||
</div> |
|
||||||
</el-form> |
|
||||||
</el-tab-pane> |
|
||||||
<el-tab-pane v-if="id" |
|
||||||
label="产品风控" |
|
||||||
name="tab2"> |
|
||||||
<info /> |
|
||||||
</el-tab-pane> |
|
||||||
</el-tabs> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script setup lang="ts"> |
|
||||||
import { ref, reactive, computed, watch, onMounted, defineEmits } from 'vue'; |
|
||||||
import { ElMessage } from 'element-plus'; |
|
||||||
import type { TabsPaneContext, FormInstance, FormRules } from 'element-plus'; |
|
||||||
import { findById, save, update } from '@/api/bank'; |
|
||||||
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment'; |
|
||||||
import { useRouter, useRoute } from 'vue-router'; |
|
||||||
import { handleId } from '@/utils/common'; |
|
||||||
import { getStatus } from '@/store/useProduct'; |
|
||||||
import Info from './Info.vue'; |
|
||||||
|
|
||||||
const emit = defineEmits(['getList']); |
|
||||||
interface RuleForm { |
|
||||||
productDefinition: string; |
|
||||||
productName: string; |
|
||||||
productCurrency: number; |
|
||||||
bankGuaranteeTypeIds: any[]; |
|
||||||
currentWorkingLife?: any; |
|
||||||
educationalRequirements?: any; |
|
||||||
loanCeiling: any; |
|
||||||
loanPurpose: any; |
|
||||||
productObject: any; |
|
||||||
maximumAge: any; |
|
||||||
maximumAnnualInterestRate: any; |
|
||||||
maximumTermOfLoan: any; |
|
||||||
age: boolean; |
|
||||||
minimumAge: any; |
|
||||||
minimumAprOnLoan: any; |
|
||||||
minimumLoan: any; |
|
||||||
minimumTermOfLoan: any; |
|
||||||
modeRepayment?: any; |
|
||||||
otherPurposesOfLoan: string; |
|
||||||
productObject: any; |
|
||||||
productType: number; |
|
||||||
providentFundAndSocialSecurity: any; |
|
||||||
whetherToSupportEarlyRepayment?: any; |
|
||||||
} |
|
||||||
|
|
||||||
const router = useRouter(); |
|
||||||
const route = useRoute(); |
|
||||||
const id = computed(() => route.query.id); |
|
||||||
const curTab = ref<string>('tab1'); |
|
||||||
const config = ref<any[]>([]); |
|
||||||
const info = ref<Record<string, any>>(null); |
|
||||||
const formRef = ref<FormInstance>(); |
|
||||||
const form = reactive<RuleForm>({ |
|
||||||
productDefinition: '', |
|
||||||
productName: '', |
|
||||||
productCurrency: 1, |
|
||||||
bankGuaranteeTypeIds: [], |
|
||||||
currentWorkingLife: [], |
|
||||||
educationalRequirements: [], |
|
||||||
loanCeiling: '', |
|
||||||
loanPurpose: '', |
|
||||||
productObject: '', |
|
||||||
maximumAge: '', |
|
||||||
maximumAnnualInterestRate: '', |
|
||||||
maximumTermOfLoan: '', |
|
||||||
age: false, |
|
||||||
minimumAge: '', |
|
||||||
minimumAprOnLoan: '', |
|
||||||
minimumLoan: '', |
|
||||||
minimumTermOfLoan: '', |
|
||||||
modeRepayment: [], |
|
||||||
otherPurposesOfLoan: '', |
|
||||||
productObject: '', |
|
||||||
productType: computed(() => +route.query.type), |
|
||||||
providentFundAndSocialSecurity: false, |
|
||||||
whetherToSupportEarlyRepayment: false, |
|
||||||
}); |
|
||||||
const rules = reactive<FormRules<RuleForm>>({ |
|
||||||
productDefinition: [{ required: true, message: '请输入产品定义', trigger: 'blur' }], |
|
||||||
productName: [{ required: true, message: '请输入产品名称', trigger: 'blur' }], |
|
||||||
productCurrency: [{ required: true, message: '请选择产品币种', trigger: 'change' }], |
|
||||||
modeRepayment: [{ required: true, message: '请选择还款方式', trigger: 'change' }], |
|
||||||
}); |
|
||||||
|
|
||||||
// tab切换回调 |
|
||||||
const tabChange = (tab: TabsPaneContext, event: Event) => { |
|
||||||
console.log(tab, event); |
|
||||||
}; |
|
||||||
// 配置项 |
|
||||||
const getConfig = async () => { |
|
||||||
const { process } = await getProcessInformationBasedOnRoles(form.productType === 1 ? 45 : 44); |
|
||||||
config.value = process; |
|
||||||
}; |
|
||||||
// 详情 |
|
||||||
const getDetail = async () => { |
|
||||||
if (id.value) { |
|
||||||
try { |
|
||||||
const { data } = await findById(id.value); |
|
||||||
info.value = data; |
|
||||||
} finally { |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
watch( |
|
||||||
() => route.query, |
|
||||||
() => { |
|
||||||
getDetail(); |
|
||||||
}, |
|
||||||
{ |
|
||||||
immediate: true, |
|
||||||
}, |
|
||||||
); |
|
||||||
// 提交 |
|
||||||
const submit = async (formEl: FormInstance | undefined) => { |
|
||||||
if (!formEl) return; |
|
||||||
await formEl.validate(async (valid, fields) => { |
|
||||||
if (valid) { |
|
||||||
try { |
|
||||||
const param = JSON.parse(JSON.stringify(form)); |
|
||||||
|
|
||||||
// 企业 |
|
||||||
if (param.productType) { |
|
||||||
if (!param.productObject) return ElMessage.error('请选择企业类型'); |
|
||||||
} |
|
||||||
if ((!param.productType && param.age) || param.productType) { |
|
||||||
if (!param.minimumAge) return ElMessage.error('请输入最小年龄'); |
|
||||||
if (!param.maximumAge) return ElMessage.error('请输入最大年龄'); |
|
||||||
if (param.minimumAge < 0 || param.minimumAge > 999 || param.maximumAge < 0 || param.maximumAge > 999) return ElMessage.error('请输入合理的年龄'); |
|
||||||
if (param.minimumAge > param.maximumAge) return ElMessage.error('最小年龄不得大于最大年龄'); |
|
||||||
} |
|
||||||
|
|
||||||
// 个人 |
|
||||||
if (!param.productType) { |
|
||||||
if (param.edu && !param.educationalRequirements.length) return ElMessage.error('请选择学历要求'); |
|
||||||
if (param.curWL && !param.currentWorkingLife.length) return ElMessage.error('请选择工作年限'); |
|
||||||
if (param.curWL && !param.currentWorkingLife.length) return ElMessage.error('请选择工作年限'); |
|
||||||
} |
|
||||||
|
|
||||||
param.currentWorkingLife = param.currentWorkingLife.join(); |
|
||||||
param.educationalRequirements = param.educationalRequirements.join(); |
|
||||||
param.modeRepayment = param.modeRepayment.join(); |
|
||||||
param.providentFundAndSocialSecurity = param.providentFundAndSocialSecurity ? 1 : ''; |
|
||||||
param.whetherToSupportEarlyRepayment = param.whetherToSupportEarlyRepayment ? 58 : ''; |
|
||||||
// 担保方式 |
|
||||||
param.addBankProductsGuarantyStyleReqList = []; |
|
||||||
param.bankGuaranteeTypeIds.forEach((e: number) => { |
|
||||||
param.addBankProductsGuarantyStyleReqList.push({ |
|
||||||
bankGuaranteeTypeId: (e > 22 && e < 33) || (e > 32 && e < 38) ? e : '', |
|
||||||
pid: e > 22 && e < 33 ? 110 : e > 32 && e < 38 ? 111 : e, |
|
||||||
}); |
|
||||||
}); |
|
||||||
if (id.value) { |
|
||||||
param.id = id.value; |
|
||||||
param.status = 295; |
|
||||||
await update(param); |
|
||||||
addRecord(param, id.value); |
|
||||||
} else { |
|
||||||
const { message } = await save(param); |
|
||||||
addRecord(param, message); |
|
||||||
} |
|
||||||
ElMessage.success('提交成功!'); |
|
||||||
emit('getList', 1); |
|
||||||
} finally { |
|
||||||
} |
|
||||||
} else { |
|
||||||
console.log('error submit!', fields); |
|
||||||
} |
|
||||||
}); |
|
||||||
}; |
|
||||||
// 新增判分记录 |
|
||||||
const addRecord = async (data: Record<string, any>, newId: number) => { |
|
||||||
const isEnterprise = data.productType === 1; |
|
||||||
const preIds = `1,2,41,${data.productType ? 45 : 44},${newId}`; // 1,关卡id,角色(这个页面是产品经理新增产品),个人/企业(44/45) |
|
||||||
const lcRule = <Record<string, any>[]>[ |
|
||||||
handleId(48, 1, data.productDefinition, preIds + ',48', 3), |
|
||||||
handleId(49, 2, data.productName, preIds + ',49', 3), |
|
||||||
handleId(50, 3, 1, preIds + ',50', 1), |
|
||||||
]; |
|
||||||
|
|
||||||
// 贷款用途 |
|
||||||
if (isEnterprise) { |
|
||||||
// 企业 |
|
||||||
lcRule.push( |
|
||||||
handleId(62, 7, data.productObject, preIds + ',61,62', 1), |
|
||||||
handleId(63, 8, '[' + data.minimumAge + ',' + data.maximumAge + ']' + '', preIds + ',61,63', 5), |
|
||||||
handleId(65, 19, data.loanPurpose, preIds + ',65', 1), |
|
||||||
); |
|
||||||
} else { |
|
||||||
// 个人 |
|
||||||
data.age && lcRule.push(handleId(100, 41, '[' + data.minimumAge + ',' + data.maximumAge + ']' + '', preIds + ',51,100', 5)); |
|
||||||
data.edu && lcRule.push(handleId(101, 42, data.educationalRequirements, preIds + ',51,101', 1)); |
|
||||||
data.curWL && lcRule.push(handleId(102, 43, data.currentWorkingLife, preIds + ',51,102', 1)); |
|
||||||
data.providentFundAndSocialSecurity && lcRule.push(handleId(103, '', '', preIds + ',51,103', '')); // 公积金社保 |
|
||||||
|
|
||||||
lcRule.push( |
|
||||||
data.loanPurpose === 107 ? handleId(107, 11, data.otherPurposesOfLoan, preIds + ',52,107', 3) : handleId(data.loanPurpose, '', '', preIds + ',52,' + data.loanPurpose, 1), |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
// 担保方式 |
|
||||||
data.bankGuaranteeTypeIds.includes(108) && lcRule.push(handleId(108, '', '', preIds + ',53,108', '')); |
|
||||||
data.bankGuaranteeTypeIds.includes(109) && lcRule.push(handleId(109, '', '', preIds + ',53,109', '')); |
|
||||||
data.bankGuaranteeTypeIds.includes(110) && lcRule.push(handleId(110, 13, data.bankGuaranteeTypeIds.filter((e: number) => e > 22 && e < 33).join(), preIds + ',53,110', 1)); |
|
||||||
data.bankGuaranteeTypeIds.includes(111) && lcRule.push(handleId(111, 14, data.bankGuaranteeTypeIds.filter((e: number) => e > 32 && e < 38).join(), preIds + ',53,111', 1)); |
|
||||||
|
|
||||||
lcRule.push( |
|
||||||
handleId(54, 15, '[' + data.minimumLoan + ',' + data.loanCeiling + ']', preIds + ',54', 5), |
|
||||||
handleId(55, 16, '[' + data.minimumAprOnLoan + ',' + data.maximumAnnualInterestRate + ']', preIds + ',55', 5), |
|
||||||
handleId(56, 17, '[' + data.minimumTermOfLoan + ',' + data.maximumTermOfLoan + ']', preIds + ',56', 5), |
|
||||||
handleId(57, 18, data.modeRepayment, preIds + ',57', 1), |
|
||||||
); |
|
||||||
|
|
||||||
data.whetherToSupportEarlyRepayment && lcRule.push(handleId(58, '', '', preIds + ',58', '')); |
|
||||||
|
|
||||||
await addOperation({ |
|
||||||
parentId: preIds, |
|
||||||
lcJudgmentRuleReq: lcRule, |
|
||||||
projectId: 1, |
|
||||||
}); |
|
||||||
}; |
|
||||||
onMounted(() => { |
|
||||||
getConfig(); |
|
||||||
}); |
|
||||||
</script> |
|
||||||
|
|
||||||
<style lang="scss" scoped> |
|
||||||
@import url(../../../styles/form.scss); |
|
||||||
.audit { |
|
||||||
@apply py-5 px-4 mb-[30px] bg-[#f9fafc] rounded-[10px]; |
|
||||||
.line { |
|
||||||
@apply mb-[18px] text-sm leading-[1.6]; |
|
||||||
} |
|
||||||
.field { |
|
||||||
@apply text-sm font-semibold; |
|
||||||
} |
|
||||||
} |
|
||||||
</style> |
|
@ -1,131 +0,0 @@ |
|||||||
<template> |
|
||||||
<div> |
|
||||||
<el-tabs v-model="curTab" |
|
||||||
@tab-click="tabChange"> |
|
||||||
<el-tab-pane label="产品审批" |
|
||||||
name="tab1"> |
|
||||||
<info /> |
|
||||||
<el-form ref="formRef" |
|
||||||
:model="form" |
|
||||||
:rules="rules" |
|
||||||
label-width="100px" |
|
||||||
label-suffix=":" |
|
||||||
class="form pt-5 mt-5 border-t border-t-solid border-t-[#EDF1F5]" |
|
||||||
status-icon> |
|
||||||
<el-form-item label="审批意见" |
|
||||||
prop="status"> |
|
||||||
<el-select v-model="form.status" |
|
||||||
placeholder="请选择"> |
|
||||||
<el-option v-for="(item, i) in config[0]?.subject?.itemList.slice(2)" |
|
||||||
:key="i" |
|
||||||
:label="item.options" |
|
||||||
:value="item.itemId" /> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="意见描述" |
|
||||||
prop="opinionDescription"> |
|
||||||
<el-input type="textarea" |
|
||||||
placeholder="审批意见500字以内。" |
|
||||||
maxlength="500" |
|
||||||
v-model="form.opinionDescription"></el-input> |
|
||||||
</el-form-item> |
|
||||||
<div class="flex justify-end"> |
|
||||||
<div class="submit" |
|
||||||
@click="submit(formRef)">审批</div> |
|
||||||
</div> |
|
||||||
</el-form> |
|
||||||
</el-tab-pane> |
|
||||||
</el-tabs> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script setup lang="ts"> |
|
||||||
import { ref, computed, reactive, watch, onMounted } from 'vue'; |
|
||||||
import { ElMessage } from 'element-plus'; |
|
||||||
import type { TabsPaneContext, FormInstance, FormRules } from 'element-plus'; |
|
||||||
import { useRouter, useRoute } from 'vue-router'; |
|
||||||
import Info from './Info.vue'; |
|
||||||
import { findById, examineAndApprove } from '@/api/bank'; |
|
||||||
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment'; |
|
||||||
import dayjs from 'dayjs'; |
|
||||||
|
|
||||||
const emit = defineEmits(['getList']); |
|
||||||
interface RuleForm { |
|
||||||
id: any; |
|
||||||
status: any; |
|
||||||
opinionDescription?: string; |
|
||||||
} |
|
||||||
const router = useRouter(); |
|
||||||
const route = useRoute(); |
|
||||||
const curTab = ref<string>('tab1'); |
|
||||||
const info = ref<any>({}); |
|
||||||
const config = ref<any[]>([]); |
|
||||||
const formRef = ref<FormInstance>(); |
|
||||||
const form = reactive<RuleForm>({ |
|
||||||
id: computed(() => +route.query.id), |
|
||||||
status: '', |
|
||||||
opinionDescription: '', |
|
||||||
}); |
|
||||||
const rules = reactive<FormRules<RuleForm>>({ |
|
||||||
status: [{ required: true, message: '请选择审批意见', trigger: 'change' }], |
|
||||||
opinionDescription: [{ required: true, message: '请输入意见描述', trigger: 'blur' }], |
|
||||||
}); |
|
||||||
|
|
||||||
// tab切换回调 |
|
||||||
const tabChange = (tab: TabsPaneContext, event: Event) => { |
|
||||||
console.log(tab, event); |
|
||||||
}; |
|
||||||
// 配置项 |
|
||||||
const getConfig = async () => { |
|
||||||
const { process } = await getProcessInformationBasedOnRoles(43); // 专家委员会43 |
|
||||||
config.value = process; |
|
||||||
}; |
|
||||||
watch( |
|
||||||
() => route.query, |
|
||||||
() => { |
|
||||||
// getDetail(); |
|
||||||
}, |
|
||||||
{ |
|
||||||
immediate: true, |
|
||||||
}, |
|
||||||
); |
|
||||||
// 提交 |
|
||||||
const submit = async (formEl: FormInstance | undefined) => { |
|
||||||
if (!formEl) return; |
|
||||||
await formEl.validate(async (valid, fields) => { |
|
||||||
if (valid) { |
|
||||||
try { |
|
||||||
const param = JSON.parse(JSON.stringify(form)); |
|
||||||
param.approvalTime = dayjs(new Date()).format('YYYY年-M月-D日'); |
|
||||||
|
|
||||||
// const { message } = await examineAndApprove(param); |
|
||||||
const { message } = await examineAndApprove(param.id, param.opinionDescription, param.status, param.approvalTime); |
|
||||||
// addRecord(param, message); |
|
||||||
ElMessage.success('提交成功!'); |
|
||||||
emit('getList', 1); |
|
||||||
} finally { |
|
||||||
} |
|
||||||
} else { |
|
||||||
console.log('error submit!', fields); |
|
||||||
} |
|
||||||
}); |
|
||||||
}; |
|
||||||
// 新增判分记录 |
|
||||||
const addRecord = async (data: Record<string, any>, newId: number) => { |
|
||||||
const preIds = `1,2,43,${data.productType ? 45 : 44},${newId}`; // 1,关卡id,角色(这个页面是专家委员会审批),个人/企业(44/45) |
|
||||||
const lcRule = <Record<string, any>[]>[handleId(145, 69, data.status, preIds + ',145', 1), handleId(146, 70, data.opinionDescription, preIds + ',146', 3)]; |
|
||||||
|
|
||||||
await addOperation({ |
|
||||||
parentId: preIds, |
|
||||||
lcJudgmentRuleReq: lcRule, |
|
||||||
projectId: 1, |
|
||||||
}); |
|
||||||
}; |
|
||||||
onMounted(() => { |
|
||||||
getConfig(); |
|
||||||
}); |
|
||||||
</script> |
|
||||||
|
|
||||||
<style lang="scss" scoped> |
|
||||||
@import url(../../../styles/form.scss); |
|
||||||
</style> |
|
@ -1,21 +0,0 @@ |
|||||||
<template> |
|
||||||
<div> |
|
||||||
<el-tabs v-model="curTab"> |
|
||||||
<el-tab-pane label="产品要素" |
|
||||||
name="tab1"> |
|
||||||
<info /> |
|
||||||
</el-tab-pane> |
|
||||||
</el-tabs> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script setup lang="ts"> |
|
||||||
import { ref } from 'vue'; |
|
||||||
import Info from './Info.vue'; |
|
||||||
|
|
||||||
const curTab = ref<string>('tab1'); |
|
||||||
</script> |
|
||||||
|
|
||||||
<style lang="scss" scoped> |
|
||||||
@import url(../../../styles/form.scss); |
|
||||||
</style> |
|
@ -1,181 +0,0 @@ |
|||||||
<template> |
|
||||||
<div v-if="info.approvalTime" |
|
||||||
class="audit"> |
|
||||||
<div class="line"> |
|
||||||
<span class="field">审批意见:</span> |
|
||||||
<span class="status">{{ getStatus(+info?.status) }}</span> |
|
||||||
</div> |
|
||||||
<div class="line"> |
|
||||||
<span class="field">意见描述:</span> |
|
||||||
{{ info.opinionDescription }} |
|
||||||
</div> |
|
||||||
<p class="mb-2 text-sm text-[#333] text-right">审查日期:{{ info.approvalTime }}</p> |
|
||||||
<p class="mb-2 text-sm text-[#333] text-right">审查员:公瑾</p> |
|
||||||
</div> |
|
||||||
<div class="info mt-2"> |
|
||||||
<h6 class="step-name">一、产品定义</h6> |
|
||||||
<p class="text">{{ info.productDefinition }}</p> |
|
||||||
<h6 class="step-name mt-5">二、产品要素</h6> |
|
||||||
<p class="text">产品名称:{{ info.productName }}</p> |
|
||||||
<p class="text">贷款币种:人民币</p> |
|
||||||
<p v-if="info.loanPurpose" |
|
||||||
class="text"> |
|
||||||
贷款用途:{{ |
|
||||||
info.loanPurpose === '购房' |
|
||||||
? '可用于住房按揭贷款、二手房住房按揭贷款。' |
|
||||||
: info.loanPurpose === '消费' |
|
||||||
? '贷款用途可用于除购房之外的合法个人消费支出,不得用于投资经营,不得用于无指定用途的个人支出。' |
|
||||||
: info.loanPurpose === '经营' && !info.productType |
|
||||||
? '可用于个人或其企业生产和经营活动中临时性、季节性等流动资金周转以及购置、安装或修理小型设备和装潢经营性场所所需的人民币贷款业务。' |
|
||||||
: info.loanPurpose === '创业' |
|
||||||
? '用于创业或再创业过程中的资金需求。' |
|
||||||
: info.loanPurpose === '经营' && info.productType |
|
||||||
? '用于短期生产经营周转的可循环的人民币信用贷款业务。' |
|
||||||
: info.otherPurposesOfLoan |
|
||||||
}} |
|
||||||
</p> |
|
||||||
<p class="text">担保方式:{{ info.guarantyStyle }}</p> |
|
||||||
<p class="text">贷款期限:{{ info.minimumTermOfLoan }}月 - {{ info.maximumTermOfLoan }}月</p> |
|
||||||
<p class="text">贷款限额:{{ info.minimumLoan }}万元 - {{ info.loanCeiling }}万元</p> |
|
||||||
<p class="text">贷款利率:{{ info.minimumAprOnLoan }}% - {{ info.maximumAnnualInterestRate }}%</p> |
|
||||||
<p class="text">还款方式:{{ info.modeRepayment }}</p> |
|
||||||
<div class="text"> |
|
||||||
贷款对象: |
|
||||||
<p v-if="info.minimumAge">年龄{{ info.minimumAge }} - {{ info.maximumAge }}周岁;</p> |
|
||||||
<p v-if="info.educationalRequirements">取得{{ info.educationalRequirements }}以上学历;</p> |
|
||||||
<p v-if="info.currentWorkingLife">{{ info.currentWorkingLife }};</p> |
|
||||||
<p v-if="info.providentFundAndSocialSecurity">连续缴纳本市社保或者公积金6个月;</p> |
|
||||||
<p>持有中国银行I类账户,且已关联至手机银行,且在我行及其他金融同业无不良信用记录。</p> |
|
||||||
</div> |
|
||||||
<template v-if="riskInfo"> |
|
||||||
<h6 class="step-name mt-5">三、材料要求</h6> |
|
||||||
<p class="text">办理账户-提供材料:{{ riskInfo?.accountMaterials }}</p> |
|
||||||
<p v-if="riskInfo?.sendingAccount" |
|
||||||
class="text">办理账户-发放账户:借记卡或放款专户</p> |
|
||||||
<p v-if="riskInfo?.loanApplicationMethod" |
|
||||||
class="text">贷款申请-申请方式:{{ riskInfo?.loanApplicationMethod }}</p> |
|
||||||
<p v-if="riskInfo?.borrowerMaterial" |
|
||||||
class="text">贷款申请-提供材料-借款人材料:{{ riskInfo?.borrowerMaterial }}</p> |
|
||||||
<template v-if="info.productType"> |
|
||||||
<p v-if="riskInfo?.enterpriseMaterial" |
|
||||||
class="text">贷款申请-提供材料-企业材料:{{ riskInfo?.enterpriseMaterial }}</p> |
|
||||||
<p v-if="riskInfo?.collateral" |
|
||||||
class="text">贷款申请-提供材料-抵押物:{{ riskInfo?.collateral }}</p> |
|
||||||
</template> |
|
||||||
<template v-else> |
|
||||||
<p v-if="riskInfo?.mateMaterial" |
|
||||||
class="text">贷款申请-提供材料-配偶材料:{{ riskInfo?.mateMaterial }}</p> |
|
||||||
<p v-if="riskInfo?.businessMaterials" |
|
||||||
class="text">贷款申请-提供材料-经营类材料:{{ riskInfo?.businessMaterials }}</p> |
|
||||||
</template> |
|
||||||
<p v-if="riskInfo?.supplementaryMaterials" |
|
||||||
class="text">贷款申请-提供材料-补充材料:{{ riskInfo?.supplementaryMaterials }}</p> |
|
||||||
<p v-if="riskInfo?.runBatchObject" |
|
||||||
class="text">系统跑批准入风控策略-跑批对象:{{ riskInfo?.runBatchObject }}</p> |
|
||||||
<p v-if="riskInfo?.accessStrategy" |
|
||||||
class="text">系统跑批准入风控策略-准入策略:{{ riskInfo?.accessStrategy }}</p> |
|
||||||
<p v-if="riskInfo?.personalCreditScoringStrategies" |
|
||||||
class="text">系统跑批准入风控策略-信用评分策略:{{ riskInfo?.personalCreditScoringStrategies }}</p> |
|
||||||
<p v-if="riskInfo?.riskDegreeStrategy" |
|
||||||
class="text">系统跑批准入风控策略-风险度策略:{{ riskInfo?.riskDegreeStrategy }}</p> |
|
||||||
<p v-if="riskInfo?.interestRatePricingModel" |
|
||||||
class="text">系统跑批准入风控策略-利率定价模型-个人额度模型:{{ riskInfo?.interestRatePricingModel }}</p> |
|
||||||
<p v-if="riskInfo?.individualInterestRateModel" |
|
||||||
class="text">系统跑批准入风控策略-利率定价模型-个人利率模型</p> |
|
||||||
<p v-if="riskInfo?.dueDiligenceMode" |
|
||||||
class="text">尽职调查-尽调方式:{{ riskInfo?.dueDiligenceMode }}</p> |
|
||||||
<p v-if="riskInfo?.dueDiligenceContent" |
|
||||||
class="text">尽职调查-尽调内容:{{ riskInfo?.dueDiligenceContent }}</p> |
|
||||||
<p v-if="riskInfo?.reviewContent" |
|
||||||
class="text">贷款审查-审查内容:{{ riskInfo?.reviewContent }}</p> |
|
||||||
<p v-if="riskInfo?.reviewSignature" |
|
||||||
class="text">贷款审查-审查签字:{{ riskInfo?.reviewSignature }}</p> |
|
||||||
<p v-if="riskInfo?.reviewApproveContent" |
|
||||||
class="text">贷款审批-审批内容:{{ riskInfo?.reviewApproveContent }}</p> |
|
||||||
<p v-if="riskInfo?.approvalSignature" |
|
||||||
class="text">贷款审批-审批签字:{{ riskInfo?.approvalSignature }}</p> |
|
||||||
<p v-if="riskInfo?.contractMaterials" |
|
||||||
class="text">签订合同-提供的材料:{{ riskInfo?.contractMaterials }}</p> |
|
||||||
<p v-if="riskInfo?.loanContract" |
|
||||||
class="text">签订合同-合同模板-借贷合同:{{ riskInfo?.loanContract }}</p> |
|
||||||
<p v-if="riskInfo?.mortgageContract" |
|
||||||
class="text">签订合同-合同模板-抵押合同:{{ riskInfo?.mortgageContract }}</p> |
|
||||||
<p v-if="riskInfo?.pledgeContract" |
|
||||||
class="text">签订合同-合同模板-质押合同:{{ riskInfo?.pledgeContract }}</p> |
|
||||||
<p v-if="riskInfo?.guaranteeContract" |
|
||||||
class="text">签订合同-合同模板-担保合同:{{ riskInfo?.guaranteeContract }}</p> |
|
||||||
<p v-if="riskInfo?.selectionStrategy" |
|
||||||
class="text">贷后管理-选择策略:{{ riskInfo?.selectionStrategy }}</p> |
|
||||||
|
|
||||||
<h6 class="step-name mt-5">四、业务流程</h6> |
|
||||||
<p class="text">1、贷款人APP向智信银行公司业务部门提交借款申请,同时提交贷款用途证明文件以及有关资料;</p> |
|
||||||
<p class="text">2、智信银行对贷款人的贷款申请进行审查,同时根据实际情况要求借款人提供补充资料;</p> |
|
||||||
<p class="text">3、智信银行内部审批通过后,与贷款人签订借款合同;</p> |
|
||||||
<p class="text">4、贷款人落实有关提款前提条件,根据贷款合同提款。</p> |
|
||||||
<h6 class="step-name mt-5">五、注意要点</h6> |
|
||||||
<p class="text"> |
|
||||||
贷款人在使用款额度时,必须明确说明贷款用途。贷款人必须在获得循环贷款额度后,方可在额度与用途范围内申请贷款,受理机构仅限在原经办行,同时逐笔上报中心核批。单笔贷款金额不得超过贷款人单笔消费(或投资)总金额的80%。 |
|
||||||
</p> |
|
||||||
</template> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script setup lang="ts"> |
|
||||||
import { ref, computed, watch, onMounted } from 'vue'; |
|
||||||
import { findById } from '@/api/bank'; |
|
||||||
import { useRouter, useRoute } from 'vue-router'; |
|
||||||
import { getStatus } from '@/store/useProduct'; |
|
||||||
|
|
||||||
const router = useRouter(); |
|
||||||
const route = useRoute(); |
|
||||||
const id = computed(() => +route.query.id); |
|
||||||
const info = ref<Record<string, any>>({}); |
|
||||||
const riskInfo = ref<Record<string, any>>(null); |
|
||||||
|
|
||||||
// 详情 |
|
||||||
const getDetail = async () => { |
|
||||||
if (id.value) { |
|
||||||
try { |
|
||||||
const { data } = await findById(id.value); |
|
||||||
info.value = data; |
|
||||||
if (info.value.riskControlDetails) riskInfo.value = data.riskControlDetails; |
|
||||||
} finally { |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
watch( |
|
||||||
() => route.query, |
|
||||||
() => { |
|
||||||
getDetail(); |
|
||||||
}, |
|
||||||
{ |
|
||||||
immediate: true, |
|
||||||
}, |
|
||||||
); |
|
||||||
</script> |
|
||||||
|
|
||||||
<style lang="scss" scoped> |
|
||||||
.info { |
|
||||||
.step-name { |
|
||||||
@apply mb-3 text-sm font-semibold text-[#006bff]; |
|
||||||
} |
|
||||||
.line { |
|
||||||
@apply flex mb-2; |
|
||||||
} |
|
||||||
.label { |
|
||||||
@apply mr-1 text-sm font-semibold text-[#333] leading-[32px]; |
|
||||||
} |
|
||||||
.text { |
|
||||||
@apply text-sm text-[#333] leading-[32px]; |
|
||||||
} |
|
||||||
} |
|
||||||
.audit { |
|
||||||
@apply py-5 px-4 mb-[30px] bg-[#f9fafc] rounded-[10px]; |
|
||||||
.line { |
|
||||||
@apply mb-[18px] text-sm leading-[1.6]; |
|
||||||
} |
|
||||||
.field { |
|
||||||
@apply text-sm font-semibold; |
|
||||||
} |
|
||||||
} |
|
||||||
</style> |
|