import InventoryOperationApi from "@/api/product/inventoryOperation";
|
import TwistApi from "@/api/product/twist";
|
import { MOCK_BOBBIN, MOCK_ENABLED, MOCK_SOURCE_STOCK } from "./mock";
|
|
/** 操作类型 */
|
export const OP_SPLIT = "SPLIT";
|
export const OP_STRAND_REWIND = "STRAND_REWIND";
|
|
/** 物料类型:源盘与目标盘都走「成品」(与 PC 端成品拆盘一致) */
|
export const MATERIAL_TYPE_FG = "成品";
|
|
/** 上一步扫码领用到的源盘,通过本地缓存传给办理页 */
|
export const SOURCE_STORAGE_KEY = "inventoryOperationSourceReel";
|
|
/** 可选的两种操作 */
|
export const OPERATION_TYPES = [
|
{
|
value: OP_SPLIT,
|
label: "成品拆盘",
|
desc: "一个源盘拆成多个子盘",
|
icon: "fork",
|
},
|
{
|
value: OP_STRAND_REWIND,
|
label: "绞线复绕",
|
desc: "整盘复绕,可沿用原盘号或生成新盘号",
|
icon: "rotate",
|
},
|
];
|
|
/** 扫码内容里可能表示「盘号」的字段 */
|
export const REEL_CODE_KEYS = [
|
"batchCode",
|
"dishNo",
|
"monofilamentNumber",
|
"systemNo",
|
"code",
|
"盘号",
|
"批次号",
|
];
|
|
/** 扫码内容里可能表示「盘具编号」的字段 */
|
export const DISH_CODE_KEYS = [
|
"weighingCode",
|
"weighingNo",
|
"dishCode",
|
"receiveDishNo",
|
"code",
|
"称重编号",
|
"盘具编号",
|
];
|
|
/** 解析扫码内容:兼容 JSON 与纯文本 */
|
export function parseScanCode(payload: any) {
|
const raw = payload?.code ?? payload;
|
if (raw === undefined || raw === null) return null;
|
if (typeof raw === "object") return raw;
|
const text = String(raw).trim();
|
if (!text) return null;
|
if (text.startsWith("{")) {
|
try {
|
return JSON.parse(text);
|
} catch {
|
// JSON 解析失败时按纯文本编号处理
|
}
|
}
|
return { code: text };
|
}
|
|
/** 从解析后的对象里按候选字段取编号 */
|
export function pickValue(data: any, keys: string[]) {
|
for (const key of keys) {
|
const value = data?.[key];
|
if (value !== undefined && value !== null && String(value).trim() !== "") {
|
return String(value).trim();
|
}
|
}
|
return "";
|
}
|
|
/** 统一从分页/数组响应里取列表 */
|
function pickRecords(data: any): any[] {
|
const pageData: any = data ?? {};
|
return (
|
pageData?.records ??
|
pageData?.list ??
|
pageData?.rows ??
|
(Array.isArray(pageData) ? pageData : [])
|
);
|
}
|
|
/**
|
* 源盘(成品库存)查询:真实接口优先;接口未联调/查不到时回落模拟数据。
|
* 模拟模式下盘号取扫码/输入的值,方便连续测试。
|
* @returns record 为 null 表示确实查不到
|
*/
|
export async function findSourceStock(code: string) {
|
try {
|
const { data } = await InventoryOperationApi.searchStock({
|
keyword: code,
|
materialType: MATERIAL_TYPE_FG,
|
ncReturnFlag: "Y",
|
});
|
const records = pickRecords(data);
|
const exact = (records || []).find((row: any) => String(row?.batchCode ?? "").trim() === code);
|
const record = exact ?? (records?.length === 1 ? records[0] : null);
|
if (record) return { record, mocked: false };
|
} catch {
|
// 接口未就绪,走下面的模拟数据
|
}
|
if (!MOCK_ENABLED) return { record: null, mocked: false };
|
return { record: { ...MOCK_SOURCE_STOCK, batchCode: code }, mocked: true };
|
}
|
|
/**
|
* 盘具(盘具称重台账)查询:真实接口优先;接口未联调/查不到时回落模拟数据。
|
* 模拟模式下盘具编号取扫码/输入的值,方便一个单子里测试多个盘具。
|
* @returns record 为 null 表示确实查不到
|
*/
|
export async function findBobbin(code: string) {
|
try {
|
const { data } = await TwistApi.queryBobbinWeighingPage({
|
current: 1,
|
size: 50,
|
weighingCode: code,
|
});
|
const records = pickRecords(data);
|
const exact = (records || []).find(
|
(row: any) => String(row?.weighingCode ?? "").trim() === code
|
);
|
const record = exact ?? (records?.length === 1 ? records[0] : null);
|
if (record) return { record, mocked: false };
|
} catch {
|
// 接口未就绪,走下面的模拟数据
|
}
|
if (!MOCK_ENABLED) return { record: null, mocked: false };
|
return { record: { ...MOCK_BOBBIN, weighingCode: code }, mocked: true };
|
}
|
|
/** 盘具是否已被领用 */
|
export function isBobbinReceived(row: any) {
|
const value = row?.received ?? row?.isReceived;
|
return [true, 1, "1", "true", "是"].includes(value);
|
}
|