0407-北仑客群+客群业绩统计+网格整体业绩修改+青田贷款客户经理
This commit is contained in:
@@ -17,15 +17,6 @@ export function getCustGroup(id) {
|
||||
})
|
||||
}
|
||||
|
||||
// 异步创建客群(网格导入)
|
||||
export function createCustGroupByGrid(data) {
|
||||
return request({
|
||||
url: '/group/cust/createByGrid',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 异步创建客群(模板导入)
|
||||
export function createCustGroupByTemplate(data) {
|
||||
return request({
|
||||
@@ -36,24 +27,6 @@ export function createCustGroupByTemplate(data) {
|
||||
})
|
||||
}
|
||||
|
||||
// 更新客群
|
||||
export function updateCustGroup(data) {
|
||||
return request({
|
||||
url: '/group/cust/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新客群(网格导入)
|
||||
export function updateCustGroupByGrid(data) {
|
||||
return request({
|
||||
url: '/group/cust/updateByGrid',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新客群(模板导入)
|
||||
export function updateCustGroupByTemplate(data) {
|
||||
return request({
|
||||
@@ -100,24 +73,6 @@ export function removeMembers(groupId, memberIds) {
|
||||
})
|
||||
}
|
||||
|
||||
// 检查客群名称是否存在
|
||||
export function checkGroupNameExist(groupName) {
|
||||
return request({
|
||||
url: '/group/cust/checkName',
|
||||
method: 'get',
|
||||
params: { groupName: groupName }
|
||||
})
|
||||
}
|
||||
|
||||
// 根据网格类型获取客户经理列表
|
||||
export function getManagerList(gridType) {
|
||||
return request({
|
||||
url: '/grid/cmpm/managerList',
|
||||
method: 'get',
|
||||
params: { gridType: gridType }
|
||||
})
|
||||
}
|
||||
|
||||
// 分页查询客群成员列表
|
||||
export function listCustGroupMembers(groupId, query) {
|
||||
return request({
|
||||
@@ -135,3 +90,11 @@ export function getRegionGridListForGroup(query) {
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 获取所有客群标签列表
|
||||
export function getAllGroupTags() {
|
||||
return request({
|
||||
url: '/group/cust/tags',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
69
ruoyi-ui/src/api/group/performance.js
Normal file
69
ruoyi-ui/src/api/group/performance.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
export function getGroupPerformanceLsList(params) {
|
||||
return request({
|
||||
url: '/group/performance/ls/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
export function getGroupPerformanceGsList(params) {
|
||||
return request({
|
||||
url: '/group/performance/gs/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
export function getGroupPerformanceLsCustList(params) {
|
||||
return request({
|
||||
url: '/group/performance/ls/custList',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
export function getGroupPerformanceGsCustList(params) {
|
||||
return request({
|
||||
url: '/group/performance/gs/custList',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
export function exportGroupPerformanceLs(params) {
|
||||
return request({
|
||||
url: '/group/performance/exportLs',
|
||||
method: 'get',
|
||||
params,
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
export function exportGroupPerformanceGs(params) {
|
||||
return request({
|
||||
url: '/group/performance/exportGs',
|
||||
method: 'get',
|
||||
params,
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
export function exportGroupPerformanceLsCust(params) {
|
||||
return request({
|
||||
url: '/group/performance/exportLsCust',
|
||||
method: 'get',
|
||||
params,
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
export function exportGroupPerformanceGsCust(params) {
|
||||
return request({
|
||||
url: '/group/performance/exportGsCust',
|
||||
method: 'get',
|
||||
params,
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
@@ -238,6 +238,28 @@ export const constantRoutes = [
|
||||
component: () => import('@/views/group/custGroup/detail')
|
||||
}]
|
||||
},
|
||||
{
|
||||
path: '/center/groupPerformance/list',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [{
|
||||
path: '/center/groupPerformance/list',
|
||||
name: 'GroupPerformanceList',
|
||||
meta: { title: '客群业绩统计', activeMenu: '/center/groupPerformance/list' },
|
||||
component: () => import('@/views/group/performance/list')
|
||||
}]
|
||||
},
|
||||
{
|
||||
path: '/center/groupPerformance/custom',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [{
|
||||
path: '/center/groupPerformance/custom',
|
||||
name: 'GroupPerformanceCustom',
|
||||
meta: { title: '客群客户明细', activeMenu: '/center/groupPerformance/list' },
|
||||
component: () => import('@/views/group/performance/custom')
|
||||
}]
|
||||
},
|
||||
{
|
||||
path: '/checklist/customerlist',
|
||||
component: Layout,
|
||||
@@ -353,8 +375,8 @@ export const constantRoutes = [
|
||||
meta: { title: '个人中心', icon: 'user' }
|
||||
}
|
||||
]
|
||||
},
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
// 动态路由,基于用户权限动态去加载
|
||||
export const dynamicRoutes = [
|
||||
|
||||
@@ -432,7 +432,7 @@
|
||||
v-if="item.cmpmType == '贷款客户经理'"
|
||||
:label="`${item.cmpmType}:`"
|
||||
>
|
||||
<span>{{ item.cmpmUserList }}</span>
|
||||
<span>{{ is932Dept ? `${baseForm.belongUserName}-${baseForm.belongUserId}` : item.cmpmUserList }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -1242,6 +1242,7 @@ export default {
|
||||
businessScope: '',
|
||||
gridUserName: '',
|
||||
belongUserName: '',
|
||||
belongUserId: '',
|
||||
updateTime: ''
|
||||
},
|
||||
registerLocationNum: '',
|
||||
@@ -1374,7 +1375,7 @@ export default {
|
||||
Custom
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['roles', 'userName']),
|
||||
...mapGetters(['roles', 'userName', 'deptId']),
|
||||
isHeadAdmin() {
|
||||
return this.roles.includes('headAdmin')
|
||||
},
|
||||
@@ -1386,6 +1387,10 @@ export default {
|
||||
isPrivate() {
|
||||
return this.roles.includes('headPrivate')
|
||||
},
|
||||
// 是否932开头部门
|
||||
is932Dept() {
|
||||
return String(this.deptId || '').substring(0, 3) === '932'
|
||||
},
|
||||
// 运管部
|
||||
isHeadOps() {
|
||||
return this.roles.includes('headOps')
|
||||
|
||||
@@ -437,7 +437,7 @@
|
||||
v-if="item.cmpmType == '贷款客户经理'"
|
||||
:label="`${item.cmpmType}:`"
|
||||
>
|
||||
<span>{{ item.cmpmUserList }}</span>
|
||||
<span>{{ is932Dept ? `${baseForm.belongUserName}-${baseForm.belongUserId}` : item.cmpmUserList }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -1460,6 +1460,7 @@ export default {
|
||||
tel: '',
|
||||
gridUserName: '',
|
||||
belongUserName: '',
|
||||
belongUserId: '',
|
||||
updateTime: ''
|
||||
},
|
||||
registerLocationNum: '',
|
||||
@@ -1663,6 +1664,9 @@ export default {
|
||||
},
|
||||
is825() {
|
||||
return String(this.deptId || '').substring(0, 3) === '825'
|
||||
},
|
||||
is932Dept() {
|
||||
return String(this.deptId || '').substring(0, 3) === '932'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -364,7 +364,7 @@
|
||||
v-if="item.cmpmType == '贷款客户经理'"
|
||||
:label="`${item.cmpmType}:`"
|
||||
>
|
||||
<span>{{ item.cmpmUserList }}</span>
|
||||
<span>{{ is932Dept ? `${profile.belongUserName}-${profile.belongUserId}` : item.cmpmUserList }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -1663,7 +1663,7 @@ export default {
|
||||
CustContact
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['roles', 'userName']),
|
||||
...mapGetters(['roles', 'userName', 'deptId']),
|
||||
isHeadAdmin() {
|
||||
return this.roles.includes('headAdmin')
|
||||
},
|
||||
@@ -1675,6 +1675,10 @@ export default {
|
||||
isPrivate() {
|
||||
return this.roles.includes('headPrivate')
|
||||
},
|
||||
// 是否932开头部门
|
||||
is932Dept() {
|
||||
return String(this.deptId || '').substring(0, 3) === '932'
|
||||
},
|
||||
// 运管部
|
||||
isHeadOps() {
|
||||
return this.roles.includes('headOps')
|
||||
|
||||
@@ -235,10 +235,11 @@ export const privateColumnsNew825 = [
|
||||
{ prop: 'cfyxNum', label: '财富有效客户数', width: 150 },
|
||||
{ prop: 'yxxykNum', label: '有效信用卡数', width: 140 },
|
||||
{ prop: 'yxsbkNum', label: '有效社保卡户数', width: 150 },
|
||||
{ prop: 'twoTo3SbkNum', label: '二换三社保卡户数', width: 160 },
|
||||
{ prop: 'twoTo3SbkNum', label: '有效社保卡新增', width: 160 },
|
||||
{ prop: 'yljToSbkNum', label: '养老金迁移至社保卡户数', width: 180 },
|
||||
{ prop: 'fshlNum', label: '丰收互联客户数', width: 150 },
|
||||
{ prop: 'yxsdNum', label: '有效收单商户', width: 140 },
|
||||
{ prop: 'hxsdNum', label: '核心收单户数', width: 140 },
|
||||
{ prop: 'zf365rt', label: '近365天走访率', width: 140 },
|
||||
{ prop: 'zf180rt', label: '近180天走访率', width: 140 },
|
||||
{ prop: 'zf90rt', label: '近90天走访率', width: 140 },
|
||||
@@ -638,8 +639,9 @@ export const privateTotalColumnsNew825 = [
|
||||
{ prop: 'isGrhx', label: '是否个人核心客户', width: 140 },
|
||||
{ prop: 'isCfyx', label: '是否财富有效客户', width: 140 },
|
||||
{ prop: 'isYxsbk', label: '是否有效社保卡客户', width: 150 },
|
||||
{ prop: 'is2to3Sbk', label: '是否二换三社保卡', width: 150 },
|
||||
{ prop: 'is2to3Sbk', label: '是否有效社保卡新增', width: 150 },
|
||||
{ prop: 'isYljToSbk', label: '是否养老金迁移至社保卡', width: 180 },
|
||||
{ prop: 'isHxsd', label: '是否核心收单', width: 120 },
|
||||
{ prop: 'is365zf', label: '近365天有无走访', width: 140 },
|
||||
{ prop: 'is180zf', label: '近180天有无走访', width: 140 },
|
||||
{ prop: 'is90zf', label: '近90天有无走访', width: 140 },
|
||||
|
||||
@@ -22,11 +22,22 @@
|
||||
<el-radio label="0">静态客群</el-radio>
|
||||
<el-radio label="1">动态客群</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="form-tip">
|
||||
静态客群:创建后客户列表固定,除非手动更新
|
||||
<!-- <div class="form-tip">
|
||||
静态客群:创建后客户列表固定
|
||||
<br />
|
||||
动态客群:系统定期根据原始条件自动刷新客户列表
|
||||
</div>
|
||||
</div> -->
|
||||
</el-form-item>
|
||||
<el-form-item label="客群类型" prop="groupType">
|
||||
<el-radio-group v-model="form.groupType" :disabled="isEdit">
|
||||
<el-radio label="0">零售类</el-radio>
|
||||
<el-radio label="1">公司类</el-radio>
|
||||
</el-radio-group>
|
||||
<!-- <div class="form-tip">
|
||||
零售类:只能导入个人和商户客户
|
||||
<br />
|
||||
公司类:只能导入企业客户
|
||||
</div> -->
|
||||
</el-form-item>
|
||||
<el-form-item label="有效期" prop="validTime">
|
||||
<el-date-picker
|
||||
@@ -42,89 +53,103 @@
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" :rows="2" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="客群标签">
|
||||
<div class="tag-input-wrapper">
|
||||
<el-input
|
||||
v-model="tagInput"
|
||||
placeholder="输入标签后点击加号添加"
|
||||
style="width: calc(100% - 40px)"
|
||||
@keyup.enter.native="addTag"
|
||||
/>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="addTag" style="margin-left: 8px" />
|
||||
</div>
|
||||
<div class="tag-list" v-if="allTags.length > 0">
|
||||
<span class="tag-label">已有标签:</span>
|
||||
<el-tag
|
||||
v-for="tag in allTags"
|
||||
:key="tag"
|
||||
:type="selectedTags.includes(tag) ? 'primary' : 'info'"
|
||||
:effect="selectedTags.includes(tag) ? 'dark' : 'plain'"
|
||||
@click="toggleTag(tag)"
|
||||
style="cursor: pointer; margin-right: 8px; margin-bottom: 8px"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="selected-tags" v-if="selectedTags.length > 0">
|
||||
<span class="tag-label">已选标签:</span>
|
||||
<el-tag
|
||||
v-for="tag in selectedTags"
|
||||
:key="tag"
|
||||
closable
|
||||
@close="removeTag(tag)"
|
||||
style="margin-right: 8px; margin-bottom: 8px"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="开启共享">
|
||||
<el-switch v-model="shareEnabled" />
|
||||
</el-form-item>
|
||||
<el-form-item label="可见部门" v-if="shareEnabled">
|
||||
<el-select
|
||||
v-model="form.shareDeptIdList"
|
||||
v-model="shareDeptList"
|
||||
multiple
|
||||
filterable
|
||||
placeholder="请选择可见部门"
|
||||
style="width: 100%"
|
||||
popper-class="dept-select-popper"
|
||||
>
|
||||
<el-option
|
||||
v-for="dept in deptOptions"
|
||||
:key="dept.deptId"
|
||||
:label="dept.deptName"
|
||||
:value="dept.deptId"
|
||||
:value="String(dept.deptId)"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="创建方式" prop="createMode">
|
||||
<el-radio-group v-model="form.createMode" :disabled="isEdit">
|
||||
<el-radio label="1">模板导入</el-radio>
|
||||
<el-radio label="2">绩效网格</el-radio>
|
||||
<el-radio label="3">地理网格</el-radio>
|
||||
<el-radio label="4">绘制网格</el-radio>
|
||||
</el-radio-group>
|
||||
<!-- 模板导入 -->
|
||||
<el-form-item label="客户文件" prop="file">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
:on-change="handleFileChange"
|
||||
:auto-upload="false"
|
||||
:show-file-list="true"
|
||||
:limit="1"
|
||||
accept=".xlsx,.xls"
|
||||
>
|
||||
<el-button slot="trigger" size="small" icon="el-icon-upload">选择文件</el-button>
|
||||
<el-button size="small" type="text" @click.stop="downloadTemplate" style="margin-left: 15px">
|
||||
下载模板
|
||||
</el-button>
|
||||
<div slot="tip" class="el-upload__tip">
|
||||
仅支持Excel文件,文件大小不超过10MB
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 模板导入 -->
|
||||
<template v-if="form.createMode === '1'">
|
||||
<el-form-item label="客户文件" prop="file">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
:on-change="handleFileChange"
|
||||
:auto-upload="false"
|
||||
:show-file-list="true"
|
||||
:limit="1"
|
||||
accept=".xlsx,.xls"
|
||||
>
|
||||
<el-button slot="trigger" size="small" icon="el-icon-upload">选择文件</el-button>
|
||||
<el-button size="small" type="text" @click.stop="downloadTemplate" style="margin-left: 15px">
|
||||
下载模板
|
||||
</el-button>
|
||||
<div slot="tip" class="el-upload__tip">
|
||||
仅支持Excel文件,文件大小不超过10MB
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="匹配网格类型" prop="gridType">
|
||||
<el-radio-group v-model="form.gridType" @change="handleGridTypeChange">
|
||||
<el-radio label="0">绩效网格</el-radio>
|
||||
<!-- 暂时隐藏,后续版本开放
|
||||
<el-radio label="1">地理网格</el-radio>
|
||||
<el-radio label="2">绘制网格</el-radio>
|
||||
-->
|
||||
</el-radio-group>
|
||||
<div class="form-tip">
|
||||
系统将根据客户信息从所选网格匹配管户关系,匹配不上则保存空的管户关系
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 绩效网格 -->
|
||||
<template v-if="form.createMode === '2'">
|
||||
<el-form-item label="业务类型" prop="cmpmBizType">
|
||||
<el-select v-model="gridForm.cmpmBizType" placeholder="请选择业务类型" style="width: 100%" @change="handleCmpmBizTypeChange">
|
||||
<el-option label="零售" value="retail" />
|
||||
<el-option label="对公" value="corporate" />
|
||||
<el-option label="对公账户" value="corporate_account" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户经理" prop="userNames">
|
||||
<el-select
|
||||
v-model="gridForm.userNames"
|
||||
multiple
|
||||
filterable
|
||||
placeholder="请选择客户经理"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="user in userOptions"
|
||||
:key="user.userName"
|
||||
:label="user.nickName"
|
||||
:value="user.userName"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 地理网格 -->
|
||||
<template v-if="form.createMode === '3'">
|
||||
<!-- 地理网格筛选 - 暂时隐藏,后续版本开放
|
||||
<template v-if="form.gridType === '1'">
|
||||
<el-form-item label="网格级别">
|
||||
<el-radio-group v-model="regionQuery.gridLevel">
|
||||
<el-radio label="1">总行行政网格</el-radio>
|
||||
@@ -146,11 +171,11 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="选择网格">
|
||||
<el-select
|
||||
v-model="gridForm.regionGridIds"
|
||||
v-model="form.regionGridIds"
|
||||
multiple
|
||||
filterable
|
||||
collapse-tags
|
||||
placeholder="请先查询网格,然后选择"
|
||||
placeholder="请选择网格"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
@@ -162,15 +187,16 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
-->
|
||||
|
||||
<!-- 绘制网格 -->
|
||||
<template v-if="form.createMode === '4'">
|
||||
<el-form-item label="绘制网格" prop="drawGridIds">
|
||||
<!-- 绘制网格筛选 - 暂时隐藏,后续版本开放
|
||||
<template v-if="form.gridType === '2'">
|
||||
<el-form-item label="绘制网格">
|
||||
<el-select
|
||||
v-model="gridForm.drawGridIds"
|
||||
v-model="form.drawGridIds"
|
||||
multiple
|
||||
filterable
|
||||
placeholder="请选择绘制网格"
|
||||
placeholder="请选择网格"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
@@ -182,6 +208,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
-->
|
||||
</el-form>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
@@ -195,16 +222,14 @@
|
||||
|
||||
<script>
|
||||
import {
|
||||
createCustGroupByGrid,
|
||||
createCustGroupByTemplate,
|
||||
updateCustGroupByGrid,
|
||||
updateCustGroupByTemplate,
|
||||
downloadTemplate,
|
||||
getManagerList,
|
||||
getRegionGridListForGroup
|
||||
getRegionGridListForGroup,
|
||||
getCreateStatus,
|
||||
getAllGroupTags
|
||||
} from '@/api/group/custGroup'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { listUser } from '@/api/system/user'
|
||||
import { listDept } from '@/api/system/dept'
|
||||
import { getSimpleGridList } from '@/api/grid/list/gridlist'
|
||||
|
||||
@@ -231,8 +256,61 @@ export default {
|
||||
// 上传地址
|
||||
uploadUrl: process.env.VUE_APP_BASE_API + '/group/cust/createByTemplate',
|
||||
uploadHeaders: { Authorization: 'Bearer ' + getToken() },
|
||||
// 处理中提示
|
||||
processTipVisible: false
|
||||
// 表单数据
|
||||
form: {
|
||||
id: null,
|
||||
groupName: null,
|
||||
groupMode: '0',
|
||||
groupType: '0',
|
||||
groupStatus: '0',
|
||||
gridType: '0',
|
||||
regionGridIds: [],
|
||||
drawGridIds: [],
|
||||
shareEnabled: 0,
|
||||
shareDeptIdList: [],
|
||||
remark: null,
|
||||
validTime: null
|
||||
},
|
||||
// 共享开关
|
||||
shareEnabled: false,
|
||||
// 已选部门列表(字符串数组,用于el-select绑定)
|
||||
shareDeptList: [],
|
||||
// 上传文件
|
||||
uploadFile: null,
|
||||
// 表单验证规则
|
||||
rules: {
|
||||
groupName: [
|
||||
{ required: true, message: '请输入客群名称', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
groupMode: [{ required: true, message: '请选择客群模式', trigger: 'change' }],
|
||||
groupType: [{ required: true, message: '请选择客群类型', trigger: 'change' }],
|
||||
gridType: [{ required: true, message: '请选择匹配网格类型', trigger: 'change' }]
|
||||
},
|
||||
// 部门选项
|
||||
deptOptions: [],
|
||||
// 地理网格选项
|
||||
regionGridOptions: [],
|
||||
// 地理网格查询条件
|
||||
regionQuery: {
|
||||
gridLevel: '1',
|
||||
gridDutyType: null,
|
||||
gridName: null
|
||||
},
|
||||
// 地理网格加载状态
|
||||
regionLoading: false,
|
||||
// 绘制网格选项
|
||||
drawGridOptions: [],
|
||||
// 轮询定时器
|
||||
pollTimer: null,
|
||||
// 标签输入框内容
|
||||
tagInput: '',
|
||||
// 所有已有标签列表
|
||||
allTags: [],
|
||||
// 已选标签列表
|
||||
selectedTags: [],
|
||||
// 关闭弹窗时是否保留状态轮询
|
||||
keepPollingOnClose: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -247,66 +325,6 @@ export default {
|
||||
return '确 定'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 提交中状态
|
||||
submitting: false,
|
||||
// 上传地址
|
||||
uploadUrl: process.env.VUE_APP_BASE_API + '/group/cust/createByTemplate',
|
||||
uploadHeaders: { Authorization: 'Bearer ' + getToken() },
|
||||
// 处理中提示
|
||||
processTipVisible: false,
|
||||
// 表单数据
|
||||
form: {
|
||||
id: null,
|
||||
groupName: null,
|
||||
groupMode: '0',
|
||||
createMode: '1',
|
||||
groupStatus: '0',
|
||||
shareEnabled: 0,
|
||||
shareDeptIdList: [],
|
||||
remark: null,
|
||||
validTime: null
|
||||
},
|
||||
// 共享开关
|
||||
shareEnabled: false,
|
||||
// 网格表单数据
|
||||
gridForm: {
|
||||
gridType: '0',
|
||||
cmpmBizType: null,
|
||||
userNames: [],
|
||||
regionGridIds: [],
|
||||
drawGridIds: []
|
||||
},
|
||||
// 上传文件
|
||||
uploadFile: null,
|
||||
// 表单验证规则
|
||||
rules: {
|
||||
groupName: [
|
||||
{ required: true, message: '请输入客群名称', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
groupMode: [{ required: true, message: '请选择客群模式', trigger: 'change' }],
|
||||
createMode: [{ required: true, message: '请选择创建方式', trigger: 'change' }]
|
||||
},
|
||||
// 部门选项
|
||||
deptOptions: [],
|
||||
// 用户选项
|
||||
userOptions: [],
|
||||
// 地理网格选项
|
||||
regionGridOptions: [],
|
||||
// 地理网格查询条件
|
||||
regionQuery: {
|
||||
gridLevel: '1',
|
||||
gridDutyType: null,
|
||||
gridName: null
|
||||
},
|
||||
// 地理网格加载状态
|
||||
regionLoading: false,
|
||||
// 绘制网格选项
|
||||
drawGridOptions: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (val) {
|
||||
@@ -318,143 +336,142 @@ export default {
|
||||
if (val && Object.keys(val).length > 0) {
|
||||
this.form = { ...val }
|
||||
this.shareEnabled = val.shareEnabled === 1
|
||||
// 解析 shareDeptIds 字符串为 shareDeptIdList 数组
|
||||
// 解析 shareDeptIds 字符串为 shareDeptList 数组(保持字符串类型以匹配el-option的value)
|
||||
if (val.shareDeptIds) {
|
||||
this.form.shareDeptIdList = val.shareDeptIds.split(',').filter(id => id)
|
||||
this.shareDeptList = val.shareDeptIds.split(',').filter(id => id)
|
||||
} else {
|
||||
this.form.shareDeptIdList = []
|
||||
this.shareDeptList = []
|
||||
}
|
||||
// 解析网格ID
|
||||
if (val.regionGridIds) {
|
||||
this.form.regionGridIds = val.regionGridIds.split(',').map(id => parseInt(id)).filter(id => id)
|
||||
} else {
|
||||
this.form.regionGridIds = []
|
||||
}
|
||||
if (val.drawGridIds) {
|
||||
this.form.drawGridIds = val.drawGridIds.split(',').map(id => parseInt(id)).filter(id => id)
|
||||
} else {
|
||||
this.form.drawGridIds = []
|
||||
}
|
||||
// 解析标签
|
||||
if (val.groupTags) {
|
||||
this.selectedTags = val.groupTags.split(',').map(tag => tag.trim()).filter(tag => tag)
|
||||
} else {
|
||||
this.selectedTags = []
|
||||
}
|
||||
|
||||
// 反显网格数据(需要在 form.createMode watch 之后执行)
|
||||
// 反显网格数据
|
||||
this.$nextTick(() => {
|
||||
this.restoreGridData(val)
|
||||
})
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
'form.createMode'(val) {
|
||||
// 重置网格表单
|
||||
this.gridForm = {
|
||||
gridType: val === '2' ? '0' : val === '3' ? '1' : '2',
|
||||
regionGridIds: [],
|
||||
drawGridIds: []
|
||||
}
|
||||
// 切换到地理网格模式时,重置查询条件
|
||||
if (val === '3') {
|
||||
this.resetRegionQuery()
|
||||
}
|
||||
// 切换到绘制网格模式时,加载绘制网格列表
|
||||
if (val === '4') {
|
||||
this.loadDrawGridOptions()
|
||||
}
|
||||
},
|
||||
'gridForm.cmpmBizType'(val) {
|
||||
// 当业务类型改变时,清空已选择的客户经理
|
||||
if (val) {
|
||||
this.gridForm.userNames = []
|
||||
this.loadManagerOptions()
|
||||
}
|
||||
},
|
||||
'form.createStatus'(val) {
|
||||
// 监听创建状态变化,显示提示
|
||||
if (this.isEdit && val === '0') {
|
||||
this.processTipVisible = true
|
||||
} else if (this.processTipVisible) {
|
||||
this.processTipVisible = false
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadDeptOptions()
|
||||
this.loadAllTags()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearPollTimer()
|
||||
},
|
||||
methods: {
|
||||
/** 初始化 */
|
||||
init() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form && this.$refs.form.clearValidate()
|
||||
// 编辑模式下,恢复网格数据
|
||||
if (this.isEdit && this.groupData && Object.keys(this.groupData).length > 0) {
|
||||
this.restoreGridData(this.groupData)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/** 反显网格数据 */
|
||||
restoreGridData(data) {
|
||||
if (!this.isEdit) return
|
||||
if (!this.isEdit || !data.gridType) return
|
||||
|
||||
const createMode = String(data.createMode)
|
||||
// 根据创建方式反显网格数据
|
||||
if (createMode === '2' && data.gridType === '0') {
|
||||
// 绩效网格
|
||||
this.gridForm.gridType = '0'
|
||||
this.gridForm.cmpmBizType = data.cmpmBizType
|
||||
if (data.gridUserNames) {
|
||||
this.gridForm.userNames = data.gridUserNames.split(',').filter(n => n)
|
||||
// 加载客户经理选项
|
||||
this.loadManagerOptions()
|
||||
}
|
||||
} else if (createMode === '3' && data.gridType === '1') {
|
||||
// 地理网格 - 需要查询所有网格以便正确反显
|
||||
this.gridForm.gridType = '1'
|
||||
// 设置默认查询条件(获取所有网格)
|
||||
this.regionQuery = {
|
||||
gridLevel: '1',
|
||||
gridDutyType: null,
|
||||
gridName: null
|
||||
}
|
||||
if (data.gridType === '1') {
|
||||
this.resetRegionQuery()
|
||||
if (data.regionGridIds) {
|
||||
this.gridForm.regionGridIds = data.regionGridIds.split(',').map(id => parseInt(id)).filter(id => id)
|
||||
// 加载地理网格选项(无查询条件,获取全部)
|
||||
this.loadRegionGridOptions()
|
||||
}
|
||||
} else if (createMode === '4' && data.gridType === '2') {
|
||||
// 绘制网格
|
||||
this.gridForm.gridType = '2'
|
||||
if (data.drawGridIds) {
|
||||
this.gridForm.drawGridIds = data.drawGridIds.split(',').map(id => parseInt(id)).filter(id => id)
|
||||
// 加载绘制网格选项
|
||||
this.loadDrawGridOptions()
|
||||
}
|
||||
} else if (data.gridType === '2') {
|
||||
this.loadDrawGridOptions()
|
||||
}
|
||||
},
|
||||
|
||||
/** 加载部门选项 */
|
||||
loadDeptOptions() {
|
||||
listDept().then(response => {
|
||||
this.deptOptions = response.data || []
|
||||
// 将树形结构扁平化,以便el-select遍历
|
||||
this.deptOptions = this.flattenDeptList(response.data || [])
|
||||
}).catch(() => {
|
||||
this.deptOptions = []
|
||||
})
|
||||
},
|
||||
|
||||
/** 加载用户选项 */
|
||||
loadUserOptions() {
|
||||
listUser().then(response => {
|
||||
this.userOptions = response.rows || []
|
||||
/** 扁平化部门树 */
|
||||
flattenDeptList(list, result = []) {
|
||||
list.forEach(item => {
|
||||
result.push({ deptId: item.deptId, deptName: item.deptName })
|
||||
if (item.children && item.children.length > 0) {
|
||||
this.flattenDeptList(item.children, result)
|
||||
}
|
||||
})
|
||||
return result
|
||||
},
|
||||
|
||||
/** 加载所有已有标签 */
|
||||
loadAllTags() {
|
||||
getAllGroupTags().then(response => {
|
||||
this.allTags = response.data || []
|
||||
}).catch(() => {
|
||||
this.userOptions = []
|
||||
this.allTags = []
|
||||
})
|
||||
},
|
||||
|
||||
/** 根据业务类型加载客户经理选项 */
|
||||
loadManagerOptions() {
|
||||
if (!this.gridForm.cmpmBizType) {
|
||||
this.userOptions = []
|
||||
/** 添加标签 */
|
||||
addTag() {
|
||||
const tag = this.tagInput.trim()
|
||||
if (!tag) return
|
||||
if (this.selectedTags.includes(tag)) {
|
||||
this.$message.warning('该标签已添加')
|
||||
return
|
||||
}
|
||||
getManagerList(this.gridForm.cmpmBizType).then(response => {
|
||||
this.userOptions = response.data || []
|
||||
}).catch(() => {
|
||||
this.userOptions = []
|
||||
})
|
||||
this.selectedTags.push(tag)
|
||||
// 如果是新标签,添加到allTags中
|
||||
if (!this.allTags.includes(tag)) {
|
||||
this.allTags.push(tag)
|
||||
}
|
||||
this.tagInput = ''
|
||||
},
|
||||
|
||||
/** 业务类型改变处理 */
|
||||
handleCmpmBizTypeChange(val) {
|
||||
// 清空已选择的客户经理
|
||||
this.gridForm.userNames = []
|
||||
/** 切换标签选中状态 */
|
||||
toggleTag(tag) {
|
||||
const index = this.selectedTags.indexOf(tag)
|
||||
if (index > -1) {
|
||||
this.selectedTags.splice(index, 1)
|
||||
} else {
|
||||
this.selectedTags.push(tag)
|
||||
}
|
||||
},
|
||||
|
||||
/** 移除已选标签 */
|
||||
removeTag(tag) {
|
||||
const index = this.selectedTags.indexOf(tag)
|
||||
if (index > -1) {
|
||||
this.selectedTags.splice(index, 1)
|
||||
}
|
||||
},
|
||||
|
||||
/** 网格类型改变处理 */
|
||||
handleGridTypeChange(val) {
|
||||
if (val === '1') {
|
||||
this.resetRegionQuery()
|
||||
} else if (val === '2') {
|
||||
this.loadDrawGridOptions()
|
||||
}
|
||||
// 清空网格选择
|
||||
this.form.regionGridIds = []
|
||||
this.form.drawGridIds = []
|
||||
},
|
||||
|
||||
/** 加载地理网格选项 */
|
||||
@@ -486,7 +503,7 @@ export default {
|
||||
gridDutyType: null,
|
||||
gridName: null
|
||||
}
|
||||
this.gridForm.regionGridIds = []
|
||||
this.form.regionGridIds = []
|
||||
},
|
||||
|
||||
/** 加载绘制网格选项 */
|
||||
@@ -534,130 +551,138 @@ export default {
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
if (!this.uploadFile && !this.isEdit) {
|
||||
this.$modal.msgWarning('请选择要上传的文件')
|
||||
return
|
||||
}
|
||||
|
||||
// 处理共享设置
|
||||
this.form.shareEnabled = this.shareEnabled ? 1 : 0
|
||||
// 转换 shareDeptIdList 数组为 shareDeptIds 逗号分隔字符串
|
||||
this.form.shareDeptIds = this.form.shareDeptIdList.join(',')
|
||||
this.form.shareDeptIds = this.shareDeptList.join(',')
|
||||
// 转换选中的标签为逗号分隔字符串
|
||||
this.form.groupTags = this.selectedTags.join(',')
|
||||
// 转换网格ID数组为逗号分隔字符串
|
||||
this.form.regionGridIds = this.form.regionGridIds.join(',')
|
||||
this.form.drawGridIds = this.form.drawGridIds.join(',')
|
||||
|
||||
// 根据创建方式处理提交数据
|
||||
if (this.form.createMode === '1') {
|
||||
this.handleTemplateSubmit()
|
||||
this.submitting = true
|
||||
|
||||
// 构建表单数据
|
||||
const formData = new FormData()
|
||||
formData.append('dto', JSON.stringify(this.form))
|
||||
if (this.uploadFile) {
|
||||
formData.append('file', this.uploadFile)
|
||||
}
|
||||
|
||||
if (this.isEdit) {
|
||||
// 编辑模式
|
||||
updateCustGroupByTemplate(formData).then(response => {
|
||||
this.submitting = false
|
||||
if (response.msg === '客群更新成功') {
|
||||
// 没有上传文件,直接更新成功
|
||||
this.$modal.msgSuccess('客群更新成功')
|
||||
this.$emit('submit', { id: this.form.id, refresh: true })
|
||||
} else {
|
||||
// 有上传文件,后台正在处理
|
||||
this.$modal.msgSuccess('客群更新任务已提交,后台正在处理')
|
||||
this.keepPollingOnClose = true
|
||||
this.startPollingStatus(this.form.id)
|
||||
}
|
||||
this.handleClose()
|
||||
}).catch(() => {
|
||||
this.submitting = false
|
||||
})
|
||||
} else {
|
||||
this.handleGridSubmit()
|
||||
// 新增模式
|
||||
createCustGroupByTemplate(formData).then(response => {
|
||||
const groupId = response && response.data ? response.data : null
|
||||
if (!groupId) {
|
||||
this.$modal.msgError('客群创建成功但未获取到任务ID,请稍后在列表中查看状态')
|
||||
this.submitting = false
|
||||
this.handleClose()
|
||||
return
|
||||
}
|
||||
this.$modal.msgSuccess('客群创建任务已提交,后台正在处理')
|
||||
this.submitting = false
|
||||
this.keepPollingOnClose = true
|
||||
this.startPollingStatus(groupId)
|
||||
this.handleClose()
|
||||
}).catch(() => {
|
||||
this.submitting = false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/** 模板导入提交 */
|
||||
handleTemplateSubmit() {
|
||||
if (!this.uploadFile && !this.isEdit) {
|
||||
this.$modal.msgWarning('请选择要上传的文件')
|
||||
return
|
||||
}
|
||||
|
||||
this.submitting = true
|
||||
|
||||
// 构建表单数据
|
||||
const formData = new FormData()
|
||||
formData.append('dto', JSON.stringify(this.form))
|
||||
if (this.uploadFile) {
|
||||
formData.append('file', this.uploadFile)
|
||||
}
|
||||
|
||||
if (this.isEdit) {
|
||||
// 编辑模式:重新导入模板文件
|
||||
updateCustGroupByTemplate(formData).then(response => {
|
||||
this.$modal.msgSuccess('客群更新中,请稍后刷新查看')
|
||||
this.submitting = false
|
||||
this.$emit('submit', { id: this.form.id })
|
||||
this.handleClose()
|
||||
}).catch(() => {
|
||||
this.submitting = false
|
||||
})
|
||||
} else {
|
||||
// 新增模式
|
||||
createCustGroupByTemplate(formData).then(response => {
|
||||
this.$modal.msgSuccess('客群创建中,请稍后刷新查看')
|
||||
this.submitting = false
|
||||
this.$emit('submit', { id: response.data })
|
||||
this.handleClose()
|
||||
}).catch(() => {
|
||||
this.submitting = false
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/** 网格导入提交 */
|
||||
handleGridSubmit() {
|
||||
this.submitting = true
|
||||
|
||||
// 构建提交数据
|
||||
const submitData = {
|
||||
custGroup: { ...this.form },
|
||||
gridType: this.form.createMode === '2' ? '0' : this.form.createMode === '3' ? '1' : '2',
|
||||
cmpmBizType: this.gridForm.cmpmBizType,
|
||||
userNames: this.gridForm.userNames,
|
||||
regionGridIds: this.gridForm.regionGridIds,
|
||||
drawGridIds: this.gridForm.drawGridIds
|
||||
}
|
||||
|
||||
if (this.isEdit) {
|
||||
// 编辑模式:重新导入网格
|
||||
updateCustGroupByGrid(submitData).then(response => {
|
||||
// 使用后端返回的消息
|
||||
const msg = response.msg || '客群更新成功'
|
||||
if (msg.includes('更新中')) {
|
||||
this.$modal.msgSuccess('客群更新中,请稍后刷新查看')
|
||||
} else {
|
||||
this.$modal.msgSuccess(msg)
|
||||
}
|
||||
this.submitting = false
|
||||
this.$emit('submit', { id: this.form.id })
|
||||
this.handleClose()
|
||||
}).catch(() => {
|
||||
this.submitting = false
|
||||
})
|
||||
} else {
|
||||
// 新增模式
|
||||
createCustGroupByGrid(submitData).then(response => {
|
||||
this.$modal.msgSuccess('客群创建中,请稍后刷新查看')
|
||||
this.submitting = false
|
||||
this.$emit('submit', { id: response.data })
|
||||
this.handleClose()
|
||||
}).catch(() => {
|
||||
this.submitting = false
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/** 关闭弹窗 */
|
||||
handleClose() {
|
||||
this.$emit('update:visible', false)
|
||||
this.resetForm()
|
||||
},
|
||||
|
||||
/** 开始轮询创建状态 */
|
||||
startPollingStatus(groupId) {
|
||||
if (!groupId || groupId === 'undefined' || groupId === 'null') {
|
||||
return
|
||||
}
|
||||
this.clearPollTimer()
|
||||
// 每30秒轮询一次
|
||||
this.pollTimer = setInterval(() => {
|
||||
getCreateStatus(groupId).then(res => {
|
||||
const status = res.data
|
||||
if (status === '1') {
|
||||
// 创建成功
|
||||
this.clearPollTimer()
|
||||
this.keepPollingOnClose = false
|
||||
window.dispatchEvent(new Event('notice-center-refresh'))
|
||||
this.$modal.msgSuccess('客群导入完成')
|
||||
this.$emit('submit', { id: groupId, refresh: true })
|
||||
} else if (status === '2') {
|
||||
// 创建失败
|
||||
this.clearPollTimer()
|
||||
this.keepPollingOnClose = false
|
||||
window.dispatchEvent(new Event('notice-center-refresh'))
|
||||
this.$modal.msgError('客群导入失败,请查看消息中心了解详情')
|
||||
}
|
||||
}).catch(() => {
|
||||
// 查询失败,继续轮询
|
||||
})
|
||||
}, 30000)
|
||||
},
|
||||
|
||||
/** 清除轮询定时器 */
|
||||
clearPollTimer() {
|
||||
if (this.pollTimer) {
|
||||
clearInterval(this.pollTimer)
|
||||
this.pollTimer = null
|
||||
}
|
||||
},
|
||||
|
||||
/** 重置表单 */
|
||||
resetForm() {
|
||||
if (!this.keepPollingOnClose) {
|
||||
this.clearPollTimer()
|
||||
}
|
||||
this.form = {
|
||||
id: null,
|
||||
groupName: null,
|
||||
groupMode: '0',
|
||||
createMode: '1',
|
||||
groupType: '0',
|
||||
groupStatus: '0',
|
||||
gridType: '0',
|
||||
regionGridIds: [],
|
||||
drawGridIds: [],
|
||||
shareEnabled: 0,
|
||||
shareDeptIdList: [],
|
||||
remark: null,
|
||||
validTime: null
|
||||
}
|
||||
this.shareEnabled = false
|
||||
this.gridForm = {
|
||||
gridType: '0',
|
||||
cmpmBizType: null,
|
||||
userNames: [],
|
||||
regionGridIds: [],
|
||||
drawGridIds: []
|
||||
}
|
||||
this.shareDeptList = []
|
||||
this.tagInput = ''
|
||||
this.selectedTags = []
|
||||
this.uploadFile = null
|
||||
if (this.$refs.upload) {
|
||||
this.$refs.upload.clearFiles()
|
||||
@@ -677,4 +702,31 @@ export default {
|
||||
line-height: 1.5;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.tag-input-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tag-list,
|
||||
.selected-tags {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tag-label {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
/* 解决弹窗内下拉框被遮挡的问题 */
|
||||
.dept-select-popper {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -36,19 +36,51 @@
|
||||
<div class="main_table">
|
||||
<el-table v-loading="loading" :data="memberList">
|
||||
<el-table-column label="序号" type="index" width="60" align="center" :index="indexMethod" />
|
||||
<el-table-column label="客户类型" align="center" width="100">
|
||||
<el-table-column label="存量状态" align="center" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.isExisting" size="small" type="success">存量</el-tag>
|
||||
<el-tag v-else size="small" type="danger">非存量</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="客户类型" align="center" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.custType === '0'" size="small">个人</el-tag>
|
||||
<el-tag v-else-if="scope.row.custType === '1'" size="small" type="warning">商户</el-tag>
|
||||
<el-tag v-else-if="scope.row.custType === '2'" size="small" type="success">企业</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="客户号" prop="custId" width="150" />
|
||||
<el-table-column label="客户姓名" prop="custName" width="120" />
|
||||
<el-table-column label="客户号" prop="custId" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleCustClick(scope.row)">{{ scope.row.custId }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="客户姓名" prop="custName" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleCustClick(scope.row)">{{ scope.row.custName || '-' }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="身份证号" prop="custIdc" show-overflow-tooltip />
|
||||
<el-table-column label="统信码" prop="socialCreditCode" show-overflow-tooltip />
|
||||
<el-table-column label="客户经理" prop="nickName" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.nickName">{{ scope.row.nickName }}</span>
|
||||
<span v-else class="text-muted">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所属网点" prop="outletName" width="150">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.outletName">{{ scope.row.outletName }}</span>
|
||||
<span v-else class="text-muted">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所属支行" prop="branchName" width="150">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.branchName">{{ scope.row.branchName }}</span>
|
||||
<span v-else class="text-muted">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="添加时间" prop="createTime" width="180" />
|
||||
<el-table-column v-if="isMineView" label="操作" align="center" width="100" fixed="right">
|
||||
<el-table-column v-if="isMineView" label="操作" align="center" width="80" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="handleRemove(scope.row)">移除</el-button>
|
||||
</template>
|
||||
@@ -155,11 +187,45 @@ export default {
|
||||
|
||||
/** 返回 */
|
||||
goBack() {
|
||||
const fromPerformance = this.$route.query.fromPerformance
|
||||
if (fromPerformance === '1') {
|
||||
// 从网格业绩统计页进入,返回网格业绩统计页的客群报表
|
||||
this.$router.push({
|
||||
path: '/center/performance/list',
|
||||
query: { isActive: '8' }
|
||||
})
|
||||
} else {
|
||||
// 从客群列表进入,返回客群列表
|
||||
this.$router.push({
|
||||
path: '/group/custGroup',
|
||||
query: {
|
||||
tab: this.viewType,
|
||||
refresh: Date.now()
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/** 点击客户号/姓名跳转360视图 */
|
||||
handleCustClick(row) {
|
||||
const custType = row.custType
|
||||
let path = ''
|
||||
if (custType === '0') {
|
||||
// 个人客户
|
||||
path = '/360charts/indexcharts'
|
||||
} else if (custType === '1') {
|
||||
// 商户
|
||||
path = '/360charts/commercial/'
|
||||
} else if (custType === '2') {
|
||||
// 企业
|
||||
path = '/360charts/firm/'
|
||||
}
|
||||
this.$router.push({
|
||||
path: '/group/custGroup',
|
||||
path: path,
|
||||
query: {
|
||||
tab: this.viewType,
|
||||
refresh: Date.now()
|
||||
custId: row.custId,
|
||||
selectedTab: custType,
|
||||
backUrl: '/group/custGroup'
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -214,5 +280,9 @@ export default {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -35,19 +35,6 @@
|
||||
<el-option label="动态" value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建方式" prop="createMode">
|
||||
<el-select
|
||||
v-model="queryParams.createMode"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 150px"
|
||||
>
|
||||
<el-option label="模板导入" value="1" />
|
||||
<el-option label="绩效网格" value="2" />
|
||||
<el-option label="地理网格" value="3" />
|
||||
<el-option label="绘制网格" value="4" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="客群状态" prop="groupStatus">
|
||||
<el-select
|
||||
v-model="queryParams.groupStatus"
|
||||
@@ -59,6 +46,22 @@
|
||||
<el-option label="已禁用" value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="客群标签" prop="groupTags">
|
||||
<el-select
|
||||
v-model="queryParams.groupTags"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 150px"
|
||||
>
|
||||
<el-option
|
||||
v-for="tag in allTags"
|
||||
:key="tag"
|
||||
:label="tag"
|
||||
:value="tag"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery">
|
||||
搜索
|
||||
@@ -104,31 +107,38 @@
|
||||
width="55"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column label="客群名称" prop="groupName" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="客群模式" align="center" width="100">
|
||||
<el-table-column label="客群名称" prop="groupName" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="客群模式" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.groupMode === '0'" type="info" size="small">静态</el-tag>
|
||||
<el-tag v-else-if="scope.row.groupMode === '1'" type="success" size="small">动态</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建方式" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.createMode === '1'">模板导入</span>
|
||||
<span v-else-if="scope.row.createMode === '2'">绩效网格</span>
|
||||
<span v-else-if="scope.row.createMode === '3'">地理网格</span>
|
||||
<span v-else-if="scope.row.createMode === '4'">绘制网格</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="客户数量" align="center" prop="custCount" width="100" />
|
||||
<el-table-column label="客群状态" align="center" width="100">
|
||||
<el-table-column label="客户数量" align="center" prop="custCount" width="120" />
|
||||
<el-table-column label="客群状态" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.groupStatus === '0'" type="success" size="small">正常</el-tag>
|
||||
<el-tag v-else-if="scope.row.groupStatus === '1'" type="danger" size="small">已禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="客群标签" min-width="150">
|
||||
<template slot-scope="scope">
|
||||
<template v-if="scope.row.groupTags">
|
||||
<el-tag
|
||||
v-for="tag in scope.row.groupTags.split(',')"
|
||||
:key="tag"
|
||||
size="small"
|
||||
style="margin-right: 5px; margin-bottom: 3px"
|
||||
>
|
||||
{{ tag.trim() }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建者" prop="nickName" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="创建时间" prop="createTime" width="180" />
|
||||
<el-table-column label="操作" align="center" width="180" fixed="right">
|
||||
<el-table-column label="备注" prop="remark" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" width="200" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
@@ -179,7 +189,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listCustGroup, getCustGroup, deleteCustGroup } from '@/api/group/custGroup'
|
||||
import { listCustGroup, getCustGroup, deleteCustGroup, getAllGroupTags } from '@/api/group/custGroup'
|
||||
import CreateDialog from './components/create-dialog'
|
||||
|
||||
export default {
|
||||
@@ -204,10 +214,12 @@ export default {
|
||||
pageSize: 10,
|
||||
groupName: null,
|
||||
groupMode: null,
|
||||
createMode: null,
|
||||
groupStatus: null,
|
||||
groupTags: null,
|
||||
viewType: 'mine'
|
||||
}
|
||||
},
|
||||
// 所有标签列表
|
||||
allTags: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -218,6 +230,7 @@ export default {
|
||||
created() {
|
||||
this.activeTab = this.$route.query.tab || 'mine'
|
||||
this.getList()
|
||||
this.loadAllTags()
|
||||
},
|
||||
watch: {
|
||||
'$route.query.refresh'() {
|
||||
@@ -261,6 +274,15 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
/** 加载所有标签列表 */
|
||||
loadAllTags() {
|
||||
getAllGroupTags().then(response => {
|
||||
this.allTags = response.data || []
|
||||
}).catch(() => {
|
||||
this.allTags = []
|
||||
})
|
||||
},
|
||||
|
||||
handleTabChange() {
|
||||
this.ids = []
|
||||
this.single = true
|
||||
@@ -323,6 +345,12 @@ export default {
|
||||
this.$modal.confirm('是否确认删除选中的客群?').then(() => {
|
||||
return deleteCustGroup(ids)
|
||||
}).then(() => {
|
||||
if (this.groupList.length <= ids.length && this.queryParams.pageNum > 1) {
|
||||
this.queryParams.pageNum -= 1
|
||||
}
|
||||
this.ids = []
|
||||
this.single = true
|
||||
this.multiple = true
|
||||
this.refreshList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {})
|
||||
@@ -339,7 +367,6 @@ export default {
|
||||
id: null,
|
||||
groupName: null,
|
||||
groupMode: '0',
|
||||
createMode: null,
|
||||
groupStatus: '0',
|
||||
shareEnabled: 0,
|
||||
shareDeptIdList: [],
|
||||
|
||||
275
ruoyi-ui/src/views/group/performance/custom/index.vue
Normal file
275
ruoyi-ui/src/views/group/performance/custom/index.vue
Normal file
@@ -0,0 +1,275 @@
|
||||
<template>
|
||||
<div class="customer-wrap">
|
||||
<div class="content-box">
|
||||
<div class="form-box">
|
||||
<el-form ref="searchForm" :model="searchForm">
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="客户名称" prop="custName" label-width="80px">
|
||||
<el-input
|
||||
v-model="searchForm.custName"
|
||||
clearable
|
||||
@keyup.enter.native="handleSearch"
|
||||
@clear="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="selectedTab === '1'" :span="6">
|
||||
<el-form-item label="证件号" prop="custIdc" label-width="80px">
|
||||
<el-input
|
||||
v-model="searchForm.custIdc"
|
||||
clearable
|
||||
@keyup.enter.native="handleSearch"
|
||||
@clear="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-else :span="6">
|
||||
<el-form-item label="统一信用码" prop="socialCreditCode" label-width="100px">
|
||||
<el-input
|
||||
v-model="searchForm.socialCreditCode"
|
||||
clearable
|
||||
@keyup.enter.native="handleSearch"
|
||||
@clear="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5" :offset="1" style="text-align: left">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="operate-btn">
|
||||
<el-button @click="returnLastPage">返回上一级</el-button>
|
||||
<el-button type="primary" @click="handleDownload">导出</el-button>
|
||||
</div>
|
||||
|
||||
<div class="remark">
|
||||
<span>统计日期:<span class="span-value">{{ dt }}</span></span>
|
||||
<span>客群名称:<span class="span-value">{{ groupName }}</span></span>
|
||||
<span>客群模式:<span class="span-value">{{ groupModeText }}</span></span>
|
||||
</div>
|
||||
|
||||
<div class="main_table">
|
||||
<el-table v-loading="loading" :data="tableData" style="width: 100%">
|
||||
<el-table-column
|
||||
v-for="(item, index) in tableColumns"
|
||||
:key="index"
|
||||
align="center"
|
||||
:prop="item.prop"
|
||||
:label="item.label"
|
||||
show-overflow-tooltip
|
||||
:width="item.width || 120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
v-if="item.prop === 'custName'"
|
||||
type="text"
|
||||
class="special-btn"
|
||||
@click="openCustomer(scope.row)"
|
||||
>
|
||||
{{ scope.row[item.prop] || '-' }}
|
||||
</el-button>
|
||||
<span v-else>{{ scope.row[item.prop] || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="pageSize"
|
||||
layout="->,total,prev,pager,next,sizes"
|
||||
:total="total"
|
||||
:current-page="pageNum"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getGroupPerformanceLsCustList,
|
||||
getGroupPerformanceGsCustList,
|
||||
exportGroupPerformanceLsCust,
|
||||
exportGroupPerformanceGsCust
|
||||
} from '@/api/group/performance';
|
||||
import { retailDetailColumns, publicDetailColumns, groupModeDict } from '../list/list';
|
||||
import { downloadFiles } from '@/utils';
|
||||
|
||||
export default {
|
||||
name: 'GroupPerformanceCustom',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
tableData: [],
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
tableColumns: [],
|
||||
selectedTab: '1',
|
||||
dt: '',
|
||||
groupId: '',
|
||||
groupName: '',
|
||||
groupMode: '',
|
||||
searchForm: {
|
||||
custName: '',
|
||||
custIdc: '',
|
||||
socialCreditCode: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
groupModeText() {
|
||||
return groupModeDict[this.groupMode] || '-';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const { type, dt, groupId, groupName, groupMode } = this.$route.query;
|
||||
this.selectedTab = type || '1';
|
||||
this.dt = dt || '';
|
||||
this.groupId = groupId || '';
|
||||
this.groupName = groupName || '';
|
||||
this.groupMode = groupMode || '';
|
||||
this.tableColumns = this.selectedTab === '1' ? retailDetailColumns : publicDetailColumns;
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true;
|
||||
const api = this.selectedTab === '1' ? getGroupPerformanceLsCustList : getGroupPerformanceGsCustList;
|
||||
const params = {
|
||||
groupId: this.groupId,
|
||||
dt: this.dt,
|
||||
custName: this.searchForm.custName,
|
||||
custIdc: this.searchForm.custIdc,
|
||||
socialCreditCode: this.searchForm.socialCreditCode,
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize
|
||||
};
|
||||
api(params).then(res => {
|
||||
this.tableData = res.rows;
|
||||
this.total = res.total;
|
||||
this.loading = false;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleSearch() {
|
||||
this.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleReset() {
|
||||
this.searchForm = {
|
||||
custName: '',
|
||||
custIdc: '',
|
||||
socialCreditCode: ''
|
||||
};
|
||||
this.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size;
|
||||
this.getList();
|
||||
},
|
||||
handleCurrentChange(page) {
|
||||
this.pageNum = page;
|
||||
this.getList();
|
||||
},
|
||||
handleDownload() {
|
||||
const api = this.selectedTab === '1' ? exportGroupPerformanceLsCust : exportGroupPerformanceGsCust;
|
||||
const fileName = this.selectedTab === '1' ? '零售客群客户明细' : '公司客群客户明细';
|
||||
api({
|
||||
groupId: this.groupId,
|
||||
dt: this.dt,
|
||||
custName: this.searchForm.custName,
|
||||
custIdc: this.searchForm.custIdc,
|
||||
socialCreditCode: this.searchForm.socialCreditCode
|
||||
}).then(res => {
|
||||
downloadFiles(res, `${fileName}_${new Date().getTime()}.xlsx`);
|
||||
});
|
||||
},
|
||||
returnLastPage() {
|
||||
this.$router.replace({
|
||||
path: '/center/groupPerformance/list'
|
||||
});
|
||||
},
|
||||
openCustomer(row) {
|
||||
const custType = row.custType;
|
||||
let path = '';
|
||||
const rawId = this.selectedTab === '1' ? row.custIdc : row.socialCreditCode;
|
||||
const custId = rawId ? (custType === '0' ? `101${rawId}` : `202${rawId}`) : '';
|
||||
if (custType === '0') {
|
||||
path = '/360charts/indexcharts';
|
||||
} else if (custType === '1') {
|
||||
path = '/360charts/commercial/';
|
||||
} else if (custType === '2') {
|
||||
path = '/360charts/firm/';
|
||||
}
|
||||
if (!path || !custId) {
|
||||
return;
|
||||
}
|
||||
this.$router.push({
|
||||
path: path,
|
||||
query: {
|
||||
custId,
|
||||
selectedTab: custType,
|
||||
backUrl: '/center/groupPerformance/list'
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.customer-wrap {
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 3px 8px 0 #00000017;
|
||||
}
|
||||
|
||||
.content-box {
|
||||
padding: 20px 24px 24px;
|
||||
}
|
||||
|
||||
.operate-btn {
|
||||
margin-bottom: 12px;
|
||||
|
||||
.el-button + .el-button {
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.remark {
|
||||
margin-bottom: 12px;
|
||||
color: #666666;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.span-value {
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.main_table {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
::v-deep .el-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep .el-pagination {
|
||||
margin-top: 15px;
|
||||
}
|
||||
</style>
|
||||
294
ruoyi-ui/src/views/group/performance/list/index.vue
Normal file
294
ruoyi-ui/src/views/group/performance/list/index.vue
Normal file
@@ -0,0 +1,294 @@
|
||||
<template>
|
||||
<div class="customer-wrap">
|
||||
<el-radio-group
|
||||
v-model="selectedTab"
|
||||
class="header-radio"
|
||||
@input="handleTabChange"
|
||||
>
|
||||
<el-radio-button
|
||||
label="1"
|
||||
:disabled="isPublic"
|
||||
:class="{ 'btn-disabled': isPublic }"
|
||||
>零售部</el-radio-button>
|
||||
<el-radio-button
|
||||
label="2"
|
||||
:disabled="isPrivate"
|
||||
:class="{ 'btn-disabled': isPrivate }"
|
||||
>公司部</el-radio-button>
|
||||
</el-radio-group>
|
||||
|
||||
<div class="content-box">
|
||||
<div class="form-box">
|
||||
<el-form ref="searchForm" :model="searchForm">
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="客群名称" prop="groupName" label-width="80px">
|
||||
<el-input
|
||||
v-model="searchForm.groupName"
|
||||
clearable
|
||||
@keyup.enter.native="handleSearch"
|
||||
@clear="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="统计日期" prop="dt" label-width="80px">
|
||||
<el-date-picker
|
||||
v-model="searchForm.dt"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
:clearable="false"
|
||||
:picker-options="pickerOptions"
|
||||
@change="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4" style="text-align: right">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<el-button type="primary" @click="handleDownload">导出</el-button>
|
||||
</div>
|
||||
|
||||
<div class="main_table">
|
||||
<el-table
|
||||
:key="tableKey"
|
||||
v-loading="loading"
|
||||
:data="tableData"
|
||||
style="width: 100%"
|
||||
max-height="650"
|
||||
>
|
||||
<el-table-column
|
||||
v-for="(item, index) in tableColumns"
|
||||
:key="index"
|
||||
align="center"
|
||||
:prop="item.prop"
|
||||
:label="item.label"
|
||||
show-overflow-tooltip
|
||||
:width="item.width || 120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="item.dict">{{ item.dict[scope.row[item.prop]] || '-' }}</span>
|
||||
<span v-else>{{ scope.row[item.prop] || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作" width="100" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleView(scope.row)">客户明细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="pageSize"
|
||||
layout="->,total,prev,pager,next,sizes"
|
||||
:total="total"
|
||||
:current-page="pageNum"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getGroupPerformanceLsList,
|
||||
getGroupPerformanceGsList,
|
||||
exportGroupPerformanceLs,
|
||||
exportGroupPerformanceGs
|
||||
} from '@/api/group/performance';
|
||||
import { retailColumns, publicColumns } from './list';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadFiles } from '@/utils';
|
||||
|
||||
export default {
|
||||
name: 'GroupPerformanceList',
|
||||
data() {
|
||||
return {
|
||||
pickerOptions: {
|
||||
disabledDate(time) {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
return time.getTime() >= today.getTime();
|
||||
}
|
||||
},
|
||||
selectedTab: '1',
|
||||
loading: false,
|
||||
tableData: [],
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
tableColumns: [],
|
||||
tableKey: 'group-performance-1',
|
||||
searchForm: {
|
||||
groupName: '',
|
||||
dt: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['roles']),
|
||||
isPublic() {
|
||||
return this.roles.includes('headPublic');
|
||||
},
|
||||
isPrivate() {
|
||||
return this.roles.includes('headPrivate');
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 1);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
this.searchForm.dt = `${year}-${month}-${day}`;
|
||||
if (this.isPublic) {
|
||||
this.selectedTab = '2';
|
||||
} else if (this.isPrivate) {
|
||||
this.selectedTab = '1';
|
||||
}
|
||||
this.updateColumns();
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
updateColumns() {
|
||||
this.tableColumns = this.selectedTab === '1' ? retailColumns : publicColumns;
|
||||
this.tableKey = `group-performance-${this.selectedTab}`;
|
||||
},
|
||||
getList() {
|
||||
this.loading = true;
|
||||
const api = this.selectedTab === '1' ? getGroupPerformanceLsList : getGroupPerformanceGsList;
|
||||
api({
|
||||
...this.searchForm,
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize
|
||||
}).then(res => {
|
||||
this.tableData = res.rows;
|
||||
this.total = res.total;
|
||||
this.loading = false;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleTabChange() {
|
||||
this.updateColumns();
|
||||
this.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleReset() {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 1);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
this.searchForm = {
|
||||
groupName: '',
|
||||
dt: `${year}-${month}-${day}`
|
||||
};
|
||||
this.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size;
|
||||
this.getList();
|
||||
},
|
||||
handleCurrentChange(page) {
|
||||
this.pageNum = page;
|
||||
this.getList();
|
||||
},
|
||||
handleView(row) {
|
||||
this.$router.push({
|
||||
path: '/center/groupPerformance/custom',
|
||||
query: {
|
||||
type: this.selectedTab,
|
||||
dt: row.dt,
|
||||
groupId: row.groupId,
|
||||
groupName: row.groupName,
|
||||
groupMode: row.groupMode
|
||||
}
|
||||
});
|
||||
},
|
||||
handleDownload() {
|
||||
const api = this.selectedTab === '1' ? exportGroupPerformanceLs : exportGroupPerformanceGs;
|
||||
const fileName = this.selectedTab === '1' ? '零售客群业绩汇总' : '公司客群业绩汇总';
|
||||
api(this.searchForm).then(res => {
|
||||
downloadFiles(res, `${fileName}_${new Date().getTime()}.xlsx`);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.customer-wrap {
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
border-radius: 16px 16px 0 0;
|
||||
box-shadow: 0 3px 8px 0 #00000017;
|
||||
|
||||
.header-radio {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
|
||||
.btn-disabled {
|
||||
::v-deep .el-radio-button__inner {
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
}
|
||||
|
||||
.el-radio-button {
|
||||
flex: 1;
|
||||
|
||||
::v-deep .el-radio-button__inner {
|
||||
width: 100%;
|
||||
border: none;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.44px;
|
||||
line-height: 25px;
|
||||
font-size: 16px;
|
||||
color: #666666;
|
||||
padding: 11px 0 12px 0;
|
||||
}
|
||||
|
||||
::v-deep .el-radio-button__orig-radio:checked + .el-radio-button__inner {
|
||||
background-color: #4886f8;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-box {
|
||||
padding: 20px 24px 24px;
|
||||
}
|
||||
|
||||
.main_table {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
::v-deep .el-date-editor,
|
||||
::v-deep .el-input,
|
||||
::v-deep .el-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep .el-pagination {
|
||||
margin-top: 15px;
|
||||
}
|
||||
</style>
|
||||
194
ruoyi-ui/src/views/group/performance/list/list.js
Normal file
194
ruoyi-ui/src/views/group/performance/list/list.js
Normal file
@@ -0,0 +1,194 @@
|
||||
export const groupModeDict = {
|
||||
'0': '静态',
|
||||
'1': '动态'
|
||||
};
|
||||
|
||||
export const retailColumns = [
|
||||
{ prop: 'dt', label: '统计日期', width: 140 },
|
||||
{ prop: 'groupName', label: '客群名称', width: 180 },
|
||||
{ prop: 'groupMode', label: '客群模式', width: 100, dict: groupModeDict },
|
||||
{ prop: 'deptId', label: '归属支行机构号', width: 140 },
|
||||
{ prop: 'deptName', label: '归属支行名称', width: 160 },
|
||||
{ prop: 'outletsId', label: '归属网点机构号', width: 140 },
|
||||
{ prop: 'outletsName', label: '归属网点名称', width: 160 },
|
||||
{ prop: 'userName', label: '归属客户经理', width: 140 },
|
||||
{ prop: 'custNum', label: '入格客户数', width: 120 },
|
||||
{ prop: 'zf365cnt', label: '近365天已走访人数', width: 150 },
|
||||
{ prop: 'zf180cnt', label: '近180天已走访人数', width: 150 },
|
||||
{ prop: 'zf90cnt', label: '近90天已走访人数', width: 150 },
|
||||
{ prop: 'zf30cnt', label: '近30天已走访人数', width: 150 },
|
||||
{ prop: 'zf365rt', label: '近365天走访率', width: 140 },
|
||||
{ prop: 'zf180rt', label: '近180天走访率', width: 140 },
|
||||
{ prop: 'zf90rt', label: '近90天走访率', width: 140 },
|
||||
{ prop: 'zf30rt', label: '近30天走访率', width: 140 },
|
||||
{ prop: 'curBalD', label: '活期存款余额(元)', width: 160 },
|
||||
{ prop: 'sxRat', label: '授信率(%)', width: 120 },
|
||||
{ prop: 'yxRat', label: '用信覆盖率', width: 120 },
|
||||
{ prop: 'sxNum', label: '授信户数', width: 120 },
|
||||
{ prop: 'yxNum', label: '用信户数', width: 120 },
|
||||
{ prop: 'sxBal', label: '授信金额(合同)', width: 160 },
|
||||
{ prop: 'balLoan', label: '贷款余额(元)', width: 150 },
|
||||
{ prop: 'loanAve', label: '贷款年日均(元)', width: 150 },
|
||||
{ prop: 'yxhtRat', label: '合同签约率(%)', width: 140 },
|
||||
{ prop: 'dianRat', label: '代扣电费覆盖率(%)', width: 150 },
|
||||
{ prop: 'shuiRat', label: '代扣水费率(%)', width: 140 },
|
||||
{ prop: 'taxRat', label: '代扣税费率(%)', width: 140 },
|
||||
{ prop: 'openRat', label: '开户率(%)', width: 120 },
|
||||
{ prop: 'yxhtNum', label: '合同签约客户数', width: 150 },
|
||||
{ prop: 'dianNum', label: '代扣电费客户数', width: 150 },
|
||||
{ prop: 'shuiNum', label: '代扣水费客户数', width: 150 },
|
||||
{ prop: 'taxNum', label: '代扣税费数', width: 140 },
|
||||
{ prop: 'openNum', label: '开户数', width: 120 },
|
||||
{ prop: 'depBal', label: '存款余额(元)', width: 150 },
|
||||
{ prop: 'finBal', label: '财富余额(元)', width: 150 },
|
||||
{ prop: 'grhxNum', label: '个人核心客户数', width: 150 },
|
||||
{ prop: 'cfyxNum', label: '财富有效客户数', width: 150 },
|
||||
{ prop: 'yxxykNum', label: '有效信用卡数', width: 140 },
|
||||
{ prop: 'yxsbkNum', label: '有效社保卡户数', width: 150 },
|
||||
{ prop: 'twoTo3SbkNum', label: '二换三社保卡户数', width: 160 },
|
||||
{ prop: 'yljToSbkNum', label: '养老金迁移至社保卡户数', width: 180 },
|
||||
{ prop: 'fshlNum', label: '丰收互联客户数', width: 150 },
|
||||
{ prop: 'yxsdNum', label: '有效收单商户', width: 140 },
|
||||
{ prop: 'hxsdNum', label: '核心收单户数', width: 140 },
|
||||
{ prop: 'regionCode', label: '归属行政区划编码', width: 160 }
|
||||
];
|
||||
|
||||
export const publicColumns = [
|
||||
{ prop: 'dt', label: '统计日期', width: 140 },
|
||||
{ prop: 'groupName', label: '客群名称', width: 180 },
|
||||
{ prop: 'groupMode', label: '客群模式', width: 100, dict: groupModeDict },
|
||||
{ prop: 'deptId', label: '归属支行', width: 120 },
|
||||
{ prop: 'deptName', label: '归属支行名称', width: 140 },
|
||||
{ prop: 'outletsId', label: '归属网点', width: 120 },
|
||||
{ prop: 'outletsName', label: '归属网点名称', width: 140 },
|
||||
{ prop: 'userName', label: '归属客户经理', width: 140 },
|
||||
{ prop: 'custNum', label: '入格客户数', width: 120 },
|
||||
{ prop: 'hqCurBalance', label: '活期存款余额', width: 140 },
|
||||
{ prop: 'bzCurBalance', label: '保证金存款余额', width: 150 },
|
||||
{ prop: 'loanBalanceCny', label: '贷款余额', width: 140 },
|
||||
{ prop: 'financeProd711Balance', label: '贴现余额', width: 140 },
|
||||
{ prop: 'financeProd716Balance', label: '承兑汇票余额', width: 150 },
|
||||
{ prop: 'loanYearDailyaverage', label: '贷款年日均', width: 140 },
|
||||
{ prop: 'qfcdRat', label: '签发承兑汇票率', width: 140 },
|
||||
{ prop: 'txRat', label: '贴现业务率', width: 120 },
|
||||
{ prop: 'bhRat', label: '保函业务率', width: 120 },
|
||||
{ prop: 'yxdfgzRat', label: '有效代发工资率', width: 150 },
|
||||
{ prop: 'dkdfRat', label: '代扣电费率', width: 120 },
|
||||
{ prop: 'dksfRat', label: '代扣水费率', width: 120 },
|
||||
{ prop: 'dkshfRat', label: '代扣税费率', width: 120 },
|
||||
{ prop: 'pjbRat', label: '票据宝签约率', width: 130 },
|
||||
{ prop: 'czbRat', label: '财资宝签约率', width: 130 },
|
||||
{ prop: 'sfbRat', label: '收付宝签约率', width: 130 },
|
||||
{ prop: 'mrbRat', label: '贸融宝签约率', width: 130 },
|
||||
{ prop: 'szstRat', label: '数字生态产品签约率', width: 170 },
|
||||
{ prop: 'khRat', label: '开户率', width: 120 },
|
||||
{ prop: 'gjjsywRat', label: '国际结算业务率', width: 150 },
|
||||
{ prop: 'yqjshRat', label: '远期结算汇业务率', width: 160 },
|
||||
{ prop: 'qfcdNum', label: '签发承兑汇票数', width: 150 },
|
||||
{ prop: 'txNum', label: '贴现业务数', width: 120 },
|
||||
{ prop: 'bhNum', label: '保函业务数', width: 120 },
|
||||
{ prop: 'yxdfgzNum', label: '有效代发工资数', width: 150 },
|
||||
{ prop: 'ustrCountPerM', label: '月均代发工资笔数', width: 150 },
|
||||
{ prop: 'ustrBalM', label: '月均代发工资金额(元)', width: 170 },
|
||||
{ prop: 'dkdfNum', label: '代扣电费数', width: 120 },
|
||||
{ prop: 'dksfNum', label: '代扣水费数', width: 120 },
|
||||
{ prop: 'dkshfNum', label: '代扣税费数', width: 120 },
|
||||
{ prop: 'pjbNum', label: '票据宝签约数', width: 130 },
|
||||
{ prop: 'czbNum', label: '财资宝签约数', width: 130 },
|
||||
{ prop: 'sfbNum', label: '收付宝签约数', width: 130 },
|
||||
{ prop: 'mrbNum', label: '贸融宝签约数', width: 130 },
|
||||
{ prop: 'szstNum', label: '数字生态产品签约数', width: 170 },
|
||||
{ prop: 'khNum', label: '开户数', width: 120 },
|
||||
{ prop: 'gjjsywNum', label: '国际结算业务数', width: 150 },
|
||||
{ prop: 'yqjshNum', label: '远期结算汇业务数', width: 160 },
|
||||
{ prop: 'htqyRat', label: '合同签约率', width: 130 },
|
||||
{ prop: 'htqyNum', label: '合同签约数', width: 130 },
|
||||
{ prop: 'zf365cnt', label: '近365天已走访人数', width: 150 },
|
||||
{ prop: 'zf180cnt', label: '近180天已走访人数', width: 150 },
|
||||
{ prop: 'zf90cnt', label: '近90天已走访人数', width: 150 },
|
||||
{ prop: 'zf30cnt', label: '近30天已走访人数', width: 150 },
|
||||
{ prop: 'zf365rt', label: '近365天走访率', width: 140 },
|
||||
{ prop: 'zf180rt', label: '近180天走访率', width: 140 },
|
||||
{ prop: 'zf90rt', label: '近90天走访率', width: 140 },
|
||||
{ prop: 'zf30rt', label: '近30天走访率', width: 140 },
|
||||
{ prop: 'phRat', label: '建档率', width: 120 },
|
||||
{ prop: 'phNum', label: '建档数', width: 120 },
|
||||
{ prop: 'regionCode', label: '归属行政区划编码', width: 160 }
|
||||
];
|
||||
|
||||
export const retailDetailColumns = [
|
||||
{ prop: 'custName', label: '客户名称', width: 160 },
|
||||
{ prop: 'custIdc', label: '客户证件号', width: 180 },
|
||||
{ prop: 'custIsn', label: '客户内码', width: 140 },
|
||||
{ prop: 'curBalD', label: '活期存款余额', width: 140 },
|
||||
{ prop: 'balLoan', label: '贷款余额', width: 140 },
|
||||
{ prop: 'loanAve', label: '贷款年日均', width: 140 },
|
||||
{ prop: 'isSx', label: '是否授信', width: 100 },
|
||||
{ prop: 'isYx', label: '是否用信', width: 100 },
|
||||
{ prop: 'sxBal', label: '授信金额', width: 120 },
|
||||
{ prop: 'isYxht', label: '是否合同签约', width: 120 },
|
||||
{ prop: 'isXyk', label: '是否持有信用卡', width: 130 },
|
||||
{ prop: 'fshl', label: '是否开通丰收互联', width: 140 },
|
||||
{ prop: 'isSd', label: '是否办理收单', width: 120 },
|
||||
{ prop: 'dian', label: '是否代扣电费', width: 120 },
|
||||
{ prop: 'shui', label: '是否代扣水费', width: 120 },
|
||||
{ prop: 'tax', label: '是否代扣税费', width: 120 },
|
||||
{ prop: 'openNum', label: '开户数', width: 100 },
|
||||
{ prop: 'depBal', label: '存款余额', width: 120 },
|
||||
{ prop: 'finBal', label: '财富余额', width: 120 },
|
||||
{ prop: 'isGrhx', label: '是否个人核心客户', width: 140 },
|
||||
{ prop: 'isCfyx', label: '是否财富有效客户', width: 140 },
|
||||
{ prop: 'isYxsbk', label: '是否有效社保卡客户', width: 150 },
|
||||
{ prop: 'is2to3Sbk', label: '是否二换三社保卡', width: 140 },
|
||||
{ prop: 'isYljToSbk', label: '是否养老金迁移至社保卡', width: 180 },
|
||||
{ prop: 'is365zf', label: '近365天有无走访', width: 140 },
|
||||
{ prop: 'is180zf', label: '近180天有无走访', width: 140 },
|
||||
{ prop: 'is90zf', label: '近90天有无走访', width: 140 },
|
||||
{ prop: 'is30zf', label: '近30天有无走访', width: 140 },
|
||||
{ prop: 'isHxsd', label: '是否核心收单', width: 120 },
|
||||
{ prop: 'custType', label: '客户类型', width: 100 },
|
||||
{ prop: 'regionCode', label: '归属行政区划编码', width: 160 }
|
||||
];
|
||||
|
||||
export const publicDetailColumns = [
|
||||
{ prop: 'custName', label: '客户名称', width: 160 },
|
||||
{ prop: 'socialCreditCode', label: '客户证件号', width: 200 },
|
||||
{ prop: 'custIsn', label: '客户内码', width: 140 },
|
||||
{ prop: 'hqCurBalance', label: '活期存款余额', width: 140 },
|
||||
{ prop: 'bzCurBalance', label: '保证金存款余额', width: 150 },
|
||||
{ prop: 'isCredit', label: '是否授信', width: 100 },
|
||||
{ prop: 'loanBalanceCny', label: '贷款余额', width: 140 },
|
||||
{ prop: 'loanYearDailyaverage', label: '贷款年日均', width: 140 },
|
||||
{ prop: 'financeProd716OpenFlag', label: '是否有签发承兑汇票', width: 160 },
|
||||
{ prop: 'financeProd716Balance', label: '承兑汇票余额', width: 150 },
|
||||
{ prop: 'financeProd711OpenFlag', label: '是否有贴现业务', width: 140 },
|
||||
{ prop: 'financeProd711Balance', label: '贴现金额', width: 120 },
|
||||
{ prop: 'intlBussinessJcbhOpenFlag', label: '是否有保函业务', width: 140 },
|
||||
{ prop: 'isUstr', label: '是否为有效代发工资客户', width: 170 },
|
||||
{ prop: 'ustrCountPerM', label: '月均代发工资笔数', width: 150 },
|
||||
{ prop: 'ustrBalM', label: '月均代发工资金额(元)', width: 170 },
|
||||
{ prop: 'elecchargeSignFlag', label: '是否代扣电费', width: 120 },
|
||||
{ prop: 'waterchargeSignFlag', label: '是否代扣水费', width: 120 },
|
||||
{ prop: 'taxdeductionSignFlag', label: '是否代扣税费', width: 120 },
|
||||
{ prop: 'pjb', label: '是否票据宝签约', width: 130 },
|
||||
{ prop: 'czb', label: '是否财资宝签约', width: 130 },
|
||||
{ prop: 'sfb', label: '是否收付宝签约', width: 130 },
|
||||
{ prop: 'mrb', label: '是否贸融宝签约', width: 130 },
|
||||
{ prop: 'szst', label: '是否数字生态产品签约', width: 170 },
|
||||
{ prop: 'isOpenSts', label: '是否开户', width: 100 },
|
||||
{ prop: 'intlBussinessOpenFlag', label: '是否国际结算业务', width: 150 },
|
||||
{ prop: 'intlBussiness325OpenFlag', label: '是否有远期结算汇业务', width: 170 },
|
||||
{ prop: 'isHtqy', label: '是否合同签约', width: 120 },
|
||||
{ prop: 'deptName', label: '归属支行名称', width: 140 },
|
||||
{ prop: 'outletsId', label: '归属网点id', width: 120 },
|
||||
{ prop: 'outletsName', label: '归属网点名称', width: 140 },
|
||||
{ prop: 'userName', label: '归属客户经理', width: 140 },
|
||||
{ prop: 'deptId', label: '归属支行id', width: 120 },
|
||||
{ prop: 'is365zf', label: '近365天有无走访', width: 140 },
|
||||
{ prop: 'is180zf', label: '近180天有无走访', width: 140 },
|
||||
{ prop: 'is90zf', label: '近90天有无走访', width: 140 },
|
||||
{ prop: 'is30zf', label: '近30天有无走访', width: 140 },
|
||||
{ prop: 'isPh', label: '是否建档', width: 100 },
|
||||
{ prop: 'custType', label: '客户类型', width: 100 },
|
||||
{ prop: 'regionCode', label: '归属行政区划编码', width: 160 }
|
||||
];
|
||||
Reference in New Issue
Block a user