quyx@nextosd.com 4 月之前
父节点
当前提交
9c90ae9682
共有 1 个文件被更改,包括 36 次插入109 次删除
  1. 36 109
      src/components/RegionNode.vue

+ 36 - 109
src/components/RegionNode.vue

@@ -1,35 +1,23 @@
-<!-- RegionNode.vue -->
 <template>
   <li class="region-node">
-    <div class="region-header relative"> <!-- 新增 relative 类 -->
-      <!-- 复选框使用绝对定位,固定位置 -->
-      <div class="checkbox-wrapper absolute">
-        <input
-            type="checkbox"
-            :id="region.regionId"
-            :checked="region.checked"
-            :indeterminate="region.indeterminate"
-            @change="toggleRegion"
-            :disabled="disabled"
-        />
-      </div>
-      <!-- 文字使用 padding 留出左侧空间 -->
-      <label
-          :style="{
-          color: disabled ? (region.checked ? '#a8abb2' : '#a8abb2') : (region.checked ? '#FF0066' : '#606266'),
-          cursor: disabled ? 'not-allowed' : 'pointer'
-        }"
-          :for="region.id"
+    <div class="region-header">
+      <!-- 使用Element Plus默认样式的el-checkbox -->
+      <el-checkbox
           class="ml-checkbox"
+          :id="region.regionId"
+          v-model="region.checked"
+          :indeterminate="region.indeterminate"
+          @change="handleCheckboxChange"
+          :disabled="disabled"
       >
         {{ region.regionName }}
-      </label>
+      </el-checkbox>
     </div>
 
     <ul v-if="region.children && region.children.length > 0" class="child-nodes">
       <RegionNode
           v-for="child in region.children"
-          :key="child.id"
+          :key="child.regionId"
           :region="child"
           @check-change="handleChildCheckChange"
           :disabled="disabled"
@@ -39,12 +27,13 @@
 </template>
 
 <script setup>
-import {defineEmits, defineProps} from 'vue';
+import { defineEmits, defineProps } from 'vue';
 
 const props = defineProps({
   region: {
     type: Object,
-    required: true
+    required: true,
+    default: () => ({})
   },
   disabled: {
     type: Boolean,
@@ -56,21 +45,23 @@ const emits = defineEmits(['check-change']);
 
 // 初始化节点状态
 const initNodeState = (node) => {
+  if (!node) return;
+  // 确保节点有必要的属性
+  if (node.checked === undefined) node.checked = false;
+  if (node.indeterminate === undefined) node.indeterminate = false;
+
   if (node.children && node.children.length > 0) {
-    node.children.forEach(child => {
-      initNodeState(child);
-    });
+    node.children.forEach(child => initNodeState(child));
   }
 };
 
 // 初始化当前节点
 initNodeState(props.region);
 
-// 切换节点选中状态
-const toggleRegion = () => {
-  const newChecked = !props.region.checked;
-  updateNodeChecked(props.region, newChecked);
-  emits('check-change', props.region.regionId, newChecked);
+// 处理复选框变更
+const handleCheckboxChange = (checked) => {
+  updateNodeChecked(props.region, checked);
+  emits('check-change', props.region.regionId, checked);
 };
 
 // 处理子节点选中状态变更
@@ -79,9 +70,10 @@ const handleChildCheckChange = (childId, isChecked) => {
   updateParentState(props.region);
 };
 
-
 // 更新节点及其子节点的选中状态
 const updateNodeChecked = (node, isChecked) => {
+  if (!node) return;
+
   node.checked = isChecked;
   node.indeterminate = false;
 
@@ -93,112 +85,47 @@ const updateNodeChecked = (node, isChecked) => {
 };
 
 // 更新父节点状态
-// const updateParentState = (parentNode) => {
-//   if (!parentNode.children || parentNode.children.length === 0) return;
-//
-//   const allChecked = parentNode.children.every(child => child.checked);
-//   const noneChecked = parentNode.children.every(child => !child.checked);
-//
-//   parentNode.checked = allChecked;
-//   parentNode.indeterminate = !allChecked && !noneChecked;
-// };
 const updateParentState = (parentNode) => {
-  if (!parentNode.children || parentNode.children.length === 0) return;
+  if (!parentNode || !parentNode.children || parentNode.children.length === 0) return;
 
-  // 子ノードが選択されている限り、親ノードはchecked:trueとマークされます。
   parentNode.checked = parentNode.children.some(child => child.checked);
-  // indeterminateを必要とせずにfalseにする
   parentNode.indeterminate = false;
 };
 </script>
 
 <style scoped>
 .region-node {
-  margin: 4px 0;
+  margin: 1px 0;
+  list-style: none;
 }
 
 .region-header {
   display: flex;
   align-items: center;
-  cursor: pointer;
-}
-.region-header label {
-  font-size: 14px;
-  font-weight: 400;
+  margin-bottom: 0;
 }
 
 .child-nodes {
-  margin-left: 20px;
+  margin-left: 15px;
   padding-left: 0;
-  list-style: none;
   display: flex;
   flex-wrap: wrap;
   gap: 29px;
   row-gap: 3px;
-  }
+}
 
 .child-nodes .region-node {
   width: calc(100% / 7 - 26px);
   box-sizing: border-box;
 }
 
-input[type="checkbox"] {
-  -webkit-appearance: none;
-  -moz-appearance: none;
-  appearance: none;
-  width: 14px;
-  height: 14px;
-  border: 1px solid #dcdfe6;
-  border-radius: 2px;
-  background-color: white;
-  position: relative;
-  cursor: pointer;
-  vertical-align: middle;
-  margin-right: 1px;
-  margin-top: -4px;
-}
-input[type="checkbox"]:checked {
-  background-color: #FF0066;
-  border-color: #FF0066;
-}
-
-input[type="checkbox"]:checked::after {
-  content: "";
-  position: absolute;
-  left: 3.85px;
-  top: 0.7px;
-  width: 4.14px;
-  height: 7.88px;
-  border: 1.53px solid white;
-  border-top: none;
-  border-left: none;
-  transform: rotate(45deg);
-}
-.relative {
-  position: relative;
-}
-
-.checkbox-wrapper {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 16px;
-}
-
 .ml-checkbox {
-  padding-left: 22px;
+  padding-left: 3px;
   display: block;
-  margin-top: 1px;
-}
-input[type="checkbox"]:disabled {
-  background-color: #f5f7fa;
-  border-color: #e4e7ed;
-  cursor: not-allowed;
 }
-input[type="checkbox"]:disabled:checked {
-  background-color: #f2f6fc;
-}
-input[type="checkbox"]:disabled:checked::after {
-  border-color: #a8abb2;
+@media (max-width: 767px) {
+  .child-nodes .region-node {
+    width: calc(100% / 4 - 12px);
+  }
 }
 </style>