Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
17be1abb
authored
Jan 06, 2024
by
puhui999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
客户详情完善
parent
7fd56430
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
208 additions
and
175 deletions
+208
-175
src/api/crm/customer/index.ts
+14
-2
src/api/crm/permission/index.ts
+0
-12
src/components/OperateLogV2/src/OperateLogV2.vue
+7
-78
src/views/crm/customer/detail/CustomerDetailsHeader.vue
+2
-43
src/views/crm/customer/detail/index.vue
+76
-20
src/views/crm/customer/index.vue
+100
-15
src/views/crm/permission/components/PermissionList.vue
+9
-5
No files found.
src/api/crm/customer/index.ts
View file @
17be1abb
...
@@ -69,11 +69,23 @@ export const queryAllList = async () => {
...
@@ -69,11 +69,23 @@ export const queryAllList = async () => {
}
}
// 查询客户操作日志
// 查询客户操作日志
export
const
getOperateLogPage
=
async
(
params
:
any
)
=>
{
export
const
getOperateLogPage
=
async
(
id
:
number
)
=>
{
return
await
request
.
get
({
url
:
'/crm/customer/operate-log-page
'
,
params
})
return
await
request
.
get
({
url
:
'/crm/customer/operate-log-page
?id='
+
id
})
}
}
//======================= 业务操作 =======================
// 锁定/解锁客户
// 锁定/解锁客户
export
const
lockCustomer
=
async
(
id
:
number
,
lockStatus
:
boolean
)
=>
{
export
const
lockCustomer
=
async
(
id
:
number
,
lockStatus
:
boolean
)
=>
{
return
await
request
.
put
({
url
:
`/crm/customer/lock`
,
data
:
{
id
,
lockStatus
}
})
return
await
request
.
put
({
url
:
`/crm/customer/lock`
,
data
:
{
id
,
lockStatus
}
})
}
}
// 领取公海客户
export
const
receive
=
async
(
ids
:
any
[])
=>
{
return
await
request
.
put
({
url
:
'/crm/customer/receive'
,
params
:
{
ids
:
ids
.
join
(
','
)
}
})
}
// 客户放入公海
export
const
putPool
=
async
(
id
:
number
)
=>
{
return
await
request
.
put
({
url
:
`/crm/customer/put-pool?id=
${
id
}
`
})
}
src/api/crm/permission/index.ts
View file @
17be1abb
...
@@ -58,15 +58,3 @@ export const deletePermissionBatch = async (params) => {
...
@@ -58,15 +58,3 @@ export const deletePermissionBatch = async (params) => {
export
const
deleteSelfPermission
=
async
(
id
)
=>
{
export
const
deleteSelfPermission
=
async
(
id
)
=>
{
return
await
request
.
delete
({
url
:
'/crm/permission/quit-team?id='
+
id
})
return
await
request
.
delete
({
url
:
'/crm/permission/quit-team?id='
+
id
})
}
}
// TODO @puhui999:调整下位置
// 领取公海数据
export
const
receive
=
async
(
data
:
{
bizType
:
number
;
bizId
:
number
})
=>
{
return
await
request
.
put
({
url
:
`/crm/permission/receive`
,
data
})
}
// TODO @puhui999:调整下位置
// 数据放入公海
export
const
putPool
=
async
(
data
:
{
bizType
:
number
;
bizId
:
number
})
=>
{
return
await
request
.
put
({
url
:
`/crm/permission/put-pool`
,
data
})
}
src/components/OperateLogV2/src/OperateLogV2.vue
View file @
17be1abb
...
@@ -2,36 +2,14 @@
...
@@ -2,36 +2,14 @@
<div
class=
"p-20px"
>
<div
class=
"p-20px"
>
<el-timeline>
<el-timeline>
<el-timeline-item
<el-timeline-item
v-for=
"(log, index) in log
Data
List"
v-for=
"(log, index) in logList"
:key=
"index"
:key=
"index"
:timestamp=
"formatDate(log.createTime)"
:timestamp=
"formatDate(log.createTime)"
placement=
"top"
placement=
"top"
>
>
<div
class=
"el-timeline-right-content"
>
<div
class=
"el-timeline-right-content"
>
<el-row>
<el-col
:span=
"24"
class=
"mb-10px"
>
=======================
<el-tag
class=
"mr-10px"
type=
"success"
>
{{
log
.
userName
}}
</el-tag>
<el-tag
class=
"mr-10px"
type=
"success"
>
{{
log
.
userName
}}
</el-tag>
<span>
{{
log
.
title
}}
</span>
{{
log
.
action
}}
=======================
</el-col>
<!-- 先处理一下有几行-->
<template
v-for=
"colNum in log.colSize"
:key=
"colNum + 'col'"
>
<el-col
:span=
"24"
class=
"mb-10px"
>
<!-- 处理每一行-->
<template
v-for=
"(tagVal, index2) in log.tagsContentList.slice(
(colNum - 1) * 3,
3 * colNum
)"
:key=
"index2"
>
<el-tag
class=
"mx-10px"
>
{{
tagVal
}}
</el-tag>
<span>
{{
log
.
contentStrList
[
index2
]
}}
</span>
</
template
>
</el-col>
</template>
</el-row>
</div>
</div>
<template
#
dot
>
<template
#
dot
>
<span
:style=
"
{ backgroundColor: getUserTypeColor(log.userType) }" class="dot-node-style">
<span
:style=
"
{ backgroundColor: getUserTypeColor(log.userType) }" class="dot-node-style">
...
@@ -51,11 +29,13 @@ import { ElTag } from 'element-plus'
...
@@ -51,11 +29,13 @@ import { ElTag } from 'element-plus'
defineOptions
({
name
:
'OperateLogV2'
})
defineOptions
({
name
:
'OperateLogV2'
})
const
props
=
defineProps
<
{
interface
Props
{
logList
:
OperateLogV2VO
[]
// 操作日志列表
logList
:
OperateLogV2VO
[]
// 操作日志列表
}
>
()
}
const
logDataList
=
ref
<
OperateLogV2VO
[]
>
([])
// 操作日志列表
withDefaults
(
defineProps
<
Props
>
(),
{
logList
:
()
=>
[]
})
/** 获得 userType 颜色 */
/** 获得 userType 颜色 */
const
getUserTypeColor
=
(
type
:
number
)
=>
{
const
getUserTypeColor
=
(
type
:
number
)
=>
{
...
@@ -72,57 +52,6 @@ const getUserTypeColor = (type: number) => {
...
@@ -72,57 +52,6 @@ const getUserTypeColor = (type: number) => {
}
}
return
'#409EFF'
return
'#409EFF'
}
}
// 提取 tag 所需内容和位置
const
renderTags
=
(
content
:
string
)
=>
{
let
newStr
=
unref
(
content
).
slice
()
// 去掉引用
newStr
=
newStr
.
replaceAll
(
'【】'
,
'【空】'
).
replaceAll
(
';'
,
''
)
// 处理掉分号 特殊:处理一下空的情况
const
regex
=
/【
([^
【】
]
+
)
】/g
const
fg
=
'|'
// 原始位置替换符号
let
match
:
any
[]
|
null
let
matchStr
:
string
[]
=
[]
let
oldStr
:
string
[]
=
[]
while
((
match
=
regex
.
exec
(
newStr
))
!==
null
)
{
matchStr
.
push
(
match
[
1
])
// 提取值
oldStr
.
push
(
match
[
0
])
// 原值
}
// 为什么重新循环不放在 while 中一起是因为替换重新赋值过后 match 值就不准确了
oldStr
.
forEach
((
item
)
=>
{
newStr
=
newStr
.
replace
(
item
,
fg
)
})
return
[
newStr
.
split
(
fg
),
matchStr
]
}
const
initLog
=
()
=>
{
logDataList
.
value
=
props
.
logList
.
map
((
logItem
)
=>
{
const
keyValue
=
renderTags
(
logItem
.
action
)
// 挂载数据
logItem
.
contentStrList
=
keyValue
[
0
]
if
(
keyValue
[
0
][
0
]
===
'从'
)
{
logItem
.
title
=
logItem
.
subType
}
else
{
logItem
.
title
=
keyValue
[
0
][
0
]
logItem
.
contentStrList
.
splice
(
0
,
1
)
}
logItem
.
colSize
=
keyValue
[
0
].
length
/
3
// 变更记录行数
logItem
.
tagsContentList
=
keyValue
[
1
]
return
logItem
})
}
watch
(
()
=>
props
.
logList
.
length
,
(
newObj
)
=>
{
if
(
newObj
)
{
initLog
()
console
.
log
(
logDataList
.
value
)
}
},
{
immediate
:
true
,
deep
:
true
}
)
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
...
...
src/views/crm/customer/detail/CustomerDetailsHeader.vue
View file @
17be1abb
...
@@ -11,19 +11,7 @@
...
@@ -11,19 +11,7 @@
</div>
</div>
<div>
<div>
<!-- 右上:按钮 -->
<!-- 右上:按钮 -->
<el-button
<slot></slot>
type=
"primary"
v-hasPermi=
"['crm:customer:update']"
@
click=
"openForm(customer.id)"
>
编辑
</el-button>
<!-- TODO @puhui999:转移的操作接入 -->
<el-button
type=
"primary"
@
click=
"transfer"
>
转移
</el-button>
<!-- TODO @puhui999:修改成交状态的接入 -->
<el-button>
更改成交状态
</el-button>
<el-button
v-if=
"customer.lockStatus"
@
click=
"handleUnlock(customer.id!)"
>
解锁
</el-button>
<el-button
v-else
@
click=
"handleLock(customer.id!)"
>
锁定
</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -42,43 +30,14 @@
...
@@ -42,43 +30,14 @@
<el-descriptions-item
label=
"首要联系人电话"
>
{{
customer
.
mobile
}}
</el-descriptions-item>
<el-descriptions-item
label=
"首要联系人电话"
>
{{
customer
.
mobile
}}
</el-descriptions-item>
</el-descriptions>
</el-descriptions>
</ContentWrap>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<CustomerForm
ref=
"formRef"
@
success=
"emit('refresh')"
/>
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
CustomerForm
from
'../CustomerForm.vue'
defineOptions
({
name
:
'CustomerDetailsHeader'
})
defineOptions
({
name
:
'CustomerDetailsHeader'
})
defineProps
<
{
const
{
customer
,
loading
}
=
defineProps
<
{
customer
:
CustomerApi
.
CustomerVO
// 客户信息
customer
:
CustomerApi
.
CustomerVO
// 客户信息
loading
:
boolean
// 加载中
loading
:
boolean
// 加载中
}
>
()
}
>
()
const
message
=
useMessage
()
// 消息弹窗
/** 修改操作 */
const
formRef
=
ref
()
const
openForm
=
(
id
?:
number
)
=>
{
formRef
.
value
.
open
(
'update'
,
id
)
}
/** 锁定操作 */
const
handleLock
=
async
(
id
:
number
)
=>
{
await
CustomerApi
.
lockCustomer
(
id
,
true
)
message
.
success
(
'锁定成功'
)
emit
(
'refresh'
)
}
/** 解锁操作 */
const
handleUnlock
=
async
(
id
:
number
)
=>
{
console
.
log
(
customer
,
'======='
)
await
CustomerApi
.
lockCustomer
(
id
,
false
)
message
.
success
(
'解锁成功'
)
emit
(
'refresh'
)
}
const
emit
=
defineEmits
([
'refresh'
])
// 定义 success 事件,用于操作成功后的回调
</
script
>
</
script
>
src/views/crm/customer/detail/index.vue
View file @
17be1abb
<
template
>
<
template
>
<CustomerDetailsHeader
:customer=
"customer"
:loading=
"loading"
@
refresh=
"getCustomer(id)"
/>
<CustomerDetailsHeader
:customer=
"customer"
:loading=
"loading"
>
<el-button
@
click=
"close"
>
返回
</el-button>
<!-- TODO puhui999: 按钮数据权限收尾统一完善,需要按权限分级和客户状态来动态显示匹配的按钮 -->
<el-button
v-hasPermi=
"['crm:customer:update']"
type=
"primary"
@
click=
"openForm"
>
编辑
</el-button>
<!-- TODO @puhui999:转移的操作接入 -->
<el-button
type=
"primary"
@
click=
"transfer"
>
转移
</el-button>
<!-- TODO @puhui999:修改成交状态的接入 -->
<el-button>
更改成交状态
</el-button>
<el-button
v-if=
"customer.lockStatus"
@
click=
"handleUnlock"
>
解锁
</el-button>
<el-button
v-if=
"!customer.lockStatus"
@
click=
"handleLock"
>
锁定
</el-button>
<el-button
v-if=
"!customer.ownerUserId"
type=
"primary"
@
click=
"receive"
>
领取客户
</el-button>
<el-button
v-if=
"customer.ownerUserId"
type=
"primary"
@
click=
"putPool"
>
客户放入公海
</el-button>
</CustomerDetailsHeader>
<el-col>
<el-col>
<el-tabs>
<el-tabs>
<el-tab-pane
label=
"详细资料"
>
<el-tab-pane
label=
"详细资料"
>
...
@@ -11,7 +25,7 @@
...
@@ -11,7 +25,7 @@
<el-tab-pane
label=
"联系人"
lazy
>
<el-tab-pane
label=
"联系人"
lazy
>
<ContactList
:biz-id=
"customer.id!"
:biz-type=
"BizTypeEnum.CRM_CUSTOMER"
/>
<ContactList
:biz-id=
"customer.id!"
:biz-type=
"BizTypeEnum.CRM_CUSTOMER"
/>
</el-tab-pane>
</el-tab-pane>
<el-tab-pane
label=
"团队成员"
lazy
>
<el-tab-pane
label=
"团队成员"
>
<PermissionList
:biz-id=
"customer.id!"
:biz-type=
"BizTypeEnum.CRM_CUSTOMER"
/>
<PermissionList
:biz-id=
"customer.id!"
:biz-type=
"BizTypeEnum.CRM_CUSTOMER"
/>
</el-tab-pane>
</el-tab-pane>
<el-tab-pane
label=
"商机"
lazy
>
<el-tab-pane
label=
"商机"
lazy
>
...
@@ -27,10 +41,14 @@
...
@@ -27,10 +41,14 @@
<el-tab-pane
label=
"回访"
lazy
>
TODO 待开发
</el-tab-pane>
<el-tab-pane
label=
"回访"
lazy
>
TODO 待开发
</el-tab-pane>
</el-tabs>
</el-tabs>
</el-col>
</el-col>
<!-- 表单弹窗:添加/修改 -->
<CustomerForm
ref=
"formRef"
@
success=
"getCustomer"
/>
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
useTagsViewStore
}
from
'@/store/modules/tagsView'
import
{
useTagsViewStore
}
from
'@/store/modules/tagsView'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
CustomerForm
from
'@/views/crm/customer/CustomerForm.vue'
import
CustomerDetailsInfo
from
'./CustomerDetailsInfo.vue'
// 客户明细 - 详细信息
import
CustomerDetailsInfo
from
'./CustomerDetailsInfo.vue'
// 客户明细 - 详细信息
import
CustomerDetailsHeader
from
'./CustomerDetailsHeader.vue'
// 客户明细 - 头部
import
CustomerDetailsHeader
from
'./CustomerDetailsHeader.vue'
// 客户明细 - 头部
import
ContactList
from
'@/views/crm/contact/components/ContactList.vue'
// 联系人列表
import
ContactList
from
'@/views/crm/contact/components/ContactList.vue'
// 联系人列表
...
@@ -40,48 +58,86 @@ import ReceivableList from '@/views/crm/receivable/components/ReceivableList.vue
...
@@ -40,48 +58,86 @@ import ReceivableList from '@/views/crm/receivable/components/ReceivableList.vue
import
ReceivablePlanList
from
'@/views/crm/receivable/plan/components/ReceivablePlanList.vue'
// 回款计划列表
import
ReceivablePlanList
from
'@/views/crm/receivable/plan/components/ReceivablePlanList.vue'
// 回款计划列表
import
PermissionList
from
'@/views/crm/permission/components/PermissionList.vue'
// 团队成员列表(权限)
import
PermissionList
from
'@/views/crm/permission/components/PermissionList.vue'
// 团队成员列表(权限)
import
{
BizTypeEnum
}
from
'@/api/crm/permission'
import
{
BizTypeEnum
}
from
'@/api/crm/permission'
import
{
OperateLogV2VO
}
from
'@/api/system/operatelog'
import
type
{
OperateLogV2VO
}
from
'@/api/system/operatelog'
defineOptions
({
name
:
'CrmCustomerDetail'
})
defineOptions
({
name
:
'CrmCustomerDetail'
})
const
route
=
useRoute
()
const
customerId
=
ref
(
0
)
// 客户编号
const
id
=
Number
(
route
.
params
.
id
)
// 客户编号
const
loading
=
ref
(
true
)
// 加载中
const
loading
=
ref
(
true
)
// 加载中
const
message
=
useMessage
()
// 消息弹窗
const
{
delView
}
=
useTagsViewStore
()
// 视图操作
const
{
currentRoute
,
push
}
=
useRouter
()
// 路由
/** 获取详情 */
/** 获取详情 */
const
customer
=
ref
<
CustomerApi
.
CustomerVO
>
({}
as
CustomerApi
.
CustomerVO
)
// 客户详情
const
customer
=
ref
<
CustomerApi
.
CustomerVO
>
({}
as
CustomerApi
.
CustomerVO
)
// 客户详情
const
getCustomer
=
async
(
id
:
number
)
=>
{
const
getCustomer
=
async
()
=>
{
loading
.
value
=
true
loading
.
value
=
true
try
{
try
{
customer
.
value
=
await
CustomerApi
.
getCustomer
(
id
)
customer
.
value
=
await
CustomerApi
.
getCustomer
(
customerId
.
value
)
await
getOperateLog
(
id
)
await
getOperateLog
()
}
finally
{
}
finally
{
loading
.
value
=
false
loading
.
value
=
false
}
}
}
}
const
formRef
=
ref
<
InstanceType
<
typeof
CustomerForm
>>
()
// 客户表单 Ref
// 编辑客户
const
openForm
=
()
=>
{
formRef
.
value
?.
open
(
'update'
,
customerId
.
value
)
}
// 客户转移
const
transfer
=
()
=>
{}
// 锁定客户
const
handleLock
=
async
()
=>
{
await
message
.
confirm
(
`确定锁定客户【
${
customer
.
value
.
name
}
】 吗?`
)
await
CustomerApi
.
lockCustomer
(
unref
(
customerId
.
value
),
true
)
message
.
success
(
`锁定客户【
${
customer
.
value
.
name
}
】成功`
)
await
getCustomer
()
}
// 解锁客户
const
handleUnlock
=
async
()
=>
{
await
message
.
confirm
(
`确定解锁客户【
${
customer
.
value
.
name
}
】 吗?`
)
await
CustomerApi
.
lockCustomer
(
unref
(
customerId
.
value
),
false
)
message
.
success
(
`解锁客户【
${
customer
.
value
.
name
}
】成功`
)
await
getCustomer
()
}
// 领取客户
const
receive
=
async
()
=>
{
await
message
.
confirm
(
`确定领取客户【
${
customer
.
value
.
name
}
】 吗?`
)
await
CustomerApi
.
receive
([
unref
(
customerId
.
value
)])
message
.
success
(
`领取客户【
${
customer
.
value
.
name
}
】成功`
)
await
getCustomer
()
}
// 客户放入公海
const
putPool
=
async
()
=>
{
await
message
.
confirm
(
`确定将客户【
${
customer
.
value
.
name
}
】放入公海吗?`
)
await
CustomerApi
.
putPool
(
unref
(
customerId
.
value
))
message
.
success
(
`客户【
${
customer
.
value
.
name
}
】放入公海成功`
)
close
()
}
const
logList
=
ref
<
OperateLogV2VO
[]
>
([])
// 操作日志列表
const
logList
=
ref
<
OperateLogV2VO
[]
>
([])
// 操作日志列表
/**
/**
* 获取操作日志
* 获取操作日志
*/
*/
const
getOperateLog
=
async
(
customerId
:
number
)
=>
{
const
getOperateLog
=
async
()
=>
{
if
(
!
customerId
)
{
if
(
!
customerId
.
value
)
{
return
return
}
}
const
data
=
await
CustomerApi
.
getOperateLogPage
({
const
data
=
await
CustomerApi
.
getOperateLogPage
(
customerId
.
value
)
pageNo
:
1
,
pageSize
:
10
,
bizId
:
customerId
})
logList
.
value
=
data
.
list
logList
.
value
=
data
.
list
}
}
const
close
=
()
=>
{
delView
(
unref
(
currentRoute
))
// TODO 先返回到客户列表
push
({
name
:
'CrmCustomer'
})
}
/** 初始化 */
/** 初始化 */
const
{
delView
}
=
useTagsViewStore
()
// 视图操作
const
{
params
}
=
useRoute
()
const
{
currentRoute
}
=
useRouter
()
// 路由
onMounted
(()
=>
{
onMounted
(()
=>
{
if
(
!
id
)
{
if
(
!
params
.
id
)
{
ElMessage
.
warning
(
'参数错误,客户不能为空!'
)
ElMessage
.
warning
(
'参数错误,客户不能为空!'
)
delView
(
unref
(
currentRoute
)
)
close
(
)
return
return
}
}
getCustomer
(
id
)
customerId
.
value
=
params
.
id
as
unknown
as
number
getCustomer
()
})
})
</
script
>
</
script
>
src/views/crm/customer/index.vue
View file @
17be1abb
...
@@ -72,10 +72,17 @@
...
@@ -72,10 +72,17 @@
</el-select>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
</el-button>
<el-button
@
click=
"handleQuery"
>
<el-button
@
click=
"resetQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
重置
</el-button>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery(undefined)"
>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
重置
</el-button>
<el-button
v-hasPermi=
"['crm:customer:create']"
type=
"primary"
@
click=
"openForm('create')"
>
<el-button
v-hasPermi=
"['crm:customer:create']"
type=
"primary"
@
click=
"openForm('create')"
>
<Icon
class=
"mr-5px"
icon=
"ep:plus"
/>
新增
<Icon
class=
"mr-5px"
icon=
"ep:plus"
/>
新增
</el-button>
</el-button>
<el-button
<el-button
v-hasPermi=
"['crm:customer:export']"
v-hasPermi=
"['crm:customer:export']"
...
@@ -84,7 +91,8 @@
...
@@ -84,7 +91,8 @@
type=
"success"
type=
"success"
@
click=
"handleExport"
@
click=
"handleExport"
>
>
<Icon
class=
"mr-5px"
icon=
"ep:download"
/>
导出
<Icon
class=
"mr-5px"
icon=
"ep:download"
/>
导出
</el-button>
</el-button>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
...
@@ -92,11 +100,19 @@
...
@@ -92,11 +100,19 @@
<!-- 列表 -->
<!-- 列表 -->
<ContentWrap>
<ContentWrap>
<el-tabs
v-model=
"activeName"
@
tab-click=
"handleClick"
>
<el-tab-pane
label=
"客户列表"
name=
"1"
/>
<el-tab-pane
label=
"我负责人的"
name=
"2"
/>
<el-tab-pane
label=
"我关注的"
name=
"3"
/>
<el-tab-pane
label=
"我参与的"
name=
"4"
/>
<el-tab-pane
label=
"下属负责的"
name=
"5"
/>
<el-tab-pane
label=
"客户公海"
name=
"6"
/>
</el-tabs>
<el-table
v-loading=
"loading"
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table
v-loading=
"loading"
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table-column
align=
"center"
label=
"编号"
prop=
"id"
/>
<el-table-column
align=
"center"
label=
"编号"
prop=
"id"
/>
<el-table-column
align=
"center"
label=
"客户名称"
prop=
"name"
width=
"160"
>
<el-table-column
align=
"center"
label=
"客户名称"
prop=
"name"
width=
"160"
>
<template
#
default=
"scope"
>
<template
#
default=
"scope"
>
<el-link
type=
"primary"
:underline=
"false
"
@
click=
"openDetail(scope.row.id)"
>
<el-link
:underline=
"false"
type=
"primary
"
@
click=
"openDetail(scope.row.id)"
>
{{
scope
.
row
.
name
}}
{{
scope
.
row
.
name
}}
</el-link>
</el-link>
</
template
>
</
template
>
...
@@ -197,6 +213,7 @@ import { dateFormatter } from '@/utils/formatTime'
...
@@ -197,6 +213,7 @@ import { dateFormatter } from '@/utils/formatTime'
import
download
from
'@/utils/download'
import
download
from
'@/utils/download'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
CustomerForm
from
'./CustomerForm.vue'
import
CustomerForm
from
'./CustomerForm.vue'
import
{
TabsPaneContext
}
from
'element-plus'
defineOptions
({
name
:
'CrmCustomer'
})
defineOptions
({
name
:
'CrmCustomer'
})
...
@@ -206,24 +223,75 @@ const { t } = useI18n() // 国际化
...
@@ -206,24 +223,75 @@ const { t } = useI18n() // 国际化
const
loading
=
ref
(
true
)
// 列表的加载中
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
list
=
ref
([])
// 列表的数据
const
queryParams
=
reactive
({
const
queryParams
=
ref
<
{
pageNo
:
number
pageSize
:
number
name
:
string
mobile
:
string
industryId
:
number
|
undefined
level
:
number
|
undefined
source
:
number
|
undefined
sceneType
:
number
|
undefined
pool
:
boolean
|
undefined
}
>
({
pageNo
:
1
,
pageNo
:
1
,
pageSize
:
10
,
pageSize
:
10
,
pool
:
false
,
name
:
''
,
name
:
''
,
mobile
:
''
,
mobile
:
''
,
industryId
:
undefined
,
industryId
:
undefined
,
level
:
undefined
,
level
:
undefined
,
source
:
undefined
source
:
undefined
,
sceneType
:
undefined
,
pool
:
undefined
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
()
// 搜索的表单
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
activeName
=
ref
(
'1'
)
// 列表 tab
enum
CrmSceneTypeEnum
{
OWNER
=
1
,
FOLLOW
=
2
,
INVOLVED
=
3
,
SUBORDINATE
=
4
}
const
handleClick
=
(
tab
:
TabsPaneContext
)
=>
{
switch
(
tab
.
paneName
)
{
case
'1'
:
resetQuery
()
break
case
'2'
:
resetQuery
(()
=>
{
queryParams
.
value
.
sceneType
=
CrmSceneTypeEnum
.
OWNER
})
break
case
'3'
:
resetQuery
(()
=>
{
queryParams
.
value
.
sceneType
=
CrmSceneTypeEnum
.
FOLLOW
})
break
case
'4'
:
resetQuery
(()
=>
{
queryParams
.
value
.
sceneType
=
CrmSceneTypeEnum
.
INVOLVED
})
break
case
'5'
:
resetQuery
(()
=>
{
queryParams
.
value
.
sceneType
=
CrmSceneTypeEnum
.
SUBORDINATE
})
break
case
'6'
:
resetQuery
(()
=>
{
queryParams
.
value
.
pool
=
true
})
break
}
}
/** 查询列表 */
/** 查询列表 */
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
loading
.
value
=
true
loading
.
value
=
true
try
{
try
{
const
data
=
await
CustomerApi
.
getCustomerPage
(
queryParams
)
const
data
=
await
CustomerApi
.
getCustomerPage
(
queryParams
.
value
)
list
.
value
=
data
.
list
list
.
value
=
data
.
list
total
.
value
=
data
.
total
total
.
value
=
data
.
total
}
finally
{
}
finally
{
...
@@ -233,19 +301,30 @@ const getList = async () => {
...
@@ -233,19 +301,30 @@ const getList = async () => {
/** 搜索按钮操作 */
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
queryParams
.
value
.
pageNo
=
1
getList
()
getList
()
}
}
/** 重置按钮操作 */
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
const
resetQuery
=
(
func
:
Function
|
undefined
=
undefined
)
=>
{
queryFormRef
.
value
.
resetFields
()
queryFormRef
.
value
.
resetFields
()
queryParams
.
pool
=
false
queryParams
.
value
=
{
pageNo
:
1
,
pageSize
:
10
,
name
:
''
,
mobile
:
''
,
industryId
:
undefined
,
level
:
undefined
,
source
:
undefined
,
sceneType
:
undefined
,
pool
:
undefined
}
func
&&
func
()
handleQuery
()
handleQuery
()
}
}
/** 打开客户详情 */
/** 打开客户详情 */
const
{
push
}
=
useRouter
()
const
{
currentRoute
,
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmCustomerDetail'
,
params
:
{
id
}
})
push
({
name
:
'CrmCustomerDetail'
,
params
:
{
id
}
})
}
}
...
@@ -276,14 +355,20 @@ const handleExport = async () => {
...
@@ -276,14 +355,20 @@ const handleExport = async () => {
await
message
.
exportConfirm
()
await
message
.
exportConfirm
()
// 发起导出
// 发起导出
exportLoading
.
value
=
true
exportLoading
.
value
=
true
const
data
=
await
CustomerApi
.
exportCustomer
(
queryParams
)
const
data
=
await
CustomerApi
.
exportCustomer
(
queryParams
.
value
)
download
.
excel
(
data
,
'客户.xls'
)
download
.
excel
(
data
,
'客户.xls'
)
}
catch
{
}
catch
{
}
finally
{
}
finally
{
exportLoading
.
value
=
false
exportLoading
.
value
=
false
}
}
}
}
// 监听路由变化更新列表
watch
(
()
=>
currentRoute
.
value
,
()
=>
{
getList
()
}
)
/** 初始化 **/
/** 初始化 **/
onMounted
(()
=>
{
onMounted
(()
=>
{
getList
()
getList
()
...
...
src/views/crm/permission/components/PermissionList.vue
View file @
17be1abb
...
@@ -2,7 +2,8 @@
...
@@ -2,7 +2,8 @@
<!-- 操作栏 -->
<!-- 操作栏 -->
<el-row
justify=
"end"
>
<el-row
justify=
"end"
>
<el-button
@
click=
"openForm"
>
<el-button
@
click=
"openForm"
>
<Icon
class=
"mr-5px"
icon=
"fluent:people-team-add-20-filled"
/>
添加团队成员
<Icon
class=
"mr-5px"
icon=
"fluent:people-team-add-20-filled"
/>
添加团队成员
</el-button>
</el-button>
<el-button
@
click=
"handleUpdate"
>
<el-button
@
click=
"handleUpdate"
>
<Icon
class=
"mr-5px"
icon=
"ep:edit"
/>
<Icon
class=
"mr-5px"
icon=
"ep:edit"
/>
...
@@ -105,14 +106,14 @@ const handleDelete = async () => {
...
@@ -105,14 +106,14 @@ const handleDelete = async () => {
message
.
warning
(
'请先选择团队成员后操作!'
)
message
.
warning
(
'请先选择团队成员后操作!'
)
return
return
}
}
// TODO @puhui999:应该有个提示哈
await
message
.
delConfirm
(
'是否删除选择的团队成员?'
)
await
message
.
delConfirm
()
const
ids
=
multipleSelection
.
value
?.
map
((
item
)
=>
item
.
id
)
const
ids
=
multipleSelection
.
value
?.
map
((
item
)
=>
item
.
id
)
await
PermissionApi
.
deletePermissionBatch
({
await
PermissionApi
.
deletePermissionBatch
({
bizType
:
props
.
bizType
,
bizType
:
props
.
bizType
,
bizId
:
props
.
bizId
,
bizId
:
props
.
bizId
,
ids
ids
})
})
message
.
success
(
'删除成功'
)
}
}
/** 退出团队 */
/** 退出团队 */
...
@@ -125,7 +126,7 @@ const handleQuit = async () => {
...
@@ -125,7 +126,7 @@ const handleQuit = async () => {
message
.
warning
(
'负责人不能退出团队!'
)
message
.
warning
(
'负责人不能退出团队!'
)
return
return
}
}
// TODO @puhui999:应该有个提示哈
await
message
.
confirm
(
'确认退出团队吗?'
)
const
userPermission
=
list
.
value
.
find
((
item
)
=>
item
.
userId
===
userStore
.
getUser
.
id
)
const
userPermission
=
list
.
value
.
find
((
item
)
=>
item
.
userId
===
userStore
.
getUser
.
id
)
await
PermissionApi
.
deleteSelfPermission
(
userPermission
?.
id
)
await
PermissionApi
.
deleteSelfPermission
(
userPermission
?.
id
)
}
}
...
@@ -133,7 +134,10 @@ const handleQuit = async () => {
...
@@ -133,7 +134,10 @@ const handleQuit = async () => {
/** 监听打开的 bizId + bizType,从而加载最新的列表 */
/** 监听打开的 bizId + bizType,从而加载最新的列表 */
watch
(
watch
(
()
=>
[
props
.
bizId
,
props
.
bizType
],
()
=>
[
props
.
bizId
,
props
.
bizType
],
()
=>
{
(
val
)
=>
{
if
(
!
val
[
0
])
{
return
}
getList
()
getList
()
},
},
{
immediate
:
true
,
deep
:
true
}
{
immediate
:
true
,
deep
:
true
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment