From 6725318f27af0738ef3e44d5a6568baaf4e99899 Mon Sep 17 00:00:00 2001 From: puhui999 <puhui999@163.com> Date: Sat, 24 Feb 2024 23:01:29 +0800 Subject: [PATCH] =?UTF-8?q?CRM=EF=BC=9A=E5=AE=8C=E5=96=84=E5=9B=9E?= =?UTF-8?q?=E6=AC=BE=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/crm/contract/index.ts | 7 + src/api/crm/customer/index.ts | 5 + src/api/crm/receivable/plan/index.ts | 4 +- src/views/crm/customer/CustomerImportForm.vue | 14 +- .../receivable/plan/ReceivablePlanForm.vue | 248 ++++++++++-------- src/views/crm/receivable/plan/index.vue | 147 ++++++----- 6 files changed, 232 insertions(+), 193 deletions(-) diff --git a/src/api/crm/contract/index.ts b/src/api/crm/contract/index.ts index 1115e950..494c60c7 100644 --- a/src/api/crm/contract/index.ts +++ b/src/api/crm/contract/index.ts @@ -65,6 +65,13 @@ export const getContract = async (id: number) => { return await request.get({ url: `/crm/contract/get?id=` + id }) } +// 查询 CRM 合同下拉列表 +export const getCrmContractSimpleListByCustomerId = async (customerId: number) => { + return await request.get({ + url: `/crm/contract/list-all-simple-by-customer?customerId=${customerId}` + }) +} + // 新增 CRM 合同 export const createContract = async (data: ContractVO) => { return await request.post({ url: `/crm/contract/create`, data }) diff --git a/src/api/crm/customer/index.ts b/src/api/crm/customer/index.ts index cc15eb5e..c684e98d 100644 --- a/src/api/crm/customer/index.ts +++ b/src/api/crm/customer/index.ts @@ -90,6 +90,11 @@ export const importCustomerTemplate = () => { return request.download({ url: '/crm/customer/get-import-template' }) } +// 导入客户 +export const handleImport = async (formData) => { + return await request.upload({ url: `/crm/customer/import`, data: formData }) +} + // 客户列表 export const getCustomerSimpleList = async () => { return await request.get({ url: `/crm/customer/simple-list` }) diff --git a/src/api/crm/receivable/plan/index.ts b/src/api/crm/receivable/plan/index.ts index 3ddbd7db..98fadb0d 100644 --- a/src/api/crm/receivable/plan/index.ts +++ b/src/api/crm/receivable/plan/index.ts @@ -4,8 +4,7 @@ export interface ReceivablePlanVO { id: number period: number receivableId: number - status: number - checkStatus: string + finishStatus: number processInstanceId: number price: number returnTime: Date @@ -14,7 +13,6 @@ export interface ReceivablePlanVO { customerId: number contractId: number ownerUserId: number - sort: number remark: string } diff --git a/src/views/crm/customer/CustomerImportForm.vue b/src/views/crm/customer/CustomerImportForm.vue index 4290b361..af802ab2 100644 --- a/src/views/crm/customer/CustomerImportForm.vue +++ b/src/views/crm/customer/CustomerImportForm.vue @@ -4,7 +4,6 @@ <el-upload ref="uploadRef" v-model:file-list="fileList" - :action="importUrl + '?updateSupport=' + updateSupport" :auto-upload="false" :disabled="formLoading" :headers="uploadHeaders" @@ -13,6 +12,7 @@ :on-exceed="handleExceed" :on-success="submitFormSuccess" accept=".xlsx, .xls" + action="none" drag > <Icon icon="ep:upload" /> @@ -45,6 +45,7 @@ import * as CustomerApi from '@/api/crm/customer' import { getAccessToken, getTenantId } from '@/utils/auth' import download from '@/utils/download' +import type { UploadUserFile } from 'element-plus' defineOptions({ name: 'SystemUserImportForm' }) @@ -53,11 +54,9 @@ const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const formLoading = ref(false) // 表单的加载中 const uploadRef = ref() -const importUrl = - import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/crm/customer/import' const uploadHeaders = ref() // 上传 Header 头 -const fileList = ref([]) // 文件列表 -const updateSupport = ref(0) // 是否更新已经存在的客户数据 +const fileList = ref<UploadUserFile[]>([]) // 文件列表 +const updateSupport = ref(false) // 是否更新已经存在的客户数据 /** 打开弹窗 */ const open = () => { @@ -79,7 +78,10 @@ const submitForm = async () => { 'tenant-id': getTenantId() } formLoading.value = true - uploadRef.value!.submit() + const formData = new FormData() + formData.append('updateSupport', updateSupport.value) + formData.append('file', fileList.value[0].raw) + await CustomerApi.handleImport(formData) } /** 文件上传成功 */ diff --git a/src/views/crm/receivable/plan/ReceivablePlanForm.vue b/src/views/crm/receivable/plan/ReceivablePlanForm.vue index 29897b15..b6fa9799 100644 --- a/src/views/crm/receivable/plan/ReceivablePlanForm.vue +++ b/src/views/crm/receivable/plan/ReceivablePlanForm.vue @@ -1,95 +1,119 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" - label-width="100px" - v-loading="formLoading" + label-width="110px" > - <el-form-item label="客户名称" prop="customerId"> - <el-input v-model="formData.customerId" placeholder="请输入客户名称" /> - </el-form-item> - <el-form-item label="合同名称" prop="contractId"> - <el-input v-model="formData.contractId" placeholder="请输入合同名称" /> - </el-form-item> - <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-form-item label="期数" prop="period"> - <el-input-number v-model="formData.period" placeholder="请输入期数" /> - </el-form-item> - <!--<el-form-item label="回款ID" prop="receivableId"> - <el-input v-model="formData.receivableId" placeholder="请输入回款ID" /> - </el-form-item> - <el-form-item label="完成状态" prop="status"> - <el-select v-model="formData.status" placeholder="请选择完成状态"> - <el-option - v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - <el-form-item label="审批状态" prop="checkStatus"> - <el-select v-model="formData.checkStatus" placeholder="请选择审批状态"> - <el-option - v-for="dict in getStrDictOptions(DICT_TYPE.CRM_RECEIVABLE_CHECK_STATUS)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - <el-form-item label="工作流编号" prop="processInstanceId"> - <el-input v-model="formData.processInstanceId" placeholder="请输入工作流编号" /> - </el-form-item>--> - <el-form-item label="计划回款金额" prop="price"> - <el-input-number v-model="formData.price" placeholder="请输入计划回款金额" /> - </el-form-item> - <el-form-item label="计划回款日期" prop="returnTime"> - <el-date-picker - v-model="formData.returnTime" - type="date" - value-format="x" - placeholder="选择计划回款日期" - /> - </el-form-item> - <el-form-item label="提前几天提醒" prop="remindDays"> - <el-input-number v-model="formData.remindDays" placeholder="请输入提前几天提醒" /> - </el-form-item> - <el-form-item label="提醒日期" prop="remindTime"> - <el-date-picker - v-model="formData.remindTime" - type="date" - value-format="x" - placeholder="选择提醒日期" - /> - </el-form-item> - <el-form-item label="显示排序" prop="sort"> - <el-input-number v-model="formData.sort" :min="0" controls-position="right" /> - </el-form-item> - <el-form-item label="备注" prop="remark"> - <el-input type="textarea" :rows="3" v-model="formData.remark" placeholder="请输入备注" /> - </el-form-item> + <el-row> + <el-col :span="12"> + <el-form-item label="客户名称" prop="customerId"> + <el-select v-model="formData.customerId" class="w-1/1" placeholder="请选择客户"> + <el-option + v-for="item in customerList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="合同名称" prop="contractId"> + <el-select + v-model="formData.contractId" + :disabled="!formData.customerId" + class="!w-100%" + placeholder="请选择合同" + > + <el-option + v-for="data in contractList" + :key="data.id" + :label="data.name" + :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" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="计划回款金额" prop="price"> + <el-input-number + v-model="formData.price" + class="!w-100%" + controls-position="right" + placeholder="请输入计划回款金额" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="计划回款日期" prop="returnTime"> + <el-date-picker + v-model="formData.returnTime" + placeholder="选择计划回款日期" + type="date" + value-format="x" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="提前几天提醒" prop="remindDays"> + <el-input-number + v-model="formData.remindDays" + class="!w-100%" + controls-position="right" + placeholder="请输入提前几天提醒" + /> + </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> + </el-col> + <el-col :span="24"> + <el-form-item label="备注" prop="remark"> + <el-input + v-model="formData.remark" + :rows="3" + placeholder="请输入备注" + type="textarea" + /> + </el-form-item> + </el-col> + </el-row> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" setup> import * as ReceivablePlanApi from '@/api/crm/receivable/plan' 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' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const userList = ref<UserApi.UserVO[]>([]) // 用户列表 @@ -97,28 +121,18 @@ const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 -const formData = ref({ - id: undefined, - period: undefined, - receivableId: undefined, - status: undefined, - checkStatus: undefined, - processInstanceId: undefined, - price: undefined, - returnTime: undefined, - remindDays: undefined, - remindTime: undefined, - customerId: undefined, - contractId: undefined, - ownerUserId: undefined, - sort: undefined, - remark: undefined -}) +const formData = ref<ReceivablePlanApi.ReceivablePlanVO>({} as ReceivablePlanApi.ReceivablePlanVO) const formRules = reactive({ - status: [{ required: true, message: '完成状态不能为空', trigger: 'change' }] + 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' }] }) const formRef = ref() // 表单 Ref - +const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表 +const contractList = ref<ContractApi.ContractVO[]>([]) // 合同列表 /** 打开弹窗 */ const open = async (type: string, id?: number) => { dialogVisible.value = true @@ -137,9 +151,31 @@ const open = async (type: string, id?: number) => { // 获得用户列表 userList.value = await UserApi.getSimpleUserList() + // 获得客户列表 + customerList.value = await CustomerApi.getCustomerSimpleList() + // 默认新建时选中自己 + if (formType.value === 'create') { + formData.value.ownerUserId = useUserStore().getUser.id + } } 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 () => { @@ -168,23 +204,7 @@ const submitForm = async () => { /** 重置表单 */ const resetForm = () => { - formData.value = { - id: undefined, - period: undefined, - receivableId: undefined, - status: undefined, - checkStatus: undefined, - processInstanceId: undefined, - price: undefined, - returnTime: undefined, - remindDays: undefined, - remindTime: undefined, - customerId: undefined, - contractId: undefined, - ownerUserId: undefined, - sort: undefined, - remark: undefined - } + formData.value = {} as ReceivablePlanApi.ReceivablePlanVO formRef.value?.resetFields() } </script> diff --git a/src/views/crm/receivable/plan/index.vue b/src/views/crm/receivable/plan/index.vue index decd79bc..16b54aee 100644 --- a/src/views/crm/receivable/plan/index.vue +++ b/src/views/crm/receivable/plan/index.vue @@ -2,49 +2,63 @@ <ContentWrap> <!-- 搜索工作栏 --> <el-form - class="-mb-15px" - :model="queryParams" ref="queryFormRef" :inline="true" + :model="queryParams" + class="-mb-15px" label-width="68px" > <el-form-item label="客户" prop="customerId"> - <el-input + <el-select v-model="queryParams.customerId" - placeholder="请输入客户" - clearable - @keyup.enter="handleQuery" class="!w-240px" - /> + placeholder="请选择客户" + @keyup.enter="handleQuery" + > + <el-option + v-for="item in customerList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> </el-form-item> - <el-form-item label="合同" prop="contractId"> + <el-form-item label="合同编号" prop="contractNo"> <el-input - v-model="queryParams.contractId" - placeholder="请输入合同" - clearable - @keyup.enter="handleQuery" + v-model="queryParams.contractNo" class="!w-240px" + clearable + placeholder="请输入合同编号" + @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> - <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> - <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> - <el-button - type="primary" - plain - @click="openForm('create')" - v-hasPermi="['crm:receivable-plan:create']" - > - <Icon icon="ep:plus" class="mr-5px" /> 新增 + <el-button @click="handleQuery"> + <Icon class="mr-5px" icon="ep:search" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon class="mr-5px" icon="ep:refresh" /> + 重置 </el-button> <el-button - type="success" + v-hasPermi="['crm:receivable-plan:create']" plain - @click="handleExport" - :loading="exportLoading" - v-hasPermi="['crm:receivable-plan:export']" + type="primary" + @click="openForm('create')" > - <Icon icon="ep:download" class="mr-5px" /> 导出 + <Icon class="mr-5px" icon="ep:plus" /> + 新增 + </el-button> + <el-button + v-hasPermi="['crm:receivable-plan:export']" + :loading="exportLoading" + plain + type="success" + @click="handleExport" + > + <Icon class="mr-5px" icon="ep:download" /> + 导出 </el-button> </el-form-item> </el-form> @@ -52,68 +66,58 @@ <!-- 列表 --> <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 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" label="合同编号" prop="contractNo" width="200px" /> + <el-table-column align="center" label="期数" prop="period" /> + <el-table-column align="center" label="计划回款" prop="price" /> <el-table-column - label="计划回款日期" - align="center" - prop="returnTime" :formatter="dateFormatter2" + align="center" + label="计划回款日期" + prop="returnTime" width="180px" /> - <el-table-column label="提前几天提醒" align="center" prop="remindDays" /> - <!--<el-table-column - label="提醒日期" + <el-table-column align="center" label="提前几天提醒" prop="remindDays" width="150" /> + <el-table-column + :formatter="dateFormatter2" align="center" + label="提醒日期" prop="remindTime" - :formatter="dateFormatter" width="180px" - />--> - <!--<el-table-column label="回款ID" align="center" prop="receivableId" />--> - <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"> + /> + <el-table-column label="负责人" prop="ownerUserId" 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 align="center" label="备注" prop="remark" /> <el-table-column - label="创建时间" align="center" - prop="createTime" - :formatter="dateFormatter" - width="180px" - /> - <el-table-column label="操作" align="center" width="130px"> + 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="130px"> <template #default="scope"> <el-button + v-hasPermi="['crm:receivable-plan:update']" link type="primary" @click="openForm('update', scope.row.id)" - v-hasPermi="['crm:receivable-plan:update']" > 编辑 </el-button> <el-button + v-hasPermi="['crm:receivable-plan:delete']" link type="danger" @click="handleDelete(scope.row.id)" - v-hasPermi="['crm:receivable-plan:delete']" > 删除 </el-button> @@ -122,9 +126,9 @@ </el-table> <!-- 分页 --> <Pagination - :total="total" - v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" + v-model:page="queryParams.pageNo" + :total="total" @pagination="getList" /> </ContentWrap> @@ -133,13 +137,14 @@ <ReceivablePlanForm ref="formRef" @success="getList" /> </template> -<script setup lang="ts"> +<script lang="ts" setup> import { DICT_TYPE } from '@/utils/dict' -import { dateFormatter, dateFormatter2 } from '@/utils/formatTime' +import { dateFormatter2 } 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' defineOptions({ name: 'ReceivablePlan' }) @@ -153,8 +158,8 @@ const userList = ref<UserApi.UserVO[]>([]) // 用户列表 const queryParams = reactive({ pageNo: 1, pageSize: 10, - customerId: null, - contractId: null + customerId: undefined, + contractNo: undefined }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 @@ -216,11 +221,13 @@ const handleExport = async () => { exportLoading.value = false } } - +const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表 /** 初始化 **/ onMounted(async () => { await getList() // 获取用户列表 userList.value = await UserApi.getSimpleUserList() + // 获得客户列表 + customerList.value = await CustomerApi.getCustomerSimpleList() }) </script>