Initial commit

This commit is contained in:
汤学会
2026-06-12 16:00:56 +08:00
commit c927886888
337 changed files with 160396 additions and 0 deletions
+169
View File
@@ -0,0 +1,169 @@
const CHINESE_CODE_INITIALS = {
产: "C",
品: "P",
原: "Y",
料: "L",
本: "B",
体: "T",
垃: "L",
圾: "J",
桶: "T",
垫: "D",
电: "D",
脑: "N",
支: "Z",
架: "J",
钢: "G",
板: "B",
卷: "J",
铝: "L",
合: "H",
金: "J",
铁: "T",
铜: "T",
不: "B",
锈: "X",
冷: "L",
热: "R",
轧: "Z",
镀: "D",
锌: "X",
冲: "C",
压: "Y",
件: "J",
片: "P",
管: "G",
棒: "B",
圆: "Y",
方: "F",
型: "X",
材: "C",
外: "W",
壳: "K",
底: "D",
座: "Z",
盖: "G",
盒: "H",
箱: "X",
门: "M",
锁: "S",
扣: "K",
连: "L",
接: "J"
};
function normalizeText(value) {
return String(value || "").trim();
}
export function normalizeCodeToken(value, maxLength = 24) {
const text = normalizeText(value).toUpperCase();
if (!text) {
return "";
}
const chunks = [];
let current = "";
let currentKind = "";
const flushCurrent = () => {
if (current) {
chunks.push(current);
}
current = "";
currentKind = "";
};
for (const char of text.replaceAll("×", "X").replaceAll("*", "X")) {
let kind = "";
let tokenChar = "";
if (/^[A-Z0-9.]$/.test(char)) {
kind = "LATIN";
tokenChar = char;
} else if (/^[\u4e00-\u9fff]$/.test(char)) {
const mapped = CHINESE_CODE_INITIALS[char];
if (mapped) {
kind = "CJK";
tokenChar = mapped;
} else {
kind = "CJK_RAW";
tokenChar = char;
}
} else {
flushCurrent();
continue;
}
if (currentKind && currentKind !== kind) {
flushCurrent();
}
currentKind = kind;
current += tokenChar;
}
flushCurrent();
return chunks.join("-").slice(0, maxLength).replace(/^[.-]+|[.-]+$/g, "");
}
function buildCodePrefix(parts, maxLength = 42) {
const tokens = parts.map((part) => normalizeCodeToken(part)).filter(Boolean);
if (!tokens.length) {
return "";
}
return tokens.join("-").slice(0, maxLength).replace(/^[.-]+|[.-]+$/g, "");
}
export function buildNextProductSpecCode(products = []) {
let maxNo = 0;
for (const product of products || []) {
const code = normalizeText(product?.item_code);
const match = code.match(/^产品需规(\d{5})$/);
if (match) {
maxNo = Math.max(maxNo, Number(match[1]));
}
}
return `产品需规${String(maxNo + 1).padStart(5, "0")}`;
}
export function buildProductCodePreview(form, savedCode = "", nextCode = "") {
if (normalizeText(savedCode)) {
return savedCode;
}
return normalizeText(nextCode) || "产品需规00001";
}
export function buildNextMaterialCode(materials = []) {
let maxNo = 0;
for (const material of materials || []) {
const code = normalizeText(material?.item_code);
const match = code.match(/^原材料(\d{5})$/);
if (match) {
maxNo = Math.max(maxNo, Number(match[1]));
}
}
return `原材料${String(maxNo + 1).padStart(5, "0")}`;
}
export function buildMaterialCodePreview(form, savedCode = "", nextCode = "") {
if (normalizeText(savedCode)) {
return savedCode;
}
return normalizeText(nextCode) || "原材料00001";
}
export function buildBomCodePreview(productCode, savedCode = "") {
if (normalizeText(savedCode)) {
return savedCode;
}
const prefix = buildCodePrefix(["BOM", productCode || "产品编码"], 50) || "BOM-产品编码";
return prefix;
}
export function buildRouteCodePreview(productCode, savedCode = "") {
if (normalizeText(savedCode)) {
return savedCode;
}
const prefix = buildCodePrefix(["ROUTE", productCode || "产品编码"], 50) || "ROUTE-产品编码";
return prefix;
}