liujt 20 часов назад
Родитель
Сommit
a3015c7758

+ 68 - 47
lib/vue-form-making-v3/dist/form-making-v3.es.js

@@ -49960,15 +49960,26 @@ const _sfc_main$10 = {
     const fieldValue = ref("");
     const cascaderValue = ref("");
     const show2 = ref(false);
+    function normalizeTree(list) {
+      return (list || []).map((node) => {
+        var _a2, _b;
+        return {
+          value: node.value,
+          text: (_b = (_a2 = node.text) != null ? _a2 : node.label) != null ? _b : node.name,
+          children: node.children && node.children.length ? normalizeTree(node.children) : void 0
+        };
+      });
+    }
+    const normalizedOptions = computed(() => normalizeTree(props2.options));
     watchEffect(() => {
       var _a2;
       if (props2.isPathValue) {
         const values = Array.isArray(props2.modelValue) ? props2.modelValue : [props2.modelValue];
-        fieldValue.value = getCascaderText([...values], props2.options).join("/");
+        fieldValue.value = getCascaderText([...values], normalizedOptions.value).join("/");
         cascaderValue.value = values.length > 0 ? values[values.length - 1] : "";
       } else {
         const value = Array.isArray(props2.modelValue) ? (_a2 = props2.modelValue) == null ? void 0 : _a2[0] : props2.modelValue;
-        fieldValue.value = getTreeText(value, props2.options);
+        fieldValue.value = getTreeText(value, normalizedOptions.value);
         cascaderValue.value = value;
       }
     });
@@ -50052,7 +50063,7 @@ const _sfc_main$10 = {
             createVNode(_component_van_cascader, mergeProps({
               modelValue: cascaderValue.value,
               "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => cascaderValue.value = $event),
-              options: __props.options,
+              options: normalizedOptions.value,
               title: __props.publicProps.label,
               onClose: _cache[2] || (_cache[2] = ($event) => show2.value = false),
               onFinish
@@ -50426,24 +50437,22 @@ const _sfc_main$_ = {
     function selectedLeafSet() {
       const set = /* @__PURE__ */ new Set();
       props2.modelValue.forEach((p) => {
-        if (Array.isArray(p))
-          set.add(p[p.length - 1]);
-        else
-          set.add(p);
+        const leaf = Array.isArray(p) ? p[p.length - 1] : p;
+        set.add(String(leaf));
       });
       return set;
     }
     function pathKey(p) {
-      return Array.isArray(p) ? p.join("/") : String(p);
+      return Array.isArray(p) ? p.map(String).join("/") : String(p);
     }
     function state(node) {
       if (!hasChildren(node)) {
-        return { checked: selectedLeafSet().has(node.value), indeterminate: false };
+        return { checked: selectedLeafSet().has(String(node.value)), indeterminate: false };
       }
       const leaves = collectLeaves(node);
       if (leaves.length === 0)
         return { checked: false, indeterminate: false };
-      const sel = leaves.filter((v) => selectedLeafSet().has(v));
+      const sel = leaves.filter((v) => selectedLeafSet().has(String(v)));
       return {
         checked: sel.length === leaves.length,
         indeterminate: sel.length > 0 && sel.length < leaves.length
@@ -50452,17 +50461,14 @@ const _sfc_main$_ = {
     function toggle2(node) {
       const paths = collectPaths(node, props2.prefix);
       const isChecked = state(node).checked;
-      const set = new Set(props2.modelValue.map(pathKey));
+      const pathMap = new Map(props2.modelValue.map((p) => [pathKey(p), p]));
       if (isChecked) {
         const rm = new Set(paths.map(pathKey));
-        set.forEach((k) => {
-          if (rm.has(k))
-            set.delete(k);
-        });
+        rm.forEach((k) => pathMap.delete(k));
       } else {
-        paths.forEach((p) => set.add(pathKey(p)));
+        paths.forEach((p) => pathMap.set(pathKey(p), p));
       }
-      emitChange([...set].map((k) => k.split("/")));
+      emitChange([...pathMap.values()]);
     }
     function emitChange(val) {
       emit2("update:modelValue", val);
@@ -50511,7 +50517,7 @@ const _sfc_main$_ = {
     };
   }
 };
-var DeptCascaderTree = /* @__PURE__ */ _export_sfc(_sfc_main$_, [["__scopeId", "data-v-d69faff4"]]);
+var DeptCascaderTree = /* @__PURE__ */ _export_sfc(_sfc_main$_, [["__scopeId", "data-v-1ec09c66"]]);
 var DeptCascader_vue_vue_type_style_index_0_scoped_true_lang = "";
 const _hoisted_1$z = { class: "dept-cascader__header" };
 const _hoisted_2$w = { class: "dept-cascader__title" };
@@ -50550,10 +50556,24 @@ const _sfc_main$Z = {
     function isLeaf(node) {
       return !node.children || node.children.length === 0;
     }
+    function normalizeTree(list) {
+      return (list || []).map((node) => {
+        var _a2, _b;
+        return {
+          value: node.value,
+          text: (_b = (_a2 = node.text) != null ? _a2 : node.label) != null ? _b : node.name,
+          children: node.children && node.children.length ? normalizeTree(node.children) : void 0
+        };
+      });
+    }
+    const normalizedOptions = computed(() => normalizeTree(props2.options));
+    function sameVal(a, b) {
+      return String(a) === String(b);
+    }
     function getTreeText(value, options) {
       for (let i = 0; i < options.length; i++) {
         const cur = options[i];
-        if (cur.value === value)
+        if (sameVal(cur.value, value))
           return cur.text;
         if (!isLeaf(cur)) {
           const res = getTreeText(value, cur.children);
@@ -50565,7 +50585,7 @@ const _sfc_main$Z = {
     }
     function getCascaderText(values, options, texts = []) {
       if (values.length >= 1) {
-        const cur = options == null ? void 0 : options.find((opt) => opt.value === values[0]);
+        const cur = options == null ? void 0 : options.find((opt) => sameVal(opt.value, values[0]));
         if (cur)
           texts.push(cur.text);
         values.splice(0, 1);
@@ -50576,7 +50596,7 @@ const _sfc_main$Z = {
     function findPath(value, options, prefix = []) {
       for (const opt of options) {
         const cur = [...prefix, opt.value];
-        if (opt.value === value)
+        if (sameVal(opt.value, value))
           return cur;
         if (opt.children && opt.children.length) {
           const r = findPath(value, opt.children, cur);
@@ -50590,7 +50610,7 @@ const _sfc_main$Z = {
       const texts = [];
       let cur = options;
       for (const v of path) {
-        const node = cur == null ? void 0 : cur.find((o) => o.value === v);
+        const node = cur == null ? void 0 : cur.find((o) => sameVal(o.value, v));
         if (!node)
           break;
         texts.push(node.text);
@@ -50598,27 +50618,28 @@ const _sfc_main$Z = {
       }
       return texts.join("/");
     }
-    watch(
-      () => props2.modelValue,
-      (val) => {
-        if (props2.multiple) {
-          const arr = Array.isArray(val) ? val : val ? [val] : [];
-          selectedValues.value = arr.map(
-            (item2) => Array.isArray(item2) ? item2 : findPath(item2, props2.options) || [item2]
-          );
-          fieldValue.value = selectedValues.value.map((p) => Array.isArray(p) ? getPathText(p, props2.options) : getTreeText(p, props2.options)).filter(Boolean).join("\u3001");
-        } else if (props2.isPathValue) {
-          const values = Array.isArray(val) ? val : val ? [val] : [];
-          cascaderValue.value = values.length ? values[values.length - 1] : "";
-          fieldValue.value = getCascaderText([...values], props2.options).join("/");
-        } else {
-          const value = Array.isArray(val) ? val[0] : val;
-          cascaderValue.value = value;
-          fieldValue.value = getTreeText(value, props2.options);
-        }
-      },
-      { immediate: true }
-    );
+    function computeMultiText(paths) {
+      return paths.map((p) => Array.isArray(p) ? getPathText(p, normalizedOptions.value) : getTreeText(p, normalizedOptions.value)).filter(Boolean).join("\u3001");
+    }
+    function applyModelValue(val) {
+      if (props2.multiple) {
+        const arr = Array.isArray(val) ? val : val ? [val] : [];
+        selectedValues.value = arr.map(
+          (item2) => Array.isArray(item2) ? item2 : findPath(item2, normalizedOptions.value) || [item2]
+        );
+        fieldValue.value = computeMultiText(selectedValues.value);
+      } else if (props2.isPathValue) {
+        const values = Array.isArray(val) ? val : val ? [val] : [];
+        cascaderValue.value = values.length ? values[values.length - 1] : "";
+        fieldValue.value = getCascaderText([...values], normalizedOptions.value).join("/");
+      } else {
+        const value = Array.isArray(val) ? val[0] : val;
+        cascaderValue.value = value;
+        fieldValue.value = getTreeText(value, normalizedOptions.value);
+      }
+    }
+    watch(() => props2.modelValue, (val) => applyModelValue(val), { immediate: true });
+    watch(() => props2.options, () => applyModelValue(props2.modelValue), { deep: true });
     function onFinish({ selectedOptions }) {
       if (props2.isPathValue) {
         emit2("update:modelValue", selectedOptions.map((i) => i.value));
@@ -50632,7 +50653,7 @@ const _sfc_main$Z = {
     function onMultiChange(val) {
       emit2("update:modelValue", val);
       selectedValues.value = val;
-      fieldValue.value = val.map((p) => Array.isArray(p) ? getPathText(p, props2.options) : getTreeText(p, props2.options)).filter(Boolean).join("\u3001");
+      fieldValue.value = computeMultiText(val);
     }
     function onShowPicker() {
       if (props2.printRead || props2.disabled)
@@ -50704,7 +50725,7 @@ const _sfc_main$Z = {
               ]),
               __props.multiple ? (openBlock(), createElementBlock("div", _hoisted_4$l, [
                 createVNode(DeptCascaderTree, {
-                  nodes: __props.options,
+                  nodes: normalizedOptions.value,
                   "model-value": selectedValues.value,
                   "expand-all": expandAll.value,
                   "onUpdate:modelValue": onMultiChange
@@ -50713,7 +50734,7 @@ const _sfc_main$Z = {
                 key: 1,
                 modelValue: cascaderValue.value,
                 "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => cascaderValue.value = $event),
-                options: __props.options,
+                options: normalizedOptions.value,
                 title: __props.title || ((_b = __props.publicProps) == null ? void 0 : _b.label),
                 onClose: _cache[3] || (_cache[3] = ($event) => show2.value = false),
                 onFinish
@@ -50726,7 +50747,7 @@ const _sfc_main$Z = {
     };
   }
 };
-var FmVantDeptCascader = /* @__PURE__ */ _export_sfc(_sfc_main$Z, [["__scopeId", "data-v-bb4c6c32"]]);
+var FmVantDeptCascader = /* @__PURE__ */ _export_sfc(_sfc_main$Z, [["__scopeId", "data-v-0333cc83"]]);
 const _sfc_main$Y = {
   components: {
     FmVantSelect,

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
lib/vue-form-making-v3/dist/form-making-v3.umd.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
lib/vue-form-making-v3/dist/index.css


+ 15 - 4
lib/vue-form-making-v3/src/components/VantGenerator/components/Cascader.vue

@@ -1,5 +1,5 @@
 <script setup>
-import { ref, watchEffect } from 'vue'
+import { ref, watchEffect, computed } from 'vue'
 
 const props = defineProps({
   modelValue: [String, Number, Array],
@@ -20,17 +20,28 @@ const fieldValue = ref('')
 const cascaderValue = ref('')
 const show = ref(false)
 
+// 兼容「设计器」(text) 与「生成器」(label) 两种字段命名,统一成 text
+function normalizeTree(list) {
+  return (list || []).map((node) => ({
+    value: node.value,
+    text: node.text ?? node.label ?? node.name,
+    children: node.children && node.children.length ? normalizeTree(node.children) : undefined
+  }))
+}
+
+const normalizedOptions = computed(() => normalizeTree(props.options))
+
 watchEffect(() => {
   if (props.isPathValue) {
     const values = Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]
 
-    fieldValue.value = getCascaderText([...values], props.options).join('/')
+    fieldValue.value = getCascaderText([...values], normalizedOptions.value).join('/')
 
     cascaderValue.value = values.length > 0 ? values[values.length - 1] : ''
   } else {
     const value = Array.isArray(props.modelValue) ? props.modelValue?.[0] : props.modelValue
 
-    fieldValue.value = getTreeText(value, props.options)
+    fieldValue.value = getTreeText(value, normalizedOptions.value)
     cascaderValue.value = value
   }
 })
@@ -106,7 +117,7 @@ function onShowPicker () {
 <van-popup v-model:show="show" round position="bottom" teleport="body" z-index="5000">
   <van-cascader
     v-model="cascaderValue"
-    :options="options"
+    :options="normalizedOptions"
     :title="publicProps.label"
     @close="show = false"
     @finish="onFinish"

+ 50 - 32
lib/vue-form-making-v3/src/components/VantGenerator/components/DeptCascader.vue

@@ -25,7 +25,7 @@
 
     <div v-if="multiple" class="dept-cascader__body">
       <DeptCascaderTree
-        :nodes="options"
+        :nodes="normalizedOptions"
         :model-value="selectedValues"
         :expand-all="expandAll"
         @update:model-value="onMultiChange"
@@ -35,7 +35,7 @@
     <van-cascader
       v-else
       v-model="cascaderValue"
-      :options="options"
+      :options="normalizedOptions"
       :title="title || publicProps?.label"
       @close="show = false"
       @finish="onFinish"
@@ -45,7 +45,7 @@
 </template>
 
 <script setup>
-import { ref, watch } from 'vue'
+import { ref, watch, computed } from 'vue'
 import DeptCascaderTree from './DeptCascaderTree.vue'
 
 const props = defineProps({
@@ -74,6 +74,18 @@ function isLeaf(node) {
   return !node.children || node.children.length === 0
 }
 
+// 兼容「设计器」(text) 与「生成器」(label) 两种字段命名,统一成 text,
+// 否则从生成器拿到的 {value,label,children} 在详情里读不到 text → 显示为空
+function normalizeTree(list) {
+  return (list || []).map((node) => ({
+    value: node.value,
+    text: node.text ?? node.label ?? node.name,
+    children: node.children && node.children.length ? normalizeTree(node.children) : undefined
+  }))
+}
+
+const normalizedOptions = computed(() => normalizeTree(props.options))
+
 // 数值 / 字符串 id 统一比较,保证 Vue2 保存的数值 id 在 v3 详情返显时仍能对上
 function sameVal(a, b) {
   return String(a) === String(b)
@@ -127,31 +139,40 @@ function getPathText(path, options) {
   return texts.join('/')
 }
 
-watch(
-  () => props.modelValue,
-  (val) => {
-    if (props.multiple) {
-      const arr = Array.isArray(val) ? val : val ? [val] : []
-      // 兼容旧格式:纯叶子值自动补成完整路径
-      selectedValues.value = arr.map((item) =>
-        Array.isArray(item) ? item : findPath(item, props.options) || [item]
-      )
-      fieldValue.value = selectedValues.value
-        .map((p) => (Array.isArray(p) ? getPathText(p, props.options) : getTreeText(p, props.options)))
-        .filter(Boolean)
-        .join('、')
-    } else if (props.isPathValue) {
-      const values = Array.isArray(val) ? val : val ? [val] : []
-      cascaderValue.value = values.length ? values[values.length - 1] : ''
-      fieldValue.value = getCascaderText([...values], props.options).join('/')
-    } else {
-      const value = Array.isArray(val) ? val[0] : val
-      cascaderValue.value = value
-      fieldValue.value = getTreeText(value, props.options)
-    }
-  },
-  { immediate: true }
-)
+// 多选:把选中路径数组转成「/」文本
+function computeMultiText(paths) {
+  return paths
+    .map((p) => (Array.isArray(p) ? getPathText(p, normalizedOptions.value) : getTreeText(p, normalizedOptions.value)))
+    .filter(Boolean)
+    .join('、')
+}
+
+// 根据当前值 + 选项重算显示文本(详情/只读模式下直接展示 fieldValue)
+function applyModelValue(val) {
+  if (props.multiple) {
+    const arr = Array.isArray(val) ? val : val ? [val] : []
+    // 兼容旧格式:纯叶子值自动补成完整路径
+    selectedValues.value = arr.map((item) =>
+      Array.isArray(item) ? item : findPath(item, normalizedOptions.value) || [item]
+    )
+    fieldValue.value = computeMultiText(selectedValues.value)
+  } else if (props.isPathValue) {
+    const values = Array.isArray(val) ? val : val ? [val] : []
+    cascaderValue.value = values.length ? values[values.length - 1] : ''
+    fieldValue.value = getCascaderText([...values], normalizedOptions.value).join('/')
+  } else {
+    const value = Array.isArray(val) ? val[0] : val
+    cascaderValue.value = value
+    fieldValue.value = getTreeText(value, normalizedOptions.value)
+  }
+}
+
+// 值变化时重算显示文本
+watch(() => props.modelValue, (val) => applyModelValue(val), { immediate: true })
+
+// 选项(部门树)通常异步、晚于值到达:值先到时文本算不出来,
+// 选项就绪后必须重算,否则详情/只读模式文本为空
+watch(() => props.options, () => applyModelValue(props.modelValue), { deep: true })
 
 function onFinish({ selectedOptions }) {
   if (props.isPathValue) {
@@ -167,10 +188,7 @@ function onFinish({ selectedOptions }) {
 function onMultiChange(val) {
   emit('update:modelValue', val)
   selectedValues.value = val
-  fieldValue.value = val
-    .map((p) => (Array.isArray(p) ? getPathText(p, props.options) : getTreeText(p, props.options)))
-    .filter(Boolean)
-    .join('、')
+  fieldValue.value = computeMultiText(val)
 }
 
 function onShowPicker() {

Некоторые файлы не были показаны из-за большого количества измененных файлов