sen
2026-02-01 93f8c736fd50a80a72d633e888e2d65904bcd7fc
ui/admin-ui3/src/views/cwgl/voucherSubjectSetting/index.vue
@@ -53,6 +53,7 @@
  form: <VoucherSubjectSettingI>{},
  queryParams: <VoucherSubjectSettingI & PageQueryInterface>{
    type: "0",
    accountingItemsContains: [], // 必须初始化为数组
  },
  page: <PagesInterface>{
    pageSize: 10,
@@ -106,62 +107,50 @@
      ],
    },
    // parentSubjectName: {
    //   label: '上级科目名称',
    //   prop: 'parentSubjectCode',
    //   type: 'cascader',      // 级联选择器
    //   dataType: 'string',
    //   // dicUrl: '/api/cwgl/subject/tree',
    //   placeholder: '请选择上级科目名称',
    //   // --- 控制显示逻辑 ---
    //   hide: true,            // 在表格列中隐藏
    //   search: false,         // 在搜索栏中隐藏
    //   display: true,         // 在新增/修改弹窗中显示(默认为true)
    //   // --------------------
    //   filterable: true,      // 开启搜索过滤
    //   checkStrictly: true,   // 允许选择任意一级(可选父级)
    //   emitPath: false,       // 提交时只保留最后一级的值
    //   props: {
    //     label: 'name',
    //     value: 'code',
    //     children: 'children'
    //   },
    //   label: '上级科目名称2',
    //   minWidth: 150,
    //   // rules: [
    //   //   {
    //   //     required: true,
    //   //     message: "上级科目名称不能为空", trigger: "blur"
    //   //   }
    //   // ],
    //   /*  */
    //   search: true,
    //   rules: [
    //     {
    //       required: true,
    //       message: "科目名称不能为空", trigger: "blur"
    //     }
    //   ],
    // },
    parentSubjectName: {
    parentId: {
      label: '上级科目名称',
      minWidth: 150,
      search: true,
      prop: 'parentId',
      type: 'tree',
      hide: true,
      dicData: [],
      props: {
        label: 'fullName', // 关键点:绑定我们预处理好的全路径字段
        value: 'id'
      },
      addDisabled: true,
      editDisabled: true,
      rules: [
        {
          required: true,
          message: "科目名称不能为空", trigger: "blur"
        }
      ],
        { required: true, message: "上级科目不能为空", trigger: "change" }
      ]
    },
    parentSubjectCode: {
      label: '上级科目代码',
      minWidth: 150,
      disabled: true, // 设置为禁用,仅供查看
      // 如果希望在表格也显示,这里不要写 hide: true
    },
    parentSubjectCode: {
      label: '上级科目代码',
      minWidth: 150,
      search: true,
      rules: [
        {
          required: true,
          message: "科目名称不能为空", trigger: "blur"
        }
      ],
      // rules: [
      //   {
      //     required: true,
      //     message: "科目名称不能为空", trigger: "blur"
      //   }
      // ],
    },
    // parentSubjectCode: {
    //   label: '上级科目代码',
