优化店铺配置相关

This commit is contained in:
yml
2026-04-14 16:15:17 +08:00
parent ed45eab26c
commit bb47d168a9
20 changed files with 425 additions and 198 deletions
@@ -2,10 +2,11 @@
import { query } from '../../db/client.js'
import {
getAgisoMessagingDefaults,
getAgisoShopConfig,
getAgisoShopConfigMap,
getAgisoShopsFilePath,
saveAgisoShopConfigMap,
saveAgisoMessagingConfig,
} from '../platforms/agiso/shop-config-service.js'
import { enrichAgisoXianyuTradeOrder } from '../platforms/agiso/xianyu/order-detail-service.js'
import {
@@ -26,6 +27,7 @@ import { resolveDisplayShopName } from './admin-read-shared-helpers.js'
export async function getAdminAgisoShopConfigs() {
const configMap = getAgisoShopConfigMap()
const defaults = getAgisoMessagingDefaults()
const rowsResult = await query(
`
SELECT
@@ -43,20 +45,10 @@ export async function getAdminAgisoShopConfigs() {
return {
filePath: getAgisoShopsFilePath(),
defaults: mapAdminAgisoMessagingDefaults(defaults),
shops: Object.entries(configMap)
.sort(([left], [right]) => left.localeCompare(right))
.map(([shopId, config]) => ({
shopId,
shopName: String(config.shopName || '').trim(),
accessToken: String(config.accessToken || '').trim(),
accessTokenMasked: maskSecret(config.accessToken),
enabled: typeof config.enabled === 'boolean' ? config.enabled : null,
messageTemplate: String(config.messageTemplate || '').trim(),
autoDeliveryMessageTemplate: String(config.autoDeliveryMessageTemplate || '').trim(),
appSecretConfigured: Boolean(String(config.appSecret || '').trim()),
apiVersion: String(config.apiVersion || '').trim(),
sendMessageEndpoint: String(config.sendMessageEndpoint || '').trim(),
})),
.map(([shopId, config]) => mapAdminAgisoShopConfigItem(shopId, config)),
observedShops: rows.map((row) => ({
shopId: String(row.shop_id || '').trim(),
detectedShopName: String(row.detected_shop_name || '').trim(),
@@ -71,9 +63,14 @@ export async function getAdminAgisoShopConfigs() {
/** @param {AdminAgisoShopConfigSaveInput} [payload] */
export function updateAdminAgisoShopConfigs(payload = /** @type {AdminAgisoShopConfigSaveInput} */ ({})) {
const rawItems = Array.isArray(payload.shops) ? payload.shops : []
const currentDefaults = getAgisoMessagingDefaults()
const currentMap = getAgisoShopConfigMap()
const nextDefaults = { ...currentDefaults }
const nextMap = {}
applyOptionalStringField(nextDefaults, 'messageTemplate', payload.defaults)
applyOptionalStringField(nextDefaults, 'autoDeliveryMessageTemplate', payload.defaults)
for (const item of rawItems) {
const shopId = String(item?.shopId || '').trim()
if (!shopId) {
@@ -128,27 +125,56 @@ export function updateAdminAgisoShopConfigs(payload = /** @type {AdminAgisoShopC
nextMap[shopId] = next
}
const saved = saveAgisoShopConfigMap(nextMap)
const saved = saveAgisoMessagingConfig({
defaults: nextDefaults,
shops: nextMap,
})
return {
filePath: getAgisoShopsFilePath(),
shops: Object.entries(saved)
defaults: mapAdminAgisoMessagingDefaults(saved.defaults),
shops: Object.entries(saved.shops)
.sort(([left], [right]) => left.localeCompare(right))
.map(([shopId, config]) => ({
shopId,
shopName: String(config.shopName || '').trim(),
accessToken: String(config.accessToken || '').trim(),
accessTokenMasked: maskSecret(config.accessToken),
enabled: typeof config.enabled === 'boolean' ? config.enabled : null,
messageTemplate: String(config.messageTemplate || '').trim(),
autoDeliveryMessageTemplate: String(config.autoDeliveryMessageTemplate || '').trim(),
appSecretConfigured: Boolean(String(config.appSecret || '').trim()),
apiVersion: String(config.apiVersion || '').trim(),
sendMessageEndpoint: String(config.sendMessageEndpoint || '').trim(),
})),
.map(([shopId, config]) => mapAdminAgisoShopConfigItem(shopId, config)),
}
}
function mapAdminAgisoMessagingDefaults(defaults = {}) {
return {
messageTemplate: String(defaults.messageTemplate || '').trim(),
autoDeliveryMessageTemplate: String(defaults.autoDeliveryMessageTemplate || '').trim(),
}
}
function mapAdminAgisoShopConfigItem(shopId, config = {}) {
return {
shopId,
shopName: String(config.shopName || '').trim(),
accessToken: String(config.accessToken || '').trim(),
accessTokenMasked: maskSecret(config.accessToken),
enabled: typeof config.enabled === 'boolean' ? config.enabled : null,
messageTemplate: String(config.messageTemplate || '').trim(),
autoDeliveryMessageTemplate: String(config.autoDeliveryMessageTemplate || '').trim(),
appSecretConfigured: Boolean(String(config.appSecret || '').trim()),
apiVersion: String(config.apiVersion || '').trim(),
sendMessageEndpoint: String(config.sendMessageEndpoint || '').trim(),
}
}
function applyOptionalStringField(target, key, source) {
if (!source || typeof source[key] !== 'string') {
return
}
const value = String(source[key] || '').trim()
if (value) {
target[key] = value
return
}
delete target[key]
}
export async function getAdminFulfillmentBindingConfigs() {
const bindings = getOrderFulfillmentBindingConfigs()
const rowsResult = await query(
@@ -4,6 +4,17 @@ import path from 'node:path'
import { PROJECT_ROOT, runtimeConfig } from '../../../config/runtime.js'
const AGISO_SHOPS_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'agiso-shops.json')
const AGISO_MESSAGING_DEFAULT_KEYS = ['messageTemplate', 'autoDeliveryMessageTemplate']
const AGISO_SHOP_CONFIG_KEYS = [
'shopName',
'accessToken',
'messageTemplate',
'autoDeliveryMessageTemplate',
'appSecret',
'apiVersion',
'sendMessageEndpoint',
'tradeDetailEndpoint',
]
export function getAgisoShopsFilePath() {
return AGISO_SHOPS_FILE_PATH
@@ -11,11 +22,11 @@ export function getAgisoShopsFilePath() {
export function getAgisoShopConfigMap() {
const envConfig = normalizeAgisoShopConfigMap(runtimeConfig.platforms?.agiso?.messaging?.shops || {})
const fileConfig = loadAgisoShopConfigMapFromFile()
const fileConfig = loadAgisoMessagingConfigDocumentFromFile()
return {
...envConfig,
...fileConfig,
...fileConfig.shops,
}
}
@@ -28,24 +39,34 @@ export function getAgisoShopConfig(shopId) {
return getAgisoShopConfigMap()[normalizedShopId] || null
}
export function saveAgisoShopConfigMap(rawValue) {
const normalized = normalizeAgisoShopConfigMap(rawValue)
export function getAgisoMessagingDefaults() {
return loadAgisoMessagingConfigDocumentFromFile().defaults
}
export function saveAgisoMessagingConfig(rawValue) {
const normalized = normalizeAgisoMessagingConfigDocument(rawValue)
fs.mkdirSync(path.dirname(AGISO_SHOPS_FILE_PATH), { recursive: true })
fs.writeFileSync(AGISO_SHOPS_FILE_PATH, `${JSON.stringify(normalized, null, 2)}\n`, 'utf8')
return normalized
}
function loadAgisoShopConfigMapFromFile() {
function loadAgisoMessagingConfigDocumentFromFile() {
if (!fs.existsSync(AGISO_SHOPS_FILE_PATH)) {
return {}
return {
defaults: {},
shops: {},
}
}
try {
const rawText = fs.readFileSync(AGISO_SHOPS_FILE_PATH, 'utf8')
const parsed = JSON.parse(rawText)
return normalizeAgisoShopConfigMap(parsed)
return normalizeAgisoMessagingConfigDocument(parsed)
} catch {
return {}
return {
defaults: {},
shops: {},
}
}
}
@@ -64,7 +85,7 @@ function normalizeAgisoShopConfigMap(rawValue) {
next.enabled = enabled
}
for (const key of ['shopName', 'accessToken', 'messageTemplate', 'autoDeliveryMessageTemplate', 'appSecret', 'apiVersion', 'sendMessageEndpoint', 'tradeDetailEndpoint']) {
for (const key of AGISO_SHOP_CONFIG_KEYS) {
const value = String(config[key] || '').trim()
if (value) {
next[key] = value
@@ -77,6 +98,34 @@ function normalizeAgisoShopConfigMap(rawValue) {
return output
}
function normalizeAgisoMessagingDefaults(rawValue) {
const output = {}
if (!isPlainObject(rawValue)) {
return output
}
for (const key of AGISO_MESSAGING_DEFAULT_KEYS) {
const value = String(rawValue[key] || '').trim()
if (value) {
output[key] = value
}
}
return output
}
function normalizeAgisoMessagingConfigDocument(rawValue) {
const normalizedValue = isPlainObject(rawValue) ? rawValue : {}
const hasStructuredShape = Object.prototype.hasOwnProperty.call(normalizedValue, 'defaults')
|| Object.prototype.hasOwnProperty.call(normalizedValue, 'shops')
return {
defaults: normalizeAgisoMessagingDefaults(hasStructuredShape ? normalizedValue.defaults : {}),
shops: normalizeAgisoShopConfigMap(hasStructuredShape ? normalizedValue.shops : normalizedValue),
}
}
function normalizeBooleanLike(value) {
if (typeof value === 'boolean') {
return value
@@ -253,7 +253,7 @@ function resolveAgisoXianyuAutoDeliveryConfig(order) {
endpoint: String(baseConfig.endpoint || '').trim(),
apiVersion: String(baseConfig.apiVersion || shopConfig.apiVersion || '1').trim() || '1',
appSecret: String(shopConfig.appSecret || runtimeConfig.platforms?.agiso?.appSecret || '').trim(),
accessToken: String(shopConfig.accessToken || runtimeConfig.platforms?.agiso?.messaging?.accessToken || '').trim(),
accessToken: String(shopConfig.accessToken || '').trim(),
aldsType: normalizePositiveInteger(baseConfig.aldsType, 1),
ignoreAldsLog: normalizeBooleanLike(baseConfig.ignoreAldsLog, false),
ignoreBlackList: normalizeBooleanLike(baseConfig.ignoreBlackList, false),
@@ -1,7 +1,7 @@
import crypto from 'node:crypto'
import { runtimeConfig } from '../../../../config/runtime.js'
import { getAgisoShopConfigMap } from '../shop-config-service.js'
import { getAgisoMessagingDefaults, getAgisoShopConfigMap } from '../shop-config-service.js'
import {
createMessageDelivery,
findLatestSuccessfulMessageDeliveryByTask,
@@ -161,12 +161,14 @@ async function deliverAgisoXianyuMessageForTask({
function resolveAgisoXianyuMessagingConfig(order) {
const baseConfig = runtimeConfig.platforms?.agiso?.messaging || {}
const fileDefaults = getAgisoMessagingDefaults()
const shopId = String(order?.shop_id || '').trim()
const shopConfigs = getAgisoShopConfigMap()
const shopConfig = shopId && isPlainObject(shopConfigs[shopId]) ? shopConfigs[shopId] : {}
return {
...baseConfig,
...fileDefaults,
...shopConfig,
}
}
@@ -214,7 +214,7 @@ function resolveAgisoXianyuTradeDetailConfig(shopId) {
return {
endpoint: String(shopConfig.tradeDetailEndpoint || baseConfig.endpoint || '').trim(),
apiVersion: String(shopConfig.tradeDetailApiVersion || baseConfig.apiVersion || '1').trim() || '1',
accessToken: String(shopConfig.accessToken || runtimeConfig.platforms?.agiso?.messaging?.accessToken || '').trim(),
accessToken: String(shopConfig.accessToken || '').trim(),
appSecret: String(shopConfig.appSecret || runtimeConfig.platforms?.agiso?.appSecret || '').trim(),
timeoutMs: normalizePositiveInteger(shopConfig.tradeDetailTimeoutMs || baseConfig.timeoutMs, DEFAULT_DETAIL_TIMEOUT_MS),
}