yujialong 1 year ago
parent 1e3e64e19a
commit 5b4eb3ec15
  1. 1
      src/api/bank.ts
  2. 14
      src/layout/components/AppHeader.vue
  3. 4
      src/layout/components/AppSidebar/Menu.vue
  4. 2
      src/layout/index.vue
  5. 104
      src/views/product/Add.vue
  6. 97
      src/views/product/List.vue

@ -4,7 +4,6 @@ export const queryStorageList = async (params?: Record<string, any>): Promise<an
export const queryStorage = async (id: number): Promise<any> => (await axios.get(`/backend/core/storage/${id}`)).data;
export const updateStorage = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/storage?_method=put', data)).data;
export const primaryTypeOfGuarantee = async (): Promise<any> => (await axios.post('/product/bankGuaranteeType/primaryTypeOfGuarantee')).data;
export const typeOfGuarantee = async (): Promise<any> => (await axios.post('/product/bankGuaranteeType/typeOfGuarantee')).data;
export const bankingProductsList = async (data: Record<string, any>): Promise<any> => (await axios.post('/product/product/bank/products/bankingProductsList', data)).data;
export const batchDeletion = async (ids: number[]): Promise<any> => (await axios.post('/product/product/bank/products/batchDeletion', ids)).data;

@ -1,6 +1,10 @@
<template>
<div class="flex justify-between items-center py-6 px-5 overflow-hidden">
<div class="flex justify-between items-center w-full py-6 px-5 overflow-hidden bg-transparent">
<logo :collapse="collapse" />
<div>
<el-button @click="switchRole(1)">切换产品经理</el-button>
<el-button @click="switchRole(2)">切换风控经理</el-button>
</div>
<div class="inline-flex items-center">
<img class="mr-3 cursor-pointer"
src="@/assets/images/2.png"
@ -17,6 +21,7 @@
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { useRouter } from 'vue-router';
import { setCookieLocale, getSessionSiteId, setSessionSiteId } from '@/utils/common';
import { toTree, flatTree } from '@/utils/tree';
// import { querySiteList } from '@/api/bank';
@ -24,6 +29,7 @@ import { currentUser, perm, logout } from '@/store/useCurrentUser';
import { appState, toggleSidebar } from '@/store/useAppState';
import Logo from './Logo.vue';
const router = useRouter();
const siteId = ref<number | null>(getSessionSiteId());
const siteList = ref<any[]>([]);
const site = computed(() => siteList.value.find((item) => item.id === siteId.value));
@ -33,10 +39,8 @@ const fetchSiteList = async () => {
// siteId.value = siteList.value[0]?.id;
// }
};
const changeSiteId = (id: number) => {
setSessionSiteId(id);
siteId.value = id;
window.location.reload();
const switchRole = (type: number) => {
router.push(`/product?type=0&i=1&role=${type}`);
};
onMounted(() => {
// fetchSiteList();

@ -23,7 +23,7 @@
</li>
</template>
<template v-else>
<li>
<li :class="{ active: active == 1 }">
<img class="icon"
src="@/assets/images/icon1.png"
alt="" />
@ -71,7 +71,7 @@ import { isShowMenu } from '@/store/useCurrentUser';
const router = useRouter();
const route = useRoute();
const active = computed(() => route.query.i);
const isProduct = ref<any>(true);
const isProduct = computed(() => route.query.role == 1 || !route.query.role);
//
const toPage = (path: string) => {

@ -7,7 +7,7 @@
<app-header />
<app-sidebar v-if="!hideNav"
class="sidebar fixed h-full px-5 overflow-hidden transition-width duration-300 z-40" />
<div class="main transition-margin duration-300"
<div class="main h-[calc(100vh-85px)] transition-margin duration-300 overflow-auto"
:class="{ 'md:ml-sidebar': !hideNav }">
<app-main />
</div>

@ -35,6 +35,32 @@
<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-group class="mt-1"
@ -55,7 +81,7 @@
<el-checkbox-group v-if="form.edu"
class="mt-2 ml-5"
v-model="form.educationalRequirements">
<el-checkbox v-for="(item, i) in config[3]?.recordChildren[1]?.subject?.itemList"
<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>
@ -67,13 +93,14 @@
<el-checkbox-group v-if="form.curWL"
class="mt-2 ml-5"
v-model="form.currentWorkingLife">
<el-checkbox v-for="(item, i) in config[3]?.recordChildren[2]?.subject?.itemList"
<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="贷款用途"
@ -81,9 +108,16 @@
<div class="flex-1">
<p class="field-name">选择本产品贷款资金的用途</p>
<el-radio-group v-model="form.loanPurpose">
<el-radio v-for="(item, i) in config[4]?.recordChildren"
<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-[250px] ml-5"
@ -96,7 +130,7 @@
prop="bankGuaranteeTypeIds">
<div class="flex-1">
<p class="field-name">选择本产品的担保种类</p>
<div v-for="(item, i) in config[5]?.recordChildren"
<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">
@ -159,7 +193,7 @@
<div class="flex-1">
<p class="field-name">选择本产品可以选择的还款方式</p>
<el-checkbox-group v-model="form.modeRepayment">
<el-checkbox v-for="(item, i) in config[9]?.subject?.itemList"
<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>
@ -199,18 +233,19 @@ interface RuleForm {
bankGuaranteeTypeIds: any[];
currentWorkingLife?: any;
educationalRequirements?: any;
loanCeiling?: number;
loanPurpose?: number;
maximumAge?: number;
maximumAnnualInterestRate?: number;
maximumTermOfLoan?: number;
minimumAge?: number;
minimumAprOnLoan?: number;
minimumLoan?: number;
minimumTermOfLoan?: number;
loanCeiling: any;
loanPurpose: any;
productObject: any;
maximumAge: any;
maximumAnnualInterestRate: any;
maximumTermOfLoan: any;
minimumAge: any;
minimumAprOnLoan: any;
minimumLoan: any;
minimumTermOfLoan: any;
modeRepayment?: any;
otherPurposesOfLoan: string;
productObject?: number;
productObject: any;
productType: number;
providentFundAndSocialSecurity: any;
whetherToSupportEarlyRepayment?: any;
@ -219,7 +254,7 @@ interface RuleForm {
const router = useRouter();
const route = useRoute();
const curTab = ref<string>('tab1');
const config = ref<any>({});
const config = ref<any>([]);
const formRef = ref<FormInstance>();
const form = reactive<RuleForm>({
productDefinition: '',
@ -230,6 +265,7 @@ const form = reactive<RuleForm>({
educationalRequirements: [],
loanCeiling: '',
loanPurpose: '',
productObject: '',
maximumAge: '',
maximumAnnualInterestRate: '',
maximumTermOfLoan: '',
@ -262,7 +298,7 @@ const tabChange = (tab: TabsPaneContext, event: Event) => {
};
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(41);
const { process } = await getProcessInformationBasedOnRoles(form.productType === 1 ? 45 : 44);
config.value = process;
};
//
@ -277,14 +313,18 @@ const submit = async (formEl: FormInstance | undefined) => {
param.modeRepayment = param.modeRepayment.join();
param.providentFundAndSocialSecurity = param.providentFundAndSocialSecurity ? 13 : '';
param.whetherToSupportEarlyRepayment = param.whetherToSupportEarlyRepayment ? 58 : '';
console.log(33, form, param);
await save(param);
addRecord(param);
//
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,
});
});
const { message } = await save(param);
addRecord(param, message);
ElMessage.success('提交成功!');
emit('getList', 1);
// setTimeout(() => {
// router.push(``)
// }, 1500);
} finally {
}
} else {
@ -293,22 +333,34 @@ const submit = async (formEl: FormInstance | undefined) => {
});
};
//
const addRecord = async (data: any) => {
const preIds = `1,2,41,${data.productType ? 45 : 44}`; // 1id/44/45
const addRecord = async (data: Record<string, any>, newId: number) => {
const isEnterprise = data.productType === 1;
const preIds = `1,2,41,${data.productType ? 45 : 44},${newId}`; // 1id/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', ''));

@ -4,16 +4,22 @@
<search v-model="params.keyWord"
@change="initList"></search>
<div class="filter">
<el-checkbox-group v-if="role == 2"
class="mr-5"
v-model="productTypes">
<el-checkbox :label="0">个人</el-checkbox>
<el-checkbox :label="1">企业</el-checkbox>
</el-checkbox-group>
<div class="select">
<el-select v-model="params.guarantyStyleId"
placeholder="担保方式"
size="large"
@change="initList">
size="large">
<el-option label="担保方式"
value="" />
<el-option v-for="item in guarantees"
:key="item.id"
:label="item.guarantyStyle"
:label="item.name"
:value="item.id" />
</el-select>
<img src="@/assets/images/7.png"
@ -23,8 +29,7 @@
<div class="select">
<el-select v-model="params.status"
placeholder="产品进度"
size="large"
@change="initList">
size="large">
<el-option v-for="item in paces"
:key="item.id"
:label="item.name"
@ -34,7 +39,8 @@
alt=""
class="icon" />
</div>
<div class="add-btn"
<div v-if="role == 1"
class="add-btn"
@click="toAdd">
<img src="@/assets/images/plus.png"
alt=""
@ -55,6 +61,13 @@
label="产品名称"></el-table-column>
<el-table-column prop="productNumber"
label="产品编号"></el-table-column>
<el-table-column v-if="role == 2"
prop="loanCeiling"
label="贷款对象">
<template #default="{ row }">
{{ row.productType ? '企业' : '个人' }}
</template>
</el-table-column>
<el-table-column prop="guarantyStyle"
label="担保方式"></el-table-column>
<el-table-column prop="loanCeiling"
@ -76,16 +89,18 @@
label="操作">
<template #default="{ row }">
<el-button type="text"
@click="handleEdit(row.id)"
size="small">配置要素</el-button>
size="small"
@click="toDetail(`/product/cardList/config`, row.id)">配置{{ role == 1 ? '要素' : '风控' }}</el-button>
<el-button type="text"
@click="toDetail(row.id)"
@click="toDetail(`/product/cardList/detail`, row.id)"
size="small">产品详情</el-button>
<el-popconfirm title="您确定删除吗?"
@confirm="handleDelete(row.id)">
<el-popconfirm v-if="role == 1"
title="您确定删除吗?"
@confirm.stop="handleDelete(row.id)">
<template #reference>
<el-button type="text"
size="small">删除</el-button>
size="small"
@click.stop="stop">删除</el-button>
</template>
</el-popconfirm>
</template></el-table-column>
@ -110,7 +125,8 @@ import { useI18n } from 'vue-i18n';
import dayjs from 'dayjs';
import { perm } from '@/store/useCurrentUser';
import { pageSizes, pageLayout, toParams, resetParams } from '@/utils/common';
import { primaryTypeOfGuarantee, bankingProductsList, batchDeletion } from '@/api/bank';
import { getProcessInformationBasedOnRoles } from '@/api/judgment';
import { bankingProductsList, batchDeletion } from '@/api/bank';
import Search from '@/components/Search.vue';
import { useRouter, useRoute } from 'vue-router';
import { getStatus } from '@/store/useProduct';
@ -118,15 +134,23 @@ import { getStatus } from '@/store/useProduct';
const { t } = useI18n();
const router = useRouter();
const route = useRoute();
const productTypes = ref<number[]>([0, 1]);
const params = reactive({
createDateSort: '',
guarantyStyleId: '',
keyWord: '',
productType: '',
productType: computed(() => {
let val = <number | string>'';
if (route.query.role == 2) {
if (productTypes.value.length === 1) val = productTypes.value[0];
return val;
}
return +route.query.type;
}),
status: '',
});
params.productType = computed(() => +route.query.type);
const sort = ref<any>();
// params.productType = computed(() => (route.query.role == 2 ? '' : +route.query.type));
const role = computed(() => route.query.role || 1); // 12
const currentPage = ref<number>(1);
const pageSize = ref<number>(10);
const total = ref<number>(0);
@ -163,11 +187,12 @@ const loading = ref<boolean>(false);
//
const getGuarantee = async () => {
try {
const { data } = await primaryTypeOfGuarantee();
guarantees.value = data;
const { process } = await getProcessInformationBasedOnRoles(44);
guarantees.value = process[5].recordChildren;
} finally {
}
};
const stop = () => {};
//
const getList = async () => {
loading.value = true;
@ -189,7 +214,11 @@ onMounted(() => {
getList();
});
watch([() => params.keyWord, () => route.query.type], initList);
watch([params, () => route.query], initList);
// watch(productTypes, (val) => {
// console.log('🚀 ~ file: List.vue:207 ~ watch ~ val:', val);
// params.productType = val.length === 2 ? '' :
// });
const handleSort = ({ column, prop, order }: { column: any; prop: string; order: string }) => {
params.createDateSort = order === 'descending' ? 'desc' : order === 'ascending' ? 'asc' : '';
getList();
@ -202,9 +231,9 @@ const toAdd = () => {
});
};
//
const toDetail = async (id: number) => {
const toDetail = async (path: string, id: number) => {
router.push({
path: `/product/cardList/detail`,
path,
query: {
...route.query,
id,
@ -225,38 +254,26 @@ const handleDelete = async (id: number) => {
<style lang="scss" scoped>
.filter {
display: inline-flex;
align-items: center;
@apply inline-flex items-center;
.select {
position: relative;
margin-right: 12px;
@apply relative mr-[12px];
.icon {
position: absolute;
top: 12px;
left: 20px;
@apply absolute top-[12px] left-5;
}
:deep(.el-select) {
width: 170px;
@apply w-[170px];
.el-input__inner {
padding-left: 41px;
border-radius: 18px;
border-color: #dfe9f8;
@apply pl-[41px] rounded-[18px] border-[#dfe9f8];
}
}
}
.add-btn {
display: inline-flex;
align-items: center;
height: 36px;
padding: 0 24px;
font-size: 14px;
color: #fff;
@apply inline-flex items-center h-[36px] px-[24px] text-sm text-white rounded-[18px] cursor-pointer;
background: linear-gradient(-36deg, #006bff, #2ab1ff);
border: 1px solid #ffffff;
border-radius: 18px;
cursor: pointer;
.icon {
margin-right: 8px;
@apply mr-[8px];
}
}
}

Loading…
Cancel
Save