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
1694827c
authored
Feb 27, 2024
by
puhui999
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'yudao/dev' into dev-crm
parents
32d58924
c792e69a
Hide whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
1436 additions
and
537 deletions
+1436
-537
src/api/crm/backlog/index.ts
+0
-22
src/api/crm/contract/index.ts
+3
-2
src/api/crm/receivable/index.ts
+15
-0
src/api/crm/receivable/plan/index.ts
+19
-4
src/router/modules/remaining.ts
+22
-0
src/views/crm/backlog/components/ContractAuditList.vue
+19
-2
src/views/crm/backlog/components/ContractRemindList.vue
+19
-2
src/views/crm/backlog/components/ReceivableAuditList.vue
+201
-0
src/views/crm/backlog/components/ReceivablePlanRemindList.vue
+220
-0
src/views/crm/backlog/index.vue
+16
-13
src/views/crm/backlog/tables/CheckReceivables.vue
+0
-124
src/views/crm/backlog/tables/RemindReceivables.vue
+0
-128
src/views/crm/backlog/tables/common.ts
+0
-38
src/views/crm/business/BusinessForm.vue
+0
-1
src/views/crm/contact/ContactForm.vue
+0
-1
src/views/crm/contract/ContractForm.vue
+0
-1
src/views/crm/contract/detail/ContractDetailsHeader.vue
+3
-2
src/views/crm/contract/detail/index.vue
+3
-3
src/views/crm/contract/index.vue
+26
-2
src/views/crm/customer/CustomerImportForm.vue
+1
-0
src/views/crm/customer/detail/index.vue
+3
-3
src/views/crm/customer/limitConfig/CustomerLimitConfigForm.vue
+0
-1
src/views/crm/permission/components/PermissionForm.vue
+0
-1
src/views/crm/permission/components/TransferForm.vue
+1
-2
src/views/crm/product/ProductForm.vue
+1
-1
src/views/crm/receivable/ReceivableForm.vue
+105
-81
src/views/crm/receivable/components/ReceivableList.vue
+16
-6
src/views/crm/receivable/detail/ReceivableDetailsHeader.vue
+43
-0
src/views/crm/receivable/detail/ReceivableDetailsInfo.vue
+62
-0
src/views/crm/receivable/detail/index.vue
+100
-0
src/views/crm/receivable/index.vue
+96
-11
src/views/crm/receivable/plan/ReceivablePlanForm.vue
+75
-49
src/views/crm/receivable/plan/components/ReceivablePlanList.vue
+17
-20
src/views/crm/receivable/plan/detail/ReceivablePlanDetailsHeader.vue
+44
-0
src/views/crm/receivable/plan/detail/ReceivablePlanDetailsInfo.vue
+83
-0
src/views/crm/receivable/plan/detail/index.vue
+103
-0
src/views/crm/receivable/plan/index.vue
+120
-17
No files found.
src/api/crm/backlog/index.ts
deleted
100644 → 0
View file @
32d58924
import
request
from
'@/config/axios'
// TODO 芋艿:融合下
// 5. 获得待审核合同数量
export
const
getCheckContractCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/contract/check-contract-count'
})
}
// 6. 获得待审核回款数量
export
const
getCheckReceivablesCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/receivable/check-receivables-count'
})
}
// 7. 获得待回款提醒数量
export
const
getRemindReceivablePlanCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/receivable-plan/remind-receivable-plan-count'
})
}
// 8. 获得即将到期的合同数量
export
const
getEndContractCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/contract/end-contract-count'
})
}
src/api/crm/contract/index.ts
View file @
1694827c
...
...
@@ -21,6 +21,7 @@ export interface ContractVO {
totalProductPrice
:
number
discountPercent
:
number
totalPrice
:
number
totalReceivablePrice
:
number
signContactId
:
number
signContactName
?:
string
signUserId
:
number
...
...
@@ -66,9 +67,9 @@ export const getContract = async (id: number) => {
}
// 查询 CRM 合同下拉列表
export
const
getC
rmContractSimpleListByCustomerId
=
async
(
customerId
:
number
)
=>
{
export
const
getC
ontractSimpleList
=
async
(
customerId
:
number
)
=>
{
return
await
request
.
get
({
url
:
`/crm/contract/
list-all-simple-by-customer
?customerId=
${
customerId
}
`
url
:
`/crm/contract/
simple-list
?customerId=
${
customerId
}
`
})
}
...
...
src/api/crm/receivable/index.ts
View file @
1694827c
...
...
@@ -5,14 +5,24 @@ export interface ReceivableVO {
no
:
string
planId
:
number
customerId
:
number
customerName
?:
string
contractId
:
number
contract
?:
{
no
:
string
totalPrice
:
number
}
auditStatus
:
number
processInstanceId
:
number
returnTime
:
Date
returnType
:
string
price
:
number
ownerUserId
:
number
ownerUserName
?:
string
remark
:
string
creator
:
string
// 创建人
creatorName
?:
string
// 创建人名称
createTime
:
Date
// 创建时间
updateTime
:
Date
// 更新时间
}
// 查询回款列表
...
...
@@ -54,3 +64,8 @@ export const exportReceivable = async (params) => {
export
const
submitReceivable
=
async
(
id
:
number
)
=>
{
return
await
request
.
put
({
url
:
`/crm/receivable/submit?id=
${
id
}
`
})
}
// 获得待审核回款数量
export
const
getAuditReceivableCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/receivable/audit-count'
})
}
src/api/crm/receivable/plan/index.ts
View file @
1694827c
...
...
@@ -4,16 +4,26 @@ export interface ReceivablePlanVO {
id
:
number
period
:
number
receivableId
:
number
finishStatus
:
number
processInstanceId
:
number
price
:
number
returnTime
:
Date
remindDays
:
number
returnType
:
number
remindTime
:
Date
customerId
:
number
customerName
?:
string
contractId
:
number
contractNo
?:
string
ownerUserId
:
number
ownerUserName
?:
string
remark
:
string
creator
:
string
// 创建人
creatorName
?:
string
// 创建人名称
createTime
:
Date
// 创建时间
updateTime
:
Date
// 更新时间
receivable
?:
{
price
:
number
returnTime
:
Date
}
}
// 查询回款计划列表
...
...
@@ -32,9 +42,9 @@ export const getReceivablePlan = async (id: number) => {
}
// 查询回款计划下拉数据
export
const
getReceivablePlan
ListByContractId
=
async
(
customerId
:
number
,
contractId
:
number
)
=>
{
export
const
getReceivablePlan
SimpleList
=
async
(
customerId
:
number
,
contractId
:
number
)
=>
{
return
await
request
.
get
({
url
:
`/crm/receivable-plan/
list-all-simple-by-customer
?customerId=
${
customerId
}
&contractId=
${
contractId
}
`
url
:
`/crm/receivable-plan/
simple-list
?customerId=
${
customerId
}
&contractId=
${
contractId
}
`
})
}
...
...
@@ -57,3 +67,8 @@ export const deleteReceivablePlan = async (id: number) => {
export
const
exportReceivablePlan
=
async
(
params
)
=>
{
return
await
request
.
download
({
url
:
`/crm/receivable-plan/export-excel`
,
params
})
}
// 获得待回款提醒数量
export
const
getReceivablePlanRemindCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/receivable-plan/remind-count'
})
}
src/router/modules/remaining.ts
View file @
1694827c
...
...
@@ -540,6 +540,28 @@ const remainingRouter: AppRouteRecordRaw[] = [
component
:
()
=>
import
(
'@/views/crm/contract/detail/index.vue'
)
},
{
path
:
'receivable-plan/detail/:id'
,
name
:
'CrmReceivablePlanDetail'
,
meta
:
{
title
:
'回款计划详情'
,
noCache
:
true
,
hidden
:
true
,
activeMenu
:
'/crm/receivable-plan'
},
component
:
()
=>
import
(
'@/views/crm/receivable/plan/detail/index.vue'
)
},
{
path
:
'receivable/detail/:id'
,
name
:
'CrmReceivableDetail'
,
meta
:
{
title
:
'回款详情'
,
noCache
:
true
,
hidden
:
true
,
activeMenu
:
'/crm/receivable'
},
component
:
()
=>
import
(
'@/views/crm/receivable/detail/index.vue'
)
},
{
path
:
'contact/detail/:id'
,
name
:
'CrmContactDetail'
,
meta
:
{
...
...
src/views/crm/backlog/components/ContractAuditList.vue
View file @
1694827c
...
...
@@ -101,7 +101,24 @@
</el-table-column>
<el-table-column
align=
"center"
label=
"公司签约人"
prop=
"signUserName"
width=
"130"
/>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
width=
"200"
/>
<!-- TODO @puhui999:后续可加 【已收款金额】、【未收款金额】 -->
<el-table-column
align=
"center"
label=
"已回款金额(元)"
prop=
"totalReceivablePrice"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
align=
"center"
label=
"未回款金额(元)"
prop=
"totalReceivablePrice"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
>
<
template
#
default=
"scope"
>
{{
erpPriceInputFormatter
(
scope
.
row
.
totalPrice
-
scope
.
row
.
totalReceivablePrice
)
}}
</
template
>
</el-table-column>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
...
...
@@ -159,7 +176,7 @@ import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
import
*
as
ContractApi
from
'@/api/crm/contract'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
AUDIT_STATUS
}
from
'./common'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
erpPrice
InputFormatter
,
erpPrice
TableColumnFormatter
}
from
'@/utils'
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
...
...
src/views/crm/backlog/components/ContractRemindList.vue
View file @
1694827c
...
...
@@ -101,7 +101,24 @@
</el-table-column>
<el-table-column
align=
"center"
label=
"公司签约人"
prop=
"signUserName"
width=
"130"
/>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
width=
"200"
/>
<!-- TODO @puhui999:后续可加 【已收款金额】、【未收款金额】 -->
<el-table-column
align=
"center"
label=
"已回款金额(元)"
prop=
"totalReceivablePrice"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
align=
"center"
label=
"未回款金额(元)"
prop=
"totalReceivablePrice"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
>
<
template
#
default=
"scope"
>
{{
erpPriceInputFormatter
(
scope
.
row
.
totalPrice
-
scope
.
row
.
totalReceivablePrice
)
}}
</
template
>
</el-table-column>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
...
...
@@ -160,7 +177,7 @@ import * as ContractApi from '@/api/crm/contract'
import
{
fenToYuanFormat
}
from
'@/utils/formatter'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
CONTRACT_EXPIRY_TYPE
}
from
'./common'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
erpPrice
InputFormatter
,
erpPrice
TableColumnFormatter
}
from
'@/utils'
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
...
...
src/views/crm/backlog/components/ReceivableAuditList.vue
0 → 100644
View file @
1694827c
<!-- 待审核回款 -->
<
template
>
<ContentWrap>
<div
class=
"pb-5 text-xl"
>
待审核回款
</div>
<!-- 搜索工作栏 -->
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
label-width=
"68px"
>
<el-form-item
label=
"合同状态"
prop=
"auditStatus"
>
<el-select
v-model=
"queryParams.auditStatus"
class=
"!w-240px"
placeholder=
"状态"
@
change=
"handleQuery"
>
<el-option
v-for=
"(option, index) in AUDIT_STATUS"
:label=
"option.label"
:value=
"option.value"
:key=
"index"
/>
</el-select>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<el-table-column
align=
"center"
fixed=
"left"
label=
"回款编号"
prop=
"no"
width=
"180"
>
<template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openDetail(scope.row.id)"
>
{{
scope
.
row
.
no
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"客户名称"
prop=
"customerName"
width=
"120"
>
<
template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openCustomerDetail(scope.row.customerId)"
>
{{
scope
.
row
.
customerName
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"合同编号"
prop=
"contractNo"
width=
"180"
>
<
template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openContractDetail(scope.row.contractId)"
>
{{
scope
.
row
.
contract
.
no
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
:formatter=
"dateFormatter2"
align=
"center"
label=
"回款日期"
prop=
"returnTime"
width=
"150px"
/>
<el-table-column
align=
"center"
label=
"回款金额(元)"
prop=
"price"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
align=
"center"
label=
"回款方式"
prop=
"returnType"
width=
"130px"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
:value=
"scope.row.returnType"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
width=
"200"
/>
<el-table-column
align=
"center"
label=
"合同金额(元)"
prop=
"contract.totalPrice"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
align=
"center"
label=
"负责人"
prop=
"ownerUserName"
width=
"120"
/>
<el-table-column
align=
"center"
label=
"所属部门"
prop=
"ownerUserDeptName"
width=
"100px"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"更新时间"
prop=
"updateTime"
width=
"180px"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"创建时间"
prop=
"createTime"
width=
"180px"
/>
<el-table-column
align=
"center"
label=
"创建人"
prop=
"creatorName"
width=
"120"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"回款状态"
prop=
"auditStatus"
width=
"120"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_AUDIT_STATUS"
:value=
"scope.row.auditStatus"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"180px"
>
<
template
#
default=
"scope"
>
<el-button
v-hasPermi=
"['crm:receivable:update']"
link
type=
"primary"
@
click=
"handleProcessDetail(scope.row)"
>
查看审批
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getList"
/>
</ContentWrap>
</template>
<
script
setup
lang=
"ts"
>
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter
,
dateFormatter2
}
from
'@/utils/formatTime'
import
*
as
ReceivableApi
from
'@/api/crm/receivable'
import
{
AUDIT_STATUS
}
from
'./common'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
defineOptions
({
name
:
'CrmReceivableAuditList'
})
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
auditStatus
:
10
})
const
queryFormRef
=
ref
()
// 搜索的表单
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
ReceivableApi
.
getReceivablePage
(
queryParams
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 查看审批 */
const
handleProcessDetail
=
(
row
:
ReceivableApi
.
ReceivableVO
)
=>
{
push
({
name
:
'BpmProcessInstanceDetail'
,
query
:
{
id
:
row
.
processInstanceId
}
})
}
/** 打开回款详情 */
const
{
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmReceivableDetail'
,
params
:
{
id
}
})
}
/** 打开客户详情 */
const
openCustomerDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmCustomerDetail'
,
params
:
{
id
}
})
}
/** 打开合同详情 */
const
openContractDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmContractDetail'
,
params
:
{
id
}
})
}
/** 激活时 */
onActivated
(
async
()
=>
{
await
getList
()
})
/** 初始化 **/
onMounted
(()
=>
{
getList
()
})
</
script
>
src/views/crm/backlog/components/ReceivablePlanRemindList.vue
0 → 100644
View file @
1694827c
<!-- 待回款提醒 -->
<
template
>
<ContentWrap>
<div
class=
"pb-5 text-xl"
>
待回款提醒
</div>
<!-- 搜索工作栏 -->
<el-form
ref=
"queryFormRef"
:inline=
"true"
:model=
"queryParams"
class=
"-mb-15px"
label-width=
"68px"
>
<el-form-item
label=
"合同状态"
prop=
"remindType"
>
<el-select
v-model=
"queryParams.remindType"
class=
"!w-240px"
placeholder=
"状态"
@
change=
"handleQuery"
>
<el-option
v-for=
"(option, index) in RECEIVABLE_REMIND_TYPE"
:label=
"option.label"
:value=
"option.value"
:key=
"index"
/>
</el-select>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<el-table-column
align=
"center"
fixed=
"left"
label=
"客户名称"
prop=
"customerName"
width=
"150"
>
<template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openCustomerDetail(scope.row.customerId)"
>
{{
scope
.
row
.
customerName
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"合同编号"
prop=
"contractNo"
width=
"200px"
/>
<el-table-column
align=
"center"
label=
"期数"
prop=
"period"
>
<
template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openDetail(scope.row.id)"
>
{{
scope
.
row
.
period
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"计划回款金额(元)"
prop=
"price"
width=
"160"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
:formatter=
"dateFormatter2"
align=
"center"
label=
"计划回款日期"
prop=
"returnTime"
width=
"180px"
/>
<el-table-column
align=
"center"
label=
"提前几天提醒"
prop=
"remindDays"
width=
"150"
/>
<el-table-column
align=
"center"
label=
"提醒日期"
prop=
"remindTime"
width=
"180px"
:formatter=
"dateFormatter2"
/>
<el-table-column
align=
"center"
label=
"回款方式"
prop=
"returnType"
width=
"130px"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
:value=
"scope.row.returnType"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
/>
<el-table-column
label=
"负责人"
prop=
"ownerUserName"
width=
"120"
/>
<el-table-column
align=
"center"
label=
"实际回款金额(元)"
prop=
"receivable.price"
width=
"160"
>
<
template
#
default=
"scope"
>
<el-text
v-if=
"scope.row.receivable"
>
{{
erpPriceInputFormatter
(
scope
.
row
.
receivable
.
price
)
}}
</el-text>
<el-text
v-else
>
{{
erpPriceInputFormatter
(
0
)
}}
</el-text>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"实际回款日期"
prop=
"receivable.returnTime"
width=
"180px"
:formatter=
"dateFormatter2"
/>
<el-table-column
align=
"center"
label=
"实际回款金额(元)"
prop=
"receivable.price"
width=
"160"
>
<
template
#
default=
"scope"
>
<el-text
v-if=
"scope.row.receivable"
>
{{
erpPriceInputFormatter
(
scope
.
row
.
price
-
scope
.
row
.
receivable
.
price
)
}}
</el-text>
<el-text
v-else
>
{{
erpPriceInputFormatter
(
scope
.
row
.
price
)
}}
</el-text>
</
template
>
</el-table-column>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"更新时间"
prop=
"updateTime"
width=
"180px"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"创建时间"
prop=
"createTime"
width=
"180px"
/>
<el-table-column
align=
"center"
label=
"创建人"
prop=
"creatorName"
width=
"100px"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"180px"
>
<
template
#
default=
"scope"
>
<el-button
v-hasPermi=
"['crm:receivable:create']"
link
type=
"success"
@
click=
"openReceivableForm(scope.row)"
:disabled=
"scope.row.receivableId"
>
创建回款
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<ReceivableForm
ref=
"receivableFormRef"
@
success=
"getList"
/>
</template>
<
script
setup
lang=
"ts"
>
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter
,
dateFormatter2
}
from
'@/utils/formatTime'
import
*
as
ReceivablePlanApi
from
'@/api/crm/receivable/plan'
import
{
RECEIVABLE_REMIND_TYPE
}
from
'./common'
import
{
erpPriceInputFormatter
,
erpPriceTableColumnFormatter
}
from
'@/utils'
import
ReceivableForm
from
'@/views/crm/receivable/ReceivableForm.vue'
defineOptions
({
name
:
'ReceivablePlanRemindList'
})
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
remindType
:
1
})
const
queryFormRef
=
ref
()
// 搜索的表单
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
ReceivablePlanApi
.
getReceivablePlanPage
(
queryParams
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 创建回款操作 */
const
receivableFormRef
=
ref
()
const
openReceivableForm
=
(
row
:
ReceivablePlanApi
.
ReceivablePlanVO
)
=>
{
receivableFormRef
.
value
.
open
(
'create'
,
undefined
,
row
)
}
/** 打开详情 */
const
{
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmReceivablePlanDetail'
,
params
:
{
id
}
})
}
/** 打开客户详情 */
const
openCustomerDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmCustomerDetail'
,
params
:
{
id
}
})
}
/** 激活时 */
onActivated
(
async
()
=>
{
await
getList
()
})
/** 初始化 **/
onMounted
(
async
()
=>
{
await
getList
()
})
</
script
>
src/views/crm/backlog/index.vue
View file @
1694827c
...
...
@@ -18,28 +18,29 @@
<CustomerTodayContactList
v-if=
"leftMenu === 'customerTodayContact'"
/>
<ClueFollowList
v-if=
"leftMenu === 'clueFollow'"
/>
<ContractAuditList
v-if=
"leftMenu === 'contractAudit'"
/>
<
CheckReceivables
v-if=
"leftMenu === 'checkReceivables
'"
/>
<
ReceivableAuditList
v-if=
"leftMenu === 'receivableAudit
'"
/>
<ContractRemindList
v-if=
"leftMenu === 'contractRemind'"
/>
<CustomerFollowList
v-if=
"leftMenu === 'customerFollow'"
/>
<CustomerPutPoolRemindList
v-if=
"leftMenu === 'customerPutPoolRemind'"
/>
<Re
mindReceivables
v-if=
"leftMenu === 'remindReceivables
'"
/>
<Re
ceivablePlanRemindList
v-if=
"leftMenu === 'receivablePlanRemind
'"
/>
</el-col>
</el-row>
</
template
>
<
script
lang=
"ts"
setup
>
import
*
as
BacklogApi
from
'@/api/crm/backlog'
import
CustomerFollowList
from
'./components/CustomerFollowList.vue'
import
CustomerTodayContactList
from
'./components/CustomerTodayContactList.vue'
import
CustomerPutPoolRemindList
from
'./components/CustomerPutPoolRemindList.vue'
import
ClueFollowList
from
'./components/ClueFollowList.vue'
import
ContractAuditList
from
'./components/ContractAuditList.vue'
import
ContractRemindList
from
'./components/ContractRemindList.vue'
import
Re
mindReceivables
from
'./tables/RemindReceivables
.vue'
import
CheckReceivables
from
'./tables/CheckReceivables
.vue'
import
Re
ceivablePlanRemindList
from
'./components/ReceivablePlanRemindList
.vue'
import
ReceivableAuditList
from
'./components/ReceivableAuditList
.vue'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
*
as
ClueApi
from
'@/api/crm/clue'
import
*
as
ContractApi
from
'@/api/crm/contract'
import
*
as
ReceivableApi
from
'@/api/crm/receivable'
import
*
as
ReceivablePlanApi
from
'@/api/crm/receivable/plan'
defineOptions
({
name
:
'CrmBacklog'
})
...
...
@@ -51,8 +52,8 @@ const customerPutPoolRemindCount = ref(0)
const
customerTodayContactCount
=
ref
(
0
)
const
contractAuditCount
=
ref
(
0
)
const
contractRemindCount
=
ref
(
0
)
const
checkReceivables
Count
=
ref
(
0
)
const
re
mindReceivables
Count
=
ref
(
0
)
const
receivableAudit
Count
=
ref
(
0
)
const
re
ceivablePlanRemind
Count
=
ref
(
0
)
const
leftSides
=
ref
([
{
...
...
@@ -82,13 +83,13 @@ const leftSides = ref([
},
{
name
:
'待审核回款'
,
menu
:
'
checkReceivables
'
,
count
:
checkReceivables
Count
menu
:
'
receivableAudit
'
,
count
:
receivableAudit
Count
},
{
name
:
'待回款提醒'
,
menu
:
're
mindReceivables
'
,
count
:
re
mindReceivables
Count
menu
:
're
ceivablePlanRemind
'
,
count
:
re
ceivablePlanRemind
Count
},
{
name
:
'即将到期的合同'
,
...
...
@@ -113,8 +114,10 @@ const getCount = () => {
ClueApi
.
getFollowClueCount
().
then
((
count
)
=>
(
clueFollowCount
.
value
=
count
))
ContractApi
.
getAuditContractCount
().
then
((
count
)
=>
(
contractAuditCount
.
value
=
count
))
ContractApi
.
getRemindContractCount
().
then
((
count
)
=>
(
contractRemindCount
.
value
=
count
))
BacklogApi
.
getCheckReceivablesCount
().
then
((
count
)
=>
(
checkReceivablesCount
.
value
=
count
))
BacklogApi
.
getRemindReceivablePlanCount
().
then
((
count
)
=>
(
remindReceivablesCount
.
value
=
count
))
ReceivableApi
.
getAuditReceivableCount
().
then
((
count
)
=>
(
receivableAuditCount
.
value
=
count
))
ReceivablePlanApi
.
getReceivablePlanRemindCount
().
then
(
(
count
)
=>
(
receivablePlanRemindCount
.
value
=
count
)
)
}
/** 激活时 */
...
...
src/views/crm/backlog/tables/CheckReceivables.vue
deleted
100644 → 0
View file @
32d58924
<!-- 待审核回款 -->
<
template
>
<ContentWrap>
<div
class=
"pb-5 text-xl"
>
待审核回款
</div>
<!-- 搜索工作栏 -->
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
label-width=
"68px"
>
<el-form-item
label=
"合同状态"
prop=
"auditStatus"
>
<el-select
v-model=
"queryParams.auditStatus"
class=
"!w-240px"
placeholder=
"状态"
@
change=
"handleQuery"
>
<el-option
v-for=
"(option, index) in AUDIT_STATUS"
:label=
"option.label"
:value=
"option.value"
:key=
"index"
/>
</el-select>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<el-table-column
label=
"ID"
align=
"center"
prop=
"id"
/>
<el-table-column
label=
"回款编号"
align=
"center"
prop=
"no"
/>
<!--
<el-table-column
label=
"回款计划ID"
align=
"center"
prop=
"planId"
/>
-->
<el-table-column
label=
"客户"
align=
"center"
prop=
"customerId"
/>
<el-table-column
label=
"合同"
align=
"center"
prop=
"contractId"
/>
<el-table-column
label=
"审批状态"
align=
"center"
prop=
"checkStatus"
width=
"130px"
>
<template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_AUDIT_STATUS"
:value=
"scope.row.checkStatus"
/>
</
template
>
</el-table-column>
<!-- <el-table-column label="工作流编号" align="center" prop="processInstanceId" />-->
<el-table-column
label=
"回款日期"
align=
"center"
prop=
"returnTime"
:formatter=
"dateFormatter2"
width=
"150px"
/>
<el-table-column
label=
"回款方式"
align=
"center"
prop=
"returnType"
width=
"130px"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
:value=
"scope.row.returnType"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"回款金额(元)"
align=
"center"
prop=
"price"
/>
<el-table-column
label=
"负责人"
align=
"center"
prop=
"ownerUserId"
/>
<el-table-column
label=
"批次"
align=
"center"
prop=
"batchId"
/>
<!--<el-table-column label="显示顺序" align="center" prop="sort" />-->
<el-table-column
label=
"状态"
align=
"center"
prop=
"status"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.COMMON_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"备注"
align=
"center"
prop=
"remark"
/>
<el-table-column
label=
"创建时间"
align=
"center"
prop=
"createTime"
:formatter=
"dateFormatter"
width=
"180px"
/>
</el-table>
<!-- 分页 -->
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getList"
/>
</ContentWrap>
</template>
<
script
setup
lang=
"ts"
name=
"CheckReceivables"
>
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter
,
dateFormatter2
}
from
'@/utils/formatTime'
import
*
as
ReceivableApi
from
'@/api/crm/receivable'
import
{
AUDIT_STATUS
}
from
'./common'
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
auditStatus
:
20
})
const
queryFormRef
=
ref
()
// 搜索的表单
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
ReceivableApi
.
getReceivablePage
(
queryParams
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 初始化 **/
onMounted
(()
=>
{
getList
()
})
</
script
>
<
style
scoped
></
style
>
src/views/crm/backlog/tables/RemindReceivables.vue
deleted
100644 → 0
View file @
32d58924
<!-- 待回款提醒 -->
<
template
>
<ContentWrap>
<div
class=
"pb-5 text-xl"
>
待回款提醒
</div>
<!-- 搜索工作栏 -->
<el-form
ref=
"queryFormRef"
:inline=
"true"
:model=
"queryParams"
class=
"-mb-15px"
label-width=
"68px"
>
<el-form-item
label=
"合同状态"
prop=
"remindType"
>
<el-select
v-model=
"queryParams.remindType"
class=
"!w-240px"
placeholder=
"状态"
@
change=
"handleQuery"
>
<el-option
v-for=
"(option, index) in RECEIVABLE_REMIND_TYPE"
:label=
"option.label"
:value=
"option.value"
:key=
"index"
/>
</el-select>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<!--
<el-table-column
label=
"ID"
align=
"center"
prop=
"id"
/>
-->
<el-table-column
label=
"客户名称"
align=
"center"
prop=
"customerId"
width=
"150px"
/>
<el-table-column
label=
"合同名称"
align=
"center"
prop=
"contractId"
width=
"150px"
/>
<el-table-column
label=
"期数"
align=
"center"
prop=
"period"
/>
<el-table-column
label=
"计划回款"
align=
"center"
prop=
"price"
/>
<el-table-column
label=
"计划回款日期"
align=
"center"
prop=
"returnTime"
:formatter=
"dateFormatter2"
width=
"180px"
/>
<el-table-column
label=
"提前几天提醒"
align=
"center"
prop=
"remindDays"
/>
<el-table-column
label=
"完成状态"
align=
"center"
prop=
"status"
>
<template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.COMMON_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"审批状态"
align=
"center"
prop=
"checkStatus"
width=
"130px"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_AUDIT_STATUS"
:value=
"scope.row.checkStatus"
/>
</
template
>
</el-table-column>
<!--<el-table-column label="工作流编号" align="center" prop="processInstanceId" />-->
<el-table-column
prop=
"ownerUserId"
label=
"负责人"
width=
"120"
>
<
template
#
default=
"scope"
>
{{
userList
.
find
((
user
)
=>
user
.
id
===
scope
.
row
.
ownerUserId
)?.
nickname
}}
</
template
>
</el-table-column>
<el-table-column
label=
"显示顺序"
align=
"center"
prop=
"sort"
/>
<el-table-column
label=
"备注"
align=
"center"
prop=
"remark"
/>
<el-table-column
label=
"创建时间"
align=
"center"
prop=
"createTime"
:formatter=
"dateFormatter"
width=
"180px"
/>
</el-table>
<!-- 分页 -->
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getList"
/>
</ContentWrap>
</template>
<
script
setup
lang=
"ts"
name=
"RemindReceivables"
>
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter
,
dateFormatter2
}
from
'@/utils/formatTime'
import
*
as
ReceivablePlanApi
from
'@/api/crm/receivable/plan'
import
*
as
UserApi
from
'@/api/system/user'
import
{
RECEIVABLE_REMIND_TYPE
}
from
'./common'
defineOptions
({
name
:
'ReceivablePlan'
})
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
userList
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
remindType
:
1
})
const
queryFormRef
=
ref
()
// 搜索的表单
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
ReceivablePlanApi
.
getReceivablePlanPage
(
queryParams
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 初始化 **/
onMounted
(
async
()
=>
{
await
getList
()
// 获取用户列表
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
})
</
script
>
<
style
scoped
></
style
>
src/views/crm/backlog/tables/common.ts
deleted
100644 → 0
View file @
32d58924
/** 跟进状态 */
export
const
FOLLOWUP_STATUS
=
[
{
label
:
'已跟进'
,
value
:
true
},
{
label
:
'待跟进'
,
value
:
false
}
]
/** 归属范围 */
export
const
SCENE_TYPES
=
[
{
label
:
'我负责的'
,
value
:
1
},
{
label
:
'我参与的'
,
value
:
2
},
{
label
:
'下属负责的'
,
value
:
3
}
]
/** 联系状态 */
export
const
CONTACT_STATUS
=
[
{
label
:
'今日需联系'
,
value
:
1
},
{
label
:
'已逾期'
,
value
:
2
},
{
label
:
'已联系'
,
value
:
3
}
]
/** 审批状态 */
export
const
AUDIT_STATUS
=
[
{
label
:
'已审批'
,
value
:
20
},
{
label
:
'待审批'
,
value
:
10
}
]
/** 回款提醒类型 */
export
const
RECEIVABLE_REMIND_TYPE
=
[
{
label
:
'待回款'
,
value
:
1
},
{
label
:
'已逾期'
,
value
:
2
},
{
label
:
'已回款'
,
value
:
3
}
]
/** 合同过期状态 */
export
const
CONTRACT_EXPIRY_TYPE
=
[
{
label
:
'即将过期'
,
value
:
1
},
{
label
:
'已过期'
,
value
:
2
}
]
src/views/crm/business/BusinessForm.vue
View file @
1694827c
...
...
@@ -175,7 +175,6 @@ const formRules = reactive({
const
formRef
=
ref
()
// 表单 Ref
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
statusTypeList
=
ref
([])
// 商机状态类型列表
// TODO 芋艿:统一的客户选择面板
const
customerList
=
ref
([])
// 客户列表的数据
/** 子表的表单 */
...
...
src/views/crm/contact/ContactForm.vue
View file @
1694827c
...
...
@@ -214,7 +214,6 @@ const formRules = reactive({
})
const
formRef
=
ref
()
// 表单 Ref
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
// TODO 芋艿:统一的客户选择面板
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
// 客户列表
const
contactList
=
ref
<
ContactApi
.
ContactVO
[]
>
([])
// 联系人列表
...
...
src/views/crm/contract/ContractForm.vue
View file @
1694827c
...
...
@@ -235,7 +235,6 @@ const formRules = reactive({
})
const
formRef
=
ref
()
// 表单 Ref
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
// TODO 芋艿:统一的客户选择面板
const
customerList
=
ref
([])
// 客户列表的数据
const
businessList
=
ref
<
BusinessApi
.
BusinessVO
[]
>
([])
const
contactList
=
ref
<
ContactApi
.
ContactVO
[]
>
([])
...
...
src/views/crm/contract/detail/ContractDetailsHeader.vue
View file @
1694827c
...
...
@@ -26,8 +26,9 @@
<el-descriptions-item
label=
"下单时间"
>
{{
formatDate
(
contract
.
orderDate
)
}}
</el-descriptions-item>
<!-- TODO 芋艿:回款金额 -->
<el-descriptions-item
label=
"回款金额(元)"
>
待实现
</el-descriptions-item>
<el-descriptions-item
label=
"回款金额(元)"
>
{{
erpPriceInputFormatter
(
contract
.
totalReceivablePrice
)
}}
</el-descriptions-item>
<el-descriptions-item
label=
"负责人"
>
{{
contract
.
ownerUserName
}}
</el-descriptions-item>
...
...
src/views/crm/contract/detail/index.vue
View file @
1694827c
...
...
@@ -23,7 +23,7 @@
<ReceivablePlanList
:contract-id=
"contract.id!"
:customer-id=
"contract.customerId"
@
cr
ate-receivable=
"cr
ateReceivable"
@
cr
eate-receivable=
"cre
ateReceivable"
/>
<ReceivableList
ref=
"receivableListRef"
...
...
@@ -108,8 +108,8 @@ const getOperateLog = async (contractId: number) => {
/** 从回款计划创建回款 */
const
receivableListRef
=
ref
<
InstanceType
<
typeof
ReceivableList
>>
()
// 回款列表 Ref
const
crateReceivable
=
(
planData
:
any
)
=>
{
receivableListRef
.
value
?.
crateReceivable
(
planData
)
const
cr
e
ateReceivable
=
(
planData
:
any
)
=>
{
receivableListRef
.
value
?.
cr
e
ateReceivable
(
planData
)
}
/** 转移 */
...
...
src/views/crm/contract/index.vue
View file @
1694827c
...
...
@@ -150,7 +150,24 @@
</el-table-column>
<el-table-column
align=
"center"
label=
"公司签约人"
prop=
"signUserName"
width=
"130"
/>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
width=
"200"
/>
<!-- TODO @puhui999:后续可加 【已收款金额】、【未收款金额】 -->
<el-table-column
align=
"center"
label=
"已回款金额(元)"
prop=
"totalReceivablePrice"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
align=
"center"
label=
"未回款金额(元)"
prop=
"totalReceivablePrice"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
>
<
template
#
default=
"scope"
>
{{
erpPriceInputFormatter
(
scope
.
row
.
totalPrice
-
scope
.
row
.
totalReceivablePrice
)
}}
</
template
>
</el-table-column>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
...
...
@@ -246,8 +263,9 @@ import download from '@/utils/download'
import
*
as
ContractApi
from
'@/api/crm/contract'
import
ContractForm
from
'./ContractForm.vue'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
erpPrice
InputFormatter
,
erpPrice
TableColumnFormatter
}
from
'@/utils'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
{
TabsPaneContext
}
from
'element-plus'
defineOptions
({
name
:
'CrmContract'
})
...
...
@@ -271,6 +289,12 @@ const exportLoading = ref(false) // 导出的加载中
const
activeName
=
ref
(
'1'
)
// 列表 tab
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
// 客户列表
/** tab 切换 */
const
handleTabClick
=
(
tab
:
TabsPaneContext
)
=>
{
queryParams
.
sceneType
=
tab
.
paneName
handleQuery
()
}
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
...
...
src/views/crm/customer/CustomerImportForm.vue
View file @
1694827c
...
...
@@ -81,6 +81,7 @@ const submitForm = async () => {
const
formData
=
new
FormData
()
formData
.
append
(
'updateSupport'
,
updateSupport
.
value
)
formData
.
append
(
'file'
,
fileList
.
value
[
0
].
raw
)
// TODO @芋艿:后面是不是可以采用这种形式,去掉 uploadHeaders
await
CustomerApi
.
handleImport
(
formData
)
}
...
...
src/views/crm/customer/detail/index.vue
View file @
1694827c
...
...
@@ -64,7 +64,7 @@
<ContractList
:biz-id=
"customer.id!"
:biz-type=
"BizTypeEnum.CRM_CUSTOMER"
/>
</el-tab-pane>
<el-tab-pane
label=
"回款"
lazy
>
<ReceivablePlanList
:customer-id=
"customer.id!"
@
cr
ate-receivable=
"cr
ateReceivable"
/>
<ReceivablePlanList
:customer-id=
"customer.id!"
@
cr
eate-receivable=
"cre
ateReceivable"
/>
<ReceivableList
ref=
"receivableListRef"
:customer-id=
"customer.id!"
/>
</el-tab-pane>
<el-tab-pane
label=
"操作日志"
>
...
...
@@ -199,8 +199,8 @@ const getOperateLog = async () => {
/** 从回款计划创建回款 */
const
receivableListRef
=
ref
<
InstanceType
<
typeof
ReceivableList
>>
()
// 回款列表 Ref
const
crateReceivable
=
(
planData
:
any
)
=>
{
receivableListRef
.
value
?.
crateReceivable
(
planData
)
const
cr
e
ateReceivable
=
(
planData
:
any
)
=>
{
receivableListRef
.
value
?.
cr
e
ateReceivable
(
planData
)
}
const
close
=
()
=>
{
...
...
src/views/crm/customer/limitConfig/CustomerLimitConfigForm.vue
View file @
1694827c
...
...
@@ -82,7 +82,6 @@ const formRules = reactive({
maxCount
:
[{
required
:
true
,
message
:
'数量上限不能为空'
,
trigger
:
'blur'
}]
})
const
formRef
=
ref
()
// 表单 Ref
// TODO @芋艿:看看怎么搞个部门选择组件
const
deptTree
=
ref
()
// 部门树形结构
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
...
...
src/views/crm/permission/components/PermissionForm.vue
View file @
1694827c
...
...
@@ -129,7 +129,6 @@ const resetForm = (bizType: number, bizId: number) => {
}
onMounted
(
async
()
=>
{
// 获得用户列表
// TODO 芋艿:用户列表的选择组件
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
})
</
script
>
src/views/crm/permission/components/TransferForm.vue
View file @
1694827c
...
...
@@ -40,7 +40,7 @@
</el-radio-group>
</el-form-item>
</el-form>
<!-- TODO 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择 -->
<!-- TODO
@puhui999
转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择 -->
<
template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
...
...
@@ -117,7 +117,6 @@ const resetForm = () => {
}
onMounted
(
async
()
=>
{
// 获得用户列表
// TODO 芋艿:用户列表的选择组件
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
})
</
script
>
src/views/crm/product/ProductForm.vue
View file @
1694827c
...
...
@@ -207,6 +207,6 @@ onMounted(async () => {
const
data
=
await
ProductCategoryApi
.
getProductCategoryList
({})
productCategoryList
.
value
=
handleTree
(
data
,
'id'
,
'parentId'
)
// 系统用户列表
userList
.
value
=
await
getSimpleUserList
()
// TODO 芋艿:替换成用户组件
userList
.
value
=
await
getSimpleUserList
()
})
</
script
>
src/views/crm/receivable/ReceivableForm.vue
View file @
1694827c
...
...
@@ -10,12 +10,37 @@
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"回款编号"
prop=
"no"
>
<el-input
v-model=
"formData.no"
placeholder=
"请输入回款编号
"
/>
<el-input
disabled
v-model=
"formData.no"
placeholder=
"保存时自动生成
"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"负责人"
prop=
"ownerUserId"
>
<el-select
v-model=
"formData.ownerUserId"
:disabled=
"formType !== 'create'"
class=
"w-1/1"
>
<el-option
v-for=
"item in userOptions"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"客户名称"
prop=
"customerId"
>
<el-select
v-model=
"formData.customerId"
class=
"w-1/1"
placeholder=
"请选择客户"
>
<el-select
v-model=
"formData.customerId"
:disabled=
"formType !== 'create'"
class=
"w-1/1"
filterable
@
change=
"handleCustomerChange"
placeholder=
"请选择客户"
>
<el-option
v-for=
"item in customerList"
:key=
"item.id"
...
...
@@ -29,8 +54,10 @@
<el-form-item
label=
"合同名称"
prop=
"contractId"
>
<el-select
v-model=
"formData.contractId"
:disabled=
"!formData.customerId"
class=
"!w-100%"
:disabled=
"formType !== 'create' || !formData.customerId"
class=
"w-1/1"
filterable
@
change=
"handleContractChange"
placeholder=
"请选择合同"
>
<el-option
...
...
@@ -38,44 +65,37 @@
:key=
"data.id"
:label=
"data.name"
:value=
"data.id!"
:disabled=
"data.auditStatus !== 20"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"回款期数"
prop=
"planId"
>
<el-select
v-model=
"formData.planId"
:disabled=
"!formData.contractId"
class=
"!w-100%"
:disabled=
"formType !== 'create' || !formData.contractId"
class=
"!w-1/1"
@
change=
"handleReceivablePlanChange"
placeholder=
"请选择回款期数"
>
<el-option
v-for=
"data in receivablePlanList"
:key=
"data.id"
:label=
"
data.period + '
期'"
:label=
"
'第 ' + data.period + '
期'"
:value=
"data.id!"
/>
</el-select>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"负责人"
prop=
"ownerUserId"
>
<el-select
v-model=
"formData.ownerUserId"
clearable
placeholder=
"请输入负责人"
>
<el-option
v-for=
"item in userList"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id"
:disabled=
"data.receivableId"
/>
</el-select>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"回款方式"
prop=
"returnType"
>
<el-select
v-model=
"formData.returnType"
placeholder=
"请选择回款方式"
>
<el-select
v-model=
"formData.returnType"
class=
"w-1/1"
placeholder=
"请选择回款方式"
>
<el-option
v-for=
"dict in get
Str
DictOptions(DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE)"
v-for=
"dict in get
Int
DictOptions(DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE)"
:key=
"dict.value"
:label=
"dict.label"
:value=
"dict.value"
...
...
@@ -83,6 +103,8 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"回款金额"
prop=
"price"
>
<el-input-number
...
...
@@ -90,6 +112,8 @@
class=
"!w-100%"
controls-position=
"right"
placeholder=
"请输入回款金额"
:min=
"0.01"
:precision=
"2"
/>
</el-form-item>
</el-col>
...
...
@@ -103,14 +127,11 @@
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"24"
>
<el-form-item
label=
"备注"
prop=
"remark"
>
<el-input
v-model=
"formData.remark"
:rows=
"3"
placeholder=
"请输入备注"
type=
"textarea"
/>
<el-input
v-model=
"formData.remark"
placeholder=
"请输入备注"
type=
"textarea"
/>
</el-form-item>
</el-col>
</el-row>
...
...
@@ -128,21 +149,20 @@ import * as UserApi from '@/api/system/user'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
*
as
ContractApi
from
'@/api/crm/contract'
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
DICT_TYPE
,
getStrDictOptions
}
from
'@/utils/dict'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
form
from
'@/components/Form/src/Form.vue'
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
const
user
List
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
user
Options
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
dialogTitle
=
ref
(
''
)
// 弹窗的标题
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const
formType
=
ref
(
''
)
// 表单的类型:create - 新增;update - 修改
const
formData
=
ref
<
ReceivableApi
.
ReceivableVO
>
({}
as
ReceivableApi
.
ReceivableVO
)
const
formRules
=
reactive
({
no
:
[{
required
:
true
,
message
:
'回款编号不能为空'
,
trigger
:
'blur'
}],
customerId
:
[{
required
:
true
,
message
:
'客户不能为空'
,
trigger
:
'blur'
}],
contractId
:
[{
required
:
true
,
message
:
'合同不能为空'
,
trigger
:
'blur'
}],
auditStatus
:
[{
required
:
true
,
message
:
'审批状态不能为空'
,
trigger
:
'blur'
}],
returnTime
:
[{
required
:
true
,
message
:
'回款日期不能为空'
,
trigger
:
'blur'
}],
price
:
[{
required
:
true
,
message
:
'回款金额不能为空'
,
trigger
:
'blur'
}]
})
...
...
@@ -150,8 +170,13 @@ const formRef = ref() // 表单 Ref
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
// 客户列表
const
contractList
=
ref
<
ContractApi
.
ContractVO
[]
>
([])
// 合同列表
const
receivablePlanList
=
ref
<
ReceivablePlanApi
.
ReceivablePlanVO
[]
>
([])
// 回款计划列表
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
,
planData
?:
ReceivablePlanApi
.
ReceivablePlanVO
)
=>
{
const
open
=
async
(
type
:
string
,
id
?:
number
,
receivablePlan
?:
ReceivablePlanApi
.
ReceivablePlanVO
)
=>
{
dialogVisible
.
value
=
true
dialogTitle
.
value
=
t
(
'action.'
+
type
)
formType
.
value
=
type
...
...
@@ -166,7 +191,7 @@ const open = async (type: string, id?: number, planData?: ReceivablePlanApi.Rece
}
}
// 获得用户列表
user
List
.
value
=
await
UserApi
.
getSimpleUserList
()
user
Options
.
value
=
await
UserApi
.
getSimpleUserList
()
// 获得客户列表
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
// 默认新建时选中自己
...
...
@@ -174,10 +199,16 @@ const open = async (type: string, id?: number, planData?: ReceivablePlanApi.Rece
formData
.
value
.
ownerUserId
=
useUserStore
().
getUser
.
id
}
// 从回款计划创建回款
if
(
planData
)
{
formData
.
value
.
customerId
=
planData
.
customerId
formData
.
value
.
contractId
=
planData
.
contractId
formData
.
value
.
planId
=
planData
.
id
if
(
receivablePlan
)
{
formData
.
value
.
customerId
=
receivablePlan
.
customerId
await
handleCustomerChange
(
receivablePlan
.
customerId
)
formData
.
value
.
contractId
=
receivablePlan
.
contractId
await
handleContractChange
(
receivablePlan
.
contractId
)
if
(
receivablePlan
.
id
)
{
formData
.
value
.
planId
=
receivablePlan
.
id
formData
.
value
.
price
=
receivablePlan
.
price
formData
.
value
.
returnType
=
receivablePlan
.
returnType
}
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
...
...
@@ -214,53 +245,46 @@ const resetForm = () => {
formRef
.
value
?.
resetFields
()
}
const
getContractList
=
async
(
customerId
:
number
)
=>
{
contractList
.
value
=
await
ContractApi
.
getCrmContractSimpleListByCustomerId
(
customerId
)
}
const
getReceivablePlanList
=
async
(
contractId
:
number
)
=>
{
receivablePlanList
.
value
=
await
ReceivablePlanApi
.
getReceivablePlanListByContractId
(
formData
.
value
.
customerId
,
contractId
)
/** 处理切换客户 */
const
handleCustomerChange
=
async
(
customerId
:
number
)
=>
{
// 重置合同编号
formData
.
value
.
contractId
=
undefined
// 获得合同列表
if
(
customerId
)
{
contractList
.
value
=
[]
contractList
.
value
=
await
ContractApi
.
getContractSimpleList
(
customerId
)
}
}
watch
(
()
=>
formData
.
value
.
customerId
,
(
newVal
)
=>
{
if
(
!
newVal
)
{
return
/** 处理切换合同 */
const
handleContractChange
=
async
(
contractId
:
number
)
=>
{
// 重置回款计划编号
formData
.
value
.
planId
=
undefined
if
(
contractId
)
{
// 获得回款计划列表
receivablePlanList
.
value
=
[]
receivablePlanList
.
value
=
await
ReceivablePlanApi
.
getReceivablePlanSimpleList
(
formData
.
value
.
customerId
,
contractId
)
// 设置金额
const
contract
=
contractList
.
value
.
find
((
item
)
=>
item
.
id
===
contractId
)
if
(
contract
)
{
formData
.
value
.
price
=
contract
.
totalPrice
-
contract
.
totalReceivablePrice
}
getContractList
(
newVal
)
},
{
immediate
:
true
}
)
watch
(
()
=>
formData
.
value
.
contractId
,
(
newVal
)
=>
{
if
(
!
newVal
)
{
return
}
getReceivablePlanList
(
newVal
)
},
{
immediate
:
true
}
/** 处理切换回款计划 */
const
handleReceivablePlanChange
=
(
planId
:
number
)
=>
{
if
(
!
planId
)
{
return
}
)
watch
(
()
=>
formData
.
value
.
planId
,
(
newVal
)
=>
{
if
(
!
newVal
)
{
return
}
const
receivablePlan
=
receivablePlanList
.
value
.
find
((
item
)
=>
item
.
id
===
newVal
)
if
(
!
receivablePlan
)
{
return
}
// 只有没有金额的时候才设置
if
(
!
formData
.
value
.
price
||
formData
.
value
.
price
===
0
)
{
formData
.
value
.
price
=
receivablePlan
.
price
}
const
receivablePlan
=
receivablePlanList
.
value
.
find
((
item
)
=>
item
.
id
===
planId
)
if
(
!
receivablePlan
)
{
return
}
)
formData
.
value
.
price
=
receivablePlan
.
price
formData
.
value
.
returnType
=
receivablePlan
.
returnType
}
</
script
>
src/views/crm/receivable/components/ReceivableList.vue
View file @
1694827c
<
template
>
<!-- 操作栏 -->
<el-row
justify=
"end"
>
<el-button
@
click=
"openForm"
>
<el-button
@
click=
"openForm
('create')
"
>
<Icon
class=
"mr-5px"
icon=
"icon-park:income-one"
/>
创建回款
</el-button>
...
...
@@ -12,7 +12,7 @@
<el-table
v-loading=
"loading"
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table-column
align=
"center"
label=
"回款编号"
prop=
"no"
/>
<el-table-column
align=
"center"
label=
"客户"
prop=
"customerName"
/>
<el-table-column
align=
"center"
label=
"合同"
prop=
"contract
Name
"
/>
<el-table-column
align=
"center"
label=
"合同"
prop=
"contract
.no
"
/>
<el-table-column
:formatter=
"dateFormatter2"
align=
"center"
...
...
@@ -25,7 +25,12 @@
<dict-tag
:type=
"DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
:value=
"scope.row.returnType"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"回款金额(元)"
prop=
"price"
/>
<el-table-column
align=
"center"
label=
"回款金额(元)"
prop=
"price"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
align=
"center"
label=
"负责人"
prop=
"ownerUserName"
/>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"130px"
>
...
...
@@ -67,6 +72,7 @@ import * as ReceivableApi from '@/api/crm/receivable'
import
ReceivableForm
from
'./../ReceivableForm.vue'
import
{
dateFormatter2
}
from
'@/utils/formatTime'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
defineOptions
({
name
:
'CrmReceivableList'
})
const
props
=
defineProps
<
{
...
...
@@ -117,7 +123,10 @@ const handleQuery = () => {
/** 添加/修改操作 */
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
formRef
.
value
.
open
(
type
,
id
)
formRef
.
value
.
open
(
type
,
id
,
{
customerId
:
props
.
customerId
,
contractId
:
props
.
contractId
})
}
/** 删除按钮操作 */
...
...
@@ -134,11 +143,12 @@ const handleDelete = async (id: number) => {
}
/** 从回款计划创建回款 */
const
crateReceivable
=
(
planData
:
any
)
=>
{
const
cr
e
ateReceivable
=
(
planData
:
any
)
=>
{
const
data
=
planData
as
unknown
as
ReceivablePlanApi
.
ReceivablePlanVO
formRef
.
value
.
open
(
'create'
,
undefined
,
data
)
}
defineExpose
({
crateReceivable
})
defineExpose
({
createReceivable
})
/** 监听打开的 customerId + contractId,从而加载最新的列表 */
watch
(
()
=>
[
props
.
customerId
,
props
.
contractId
],
...
...
src/views/crm/receivable/detail/ReceivableDetailsHeader.vue
0 → 100644
View file @
1694827c
<
template
>
<div>
<div
class=
"flex items-start justify-between"
>
<div>
<el-col>
<el-row>
<span
class=
"text-xl font-bold"
>
{{
receivable
.
no
}}
</span>
</el-row>
</el-col>
</div>
<div>
<!-- 右上:按钮 -->
<slot></slot>
</div>
</div>
</div>
<ContentWrap
class=
"mt-10px"
>
<el-descriptions
:column=
"5"
direction=
"vertical"
>
<el-descriptions-item
label=
"客户名称"
>
{{
receivable
.
customerName
}}
</el-descriptions-item>
<el-descriptions-item
label=
"合同金额"
>
{{
erpPriceInputFormatter
(
receivable
.
contract
?.
totalPrice
)
}}
</el-descriptions-item>
<el-descriptions-item
label=
"回款日期"
>
{{
formatDate
(
receivable
.
returnTime
)
}}
</el-descriptions-item>
<el-descriptions-item
label=
"回款金额"
>
{{
erpPriceInputFormatter
(
receivable
.
price
)
}}
</el-descriptions-item>
<el-descriptions-item
label=
"负责人"
>
{{
receivable
.
ownerUserName
}}
</el-descriptions-item>
</el-descriptions>
</ContentWrap>
</
template
>
<
script
lang=
"ts"
setup
>
import
*
as
ReceivableApi
from
'@/api/crm/receivable'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
erpPriceInputFormatter
}
from
'@/utils'
const
{
receivable
}
=
defineProps
<
{
receivable
:
ReceivableApi
.
ReceivableVO
}
>
()
</
script
>
src/views/crm/receivable/detail/ReceivableDetailsInfo.vue
0 → 100644
View file @
1694827c
<
template
>
<ContentWrap>
<el-collapse
v-model=
"activeNames"
>
<el-collapse-item
name=
"basicInfo"
>
<template
#
title
>
<span
class=
"text-base font-bold"
>
基本信息
</span>
</
template
>
<el-descriptions
:column=
"4"
>
<el-descriptions-item
label=
"回款编号"
>
{{ receivable.no }}
</el-descriptions-item>
<el-descriptions-item
label=
"客户名称"
>
{{ receivable.customerName }}
</el-descriptions-item>
<el-descriptions-item
label=
"合同编号"
>
{{ receivable.contract?.no }}
</el-descriptions-item>
<el-descriptions-item
label=
"回款日期"
>
{{ formatDate(receivable.returnTime, 'YYYY-MM-DD') }}
</el-descriptions-item>
<el-descriptions-item
label=
"回款金额"
>
{{ erpPriceInputFormatter(receivable.price) }}
</el-descriptions-item>
<el-descriptions-item
label=
"回款方式"
>
<dict-tag
:type=
"DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
:value=
"receivable.returnType"
/>
</el-descriptions-item>
<el-descriptions-item
label=
"备注"
>
{{ receivable.remark }}
</el-descriptions-item>
</el-descriptions>
</el-collapse-item>
<el-collapse-item
name=
"systemInfo"
>
<
template
#
title
>
<span
class=
"text-base font-bold"
>
系统信息
</span>
</
template
>
<el-descriptions
:column=
"4"
>
<el-descriptions-item
label=
"负责人"
>
{{ receivable.ownerUserName }}
</el-descriptions-item>
<el-descriptions-item
label=
"创建人"
>
{{ receivable.creatorName }}
</el-descriptions-item>
<el-descriptions-item
label=
"创建时间"
>
{{ formatDate(receivable.createTime) }}
</el-descriptions-item>
<el-descriptions-item
label=
"更新时间"
>
{{ formatDate(receivable.updateTime) }}
</el-descriptions-item>
</el-descriptions>
</el-collapse-item>
</el-collapse>
</ContentWrap>
</template>
<
script
setup
lang=
"ts"
>
import
*
as
ReceivableApi
from
'@/api/crm/receivable'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
erpPriceInputFormatter
}
from
'@/utils'
const
{
receivable
}
=
defineProps
<
{
receivable
:
ReceivableApi
.
ReceivableVO
}
>
()
// 展示的折叠面板
const
activeNames
=
ref
([
'basicInfo'
,
'systemInfo'
])
</
script
>
src/views/crm/receivable/detail/index.vue
0 → 100644
View file @
1694827c
<
template
>
<ReceivableDetailsHeader
v-loading=
"loading"
:receivable=
"receivable"
>
<el-button
v-if=
"permissionListRef?.validateWrite"
@
click=
"openForm('update', receivable.id)"
>
编辑
</el-button>
</ReceivableDetailsHeader>
<el-col>
<el-tabs>
<el-tab-pane
label=
"详细资料"
>
<ReceivableDetailsInfo
:receivable=
"receivable"
/>
</el-tab-pane>
<el-tab-pane
label=
"操作日志"
>
<OperateLogV2
:log-list=
"logList"
/>
</el-tab-pane>
<el-tab-pane
label=
"团队成员"
>
<PermissionList
ref=
"permissionListRef"
:biz-id=
"receivable.id!"
:biz-type=
"BizTypeEnum.CRM_RECEIVABLE"
:show-action=
"true"
@
quit-team=
"close"
/>
</el-tab-pane>
</el-tabs>
</el-col>
<!-- 表单弹窗:添加/修改 -->
<ReceivableForm
ref=
"formRef"
@
success=
"getReceivable(receivable.id)"
/>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
useTagsViewStore
}
from
'@/store/modules/tagsView'
import
*
as
ReceivableApi
from
'@/api/crm/receivable'
import
ReceivableDetailsHeader
from
'./ReceivableDetailsHeader.vue'
import
ReceivableDetailsInfo
from
'./ReceivableDetailsInfo.vue'
import
PermissionList
from
'@/views/crm/permission/components/PermissionList.vue'
// 团队成员列表(权限)
import
{
BizTypeEnum
}
from
'@/api/crm/permission'
import
{
OperateLogV2VO
}
from
'@/api/system/operatelog'
import
{
getOperateLogPage
}
from
'@/api/crm/operateLog'
import
ReceivableForm
from
'@/views/crm/receivable/ReceivableForm.vue'
defineOptions
({
name
:
'CrmReceivablePlanDetail'
})
const
props
=
defineProps
<
{
id
?:
number
}
>
()
const
route
=
useRoute
()
const
message
=
useMessage
()
const
receivableId
=
ref
(
0
)
// 回款编号
const
loading
=
ref
(
true
)
// 加载中
const
receivable
=
ref
<
ReceivableApi
.
ReceivableVO
>
({}
as
ReceivableApi
.
ReceivableVO
)
// 回款详情
const
permissionListRef
=
ref
<
InstanceType
<
typeof
PermissionList
>>
()
// 团队成员列表 Ref
/** 获取详情 */
const
getReceivable
=
async
(
id
:
number
)
=>
{
loading
.
value
=
true
try
{
receivable
.
value
=
await
ReceivableApi
.
getReceivable
(
id
)
await
getOperateLog
(
id
)
}
finally
{
loading
.
value
=
false
}
}
/** 编辑 */
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
formRef
.
value
.
open
(
type
,
id
)
}
/** 获取操作日志 */
const
logList
=
ref
<
OperateLogV2VO
[]
>
([])
// 操作日志列表
const
getOperateLog
=
async
(
receivableId
:
number
)
=>
{
if
(
!
receivableId
)
{
return
}
const
data
=
await
getOperateLogPage
({
bizType
:
BizTypeEnum
.
CRM_RECEIVABLE
,
bizId
:
receivableId
})
logList
.
value
=
data
.
list
}
/** 关闭窗口 */
const
{
delView
}
=
useTagsViewStore
()
// 视图操作
const
{
currentRoute
}
=
useRouter
()
// 路由
const
close
=
()
=>
{
delView
(
unref
(
currentRoute
))
}
/** 初始化 */
const
{
params
}
=
useRoute
()
onMounted
(
async
()
=>
{
const
id
=
props
.
id
||
route
.
params
.
id
if
(
!
id
)
{
message
.
warning
(
'参数错误,回款不能为空!'
)
close
()
return
}
receivableId
.
value
=
id
await
getReceivable
(
receivableId
.
value
)
})
</
script
>
src/views/crm/receivable/index.vue
View file @
1694827c
...
...
@@ -66,10 +66,41 @@
<!-- 列表 -->
<ContentWrap>
<el-tabs
v-model=
"activeName"
@
tab-click=
"handleTabClick"
>
<el-tab-pane
label=
"我负责的"
name=
"1"
/>
<el-tab-pane
label=
"我参与的"
name=
"2"
/>
<el-tab-pane
label=
"下属负责的"
name=
"3"
/>
</el-tabs>
<el-table
v-loading=
"loading"
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table-column
align=
"center"
label=
"回款编号"
prop=
"no"
/>
<el-table-column
align=
"center"
label=
"客户"
prop=
"customerName"
/>
<el-table-column
align=
"center"
label=
"合同"
prop=
"contractName"
/>
<el-table-column
align=
"center"
fixed=
"left"
label=
"回款编号"
prop=
"no"
width=
"180"
>
<template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openDetail(scope.row.id)"
>
{{
scope
.
row
.
no
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"客户名称"
prop=
"customerName"
width=
"120"
>
<
template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openCustomerDetail(scope.row.customerId)"
>
{{
scope
.
row
.
customerName
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"合同编号"
prop=
"contractNo"
width=
"180"
>
<
template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openContractDetail(scope.row.contractId)"
>
{{
scope
.
row
.
contract
.
no
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
:formatter=
"dateFormatter2"
align=
"center"
...
...
@@ -77,14 +108,43 @@
prop=
"returnTime"
width=
"150px"
/>
<el-table-column
align=
"center"
label=
"回款金额(元)"
prop=
"price"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
align=
"center"
label=
"回款方式"
prop=
"returnType"
width=
"130px"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
:value=
"scope.row.returnType"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"回款金额(元)"
prop=
"price"
/>
<el-table-column
align=
"center"
label=
"负责人"
prop=
"ownerUserName"
/>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
/>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
width=
"200"
/>
<el-table-column
align=
"center"
label=
"合同金额(元)"
prop=
"contract.totalPrice"
width=
"140"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
align=
"center"
label=
"负责人"
prop=
"ownerUserName"
width=
"120"
/>
<el-table-column
align=
"center"
label=
"所属部门"
prop=
"ownerUserDeptName"
width=
"100px"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"更新时间"
prop=
"updateTime"
width=
"180px"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"创建时间"
prop=
"createTime"
width=
"180px"
/>
<el-table-column
align=
"center"
label=
"创建人"
prop=
"creatorName"
width=
"120"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"回款状态"
prop=
"auditStatus"
width=
"120"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_AUDIT_STATUS"
:value=
"scope.row.auditStatus"
/>
...
...
@@ -141,31 +201,40 @@
<!-- 表单弹窗:添加/修改 -->
<ReceivableForm
ref=
"formRef"
@
success=
"getList"
/>
</template>
<
script
lang=
"ts"
setup
>
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter2
}
from
'@/utils/formatTime'
import
{
dateFormatter
,
dateFormatter
2
}
from
'@/utils/formatTime'
import
download
from
'@/utils/download'
import
*
as
ReceivableApi
from
'@/api/crm/receivable'
import
ReceivableForm
from
'./ReceivableForm.vue'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
{
TabsPaneContext
}
from
'element-plus'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
defineOptions
({
name
:
'Receivable'
})
const
message
=
useMessage
()
// 消息弹窗
const
{
t
}
=
useI18n
()
// 国际化
const
{
push
}
=
useRouter
()
// 路由
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
sceneType
:
'1'
,
// 默认和 activeName 相等
no
:
undefined
,
customerId
:
undefined
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
activeName
=
ref
(
'1'
)
// 列表 tab
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
// 客户列表
/** tab 切换 */
const
handleTabClick
=
(
tab
:
TabsPaneContext
)
=>
{
queryParams
.
sceneType
=
tab
.
paneName
handleQuery
()
}
/** 查询列表 */
const
getList
=
async
()
=>
{
...
...
@@ -222,7 +291,23 @@ const handleSubmit = async (row: ReceivableApi.ReceivableVO) => {
const
handleProcessDetail
=
(
row
:
ReceivableApi
.
ReceivableVO
)
=>
{
push
({
name
:
'BpmProcessInstanceDetail'
,
query
:
{
id
:
row
.
processInstanceId
}
})
}
// TODO puhui999: 回款流程审批表单详情查看后面完善
/** 打开回款详情 */
const
{
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmReceivableDetail'
,
params
:
{
id
}
})
}
/** 打开客户详情 */
const
openCustomerDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmCustomerDetail'
,
params
:
{
id
}
})
}
/** 打开合同详情 */
const
openContractDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmContractDetail'
,
params
:
{
id
}
})
}
/** 导出按钮操作 */
const
handleExport
=
async
()
=>
{
try
{
...
...
@@ -237,7 +322,7 @@ const handleExport = async () => {
exportLoading
.
value
=
false
}
}
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
// 客户列表
/** 初始化 **/
onMounted
(
async
()
=>
{
await
getList
()
...
...
src/views/crm/receivable/plan/ReceivablePlanForm.vue
View file @
1694827c
...
...
@@ -9,8 +9,38 @@
>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"还款期数"
prop=
"period"
>
<el-input
disabled
v-model=
"formData.period"
placeholder=
"保存时自动生成"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"负责人"
prop=
"ownerUserId"
>
<el-select
v-model=
"formData.ownerUserId"
:disabled=
"formType !== 'create'"
class=
"w-1/1"
>
<el-option
v-for=
"item in userOptions"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"客户名称"
prop=
"customerId"
>
<el-select
v-model=
"formData.customerId"
class=
"w-1/1"
placeholder=
"请选择客户"
>
<el-select
v-model=
"formData.customerId"
:disabled=
"formType !== 'create'"
class=
"w-1/1"
filterable
@
change=
"handleCustomerChange"
placeholder=
"请选择客户"
>
<el-option
v-for=
"item in customerList"
:key=
"item.id"
...
...
@@ -24,8 +54,9 @@
<el-form-item
label=
"合同名称"
prop=
"contractId"
>
<el-select
v-model=
"formData.contractId"
:disabled=
"!formData.customerId"
class=
"!w-100%"
:disabled=
"formType !== 'create' || !formData.customerId"
class=
"w-1/1"
filterable
placeholder=
"请选择合同"
>
<el-option
...
...
@@ -37,18 +68,8 @@
</el-select>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"负责人"
prop=
"ownerUserId"
>
<el-select
v-model=
"formData.ownerUserId"
clearable
placeholder=
"请输入负责人"
>
<el-option
v-for=
"item in userList"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"计划回款金额"
prop=
"price"
>
<el-input-number
...
...
@@ -56,6 +77,8 @@
class=
"!w-100%"
controls-position=
"right"
placeholder=
"请输入计划回款金额"
:min=
"0.01"
:precision=
"2"
/>
</el-form-item>
</el-col>
...
...
@@ -69,6 +92,8 @@
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"提前几天提醒"
prop=
"remindDays"
>
<el-input-number
...
...
@@ -80,23 +105,20 @@
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"提醒日期"
prop=
"remindTime"
>
<el-date-picker
v-model=
"formData.remindTime"
placeholder=
"选择提醒日期"
type=
"date"
value-format=
"x"
/>
<el-form-item
label=
"回款方式"
prop=
"returnType"
>
<el-select
v-model=
"formData.returnType"
class=
"w-1/1"
placeholder=
"请选择回款方式"
>
<el-option
v-for=
"dict in getIntDictOptions(DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE)"
:key=
"dict.value"
:label=
"dict.label"
:value=
"dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col
:span=
"24"
>
<el-form-item
label=
"备注"
prop=
"remark"
>
<el-input
v-model=
"formData.remark"
:rows=
"3"
placeholder=
"请输入备注"
type=
"textarea"
/>
<el-input
v-model=
"formData.remark"
placeholder=
"请输入备注"
type=
"textarea"
/>
</el-form-item>
</el-col>
</el-row>
...
...
@@ -113,10 +135,12 @@ import * as UserApi from '@/api/system/user'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
*
as
ContractApi
from
'@/api/crm/contract'
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
aw
}
from
'../../../../../dist-prod/assets/index-9eac537b'
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
const
user
List
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
user
Options
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
dialogTitle
=
ref
(
''
)
// 弹窗的标题
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
...
...
@@ -125,7 +149,6 @@ const formData = ref<ReceivablePlanApi.ReceivablePlanVO>({} as ReceivablePlanApi
const
formRules
=
reactive
({
price
:
[{
required
:
true
,
message
:
'计划回款金额不能为空'
,
trigger
:
'blur'
}],
returnTime
:
[{
required
:
true
,
message
:
'计划回款日期不能为空'
,
trigger
:
'blur'
}],
remindTime
:
[{
required
:
true
,
message
:
'提醒日期不能为空'
,
trigger
:
'blur'
}],
customerId
:
[{
required
:
true
,
message
:
'客户编号不能为空'
,
trigger
:
'blur'
}],
contractId
:
[{
required
:
true
,
message
:
'合同编号不能为空'
,
trigger
:
'blur'
}],
ownerUserId
:
[{
required
:
true
,
message
:
'负责人不能为空'
,
trigger
:
'blur'
}]
...
...
@@ -133,8 +156,9 @@ const formRules = reactive({
const
formRef
=
ref
()
// 表单 Ref
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
// 客户列表
const
contractList
=
ref
<
ContractApi
.
ContractVO
[]
>
([])
// 合同列表
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
const
open
=
async
(
type
:
string
,
id
?:
number
,
customerId
?:
number
,
contractId
?:
number
)
=>
{
dialogVisible
.
value
=
true
dialogTitle
.
value
=
t
(
'action.'
+
type
)
formType
.
value
=
type
...
...
@@ -148,34 +172,25 @@ const open = async (type: string, id?: number) => {
formLoading
.
value
=
false
}
}
// 获得用户列表
user
List
.
value
=
await
UserApi
.
getSimpleUserList
()
user
Options
.
value
=
await
UserApi
.
getSimpleUserList
()
// 获得客户列表
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
// 默认新建时选中自己
if
(
formType
.
value
===
'create'
)
{
formData
.
value
.
ownerUserId
=
useUserStore
().
getUser
.
id
}
// 设置 customerId 和 contractId 默认值
if
(
customerId
)
{
formData
.
value
.
customerId
=
customerId
await
handleCustomerChange
(
customerId
)
}
if
(
contractId
)
{
formData
.
value
.
contractId
=
contractId
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
const
getContractList
=
async
(
customerId
:
number
)
=>
{
contractList
.
value
=
await
ContractApi
.
getCrmContractSimpleListByCustomerId
(
customerId
)
}
watch
(
()
=>
formData
.
value
.
customerId
,
(
newVal
)
=>
{
if
(
!
newVal
)
{
return
}
getContractList
(
newVal
)
},
{
immediate
:
true
}
)
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
const
submitForm
=
async
()
=>
{
...
...
@@ -207,4 +222,15 @@ const resetForm = () => {
formData
.
value
=
{}
as
ReceivablePlanApi
.
ReceivablePlanVO
formRef
.
value
?.
resetFields
()
}
/** 处理切换客户 */
const
handleCustomerChange
=
async
(
customerId
:
number
)
=>
{
// 重置合同编号
formData
.
value
.
contractId
=
undefined
// 获得合同列表
if
(
customerId
)
{
contractList
.
value
=
[]
contractList
.
value
=
await
ContractApi
.
getContractSimpleList
(
customerId
)
}
}
</
script
>
src/views/crm/receivable/plan/components/ReceivablePlanList.vue
View file @
1694827c
<
template
>
<!-- 操作栏 -->
<el-row
justify=
"end"
>
<el-button
@
click=
"openForm"
>
<el-button
@
click=
"openForm
('create', undefined)
"
>
<Icon
class=
"mr-5px"
icon=
"icon-park:income"
/>
创建回款计划
</el-button>
...
...
@@ -13,7 +13,13 @@
<el-table-column
align=
"center"
label=
"客户名称"
prop=
"customerName"
width=
"150px"
/>
<el-table-column
align=
"center"
label=
"合同编号"
prop=
"contractNo"
width=
"200px"
/>
<el-table-column
align=
"center"
label=
"期数"
prop=
"period"
/>
<el-table-column
align=
"center"
label=
"计划回款(元)"
prop=
"price"
width=
"120"
/>
<el-table-column
align=
"center"
label=
"计划回款(元)"
prop=
"price"
width=
"120"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
:formatter=
"dateFormatter2"
align=
"center"
...
...
@@ -31,24 +37,14 @@
/>
<el-table-column
label=
"负责人"
prop=
"ownerUserName"
width=
"120"
/>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"完成状态"
prop=
"finishStatus"
width=
"130px"
>
<template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.INFRA_BOOLEAN_STRING"
:value=
"scope.row.finishStatus"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"200px"
>
<template
#
default=
"scope"
>
<el-button
v-hasPermi=
"['crm:receivable:create']"
link
type=
"primary"
@
click=
"crateReceivable(scope.row)"
@
click=
"createReceivable(scope.row)"
:disabled=
"scope.row.receivableId"
>
创建回款
</el-button>
...
...
@@ -86,8 +82,8 @@
<
script
lang=
"ts"
setup
>
import
*
as
ReceivablePlanApi
from
'@/api/crm/receivable/plan'
import
ReceivableForm
from
'./../ReceivablePlanForm.vue'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter2
}
from
'@/utils/formatTime'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
defineOptions
({
name
:
'CrmReceivablePlanList'
})
const
props
=
defineProps
<
{
...
...
@@ -138,15 +134,15 @@ const handleQuery = () => {
/** 添加/修改操作 */
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
formRef
.
value
.
open
(
type
,
id
)
formRef
.
value
.
open
(
type
,
id
,
props
.
customerId
,
props
.
contractId
)
}
/** 创建回款 */
const
emits
=
defineEmits
<
{
(
e
:
'crateReceivable'
,
v
:
ReceivablePlanApi
.
ReceivablePlanVO
)
(
e
:
'cr
e
ateReceivable'
,
v
:
ReceivablePlanApi
.
ReceivablePlanVO
)
}
>
()
/** 创建回款 */
const
crateReceivable
=
(
row
:
ReceivablePlanApi
.
ReceivablePlanVO
)
=>
{
emits
(
'crateReceivable'
,
row
)
const
createReceivable
=
(
row
:
ReceivablePlanApi
.
ReceivablePlanVO
)
=>
{
emits
(
'createReceivable'
,
row
)
}
/** 删除按钮操作 */
...
...
@@ -161,6 +157,7 @@ const handleDelete = async (id: number) => {
await
getList
()
}
catch
{}
}
/** 监听打开的 customerId + contractId,从而加载最新的列表 */
watch
(
()
=>
[
props
.
customerId
,
props
.
contractId
],
...
...
src/views/crm/receivable/plan/detail/ReceivablePlanDetailsHeader.vue
0 → 100644
View file @
1694827c
<
template
>
<div>
<div
class=
"flex items-start justify-between"
>
<div>
<el-col>
<el-row>
<span
class=
"text-xl font-bold"
>
第
{{
receivablePlan
.
period
}}
期
</span>
</el-row>
</el-col>
</div>
<div>
<!-- 右上:按钮 -->
<slot></slot>
</div>
</div>
</div>
<ContentWrap
class=
"mt-10px"
>
<el-descriptions
:column=
"5"
direction=
"vertical"
>
<el-descriptions-item
label=
"客户名称"
>
{{
receivablePlan
.
customerName
}}
</el-descriptions-item>
<el-descriptions-item
label=
"合同编号"
>
{{
receivablePlan
.
contractNo
}}
</el-descriptions-item>
<el-descriptions-item
label=
"计划回款金额"
>
{{
erpPriceInputFormatter
(
receivablePlan
.
price
)
}}
</el-descriptions-item>
<el-descriptions-item
label=
"计划回款日期"
>
{{
formatDate
(
receivablePlan
.
returnTime
)
}}
</el-descriptions-item>
<el-descriptions-item
label=
"实际回款金额"
>
<el-text
v-if=
"receivablePlan.receivable"
>
{{
erpPriceInputFormatter
(
receivablePlan
.
receivable
.
price
)
}}
</el-text>
<el-text
v-else
>
{{
erpPriceInputFormatter
(
0
)
}}
</el-text>
</el-descriptions-item>
</el-descriptions>
</ContentWrap>
</
template
>
<
script
lang=
"ts"
setup
>
import
*
as
ReceivablePlanApi
from
'@/api/crm/receivable/plan'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
erpPriceInputFormatter
}
from
'@/utils'
const
{
receivablePlan
}
=
defineProps
<
{
receivablePlan
:
ReceivablePlanApi
.
ReceivablePlanVO
}
>
()
</
script
>
src/views/crm/receivable/plan/detail/ReceivablePlanDetailsInfo.vue
0 → 100644
View file @
1694827c
<
template
>
<ContentWrap>
<el-collapse
v-model=
"activeNames"
>
<el-collapse-item
name=
"basicInfo"
>
<template
#
title
>
<span
class=
"text-base font-bold"
>
基本信息
</span>
</
template
>
<el-descriptions
:column=
"4"
>
<el-descriptions-item
label=
"期数"
>
{{ receivablePlan.period }}
</el-descriptions-item>
<el-descriptions-item
label=
"客户名称"
>
{{ receivablePlan.customerName }}
</el-descriptions-item>
<el-descriptions-item
label=
"合同编号"
>
{{ receivablePlan.contractNo }}
</el-descriptions-item>
<el-descriptions-item
label=
"计划回款金额"
>
{{ erpPriceInputFormatter(receivablePlan.price) }}
</el-descriptions-item>
<el-descriptions-item
label=
"计划回款日期"
>
{{ formatDate(receivablePlan.returnTime, 'YYYY-MM-DD') }}
</el-descriptions-item>
<el-descriptions-item
label=
"计划回款方式"
>
<dict-tag
:type=
"DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
:value=
"receivablePlan.returnType"
/>
</el-descriptions-item>
<el-descriptions-item
label=
"提前几天提醒"
>
{{ receivablePlan.remindDays }}
</el-descriptions-item>
<el-descriptions-item
label=
"备注"
>
{{ receivablePlan.remark }}
</el-descriptions-item>
<el-descriptions-item
label=
"实际回款金额"
>
<el-text
v-if=
"receivablePlan.receivable"
>
{{ erpPriceInputFormatter(receivablePlan.receivable.price) }}
</el-text>
<el-text
v-else
>
{{ erpPriceInputFormatter(0) }}
</el-text>
</el-descriptions-item>
<el-descriptions-item
label=
"未回款金额"
>
<el-text
v-if=
"receivablePlan.receivable"
>
{{ erpPriceInputFormatter(receivablePlan.price - receivablePlan.receivable.price) }}
</el-text>
<el-text
v-else
>
{{ erpPriceInputFormatter(receivablePlan.price) }}
</el-text>
</el-descriptions-item>
<el-descriptions-item
label=
"实际回款日期"
>
{{ formatDate(receivablePlan.receivable?.returnTime, 'YYYY-MM-DD') }}
</el-descriptions-item>
</el-descriptions>
</el-collapse-item>
<el-collapse-item
name=
"systemInfo"
>
<
template
#
title
>
<span
class=
"text-base font-bold"
>
系统信息
</span>
</
template
>
<el-descriptions
:column=
"4"
>
<el-descriptions-item
label=
"负责人"
>
{{ receivablePlan.ownerUserName }}
</el-descriptions-item>
<el-descriptions-item
label=
"创建人"
>
{{ receivablePlan.creatorName }}
</el-descriptions-item>
<el-descriptions-item
label=
"创建时间"
>
{{ formatDate(receivablePlan.createTime) }}
</el-descriptions-item>
<el-descriptions-item
label=
"更新时间"
>
{{ formatDate(receivablePlan.updateTime) }}
</el-descriptions-item>
</el-descriptions>
</el-collapse-item>
</el-collapse>
</ContentWrap>
</template>
<
script
setup
lang=
"ts"
>
import
*
as
ReceivablePlanApi
from
'@/api/crm/receivable/plan'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
erpPriceInputFormatter
}
from
'@/utils'
const
{
receivablePlan
}
=
defineProps
<
{
receivablePlan
:
ReceivablePlanApi
.
ReceivablePlanVO
}
>
()
// 展示的折叠面板
const
activeNames
=
ref
([
'basicInfo'
,
'systemInfo'
])
</
script
>
src/views/crm/receivable/plan/detail/index.vue
0 → 100644
View file @
1694827c
<
template
>
<ReceivablePlanDetailsHeader
v-loading=
"loading"
:receivable-plan=
"receivablePlan"
>
<el-button
v-if=
"permissionListRef?.validateWrite"
@
click=
"openForm('update', receivablePlan.id)"
>
编辑
</el-button>
</ReceivablePlanDetailsHeader>
<el-col>
<el-tabs>
<el-tab-pane
label=
"详细资料"
>
<ReceivablePlanDetailsInfo
:receivable-plan=
"receivablePlan"
/>
</el-tab-pane>
<el-tab-pane
label=
"操作日志"
>
<OperateLogV2
:log-list=
"logList"
/>
</el-tab-pane>
<el-tab-pane
label=
"团队成员"
>
<PermissionList
ref=
"permissionListRef"
:biz-id=
"receivablePlan.id!"
:biz-type=
"BizTypeEnum.CRM_RECEIVABLE_PLAN"
:show-action=
"true"
@
quit-team=
"close"
/>
</el-tab-pane>
</el-tabs>
</el-col>
<!-- 表单弹窗:添加/修改 -->
<ReceivablePlanForm
ref=
"formRef"
@
success=
"getReceivablePlan(receivablePlan.id)"
/>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
useTagsViewStore
}
from
'@/store/modules/tagsView'
import
*
as
ReceivablePlanApi
from
'@/api/crm/receivable/plan'
import
ReceivablePlanDetailsHeader
from
'./ReceivablePlanDetailsHeader.vue'
import
ReceivablePlanDetailsInfo
from
'./ReceivablePlanDetailsInfo.vue'
import
PermissionList
from
'@/views/crm/permission/components/PermissionList.vue'
// 团队成员列表(权限)
import
{
BizTypeEnum
}
from
'@/api/crm/permission'
import
{
OperateLogV2VO
}
from
'@/api/system/operatelog'
import
{
getOperateLogPage
}
from
'@/api/crm/operateLog'
import
ReceivablePlanForm
from
'@/views/crm/receivable/plan/ReceivablePlanForm.vue'
defineOptions
({
name
:
'CrmReceivablePlanDetail'
})
const
message
=
useMessage
()
const
receivablePlanId
=
ref
(
0
)
// 回款计划编号
const
loading
=
ref
(
true
)
// 加载中
const
receivablePlan
=
ref
<
ReceivablePlanApi
.
ReceivablePlanVO
>
(
{}
as
ReceivablePlanApi
.
ReceivablePlanVO
)
// 回款计划详情
const
permissionListRef
=
ref
<
InstanceType
<
typeof
PermissionList
>>
()
// 团队成员列表 Ref
/** 获取详情 */
const
getReceivablePlan
=
async
(
id
:
number
)
=>
{
loading
.
value
=
true
try
{
receivablePlan
.
value
=
await
ReceivablePlanApi
.
getReceivablePlan
(
id
)
await
getOperateLog
(
id
)
}
finally
{
loading
.
value
=
false
}
}
/** 编辑 */
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
formRef
.
value
.
open
(
type
,
id
)
}
/** 获取操作日志 */
const
logList
=
ref
<
OperateLogV2VO
[]
>
([])
// 操作日志列表
const
getOperateLog
=
async
(
receivablePlanId
:
number
)
=>
{
if
(
!
receivablePlanId
)
{
return
}
const
data
=
await
getOperateLogPage
({
bizType
:
BizTypeEnum
.
CRM_RECEIVABLE_PLAN
,
bizId
:
receivablePlanId
})
logList
.
value
=
data
.
list
}
/** 关闭窗口 */
const
{
delView
}
=
useTagsViewStore
()
// 视图操作
const
{
currentRoute
}
=
useRouter
()
// 路由
const
close
=
()
=>
{
delView
(
unref
(
currentRoute
))
}
/** 初始化 */
const
{
params
}
=
useRoute
()
onMounted
(
async
()
=>
{
if
(
!
params
.
id
)
{
message
.
warning
(
'参数错误,回款计划不能为空!'
)
close
()
return
}
receivablePlanId
.
value
=
params
.
id
as
unknown
as
number
await
getReceivablePlan
(
receivablePlanId
.
value
)
})
</
script
>
src/views/crm/receivable/plan/index.vue
View file @
1694827c
...
...
@@ -66,11 +66,37 @@
<!-- 列表 -->
<ContentWrap>
<el-tabs
v-model=
"activeName"
@
tab-click=
"handleTabClick"
>
<el-tab-pane
label=
"我负责的"
name=
"1"
/>
<el-tab-pane
label=
"下属负责的"
name=
"3"
/>
</el-tabs>
<el-table
v-loading=
"loading"
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table-column
align=
"center"
label=
"客户名称"
prop=
"customerName"
width=
"150px"
/>
<el-table-column
align=
"center"
fixed=
"left"
label=
"客户名称"
prop=
"customerName"
width=
"150"
>
<template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openCustomerDetail(scope.row.customerId)"
>
{{
scope
.
row
.
customerName
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"合同编号"
prop=
"contractNo"
width=
"200px"
/>
<el-table-column
align=
"center"
label=
"期数"
prop=
"period"
/>
<el-table-column
align=
"center"
label=
"计划回款(元)"
prop=
"price"
width=
"120"
/>
<el-table-column
align=
"center"
label=
"期数"
prop=
"period"
>
<
template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openDetail(scope.row.id)"
>
{{
scope
.
row
.
period
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"计划回款金额(元)"
prop=
"price"
width=
"160"
:formatter=
"erpPriceTableColumnFormatter"
/>
<el-table-column
:formatter=
"dateFormatter2"
align=
"center"
...
...
@@ -80,27 +106,78 @@
/>
<el-table-column
align=
"center"
label=
"提前几天提醒"
prop=
"remindDays"
width=
"150"
/>
<el-table-column
:formatter=
"dateFormatter2"
align=
"center"
label=
"提醒日期"
prop=
"remindTime"
width=
"180px"
:formatter=
"dateFormatter2"
/>
<el-table-column
label=
"负责人"
prop=
"ownerUserName"
width=
"120"
/>
<el-table-column
align=
"center"
label=
"回款方式"
prop=
"returnType"
width=
"130px"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
:value=
"scope.row.returnType"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
/>
<el-table-column
label=
"负责人"
prop=
"ownerUserName"
width=
"120"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"完成状态"
prop=
"finishStatus"
width=
"130px"
label=
"实际回款金额(元)"
prop=
"receivable.price"
width=
"160"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.INFRA_BOOLEAN_STRING"
:value=
"scope.row.finishStatus"
/>
<el-text
v-if=
"scope.row.receivable"
>
{{
erpPriceInputFormatter
(
scope
.
row
.
receivable
.
price
)
}}
</el-text>
<el-text
v-else
>
{{
erpPriceInputFormatter
(
0
)
}}
</el-text>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"130px"
>
<el-table-column
align=
"center"
label=
"实际回款日期"
prop=
"receivable.returnTime"
width=
"180px"
:formatter=
"dateFormatter2"
/>
<el-table-column
align=
"center"
label=
"实际回款金额(元)"
prop=
"receivable.price"
width=
"160"
>
<
template
#
default=
"scope"
>
<el-text
v-if=
"scope.row.receivable"
>
{{
erpPriceInputFormatter
(
scope
.
row
.
price
-
scope
.
row
.
receivable
.
price
)
}}
</el-text>
<el-text
v-else
>
{{
erpPriceInputFormatter
(
scope
.
row
.
price
)
}}
</el-text>
</
template
>
</el-table-column>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"更新时间"
prop=
"updateTime"
width=
"180px"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"创建时间"
prop=
"createTime"
width=
"180px"
/>
<el-table-column
align=
"center"
label=
"创建人"
prop=
"creatorName"
width=
"100px"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"180px"
>
<
template
#
default=
"scope"
>
<el-button
v-hasPermi=
"['crm:receivable:create']"
link
type=
"success"
@
click=
"openReceivableForm(scope.row)"
:disabled=
"scope.row.receivableId"
>
创建回款
</el-button>
<el-button
v-hasPermi=
"['crm:receivable-plan:update']"
link
...
...
@@ -131,16 +208,19 @@
<!-- 表单弹窗:添加/修改 -->
<ReceivablePlanForm
ref=
"formRef"
@
success=
"getList"
/>
<ReceivableForm
ref=
"receivableFormRef"
@
success=
"getList"
/>
</template>
<
script
lang=
"ts"
setup
>
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter2
}
from
'@/utils/formatTime'
import
{
dateFormatter
,
dateFormatter
2
}
from
'@/utils/formatTime'
import
download
from
'@/utils/download'
import
*
as
ReceivablePlanApi
from
'@/api/crm/receivable/plan'
import
ReceivablePlanForm
from
'./ReceivablePlanForm.vue'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
{
erpPriceInputFormatter
,
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
TabsPaneContext
}
from
'element-plus'
import
ReceivableForm
from
'@/views/crm/receivable/ReceivableForm.vue'
defineOptions
({
name
:
'ReceivablePlan'
})
...
...
@@ -150,15 +230,23 @@ const { t } = useI18n() // 国际化
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
userList
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
sceneType
:
'1'
,
// 默认和 activeName 相等
customerId
:
undefined
,
contractNo
:
undefined
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
activeName
=
ref
(
'1'
)
// 列表 tab
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
// 客户列表
/** tab 切换 */
const
handleTabClick
=
(
tab
:
TabsPaneContext
)
=>
{
queryParams
.
sceneType
=
tab
.
paneName
handleQuery
()
}
/** 查询列表 */
const
getList
=
async
()
=>
{
...
...
@@ -190,6 +278,12 @@ const openForm = (type: string, id?: number) => {
formRef
.
value
.
open
(
type
,
id
)
}
/** 创建回款操作 */
const
receivableFormRef
=
ref
()
const
openReceivableForm
=
(
row
:
ReceivablePlanApi
.
ReceivablePlanVO
)
=>
{
receivableFormRef
.
value
.
open
(
'create'
,
undefined
,
row
)
}
/** 删除按钮操作 */
const
handleDelete
=
async
(
id
:
number
)
=>
{
try
{
...
...
@@ -217,12 +311,21 @@ const handleExport = async () => {
exportLoading
.
value
=
false
}
}
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
// 客户列表
/** 打开详情 */
const
{
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmReceivablePlanDetail'
,
params
:
{
id
}
})
}
/** 打开客户详情 */
const
openCustomerDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmCustomerDetail'
,
params
:
{
id
}
})
}
/** 初始化 **/
onMounted
(
async
()
=>
{
await
getList
()
// 获取用户列表
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
// 获得客户列表
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
})
...
...
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