From 7a8ac4cfe6297f4eb5077d16af5a558aabba5578 Mon Sep 17 00:00:00 2001 From: Vinjor Date: Tue, 2 Dec 2025 15:07:54 +0800 Subject: [PATCH] 1 --- .../cus/controller/CusContactsController.java | 21 ++- .../cus/controller/CusMainController.java | 13 +- .../cus/service/ICusContactsService.java | 8 + .../service/impl/CusContactsServiceImpl.java | 21 +++ .../cus/service/impl/CusMainServiceImpl.java | 46 +++--- .../src/main/resources/application-druid.yml | 2 +- dl_vue/src/api/cus/contacts.js | 9 + dl_vue/src/views/cus/contacts/editForm.vue | 20 ++- dl_vue/src/views/cus/main/checkCus.vue | 154 ++++++++++++++++++ dl_vue/src/views/cus/main/drawForm.vue | 22 ++- dl_vue/src/views/cus/main/index.vue | 45 +++-- dl_vue/src/views/cus/main/newForm.vue | 28 +++- dl_vue/src/views/cus/main/viewForm.vue | 3 +- 13 files changed, 333 insertions(+), 59 deletions(-) create mode 100644 dl_vue/src/views/cus/main/checkCus.vue diff --git a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/controller/CusContactsController.java b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/controller/CusContactsController.java index 5a98354..f973c33 100644 --- a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/controller/CusContactsController.java +++ b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/controller/CusContactsController.java @@ -35,8 +35,7 @@ import com.ruoyi.common.core.page.TableDataInfo; */ @RestController @RequestMapping("/cus/contacts") -public class CusContactsController extends BaseController -{ +public class CusContactsController extends BaseController { @Autowired private ICusContactsService cusContactsService; @Autowired @@ -129,4 +128,22 @@ public class CusContactsController extends BaseController List list = new ArrayList<>(Arrays.asList(ids)); return toAjax(cusContactsService.removeByIds(list)); } + + /** + * 校验重复客户 + * @author vinjor-M + * @date 11:21 2025/12/2 + * @param cusContacts TODO + * @return com.ruoyi.common.core.domain.AjaxResult + **/ + @Log(title = "校验重复客户", businessType = BusinessType.INSERT) + @PostMapping("/checkCus") + public AjaxResult checkCus(@RequestBody CusContacts cusContacts) { + try { + cusContactsService.checkCus(cusContacts); + return success(); + }catch (Exception e){ + return error(e.getMessage()); + } + } } diff --git a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/controller/CusMainController.java b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/controller/CusMainController.java index b9a6013..6906cc7 100644 --- a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/controller/CusMainController.java +++ b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/controller/CusMainController.java @@ -17,9 +17,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.cus.domain.CusMainSeas; -import com.ruoyi.cus.domain.CusManager; -import com.ruoyi.cus.domain.CusTimeAxis; +import com.ruoyi.cus.domain.*; import com.ruoyi.cus.service.*; import com.ruoyi.cus.vo.CusMainVO; import com.ruoyi.cus.vo.MainVO; @@ -40,7 +38,6 @@ import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.cus.domain.CusMain; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.core.page.TableDataInfo; import org.springframework.web.multipart.MultipartFile; @@ -171,6 +168,14 @@ public class CusMainController extends BaseController { @PostMapping public AjaxResult add(@RequestBody CusMainVO cusMainVO) { if (StringUtils.isEmpty(cusMainVO.getMainInfo().getId())) { + //新增客户,需要根据联系人姓名、电话、邮箱验证是否重复 + try { + //直接取第一个联系人 + CusContacts cusContacts = cusMainVO.getContact().get(0); + cusContactsService.checkCus(cusContacts); + }catch (Exception e){ + return error(e.getMessage()); + } cusMainVO.getMainInfo().setCusCode(codeGenerator.generate()); } cusMainService.saveNewCus(cusMainVO); diff --git a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/ICusContactsService.java b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/ICusContactsService.java index 9145163..ca44914 100644 --- a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/ICusContactsService.java +++ b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/ICusContactsService.java @@ -48,4 +48,12 @@ public interface ICusContactsService extends IService { * @param cusId 客户id **/ void deleteCusData(String cusId); + + /** + * 校验重复客户 + * @author vinjor-M + * @date 11:22 2025/12/2 + * @param cusContacts 客户联系人信息对象 + **/ + void checkCus(CusContacts cusContacts); } diff --git a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/impl/CusContactsServiceImpl.java b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/impl/CusContactsServiceImpl.java index 8fc3339..b7cd5cb 100644 --- a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/impl/CusContactsServiceImpl.java +++ b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/impl/CusContactsServiceImpl.java @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.domain.DlBaseEntity; import com.ruoyi.common.utils.StringUtils; +import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -132,4 +133,24 @@ public class CusContactsServiceImpl extends ServiceImpl queryWrapper = new LambdaQueryWrapper() + .apply("UPPER(name) = UPPER({0})", cusContacts.getName()) + .eq(CusContacts::getEmail, cusContacts.getEmail()) + .eq(CusContacts::getTelephone, cusContacts.getTelephone()); + List contacts = this.list(queryWrapper); + if(!contacts.isEmpty()){ + throw new Exception("存在重复的客户!"); + } + } } diff --git a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/impl/CusMainServiceImpl.java b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/impl/CusMainServiceImpl.java index 179a3e5..8e1e7a7 100644 --- a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/impl/CusMainServiceImpl.java +++ b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/cus/service/impl/CusMainServiceImpl.java @@ -70,28 +70,30 @@ public class CusMainServiceImpl extends ServiceImpl impl @DataScope(deptAlias = "cm", userAlias = "cm") public IPage queryListPage(MainVO pageReqVO, Page page) { IPage list = cusMainMapper.queryListPage(pageReqVO, page); - List cusIdList = list.getRecords().stream().map(MainVO::getId).collect(Collectors.toList()); - //公司信息 - List companyList = cusCompanyService.list(new LambdaQueryWrapper().in(CusCompany::getCusId, cusIdList).eq(DlBaseEntity::getDelFlag,'0')); - Map companyMap = companyList.stream().collect(Collectors.toMap(CusCompany::getCusId, Function.identity())); - //联系人信息 - List contacts = cusContactsService.list(new LambdaQueryWrapper().in(CusContacts::getCusId, cusIdList).eq(DlBaseEntity::getDelFlag,'0').eq(CusContacts::getIfDefault,true)); - Map contactsMap = contacts.stream().collect(Collectors.toMap(CusContacts::getCusId, Function.identity())); - list.getRecords().forEach(item->{ - if(StringUtils.isNotEmpty(item.getCusLabels())){ - item.setCusLabelList(JSON.parseArray(item.getCusLabels())); - } - if(companyMap.containsKey(item.getId())){ - CusCompany company = companyMap.get(item.getId()); - item.setCusFrom(company.getCusFrom()); - item.setCusLevel(company.getCusLevel()); - item.setBusiType(company.getBusiType()); - item.setContactAddress(company.getContactAddress()); - } - if(contactsMap.containsKey(item.getId())){ - item.setContactName(contactsMap.get(item.getId()).getName()); - } - }); + if(!list.getRecords().isEmpty()){ + List cusIdList = list.getRecords().stream().map(MainVO::getId).collect(Collectors.toList()); + //公司信息 + List companyList = cusCompanyService.list(new LambdaQueryWrapper().in(CusCompany::getCusId, cusIdList).eq(DlBaseEntity::getDelFlag,'0')); + Map companyMap = companyList.stream().collect(Collectors.toMap(CusCompany::getCusId, Function.identity())); + //联系人信息 + List contacts = cusContactsService.list(new LambdaQueryWrapper().in(CusContacts::getCusId, cusIdList).eq(DlBaseEntity::getDelFlag,'0').eq(CusContacts::getIfDefault,true)); + Map contactsMap = contacts.stream().collect(Collectors.toMap(CusContacts::getCusId, Function.identity())); + list.getRecords().forEach(item->{ + if(StringUtils.isNotEmpty(item.getCusLabels())){ + item.setCusLabelList(JSON.parseArray(item.getCusLabels())); + } + if(companyMap.containsKey(item.getId())){ + CusCompany company = companyMap.get(item.getId()); + item.setCusFrom(company.getCusFrom()); + item.setCusLevel(company.getCusLevel()); + item.setBusiType(company.getBusiType()); + item.setContactAddress(company.getContactAddress()); + } + if(contactsMap.containsKey(item.getId())){ + item.setContactName(contactsMap.get(item.getId()).getName()); + } + }); + } return list; } diff --git a/dl_admin/ruoyi-admin/src/main/resources/application-druid.yml b/dl_admin/ruoyi-admin/src/main/resources/application-druid.yml index 9630cf4..ae1238f 100644 --- a/dl_admin/ruoyi-admin/src/main/resources/application-druid.yml +++ b/dl_admin/ruoyi-admin/src/main/resources/application-druid.yml @@ -6,7 +6,7 @@ spring: druid: # 主库数据源 master: - url: jdbc:mysql://rm-bp1msd0a4kq4t7a66lo.mysql.rds.aliyuncs.com:3306/dl_crm_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + url: jdbc:mysql://rm-bp1msd0a4kq4t7a66lo.mysql.rds.aliyuncs.com:3306/dl_crm_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: csd_rw password: Csd2025#123 # 从库数据源 diff --git a/dl_vue/src/api/cus/contacts.js b/dl_vue/src/api/cus/contacts.js index 48371d0..c430818 100644 --- a/dl_vue/src/api/cus/contacts.js +++ b/dl_vue/src/api/cus/contacts.js @@ -50,3 +50,12 @@ export function delContacts(id) { method: 'delete' }) } + +// 校验重复客户 +export function checkCus(data) { + return request({ + url: '/cus/contacts/checkCus', + method: 'post', + data: data + }) +} diff --git a/dl_vue/src/views/cus/contacts/editForm.vue b/dl_vue/src/views/cus/contacts/editForm.vue index 82de033..0fa2fe2 100644 --- a/dl_vue/src/views/cus/contacts/editForm.vue +++ b/dl_vue/src/views/cus/contacts/editForm.vue @@ -109,6 +109,12 @@ import { listAll } from "@/api/base/country"; export default { name: 'editForm', dicts: ['sys_user_sex'], + props: { + country: { + type: String, + default: "" + }, + }, data() { return { title: '', @@ -188,18 +194,24 @@ export default { this.reset(cusId); this.open = true; this.title = "添加客户联系人"; + let that=this + if(this.country){ + let chooseItem = this.originalCountryAreaCodeList.filter(item =>{return item.nameCn.toLowerCase().includes(that.country)}) + this.form.telephonePre = chooseItem[0].areaCode; + this.form.whatsAppPre = chooseItem[0].areaCode; + } }, /** 修改按钮操作 */ handleUpdate(row) { this.form = JSON.parse(JSON.stringify( row)); if(this.form.telephone && this.form.telephone.length>0){ - let arr = this.form.telephone.split(" "); + let arr = this.form.telephone.split(" "); // 使用$set确保新增属性被响应式追踪 this.$set(this.form, 'telephonePre', arr[0] || ''); this.$set(this.form, 'telephone', arr[1] || ''); } if (this.form.whatsApp && this.form.whatsApp.length>0){ - let arr = this.form.whatsApp.split(" "); + let arr = this.form.whatsApp.split(" "); this.$set(this.form, 'whatsAppPre', arr[0] || ''); this.$set(this.form, 'whatsApp', arr[1] || ''); } @@ -238,10 +250,10 @@ export default { if (valid) { let dataObj = JSON.parse(JSON.stringify(this.form)) if(dataObj.telephone && dataObj.telephonePre){ - dataObj.telephone = dataObj.telephonePre+" "+ dataObj.telephone + dataObj.telephone = dataObj.telephonePre+" "+ dataObj.telephone } if(dataObj.whatsApp && dataObj.whatsAppPre){ - dataObj.whatsApp = dataObj.whatsAppPre +" "+ dataObj.whatsApp + dataObj.whatsApp = dataObj.whatsAppPre +" "+ dataObj.whatsApp } if (dataObj.id != null) { dataObj.id = dataObj.idStr diff --git a/dl_vue/src/views/cus/main/checkCus.vue b/dl_vue/src/views/cus/main/checkCus.vue new file mode 100644 index 0000000..a69948f --- /dev/null +++ b/dl_vue/src/views/cus/main/checkCus.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/dl_vue/src/views/cus/main/drawForm.vue b/dl_vue/src/views/cus/main/drawForm.vue index 0363ebd..1833183 100644 --- a/dl_vue/src/views/cus/main/drawForm.vue +++ b/dl_vue/src/views/cus/main/drawForm.vue @@ -397,6 +397,12 @@ export default { } else { this.formData.mainInfo.zoneName = null; } + //设置现有的所有联系人的手机号和WhatsApp的区号 + let chooseItem = this.originalCountryAreaCodeList.filter(item =>{return item.nameCn.toLowerCase().includes(selectedCountry.nameCn)}) + this.formData.contact.forEach(item => { + item.telephonePre = chooseItem[0].areaCode; + item.whatsAppPre = chooseItem[0].areaCode; + }); }, remoteMethod(query){ @@ -427,6 +433,14 @@ export default { * 新增联系人 */ addNewContact(){ + let that = this + let telephonePre='' + let whatsAppPre='' + if(this.formData.mainInfo.country){ + let chooseItem = this.originalCountryAreaCodeList.filter(item =>{return item.nameCn.toLowerCase().includes(that.formData.mainInfo.country)}) + telephonePre = chooseItem[0].areaCode; + whatsAppPre = chooseItem[0].areaCode; + } this.formData.contact.push({ name: '', ifDefault: false, @@ -436,9 +450,9 @@ export default { contactAddress: '', email: '', telephone: '', - telephonePre: '', + telephonePre: telephonePre, whatsApp: '', - whatsAppPre: '', + whatsAppPre: whatsAppPre, wechat: '', qq: '', }) @@ -544,10 +558,10 @@ export default { if(dataObj.contact.length>0){ dataObj.contact.map((item)=>{ if(item.telephone && item.telephonePre){ - item.telephone = item.telephonePre +" "+ item.telephone + item.telephone = item.telephonePre +" "+ item.telephone } if(item.whatsApp && item.whatsAppPre){ - item.whatsApp = item.whatsAppPre +" "+ item.whatsApp + item.whatsApp = item.whatsAppPre +" "+ item.whatsApp } }) }else{ diff --git a/dl_vue/src/views/cus/main/index.vue b/dl_vue/src/views/cus/main/index.vue index fe9bdb3..ebf60f4 100644 --- a/dl_vue/src/views/cus/main/index.vue +++ b/dl_vue/src/views/cus/main/index.vue @@ -53,17 +53,17 @@ - - 导出 - - + + + + + + + + + + + 导入 - + + + 重复校验 + @@ -281,6 +291,8 @@ + + @@ -292,10 +304,11 @@ import { getToken } from '@/utils/auth' import FollowForm from '../follow/followForm' import LabelForm from './labelForm' import SelectAllUser from '../../system/user/selectAllUser' +import CheckCus from './checkCus' export default { name: 'Main', - components: { SelectAllUser, LabelForm, DrawForm, FollowForm }, + components: { CheckCus, SelectAllUser, LabelForm, DrawForm, FollowForm }, dicts: ['cus_main_product', 'cus_label', 'cus_type', 'sys_user_sex', 'cus_from', 'cus_level', 'cus_busi_type', 'cus_follow_step'], data() { return { @@ -391,6 +404,12 @@ export default { this.upload.title = '客户导入' this.upload.open = true }, + /** + * 校验客户是否重复 + */ + checkCus(){ + this.$refs.checkCus.handleAdd() + }, /** * 给客户设置标签 */ diff --git a/dl_vue/src/views/cus/main/newForm.vue b/dl_vue/src/views/cus/main/newForm.vue index e7980cb..cc350aa 100644 --- a/dl_vue/src/views/cus/main/newForm.vue +++ b/dl_vue/src/views/cus/main/newForm.vue @@ -733,10 +733,8 @@ export default { this.countryAreaCodeList = this.originalCountryAreaCodeList; return; } - // 转换关键词为小写,避免大小写敏感 const lowerQuery = query.toLowerCase(); - // 过滤逻辑:nameCn 或 nameEn 包含关键词即保留 this.countryAreaCodeList = this.originalCountryAreaCodeList.filter(country => { const nameCnMatch = country.nameCn.toLowerCase().includes(lowerQuery); @@ -765,6 +763,12 @@ export default { } else { this.formData.mainInfo.zoneName = null; } + //设置现有的所有联系人的手机号和WhatsApp的区号 + let chooseItem = this.originalCountryAreaCodeList.filter(item =>{return item.nameCn.toLowerCase().includes(selectedCountry.nameCn)}) + this.formData.contact.forEach(item => { + item.telephonePre = chooseItem[0].areaCode; + item.whatsAppPre = chooseItem[0].areaCode; + }); }, remoteMethod(query){ @@ -817,13 +821,13 @@ export default { //操作联系人数据 this.formData.contact.forEach((item,index) => { if(item.telephone && item.telephone.length>0){ - let arr = item.telephone.split(" "); + let arr = item.telephone.split(" "); // 使用$set确保新增属性被响应式追踪 this.$set(item, 'telephonePre', arr[0] || ''); this.$set(item, 'telephone', arr[1] || ''); } if (item.whatsApp && item.whatsApp.length>0){ - let arr = item.whatsApp.split(" "); + let arr = item.whatsApp.split(" "); this.$set(item, 'whatsAppPre', arr[0] || ''); this.$set(item, 'whatsApp', arr[1] || ''); } @@ -902,6 +906,14 @@ export default { * 新增联系人 */ addNewContact(){ + let that = this + let telephonePre='' + let whatsAppPre='' + if(this.formData.mainInfo.country){ + let chooseItem = this.originalCountryAreaCodeList.filter(item =>{return item.nameCn.toLowerCase().includes(that.formData.mainInfo.country)}) + telephonePre = chooseItem[0].areaCode; + whatsAppPre = chooseItem[0].areaCode; + } this.formData.contact.push({ id: '', cusId: '', @@ -913,9 +925,9 @@ export default { contactAddress: '', email: '', telephone: '', - telephonePre: '', + telephonePre: telephonePre, whatsApp: '', - whatsAppPre: '', + whatsAppPre: whatsAppPre, wechat: '', qq: '', }) @@ -977,10 +989,10 @@ export default { if(dataObj.contact.length>0){ dataObj.contact.map((item)=>{ if(item.telephone && item.telephonePre){ - item.telephone = item.telephonePre +" "+ item.telephone + item.telephone = item.telephonePre +" "+ item.telephone } if(item.whatsApp && item.whatsAppPre){ - item.whatsApp = item.whatsAppPre +" "+ item.whatsApp + item.whatsApp = item.whatsAppPre +" "+ item.whatsApp } }) }else{ diff --git a/dl_vue/src/views/cus/main/viewForm.vue b/dl_vue/src/views/cus/main/viewForm.vue index e799125..0502ec1 100644 --- a/dl_vue/src/views/cus/main/viewForm.vue +++ b/dl_vue/src/views/cus/main/viewForm.vue @@ -211,7 +211,7 @@ - + @@ -253,6 +253,7 @@ export default { cusMain:{ fullName:"", cusCode:"", + country:"" } }, contactList:[],