|  | @@ -1,9 +1,11 @@
 | 
	
		
			
				|  |  |  import { getList, update, add, getAnnouncement, getCategoryList } from "@/api/announcement";
 | 
	
		
			
				|  |  | -import { getCustomerList } from "@/api/common/customer"; // 新增客户接口导入
 | 
	
		
			
				|  |  | +import { getCustomerList } from "@/api/common/customer";
 | 
	
		
			
				|  |  |  import { mapGetters } from "vuex";
 | 
	
		
			
				|  |  |  import {
 | 
	
		
			
				|  |  |      ROLE_OPTIONS,
 | 
	
		
			
				|  |  |      STATUS_OPTIONS,
 | 
	
		
			
				|  |  | +    ANNOUNCEMENT_STATUS,
 | 
	
		
			
				|  |  | +    ROLE_TYPES,
 | 
	
		
			
				|  |  |      getRoleLabel,
 | 
	
		
			
				|  |  |      getRoleTagType,
 | 
	
		
			
				|  |  |      getStatusLabel,
 | 
	
	
		
			
				|  | @@ -15,79 +17,46 @@ import {
 | 
	
		
			
				|  |  |  } from '@/views/announcement/constants';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  | - * 角色类型枚举
 | 
	
		
			
				|  |  | - * @typedef {1|2|4} RoleType
 | 
	
		
			
				|  |  | - * - 1: 工厂
 | 
	
		
			
				|  |  | - * - 2: 经销商
 | 
	
		
			
				|  |  | - * - 4: 零售商
 | 
	
		
			
				|  |  | + * 角色类型定义
 | 
	
		
			
				|  |  | + * @typedef {import('@/views/announcement/constants').RoleType} RoleType
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  | - * 可见角色掩码类型 (位运算)
 | 
	
		
			
				|  |  | - * @typedef {number} VisibleRolesMask
 | 
	
		
			
				|  |  | - * 支持的值:1(工厂) | 2(经销商) | 4(零售商) 及其组合
 | 
	
		
			
				|  |  | - * 例如:3(工厂+经销商), 5(工厂+零售商), 6(经销商+零售商), 7(全部)
 | 
	
		
			
				|  |  | + * 可见角色掩码类型定义
 | 
	
		
			
				|  |  | + * @typedef {import('@/views/announcement/constants').VisibleRolesMask} VisibleRolesMask
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * 角色选项类型定义
 | 
	
		
			
				|  |  | - * @typedef {Object} RoleOption
 | 
	
		
			
				|  |  | - * @property {string} label - 角色显示名称
 | 
	
		
			
				|  |  | - * @property {RoleType} value - 角色值(位运算)
 | 
	
		
			
				|  |  | + * @typedef {import('@/views/announcement/constants').RoleOption} RoleOption
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  | - * 公告状态枚举类型
 | 
	
		
			
				|  |  | - * @typedef {0|1|2} AnnouncementStatus
 | 
	
		
			
				|  |  | - * - 0: 草稿
 | 
	
		
			
				|  |  | - * - 1: 已发布
 | 
	
		
			
				|  |  | - * - 2: 已下架
 | 
	
		
			
				|  |  | + * 公告状态类型定义
 | 
	
		
			
				|  |  | + * @typedef {import('@/views/announcement/constants').AnnouncementStatus} AnnouncementStatus
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  | - * 公告数据类型定义
 | 
	
		
			
				|  |  | - * @typedef {Object} NoticeItem
 | 
	
		
			
				|  |  | - * @property {string} id - 公告ID
 | 
	
		
			
				|  |  | - * @property {string} title - 公告标题
 | 
	
		
			
				|  |  | - * @property {string} content - 公告内容
 | 
	
		
			
				|  |  | - * @property {string} categoryId - 分类ID
 | 
	
		
			
				|  |  | - * @property {string} categoryName - 分类名称
 | 
	
		
			
				|  |  | - * @property {number} orgId - 组织ID
 | 
	
		
			
				|  |  | - * @property {string} orgCode - 组织编码
 | 
	
		
			
				|  |  | - * @property {string} orgName - 组织名称
 | 
	
		
			
				|  |  | - * @property {VisibleRolesMask} visibleRoles - 可见角色掩码(位运算:1工厂 2经销商 4零售商)
 | 
	
		
			
				|  |  | - * @property {Object|null} brandScope - 品牌范围
 | 
	
		
			
				|  |  | - * @property {Array<CustomerBlacklistOption>|null} customerBlacklist - 客户黑名单
 | 
	
		
			
				|  |  | - * @property {string} remark - 备注
 | 
	
		
			
				|  |  | - * @property {string} createTime - 创建时间
 | 
	
		
			
				|  |  | - * @property {string} updateTime - 更新时间
 | 
	
		
			
				|  |  | - * @property {AnnouncementStatus} status - 状态 0草稿 1已发布 2已下架
 | 
	
		
			
				|  |  | - * @property {number} isDeleted - 是否删除
 | 
	
		
			
				|  |  | + * 公告数据项类型定义
 | 
	
		
			
				|  |  | + * @typedef {import('@/api/announcement').NoticeRecord} NoticeItem
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * 分类选项类型定义
 | 
	
		
			
				|  |  | - * @typedef {Object} CategoryOption
 | 
	
		
			
				|  |  | - * @property {string} id - 分类ID
 | 
	
		
			
				|  |  | - * @property {string} name - 分类名称
 | 
	
		
			
				|  |  | - * @property {string} value - 选项值
 | 
	
		
			
				|  |  | - * @property {string} label - 选项标签
 | 
	
		
			
				|  |  | + * @typedef {import('@/api/announcement').CategoryOption} CategoryOption
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * 分页信息类型定义
 | 
	
		
			
				|  |  |   * @typedef {Object} PageInfo
 | 
	
		
			
				|  |  | - * @property {number} pageSize - 每页大小
 | 
	
		
			
				|  |  | - * @property {number} currentPage - 当前页码
 | 
	
		
			
				|  |  | + * @property {number} pageSize - 页大小(默认10)
 | 
	
		
			
				|  |  | + * @property {number} currentPage - 当前页(从1开始)
 | 
	
		
			
				|  |  |   * @property {number} total - 总记录数
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * 查询参数类型定义
 | 
	
		
			
				|  |  | - * @typedef {Object} QueryParams
 | 
	
		
			
				|  |  | - * @property {string} [title] - 公告标题
 | 
	
		
			
				|  |  | - * @property {string} [categoryId] - 分类ID
 | 
	
		
			
				|  |  | - * @property {string} [content] - 公告内容
 | 
	
		
			
				|  |  | + * @typedef {import('@/api/announcement').NoticeQueryParams} QueryParams
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
	
		
			
				|  | @@ -142,17 +111,13 @@ import {
 | 
	
		
			
				|  |  |   * @mixin AnnouncementIndexMixin
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  | - * 客户选项类型定义
 | 
	
		
			
				|  |  | + * 客户记录类型定义
 | 
	
		
			
				|  |  |   * @typedef {import('@/api/common/customer').CustomerRecord} CustomerRecord
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * 客户黑名单选项类型定义
 | 
	
		
			
				|  |  | - * @typedef {Object} CustomerBlacklistOption
 | 
	
		
			
				|  |  | - * @property {string} id - 客户ID
 | 
	
		
			
				|  |  | - * @property {string} Customer_NAME - 客户名称
 | 
	
		
			
				|  |  | - * @property {string} Customer_CODE - 客户编码
 | 
	
		
			
				|  |  | - * @property {string} Customer_ShortName - 客户简称
 | 
	
		
			
				|  |  | + * @typedef {import('@/api/announcement').CustomerBlacklistItem} CustomerBlacklistOption
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  export default {
 | 
	
	
		
			
				|  | @@ -181,16 +146,10 @@ export default {
 | 
	
		
			
				|  |  |              /** @type {Array<CategoryOption>} 分类选项列表 */
 | 
	
		
			
				|  |  |              categoryOptions: [],
 | 
	
		
			
				|  |  |              /** @type {Array<RoleOption>} 角色选项列表 */
 | 
	
		
			
				|  |  | -            roleOptions: [
 | 
	
		
			
				|  |  | -                { label: "工厂", value: 1 },
 | 
	
		
			
				|  |  | -                { label: "经销商", value: 2 },
 | 
	
		
			
				|  |  | -                { label: "零售商", value: 4 }
 | 
	
		
			
				|  |  | -            ],
 | 
	
		
			
				|  |  | +            roleOptions: ROLE_OPTIONS,
 | 
	
		
			
				|  |  |              /** @type {Array<CustomerBlacklistOption>} 客户黑名单选项列表 */
 | 
	
		
			
				|  |  |              customerBlacklistOptions: [],
 | 
	
		
			
				|  |  | -            /**
 | 
	
		
			
				|  |  | -             * @type {Array<CustomerRecord>} 当前客户黑名单
 | 
	
		
			
				|  |  | -             */
 | 
	
		
			
				|  |  | +            /** @type {Array<CustomerRecord>} 当前客户黑名单 */
 | 
	
		
			
				|  |  |              currentCustomerBlacklist: [],
 | 
	
		
			
				|  |  |              /** @type {boolean} 客户选项加载状态 */
 | 
	
		
			
				|  |  |              customerOptionsLoading: false,
 | 
	
	
		
			
				|  | @@ -423,12 +382,14 @@ export default {
 | 
	
		
			
				|  |  |           * 加载分类选项
 | 
	
		
			
				|  |  |           * @async
 | 
	
		
			
				|  |  |           * @returns {Promise<void>}
 | 
	
		
			
				|  |  | +         * @throws {Error} 当加载分类选项失败时抛出错误
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          async loadCategoryOptions() {
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  | -                const res = await getCategoryList();
 | 
	
		
			
				|  |  | -                const categoryData = res.data.data || [];
 | 
	
		
			
				|  |  | +                const response = await getCategoryList();
 | 
	
		
			
				|  |  | +                const categoryData = response.data?.data || [];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +                /** @type {Array<CategoryOption>} */
 | 
	
		
			
				|  |  |                  this.categoryOptions = categoryData
 | 
	
		
			
				|  |  |                      .filter(item => item.status === 1 && item.isDeleted === 0)
 | 
	
		
			
				|  |  |                      .map(item => ({
 | 
	
	
		
			
				|  | @@ -442,17 +403,22 @@ export default {
 | 
	
		
			
				|  |  |                      }))
 | 
	
		
			
				|  |  |                      .sort((a, b) => a.sortOrder - b.sortOrder);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +                // 更新表格列配置中的字典数据
 | 
	
		
			
				|  |  |                  const categoryColumn = this.option.column.find(col => col.prop === 'categoryId');
 | 
	
		
			
				|  |  |                  if (categoryColumn) {
 | 
	
		
			
				|  |  |                      categoryColumn.dicData = this.categoryOptions;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              } catch (error) {
 | 
	
		
			
				|  |  |                  console.error('加载分类选项失败:', error);
 | 
	
		
			
				|  |  | -                // 使用默认分类
 | 
	
		
			
				|  |  | +                this.$message.error('加载分类选项失败,使用默认分类');
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                // 使用默认分类选项
 | 
	
		
			
				|  |  | +                /** @type {Array<CategoryOption>} */
 | 
	
		
			
				|  |  |                  this.categoryOptions = [
 | 
	
		
			
				|  |  | -                    { id: '1', name: '系统公告', value: '1', label: '系统公告' },
 | 
	
		
			
				|  |  | -                    { id: '2', name: '部门公告', value: '2', label: '部门公告' }
 | 
	
		
			
				|  |  | +                    { id: 1, name: '系统公告', value: 1, label: '系统公告', sortOrder: 0 },
 | 
	
		
			
				|  |  | +                    { id: 2, name: '部门公告', value: 2, label: '部门公告', sortOrder: 1 }
 | 
	
		
			
				|  |  |                  ];
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  |                  const categoryColumn = this.option.column.find(col => col.prop === 'categoryId');
 | 
	
		
			
				|  |  |                  if (categoryColumn) {
 | 
	
		
			
				|  |  |                      categoryColumn.dicData = this.categoryOptions;
 | 
	
	
		
			
				|  | @@ -464,19 +430,22 @@ export default {
 | 
	
		
			
				|  |  |           * 查看详情
 | 
	
		
			
				|  |  |           * @async
 | 
	
		
			
				|  |  |           * @returns {Promise<void>}
 | 
	
		
			
				|  |  | +         * @throws {Error} 当获取详情失败时抛出错误
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          async handleDetail() {
 | 
	
		
			
				|  |  |              if (this.selectionList.length !== 1) {
 | 
	
		
			
				|  |  |                  this.$message.warning("请选择一条数据查看详情");
 | 
	
		
			
				|  |  |                  return;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +            
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  | -                const res = await getAnnouncement(this.selectionList[0].id);
 | 
	
		
			
				|  |  | -                this.currentDetail = res.data.data;
 | 
	
		
			
				|  |  | +                const response = await getAnnouncement(this.selectionList[0].id);
 | 
	
		
			
				|  |  | +                /** @type {NoticeItem} */
 | 
	
		
			
				|  |  | +                this.currentDetail = response.data?.data || {};
 | 
	
		
			
				|  |  |                  this.detailVisible = true;
 | 
	
		
			
				|  |  |              } catch (error) {
 | 
	
		
			
				|  |  |                  console.error('获取详情失败:', error);
 | 
	
		
			
				|  |  | -                this.$message.error('获取详情失败');
 | 
	
		
			
				|  |  | +                this.$message.error('获取详情失败,请稍后重试');
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -487,43 +456,56 @@ export default {
 | 
	
		
			
				|  |  |           * @param {Function} done - 完成回调
 | 
	
		
			
				|  |  |           * @param {Function} loading - 加载回调
 | 
	
		
			
				|  |  |           * @returns {Promise<void>}
 | 
	
		
			
				|  |  | +         * @throws {Error} 当保存失败时抛出错误
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          async rowSave(row, done, loading) {
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  | +                // 参数验证
 | 
	
		
			
				|  |  | +                if (!row.title?.trim()) {
 | 
	
		
			
				|  |  | +                    this.$message.error('公告标题不能为空');
 | 
	
		
			
				|  |  | +                    loading();
 | 
	
		
			
				|  |  | +                    return;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                if (!row.content?.trim()) {
 | 
	
		
			
				|  |  | +                    this.$message.error('公告内容不能为空');
 | 
	
		
			
				|  |  | +                    loading();
 | 
	
		
			
				|  |  | +                    return;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                  // 计算角色掩码值
 | 
	
		
			
				|  |  | +                /** @type {VisibleRolesMask} */
 | 
	
		
			
				|  |  |                  const rolesMask = Array.isArray(row.visibleRoles)
 | 
	
		
			
				|  |  |                      ? this.calculateRolesMask(row.visibleRoles)
 | 
	
		
			
				|  |  |                      : (row.visibleRoles || 7); // 默认所有角色可见
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                /**
 | 
	
		
			
				|  |  | -                 * 过滤后的客户黑名单数据
 | 
	
		
			
				|  |  | -                 * @type {Array<CustomerRecord>}
 | 
	
		
			
				|  |  | -                 */
 | 
	
		
			
				|  |  | -                const updateCustomerBlacklist = this.currentCustomerBlacklist.filter(customer => {
 | 
	
		
			
				|  |  | -                    const ids = row.customerBlacklist.map(customer => customer.id);
 | 
	
		
			
				|  |  | -                    return ids.includes(customer.id);
 | 
	
		
			
				|  |  | +                // 处理客户黑名单数据
 | 
	
		
			
				|  |  | +                /** @type {Array<CustomerRecord>} */
 | 
	
		
			
				|  |  | +                const filteredCustomerBlacklist = this.currentCustomerBlacklist.filter(customer => {
 | 
	
		
			
				|  |  | +                    const selectedIds = (row.customerBlacklist || []).map(item => item.id);
 | 
	
		
			
				|  |  | +                    return selectedIds.includes(customer.id);
 | 
	
		
			
				|  |  |                  });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                // 设置默认值
 | 
	
		
			
				|  |  | +                // 构建表单数据
 | 
	
		
			
				|  |  | +                /** @type {import('@/api/announcement').NoticeFormData} */
 | 
	
		
			
				|  |  |                  const formData = {
 | 
	
		
			
				|  |  |                      ...row,
 | 
	
		
			
				|  |  | -                    orgId: this.userInfo.orgId || row.orgId,
 | 
	
		
			
				|  |  | -                    orgCode: this.userInfo.orgCode || row.orgCode,
 | 
	
		
			
				|  |  | -                    orgName: this.userInfo.orgName || row.orgName,
 | 
	
		
			
				|  |  | +                    orgId: this.userInfo?.orgId || row.orgId,
 | 
	
		
			
				|  |  | +                    orgCode: this.userInfo?.orgCode || row.orgCode,
 | 
	
		
			
				|  |  | +                    orgName: this.userInfo?.orgName || row.orgName,
 | 
	
		
			
				|  |  |                      brandScope: row.brandScope || {},
 | 
	
		
			
				|  |  | -                    // customerBlacklist: Array.isArray(row.customerBlacklist) ? row.customerBlacklist : [],
 | 
	
		
			
				|  |  | -                    customerBlacklist: updateCustomerBlacklist.map(customer => ({
 | 
	
		
			
				|  |  | +                    customerBlacklist: filteredCustomerBlacklist.map(customer => ({
 | 
	
		
			
				|  |  |                          ID: customer.id,
 | 
	
		
			
				|  |  |                          CODE: customer.Customer_CODE,
 | 
	
		
			
				|  |  |                          NAME: customer.Customer_NAME
 | 
	
		
			
				|  |  |                      })),
 | 
	
		
			
				|  |  |                      remark: row.remark || '',
 | 
	
		
			
				|  |  |                      visibleRoles: rolesMask,
 | 
	
		
			
				|  |  | -                    status: row.status !== undefined ? row.status : 0, // 默认草稿状态
 | 
	
		
			
				|  |  | +                    status: row.status !== undefined ? row.status : ANNOUNCEMENT_STATUS.DRAFT,
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  // 设置分类名称
 | 
	
		
			
				|  |  | -                const selectedCategory = this.categoryOptions.find(cat => cat.id === row.categoryId);
 | 
	
		
			
				|  |  | +                const selectedCategory = this.categoryOptions.find(cat => cat.id == row.categoryId);
 | 
	
		
			
				|  |  |                  if (selectedCategory) {
 | 
	
		
			
				|  |  |                      formData.categoryName = selectedCategory.name;
 | 
	
		
			
				|  |  |                  }
 | 
	
	
		
			
				|  | @@ -532,12 +514,12 @@ export default {
 | 
	
		
			
				|  |  |                  await this.onLoad(this.page);
 | 
	
		
			
				|  |  |                  this.$message({
 | 
	
		
			
				|  |  |                      type: "success",
 | 
	
		
			
				|  |  | -                    message: "操作成功!"
 | 
	
		
			
				|  |  | +                    message: "新增公告成功!"
 | 
	
		
			
				|  |  |                  });
 | 
	
		
			
				|  |  |                  done();
 | 
	
		
			
				|  |  |              } catch (error) {
 | 
	
		
			
				|  |  |                  console.error('保存失败:', error);
 | 
	
		
			
				|  |  | -                this.$message.error('保存失败');
 | 
	
		
			
				|  |  | +                this.$message.error(`保存失败: ${error.message || '未知错误'}`);
 | 
	
		
			
				|  |  |                  loading();
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          },
 | 
	
	
		
			
				|  | @@ -550,34 +532,54 @@ export default {
 | 
	
		
			
				|  |  |           * @param {Function} done - 完成回调
 | 
	
		
			
				|  |  |           * @param {Function} loading - 加载回调
 | 
	
		
			
				|  |  |           * @returns {Promise<void>}
 | 
	
		
			
				|  |  | +         * @throws {Error} 当更新失败时抛出错误
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          async rowUpdate(row, index, done, loading) {
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  | +                // 参数验证
 | 
	
		
			
				|  |  | +                if (!row.id) {
 | 
	
		
			
				|  |  | +                    this.$message.error('缺少公告ID,无法更新');
 | 
	
		
			
				|  |  | +                    loading();
 | 
	
		
			
				|  |  | +                    return;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                if (!row.title?.trim()) {
 | 
	
		
			
				|  |  | +                    this.$message.error('公告标题不能为空');
 | 
	
		
			
				|  |  | +                    loading();
 | 
	
		
			
				|  |  | +                    return;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                if (!row.content?.trim()) {
 | 
	
		
			
				|  |  | +                    this.$message.error('公告内容不能为空');
 | 
	
		
			
				|  |  | +                    loading();
 | 
	
		
			
				|  |  | +                    return;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                  // 计算角色掩码值
 | 
	
		
			
				|  |  | +                /** @type {VisibleRolesMask} */
 | 
	
		
			
				|  |  |                  const rolesMask = Array.isArray(row.visibleRoles)
 | 
	
		
			
				|  |  |                      ? this.calculateRolesMask(row.visibleRoles)
 | 
	
		
			
				|  |  |                      : row.visibleRoles;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  // 设置分类名称
 | 
	
		
			
				|  |  | -                const selectedCategory = this.categoryOptions.find(cat => cat.id === row.categoryId);
 | 
	
		
			
				|  |  | +                const selectedCategory = this.categoryOptions.find(cat => cat.id == row.categoryId);
 | 
	
		
			
				|  |  |                  if (selectedCategory) {
 | 
	
		
			
				|  |  |                      row.categoryName = selectedCategory.name;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                /**
 | 
	
		
			
				|  |  | -                 * 过滤后的客户黑名单数据
 | 
	
		
			
				|  |  | -                 * @type {Array<CustomerRecord>}
 | 
	
		
			
				|  |  | -                 */
 | 
	
		
			
				|  |  | -                const updateCustomerBlacklist = this.currentCustomerBlacklist.filter(customer => {
 | 
	
		
			
				|  |  | -                    const ids = row.customerBlacklist.map(customer => customer.id);
 | 
	
		
			
				|  |  | -                    return ids.includes(customer.id);
 | 
	
		
			
				|  |  | +                // 处理客户黑名单数据
 | 
	
		
			
				|  |  | +                /** @type {Array<CustomerRecord>} */
 | 
	
		
			
				|  |  | +                const filteredCustomerBlacklist = this.currentCustomerBlacklist.filter(customer => {
 | 
	
		
			
				|  |  | +                    const selectedIds = (row.customerBlacklist || []).map(item => item.id);
 | 
	
		
			
				|  |  | +                    return selectedIds.includes(customer.id);
 | 
	
		
			
				|  |  |                  });
 | 
	
		
			
				|  |  | -                // 确保必要字段存在
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                // 构建更新数据
 | 
	
		
			
				|  |  | +                /** @type {import('@/api/announcement').NoticeFormData} */
 | 
	
		
			
				|  |  |                  const formData = {
 | 
	
		
			
				|  |  |                      ...row,
 | 
	
		
			
				|  |  |                      brandScope: row.brandScope || {},
 | 
	
		
			
				|  |  | -                    // customerBlacklist: Array.isArray(row.customerBlacklist) ? row.customerBlacklist : [],
 | 
	
		
			
				|  |  | -                    customerBlacklist: updateCustomerBlacklist.map(customer => ({
 | 
	
		
			
				|  |  | +                    customerBlacklist: filteredCustomerBlacklist.map(customer => ({
 | 
	
		
			
				|  |  |                          ID: customer.id,
 | 
	
		
			
				|  |  |                          CODE: customer.Customer_CODE,
 | 
	
		
			
				|  |  |                          NAME: customer.Customer_NAME
 | 
	
	
		
			
				|  | @@ -590,12 +592,12 @@ export default {
 | 
	
		
			
				|  |  |                  await this.onLoad(this.page);
 | 
	
		
			
				|  |  |                  this.$message({
 | 
	
		
			
				|  |  |                      type: "success",
 | 
	
		
			
				|  |  | -                    message: "操作成功!"
 | 
	
		
			
				|  |  | +                    message: "更新公告成功!"
 | 
	
		
			
				|  |  |                  });
 | 
	
		
			
				|  |  |                  done();
 | 
	
		
			
				|  |  |              } catch (error) {
 | 
	
		
			
				|  |  |                  console.error('更新失败:', error);
 | 
	
		
			
				|  |  | -                this.$message.error('更新失败');
 | 
	
		
			
				|  |  | +                this.$message.error(`更新失败: ${error.message || '未知错误'}`);
 | 
	
		
			
				|  |  |                  loading();
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          },
 | 
	
	
		
			
				|  | @@ -606,8 +608,9 @@ export default {
 | 
	
		
			
				|  |  |           * @param {Function} done - 完成回调
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          searchChange(params, done) {
 | 
	
		
			
				|  |  | -            this.query = params;
 | 
	
		
			
				|  |  | -            this.onLoad(this.page, params);
 | 
	
		
			
				|  |  | +            /** @type {QueryParams} */
 | 
	
		
			
				|  |  | +            this.query = params || {};
 | 
	
		
			
				|  |  | +            this.onLoad(this.page, this.query);
 | 
	
		
			
				|  |  |              done();
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -615,6 +618,7 @@ export default {
 | 
	
		
			
				|  |  |           * 搜索重置事件
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          searchReset() {
 | 
	
		
			
				|  |  | +            /** @type {QueryParams} */
 | 
	
		
			
				|  |  |              this.query = {};
 | 
	
		
			
				|  |  |              this.onLoad(this.page);
 | 
	
		
			
				|  |  |          },
 | 
	
	
		
			
				|  | @@ -624,15 +628,18 @@ export default {
 | 
	
		
			
				|  |  |           * @param {Array<NoticeItem>} list - 选中的数据列表
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          selectionChange(list) {
 | 
	
		
			
				|  |  | -            this.selectionList = list;
 | 
	
		
			
				|  |  | +            /** @type {Array<NoticeItem>} */
 | 
	
		
			
				|  |  | +            this.selectionList = Array.isArray(list) ? list : [];
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /**
 | 
	
		
			
				|  |  |           * 当前页变化事件
 | 
	
		
			
				|  |  | -         * @param {number} currentPage - 当前页码
 | 
	
		
			
				|  |  | +         * @param {number} currentPage - 当前页码(从1开始)
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          currentChange(currentPage) {
 | 
	
		
			
				|  |  | -            this.page.currentPage = currentPage;
 | 
	
		
			
				|  |  | +            if (typeof currentPage === 'number' && currentPage > 0) {
 | 
	
		
			
				|  |  | +                this.page.currentPage = currentPage;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /**
 | 
	
	
		
			
				|  | @@ -640,7 +647,9 @@ export default {
 | 
	
		
			
				|  |  |           * @param {number} pageSize - 页大小
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          sizeChange(pageSize) {
 | 
	
		
			
				|  |  | -            this.page.pageSize = pageSize;
 | 
	
		
			
				|  |  | +            if (typeof pageSize === 'number' && pageSize > 0) {
 | 
	
		
			
				|  |  | +                this.page.pageSize = pageSize;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /**
 | 
	
	
		
			
				|  | @@ -654,16 +663,25 @@ export default {
 | 
	
		
			
				|  |  |           * 打开前回调
 | 
	
		
			
				|  |  |           * @async
 | 
	
		
			
				|  |  |           * @param {Function} done - 完成回调
 | 
	
		
			
				|  |  | -         * @param {string} type - 操作类型
 | 
	
		
			
				|  |  | +         * @param {string} type - 操作类型(add/edit/view)
 | 
	
		
			
				|  |  |           * @returns {Promise<void>}
 | 
	
		
			
				|  |  | +         * @throws {Error} 当获取详情失败时抛出错误
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          async beforeOpen(done, type) {
 | 
	
		
			
				|  |  |              if (["edit", "view"].includes(type)) {
 | 
	
		
			
				|  |  |                  try {
 | 
	
		
			
				|  |  | -                    const res = await getAnnouncement(this.form.id);
 | 
	
		
			
				|  |  | -                    const formData = res.data.data;
 | 
	
		
			
				|  |  | +                    if (!this.form?.id) {
 | 
	
		
			
				|  |  | +                        this.$message.error('缺少公告ID,无法获取详情');
 | 
	
		
			
				|  |  | +                        done();
 | 
	
		
			
				|  |  | +                        return;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    
 | 
	
		
			
				|  |  | +                    const response = await getAnnouncement(this.form.id);
 | 
	
		
			
				|  |  | +                    /** @type {NoticeItem} */
 | 
	
		
			
				|  |  | +                    const formData = response.data?.data || {};
 | 
	
		
			
				|  |  | +                    
 | 
	
		
			
				|  |  |                      // 将掩码值转换为数值数组格式供表单使用
 | 
	
		
			
				|  |  | -                    const roleObjects = this.parseRolesMask(formData.visibleRoles);
 | 
	
		
			
				|  |  | +                    const roleObjects = this.parseRolesMask(formData.visibleRoles || 0);
 | 
	
		
			
				|  |  |                      formData.visibleRoles = roleObjects.map(role => role.value);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      // 确保客户黑名单是数组格式
 | 
	
	
		
			
				|  | @@ -673,25 +691,31 @@ export default {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      // 如果有客户黑名单数据,设置到选项中以便显示
 | 
	
		
			
				|  |  |                      if (formData.customerBlacklist.length > 0) {
 | 
	
		
			
				|  |  | +                        /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  |                          this.customerBlacklistOptions = [...formData.customerBlacklist];
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +                    /** @type {NoticeItem} */
 | 
	
		
			
				|  |  |                      this.form = formData;
 | 
	
		
			
				|  |  |                  } catch (error) {
 | 
	
		
			
				|  |  |                      console.error('获取详情失败:', error);
 | 
	
		
			
				|  |  | +                    this.$message.error('获取详情失败,请稍后重试');
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              } else if (type === "add") {
 | 
	
		
			
				|  |  |                  // 新增时设置默认值
 | 
	
		
			
				|  |  | +                /** @type {NoticeItem} */
 | 
	
		
			
				|  |  |                  this.form = {
 | 
	
		
			
				|  |  | -                    orgId: this.userInfo.orgId || '',
 | 
	
		
			
				|  |  | -                    orgCode: this.userInfo.orgCode || '',
 | 
	
		
			
				|  |  | -                    orgName: this.userInfo.orgName || '',
 | 
	
		
			
				|  |  | -                    visibleRoles: [], // 默认经销商
 | 
	
		
			
				|  |  | +                    orgId: this.userInfo?.orgId || '',
 | 
	
		
			
				|  |  | +                    orgCode: this.userInfo?.orgCode || '',
 | 
	
		
			
				|  |  | +                    orgName: this.userInfo?.orgName || '',
 | 
	
		
			
				|  |  | +                    visibleRoles: [ROLE_TYPES.DEALER], // 默认经销商
 | 
	
		
			
				|  |  |                      brandScope: {},
 | 
	
		
			
				|  |  |                      customerBlacklist: [],
 | 
	
		
			
				|  |  | -                    remark: ''
 | 
	
		
			
				|  |  | +                    remark: '',
 | 
	
		
			
				|  |  | +                    status: ANNOUNCEMENT_STATUS.DRAFT
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |                  // 清空客户选项
 | 
	
		
			
				|  |  | +                /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  |                  this.customerBlacklistOptions = [];
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              done();
 | 
	
	
		
			
				|  | @@ -701,25 +725,42 @@ export default {
 | 
	
		
			
				|  |  |           * 加载数据
 | 
	
		
			
				|  |  |           * @async
 | 
	
		
			
				|  |  |           * @param {PageInfo} page - 分页信息
 | 
	
		
			
				|  |  | -         * @param {QueryParams} params - 查询参数
 | 
	
		
			
				|  |  | +         * @param {QueryParams} [params={}] - 查询参数
 | 
	
		
			
				|  |  |           * @returns {Promise<void>}
 | 
	
		
			
				|  |  | +         * @throws {Error} 当加载数据失败时抛出错误
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          async onLoad(page, params = {}) {
 | 
	
		
			
				|  |  |              this.loading = true;
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  | +                // 参数验证
 | 
	
		
			
				|  |  | +                if (!page || typeof page.currentPage !== 'number' || typeof page.pageSize !== 'number') {
 | 
	
		
			
				|  |  | +                    throw new Error('分页参数无效');
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                /** @type {QueryParams} */
 | 
	
		
			
				|  |  |                  const query = {
 | 
	
		
			
				|  |  |                      ...params,
 | 
	
		
			
				|  |  |                      current: page.currentPage,
 | 
	
		
			
				|  |  |                      size: page.pageSize
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                const res = await getList(page.currentPage, page.pageSize, query);
 | 
	
		
			
				|  |  | -                const data = res.data.data;
 | 
	
		
			
				|  |  | -                this.page.total = data.total;
 | 
	
		
			
				|  |  | -                this.data = data.records;
 | 
	
		
			
				|  |  | +                const response = await getList(page.currentPage, page.pageSize, query);
 | 
	
		
			
				|  |  | +                const data = response.data.data;
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                if (!data) {
 | 
	
		
			
				|  |  | +                    throw new Error('响应数据格式错误');
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                this.page.total = data.total || 0;
 | 
	
		
			
				|  |  | +                /** @type {Array<NoticeItem>} */
 | 
	
		
			
				|  |  | +                this.data = Array.isArray(data.records) ? data.records : [];
 | 
	
		
			
				|  |  |              } catch (error) {
 | 
	
		
			
				|  |  |                  console.error('加载数据失败:', error);
 | 
	
		
			
				|  |  | -                this.$message.error('加载数据失败');
 | 
	
		
			
				|  |  | +                this.$message.error(`加载数据失败: ${error.message || '未知错误'}`);
 | 
	
		
			
				|  |  | +                // 设置默认值避免页面异常
 | 
	
		
			
				|  |  | +                this.page.total = 0;
 | 
	
		
			
				|  |  | +                /** @type {Array<NoticeItem>} */
 | 
	
		
			
				|  |  | +                this.data = [];
 | 
	
		
			
				|  |  |              } finally {
 | 
	
		
			
				|  |  |                  this.loading = false;
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -730,9 +771,11 @@ export default {
 | 
	
		
			
				|  |  |           * @async
 | 
	
		
			
				|  |  |           * @param {string} query - 搜索关键词
 | 
	
		
			
				|  |  |           * @returns {Promise<void>}
 | 
	
		
			
				|  |  | +         * @throws {Error} 当搜索客户失败时抛出错误
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          async remoteSearchCustomers(query) {
 | 
	
		
			
				|  |  | -            if (!query || query.trim().length < 1) {
 | 
	
		
			
				|  |  | +            if (!query || typeof query !== 'string' || query.trim().length < 2) {
 | 
	
		
			
				|  |  | +                /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  |                  this.customerBlacklistOptions = [];
 | 
	
		
			
				|  |  |                  return;
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -750,6 +793,7 @@ export default {
 | 
	
		
			
				|  |  |                      const customers = response.data.data.records || [];
 | 
	
		
			
				|  |  |                      this.currentCustomerBlacklist = customers;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +                    /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  |                      this.customerBlacklistOptions = customers.map(customer => ({
 | 
	
		
			
				|  |  |                          id: customer.id,
 | 
	
		
			
				|  |  |                          Customer_NAME: customer.Customer_NAME,
 | 
	
	
		
			
				|  | @@ -757,11 +801,13 @@ export default {
 | 
	
		
			
				|  |  |                          Customer_ShortName: customer.Customer_ShortName
 | 
	
		
			
				|  |  |                      }));
 | 
	
		
			
				|  |  |                  } else {
 | 
	
		
			
				|  |  | +                    /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  |                      this.customerBlacklistOptions = [];
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              } catch (error) {
 | 
	
		
			
				|  |  |                  console.error('获取客户列表失败:', error);
 | 
	
		
			
				|  |  | -                this.$message.error('获取客户列表失败');
 | 
	
		
			
				|  |  | +                this.$message.error('获取客户列表失败,请稍后重试');
 | 
	
		
			
				|  |  | +                /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  |                  this.customerBlacklistOptions = [];
 | 
	
		
			
				|  |  |              } finally {
 | 
	
		
			
				|  |  |                  this.customerOptionsLoading = false;
 | 
	
	
		
			
				|  | @@ -773,7 +819,13 @@ export default {
 | 
	
		
			
				|  |  |           * @param {Array<CustomerBlacklistOption>} selectedCustomers - 选中的客户列表
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          handleCustomerBlacklistChange(selectedCustomers) {
 | 
	
		
			
				|  |  | -            this.form.customerBlacklist = selectedCustomers || [];
 | 
	
		
			
				|  |  | +            if (!Array.isArray(selectedCustomers)) {
 | 
	
		
			
				|  |  | +                /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  | +                this.form.customerBlacklist = [];
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  | +            this.form.customerBlacklist = selectedCustomers;
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /**
 | 
	
	
		
			
				|  | @@ -782,15 +834,22 @@ export default {
 | 
	
		
			
				|  |  |           * @returns {string} 显示名称
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          getCustomerDisplayName(customer) {
 | 
	
		
			
				|  |  | -            if (!customer) return '';
 | 
	
		
			
				|  |  | -            return `${customer.Customer_NAME}(${customer.Customer_CODE})`;
 | 
	
		
			
				|  |  | +            if (!customer || typeof customer !== 'object') {
 | 
	
		
			
				|  |  | +                return '';
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            const name = customer.Customer_NAME || '';
 | 
	
		
			
				|  |  | +            const code = customer.Customer_CODE || '';
 | 
	
		
			
				|  |  | +            return code ? `${name}(${code})` : name;
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /**
 | 
	
		
			
				|  |  |           * 清空客户搜索结果
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          clearCustomerOptions() {
 | 
	
		
			
				|  |  | +            /** @type {Array<CustomerBlacklistOption>} */
 | 
	
		
			
				|  |  |              this.customerBlacklistOptions = [];
 | 
	
		
			
				|  |  | +            /** @type {Array<CustomerRecord>} */
 | 
	
		
			
				|  |  | +            this.currentCustomerBlacklist = [];
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      }
 |