Browse Source

refactor(announcement): 统一客户黑名单字段命名并优化选择逻辑

yz 1 month ago
parent
commit
8aa382aa68

+ 3 - 3
src/api/types/announcement.d.ts

@@ -29,9 +29,9 @@ export type VisibleRolesMask = number;
  * 客户黑名单项类型
  */
 export interface CustomerBlacklistItem {
-  id: number;
-  Customer_NAME: string;
-  Customer_CODE: string;
+  ID: number;
+  NAME: string;
+  CODE: string;
 }
 
 export type BrandScopeItem = {

+ 67 - 34
src/components/announcement/announcement-form-mixin.js

@@ -17,17 +17,18 @@
  * @typedef {import('@/api/types/announcement').NoticeFormData} NoticeFormData
  */
 
-import { 
-  getAnnouncement, 
-  add as addAnnouncement, 
-  update as updateAnnouncement 
+import {
+  getAnnouncement,
+  add as addAnnouncement,
+  update as updateAnnouncement
 } from '@/api/announcement';
 import { getCategoryList } from '@/api/announcement/category';
-import { 
-  ROLE_OPTIONS, 
-  STATUS_OPTIONS, 
-  calculateRolesMask, 
-  parseRolesMask 
+import { getCustomerList } from '@/api/common/index';
+import {
+  ROLE_OPTIONS,
+  STATUS_OPTIONS,
+  calculateRolesMask,
+  parseRolesMask
 } from '@/views/announcement/constants';
 
 
@@ -252,6 +253,8 @@ export default {
       brandOptions: [],
       /** @type {boolean} 品牌选项加载状态 */
       brandLoading: false,
+      /** @type {Array<number>} 选中的客户ID数组 */
+      selectedCustomerIds: [],
       /** 表单验证规则 */
       formRules: {
         title: [
@@ -380,6 +383,19 @@ export default {
         }
       },
       immediate: true
+    },
+
+    /**
+     * 监听客户黑名单变化,同步selectedCustomerIds
+     */
+    'formData.customerBlacklist': {
+      handler(newVal) {
+        if (Array.isArray(newVal)) {
+          this.selectedCustomerIds = newVal.map(item => item.ID || item.id).filter(id => id != null);
+        }
+      },
+      deep: true,
+      immediate: true
     }
   },
 
@@ -392,7 +408,7 @@ export default {
      * @this {AnnouncementFormMixinComponent & Vue}
      */
     apiToFormModel: dataConverter.apiToFormModel,
-    
+
     /**
      * 表单模型转换为API数据
      * @param {AnnouncementFormModel} formModel 表单模型
@@ -400,7 +416,7 @@ export default {
      * @this {AnnouncementFormMixinComponent & Vue}
      */
     formModelToApi: dataConverter.formModelToApi,
-    
+
     /**
      * 解析角色掩码
      * @param {string | number} rolesMask 角色掩码
@@ -408,7 +424,7 @@ export default {
      * @this {AnnouncementFormMixinComponent & Vue}
      */
     parseVisibleRoles: dataConverter.parseVisibleRoles.bind(dataConverter),
-    
+
     /**
      * 计算角色掩码
      * @param {Array<RoleType>} roles 角色类型数组
@@ -416,7 +432,7 @@ export default {
      * @this {AnnouncementFormMixinComponent & Vue}
      */
     calculateRolesMask: dataConverter.calculateRolesMask.bind(dataConverter),
-    
+
     /**
      * 客户黑名单字符串化
      * @param {Array<CustomerBlacklistItem>} customerBlacklist 客户黑名单
@@ -424,7 +440,7 @@ export default {
      * @this {AnnouncementFormMixinComponent & Vue}
      */
     stringifyCustomerBlacklist: dataConverter.stringifyCustomerBlacklist,
-    
+
     /**
      * 品牌范围字符串化
      * @param {Array<BrandScopeItem>} brandScope 品牌范围
@@ -447,7 +463,7 @@ export default {
      */
     async initFormData() {
       this.formData = this.createInitialFormData();
-      
+
       if (this.editData) {
         // 优先使用传入的编辑数据
         this.formData = dataConverter.apiToFormModel(this.editData);
@@ -595,7 +611,7 @@ export default {
      */
     async loadAnnouncementDetail() {
       if (!this.announcementId) return;
-      
+
       try {
         this.formLoading = true;
         const response = await getAnnouncement(this.announcementId);
@@ -652,14 +668,14 @@ export default {
         if (!isValid) return;
 
         this.saveLoading = true;
-        
+
         // 转换数据格式
         /** @type {NoticeFormData} */
         const submitData = dataConverter.formModelToApi(this.formData);
-        
+
         // 提交数据
         const response = await this.submitAnnouncementData(submitData);
-        
+
         if (response.data && response.data.success) {
           this.$message.success(this.isEdit ? '更新成功' : '创建成功');
           this.$emit('submit-success', this.formData);
@@ -683,6 +699,7 @@ export default {
     handleReset() {
       this.formData = this.createInitialFormData();
       this.customerOptions = [];
+      this.selectedCustomerIds = [];
       this.brandOptions = [];
       this.$emit('reset');
     },
@@ -736,17 +753,33 @@ export default {
      * @this {AnnouncementFormMixinComponent & Vue}
      */
     async remoteSearchCustomers(query) {
-      if (!query || query.length < 2) {
+      if (!query || query.length < 1) {
         this.customerOptions = [];
         return;
       }
 
       try {
         this.customerLoading = true;
-        // TODO: 实现客户搜索API调用
-        this.customerOptions = [];
+        const response = await getCustomerList(1, 20, {
+          customerName: query.trim()
+        });
+
+        if (response?.data?.success && response.data.data?.records) {
+          this.customerOptions = response.data.data.records.map(customer => ({
+            value: customer.Customer_ID,
+            label: customer.Customer_NAME,
+            Customer_NAME: customer.Customer_NAME,
+            Customer_CODE: customer.Customer_CODE
+          }));
+        } else {
+          this.customerOptions = [];
+          const errorMsg = response?.data?.msg || '搜索客户失败';
+          this.$message.warning(errorMsg);
+        }
       } catch (error) {
         console.error('搜索客户失败:', error);
+        this.$message.error('网络错误,搜索客户失败');
+        this.customerOptions = [];
       } finally {
         this.customerLoading = false;
       }
@@ -777,20 +810,18 @@ export default {
 
     /**
      * 处理客户黑名单变化
-     * @param {Array<CustomerOption>} selectedCustomers 选中的客户
+     * @param {Array<number>} selectedCustomerIds 选中的客户ID数组
      * @this {AnnouncementFormMixinComponent & Vue}
      */
-    handleCustomerBlacklistChange(selectedCustomers) {
+    handleCustomerBlacklistChange(selectedCustomerIds) {
+      this.selectedCustomerIds = selectedCustomerIds;
       /** @type {Array<CustomerBlacklistItem>} */
-      this.formData.customerBlacklist = selectedCustomers.map(customer => {
-        // 从label中提取客户代码
-        const codeMatch = customer.label ? customer.label.match(/\(([^)]+)\)$/) : null;
-        const code = codeMatch ? codeMatch[1] : customer.Customer_CODE || '';
-        
+      this.formData.customerBlacklist = selectedCustomerIds.map(customerId => {
+        const customer = this.customerOptions.find(option => option.value === customerId);
         return {
-          id: typeof customer.value === 'number' ? customer.value : parseInt(String(customer.value), 10),
-          Customer_NAME: customer.Customer_NAME || (customer.label ? customer.label.replace(/\([^)]+\)$/, '').trim() : ''),
-          Customer_CODE: code
+          ID: customerId,
+          NAME: customer?.Customer_NAME || '',
+          CODE: customer?.Customer_CODE || ''
         };
       });
     },
@@ -806,7 +837,7 @@ export default {
         // 从label中提取品牌代码
         const codeMatch = brand.label ? brand.label.match(/\(([^)]+)\)$/) : null;
         const code = codeMatch ? codeMatch[1] : brand.code || '';
-        
+
         return {
           id: String(brand.value),
           name: brand.name || (brand.label ? brand.label.replace(/\([^)]+\)$/, '').trim() : ''),
@@ -821,6 +852,8 @@ export default {
      */
     clearCustomerOptions() {
       this.customerOptions = [];
+      this.selectedCustomerIds = [];
+      this.formData.customerBlacklist = [];
     },
 
     /**
@@ -831,4 +864,4 @@ export default {
       this.brandOptions = [];
     }
   }
-};
+};

+ 5 - 2
src/components/announcement/index.vue

@@ -65,7 +65,7 @@
         <!-- 自定义插槽:客户黑名单 -->
         <template #customerBlacklist="{ value, column }">
           <el-select
-            v-model="formData.customerBlacklist"
+            v-model="selectedCustomerIds"
             multiple
             filterable
             remote
@@ -82,7 +82,10 @@
               :key="item.value"
               :label="item.label"
               :value="item.value"
-            />
+            >
+              <span style="float: left">{{ item.Customer_NAME }}</span>
+              <span style="float: right; color: #8492a6; font-size: 13px">{{ item.Customer_CODE }}</span>
+            </el-option>
           </el-select>
         </template>
       </avue-form>

+ 3 - 3
src/components/announcement/types.d.ts

@@ -68,9 +68,9 @@ export interface BrandScopeItem {
  * 客户黑名单项类型定义
  */
 export interface CustomerBlacklistItem {
-  id: number;
-  Customer_NAME: string;
-  Customer_CODE: string;
+  ID: number;
+  NAME: string;
+  CODE: string;
 }
 
 /**