瀏覽代碼

完播、频道、每日统计

xdd 1 周之前
父節點
當前提交
327e8f946e

+ 87 - 18
src/components/TreeSelect/index.vue

@@ -168,6 +168,11 @@ export default {
     returnLeafOnly: {
       type: Boolean,
       default: true
+    },
+    // 新增属性:父节点是否可选
+    parentSelectable: {
+      type: Boolean,
+      default: false
     }
   },
   data() {
@@ -281,7 +286,8 @@ export default {
           [this.treeProps.label]: node[this.treeProps.label] || `节点-${node[this.nodeKey]}`,
           [this.treeProps.isLeaf]: !hasChildren,
           level: level,
-          disabled: hasChildren, // 有子节点的节点不可选择(非叶子节点)
+          // 根据 parentSelectable 属性决定父节点是否可选
+          disabled: hasChildren && !this.parentSelectable,
           originalData: { ...node },
           [this.treeProps.children]: hasChildren ? children.map(child => processNode(child, level + 1)) : undefined
         };
@@ -302,6 +308,27 @@ export default {
       return !node[this.treeProps.children] || node[this.treeProps.children].length === 0;
     },
 
+    /**
+     * 获取节点下所有叶子节点的ID
+     */
+    getAllLeafKeysUnderNode(nodeKey) {
+      const node = this.nodeMap[nodeKey];
+      if (!node) return [];
+
+      if (this.isLeafNode(node)) {
+        return [nodeKey];
+      }
+
+      const leafKeys = [];
+      const children = node[this.treeProps.children] || [];
+
+      children.forEach(child => {
+        leafKeys.push(...this.getAllLeafKeysUnderNode(child[this.nodeKey]));
+      });
+
+      return leafKeys;
+    },
+
     /**
      * 过滤出叶子节点的keys
      */
@@ -351,30 +378,72 @@ export default {
      * 处理树节点选择
      */
     handleTreeCheck(nodeData, checkStatus) {
-      // 如果是非叶子节点,不允许选择
-      if (!this.isLeafNode(nodeData)) {
+      const isNodeChecked = checkStatus.checkedKeys.includes(nodeData[this.nodeKey]);
+
+      // 如果选中的是父节点且父节点可选
+      if (!this.isLeafNode(nodeData) && this.parentSelectable && isNodeChecked) {
+        // 获取该父节点下所有叶子节点的ID
+        const leafKeysUnderParent = this.getAllLeafKeysUnderNode(nodeData[this.nodeKey]);
+
+        if (!this.multiple) {
+          // 单选模式:选择父节点下的第一个叶子节点
+          this.tempCheckedKeys = leafKeysUnderParent.slice(0, 1);
+        } else {
+          // 多选模式:添加所有叶子节点
+          const existingLeafKeys = this.tempCheckedKeys.filter(key => {
+            const node = this.nodeMap[key];
+            return node && this.isLeafNode(node);
+          });
+
+          // 合并现有的叶子节点和新选择的叶子节点,去重
+          const allLeafKeys = [...new Set([...existingLeafKeys, ...leafKeysUnderParent])];
+          this.tempCheckedKeys = allLeafKeys;
+        }
+
+        // 更新树的选中状态
+        this.$refs.taskTree.setCheckedKeys(this.tempCheckedKeys);
+        return;
+      }
+
+      // 如果取消选中父节点
+      if (!this.isLeafNode(nodeData) && this.parentSelectable && !isNodeChecked) {
+        // 获取该父节点下所有叶子节点的ID
+        const leafKeysUnderParent = this.getAllLeafKeysUnderNode(nodeData[this.nodeKey]);
+
+        // 从当前选中的keys中移除这些叶子节点
+        this.tempCheckedKeys = this.tempCheckedKeys.filter(key => !leafKeysUnderParent.includes(key));
+
+        // 更新树的选中状态
+        this.$refs.taskTree.setCheckedKeys(this.tempCheckedKeys);
+        return;
+      }
+
+      // 如果是非叶子节点且父节点不可选,不允许选择
+      if (!this.isLeafNode(nodeData) && !this.parentSelectable) {
         // 恢复之前的选中状态
         this.$refs.taskTree.setCheckedKeys(this.tempCheckedKeys);
         return;
       }
 
-      if (!this.multiple) {
-        const isNodeChecked = checkStatus.checkedKeys.includes(nodeData[this.nodeKey]);
-        if (isNodeChecked) {
-          this.tempCheckedKeys = [nodeData[this.nodeKey]];
-          this.$refs.taskTree.setCheckedKeys([nodeData[this.nodeKey]]);
+      // 处理叶子节点的选择
+      if (this.isLeafNode(nodeData)) {
+        if (!this.multiple) {
+          if (isNodeChecked) {
+            this.tempCheckedKeys = [nodeData[this.nodeKey]];
+            this.$refs.taskTree.setCheckedKeys([nodeData[this.nodeKey]]);
+          } else {
+            this.tempCheckedKeys = [];
+          }
         } else {
-          this.tempCheckedKeys = [];
+          // 只保留叶子节点的选中状态
+          const leafKeys = checkStatus.checkedKeys.filter(key => {
+            const node = this.nodeMap[key];
+            return node && this.isLeafNode(node);
+          });
+          this.tempCheckedKeys = leafKeys;
+          // 更新树的选中状态,确保只显示叶子节点被选中
+          this.$refs.taskTree.setCheckedKeys(leafKeys);
         }
-      } else {
-        // 只保留叶子节点的选中状态
-        const leafKeys = checkStatus.checkedKeys.filter(key => {
-          const node = this.nodeMap[key];
-          return node && this.isLeafNode(node);
-        });
-        this.tempCheckedKeys = leafKeys;
-        // 更新树的选中状态,确保只显示叶子节点被选中
-        this.$refs.taskTree.setCheckedKeys(leafKeys);
       }
     },
 

+ 14 - 2
src/views/statistics/section/channel.vue

@@ -6,6 +6,7 @@
           v-model="selectedCompanyList"
           :raw-data="deptList"
           placeholder="请选择销售"
+          :parentSelectable="true"
           :multiple="true"
           component-width="300px"
           :max-display-tags="3"
@@ -46,6 +47,7 @@
           v-model="selectedMultipleTasks"
           :raw-data="channelList"
           placeholder="请选择多个任务"
+          :parentSelectable="true"
           :multiple="true"
           component-width="300px"
           :max-display-tags="3"
@@ -116,7 +118,15 @@
 </template>
 
 <script>
-import { listEmployeeStats, getEmployeeList, getChannelList, exportEmployeeStats,getSOPTaskData,listPeriodList} from "@/api/system/employeeStats";
+import {
+  listEmployeeStats,
+  getEmployeeList,
+  getChannelList,
+  exportEmployeeStats,
+  getSOPTaskData,
+  listPeriodList,
+  getDeptData
+} from "@/api/system/employeeStats";
 import {getCompanyList} from "@/api/company/company";
 import {getUserList} from "@/api/company/companyUser";
 import SelectTree from "@/components/TreeSelect/index.vue";
@@ -180,7 +190,9 @@ export default {
     getSOPTaskData().then(response => {
       this.channelList = response.data;
     });
-
+    getDeptData().then(response => {
+      this.deptList = response.data;
+    })
   },
   methods: {
     handleCompanyUserId(val){

+ 2 - 0
src/views/statistics/section/index.vue

@@ -5,6 +5,7 @@
         <select-tree
           v-model="selectedCompanyList"
           :raw-data="deptList"
+          :parentSelectable="true"
           placeholder="请选择销售"
           :multiple="true"
           component-width="300px"
@@ -30,6 +31,7 @@
           v-model="selectedMultipleTasks"
           :raw-data="channelList"
           placeholder="请选择多个任务"
+          :parentSelectable="true"
           :multiple="true"
           component-width="300px"
           :max-display-tags="3"

+ 2 - 0
src/views/statistics/section/today.vue

@@ -6,6 +6,7 @@
           v-model="selectedCompanyList"
           :raw-data="deptList"
           placeholder="请选择销售"
+          :parentSelectable="true"
           :multiple="true"
           component-width="300px"
           :max-display-tags="3"
@@ -46,6 +47,7 @@
           v-model="selectedCompanyList"
           :raw-data="channelList"
           placeholder="请选择多个任务"
+          :parentSelectable="true"
           :multiple="true"
           component-width="300px"
           :max-display-tags="3"