Преглед изворни кода

feat(公告管理): 重构角色权限显示逻辑为位运算方式

yz пре 3 недеља
родитељ
комит
9d57808899
2 измењених фајлова са 127 додато и 39 уклоњено
  1. 115 37
      src/views/announcement/index.js
  2. 12 2
      src/views/announcement/index.vue

+ 115 - 37
src/views/announcement/index.js

@@ -2,15 +2,25 @@ import { getList, update, add, getAnnouncement, getCategoryList } from "@/api/an
 import { mapGetters } from "vuex";
 
 /**
- * 可见角色枚举类型 (位运算掩码)
- * @typedef {'1'|'2'|'3'|'4'|'5'|'6'|'7'} VisibleRolesMask
- * - '1': 工厂
- * - '2': 经销商
- * - '3': 工厂+经销商
- * - '4': 零售商
- * - '5': 工厂+零售商
- * - '6': 经销商+零售商
- * - '7': 工厂+经销商+零售商
+ * 角色类型枚举
+ * @typedef {1|2|4} RoleType
+ * - 1: 工厂
+ * - 2: 经销商
+ * - 4: 零售商
+ */
+
+/**
+ * 可见角色掩码类型 (位运算)
+ * @typedef {number} VisibleRolesMask
+ * 支持的值:1(工厂) | 2(经销商) | 4(零售商) 及其组合
+ * 例如:3(工厂+经销商), 5(工厂+零售商), 6(经销商+零售商), 7(全部)
+ */
+
+/**
+ * 角色选项类型定义
+ * @typedef {Object} RoleOption
+ * @property {string} label - 角色显示名称
+ * @property {RoleType} value - 角色值(位运算)
  */
 
 /**
@@ -95,6 +105,12 @@ export default {
             selectionList: [],
             /** @type {CategoryOption[]} 分类选项列表 */
             categoryOptions: [],
