新增 affiliate_dash 履约配置与商品映射(阶段 3)

- bootstrap CORE_PROFILES + routing ROUTABLE/DEFAULT_PRIORITY 接入 affiliate_dash
- planner 上下文 affiliateDash 块 + resolveDynamicAffiliateDashProfile
- product-resolution: 91 productNo→sku 映射匹配(skuMapping) + snapshot.affiliateDash
- prepare 前余额预检(getAffiliateDashWallet)
- AFFILIATE_DASH_SKU_MAPPING_JSON env 注入
- admin 后端接口(GET/POST 配置、match、products、wallet)+ 前端 Tabs 面板
- 联调:模拟 91 进单命中 affiliate_dash 路由, 未命中回退;前后端 typecheck + 212 测试通过
This commit is contained in:
yml2213
2026-08-05 15:08:41 +08:00
parent 867ffd2f3c
commit 3284fed7a1
16 changed files with 817 additions and 5 deletions
@@ -0,0 +1,80 @@
import { getAffiliateDashConfig } from '../../platforms/affiliate-dash/config.js'
import type { JsonObject } from '../../../types/json.js'
import {
getAffiliateDashWallet,
} from '../../platforms/affiliate-dash/order-service.js'
import { listAffiliateDashProducts } from '../../platforms/affiliate-dash/product-service.js'
import {
getAffiliateDashSourceConfig,
hasAffiliateDashConfig,
normalizeAffiliateDashSourceConfig,
saveAffiliateDashSourceConfig,
} from '../../platforms/affiliate-dash/source-config-service.js'
export function getAdminAffiliateDashConfig() {
const source = getAdminEditableAffiliateDashConfig()
const effective = getAffiliateDashConfig()
return {
source,
effective: mapEffectiveAffiliateDashConfig(effective),
}
}
export async function updateAdminAffiliateDashConfig(payload: JsonObject = {}) {
const saved = await saveAffiliateDashSourceConfig(payload)
const effective = getAffiliateDashConfig()
return {
source: saved,
effective: mapEffectiveAffiliateDashConfig(effective),
}
}
/** 按 91 商品编码(productNo)测试 sku 映射命中。 */
export function matchAdminAffiliateDashSku(payload: JsonObject = {}) {
const productNo = String(payload.productNo || payload.product_no || '').trim()
const source = getAdminEditableAffiliateDashConfig()
const sku = productNo
? String(source.skuMapping[productNo] || '').trim()
: ''
return {
productNo,
sku,
matched: Boolean(productNo && sku),
}
}
export async function listAdminAffiliateDashProducts(payload: JsonObject = {}) {
return listAffiliateDashProducts({
page: Number(payload.page || 1) || 1,
size: Math.min(200, Math.max(1, Number(payload.size || 50) || 50)),
})
}
export async function getAdminAffiliateDashWallet() {
return getAffiliateDashWallet()
}
function getAdminEditableAffiliateDashConfig() {
if (hasAffiliateDashConfig()) {
return getAffiliateDashSourceConfig()
}
return normalizeAffiliateDashSourceConfig(getAffiliateDashConfig())
}
function mapEffectiveAffiliateDashConfig(config: ReturnType<typeof getAffiliateDashConfig>) {
return {
enabled: config.enabled !== false,
baseUrl: config.baseUrl,
timeoutMs: config.timeoutMs,
notifyUrl: config.notifyUrl,
timestampToleranceSeconds: config.timestampToleranceSeconds,
hasAppKey: Boolean(config.appKey),
hasAppSecret: Boolean(config.appSecret),
hasCallbackSecret: Boolean(config.callbackSecret),
skuMappingCount: Object.keys(config.skuMapping).length,
}
}