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
9d44b9ac
authored
Feb 23, 2024
by
YunaiV
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
✨
CRM:完善合同的新增、修改需求
parent
11766f51
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
349 additions
and
275 deletions
+349
-275
src/views/crm/business/BusinessForm.vue
+0
-2
src/views/crm/business/components/BusinessProductForm.vue
+1
-1
src/views/crm/contract/ContractForm.vue
+165
-101
src/views/crm/contract/components/ContractProductForm.vue
+183
-0
src/views/crm/contract/components/ProductList.vue
+0
-171
No files found.
src/views/crm/business/BusinessForm.vue
View file @
9d44b9ac
...
@@ -155,7 +155,6 @@ const formData = ref({
...
@@ -155,7 +155,6 @@ const formData = ref({
id
:
undefined
,
id
:
undefined
,
name
:
undefined
,
name
:
undefined
,
customerId
:
undefined
,
customerId
:
undefined
,
contactNextTime
:
undefined
,
ownerUserId
:
undefined
,
ownerUserId
:
undefined
,
statusTypeId
:
undefined
,
statusTypeId
:
undefined
,
dealTime
:
undefined
,
dealTime
:
undefined
,
...
@@ -273,7 +272,6 @@ const resetForm = () => {
...
@@ -273,7 +272,6 @@ const resetForm = () => {
id
:
undefined
,
id
:
undefined
,
name
:
undefined
,
name
:
undefined
,
customerId
:
undefined
,
customerId
:
undefined
,
contactNextTime
:
undefined
,
ownerUserId
:
undefined
,
ownerUserId
:
undefined
,
statusTypeId
:
undefined
,
statusTypeId
:
undefined
,
dealTime
:
undefined
,
dealTime
:
undefined
,
...
...
src/views/crm/business/components/BusinessProductForm.vue
View file @
9d44b9ac
...
@@ -95,7 +95,7 @@
...
@@ -95,7 +95,7 @@
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
*
as
ProductApi
from
'@/api/crm/product'
import
*
as
ProductApi
from
'@/api/crm/product'
import
{
erp
CountInputFormatter
,
erp
PriceInputFormatter
,
erpPriceMultiply
}
from
'@/utils'
import
{
erpPriceInputFormatter
,
erpPriceMultiply
}
from
'@/utils'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
DICT_TYPE
}
from
'@/utils/dict'
const
props
=
defineProps
<
{
const
props
=
defineProps
<
{
...
...
src/views/crm/contract/ContractForm.vue
View file @
9d44b9ac
<
template
>
<
template
>
<Dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"
82
0"
>
<Dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"
128
0"
>
<el-form
<el-form
ref=
"formRef"
ref=
"formRef"
v-loading=
"formLoading"
v-loading=
"formLoading"
:model=
"formData"
:model=
"formData"
:rules=
"formRules"
:rules=
"formRules"
label-width=
"1
1
0px"
label-width=
"1
2
0px"
>
>
<el-row
:gutter=
"20"
>
<el-row>
<el-col
:span=
"
12
"
>
<el-col
:span=
"
8
"
>
<el-form-item
label=
"合同编号"
prop=
"no"
>
<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-form-item>
</el-col>
</el-col>
<el-col
:span=
"
12
"
>
<el-col
:span=
"
8
"
>
<el-form-item
label=
"合同名称"
prop=
"name"
>
<el-form-item
label=
"合同名称"
prop=
"name"
>
<el-input
v-model=
"formData.name"
placeholder=
"请输入合同名称"
/>
<el-input
v-model=
"formData.name"
placeholder=
"请输入合同名称"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"12"
>
<el-col
:span=
"8"
>
<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=
"8"
>
<el-form-item
label=
"客户名称"
prop=
"customerId"
>
<el-form-item
label=
"客户名称"
prop=
"customerId"
>
<el-select
v-model=
"formData.customerId"
>
<el-select
v-model=
"formData.customerId"
placeholder=
"请选择客户"
class=
"w-1/1"
>
<el-option
<el-option
v-for=
"item in customerList"
v-for=
"item in customerList"
:key=
"item.id"
:key=
"item.id"
:label=
"item.name"
:label=
"item.name"
:value=
"item.id
!
"
:value=
"item.id"
/>
/>
</el-select>
</el-select>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"
12
"
>
<el-col
:span=
"
8
"
>
<el-form-item
label=
"商机名称"
prop=
"businessId"
>
<el-form-item
label=
"商机名称"
prop=
"businessId"
>
<el-select
v-model=
"formData.businessId
"
>
<el-select
:disabled=
"!formData.customerId"
v-model=
"formData.businessId"
class=
"w-1/1
"
>
<el-option
<el-option
v-for=
"item in
businessList
"
v-for=
"item in
getBusinessOptions
"
:key=
"item.id"
:key=
"item.id"
:label=
"item.name"
:label=
"item.name"
:value=
"item.id!"
:value=
"item.id!"
...
@@ -42,46 +60,48 @@
...
@@ -42,46 +60,48 @@
</el-select>
</el-select>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"12"
>
</el-row>
<el-row>
<el-col
:span=
"8"
>
<el-form-item
label=
"下单日期"
prop=
"orderDate"
>
<el-form-item
label=
"下单日期"
prop=
"orderDate"
>
<el-date-picker
<el-date-picker
v-model=
"formData.orderDate"
v-model=
"formData.orderDate"
placeholder=
"选择下单日期"
placeholder=
"选择下单日期"
type=
"date"
type=
"date"
value-format=
"x"
value-format=
"x"
class=
"!w-1/1"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"12"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"合同金额"
prop=
"price"
>
<el-input
v-model=
"formData.price"
placeholder=
"请输入合同金额"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"开始时间"
prop=
"startTime"
>
<el-form-item
label=
"开始时间"
prop=
"startTime"
>
<el-date-picker
<el-date-picker
v-model=
"formData.startTime"
v-model=
"formData.startTime"
placeholder=
"选择开始时间"
placeholder=
"选择开始时间"
type=
"date"
type=
"date"
value-format=
"x"
value-format=
"x"
class=
"!w-1/1"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"
12
"
>
<el-col
:span=
"
8
"
>
<el-form-item
label=
"结束时间"
prop=
"endTime"
>
<el-form-item
label=
"结束时间"
prop=
"endTime"
>
<el-date-picker
<el-date-picker
v-model=
"formData.endTime"
v-model=
"formData.endTime"
placeholder=
"选择结束时间"
placeholder=
"选择结束时间"
type=
"date"
type=
"date"
value-format=
"x"
value-format=
"x"
class=
"!w-1/1"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"12"
>
</el-row>
<el-row>
<el-col
:span=
"8"
>
<el-form-item
label=
"公司签约人"
prop=
"signUserId"
>
<el-form-item
label=
"公司签约人"
prop=
"signUserId"
>
<el-select
v-model=
"formData.signUserId"
>
<el-select
v-model=
"formData.signUserId"
class=
"w-1/1"
>
<el-option
<el-option
v-for=
"item in user
List
"
v-for=
"item in user
Options
"
:key=
"item.id"
:key=
"item.id"
:label=
"item.nickname"
:label=
"item.nickname"
:value=
"item.id!"
:value=
"item.id!"
...
@@ -89,61 +109,70 @@
...
@@ -89,61 +109,70 @@
</el-select>
</el-select>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"12"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"客户签约人"
prop=
"contactId"
>
<el-form-item
label=
"客户签约人"
prop=
"signContactId"
>
<el-select
v-model=
"formData.contactId"
:disabled=
"!formData.customerId"
>
<el-select
v-model=
"formData.signContactId"
:disabled=
"!formData.customerId"
class=
"w-1/1"
>
<el-option
<el-option
v-for=
"item in getContactOptions"
v-for=
"item in getContactOptions"
:key=
"item.id"
:key=
"item.id"
:label=
"item.name"
:label=
"item.name"
:value=
"item.id
!
"
:value=
"item.id"
/>
/>
</el-select>
</el-select>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"12"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"负责人"
prop=
"ownerUserId"
>
<el-form-item
label=
"备注"
prop=
"remark"
>
<el-select
v-model=
"formData.ownerUserId"
>
<el-input
v-model=
"formData.remark"
placeholder=
"请输入备注"
type=
"textarea"
/>
<el-option
v-for=
"item in userList"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id!"
/>
</el-select>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"24"
>
</el-row>
<el-form-item
label=
"备注"
prop=
"remark"
>
<!-- 子表的表单 -->
<ContentWrap>
<el-tabs
v-model=
"subTabsName"
class=
"-mt-15px -mb-10px"
>
<el-tab-pane
label=
"产品清单"
name=
"product"
>
<ContractProductForm
ref=
"productFormRef"
:products=
"formData.products"
:disabled=
"disabled"
/>
</el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row>
<el-col
:span=
"8"
>
<el-form-item
label=
"产品总金额"
prop=
"totalProductPrice"
>
<el-input
<el-input
v-model=
"formData.remark"
disabled
:rows=
"3"
v-model=
"formData.totalProductPrice"
placeholder=
"请输入备注"
:formatter=
"erpPriceInputFormatter"
type=
"textarea"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<!-- TODO @puhui999:productItems 改成 products 会更好点;因为它不是 item 哈 -->
<el-col
:span=
"8"
>
<el-col
:span=
"24"
>
<el-form-item
label=
"整单折扣(%)"
prop=
"discountPercent"
>
<el-form-item
label=
"产品列表"
prop=
"productList"
>
<ProductList
v-model=
"formData.productItems"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"整单折扣(%)"
prop=
"discountPercent"
>
<el-input-number
<el-input-number
v-model=
"formData.discountPercent"
v-model=
"formData.discountPercent"
:min=
"0"
:max=
"100"
:precision=
"0"
placeholder=
"请输入整单折扣"
placeholder=
"请输入整单折扣"
class=
"!w-100%"
controls-position=
"right"
:min=
"0"
:precision=
"2"
class=
"!w-1/1"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"12"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"产品总金额(元)"
prop=
"productPrice"
>
<el-form-item
label=
"折扣后金额"
prop=
"price"
>
{{
fenToYuan
(
formData
.
productPrice
)
}}
<el-input
disabled
v-model=
"formData.totalPrice"
placeholder=
"请输入商机金额"
:formatter=
"erpPriceInputFormatter"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
@@ -160,8 +189,9 @@ import * as ContractApi from '@/api/crm/contract'
...
@@ -160,8 +189,9 @@ import * as ContractApi from '@/api/crm/contract'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
ContactApi
from
'@/api/crm/contact'
import
*
as
ContactApi
from
'@/api/crm/contact'
import
*
as
BusinessApi
from
'@/api/crm/business'
import
*
as
BusinessApi
from
'@/api/crm/business'
import
ProductList
from
'./components/ProductList.vue'
import
{
erpPriceInputFormatter
,
erpPriceMultiply
}
from
'@/utils'
import
{
fenToYuan
}
from
'@/utils'
import
{
useUserStore
}
from
'@/store/modules/user'
import
ContractProductForm
from
'@/views/crm/contract/components/ContractProductForm.vue'
const
{
t
}
=
useI18n
()
// 国际化
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
const
message
=
useMessage
()
// 消息弹窗
...
@@ -170,30 +200,56 @@ const dialogVisible = ref(false) // 弹窗的是否展示
...
@@ -170,30 +200,56 @@ const dialogVisible = ref(false) // 弹窗的是否展示
const
dialogTitle
=
ref
(
''
)
// 弹窗的标题
const
dialogTitle
=
ref
(
''
)
// 弹窗的标题
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const
formType
=
ref
(
''
)
// 表单的类型:create - 新增;update - 修改
const
formType
=
ref
(
''
)
// 表单的类型:create - 新增;update - 修改
const
formData
=
ref
<
ContractApi
.
ContractVO
>
({}
as
ContractApi
.
ContractVO
)
const
formData
=
ref
({
id
:
undefined
,
no
:
undefined
,
name
:
undefined
,
customerId
:
undefined
,
businessId
:
undefined
,
orderDate
:
undefined
,
startTime
:
undefined
,
endTime
:
undefined
,
signUserId
:
undefined
,
signContactId
:
undefined
,
ownerUserId
:
undefined
,
discountPercent
:
0
,
totalProductPrice
:
undefined
,
remark
:
undefined
,
products
:
[]
})
const
formRules
=
reactive
({
const
formRules
=
reactive
({
name
:
[{
required
:
true
,
message
:
'合同名称不能为空'
,
trigger
:
'blur'
}],
name
:
[{
required
:
true
,
message
:
'合同名称不能为空'
,
trigger
:
'blur'
}],
customerId
:
[{
required
:
true
,
message
:
'客户不能为空'
,
trigger
:
'blur'
}],
customerId
:
[{
required
:
true
,
message
:
'客户不能为空'
,
trigger
:
'blur'
}],
orderDate
:
[{
required
:
true
,
message
:
'下单日期不能为空'
,
trigger
:
'blur'
}],
orderDate
:
[{
required
:
true
,
message
:
'下单日期不能为空'
,
trigger
:
'blur'
}],
ownerUserId
:
[{
required
:
true
,
message
:
'负责人不能为空'
,
trigger
:
'blur'
}],
ownerUserId
:
[{
required
:
true
,
message
:
'负责人不能为空'
,
trigger
:
'blur'
}]
no
:
[{
required
:
true
,
message
:
'合同编号不能为空'
,
trigger
:
'blur'
}]
})
})
const
formRef
=
ref
()
// 表单 Ref
const
formRef
=
ref
()
// 表单 Ref
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
// TODO 芋艿:统一的客户选择面板
const
customerList
=
ref
([])
// 客户列表的数据
const
businessList
=
ref
<
BusinessApi
.
BusinessVO
[]
>
([])
const
contactList
=
ref
<
ContactApi
.
ContactVO
[]
>
([])
/** 监听合同产品变化,计算合同产品总价 */
/** 子表的表单 */
const
subTabsName
=
ref
(
'product'
)
const
productFormRef
=
ref
()
/** 计算 discountPrice、totalPrice 价格 */
watch
(
watch
(
()
=>
formData
.
value
.
productItems
,
()
=>
formData
.
value
,
(
val
)
=>
{
(
val
)
=>
{
if
(
!
val
||
val
.
length
===
0
)
{
if
(
!
val
)
{
formData
.
value
.
productPrice
=
0
return
return
}
}
// 使用 reduce 函数进行累加
const
totalProductPrice
=
val
.
products
.
reduce
((
prev
,
curr
)
=>
prev
+
curr
.
totalPrice
,
0
)
formData
.
value
.
productPrice
=
val
.
reduce
(
const
discountPrice
=
(
accumulator
,
currentValue
)
=>
val
.
discountPercent
!=
null
isNaN
(
accumulator
+
currentValue
.
totalPrice
)
?
0
:
accumulator
+
currentValue
.
totalPrice
,
?
erpPriceMultiply
(
totalProductPrice
,
val
.
discountPercent
/
100.0
)
0
:
0
)
const
totalPrice
=
totalProductPrice
-
discountPrice
// 赋值
formData
.
value
.
totalProductPrice
=
totalProductPrice
formData
.
value
.
totalPrice
=
totalPrice
},
},
{
deep
:
true
}
{
deep
:
true
}
)
)
...
@@ -213,7 +269,18 @@ const open = async (type: string, id?: number) => {
...
@@ -213,7 +269,18 @@ const open = async (type: string, id?: number) => {
formLoading
.
value
=
false
formLoading
.
value
=
false
}
}
}
}
await
getAllApi
()
// 获得客户列表
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
// 获得用户列表
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
// 默认新建时选中自己
if
(
formType
.
value
===
'create'
)
{
formData
.
value
.
ownerUserId
=
useUserStore
().
getUser
.
id
}
// 获取联系人
contactList
.
value
=
await
ContactApi
.
getSimpleContactList
()
// 获得商机列表
businessList
.
value
=
await
BusinessApi
.
getSimpleBusinessList
()
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
...
@@ -226,6 +293,7 @@ const submitForm = async () => {
...
@@ -226,6 +293,7 @@ const submitForm = async () => {
if
(
!
valid
)
return
if
(
!
valid
)
return
// 提交请求
// 提交请求
formLoading
.
value
=
true
formLoading
.
value
=
true
productFormRef
.
value
.
validate
()
try
{
try
{
const
data
=
unref
(
formData
.
value
)
as
unknown
as
ContractApi
.
ContractVO
const
data
=
unref
(
formData
.
value
)
as
unknown
as
ContractApi
.
ContractVO
if
(
formType
.
value
===
'create'
)
{
if
(
formType
.
value
===
'create'
)
{
...
@@ -245,39 +313,35 @@ const submitForm = async () => {
...
@@ -245,39 +313,35 @@ const submitForm = async () => {
/** 重置表单 */
/** 重置表单 */
const
resetForm
=
()
=>
{
const
resetForm
=
()
=>
{
formData
.
value
=
{}
as
ContractApi
.
ContractVO
formData
.
value
=
{
id
:
undefined
,
no
:
undefined
,
name
:
undefined
,
customerId
:
undefined
,
businessId
:
undefined
,
orderDate
:
undefined
,
startTime
:
undefined
,
endTime
:
undefined
,
signUserId
:
undefined
,
signContactId
:
undefined
,
ownerUserId
:
undefined
,
discountPercent
:
0
,
totalProductPrice
:
undefined
,
remark
:
undefined
,
products
:
[]
}
formRef
.
value
?.
resetFields
()
formRef
.
value
?.
resetFields
()
}
}
/** 获取其它相关数据 */
// TODO 芋艿:切换客户时,需要 reset 关联的几个字段
const
getAllApi
=
async
()
=>
{
// TODO 芋艿:选择商机时,需要自动设置
await
Promise
.
all
([
getCustomerList
(),
getUserList
(),
getContactListList
(),
getBusinessList
()])
}
/** 获取客户 */
const
customerList
=
ref
<
CustomerApi
.
CustomerVO
[]
>
([])
const
getCustomerList
=
async
()
=>
{
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
}
/** 动态获取客户联系人 */
/** 动态获取客户联系人 */
const
contactList
=
ref
<
ContactApi
.
ContactVO
[]
>
([])
const
getContactOptions
=
computed
(()
=>
const
getContactOptions
=
computed
(()
=>
contactList
.
value
.
filter
((
item
)
=>
item
.
customerId
===
formData
.
value
.
customerId
)
contactList
.
value
.
filter
((
item
)
=>
item
.
customerId
===
formData
.
value
.
customerId
)
)
)
const
getContactListList
=
async
()
=>
{
/** 动态获取商机 */
contactList
.
value
=
await
ContactApi
.
getSimpleContactList
()
const
getBusinessOptions
=
computed
(()
=>
}
businessList
.
value
.
filter
((
item
)
=>
item
.
customerId
===
formData
.
value
.
customerId
)
)
/** 获取用户列表 */
const
userList
=
ref
<
UserApi
.
UserVO
[]
>
([])
const
getUserList
=
async
()
=>
{
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
}
/** 获取商机 */
const
businessList
=
ref
<
BusinessApi
.
BusinessVO
[]
>
([])
const
getBusinessList
=
async
()
=>
{
businessList
.
value
=
await
BusinessApi
.
getSimpleBusinessList
()
}
</
script
>
</
script
>
src/views/crm/contract/components/ContractProductForm.vue
0 → 100644
View file @
9d44b9ac
<
template
>
<el-form
ref=
"formRef"
:model=
"formData"
:rules=
"formRules"
v-loading=
"formLoading"
label-width=
"0px"
:inline-message=
"true"
:disabled=
"disabled"
>
<el-table
:data=
"formData"
class=
"-mt-10px"
>
<el-table-column
label=
"序号"
type=
"index"
align=
"center"
width=
"60"
/>
<el-table-column
label=
"产品名称"
min-width=
"180"
>
<template
#
default=
"
{ row, $index }">
<el-form-item
:prop=
"`$
{$index}.productId`" :rules="formRules.productId" class="mb-0px!">
<el-select
v-model=
"row.productId"
clearable
filterable
@
change=
"onChangeProduct($event, row)"
placeholder=
"请选择产品"
>
<el-option
v-for=
"item in productList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
</
template
>
</el-table-column>
<el-table-column
label=
"条码"
min-width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-form-item
class=
"mb-0px!"
>
<el-input
disabled
v-model=
"row.productNo"
/>
</el-form-item>
</
template
>
</el-table-column>
<el-table-column
label=
"单位"
min-width=
"80"
>
<
template
#
default=
"{ row }"
>
<dict-tag
:type=
"DICT_TYPE.CRM_PRODUCT_UNIT"
:value=
"row.productUnit"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"价格(元)"
min-width=
"120"
>
<
template
#
default=
"{ row }"
>
<el-form-item
class=
"mb-0px!"
>
<el-input
disabled
v-model=
"row.productPrice"
:formatter=
"erpPriceInputFormatter"
/>
</el-form-item>
</
template
>
</el-table-column>
<el-table-column
label=
"售价(元)"
fixed=
"right"
min-width=
"140"
>
<
template
#
default=
"{ row, $index }"
>
<el-form-item
:prop=
"`$
{$index}.contractPrice`" class="mb-0px!">
<el-input-number
v-model=
"row.contractPrice"
controls-position=
"right"
:min=
"0.001"
:precision=
"2"
class=
"!w-100%"
/>
</el-form-item>
</
template
>
</el-table-column>
<el-table-column
label=
"数量"
prop=
"count"
fixed=
"right"
min-width=
"120"
>
<
template
#
default=
"{ row, $index }"
>
<el-form-item
:prop=
"`$
{$index}.count`" :rules="formRules.count" class="mb-0px!">
<el-input-number
v-model=
"row.count"
controls-position=
"right"
:min=
"0.001"
:precision=
"3"
class=
"!w-100%"
/>
</el-form-item>
</
template
>
</el-table-column>
<el-table-column
label=
"合计"
prop=
"totalPrice"
fixed=
"right"
min-width=
"140"
>
<
template
#
default=
"{ row, $index }"
>
<el-form-item
:prop=
"`$
{$index}.totalPrice`" class="mb-0px!">
<el-input
disabled
v-model=
"row.totalPrice"
:formatter=
"erpPriceInputFormatter"
/>
</el-form-item>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"60"
>
<
template
#
default=
"{ $index }"
>
<el-button
@
click=
"handleDelete($index)"
link
>
—
</el-button>
</
template
>
</el-table-column>
</el-table>
</el-form>
<el-row
justify=
"center"
class=
"mt-3"
v-if=
"!disabled"
>
<el-button
@
click=
"handleAdd"
round
>
+ 添加产品
</el-button>
</el-row>
</template>
<
script
setup
lang=
"ts"
>
import
*
as
ProductApi
from
'@/api/crm/product'
import
{
erpPriceInputFormatter
,
erpPriceMultiply
}
from
'@/utils'
import
{
DICT_TYPE
}
from
'@/utils/dict'
const
props
=
defineProps
<
{
products
:
undefined
disabled
:
false
}
>
()
const
formLoading
=
ref
(
false
)
// 表单的加载中
const
formData
=
ref
([])
const
formRules
=
reactive
({
productId
:
[{
required
:
true
,
message
:
'产品不能为空'
,
trigger
:
'blur'
}],
contractPrice
:
[{
required
:
true
,
message
:
'合同价格不能为空'
,
trigger
:
'blur'
}],
count
:
[{
required
:
true
,
message
:
'产品数量不能为空'
,
trigger
:
'blur'
}]
})
const
formRef
=
ref
([])
// 表单 Ref
const
productList
=
ref
<
ProductApi
.
ProductVO
[]
>
([])
// 产品列表
/** 初始化设置产品项 */
watch
(
()
=>
props
.
products
,
async
(
val
)
=>
{
formData
.
value
=
val
},
{
immediate
:
true
}
)
/** 监听合同产品变化,计算合同产品总价 */
watch
(
()
=>
formData
.
value
,
(
val
)
=>
{
if
(
!
val
||
val
.
length
===
0
)
{
return
}
// 循环处理
val
.
forEach
((
item
)
=>
{
if
(
item
.
contractPrice
!=
null
&&
item
.
count
!=
null
)
{
item
.
totalPrice
=
erpPriceMultiply
(
item
.
contractPrice
,
item
.
count
)
}
else
{
item
.
totalPrice
=
undefined
}
})
},
{
deep
:
true
}
)
/** 新增按钮操作 */
const
handleAdd
=
()
=>
{
const
row
=
{
id
:
undefined
,
productId
:
undefined
,
productUnit
:
undefined
,
// 产品单位
productNo
:
undefined
,
// 产品条码
productPrice
:
undefined
,
// 产品价格
contractPrice
:
undefined
,
count
:
1
}
formData
.
value
.
push
(
row
)
}
/** 删除按钮操作 */
const
handleDelete
=
(
index
:
number
)
=>
{
formData
.
value
.
splice
(
index
,
1
)
}
/** 处理产品变更 */
const
onChangeProduct
=
(
productId
,
row
)
=>
{
const
product
=
productList
.
value
.
find
((
item
)
=>
item
.
id
===
productId
)
if
(
product
)
{
row
.
productUnit
=
product
.
unit
row
.
productNo
=
product
.
no
row
.
productPrice
=
product
.
price
row
.
contractPrice
=
product
.
price
}
}
/** 表单校验 */
const
validate
=
()
=>
{
return
formRef
.
value
.
validate
()
}
defineExpose
({
validate
})
/** 初始化 */
onMounted
(
async
()
=>
{
productList
.
value
=
await
ProductApi
.
getProductSimpleList
()
})
</
script
>
src/views/crm/contract/components/ProductList.vue
deleted
100644 → 0
View file @
11766f51
<!-- 合同 Form 表单下的 Product 列表 -->
<
template
>
<el-row
justify=
"end"
>
<el-button
plain
type=
"primary"
@
click=
"openForm"
>
添加产品
</el-button>
</el-row>
<el-table
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table-column
align=
"center"
label=
"产品名称"
prop=
"name"
width=
"120"
/>
<el-table-column
:formatter=
"fenToYuanFormat"
align=
"center"
label=
"价格"
prop=
"price"
width=
"100"
/>
<el-table-column
align=
"center"
label=
"产品类型"
prop=
"categoryName"
width=
"100"
/>
<el-table-column
align=
"center"
label=
"产品单位"
prop=
"unit"
>
<template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_PRODUCT_UNIT"
:value=
"scope.row.unit"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"产品编码"
prop=
"no"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"数量"
prop=
"count"
width=
"100"
>
<
template
#
default=
"{ row }: { row: ProductApi.ProductExpandVO }"
>
<el-input-number
v-model=
"row.count"
controls-position=
"right"
:min=
"0"
:precision=
"0"
class=
"!w-100%"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
fixed=
"right"
label=
"折扣(%)"
prop=
"discountPercent"
width=
"120"
>
<
template
#
default=
"{ row }: { row: ProductApi.ProductExpandVO }"
>
<el-input-number
v-model=
"row.discountPercent"
controls-position=
"right"
:min=
"0"
:max=
"100"
:precision=
"0"
class=
"!w-100%"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
fixed=
"right"
label=
"合计"
prop=
"totalPrice"
width=
"100"
>
<
template
#
default=
"{ row }: { row: ProductApi.ProductExpandVO }"
>
{{
fenToYuan
(
getTotalPrice
(
row
))
}}
</
template
>
</el-table-column>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"60"
>
<
template
#
default=
"scope"
>
<el-button
link
type=
"danger"
@
click=
"handleDelete(scope.row.id)"
>
移除
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- table 选择表单 -->
<TableSelectForm
ref=
"tableSelectFormRef"
v-model=
"multipleSelection"
title=
"选择产品"
>
<el-table-column
align=
"center"
label=
"产品名称"
prop=
"name"
width=
"160"
/>
<el-table-column
align=
"center"
label=
"产品类型"
prop=
"categoryName"
width=
"160"
/>
<el-table-column
align=
"center"
label=
"产品单位"
prop=
"unit"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_PRODUCT_UNIT"
:value=
"scope.row.unit"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"产品编码"
prop=
"no"
/>
<el-table-column
:formatter=
"fenToYuanFormat"
align=
"center"
label=
"价格(元)"
prop=
"price"
width=
"100"
/>
</TableSelectForm>
</template>
<
script
lang=
"ts"
setup
>
import
*
as
ProductApi
from
'@/api/crm/product'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
fenToYuanFormat
}
from
'@/utils/formatter'
import
{
TableSelectForm
}
from
'@/components/Table/index'
import
{
fenToYuan
,
floatToFixed2
,
yuanToFen
}
from
'@/utils'
defineOptions
({
name
:
'ProductList'
})
const
props
=
withDefaults
(
defineProps
<
{
modelValue
:
ProductApi
.
ProductExpandVO
[]
}
>
(),
{
modelValue
:
()
=>
[]
})
const
emits
=
defineEmits
<
{
(
e
:
'update:modelValue'
,
v
:
any
[]):
void
}
>
()
const
list
=
ref
<
ProductApi
.
ProductExpandVO
[]
>
([])
// 已添加的产品列表
const
multipleSelection
=
ref
<
ProductApi
.
ProductExpandVO
[]
>
([])
// 多选
/** 处理删除 */
const
handleDelete
=
(
id
:
number
)
=>
{
const
index
=
list
.
value
.
findIndex
((
item
)
=>
item
.
id
===
id
)
if
(
index
!==
-
1
)
{
list
.
value
.
splice
(
index
,
1
)
}
}
/** 打开 Product 弹窗 */
const
tableSelectFormRef
=
ref
<
InstanceType
<
typeof
TableSelectForm
>>
()
const
openForm
=
()
=>
{
tableSelectFormRef
.
value
?.
open
(
ProductApi
.
getProductPage
)
}
/** 计算 totalPrice */
const
getTotalPrice
=
computed
(()
=>
(
row
:
ProductApi
.
ProductExpandVO
)
=>
{
const
totalPrice
=
(
Number
(
row
.
price
)
/
100
)
*
Number
(
row
.
count
)
*
(
1
-
Number
(
row
.
discountPercent
)
/
100
)
row
.
totalPrice
=
isNaN
(
totalPrice
)
?
0
:
yuanToFen
(
totalPrice
)
return
isNaN
(
totalPrice
)
?
0
:
totalPrice
.
toFixed
(
2
)
})
/** 编辑时合同产品回显 */
const
isSetListValue
=
ref
(
false
)
// 判断是否已经给 list 赋值过,用于编辑表单产品回显
watch
(
()
=>
props
.
modelValue
,
(
val
)
=>
{
if
(
!
val
||
val
.
length
===
0
||
isSetListValue
.
value
)
{
return
}
list
.
value
=
[
...
props
.
modelValue
.
map
((
item
)
=>
{
item
.
totalPrice
=
floatToFixed2
(
item
.
totalPrice
)
as
unknown
as
number
return
item
})
]
isSetListValue
.
value
=
true
},
{
immediate
:
true
,
deep
:
true
}
)
/** 监听列表变化,动态更新合同产品列表 */
watch
(
list
,
(
val
)
=>
{
if
(
!
val
||
val
.
length
===
0
)
{
return
}
emits
(
'update:modelValue'
,
list
.
value
)
},
{
deep
:
true
}
)
// 监听产品选择结果动态添加产品到列表中,如果产品存在则不放入列表中
watch
(
multipleSelection
,
(
val
)
=>
{
if
(
!
val
||
val
.
length
===
0
)
{
return
}
// 过滤出不在列表中的产品
const
ids
=
list
.
value
.
map
((
item
)
=>
item
.
id
)
const
productList
=
multipleSelection
.
value
.
filter
((
item
)
=>
ids
.
indexOf
(
item
.
id
)
===
-
1
)
if
(
!
productList
||
productList
.
length
===
0
)
{
return
}
list
.
value
.
push
(...
productList
)
},
{
deep
:
true
}
)
</
script
>
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