216 lines
7.0 KiB
TypeScript
216 lines
7.0 KiB
TypeScript
import path from "node:path";
|
|
|
|
import { PROJECT_ROOT } from "../../config/runtime.js";
|
|
import { readJsonFile, writeJsonFile } from "../../utils/json-file-store.js";
|
|
import { resolveKuaishouEticketShopConfig } from "../platforms/kuaishou-eticket/source-config-service.js";
|
|
|
|
const KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH = path.join(
|
|
PROJECT_ROOT,
|
|
"data",
|
|
"kuaishou-cloud-fulfillment.json"
|
|
);
|
|
|
|
type JsonObject = Record<string, any>;
|
|
|
|
export function getKuaishouCloudFulfillmentFilePath() {
|
|
return KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH;
|
|
}
|
|
|
|
export function getKuaishouCloudFulfillmentConfig() {
|
|
return loadKuaishouCloudFulfillmentConfigFromFile();
|
|
}
|
|
|
|
export function saveKuaishouCloudFulfillmentConfig(rawValue) {
|
|
return writeJsonFile(
|
|
KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH,
|
|
rawValue,
|
|
normalizeKuaishouCloudFulfillmentConfig
|
|
);
|
|
}
|
|
|
|
export function mapKuaishouCloudFulfillmentItemsToBindings(config: JsonObject = {}) {
|
|
const items = Array.isArray(config.items) ? config.items : [];
|
|
|
|
return items
|
|
.filter((item) => item && item.enabled !== false)
|
|
.map((item) => ({
|
|
provider: String(item.provider || "91kaquan").trim() || "91kaquan",
|
|
platform: String(item.platform || "kuaishou").trim() || "kuaishou",
|
|
shopId: String(item.shopId || "").trim(),
|
|
skuCode: String(item.internalSkuCode || "").trim(),
|
|
skuName: String(item.internalSkuName || "").trim(),
|
|
profileKey: "kuaishou_ct_assisted",
|
|
enabled: item.enabled !== false,
|
|
priority: normalizePriority(item.priority),
|
|
config: {
|
|
flowType: "kuaishou_cloud_fulfillment",
|
|
configId: String(item.id || "").trim(),
|
|
cloudtentacles: {
|
|
cloudSourceKey:
|
|
String(item.cloudSourceKey || "default").trim() || "default",
|
|
cloudSourceKeyFallbacks: Array.isArray(item.cloudSourceKeyFallbacks)
|
|
? item.cloudSourceKeyFallbacks
|
|
: [],
|
|
skuId: normalizePositiveInteger(item.cloudSkuId),
|
|
skuName: String(item.cloudSkuName || "").trim(),
|
|
vnKey: "1",
|
|
autoBuyEnabled: item.autoBuyEnabled !== false,
|
|
minAssetReserve: normalizeNonNegativeInteger(item.minAssetReserve, 0),
|
|
autoReturnNumberAfterDispatch:
|
|
item.autoReturnNumberAfterDispatch === true,
|
|
},
|
|
kuaishouConsume: {
|
|
shopId: String(item.kuaishouConsumeShopId || "").trim(),
|
|
shopName: String(item.kuaishouConsumeShopName || "").trim(),
|
|
autoConsumeAfterDispatch: item.autoConsumeAfterDispatch === true,
|
|
},
|
|
notes: String(item.notes || "").trim(),
|
|
},
|
|
match: {
|
|
externalSkuCode: String(item.externalSkuCode || "").trim(),
|
|
externalItemId: String(item.externalItemId || "").trim(),
|
|
externalSkuName: String(item.externalSkuName || "").trim(),
|
|
config: {
|
|
resolvedSkuName: String(
|
|
item.resolvedSkuName || item.internalSkuName || ""
|
|
).trim(),
|
|
},
|
|
},
|
|
}))
|
|
.filter(
|
|
(item) =>
|
|
item.skuCode &&
|
|
(item.match.externalSkuCode ||
|
|
item.match.externalItemId ||
|
|
item.match.externalSkuName)
|
|
);
|
|
}
|
|
|
|
function loadKuaishouCloudFulfillmentConfigFromFile() {
|
|
return readJsonFile(
|
|
KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH,
|
|
() => normalizeKuaishouCloudFulfillmentConfig({}),
|
|
normalizeKuaishouCloudFulfillmentConfig
|
|
);
|
|
}
|
|
|
|
function normalizeKuaishouCloudFulfillmentConfig(rawValue) {
|
|
const source = isPlainObject(rawValue) ? rawValue : {};
|
|
return {
|
|
enabled: source.enabled !== false,
|
|
items: Array.isArray(source.items)
|
|
? source.items
|
|
.map((item) => normalizeKuaishouCloudFulfillmentItem(item))
|
|
.filter(Boolean)
|
|
: [],
|
|
};
|
|
}
|
|
|
|
function normalizeKuaishouCloudFulfillmentItem(rawValue) {
|
|
if (!isPlainObject(rawValue)) {
|
|
return null;
|
|
}
|
|
|
|
const internalSkuCode = String(rawValue.internalSkuCode || "").trim();
|
|
const cloudSkuId = normalizePositiveInteger(rawValue.cloudSkuId);
|
|
const externalSkuCode = String(rawValue.externalSkuCode || "").trim();
|
|
const externalItemId = String(rawValue.externalItemId || "").trim();
|
|
const externalSkuName = String(rawValue.externalSkuName || "").trim();
|
|
const kuaishouConsumeShopId = String(
|
|
rawValue.kuaishouConsumeShopId || ""
|
|
).trim();
|
|
const kuaishouConsumeShopName = String(
|
|
rawValue.kuaishouConsumeShopName || ""
|
|
).trim();
|
|
const kuaishouShopConfig = resolveKuaishouEticketShopConfig({
|
|
shopId: kuaishouConsumeShopId,
|
|
shopName: kuaishouConsumeShopName,
|
|
});
|
|
|
|
if (!internalSkuCode) {
|
|
return null;
|
|
}
|
|
|
|
if (!cloudSkuId) {
|
|
return null;
|
|
}
|
|
|
|
if (!externalSkuCode && !externalItemId && !externalSkuName) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
id: String(rawValue.id || internalSkuCode).trim() || internalSkuCode,
|
|
enabled: rawValue.enabled !== false,
|
|
priority: normalizePriority(rawValue.priority),
|
|
provider: String(rawValue.provider || "91kaquan").trim() || "91kaquan",
|
|
platform: String(rawValue.platform || "kuaishou").trim() || "kuaishou",
|
|
shopId: String(rawValue.shopId || "").trim(),
|
|
internalSkuCode,
|
|
internalSkuName:
|
|
String(rawValue.internalSkuName || "").trim() || internalSkuCode,
|
|
externalSkuCode,
|
|
externalItemId,
|
|
externalSkuName,
|
|
resolvedSkuName: String(
|
|
rawValue.resolvedSkuName || rawValue.internalSkuName || ""
|
|
).trim(),
|
|
cloudSourceKey:
|
|
String(rawValue.cloudSourceKey || "default").trim() || "default",
|
|
cloudSourceKeyFallbacks: normalizeStringArray(
|
|
rawValue.cloudSourceKeyFallbacks
|
|
),
|
|
cloudSkuId,
|
|
cloudSkuName: String(rawValue.cloudSkuName || "").trim(),
|
|
vnKey: "1",
|
|
autoBuyEnabled: rawValue.autoBuyEnabled !== false,
|
|
minAssetReserve: normalizeNonNegativeInteger(rawValue.minAssetReserve, 0),
|
|
autoReturnNumberAfterDispatch:
|
|
rawValue.autoReturnNumberAfterDispatch === true,
|
|
autoConsumeAfterDispatch: rawValue.autoConsumeAfterDispatch === true,
|
|
kuaishouConsumeShopId: String(
|
|
kuaishouShopConfig?.shopId || kuaishouConsumeShopId
|
|
).trim(),
|
|
kuaishouConsumeShopName: String(
|
|
kuaishouShopConfig?.kshopName || kuaishouConsumeShopName
|
|
).trim(),
|
|
notes: String(rawValue.notes || "").trim(),
|
|
};
|
|
}
|
|
|
|
function normalizePositiveInteger(value) {
|
|
const parsed = Number(value);
|
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : 0;
|
|
}
|
|
|
|
function normalizeNonNegativeInteger(value, fallback) {
|
|
const parsed = Number(value);
|
|
return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback;
|
|
}
|
|
|
|
function normalizePriority(value) {
|
|
const parsed = Number(value);
|
|
if (!Number.isFinite(parsed)) {
|
|
return 100;
|
|
}
|
|
|
|
return Math.max(1, Math.round(parsed));
|
|
}
|
|
function isPlainObject(value) {
|
|
return Object.prototype.toString.call(value) === "[object Object]";
|
|
}
|
|
|
|
function normalizeStringArray(value) {
|
|
if (Array.isArray(value)) {
|
|
return value.map((v) => String(v || "").trim()).filter(Boolean);
|
|
}
|
|
// 兼容旧格式:字符串用逗号分隔
|
|
if (typeof value === "string") {
|
|
return value
|
|
.split(",")
|
|
.map((v) => v.trim())
|
|
.filter(Boolean);
|
|
}
|
|
return [];
|
|
}
|