From de147dda682f8ac597bbcc8555b57acbdf45dba2 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期四, 13 十一月 2025 16:55:51 +0800
Subject: [PATCH] 测试完成

---
 src/components/SortCheckbox/index.vue |  289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 289 insertions(+), 0 deletions(-)

diff --git a/src/components/SortCheckbox/index.vue b/src/components/SortCheckbox/index.vue
new file mode 100644
index 0000000..4ae95f1
--- /dev/null
+++ b/src/components/SortCheckbox/index.vue
@@ -0,0 +1,289 @@
+<template>
+  <div class="ordered-checkbox-container">
+    <!-- 妯悜鎺掑垪鐨勫閫夋缁� -->
+    <el-checkbox-group
+      v-model="checkedValues"
+      class="horizontal-checkbox-group"
+    >
+      <el-checkbox
+        v-for="option in options"
+        :key="getValue(option)"
+        :label="getValue(option)"
+      >
+        {{ getLabel(option) }}
+      </el-checkbox>
+    </el-checkbox-group>
+
+    <!-- 閫変腑椤哄簭灞曠ず鍖哄煙 -->
+    <div v-if="selectedOrder.length > 0" class="selection-order-display">
+      <span class="order-label">鏈嶅姟鎵ц椤哄簭锛�</span>
+      <span
+        v-for="(item, index) in selectedOrder"
+        :key="item.value"
+        class="order-item"
+      >
+        {{ getSelectedIndex(index) }}.{{ getLabelByValue(item.value) }}
+        <el-tooltip content="璁剧疆琛ュ伩鏃堕棿" placement="top">
+          <el-input-number
+            v-model="item.compensateTime"
+            :min="0"
+            :max="60"
+            size="mini"
+            controls-position="right"
+            class="compensate-time-input"
+            @change="handleCompensateTimeChange(item.value, $event)"
+          />
+        </el-tooltip>
+        <span v-if="index < selectedOrder.length - 1">銆�</span>
+      </span>
+    </div>
+    <div v-else class="selection-order-display">
+      <span class="order-label">鏆傛棤閫変腑椤�</span>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "OrderedCheckboxGroup",
+  props: {
+    options: {
+      type: Array,
+      default: () => [],
+    },
+    value: {
+      type: Array,
+      default: () => [],
+    },
+    initialselectedOrder: {
+      type: Array,
+      default: () => [],
+    },
+    valueKey: {
+      type: String,
+      default: "value",
+    },
+    labelKey: {
+      type: String,
+      default: "label",
+    },
+    // 鏂板锛氶粯璁よˉ鍋挎椂闂�
+    defaultCompensateTime: {
+      type: Number,
+      default: 0,
+    },
+  },
+  data() {
+    return {
+      checkedValues: [],
+      selectedOrder: [], // 鐜板湪鏍煎紡涓� [{value, compensateTime}]
+    };
+  },
+  watch: {
+    value: {
+      immediate: true,
+      handler(newVal) {
+        if (
+          Array.isArray(newVal) &&
+          newVal.length > 0 &&
+          typeof newVal[0] === "object"
+        ) {
+          console.log(this.selectedOrder, "111");
+
+          // 1. 浼犲叆鐨勬槸瀵硅薄鏁扮粍 [{ sort, preachform, compensateTime }]
+          this.checkedValues = newVal.map((item) => item.preachform); // 鎻愬彇 preachform 缁勬垚閫変腑鍊兼暟缁�
+          // 鏋勫缓 selectedOrder锛屼紭鍏堜娇鐢ㄤ紶鍏ョ殑 compensateTime锛屽惁鍒欑敤榛樿鍊�
+          this.selectedOrder = newVal.map((item) => ({
+            value: item.preachform,
+            compensateTime: item.hasOwnProperty("compensateTime")
+              ? item.compensateTime
+              : this.defaultCompensateTime,
+          }));
+        } else {
+          // 2. 浼犲叆鐨勬槸瀛楃涓叉暟缁� (濡� ["1", "3", "4"]锛屽吋瀹逛箣鍓嶇殑鐢ㄦ硶)
+          if (JSON.stringify(newVal) !== JSON.stringify(this.checkedValues)) {
+            this.checkedValues = [...newVal];
+            console.log(this.selectedOrder, "222");
+            console.log(this.newVal, "22");
+            // 鏋勫缓鎴栨洿鏂� selectedOrder锛屼繚鐣欏凡鏈夌殑 compensateTime
+            const newOrder = [];
+            newVal.forEach((value) => {
+              const existingItem = this.selectedOrder.find(
+                (item) => item.value === value
+              );
+              if (existingItem) {
+                newOrder.push(existingItem);
+              } else {
+                newOrder.push({
+                  value,
+                  compensateTime: this.hasOwnProperty(value)
+                    ? this.hasOwnProperty(value)
+                    : this.defaultCompensateTime,
+                });
+              }
+            });
+            this.selectedOrder = newOrder;
+          }
+        }
+      },
+      deep: true, // 寤鸿娣诲姞 deep: true 浠ョ‘淇濆璞℃暟缁勫唴鐨勫彉鍖栬兘琚崟鑾�
+    },
+    checkedValues(newVal, oldVal) {
+      console.log(this.selectedOrder, "333");
+      // 澶勭悊閫変腑椤圭殑鍙樺寲
+      const added = newVal.filter((item) => !oldVal.includes(item));
+      const removed = oldVal.filter((item) => !newVal.includes(item));
+
+      added.forEach((value) => {
+        if (!this.selectedOrder.find((item) => item.value === value)) {
+          this.selectedOrder.push({
+            value,
+            compensateTime: this.defaultCompensateTime,
+          });
+        }
+      });
+
+      removed.forEach((value) => {
+        const index = this.selectedOrder.findIndex(
+          (item) => item.value === value
+        );
+        if (index > -1) {
+          this.selectedOrder.splice(index, 1);
+        }
+      });
+
+      // 鏇存柊鐖剁粍浠剁殑 v-model 缁戝畾鍊硷紙閫変腑鍊兼暟缁勶級
+      this.$emit("input", [...newVal]);
+      // 瑙﹀彂 change 浜嬩欢锛屼紶閫掑畬鏁寸殑涓氬姟鏁版嵁
+      this.emitChangeEvent();
+    },
+  },
+  methods: {
+    getValue(option) {
+      return typeof option === "object" ? option[this.valueKey] : option;
+    },
+    getLabel(option) {
+      return typeof option === "object" ? option[this.labelKey] : option;
+    },
+    getLabelByValue(value) {
+      const option = this.options.find((opt) => this.getValue(opt) === value);
+      return option ? this.getLabel(option) : value;
+    },
+    getSelectedIndex(index) {
+      if (index < 20) {
+        return String.fromCharCode(0x2460 + index);
+      } else {
+        return `(${index + 1})`;
+      }
+    },
+    // 澶勭悊琛ュ伩鏃堕棿鍙樺寲
+    handleCompensateTimeChange(value, newTime) {
+      const item = this.selectedOrder.find((item) => item.value === value);
+      if (item) {
+        item.compensateTime = newTime;
+        // 琛ュ伩鏃堕棿鍙樺寲鏃讹紝鍙Е鍙� change 浜嬩欢锛屼笉瑙﹀姩 v-model
+        this.emitChangeEvent();
+      }
+    },
+    hasOwnProperty(patfrom) {
+      console.log(patfrom);
+      console.log(this.initialselectedOrder);
+      // 浣跨敤find鏂规硶鏌ユ壘鍖归厤鐨勫璞�
+      const foundObject = this.initialselectedOrder.find(
+        (item) => item.preachform === patfrom
+      );
+
+      // 濡傛灉鎵惧埌瀵硅薄锛岃繑鍥炲叾compensateTime锛涘惁鍒欒繑鍥瀎alse
+      return foundObject ? foundObject.compensateTime : false;
+    },
+    // 鍙戝皠鍙樺寲浜嬩欢
+    emitChangeEvent() {
+      // 杞崲鏁版嵁鏍煎紡涓虹埗缁勪欢闇�瑕佺殑鏍煎紡
+      const outputData = this.selectedOrder.map((item, index) => ({
+        sort: index + 1,
+        preachform: item.value,
+        compensateTime: item.compensateTime,
+      }));
+      this.$emit("change", outputData); // 鍙戝皠 change 浜嬩欢锛屼紶閫掑畬鏁存暟鎹�
+    },
+    // 鑾峰彇褰撳墠閫夋嫨椤哄簭鍜岃ˉ鍋挎椂闂�
+    getSelectionOrder() {
+      return this.selectedOrder.map((item, index) => ({
+        sort: index + 1,
+        preachform: item.value,
+        compensateTime: item.compensateTime,
+      }));
+    },
+    // 璁剧疆閫夋嫨椤哄簭鍜岃ˉ鍋挎椂闂�
+    setSelectionOrder(orderedValues) {
+      this.selectedOrder = orderedValues.map((item) => ({
+        value: item.preachform,
+        compensateTime: item.compensateTime || this.defaultCompensateTime,
+      }));
+
+      this.checkedValues = orderedValues.map((item) => item.preachform);
+      this.emitChangeEvent();
+    },
+  },
+};
+</script>
+
+<style scoped>
+.ordered-checkbox-container {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+}
+
+.horizontal-checkbox-group {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 20px;
+}
+
+.selection-order-display {
+  padding: 12px;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #ebeef5;
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+}
+
+.order-label {
+  font-weight: bold;
+  color: #606266;
+  margin-right: 8px;
+}
+
+.order-item {
+  color: #409eff;
+  font-weight: 500;
+  display: inline-flex;
+  align-items: center;
+  margin-right: 8px;
+}
+
+.compensate-time-input {
+  width: 90px;
+  margin-left: 8px;
+}
+
+/* 鍝嶅簲寮忚璁★細灏忓睆骞曟椂鎹㈣ */
+@media (max-width: 768px) {
+  .horizontal-checkbox-group {
+    gap: 12px;
+  }
+
+  .selection-order-display {
+    padding: 8px;
+    flex-direction: column;
+    align-items: flex-start;
+  }
+
+  .order-item {
+    margin-bottom: 8px;
+  }
+}
+</style>

--
Gitblit v1.9.3