From dced551698dd133b87acda47d8e2724e8d01077e Mon Sep 17 00:00:00 2001 From: dhb52 Date: Mon, 16 Oct 2023 23:56:34 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20CRM/=E5=90=88=E5=90=8C=20crud?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/crm/contract/index.ts | 53 +++++ src/views/crm/contract/ContractForm.vue | 228 +++++++++++++++++++++ src/views/crm/contract/contract.data.ts | 227 +++++++++++++++++++++ src/views/crm/contract/index.vue | 253 ++++++++++++++++++++++++ 4 files changed, 761 insertions(+) create mode 100644 src/api/crm/contract/index.ts create mode 100644 src/views/crm/contract/ContractForm.vue create mode 100644 src/views/crm/contract/contract.data.ts create mode 100644 src/views/crm/contract/index.vue diff --git a/src/api/crm/contract/index.ts b/src/api/crm/contract/index.ts new file mode 100644 index 00000000..bf438323 --- /dev/null +++ b/src/api/crm/contract/index.ts @@ -0,0 +1,53 @@ +import request from '@/config/axios' + +export interface ContractVO { + id: number + name: string + customerId: number + businessId: number + processInstanceId: number + orderDate: Date + ownerUserId: number + no: string + startTime: Date + endTime: Date + price: number + discountPercent: number + productPrice: number + roUserIds: string + rwUserIds: string + contactId: number + signUserId: number + contactLastTime: Date + remark: string +} + +// 查询合同列表 +export const getContractPage = async (params) => { + return await request.get({ url: `/crm/contract/page`, params }) +} + +// 查询合同详情 +export const getContract = async (id: number) => { + return await request.get({ url: `/crm/contract/get?id=` + id }) +} + +// 新增合同 +export const createContract = async (data: ContractVO) => { + return await request.post({ url: `/crm/contract/create`, data }) +} + +// 修改合同 +export const updateContract = async (data: ContractVO) => { + return await request.put({ url: `/crm/contract/update`, data }) +} + +// 删除合同 +export const deleteContract = async (id: number) => { + return await request.delete({ url: `/crm/contract/delete?id=` + id }) +} + +// 导出合同 Excel +export const exportContract = async (params) => { + return await request.download({ url: `/crm/contract/export-excel`, params }) +} diff --git a/src/views/crm/contract/ContractForm.vue b/src/views/crm/contract/ContractForm.vue new file mode 100644 index 00000000..5d5578f9 --- /dev/null +++ b/src/views/crm/contract/ContractForm.vue @@ -0,0 +1,228 @@ + + diff --git a/src/views/crm/contract/contract.data.ts b/src/views/crm/contract/contract.data.ts new file mode 100644 index 00000000..7550677b --- /dev/null +++ b/src/views/crm/contract/contract.data.ts @@ -0,0 +1,227 @@ +import type { CrudSchema } from '@/hooks/web/useCrudSchemas' +import { dateFormatter } from '@/utils/formatTime' + +// 表单校验 +export const rules = reactive({ + name: [required] +}) + +// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/ +const crudSchemas = reactive([ + { + label: '合同编号', + field: 'id', + isForm: false + }, + { + label: '合同名称', + field: 'name', + isSearch: true + }, + { + label: '客户编号', + field: 'customerId', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '商机编号', + field: 'businessId', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '工作流编号', + field: 'processInstanceId', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '下单日期', + field: 'orderDate', + formatter: dateFormatter, + isSearch: true, + search: { + component: 'DatePicker', + componentProps: { + valueFormat: 'YYYY-MM-DD HH:mm:ss', + type: 'daterange', + defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] + } + }, + form: { + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'x' + } + } + }, + { + label: '负责人的用户编号', + field: 'ownerUserId', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '创建时间', + field: 'createTime', + formatter: dateFormatter, + isSearch: true, + search: { + component: 'DatePicker', + componentProps: { + valueFormat: 'YYYY-MM-DD HH:mm:ss', + type: 'daterange', + defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] + } + }, + isForm: false + }, + { + label: '合同编号', + field: 'no', + isSearch: true + }, + { + label: '开始时间', + field: 'startTime', + formatter: dateFormatter, + isSearch: true, + search: { + component: 'DatePicker', + componentProps: { + valueFormat: 'YYYY-MM-DD HH:mm:ss', + type: 'daterange', + defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] + } + }, + form: { + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'x' + } + } + }, + { + label: '结束时间', + field: 'endTime', + formatter: dateFormatter, + isSearch: true, + search: { + component: 'DatePicker', + componentProps: { + valueFormat: 'YYYY-MM-DD HH:mm:ss', + type: 'daterange', + defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] + } + }, + form: { + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'x' + } + } + }, + { + label: '合同金额', + field: 'price', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '整单折扣', + field: 'discountPercent', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '产品总金额', + field: 'productPrice', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '只读权限的用户编号数组', + field: 'roUserIds', + isSearch: true + }, + { + label: '读写权限的用户编号数组', + field: 'rwUserIds', + isSearch: true + }, + { + label: '联系人编号', + field: 'contactId', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '备注', + field: 'remark', + isSearch: true + }, + { + label: '公司签约人', + field: 'signUserId', + isSearch: true, + form: { + component: 'InputNumber', + value: 0 + } + }, + { + label: '最后跟进时间', + field: 'contactLastTime', + formatter: dateFormatter, + isSearch: true, + search: { + component: 'DatePicker', + componentProps: { + valueFormat: 'YYYY-MM-DD HH:mm:ss', + type: 'daterange', + defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] + } + }, + form: { + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'x' + } + } + }, + { + label: '操作', + field: 'action', + isForm: false + } +]) +export const { allSchemas } = useCrudSchemas(crudSchemas) diff --git a/src/views/crm/contract/index.vue b/src/views/crm/contract/index.vue new file mode 100644 index 00000000..7a8211be --- /dev/null +++ b/src/views/crm/contract/index.vue @@ -0,0 +1,253 @@ + + + From c27685285a6dfac271b4337f46ab6c5067624cee Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 17 Oct 2023 19:50:09 +0800 Subject: [PATCH 2/7] =?UTF-8?q?code=20review=EF=BC=9A=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E7=9A=84=E5=AE=A1=E6=89=B9=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProcessInstanceChildrenTaskList.vue | 49 +++++++++---------- .../detail/TaskAddSignDialogForm.vue | 12 ++--- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceChildrenTaskList.vue b/src/views/bpm/processInstance/detail/ProcessInstanceChildrenTaskList.vue index f162d1fb..363874cf 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceChildrenTaskList.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceChildrenTaskList.vue @@ -1,13 +1,20 @@ @@ -53,12 +59,11 @@ import { DICT_TYPE } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import TaskSubSignDialogForm from './TaskSubSignDialogForm.vue' -const message = useMessage() // 消息弹窗 -defineOptions({ name: 'ProcessInstancechildrenList' }) +defineOptions({ name: 'ProcessInstanceChildrenTaskList' }) +const message = useMessage() // 消息弹窗 const drawerVisible = ref(false) // 抽屉的是否展示 -const tableData = ref([]) //表格数据 const baseTask = ref({}) /** 打开弹窗 */ const open = async (task: any) => { @@ -67,30 +72,22 @@ const open = async (task: any) => { return } baseTask.value = task - //设置表格数据 - tableData.value = task.children - //展开抽屉 + // 展开抽屉 drawerVisible.value = true } defineExpose({ open }) // 提供 openModal 方法,用于打开弹窗 -const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 - -/** - * 减签 - */ +/** 发起减签 */ const taskSubSignDialogForm = ref() const handleSubSign = (item) => { taskSubSignDialogForm.value.open(item.id) + // TODO @海洋:减签后,需要刷新下界面哈 } -/** - * 显示减签按钮 - * @param task - */ -const showSubSignButton = (task:any) => { - if(!isEmpty(task.children)){ - //有子任务,且子任务有任意一个是 待处理 和 待前置任务完成 则显示减签按钮 +/** 是否显示减签按钮 */ +const isSubSignButtonVisible = (task: any) => { + if (task && task.children && !isEmpty(task.children)) { + // 有子任务,且子任务有任意一个是 待处理 和 待前置任务完成 则显示减签按钮 const subTask = task.children.find((item) => item.result === 1 || item.result === 9) return !isEmpty(subTask) } diff --git a/src/views/bpm/processInstance/detail/TaskAddSignDialogForm.vue b/src/views/bpm/processInstance/detail/TaskAddSignDialogForm.vue index 4b91c9b9..40cd200e 100644 --- a/src/views/bpm/processInstance/detail/TaskAddSignDialogForm.vue +++ b/src/views/bpm/processInstance/detail/TaskAddSignDialogForm.vue @@ -22,12 +22,12 @@ From d5328918ab91235de633fe252591ad2831a68b86 Mon Sep 17 00:00:00 2001 From: "1163996518@qq.com" <1163996518@qq.com> Date: Tue, 17 Oct 2023 20:58:28 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=94=AF=E4=BB=98=E6=B8=A0=E9=81=93?= =?UTF-8?q?=E9=85=8D=E7=BD=AE--=E4=BF=AE=E5=A4=8D=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/pay/app/index.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/pay/app/index.vue b/src/views/pay/app/index.vue index c949637b..7b8f1a96 100644 --- a/src/views/pay/app/index.vue +++ b/src/views/pay/app/index.vue @@ -51,7 +51,7 @@ type="primary" plain @click="openForm('create')" - v-hasPermi="['system:tenant:create']" + v-hasPermi="['pay:app:create']" > 新增 @@ -266,7 +266,7 @@ link type="primary" @click="openForm('update', scope.row.id)" - v-hasPermi="['system:tenant:update']" + v-hasPermi="['pay:app:update']" > 编辑 @@ -274,7 +274,7 @@ link type="danger" @click="handleDelete(scope.row.id)" - v-hasPermi="['system:tenant:delete']" + v-hasPermi="['pay:app:delete']" > 删除 From 533b4e5006c13892eba5e5b4e9cbd8840b65a35d Mon Sep 17 00:00:00 2001 From: "1163996518@qq.com" <1163996518@qq.com> Date: Tue, 17 Oct 2023 21:27:13 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E6=94=AF=E4=BB=98=E6=B8=A0=E9=81=93?= =?UTF-8?q?=E9=85=8D=E7=BD=AE--=E4=BF=AE=E5=A4=8D=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/pay/app/index.vue | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/views/pay/app/index.vue b/src/views/pay/app/index.vue index 7b8f1a96..3531633f 100644 --- a/src/views/pay/app/index.vue +++ b/src/views/pay/app/index.vue @@ -47,12 +47,7 @@ 搜索 重置 - + 新增 From 8832eafaae327cf11e2918991cbe3c9939eeb386 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 17 Oct 2023 22:52:24 +0800 Subject: [PATCH 5/7] =?UTF-8?q?code=20review=EF=BC=9Acrm=20=E5=90=88?= =?UTF-8?q?=E5=90=8C=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/crm/contract/contract.data.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/crm/contract/contract.data.ts b/src/views/crm/contract/contract.data.ts index 7550677b..07458c24 100644 --- a/src/views/crm/contract/contract.data.ts +++ b/src/views/crm/contract/contract.data.ts @@ -6,6 +6,7 @@ export const rules = reactive({ name: [required] }) +// TODO @dbh52:不使用 crud 模式哈,使用标准的 ep 代码哈;主要后续 crud schema 可能会改 // CrudSchema https://doc.iocoder.cn/vue3/crud-schema/ const crudSchemas = reactive([ { From 7af2a3bcc31dcfdc65db4fec968008b3a834bd2e Mon Sep 17 00:00:00 2001 From: "913752709@qq.com" <913752709@qq.com> Date: Wed, 18 Oct 2023 20:02:59 +0800 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20CRM=20=E7=BA=BF=E7=B4=A2=E8=A1=A8?= =?UTF-8?q?=20crud?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/crm/clue/index.ts | 46 +++++ src/views/crm/clue/ClueForm.vue | 165 +++++++++++++++++ src/views/crm/clue/index.vue | 318 ++++++++++++++++++++++++++++++++ 3 files changed, 529 insertions(+) create mode 100644 src/api/crm/clue/index.ts create mode 100644 src/views/crm/clue/ClueForm.vue create mode 100644 src/views/crm/clue/index.vue diff --git a/src/api/crm/clue/index.ts b/src/api/crm/clue/index.ts new file mode 100644 index 00000000..39da03d3 --- /dev/null +++ b/src/api/crm/clue/index.ts @@ -0,0 +1,46 @@ +import request from '@/config/axios' + +export interface ClueVO { + id: number + transformStatus: boolean + followUpStatus: boolean + name: string + customerId: number + contactNextTime: Date + telephone: string + mobile: string + address: string + ownerUserId: number + contactLastTime: Date + remark: string +} + +// 查询线索列表 +export const getCluePage = async (params) => { + return await request.get({ url: `/crm/clue/page`, params }) +} + +// 查询线索详情 +export const getClue = async (id: number) => { + return await request.get({ url: `/crm/clue/get?id=` + id }) +} + +// 新增线索 +export const createClue = async (data: ClueVO) => { + return await request.post({ url: `/crm/clue/create`, data }) +} + +// 修改线索 +export const updateClue = async (data: ClueVO) => { + return await request.put({ url: `/crm/clue/update`, data }) +} + +// 删除线索 +export const deleteClue = async (id: number) => { + return await request.delete({ url: `/crm/clue/delete?id=` + id }) +} + +// 导出线索 Excel +export const exportClue = async (params) => { + return await request.download({ url: `/crm/clue/export-excel`, params }) +} diff --git a/src/views/crm/clue/ClueForm.vue b/src/views/crm/clue/ClueForm.vue new file mode 100644 index 00000000..e72e4228 --- /dev/null +++ b/src/views/crm/clue/ClueForm.vue @@ -0,0 +1,165 @@ + + diff --git a/src/views/crm/clue/index.vue b/src/views/crm/clue/index.vue new file mode 100644 index 00000000..42f20545 --- /dev/null +++ b/src/views/crm/clue/index.vue @@ -0,0 +1,318 @@ + + + From 3074adb1df8d7bc8321912d5f918a1035aa83d42 Mon Sep 17 00:00:00 2001 From: "1351515658@qq.com" <1351515658@qq.com> Date: Thu, 19 Oct 2023 18:43:02 +0800 Subject: [PATCH 7/7] =?UTF-8?q?fix=20=E5=AE=A1=E6=89=B9=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=BC=95=E5=85=A5TaskDelegateForm.vue=20?= =?UTF-8?q?=E4=B8=8D=E5=85=BC=E5=AE=B9liunx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/bpm/processInstance/detail/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/bpm/processInstance/detail/index.vue b/src/views/bpm/processInstance/detail/index.vue index f9c5452b..ba6c1298 100644 --- a/src/views/bpm/processInstance/detail/index.vue +++ b/src/views/bpm/processInstance/detail/index.vue @@ -114,7 +114,7 @@ import TaskUpdateAssigneeForm from './TaskUpdateAssigneeForm.vue' import ProcessInstanceBpmnViewer from './ProcessInstanceBpmnViewer.vue' import ProcessInstanceTaskList from './ProcessInstanceTaskList.vue' import TaskReturnDialog from './TaskReturnDialogForm.vue' -import TaskDelegateForm from './taskDelegateForm.vue' +import TaskDelegateForm from './TaskDelegateForm.vue' import TaskAddSignDialogForm from './TaskAddSignDialogForm.vue' import { registerComponent } from '@/utils/routerHelper' import { isEmpty } from '@/utils/is'