+            /** @type {RoleOption[]} 角色选项列表 */
+            roleOptions: [
+                { label: "工厂", value: 1 },
+                { label: "经销商", value: 2 },
+                { label: "零售商", value: 4 }
+            ],
             /** @type {Object} 表格配置选项 */
             option: {
                 height: 'auto',
@@ -110,7 +126,7 @@ export default {
                 selection: true,
                 excelBtn: false,
                 columnBtn: false,
-                delBtn: false, // 根据需求移除删除功能
+                delBtn: false,
                 dialogClickModal: false,
                 column: [
                     {
@@ -161,7 +177,7 @@ export default {
                         type: "number",
                         rules: [{
                             required: true,
-                            message: "请输入组织名称",
+                            message: "请输入组织ID",
                             trigger: "blur"
                         }]
                     },
@@ -178,15 +194,11 @@ export default {
                     {
                         label: "可见角色",
                         prop: "visibleRoles",
-                        type: "select",
+                        type: "checkbox",
                         dicData: [
-                            { label: "工厂", value: "1" },
-                            { label: "经销商", value: "2" },
-                            { label: "工厂+经销商", value: "3" },
-                            { label: "零售商", value: "4" },
-                            { label: "工厂+零售商", value: "5" },
-                            { label: "经销商+零售商", value: "6" },
-                            { label: "工厂+经销商+零售商", value: "7" }
+                            { label: "工厂", value: 1 },
+                            { label: "经销商", value: 2 },
+                            { label: "零售商", value: 4 }
                         ],
                         slot: true,
                         span: 12,
@@ -352,24 +364,34 @@ export default {
             }
         },
         /**
-         * 获取状态文本
-         * @param {AnnouncementStatus} status - 状态值
-         * @returns {string} 状态文本
+         * 计算角色掩码值
+         * @param {RoleType[]} selectedRoles - 选中的角色数组
+         * @returns {VisibleRolesMask} 计算后的掩码值
          */
-        getStatusText(status) {
-            const statusMap = {
-                0: '草稿',
-                1: '已发布',
-                2: '已下架'
-            };
-            return statusMap[status] ? statusMap[status] : '未知状态';
+        calculateRolesMask(selectedRoles) {
+            if (!Array.isArray(selectedRoles) || selectedRoles.length === 0) {
+                return 0;
+            }
+            return selectedRoles.reduce((mask, role) => mask | role, 0);
         },
         /**
-         * 获取可见角色文本 (支持位运算掩码)
+         * 解析角色掩码为角色数组
+         * @param {VisibleRolesMask} rolesMask - 角色掩码值
+         * @returns {RoleType[]} 角色数组
+         */
+        parseRolesMask(rolesMask) {
+            const roles = [];
+            if (rolesMask & 1) roles.push(1); // 工厂
+            if (rolesMask & 2) roles.push(2); // 经销商
+            if (rolesMask & 4) roles.push(4); // 零售商
+            return roles;
+        },
+        /**
+         * 获取可见角色文本数组 (支持位运算掩码)
          * @param {VisibleRolesMask} visibleRoles - 可见角色掩码值
-         * @returns {string} 角色文本
+         * @returns {string[]} 角色文本数组
          */
-        getVisibleRolesText(visibleRoles) {
+        getVisibleRolesTextArray(visibleRoles) {
             const roleValue = parseInt(visibleRoles, 10);
             const roles = [];
 
@@ -378,7 +400,15 @@ export default {
             if (roleValue & 2) roles.push('经销商');    // 2: 经销商
             if (roleValue & 4) roles.push('零售商');    // 4: 零售商
 
-            return roles.length > 0 ? roles.join('+') : '未知角色';
+            return roles.length > 0 ? roles : ['未知角色'];
+        },
+        /**
+         * 获取可见角色文本 (支持位运算掩码)
+         * @param {VisibleRolesMask} visibleRoles - 可见角色掩码值
+         * @returns {string} 角色文本
+         */
+        getVisibleRolesText(visibleRoles) {
+            return this.getVisibleRolesTextArray(visibleRoles).join('+');
         },
         /**
          * 查看详情
@@ -409,6 +439,11 @@ export default {
          */
         async rowSave(row, done, loading) {
             try {
+                // 计算角色掩码值
+                const rolesMask = Array.isArray(row.visibleRoles)
+                    ? this.calculateRolesMask(row.visibleRoles)
+                    : (row.visibleRoles || 7); // 默认所有角色可见
+
                 // 设置默认值
                 const formData = {
                     ...row,
@@ -418,7 +453,7 @@ export default {
                     brandScope: row.brandScope || {},
                     customerBlacklist: row.customerBlacklist || {},
                     remark: row.remark || '',
-                    visibleRoles: row.visibleRoles || '7', // 默认所有角色可见
+                    visibleRoles: rolesMask,
                     status: row.status !== undefined ? row.status : 0, // 默认草稿状态
                 };
 
@@ -452,6 +487,11 @@ export default {
          */
         async rowUpdate(row, index, done, loading) {
             try {
+                // 计算角色掩码值
+                const rolesMask = Array.isArray(row.visibleRoles)
+                    ? this.calculateRolesMask(row.visibleRoles)
+                    : row.visibleRoles;
+
                 // 设置分类名称
                 const selectedCategory = this.categoryOptions.find(cat => cat.id === row.categoryId);
                 if (selectedCategory) {
@@ -463,7 +503,8 @@ export default {
                     ...row,
                     brandScope: row.brandScope || {},
                     customerBlacklist: row.customerBlacklist || {},
-                    remark: row.remark || ''
+                    remark: row.remark || '',
+                    visibleRoles: rolesMask
                 };
 
                 await update(formData);
@@ -526,7 +567,10 @@ export default {
             if (["edit", "view"].includes(type)) {
                 try {
                     const res = await getAnnouncement(this.form.id);
-                    this.form = res.data.data;
+                    const formData = res.data.data;
+                    // 将掩码值转换为数组格式供表单使用
+                    formData.visibleRoles = this.parseRolesMask(formData.visibleRoles);
+                    this.form = formData;
                 } catch (error) {
                     console.error('获取详情失败:', error);
                 }
@@ -536,7 +580,7 @@ export default {
                     orgId: this.userInfo.orgId || 1,
                     orgCode: this.userInfo.orgCode || 'ORG_0001',
                     orgName: this.userInfo.orgName || '默认组织',
-                    visibleRoles: '2', // 默认普通用户
+                    visibleRoles: [2], // 默认经销商
                     brandScope: {},
                     customerBlacklist: {},
                     remark: ''
@@ -568,6 +612,40 @@ export default {
             this.onLoad(this.page, this.query);
         },
         /**
+         * 获取状态文本
+         * @param {AnnouncementStatus} status - 状态值
+         * @returns {string} 状态文本
+         */
+        getStatusText(status) {
+            const statusMap = {
+                0: '草稿',
+                1: '已发布',
+                2: '已下架'
+            };
+            return statusMap[status] ? statusMap[status] : '未知状态';
+        },
+        getRoleLabel(roleValue) {
+            const roleMap = {
+                1: '工厂',
+                2: '经销商',
+                4: '零售商'
+            };
+            return roleMap[roleValue] || '未知角色';
+        },
+        /**
+         * 获取角色标签类型
+         * @param {RoleType} roleValue - 角色值
+         * @returns {string} 标签类型
+         */
+        getRoleTagType(roleValue) {
+            const roleTagMap = {
+                1: 'success',    // 工厂 - 绿色
+                2: 'warning',    // 经销商 - 橙色
+                4: 'info'        // 零售商 - 蓝色
+            };
+            return roleTagMap[roleValue] || 'default';
+        },
+        /**
          * 加载数据
          * @async
          * @param {PageInfo} page - 分页信息

+ 12 - 2
src/views/announcement/index.vue

@@ -40,7 +40,11 @@
                 </el-tag>
             </template>
             <template slot-scope="{row}" slot="visibleRoles">
-                <el-tag>{{ getVisibleRolesText(row.visibleRoles) }}</el-tag>
+                <span v-for="role in parseRolesMask(row.visibleRoles)" :key="role.value">
+                    <el-tag :type="getRoleTagType(role)" size="mini" style="margin-right: 4px;">
+                        {{ getRoleLabel(role) }}
+                    </el-tag>
+                </span>
             </template>
         </avue-crud>
 
@@ -52,7 +56,13 @@
                     <p><strong>分类:</strong>{{ currentDetail.categoryName }}</p>
                     <p><strong>组织:</strong>{{ currentDetail.orgName }}</p>
                     <p><strong>创建时间:</strong>{{ currentDetail.createTime }}</p>
-                    <p><strong>可见角色:</strong>{{ getVisibleRolesText(currentDetail.visibleRoles) }}</p>
+                    <p><strong>可见角色:</strong>
+                        <span v-for="role in parseRolesMask(currentDetail.visibleRoles)" :key="role.value">
+                            <el-tag :type="getRoleTagType(role.value)" size="mini" style="margin-right: 4px;">
+                                {{ role.label }}
+                            </el-tag>
+                        </span>
+                    </p>
                     <p><strong>状态:</strong>
                         <el-tag :type="currentDetail.status === 1 ? 'success' : 'danger'">
                             {{ currentDetail.status === 1 ? '正常' : '禁用' }}