yuan
2 天以前 bb91952d1f1f59c4719d77eaf56e47eafa10126a
feat: 添加产品树过滤功能,支持新增和编辑场景下的产品类别选择
已修改2个文件
已添加1个文件
78 ■■■■■ 文件已修改
src/utils/productTree.js 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionPlan/productionPlan/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/productTree.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
/**
 * äº§å“å¤§ç±»æ ‘(/basic/product/list)工具
 *
 * è¯´æ˜Žï¼šäº§å“æ ‘一级节点是「成品 / åŠæˆå“ / åŽŸææ–™ã€è¿™ç±»æ ¹èŠ‚ç‚¹ï¼Œå…·ä½“äº§å“å¤§ç±»æŒ‚åœ¨æ ¹èŠ‚ç‚¹ä¸‹ã€‚
 * éƒ¨åˆ†ä¸šåŠ¡æ–°å¢žæ—¶åªå…è®¸é€‰æ‹©æŸä¸€ç±»äº§å“ï¼ˆå¦‚é‡‡è´­å°è´¦åªé€‰åŽŸææ–™ã€ç”Ÿäº§è®¡åˆ’åªé€‰æˆå“ï¼‰ï¼Œç¼–è¾‘æ—¶è¦ä¿æŒå®Œæ•´æ ‘ã€‚
 */
// æ ¹èŠ‚ç‚¹åç§°ï¼Œå…¼å®¹ã€ŒåŽŸææ–™ã€ã€ŒåŽŸæ–™ã€ä¸¤ç§å»ºæ³•
const RAW_MATERIAL_ROOT_NAMES = ["原材料", "原料"];
const FINISHED_PRODUCT_ROOT_NAMES = ["成品"];
/**
 * å–节点名称(树接口同时返回 label ä¸Ž productName)
 * @param {object} node æ ‘节点
 * @returns {string} èŠ‚ç‚¹åç§°
 */
const getNodeLabel = node =>
  String(node?.label ?? node?.productName ?? "").trim();
/**
 * åˆ¤æ–­èŠ‚ç‚¹åç§°æ˜¯å¦å‘½ä¸­æŒ‡å®šçš„æ ¹èŠ‚ç‚¹åç§°ï¼ˆå®Œå…¨ç›¸åŒæˆ–ä»¥è¯¥åç§°å¼€å¤´ï¼‰
 * @param {object} node æ ‘节点
 * @param {Array<string>} rootNames å…è®¸çš„æ ¹èŠ‚ç‚¹åç§°
 * @returns {boolean} æ˜¯å¦å‘½ä¸­
 */
const isRootNodeNamed = (node, rootNames) => {
  const label = getNodeLabel(node);
  if (!label) {
    return false;
  }
  return rootNames.some(name => label === name || label.startsWith(name));
};
/**
 * åªä¿ç•™æŒ‡å®šåç§°æ ¹èŠ‚ç‚¹ä¸‹çš„äº§å“æ ‘ï¼Œç”¨äºŽæ–°å¢žåœºæ™¯
 * @param {Array} tree æŽ¥å£è¿”回的产品树
 * @param {Array<string>} rootNames å…è®¸çš„æ ¹èŠ‚ç‚¹åç§°
 * @returns {Array} è¿‡æ»¤åŽçš„æ ‘(不改动原数据,编辑场景直接传原树即可)
 */
export const filterProductTreeByRoot = (tree, rootNames = []) =>
  (Array.isArray(tree) ? tree : []).filter(node =>
    isRootNodeNamed(node, rootNames)
  );
/**
 * åªä¿ç•™ã€ŒåŽŸææ–™ã€æ ¹èŠ‚ç‚¹ä¸‹çš„äº§å“æ ‘
 * @param {Array} tree æŽ¥å£è¿”回的产品树
 * @returns {Array} è¿‡æ»¤åŽçš„æ ‘
 */
export const filterRawMaterialTree = tree =>
  filterProductTreeByRoot(tree, RAW_MATERIAL_ROOT_NAMES);
/**
 * åªä¿ç•™ã€Œæˆå“ã€æ ¹èŠ‚ç‚¹ä¸‹çš„äº§å“æ ‘
 * @param {Array} tree æŽ¥å£è¿”回的产品树
 * @returns {Array} è¿‡æ»¤åŽçš„æ ‘
 */
export const filterFinishedProductTree = tree =>
  filterProductTreeByRoot(tree, FINISHED_PRODUCT_ROOT_NAMES);
src/views/procurementManagement/procurementLedger/index.vue
@@ -547,7 +547,7 @@
                              filterable
                              check-strictly
                              @change="getModels"
                              :data="productOptions"
                              :data="productFormOptions"
                              :render-after-expand="false"
                              style="width: 100%" />
            </el-form-item>
@@ -705,6 +705,7 @@
    onMounted,
    reactive,
    toRefs,
    computed,
    getCurrentInstance,
    nextTick,
  } from "vue";
@@ -762,6 +763,7 @@
  import dayjs from "dayjs";
  import FileUpload from "@/components/AttachmentUpload/file/index.vue";
  import { roundHalfUp, trimZeros } from "@/utils/formatNumber.js";
  import { filterRawMaterialTree } from "@/utils/productTree.js";
  const userStore = useUserStore();
@@ -959,6 +961,12 @@
  // äº§å“è¡¨å•弹框数据
  const productFormVisible = ref(false);
  const productOperationType = ref("");
  // æ–°å¢žäº§å“æ—¶äº§å“å¤§ç±»åªå±•示「原材料」,编辑时保持完整产品树
  const productFormOptions = computed(() =>
    productOperationType.value === "add"
      ? filterRawMaterialTree(productOptions.value)
      : productOptions.value
  );
  const productOperationIndex = ref("");
  const currentId = ref("");
  const productFormData = reactive({
src/views/productionPlan/productionPlan/index.vue
@@ -186,7 +186,7 @@
          <el-tree-select v-model="form.productId"
                          placeholder="请选择"
                          clearable
                          :data="productOptions"
                          :data="productTreeOptions"
                          :render-after-expand="false"
                          filterable
                          @change="handleProductChange"
@@ -283,6 +283,7 @@
    exportProductionPlan,
  } from "@/api/productionPlan/productionPlan.js";
  import { productTreeList, modelListPage } from "@/api/basicData/product.js";
  import { filterFinishedProductTree } from "@/utils/productTree.js";
  import PIMTable from "./components/PIMTable.vue";
  import ImportDialog from "@/components/Dialog/ImportDialog.vue";
@@ -510,6 +511,12 @@
  const dialogVisible = ref(false);
  const operationType = ref("add"); // add | edit
  const productOptions = ref([]);
  // æ–°å¢žç”Ÿäº§è®¡åˆ’时产品名称只展示「成品」,编辑时保持完整产品树
  const productTreeOptions = computed(() =>
    operationType.value === "add"
      ? filterFinishedProductTree(productOptions.value)
      : productOptions.value
  );
  const specificationOptions = ref([]);
  const queryRef = ref(null);
  const formRef = ref(null);