@@ -256,7 +245,6 @@
      minWidth: 150,
      type: 'select',
      multiple: true,
      dataType: 'string',
      dicUrl: '/system/dict/data/type/sys_accounting_item_name',
      placeholder: '请选择核算项目(可多选)',
      props: {
@@ -390,7 +378,7 @@
  }
})
// sys_accounting_type
// listVoucherSubjectSetting
const { tableData, pageF, rowSave, rowUpdate, rowDel, beforeOpen, searchChange,
  searchReset, selectionChange, onLoad, currentChange, sizeChange, handleDelete, handleExport, handleUpdate, refreshChange } = usePagePlus({
    form: form,
@@ -400,6 +388,27 @@
    page: page.value,
    getListApi: listVoucherSubjectSetting,
    getDetailApi: getVoucherSubjectSetting,
    // 【关键修复点】:拦截详情接口,在数据进入 form 之前完成格式化
    getDetailApi: (id: any) => {
      return getVoucherSubjectSetting(id).then((res: any) => {
        if (res.code === 200 && res.data) {
          // 1. 处理 accountingItems 数字转数组
          if (typeof res.data.accountingItems === 'number') {
            res.data.accountingItems = decomposeAccountingItems(res.data.accountingItems);
          } else if (!res.data.accountingItems) {
            res.data.accountingItems = [];
          }
          // 2. 处理 accountingItemsContains 确保是数组
          if (!Array.isArray(res.data.accountingItemsContains)) {
            res.data.accountingItemsContains = [];
          }
        }
        return res;
      });
    },
    exportApi: exportVoucherSubjectSetting,
    deleteApi: delVoucherSubjectSetting,
    addApi: addVoucherSubjectSetting,
@@ -440,54 +449,96 @@
      queryParams.value = newParams;
      return newParams;
    },
   handleBeforeOpenFunc: (type: string) => {
  if (!option.value?.column) return;
  const nameCol = option.value.column.parentSubjectName;
  const codeCol = option.value.column.parentSubjectCode;
      const parentIdCol = option.value.column.parentId;
  // --- 1. 新增逻辑修改 ---
  if (type === 'add') {
    if (isFromRow.value) {
      // 行内“新增子项”点击
      nameCol.disabled = true;
      codeCol.disabled = true;
      option.value.saveBtnText = '新增';
      // --- 1. 定义名称递归处理器 ---
      const formatTreeData = (list: any[], parentName = '') => {
        return list.map(item => {
          // 拼接全路径:父级名称 > 当前名称
          const currentFullName = parentName ? `${parentName} > ${item.subjectName}` : item.subjectName;
          const newItem = {
            ...item,
            fullName: currentFullName
          };
          // 如果有子节点,继续递归
          if (newItem.children && newItem.children.length > 0) {
            newItem.children = formatTreeData(newItem.children, currentFullName);
          }
          return newItem;
        });
      };
      
      // 赋值当前页签的账套(虽然行内新增通常会带入父级账套,但这里显式同步一次)
      form.value.accountSet = activeAccountSet.value;
      // --- 2. 加载并处理字典数据 ---
      listVoucherSubjectSetting({ type: activeAccountSet.value }).then(res => {
        // 将扁平数据转为树结构 (proxy.handleTree 是 Ruoyi 常用工具)
        const treeData = proxy.handleTree(res.rows, "id", "parentId");
        // 执行全路径拼接
        const fullPathTree = formatTreeData(treeData);
        // 组合最终字典,加入“顶级”选项
        const fullDic = [
          {
            id: 0,
            subjectName: '顶级科目',
            fullName: '顶级科目',
            children: fullPathTree
          }
        ];
        if (parentIdCol) parentIdCol.dicData = fullDic;
        // 异步回调中再次确保代码字段显示
        if (String(form.value.parentId) === "0" || !form.value.parentId) {
          form.value.parentSubjectCode = "顶级科目代码";
        }
      });
      // --- 3. 处理不同模式下的显示逻辑 ---
      if (type !== 'add') {
        // 【修改/查看】
        if (String(form.value.parentId) === "0" || !form.value.parentId) {
          form.value.parentSubjectCode = "顶级科目代码";
        }
        if (parentIdCol) { parentIdCol.display = true; parentIdCol.disabled = true; }
        if (codeCol) { codeCol.display = true; codeCol.disabled = true; }
    } else {
      // 顶部“新增”按钮点击
      nameCol.disabled = false;
      codeCol.disabled = false;
      option.value.saveBtnText = '保 存';
        // 【新增】
        if (isFromRow.value) {
          // 行内新增子项
          if (parentIdCol) { parentIdCol.display = true; parentIdCol.disabled = true; }
          if (codeCol) { codeCol.display = true; codeCol.disabled = true; }
        } else {
          // 顶部新增 (默认是顶级科目)
          if (parentIdCol) parentIdCol.display = false;
          if (codeCol) codeCol.display = false;
      
      // 【关键修复】先清空可能残留的旧数据(如 ID、科目代码等)
      Object.keys(form.value).forEach(key => delete form.value[key]);
      // 【核心要求】将页签的值赋值给表单账套字段
      form.value.accountSet = activeAccountSet.value;
      form.value.type = activeAccountSet.value;
      // 初始化其他必要字段
      form.value.accountingItems = [];
      form.value.enabled = "1"; // 默认启用
          const currentSet = activeAccountSet.value;
          Object.assign(form.value, {
            id: undefined,
            parentId: 0,
            parentSubjectCode: "无",
            accountSet: currentSet,
            type: currentSet,
            accountingItems: [],
            enabled: "1"
          });
    }
  } 
  // --- 2. 修改/查看逻辑(保持原样) ---
  else if (type === 'edit' || type === 'view') {
    nameCol.disabled = true;
    codeCol.disabled = true;
    option.value.updateBtnText = '修 改';
    if (typeof form.value.accountingItems === 'number') {
      form.value.accountingItems = decomposeAccountingItems(form.value.accountingItems);
    } else if (!form.value.accountingItems) {
      form.value.accountingItems = [];
      // --- 4. 格式化多选字段 ---
      const fieldsToFix = ['accountingItems', 'accountingItemsContains'];
      fieldsToFix.forEach(field => {
        const val = form.value[field];
        if (typeof val === 'number') {
          form.value[field] = decomposeAccountingItems(val);
        } else if (!Array.isArray(val)) {
          form.value[field] = [];
    }
  }
      });
  nextTick(() => {
    isFromRow.value = false;
@@ -509,6 +560,9 @@
    rowUpdateBegin: (row: any, done: any, loading: any) => {
      processAccountingItems(row);
      delete row.accountingItemsContains;
      if (row.parentSubjectCode == "顶级科目代码") {
        row.parentSubjectCode = row.subjectCode;
      }
      done(row); // 同理
    },
  })