Commit ed94205f by puhui999

CRM-合同:完善合同表单

parent a64d4240
import request from '@/config/axios' import request from '@/config/axios'
import { TransferReqVO } from '@/api/crm/customer'
export interface BusinessVO { export interface BusinessVO {
id: number id: number
...@@ -70,3 +71,8 @@ export const getBusinessPageByContact = async (params) => { ...@@ -70,3 +71,8 @@ export const getBusinessPageByContact = async (params) => {
export const getBusinessListByIds = async (val: number[]) => { export const getBusinessListByIds = async (val: number[]) => {
return await request.get({ url: '/crm/business/list-by-ids', params: { ids: val.join(',') } }) return await request.get({ url: '/crm/business/list-by-ids', params: { ids: val.join(',') } })
} }
// 商机转移
export const transfer = async (data: TransferReqVO) => {
return await request.put({ url: '/crm/business/transfer', data })
}
import request from '@/config/axios' import request from '@/config/axios'
import { ProductExpandVO } from '@/api/crm/product'
export interface ContractVO { export interface ContractVO {
id: number id: number
...@@ -20,6 +21,7 @@ export interface ContractVO { ...@@ -20,6 +21,7 @@ export interface ContractVO {
signUserId: number signUserId: number
contactLastTime: Date contactLastTime: Date
remark: string remark: string
productItems: ProductExpandVO[]
} }
// 查询 CRM 合同列表 // 查询 CRM 合同列表
......
...@@ -12,6 +12,12 @@ export interface ProductVO { ...@@ -12,6 +12,12 @@ export interface ProductVO {
ownerUserId: number ownerUserId: number
} }
export interface ProductExpandVO extends ProductVO {
count: number
discountPercent: number
totalPrice: number
}
// 查询产品列表 // 查询产品列表
export const getProductPage = async (params) => { export const getProductPage = async (params) => {
return await request.get({ url: `/crm/product/page`, params }) return await request.get({ url: `/crm/product/page`, params })
......
import Table from './src/Table.vue' import Table from './src/Table.vue'
import { ElTable } from 'element-plus' import { ElTable } from 'element-plus'
import { TableSetPropsType } from '@/types/table' import { TableSetPropsType } from '@/types/table'
import TableSelectForm from './src/TableSelectForm.vue'
export interface TableExpose { export interface TableExpose {
setProps: (props: Recordable) => void setProps: (props: Recordable) => void
...@@ -9,4 +10,4 @@ export interface TableExpose { ...@@ -9,4 +10,4 @@ export interface TableExpose {
elTableRef: ComponentRef<typeof ElTable> elTableRef: ComponentRef<typeof ElTable>
} }
export { Table } export { Table, TableSelectForm }
<template>
<Dialog v-model="dialogVisible" :appendToBody="true" :scroll="true" :title="title" width="60%">
<el-table
ref="multipleTableRef"
v-loading="loading"
:data="list"
:show-overflow-tooltip="true"
:stripe="true"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" />
<slot></slot>
</el-table>
<!-- 分页 -->
<Pagination
v-model:limit="queryParams.pageSize"
v-model:page="queryParams.pageNo"
:total="total"
@pagination="getList"
/>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { ElTable } from 'element-plus'
defineOptions({ name: 'TableSelectForm' })
withDefaults(
defineProps<{
modelValue: any[]
title: string
}>(),
{ modelValue: () => [], title: '选择' }
)
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const loading = ref(false) // 列表的加载中
const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false)
const queryParams = reactive({
pageNo: 1,
pageSize: 10
})
// 确认选择时的触发事件
const emits = defineEmits<{
(e: 'update:modelValue', v: number[]): void
}>()
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
const multipleSelection = ref<any[]>([])
const handleSelectionChange = (val: any[]) => {
multipleSelection.value = val
}
/** 触发 */
const submitForm = () => {
formLoading.value = true
try {
emits('update:modelValue', multipleSelection.value) // 返回选择的原始数据由使用方处理
} finally {
formLoading.value = false
// 关闭弹窗
dialogVisible.value = false
}
}
const getList = async (getListFunc: Function) => {
loading.value = true
try {
const data = await getListFunc(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 打开弹窗 */
const open = async (getListFunc: Function) => {
dialogVisible.value = true
await nextTick()
if (multipleSelection.value.length > 0) {
multipleTableRef.value!.clearSelection()
}
await getList(getListFunc)
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
</script>
<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="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"
/>
<el-table-column align="center" label="数量" prop="count" width="200">
<template #default="{ row }: { row: ProductApi.ProductExpandVO }">
<el-input-number v-model="row.count" class="!w-100%" />
</template>
</el-table-column>
<el-table-column align="center" label="折扣(%)" prop="discountPercent" width="200">
<template #default="{ row }: { row: ProductApi.ProductExpandVO }">
<el-input-number v-model="row.discountPercent" class="!w-100%" />
</template>
</el-table-column>
<el-table-column align="center" label="合计" prop="totalPrice" width="100">
<template #default="{ row }: { row: ProductApi.ProductExpandVO }">
{{ getTotalPrice(row) }}
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="130">
<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'
defineOptions({ name: 'ProductList' })
withDefaults(defineProps<{ modelValue: any[] }>(), { modelValue: () => [] })
const emits = defineEmits<{
(e: 'update:modelValue', v: any[]): void
}>()
const list = ref<ProductApi.ProductExpandVO[]>([])
const handleDelete = (id: number) => {
const index = list.value.findIndex((item) => item.id === id)
if (index !== -1) {
list.value.splice(index, 1)
}
}
const tableSelectFormRef = ref<InstanceType<typeof TableSelectForm>>()
const multipleSelection = ref<ProductApi.ProductExpandVO[]>([])
const openForm = () => {
tableSelectFormRef.value?.open(ProductApi.getProductPage)
}
const getTotalPrice = computed(() => (row: ProductApi.ProductExpandVO) => {
const totalPrice = (row.price * row.count * row.discountPercent) / 100
row.totalPrice = isNaN(totalPrice) ? 0 : totalPrice
return isNaN(totalPrice) ? 0 : totalPrice
})
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)
list.value.push(...multipleSelection.value.filter((item) => ids.indexOf(item.id) === -1))
},
{ deep: true }
)
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment