From 912dd110fbe8c56ccf60a3ba1cac34c37437a7b4 Mon Sep 17 00:00:00 2001 From: zy Date: Wed, 30 Apr 2025 17:59:45 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/crm/customer/index.ts | 5 + src/views/Login/components/LoginForm.vue | 6 +- .../crm/billtemplate/BillTemplateForm.vue | 14 +- .../crm/billtemplate/components/index.vue | 3 +- src/views/crm/billtemplate/index.vue | 2 +- src/views/crm/business/BusinessForm.vue | 47 ++++--- .../components/BusinessProductForm.vue | 2 +- src/views/crm/contact/ContactForm.vue | 13 +- src/views/crm/contract/detail/index.vue | 4 +- src/views/crm/contract/index.vue | 91 ++++++++++--- src/views/crm/customer/CustomerForm.vue | 121 +++++++++++++++++- .../customer/detail/CustomerDetailsInfo.vue | 3 + src/views/crm/customer/detail/index.vue | 2 +- src/views/crm/customer/index.vue | 33 ++++- src/views/crm/quotation/QuotationDetail.vue | 10 +- src/views/crm/quotation/QuotationForm.vue | 48 ++++--- .../components/QuotationProductForm.vue | 23 +++- src/views/crm/quotation/index.vue | 59 ++++++--- 18 files changed, 377 insertions(+), 109 deletions(-) diff --git a/src/api/crm/customer/index.ts b/src/api/crm/customer/index.ts index d149d4e78..6dbfc49d6 100644 --- a/src/api/crm/customer/index.ts +++ b/src/api/crm/customer/index.ts @@ -101,6 +101,11 @@ export const getCustomerSimpleList = async () => { return await request.get({ url: `/crm/customer/simple-list` }) } +// 模糊查询公司 +export const getCompanyList = async (params) => { + return await request.get({ url: `/crm/customer/fuzzyQueryCompany`, params }) +} + // ======================= 业务操作 ======================= // 客户转移 diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue index 58b98ea14..16b0425ee 100644 --- a/src/views/Login/components/LoginForm.vue +++ b/src/views/Login/components/LoginForm.vue @@ -116,8 +116,8 @@ - {{ t('login.otherLogin') }} - + + diff --git a/src/views/crm/billtemplate/BillTemplateForm.vue b/src/views/crm/billtemplate/BillTemplateForm.vue index 09461b382..e6871a232 100644 --- a/src/views/crm/billtemplate/BillTemplateForm.vue +++ b/src/views/crm/billtemplate/BillTemplateForm.vue @@ -120,7 +120,19 @@ const open = async (id?: number, customerId?: number) => { formLoading.value = true try { formData.value = await BillTemplateApi.getBillTemplate(id) - formData.value.products = formData.value.productItems + formData.value.products = formData.value.productItems.map(v => { + return { + category: v.category, + detailType: v.detailType, + productName: v.name, + productId: v.productId, + productInvoice: v.productInvoice, + productInvoiceItems: v.productInvoiceItems, + serviceFeeInvoice: v.serviceFeeInvoice, + serviceFeeInvoiceItems: v.serviceFeeInvoiceItems, + productUnit: v.unit + } + }) } finally { formLoading.value = false } diff --git a/src/views/crm/billtemplate/components/index.vue b/src/views/crm/billtemplate/components/index.vue index 99e03cd28..fe3184e8a 100644 --- a/src/views/crm/billtemplate/components/index.vue +++ b/src/views/crm/billtemplate/components/index.vue @@ -92,7 +92,7 @@ - + 添加产品 + + 添加产品 @@ -130,7 +130,6 @@ watch( const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const getList = (val: []) => { - console.log('%csrc/views/crm/billtemplate/components/index.vue:133 object', 'color: #007acc;', formData.value); for(let i = formData.value.length - 1; i >= 0; i--) { let obj = formData.value[i] if(!val.some(v => v.id === obj.productId)) formData.value.splice(i, 1) diff --git a/src/views/crm/billtemplate/index.vue b/src/views/crm/billtemplate/index.vue index 44d387dd5..e089d4739 100644 --- a/src/views/crm/billtemplate/index.vue +++ b/src/views/crm/billtemplate/index.vue @@ -77,7 +77,7 @@ - + - + @@ -34,6 +34,7 @@ @@ -72,6 +74,7 @@ :data="deptTree" :props="defaultProps" filterable + clearable check-strictly node-key="id" placeholder="请选择归属部门" @@ -109,7 +112,7 @@ - + + - - + + - - + + - + - + @@ -282,7 +286,12 @@ const formRules = reactive({ name: [{ required: true, message: '商机名称不能为空', trigger: 'blur' }], customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }], ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }], - statusTypeId: [{ required: true, message: '商机状态组不能为空', trigger: 'blur' }] + statusTypeId: [{ required: true, message: '商机状态组不能为空', trigger: 'blur' }], + saleStage: [{ required: true, message: '销售阶段不能为空', trigger: 'change' }], + paymentTerm: [{ required: true, message: '账期不能为空', trigger: 'change' }], + creditMethod: [{ required: true, message: '授信方式不能为空', trigger: 'change' }], + techSupport: [{ required: true, message: '技术需求支持不能为空', trigger: 'change' }], + }); const formRef = ref(); const userOptions = ref([]); @@ -323,8 +332,7 @@ watch( watch( () => formData.value.totalPrice, (newProducts) => { - console.log('%csrc/views/crm/business/BusinessForm.vue:326 111', 'color: #007acc;', 111); - formData.value.creditLimit = parseInt(newProducts / 365 * formData.value.creditCalcCycle) + formData.value.creditLimit = parseInt(newProducts / 365 * formData.value.creditCalcCycle) || '' }, { deep: true } @@ -349,9 +357,6 @@ const open = async (id?: number, customerId?: number) => { } } - if (!formType.value) { - formData.value.ownerUserId = useUserStore().getUser.id; - } }; const setList = (newProducts) => { @@ -370,8 +375,9 @@ const daysInMonth = new Date(currentDate.getFullYear(), currentMonth, 0).getDate const { push } = useRouter() const submitForm = async () => { - if (!productFormRef.value) return; - const valid = await productFormRef.value.validate(); + const productFormRef1 = await productFormRef.value.validate(); + if (!productFormRef1) return; + const valid = await formRef.value.validate(); if (!valid) return; formLoading.value = true; @@ -414,8 +420,9 @@ const resetForm = () => { const route = useRoute(); onMounted(async () => { - console.log('%csrc/views/crm/business/BusinessForm.vue:406 getStrDictOptions(DICT_TYPE.PAYMENT_TERM)', 'color: #007acc;', getStrDictOptions(DICT_TYPE.PAYMENT_TERM)); const customerId = route.query.customerId; + console.log('%csrc/views/crm/business/BusinessForm.vue:422 useUserStore().getUser.id', 'color: #007acc;', useUserStore().getUser.id); + formData.value.ownerUserId = customerId ? '' : useUserStore().getUser.id; formType.value = route.query.id; if (formType.value) open(formType.value, customerId) customerList.value = await CustomerApi.getCustomerSimpleList(); diff --git a/src/views/crm/business/components/BusinessProductForm.vue b/src/views/crm/business/components/BusinessProductForm.vue index 175149169..9bf435fad 100644 --- a/src/views/crm/business/components/BusinessProductForm.vue +++ b/src/views/crm/business/components/BusinessProductForm.vue @@ -68,7 +68,7 @@ - + 添加产品 + + 添加产品 diff --git a/src/views/crm/contact/ContactForm.vue b/src/views/crm/contact/ContactForm.vue index 8b81a8a24..72b501983 100644 --- a/src/views/crm/contact/ContactForm.vue +++ b/src/views/crm/contact/ContactForm.vue @@ -74,13 +74,6 @@ - - - - - - - @@ -99,8 +92,6 @@ - - @@ -113,7 +104,7 @@ - + diff --git a/src/views/crm/contract/detail/index.vue b/src/views/crm/contract/detail/index.vue index 788ba070f..8d57b1aa4 100644 --- a/src/views/crm/contract/detail/index.vue +++ b/src/views/crm/contract/detail/index.vue @@ -12,7 +12,7 @@ - + @@ -271,6 +307,7 @@ import * as ContractApi from '@/api/crm/contract' import { DICT_TYPE } from '@/utils/dict' import { erpPriceInputFormatter, erpPriceTableColumnFormatter } from '@/utils' import * as CustomerApi from '@/api/crm/customer' +import { checkPermi } from '@/utils/permission' import { TabsPaneContext } from 'element-plus' defineOptions({ name: 'CrmContract' }) @@ -345,6 +382,22 @@ const handleChange = (row) => { router.push({ name: 'CrmContractChange', query: { id: row.id } }) } +/** 操作分发 */ +const handleCommand = (command: string, row: UserApi.UserVO) => { + switch (command) { + case 'handleSubmit': + handleSubmit(row) + break + case 'handleChange': + handleChange(row) + break + case 'handleDelete': + handleDelete(row.id) + break + default: + break + } +} /** 删除按钮操作 */ const handleDelete = async (id: number) => { diff --git a/src/views/crm/customer/CustomerForm.vue b/src/views/crm/customer/CustomerForm.vue index af53fd37a..190936b00 100644 --- a/src/views/crm/customer/CustomerForm.vue +++ b/src/views/crm/customer/CustomerForm.vue @@ -10,7 +10,20 @@ - + + + @@ -126,7 +139,7 @@ --> - + @@ -163,6 +176,55 @@ --> + + + + + + + + { } finally { formLoading.value = false } - } + } + restaurants.value = await CustomerApi.getCompanyList({companyName: '小米科技有限责任公司'}) // 获得地区列表 areaList.value = await AreaApi.getAreaTree() // 获得用户列表 @@ -310,6 +380,49 @@ const submitForm = async () => { } } +// const loadAll = async (val) => { +// restaurants.value = await CustomerApi.getCompanyList({ +// companyName: val +// }) +// } + +interface RestaurantItem { + value: string + link: string +} +let timeout: ReturnType +const restaurants = ref([]) +const querySearchAsync = async (queryString: string, cb: (arg: any) => void) => { + let data = await CustomerApi.getCompanyList({ + companyName: queryString + }) + restaurants.value = data.list.map(v => { + return { + name: v.name, + value: v.name, + } + }) + console.log('%csrc/views/crm/customer/CustomerForm.vue:400 restaurants.value', 'color: #007acc;', restaurants.value); + const results = queryString + ? restaurants.value.filter(createFilter(queryString)) + : restaurants.value + + clearTimeout(timeout) + timeout = setTimeout(() => { + cb(results) + }, 3000 * Math.random()) +} +const createFilter = (queryString: string) => { + return (restaurant: RestaurantItem) => { + return ( + restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0 + ) + } +} + +const handleSelect = (item: Record) => { + console.log(item) +} /** 重置表单 */ const resetForm = () => { formData.value = { diff --git a/src/views/crm/customer/detail/CustomerDetailsInfo.vue b/src/views/crm/customer/detail/CustomerDetailsInfo.vue index fe240b9ba..c82b5c9f9 100644 --- a/src/views/crm/customer/detail/CustomerDetailsInfo.vue +++ b/src/views/crm/customer/detail/CustomerDetailsInfo.vue @@ -21,6 +21,9 @@ {{ customer.clueDeveloperName }} {{ customer.assistName }} {{ customer.industryId }} + {{ customer.maintainerName }} + {{ customer.contractorName }} + {{ customer.creditNo }} {{ customer.mobile }} {{ customer.telephone }} {{ customer.email }} diff --git a/src/views/crm/customer/detail/index.vue b/src/views/crm/customer/detail/index.vue index c3c9b3709..638e089ca 100644 --- a/src/views/crm/customer/detail/index.vue +++ b/src/views/crm/customer/detail/index.vue @@ -63,7 +63,7 @@ - + diff --git a/src/views/crm/customer/index.vue b/src/views/crm/customer/index.vue index 86bddc0e8..6e93345c1 100644 --- a/src/views/crm/customer/index.vue +++ b/src/views/crm/customer/index.vue @@ -125,14 +125,41 @@ - - - + + + + + + + + + + + + + + + + + + + - + - + + 添加 diff --git a/src/views/crm/contract/components/QuotationList.vue b/src/views/crm/contract/components/QuotationList.vue index 93b5e17ea..59cea07cd 100644 --- a/src/views/crm/contract/components/QuotationList.vue +++ b/src/views/crm/contract/components/QuotationList.vue @@ -112,7 +112,6 @@ const exportLoading = ref(false) // 导出的加载中 const getList = async () => { loading.value = true try { - console.log('%csrc/views/crm/contract/components/QuotationList.vue:112 props.bizId', 'color: #007acc;', props.bizId); queryParams.customerId = props.bizId const data = await QuotationApi.getQuotationPage(queryParams) list.value = data.list diff --git a/src/views/crm/contract/detail/ContractChangeDetail.vue b/src/views/crm/contract/detail/ContractChangeDetail.vue new file mode 100644 index 000000000..2f6aa62c1 --- /dev/null +++ b/src/views/crm/contract/detail/ContractChangeDetail.vue @@ -0,0 +1,429 @@ + + diff --git a/src/views/crm/contract/detail/ContractDetail.vue b/src/views/crm/contract/detail/ContractDetail.vue new file mode 100644 index 000000000..3edf2545c --- /dev/null +++ b/src/views/crm/contract/detail/ContractDetail.vue @@ -0,0 +1,652 @@ + + diff --git a/src/views/crm/contract/detail/index.vue b/src/views/crm/contract/detail/index.vue index 8d57b1aa4..feaca2572 100644 --- a/src/views/crm/contract/detail/index.vue +++ b/src/views/crm/contract/detail/index.vue @@ -6,12 +6,12 @@ - + - + + { } } +const previewFile = (fileUrls) => { + // 假设 fileUrls 是一个字符串,包含文件的完整 URL + if (!fileUrls) { + message.error('没有附件'); + return; + } + + // 检查文件类型 + const fileExtension = fileUrls.split('.').pop().toLowerCase(); + switch (fileExtension) { + case 'pdf': + // 预览 PDF 文件 + window.open(fileUrls, '_blank'); + break; + case 'xlsx': + case 'xls': + // 预览 Excel 文件 + window.open(fileUrls, '_blank'); + break; + case 'doc': + case 'docx': + // 预览 Word 文件 + window.open(fileUrls, '_blank'); + break; + default: + message.error('不支持的文件类型'); + break; + } +}; + /** 初始化 **/ onMounted(() => { getList() diff --git a/src/views/crm/quotation/components/QuotationProductForm.vue b/src/views/crm/quotation/components/QuotationProductForm.vue index 7042e2b67..f8aaad70e 100644 --- a/src/views/crm/quotation/components/QuotationProductForm.vue +++ b/src/views/crm/quotation/components/QuotationProductForm.vue @@ -34,7 +34,7 @@ - + - +