优化混炼示方,新增种类配置
This commit is contained in:
@@ -1,16 +1,78 @@
|
||||
import { ref } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { getChildListBatch, loadTreeData } from './category.api';
|
||||
|
||||
/** MES 物料分类 - 原辅材料编码 */
|
||||
/** MES 物料分类根编码 */
|
||||
export const MATERIAL_ROOT_CODE = 'XSLMES_MATERIAL';
|
||||
|
||||
/** MES 物料分类 - 原辅材料编码(兼容旧逻辑) */
|
||||
export const MATERIAL_RAW_AUX_CODE = 'XSLMES_MATERIAL_RAW_AUX';
|
||||
|
||||
/** 原辅材料分类节点 ID(运行时加载) */
|
||||
/** 原辅材料分类节点 ID(运行时加载,兼容旧逻辑) */
|
||||
export const materialRawAuxCategoryId = ref('');
|
||||
|
||||
/** 是否为原辅材料的直接子类 */
|
||||
/** MES 物料分类根节点 ID(运行时加载) */
|
||||
export const materialRootCategoryId = ref('');
|
||||
|
||||
/** MES 物料大类节点 ID 集合(运行时加载) */
|
||||
export const materialMajorCategoryIds = ref<Set<string>>(new Set());
|
||||
|
||||
let materialCategoryContextLoading: Promise<void> | null = null;
|
||||
|
||||
/** 加载 MES 物料分类上下文(根节点 + 大类 ID) */
|
||||
export async function ensureMaterialCategoryContext(force = false) {
|
||||
if (!force && materialRootCategoryId.value && materialMajorCategoryIds.value.size > 0) {
|
||||
return;
|
||||
}
|
||||
if (materialCategoryContextLoading) {
|
||||
await materialCategoryContextLoading;
|
||||
return;
|
||||
}
|
||||
materialCategoryContextLoading = (async () => {
|
||||
const rootRes = await defHttp.get(
|
||||
{ url: '/sys/category/loadOne', params: { field: 'code', val: MATERIAL_ROOT_CODE } },
|
||||
{ isTransformResponse: false },
|
||||
);
|
||||
if (rootRes?.success && rootRes?.result?.id) {
|
||||
materialRootCategoryId.value = String(rootRes.result.id);
|
||||
}
|
||||
const auxRes = await defHttp.get(
|
||||
{ url: '/sys/category/loadOne', params: { field: 'code', val: MATERIAL_RAW_AUX_CODE } },
|
||||
{ isTransformResponse: false },
|
||||
);
|
||||
if (auxRes?.success && auxRes?.result?.id) {
|
||||
materialRawAuxCategoryId.value = String(auxRes.result.id);
|
||||
}
|
||||
const majors = await loadTreeData({ async: false, pcode: MATERIAL_ROOT_CODE });
|
||||
const majorIds = new Set<string>();
|
||||
(Array.isArray(majors) ? majors : []).forEach((node) => {
|
||||
const nodeKey = node?.key ?? node?.value ?? node?.id;
|
||||
if (nodeKey != null) {
|
||||
majorIds.add(String(nodeKey));
|
||||
}
|
||||
});
|
||||
materialMajorCategoryIds.value = majorIds;
|
||||
})();
|
||||
try {
|
||||
await materialCategoryContextLoading;
|
||||
} finally {
|
||||
materialCategoryContextLoading = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 是否为原辅材料的直接子类(兼容旧逻辑) */
|
||||
export function isMaterialRawAuxSubCategory(pid?: string) {
|
||||
return !!materialRawAuxCategoryId.value && pid === materialRawAuxCategoryId.value;
|
||||
}
|
||||
|
||||
/** 是否为 MES 物料小类(父节点为物料大类) */
|
||||
export function isMaterialMinorCategory(pid?: string) {
|
||||
if (!pid) {
|
||||
return false;
|
||||
}
|
||||
return materialMajorCategoryIds.value.has(String(pid));
|
||||
}
|
||||
|
||||
/** 表单 Checkbox 布尔值 -> 数据库存储值 */
|
||||
export function toIsRubberFlag(value: unknown) {
|
||||
return value === true || value === '1' ? '1' : '0';
|
||||
@@ -20,3 +82,206 @@ export function toIsRubberFlag(value: unknown) {
|
||||
export function fromIsRubberFlag(value: unknown) {
|
||||
return value === '1' || value === 1 || value === true;
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】统一加载MES物料分类树(大类+小类)-----------
|
||||
export interface MesMaterialCategoryMinorItem {
|
||||
id: string;
|
||||
name: string;
|
||||
majorId: string;
|
||||
majorName: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface MesMaterialCategoryMajorItem {
|
||||
id: string;
|
||||
name: string;
|
||||
minors: MesMaterialCategoryMinorItem[];
|
||||
}
|
||||
|
||||
export interface MesMaterialCategoryTreeLoadResult {
|
||||
majors: MesMaterialCategoryMajorItem[];
|
||||
minors: MesMaterialCategoryMinorItem[];
|
||||
treeNodes: Recordable[];
|
||||
}
|
||||
|
||||
function normalizeCategoryNodeKey(node: Recordable): string {
|
||||
const key = node?.key ?? node?.value ?? node?.id;
|
||||
return key != null && String(key) !== '' ? String(key) : '';
|
||||
}
|
||||
|
||||
function normalizeCategoryNodeTitle(node: Recordable): string {
|
||||
return String(node?.title ?? node?.name ?? '');
|
||||
}
|
||||
|
||||
function normalizeTreeSelectNodes(nodes: unknown): Recordable[] {
|
||||
if (Array.isArray(nodes)) {
|
||||
return nodes as Recordable[];
|
||||
}
|
||||
if (nodes && typeof nodes === 'object') {
|
||||
const payload = nodes as Recordable;
|
||||
if (Array.isArray(payload.result)) {
|
||||
return payload.result;
|
||||
}
|
||||
if (Array.isArray(payload.records)) {
|
||||
return payload.records;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/** 加载 MES 物料分类树:根下物料大类 + 各物料小类(供密炼物料/混炼示方选料复用) */
|
||||
export async function loadMesMaterialCategoryTreeData(): Promise<MesMaterialCategoryTreeLoadResult> {
|
||||
// 优先 loadTreeRoot(与密炼物料列表页一致,已验证可用)
|
||||
try {
|
||||
const treeRes = await loadTreeData({ async: false, pcode: MATERIAL_ROOT_CODE });
|
||||
const treeResult = buildMesMaterialCategoryTreeFromTreeSelect(normalizeTreeSelectNodes(treeRes));
|
||||
if (treeResult.minors.length) {
|
||||
if (!materialRootCategoryId.value) {
|
||||
await ensureMaterialCategoryContext();
|
||||
}
|
||||
return treeResult;
|
||||
}
|
||||
} catch {
|
||||
// 继续走 batch 兜底
|
||||
}
|
||||
|
||||
let rootId = materialRootCategoryId.value;
|
||||
if (!rootId) {
|
||||
try {
|
||||
const root = await defHttp.get<Recordable>({
|
||||
url: '/sys/category/loadOne',
|
||||
params: { field: 'code', val: MATERIAL_ROOT_CODE },
|
||||
});
|
||||
if (root?.id) {
|
||||
rootId = String(root.id);
|
||||
materialRootCategoryId.value = rootId;
|
||||
}
|
||||
} catch {
|
||||
rootId = '';
|
||||
}
|
||||
}
|
||||
if (!rootId) {
|
||||
return { majors: [], minors: [], treeNodes: [] };
|
||||
}
|
||||
|
||||
let majorRecords: Recordable[] = [];
|
||||
let minorRecords: Recordable[] = [];
|
||||
try {
|
||||
const majorBatch = await getChildListBatch({ parentIds: rootId });
|
||||
if (majorBatch?.success === false) {
|
||||
return { majors: [], minors: [], treeNodes: [] };
|
||||
}
|
||||
majorRecords = (majorBatch?.result?.records || majorBatch?.records || []) as Recordable[];
|
||||
if (majorRecords.length) {
|
||||
const majorIds = majorRecords.map((item) => String(item.id)).filter(Boolean).join(',');
|
||||
if (majorIds) {
|
||||
const minorBatch = await getChildListBatch({ parentIds: majorIds });
|
||||
if (minorBatch?.success !== false) {
|
||||
minorRecords = (minorBatch?.result?.records || minorBatch?.records || []) as Recordable[];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return { majors: [], minors: [], treeNodes: [] };
|
||||
}
|
||||
|
||||
const result = buildMesMaterialCategoryTreeFromRecords(majorRecords, minorRecords);
|
||||
materialMajorCategoryIds.value = new Set(result.majors.map((item) => item.id));
|
||||
return result;
|
||||
}
|
||||
|
||||
function buildMesMaterialCategoryTreeFromRecords(majorRecords: Recordable[], minorRecords: Recordable[]) {
|
||||
const majorMap = new Map<string, { id: string; name: string; minors: MesMaterialCategoryMinorItem[] }>();
|
||||
majorRecords.forEach((record) => {
|
||||
const majorId = normalizeCategoryNodeKey(record);
|
||||
if (!majorId) {
|
||||
return;
|
||||
}
|
||||
majorMap.set(majorId, {
|
||||
id: majorId,
|
||||
name: normalizeCategoryNodeTitle(record),
|
||||
minors: [],
|
||||
});
|
||||
});
|
||||
|
||||
minorRecords.forEach((record) => {
|
||||
const majorId = record?.pid != null ? String(record.pid) : '';
|
||||
const minorId = normalizeCategoryNodeKey(record);
|
||||
const major = majorMap.get(majorId);
|
||||
if (!major || !minorId) {
|
||||
return;
|
||||
}
|
||||
major.minors.push({
|
||||
id: minorId,
|
||||
name: normalizeCategoryNodeTitle(record),
|
||||
majorId: major.id,
|
||||
majorName: major.name,
|
||||
label: major.name && normalizeCategoryNodeTitle(record)
|
||||
? `${major.name} / ${normalizeCategoryNodeTitle(record)}`
|
||||
: normalizeCategoryNodeTitle(record) || major.name,
|
||||
});
|
||||
});
|
||||
|
||||
const majors: MesMaterialCategoryMajorItem[] = [];
|
||||
const minors: MesMaterialCategoryMinorItem[] = [];
|
||||
const treeNodes: Recordable[] = [];
|
||||
|
||||
majorMap.forEach((major) => {
|
||||
if (!major.minors.length) {
|
||||
return;
|
||||
}
|
||||
majors.push({ id: major.id, name: major.name, minors: major.minors });
|
||||
minors.push(...major.minors);
|
||||
treeNodes.push({
|
||||
key: major.id,
|
||||
title: major.name,
|
||||
children: major.minors.map((minor) => ({ key: minor.id, title: minor.name })),
|
||||
});
|
||||
});
|
||||
|
||||
return { majors, minors, treeNodes };
|
||||
}
|
||||
|
||||
function buildMesMaterialCategoryTreeFromTreeSelect(majorRaw: Recordable[]) {
|
||||
const majors: MesMaterialCategoryMajorItem[] = [];
|
||||
const minors: MesMaterialCategoryMinorItem[] = [];
|
||||
const treeNodes: Recordable[] = [];
|
||||
|
||||
majorRaw.forEach((major) => {
|
||||
const majorId = normalizeCategoryNodeKey(major);
|
||||
const majorName = normalizeCategoryNodeTitle(major);
|
||||
if (!majorId) {
|
||||
return;
|
||||
}
|
||||
const majorMinors: MesMaterialCategoryMinorItem[] = [];
|
||||
(Array.isArray(major.children) ? major.children : []).forEach((child) => {
|
||||
const minorId = normalizeCategoryNodeKey(child);
|
||||
const minorName = normalizeCategoryNodeTitle(child);
|
||||
if (!minorId) {
|
||||
return;
|
||||
}
|
||||
const item: MesMaterialCategoryMinorItem = {
|
||||
id: minorId,
|
||||
name: minorName,
|
||||
majorId,
|
||||
majorName,
|
||||
label: majorName && minorName ? `${majorName} / ${minorName}` : minorName || majorName,
|
||||
};
|
||||
majorMinors.push(item);
|
||||
minors.push(item);
|
||||
});
|
||||
if (!majorMinors.length) {
|
||||
return;
|
||||
}
|
||||
majors.push({ id: majorId, name: majorName, minors: majorMinors });
|
||||
treeNodes.push({
|
||||
key: majorId,
|
||||
title: majorName,
|
||||
children: majorMinors.map((minor) => ({ key: minor.id, title: minor.name })),
|
||||
});
|
||||
});
|
||||
|
||||
materialMajorCategoryIds.value = new Set(majors.map((item) => item.id));
|
||||
return { majors, minors, treeNodes };
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】统一加载MES物料分类树(大类+小类)-----------
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
import { FormSchema } from '/@/components/Table';
|
||||
import { isMaterialRawAuxSubCategory } from './category.constants';
|
||||
import { isMaterialMinorCategory } from './category.constants';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
@@ -81,6 +81,6 @@ export const formSchema: FormSchema[] = [
|
||||
defaultValue: false,
|
||||
renderComponentContent: '胶料',
|
||||
colProps: { span: 24 },
|
||||
show: ({ values }) => isMaterialRawAuxSubCategory(values.pid),
|
||||
show: ({ values }) => isMaterialMinorCategory(values.pid),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
import {
|
||||
MATERIAL_RAW_AUX_CODE,
|
||||
materialRawAuxCategoryId,
|
||||
isMaterialRawAuxSubCategory,
|
||||
ensureMaterialCategoryContext,
|
||||
isMaterialMinorCategory,
|
||||
toIsRubberFlag,
|
||||
fromIsRubberFlag,
|
||||
} from '../category.constants';
|
||||
@@ -40,7 +41,7 @@
|
||||
|
||||
function normalizeSubmitValues(values: Recordable) {
|
||||
const payload = { ...values };
|
||||
payload.isRubber = isMaterialRawAuxSubCategory(payload.pid) ? toIsRubberFlag(payload.isRubber) : '0';
|
||||
payload.isRubber = isMaterialMinorCategory(payload.pid) ? toIsRubberFlag(payload.isRubber) : '0';
|
||||
return payload;
|
||||
}
|
||||
//表单配置
|
||||
@@ -64,6 +65,7 @@
|
||||
setModalProps({ confirmLoading: false, minHeight: 80 });
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
await ensureMaterialRawAuxCategoryId();
|
||||
await ensureMaterialCategoryContext();
|
||||
// 代码逻辑说明: 分类字典data.record为空报错------------
|
||||
isSubAdd.value = !data?.isUpdate && data.record && data.record.id;
|
||||
if (data?.record) {
|
||||
|
||||
Reference in New Issue
Block a user