diff --git a/web/main.js b/web/main.js index 2f759bd..a7a5324 100644 --- a/web/main.js +++ b/web/main.js @@ -134,19 +134,29 @@ const app = createApp({ */ const setTreeChecked = (kind, values) => { const tree = kind === 'create' ? createFieldsTree.value : editFieldsTree.value; - if (!tree || !values || !Array.isArray(values)) return; + if (!tree || !values || !Array.isArray(values)) { + console.log(`[设置树勾选] 跳过: kind=${kind}, tree存在=${!!tree}, values类型=${Array.isArray(values) ? 'array' : typeof values}`); + return; + } const treeData = kind === 'create' ? fieldTreeData.value : editFieldTreeData.value; + console.log(`[设置树勾选] kind=${kind}, values数量=${values.length}, 树数据存在=${!!treeData}`); + const keys = TreeUtils.pathsToNodeKeys(values, treeData); + console.log(`[设置树勾选] 转换后keys数量=${keys.length}`); Vue.nextTick(() => { setTimeout(() => { try { if (keys.length > 0 && tree) { + console.log(`[设置树勾选] 调用 setCheckedKeys,keys数量: ${keys.length}`); tree.setCheckedKeys(keys); + console.log(`[设置树勾选] setCheckedKeys 调用成功`); + } else { + console.warn(`[设置树勾选] 未调用 setCheckedKeys: keys.length=${keys.length}, tree存在=${!!tree}`); } } catch (error) { - console.warn('设置树形选择器选中状态失败:', error); + console.warn('[设置树勾选] 设置树形选择器选中状态失败:', error); } }, CONSTANTS.TREE_RENDER_DELAY); }); diff --git a/web/modules/fields.js b/web/modules/fields.js index 00e76a2..f4dbaef 100644 --- a/web/modules/fields.js +++ b/web/modules/fields.js @@ -91,13 +91,28 @@ class FieldsManager { * 构建树节点 * @param {string} table - 表名 * @param {Array} children - 子节点 + * @param {string} parentPrefix - 父级前缀,用于构建唯一value * @returns {Object} 树节点 */ - buildTreeNode(table, children = []) { + buildTreeNode(table, children = [], parentPrefix = '') { + // 为子表的字段节点添加表名前缀,确保 value 唯一 + const childrenWithPrefix = children.map(child => { + if (child.children) { + // 是子表节点,递归处理 + return child; + } else { + // 是字段节点,添加表名前缀 + return { + value: `${table}.${child.value}`, + label: child.label + }; + } + }); + return { - value: table, + value: parentPrefix ? `${parentPrefix}.${table}` : table, label: this.getTableLabel(table), - children + children: childrenWithPrefix }; } @@ -108,7 +123,8 @@ class FieldsManager { */ buildYmtOrderChildren(orderType) { const orderFields = this.getTableFields('order'); - const children = orderFields.map(f => ({ value: f.value, label: f.label })); + // 使用 table.field 格式作为唯一 value + const children = orderFields.map(f => ({ value: `order.${f.value}`, label: f.label })); // 添加公共子表(所有订单类型都有) children.push(this.buildTreeNode('merchant', this.getTableFields('merchant'))); @@ -135,6 +151,23 @@ class FieldsManager { children.push(this.buildTreeNode('goods_voucher_subject_config', this.getTableFields('goods_voucher_subject_config'))); } + // 调试:检查是否有重复的 value + const valueMap = new Map(); + const checkDuplicates = (nodes, prefix = '') => { + nodes.forEach(node => { + const fullPath = prefix ? `${prefix}/${node.value}` : node.value; + if (valueMap.has(node.value)) { + console.warn(`[树节点重复] 检测到重复的节点value: "${node.value}", 路径: ${fullPath}, 之前出现在: ${valueMap.get(node.value)}`); + } else { + valueMap.set(node.value, fullPath); + } + if (node.children && node.children.length > 0) { + checkDuplicates(node.children, fullPath); + } + }); + }; + checkDuplicates(children, 'order'); + return children; } @@ -145,25 +178,26 @@ class FieldsManager { */ buildMarketingOrderChildren(orderType) { const orderFields = this.getTableFields('order'); - const children = orderFields.map(f => ({ value: f.value, label: f.label })); + // 使用 table.field 格式作为唯一 value + const children = orderFields.map(f => ({ value: `order.${f.value}`, label: f.label })); // 订单详情 children.push(this.buildTreeNode('order_detail', this.getTableFields('order_detail'))); // 构建计划节点(包含 key_batch -> code_batch 嵌套) const planChildren = [ - ...this.getTableFields('plan').map(f => ({ value: f.value, label: f.label })), + ...this.getTableFields('plan').map(f => ({ value: `plan.${f.value}`, label: f.label })), this.buildTreeNode('key_batch', [ - ...this.getTableFields('key_batch').map(f => ({ value: f.value, label: f.label })), + ...this.getTableFields('key_batch').map(f => ({ value: `key_batch.${f.value}`, label: f.label })), this.buildTreeNode('code_batch', this.getTableFields('code_batch')) ]) ]; // 构建立减金节点(包含 voucher -> voucher_batch 嵌套) const voucherChildren = [ - ...this.getTableFields('order_voucher').map(f => ({ value: f.value, label: f.label })), + ...this.getTableFields('order_voucher').map(f => ({ value: `order_voucher.${f.value}`, label: f.label })), this.buildTreeNode('voucher', [ - ...this.getTableFields('voucher').map(f => ({ value: f.value, label: f.label })), + ...this.getTableFields('voucher').map(f => ({ value: `voucher.${f.value}`, label: f.label })), this.buildTreeNode('voucher_batch', this.getTableFields('voucher_batch')) ]) ]; @@ -253,15 +287,24 @@ class FieldsManager { } }; - return fields + const paths = fields .map(toPath) - .filter(path => Array.isArray(path) && path.length >= 2) - .filter(path => { - // 验证字段存在 - const table = path[path.length - 2]; - const field = path[path.length - 1]; - return this.hasField(table, field); - }); + .filter(path => Array.isArray(path) && path.length >= 2); + + // 添加调试日志:验证字段存在性 + const validPaths = paths.filter(path => { + const table = path[path.length - 2]; + const field = path[path.length - 1]; + const exists = this.hasField(table, field); + if (!exists) { + console.warn(`[字段回显] 字段不存在于元数据中: ${table}.${field}, 路径: ${JSON.stringify(path)}`); + } + return exists; + }); + + console.log(`[字段回显] 共 ${fields.length} 个字段, 转换为 ${paths.length} 个路径, 验证通过 ${validPaths.length} 个`); + + return validPaths; } /** @@ -384,7 +427,7 @@ const TreeUtils = { /** * 根据路径数组查找节点 value * @param {Array} nodes - 树节点数组 - * @param {string[]} path - 路径数组 + * @param {string[]} path - 路径数组,如 ['order', 'status'] 或 ['order', 'merchant', 'name'] * @param {number} index - 当前索引 * @returns {string|null} 节点 value */ @@ -392,16 +435,41 @@ const TreeUtils = { if (!nodes || index >= path.length) return null; const target = path[index]; + for (const node of nodes) { - if (node.value === target) { + // 节点value可能是 'order', 'order.status', 'merchant' 等格式 + const nodeTableOrField = node.value.split('.').pop(); // 取最后一部分 + const nodeValue = node.value; + + // 检查是否匹配当前路径段 + const isMatch = nodeValue === target || nodeTableOrField === target || node.value.endsWith(`.${target}`); + + if (isMatch) { if (index === path.length - 1) { + // 到达路径末尾,返回节点value return node.value; } else if (node.children && node.children.length > 0) { + // 继续在子节点中查找 const found = TreeUtils.findNodeByPath(node.children, path, index + 1); if (found) return found; } } } + + // 特殊处理:如果路径是 ['order', 'status'],直接尝试查找 'order.status' + if (index === 0 && path.length === 2) { + const combinedValue = `${path[0]}.${path[1]}`; + for (const node of nodes) { + if (node.value === combinedValue) { + return node.value; + } + if (node.children) { + const found = TreeUtils.findNode(node.children, combinedValue); + if (found) return found.value; + } + } + } + return null; }, @@ -416,9 +484,9 @@ const TreeUtils = { /** * 将选中的 keys 转换为路径数组 - * @param {string[]} checkedKeys - 选中的节点 keys + * @param {string[]} checkedKeys - 选中的节点 keys,格式如 ['order.status', 'merchant.name'] * @param {Array} treeData - 树数据 - * @returns {Array} 路径数组(仅叶子节点) + * @returns {Array} 路径数组(仅叶子节点),格式如 [['order', 'status'], ['order', 'merchant', 'name']] */ checkedKeysToLeafPaths(checkedKeys, treeData) { return checkedKeys @@ -427,8 +495,23 @@ const TreeUtils = { return node && TreeUtils.isLeafNode(node); }) .map(key => { + // key 格式可能是 'order.status' 或 'merchant.name' + // 需要根据树结构找到完整路径 const path = TreeUtils.findNodePath(treeData, key); - return path || [key]; + if (path && path.length >= 2) { + // path 是节点value的数组,需要转换为实际的表/字段路径 + // 例如:['order', 'order.status'] -> ['order', 'status'] + // ['order', 'merchant', 'merchant.name'] -> ['order', 'merchant', 'name'] + return path.map((segment, index) => { + if (segment.includes('.')) { + // 是字段节点,取字段名部分 + return segment.split('.').pop(); + } + return segment; + }); + } + // 回退方案:直接使用 key + return key.includes('.') ? key.split('.') : [key]; }) .filter(path => path.length >= 2); }, @@ -440,17 +523,27 @@ const TreeUtils = { * @returns {string[]} 节点 keys */ pathsToNodeKeys(paths, treeData) { - return paths.map(path => { + const keys = paths.map(path => { if (Array.isArray(path)) { const nodeValue = TreeUtils.findNodeByPath(treeData, path); - if (nodeValue) return nodeValue; - // 找不到时使用路径最后一部分 - return path[path.length - 1]; + if (nodeValue) { + return nodeValue; + } else { + // 找不到时使用路径最后一部分 + const fallbackKey = path[path.length - 1]; + console.warn(`[树节点转换] 路径未找到对应节点: ${JSON.stringify(path)}, 使用回退key: ${fallbackKey}`); + return fallbackKey; + } } else if (typeof path === 'string') { return path; } return null; }).filter(Boolean); + + console.log(`[树节点转换] 共转换 ${paths.length} 个路径为 ${keys.length} 个节点key`); + console.log(`[树节点转换] 节点keys:`, keys); + + return keys; } };