From b1979eea94f2935d0e4814244078013f690d88c7 Mon Sep 17 00:00:00 2001 From: yml Date: Mon, 25 May 2026 22:27:11 +0800 Subject: [PATCH] =?UTF-8?q?=E8=84=B1=E6=95=8F=E8=BF=90=E8=A1=8C=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=92=8C=E6=97=A7=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + README.md | 2 +- apps/backend/.gitignore | 2 + apps/backend/README.md | 2 + apps/backend/data/agiso-shops.json | 23 - .../data/cloudtentacles-sources.example.json | 16 + apps/backend/data/cloudtentacles-sources.json | 27 - .../kuaishou-cloud-fulfillment.example.json | 30 + .../data/kuaishou-cloud-fulfillment.json | 85 -- .../data/kuaishou-eticket-source.example.json | 13 + .../backend/data/kuaishou-eticket-source.json | 20 - .../data/notification-config.example.json | 14 + apps/backend/data/notification-config.json | 40 - .../data/order-fulfillment-bindings.json | 42 - ...-jobs.json => scheduled-jobs.example.json} | 10 +- .../src/services/open-91/shared.test.ts | 6 +- docs/91卡券/3.异步卡密下单.md | 6 +- docs/91卡券/4.查询订单接口.md | 14 +- docs/91卡券/5.当前项目对接配置.md | 2 +- docs/91卡券/6.开发设计.md | 12 +- docs/91卡券/卡密加密说明.md | 6 +- docs/app信息.md | 83 -- docs/backend-typescript-migration-plan.md | 909 ------------------ docs/cloudflared_tunnel.txt | 63 -- docs/cloudtentacles发货平台接入设计.md | 733 -------------- docs/frontend-optimization-plan.md | 524 ---------- docs/xianyu_api/咸鱼api.md | 101 -- docs/xianyu_api/更新发货状态.md | 50 - docs/xianyu_api/确认收货后通知.md | 43 - docs/咸鱼商品详情.logs | 31 - docs/快手小店核销.md | 74 -- docs/是否过期判断.md | 58 -- 32 files changed, 105 insertions(+), 2938 deletions(-) delete mode 100644 apps/backend/data/agiso-shops.json create mode 100644 apps/backend/data/cloudtentacles-sources.example.json delete mode 100644 apps/backend/data/cloudtentacles-sources.json create mode 100644 apps/backend/data/kuaishou-cloud-fulfillment.example.json delete mode 100644 apps/backend/data/kuaishou-cloud-fulfillment.json create mode 100644 apps/backend/data/kuaishou-eticket-source.example.json delete mode 100644 apps/backend/data/kuaishou-eticket-source.json create mode 100644 apps/backend/data/notification-config.example.json delete mode 100644 apps/backend/data/notification-config.json delete mode 100644 apps/backend/data/order-fulfillment-bindings.json rename apps/backend/data/{scheduled-jobs.json => scheduled-jobs.example.json} (65%) delete mode 100644 docs/app信息.md delete mode 100644 docs/backend-typescript-migration-plan.md delete mode 100644 docs/cloudflared_tunnel.txt delete mode 100644 docs/cloudtentacles发货平台接入设计.md delete mode 100644 docs/frontend-optimization-plan.md delete mode 100644 docs/xianyu_api/咸鱼api.md delete mode 100644 docs/xianyu_api/更新发货状态.md delete mode 100644 docs/xianyu_api/确认收货后通知.md delete mode 100644 docs/咸鱼商品详情.logs delete mode 100644 docs/快手小店核销.md delete mode 100644 docs/是否过期判断.md diff --git a/.gitignore b/.gitignore index de959b98..91f24627 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ apps/*/.env.local apps/backend/data/*.db apps/backend/data/*.db-shm apps/backend/data/*.db-wal +apps/backend/data/*.json +!apps/backend/data/*.example.json apps/backend/data/cloudtentacles-session.json apps/backend/data/browser-sessions apps/backend/data/redeem-screenshots diff --git a/README.md b/README.md index 03bf600a..2965fda7 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ cp .env.server.example .env - PostgreSQL 数据保存在 Docker volume `postgres_data` - Caddy 数据保存在 Docker volume `caddy_data` -注意:`apps/backend/data/*.json` 中可能包含账号、Cookie、token、平台配置等敏感信息。提交代码前请确认没有把真实生产凭据提交到仓库。 +注意:`apps/backend/data/*.json` 中可能包含账号、Cookie、token、平台配置等敏感信息,默认不进入仓库;仓库只保留 `*.example.json` 模板。 ## 生产部署 diff --git a/apps/backend/.gitignore b/apps/backend/.gitignore index b66fb04d..65e17870 100644 --- a/apps/backend/.gitignore +++ b/apps/backend/.gitignore @@ -12,4 +12,6 @@ data/logs/ data/*.db data/*.db-shm data/*.db-wal +data/*.json +!data/*.example.json data/cloudtentacles-session.json diff --git a/apps/backend/README.md b/apps/backend/README.md index 399887b7..606d98ac 100644 --- a/apps/backend/README.md +++ b/apps/backend/README.md @@ -92,3 +92,5 @@ npm test - `data/logs/webhook-YYYY-MM-DD.log` 日志按天切分,默认自动清理 7 天前的旧日志。成功的 `/health`、`/health/live`、`/health/ready` 探活请求默认不写 access log。 + +`data/*.json` 为本地运行配置,可能包含账号、Cookie、token 或平台配置,默认不提交;请复制 `data/*.example.json` 后填写真实值。 diff --git a/apps/backend/data/agiso-shops.json b/apps/backend/data/agiso-shops.json deleted file mode 100644 index e36a8b87..00000000 --- a/apps/backend/data/agiso-shops.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "defaults": { - "messageTemplate": "您的订单 {platformOrderId} 已创建领取链接,请您复制链接到浏览器自动兑换,请尽快打开并完成领取:\n\n{claimUrl}", - "autoDeliveryMessageTemplate": "亲亲,您购买的兑换码已自行兑换成功,请在游戏中邮件领取,感谢您的支持" - }, - "shops": { - "693760716": { - "enabled": true, - "shopName": "大锤商行", - "accessToken": "AldsIdlefmykv7w6xdvgf9r2ymsxrmznux74tyaehc9pwygdnrgr4" - }, - "2037495620": { - "enabled": true, - "shopName": "羊小胖。", - "accessToken": "AldsIdle4925bh8c9n3ka79fxauc9egk7uea6f6frfbbb5btvxpvu" - }, - "2209880145223": { - "enabled": true, - "shopName": "大锤号商", - "accessToken": "AldsIdleu5rzb68g8gh32sk9e8rbunes6gwyg59aph2nn5em6fp4r" - } - } -} diff --git a/apps/backend/data/cloudtentacles-sources.example.json b/apps/backend/data/cloudtentacles-sources.example.json new file mode 100644 index 00000000..74445179 --- /dev/null +++ b/apps/backend/data/cloudtentacles-sources.example.json @@ -0,0 +1,16 @@ +{ + "enabled": true, + "sources": [ + { + "key": "default", + "label": "默认账号", + "enabled": true, + "baseUrl": "https://example.com", + "username": "", + "password": "", + "phone": "", + "deviceId": "-", + "deviceType": 0 + } + ] +} diff --git a/apps/backend/data/cloudtentacles-sources.json b/apps/backend/data/cloudtentacles-sources.json deleted file mode 100644 index 9382f626..00000000 --- a/apps/backend/data/cloudtentacles-sources.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "enabled": true, - "sources": [ - { - "key": "default", - "label": "默认账号", - "enabled": true, - "baseUrl": "https://123.207.217.176", - "username": "17665234375", - "password": "yaochao11", - "phone": "17665234375", - "deviceId": "-", - "deviceType": 0 - }, - { - "key": "account2", - "label": "备用账号 1", - "enabled": true, - "baseUrl": "https://123.207.217.176", - "username": "18216161068", - "password": "yaochao11", - "phone": "18216161068", - "deviceId": "-", - "deviceType": 0 - } - ] -} diff --git a/apps/backend/data/kuaishou-cloud-fulfillment.example.json b/apps/backend/data/kuaishou-cloud-fulfillment.example.json new file mode 100644 index 00000000..41e470e5 --- /dev/null +++ b/apps/backend/data/kuaishou-cloud-fulfillment.example.json @@ -0,0 +1,30 @@ +{ + "enabled": true, + "items": [ + { + "id": "示例快手云商品", + "enabled": false, + "priority": 100, + "provider": "91kaquan", + "platform": "kuaishou", + "shopId": "91kaquan", + "internalSkuCode": "示例快手云商品", + "internalSkuName": "示例快手云商品", + "externalSkuCode": "EXTERNAL-SKU-001", + "externalItemId": "", + "externalSkuName": "示例外部商品", + "resolvedSkuName": "示例快手云商品", + "cloudSourceKey": "default", + "cloudSourceKeyFallbacks": [], + "cloudSkuId": 1, + "cloudSkuName": "示例云商品", + "autoBuyEnabled": true, + "minAssetReserve": 0, + "autoReturnNumberAfterDispatch": true, + "autoConsumeAfterDispatch": false, + "kuaishouConsumeShopId": "", + "kuaishouConsumeShopName": "", + "notes": "复制为 kuaishou-cloud-fulfillment.json 后填写真实配置" + } + ] +} diff --git a/apps/backend/data/kuaishou-cloud-fulfillment.json b/apps/backend/data/kuaishou-cloud-fulfillment.json deleted file mode 100644 index ad882ae5..00000000 --- a/apps/backend/data/kuaishou-cloud-fulfillment.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "enabled": true, - "items": [ - { - "id": "套装-浪漫天命", - "enabled": true, - "priority": 100, - "provider": "91kaquan", - "platform": "kuaishou", - "shopId": "91kaquan", - "internalSkuCode": "套装-浪漫天命", - "internalSkuName": "183999074512936", - "externalSkuCode": "183999074512936", - "externalItemId": "183999074512936", - "externalSkuName": "183999074512936", - "resolvedSkuName": "183999074512936", - "cloudSourceKey": "default", - "cloudSourceKeyFallbacks": [ - "account2" - ], - "cloudSkuId": 28, - "cloudSkuName": "套装-浪漫天命", - "vnKey": "1", - "autoBuyEnabled": true, - "minAssetReserve": 0, - "autoReturnNumberAfterDispatch": true, - "autoConsumeAfterDispatch": true, - "kuaishouConsumeShopId": "3676797936", - "kuaishouConsumeShopName": "小鱼儿游戏服务店", - "notes": "从 91卡券订单 2614500561157561 导入" - }, - { - "id": "套装-浪漫天命", - "enabled": true, - "priority": 100, - "provider": "91kaquan", - "platform": "kuaishou", - "shopId": "3676797936", - "internalSkuCode": "套装-浪漫天命", - "internalSkuName": "183999074511936", - "externalSkuCode": "183999074511936", - "externalItemId": "183999074511936", - "externalSkuName": "183999074511936", - "resolvedSkuName": "183999074511936", - "cloudSourceKey": "default", - "cloudSourceKeyFallbacks": [], - "cloudSkuId": 28, - "cloudSkuName": "套装-浪漫天命", - "vnKey": "1", - "autoBuyEnabled": true, - "minAssetReserve": 0, - "autoReturnNumberAfterDispatch": true, - "autoConsumeAfterDispatch": true, - "kuaishouConsumeShopId": "3676797936", - "kuaishouConsumeShopName": "小鱼儿游戏服务店", - "notes": "从 91卡券订单 2613900255300561 导入" - }, - { - "id": "91卡券订单取样导入", - "enabled": true, - "priority": 100, - "provider": "91kaquan", - "platform": "kuaishou", - "shopId": "91kaquan", - "internalSkuCode": "套装-浪漫天命", - "internalSkuName": "套装-浪漫天命", - "externalSkuCode": "183999074510936", - "externalItemId": "183999074510936", - "externalSkuName": "183999074510936", - "resolvedSkuName": "183999074510936", - "cloudSourceKey": "default", - "cloudSourceKeyFallbacks": [], - "cloudSkuId": 28, - "cloudSkuName": "套装-浪漫天命", - "vnKey": "1", - "autoBuyEnabled": true, - "minAssetReserve": 0, - "autoReturnNumberAfterDispatch": true, - "autoConsumeAfterDispatch": true, - "kuaishouConsumeShopId": "3676797936", - "kuaishouConsumeShopName": "小鱼儿游戏服务店", - "notes": "从 91卡券订单 2613300010204561 导入" - } - ] -} diff --git a/apps/backend/data/kuaishou-eticket-source.example.json b/apps/backend/data/kuaishou-eticket-source.example.json new file mode 100644 index 00000000..74ea81eb --- /dev/null +++ b/apps/backend/data/kuaishou-eticket-source.example.json @@ -0,0 +1,13 @@ +{ + "enabled": true, + "baseUrl": "https://s.kwaixiaodian.com", + "shops": [ + { + "shopId": "", + "kshopName": "", + "cookie": "", + "userAvatar": "", + "enabled": false + } + ] +} diff --git a/apps/backend/data/kuaishou-eticket-source.json b/apps/backend/data/kuaishou-eticket-source.json deleted file mode 100644 index 400be546..00000000 --- a/apps/backend/data/kuaishou-eticket-source.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "enabled": true, - "baseUrl": "https://s.kwaixiaodian.com", - "shops": [ - { - "shopId": "3676797936", - "kshopName": "小鱼儿游戏服务店", - "cookie": "_did=web_977722931F45F3C4; did=web_mxsox80uwsj3o4bkdsi2xhbxnx5gdlpn; sid=kshop.api; kshop.api_st=Cgxrc2hvcC5hcGkuc3QSoAHnDz5KbyPrdR8uWNB0MspVtX2zUOBrDcysluKZ9P6NT0IaEtnV-24otPiLyxcbH1iStuNg84bSxClfdu63cgMKzi0AovJn5DFqJUjXPfJZ1XxL8xDXOIdvv73SVr0eQhPKrD_twqnWJu-1HLgxl294XMhDPhO8JbNcFhv_cOwBsxjZYUNMs_7kpRHIpDEU_adQH0zQOBVQYu4AzU0rhF2EGhI9zclILZeuwZLmGG1mEKpcYGMiIOkT8avvcn-qSsIRdLyBf0U1Fjoud_FP9qcCFMjohN1AKAUwAQ; kshop.api_ph=a5c01f4da50e7eda8facb70fd1b13af57eb3; bUserId=1000324969453; userId=3676797936; kuaishou.shop.b_st=ChJrdWFpc2hvdS5zaG9wLmIuc3QSoAHbRIrpTvTjW-nbSsGDVimfmFK01ohV83Wh1v9vCN89z4-bJqpa_r7jmXBgL53hZ0OD5Y8Jz5fUPxWT-6PYNCfLVB20XogIDibxfXXjJSW5d4nchty1_veIl6r4NsUhHu0N93XRsx8vUxfQvAwlczsvefFqvPeZ3iAQnACDEVqJ7m7oI5BK9MCobzGGGuznAgtY8l0Z10qy3e5WmPgiSaI4GhLSubyi-uEBAthqCoUoWxNxjR0iINJ8MTa8OcsVUjQ5AuIuH9BtGr4JuS89zMjEz3McjsjmKAUwAQ; kuaishou.shop.b_ph=0a29c066148190b0759c776da8e94775e7dd", - "userAvatar": "https://p2-pro.a.yximgs.com/uhead/AB/2024/11/17/20/BMjAyNDExMTcyMDQ3NTdfMzY3Njc5NzkzNl8yX2hkODUyXzIwNg==_s.jpg", - "enabled": true - }, - { - "shopId": "4269276762", - "kshopName": "稚嫩游戏交易店", - "cookie": "_did=web_1426300268274CD9; did=web_ozkrrsevhb6yuztyk6m63vqqi5h2pzfl; __risk_web_device_id=cd52e12c1773406609757e71; sid=kuaishou.shop.b; sellerId=4269276762; bUserId=1000492186791; userId=4269276762; merchantSellerId=4269276762; merchantSessionKey=1777621574120_fbd47024d23e73fc4ad1a157ffece433; kuaishou.shop.b_st=ChJrdWFpc2hvdS5zaG9wLmIuc3QSoAFzGnewF-wCpt4rHi-D-pp8zPUp7HByKY0MlHkw-WV676zG7z09Y5i7d7URwmGC8CL13jN0fOGV7d3GfaH2XLH8d4p60z0Ms-dIX0bipkI0yUWHfgnWqv9VPa8HqVRqMLs2VGD82X9tAR3eN9PXu38AYg0a5kpawchGPb2tjcYgLgH5b5DnJgjipHqzWb8Ma8AcLOmryqCSg4ZHwO5dbVJHGhIdwFBlxRpZgyh6i0Do-DSRsroiIIayd1xA628OsvCY2qV1HjCrTvMVt-3LmXcU6rLKSzytKAUwAQ; kuaishou.shop.b_ph=38925ccb882ec5456dd1c6bcee3f87b7e740", - "userAvatar": "https://p2-pro.a.yximgs.com/uhead/AB/2024/07/23/17/BMjAyNDA3MjMxNzA1MThfNDI2OTI3Njc2Ml8yX2hkNDg1XzgxNQ==_s.jpg", - "enabled": true - } - ] -} diff --git a/apps/backend/data/notification-config.example.json b/apps/backend/data/notification-config.example.json new file mode 100644 index 00000000..1f1a0785 --- /dev/null +++ b/apps/backend/data/notification-config.example.json @@ -0,0 +1,14 @@ +{ + "enabled": true, + "channels": { + "bark": { + "enabled": true, + "serverUrl": "https://api.day.app", + "recipients": [] + }, + "wpush": { + "enabled": true, + "recipients": [] + } + } +} diff --git a/apps/backend/data/notification-config.json b/apps/backend/data/notification-config.json deleted file mode 100644 index 573fe861..00000000 --- a/apps/backend/data/notification-config.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "enabled": true, - "channels": { - "bark": { - "enabled": true, - "serverUrl": "https://api.day.app", - "recipients": [ - { - "id": "cdab629b-0480-4741-a4b5-4c11fb8fbc6b", - "name": "弋宸先生", - "deviceKey": "NaiQzbZkJTcaW23VWU9AXf", - "enabled": true - }, - { - "id": "82af4cb0-f6b2-4636-b1ca-29f482c49b30", - "name": "yml-测试1", - "deviceKey": "5EdwoMkrpuAfNLZN8aVrh5", - "enabled": true - } - ] - }, - "wpush": { - "enabled": true, - "recipients": [ - { - "id": "1c1089bb-4a54-4ec9-a10f-15b8099fdfb0", - "name": "y", - "apiKey": "WPUSHcPSmgodKUwMCB13IFSHJsyBqUI4", - "enabled": true - }, - { - "id": "5affc7d0-3944-43ee-90cb-8242ab9b34e7", - "name": "yml", - "apiKey": "WPUSHsa44qjF35klEZRqVHxAouoDE2A6", - "enabled": true - } - ] - } - } -} diff --git a/apps/backend/data/order-fulfillment-bindings.json b/apps/backend/data/order-fulfillment-bindings.json deleted file mode 100644 index c3837b32..00000000 --- a/apps/backend/data/order-fulfillment-bindings.json +++ /dev/null @@ -1,42 +0,0 @@ -[ - { - "provider": "agiso", - "platform": "xianyu", - "shopId": "2209880145223", - "shopName": "", - "skuCode": "海底捞第五人格皮肤", - "skuName": "海底捞第五人格皮肤", - "profileKey": "tencent_claim_redeem", - "enabled": false, - "priority": 100, - "config": {}, - "match": { - "externalSkuCode": "6227949975509", - "externalItemId": "1038123159888", - "externalSkuName": "海底捞第五人格皮肤", - "config": { - "resolvedSkuName": "海底捞第五人格皮肤" - } - } - }, - { - "provider": "agiso", - "platform": "xianyu", - "shopId": "2209880145223", - "shopName": "", - "skuCode": "三角洲海底捞动作", - "skuName": "海底捞干员庆生动作1个", - "profileKey": "tencent_claim_redeem", - "enabled": true, - "priority": 100, - "config": {}, - "match": { - "externalSkuCode": "6063968816746", - "externalItemId": "1041598483721", - "externalSkuName": "海底捞干员庆生动作1个", - "config": { - "resolvedSkuName": "海底捞干员庆生动作1个" - } - } - } -] diff --git a/apps/backend/data/scheduled-jobs.json b/apps/backend/data/scheduled-jobs.example.json similarity index 65% rename from apps/backend/data/scheduled-jobs.json rename to apps/backend/data/scheduled-jobs.example.json index 650f4da9..ac9517a1 100644 --- a/apps/backend/data/scheduled-jobs.json +++ b/apps/backend/data/scheduled-jobs.example.json @@ -4,8 +4,8 @@ { "id": "cloudtentacles-health", "type": "cloudtentacles_health", - "enabled": true, - "intervalSeconds": 18000, + "enabled": false, + "intervalSeconds": 300, "cooldownSeconds": 1800, "config": { "assetThreshold": 500, @@ -14,12 +14,6 @@ "sourceKey": "default", "label": "默认账号", "enabled": true, - "assetThreshold": 100 - }, - { - "sourceKey": "account2", - "label": "备用账号 1", - "enabled": true, "assetThreshold": 500 } ] diff --git a/apps/backend/src/services/open-91/shared.test.ts b/apps/backend/src/services/open-91/shared.test.ts index ddaba561..27aa7866 100644 --- a/apps/backend/src/services/open-91/shared.test.ts +++ b/apps/backend/src/services/open-91/shared.test.ts @@ -113,14 +113,14 @@ test('resolveOpen91QueryState returns success only when every task is ready', () test('buildOpen91CardItem mirrors claim link into jumpLink and leaves password empty', () => { assert.deepEqual( buildOpen91CardItem({ - claimUrl: 'https://221329.cc.cd/#/claim/abc123xyz', + claimUrl: 'https://example.com/#/claim/abc123xyz', expireTime: '2026-05-05 12:00:00', }), { - cardNo: 'https://221329.cc.cd/#/claim/abc123xyz', + cardNo: 'https://example.com/#/claim/abc123xyz', cardPwd: '', expireTime: '2026-05-05 12:00:00', - jumpLink: 'https://221329.cc.cd/#/claim/abc123xyz', + jumpLink: 'https://example.com/#/claim/abc123xyz', }, ) }) diff --git a/docs/91卡券/3.异步卡密下单.md b/docs/91卡券/3.异步卡密下单.md index 6f4356a5..f1fbb30e 100644 --- a/docs/91卡券/3.异步卡密下单.md +++ b/docs/91卡券/3.异步卡密下单.md @@ -27,7 +27,7 @@ 请按以下地址配置: ```text -POST https://221329.cc.cd/api/v1/open/91/orders/create +POST https://你的域名/api/v1/open/91/orders/create ``` ## 4. 请求方式 @@ -97,7 +97,7 @@ your_secret_keybuyNum=1&callbackUrl=https://cb.example.com/notify/91/order&maxAm 4. 若 `productNo` 已映射到快手 Cloud 履约商品,则创建履约任务; 5. 若 `productNo` 尚未配置,则订单进入后台“待补全”队列,由运营补齐履约配置后重试生成任务; 6. 若传入 `maxAmount`,则校验成本是否超限; -7. 履约任务生成后,生成当前项目领取链接,例如:`https://221329.cc.cd/#/claim/{token}`; +7. 履约任务生成后,生成当前项目领取链接,例如:`https://你的域名/#/claim/{token}`; 8. 首次响应返回处理中状态,由 `91卡券` 后续调用查询订单接口获取最终卡密内容。 ## 10. 响应参数 @@ -151,6 +151,6 @@ your_secret_keybuyNum=1&callbackUrl=https://cb.example.com/notify/91/order&maxAm - `productNo` 请按我方提供的商品编号配置; - 若 `productNo` 尚未配置,当前项目会先保存订单并返回 `orderStatus = 10`,后台补齐履约配置后可手动重试; - 本接口成功受理后,不代表最终卡密已可交付; -- 最终交付内容为我方系统生成的领取链接,链接域名固定为 `221329.cc.cd`; +- 最终交付内容为我方系统生成的领取链接,链接域名按实际部署域名配置; - 该链接将在“查询订单接口”中,通过 `cards` 加密串返回; - 建议 `91卡券` 将此商品配置为:`异步卡密商品`。 diff --git a/docs/91卡券/4.查询订单接口.md b/docs/91卡券/4.查询订单接口.md index b0fa2e97..5e920343 100644 --- a/docs/91卡券/4.查询订单接口.md +++ b/docs/91卡券/4.查询订单接口.md @@ -21,7 +21,7 @@ 请按以下地址配置: ```text -POST https://221329.cc.cd/api/v1/open/91/orders/query +POST https://你的域名/api/v1/open/91/orders/query ``` ## 4. 请求方式 @@ -96,7 +96,7 @@ your_secret_keyorderNo=P91KS202605040001×tamp=1777867260&version=1.0your_se | `failReason` | string | 失败时建议返回 | 失败原因。 | | `orderCost` | decimal(14,4) | 成功时建议返回 | 订单总成本,单位:元。 | | `cards` | string | `orderStatus = 20` 时必须 | 卡密数据加密串。当前项目通过该字段返回领取链接。 | -| `cards[0].cardNo` | string | 成功时必须 | 最终交付的领取链接,格式为 `https://221329.cc.cd/#/claim/{token}`。 | +| `cards[0].cardNo` | string | 成功时必须 | 最终交付的领取链接,格式为 `https://你的域名/#/claim/{token}`。 | | `cards[0].cardPwd` | string | 可选 | 当前场景固定为空字符串。 | | `cards[0].expireTime` | string | 可选 | 领取链接过期时间,支持 `yyyy-MM-dd HH:mm:ss` 或 10 位秒级 Unix 时间戳。 | | `cards[0].jumpLink` | string | 可选 | 与 `cardNo` 保持一致,用于兼容链接展示场景。 | @@ -115,10 +115,10 @@ your_secret_keyorderNo=P91KS202605040001×tamp=1777867260&version=1.0your_se ```json [ { - "cardNo": "https://221329.cc.cd/#/claim/abc123xyz", + "cardNo": "https://你的域名/#/claim/abc123xyz", "cardPwd": "", "expireTime": "2026-05-05 12:00:00", - "jumpLink": "https://221329.cc.cd/#/claim/abc123xyz" + "jumpLink": "https://你的域名/#/claim/abc123xyz" } ] ``` @@ -168,10 +168,10 @@ your_secret_keyorderNo=P91KS202605040001×tamp=1777867260&version=1.0your_se ```json [ { - "cardNo": "https://221329.cc.cd/#/claim/abc123xyz", + "cardNo": "https://你的域名/#/claim/abc123xyz", "cardPwd": "", "expireTime": "2026-05-05 12:00:00", - "jumpLink": "https://221329.cc.cd/#/claim/abc123xyz" + "jumpLink": "https://你的域名/#/claim/abc123xyz" } ] ``` @@ -198,7 +198,7 @@ your_secret_keyorderNo=P91KS202605040001×tamp=1777867260&version=1.0your_se - 当返回 `orderStatus = 20` 时,表示我方已准备好最终交付内容; - 当返回 `orderStatus = 10` 时,可能是履约任务正在准备,也可能是后台正在补齐 `productNo` 对应的履约配置; - 最终交付内容是领取链接,不是传统卡号密码; -- 领取链接域名固定为 `221329.cc.cd`; +- 领取链接域名按实际部署域名配置; - 买家收到链接后,会进入我方系统领取页完成后续快手核销与履约流程; - 建议 `91卡券` 侧确认: - `cards.cardNo` 可直接展示完整链接; diff --git a/docs/91卡券/5.当前项目对接配置.md b/docs/91卡券/5.当前项目对接配置.md index 17eb57f5..def9a263 100644 --- a/docs/91卡券/5.当前项目对接配置.md +++ b/docs/91卡券/5.当前项目对接配置.md @@ -12,7 +12,7 @@ ## 2. 对接结论 -本次对接不走 `Agiso/咸鱼` 的站内消息链路,而是走: +本次对接采用独立开放接口链路: 1. `91卡券` 调用我方异步下单接口; 2. 我方创建内部订单,并生成领取链接; diff --git a/docs/91卡券/6.开发设计.md b/docs/91卡券/6.开发设计.md index 88cfc65f..b4ba9967 100644 --- a/docs/91卡券/6.开发设计.md +++ b/docs/91卡券/6.开发设计.md @@ -4,8 +4,8 @@ 基于以下对外接口文档完成当前项目接入: -- [3.异步卡密下单.md](/Users/yml/codes/order-site-workspace/docs/91卡券/3.异步卡密下单.md:1) -- [4.查询订单接口.md](/Users/yml/codes/order-site-workspace/docs/91卡券/4.查询订单接口.md:1) +- [3.异步卡密下单.md](./3.异步卡密下单.md) +- [4.查询订单接口.md](./4.查询订单接口.md) 目标能力: @@ -13,13 +13,13 @@ 2. 我方将订单作为独立接入平台订单写入当前项目; 3. 已配置商品自动走现有快手 Cloud 履约链路; 4. 未配置商品进入后台待补全队列,可手动补齐履约信息后重试; -5. 我方生成领取链接 `https://221329.cc.cd/#/claim/{token}`; +5. 我方生成领取链接 `https://你的域名/#/claim/{token}`; 6. `91卡券` 调用查询订单接口; 7. 我方在 `cards` 中返回领取链接,由 `91卡券` 自动发货给买家。 ## 2. 设计原则 -- `91卡券` 作为**新的订单来源**,不复用 `agiso`。 +- `91卡券` 作为**独立订单来源**。 - `91卡券` 不是新的履约执行器,而是外部售卖、订单输入和自动发货通道。 - 当前项目真正的交付物仍然是 `claimUrl`。 - 查询接口返回 `20` 的判断标准是“领取链接已生成并可发”,不是“快手最终兑换完成”。 @@ -37,7 +37,7 @@ 原因: -- 避免与 `agiso` webhook 语义混淆; +- 避免与其他平台回调语义混淆; - 避免复用历史后台拉单来源; - 便于后续单独做日志、排障和绑定配置。 @@ -219,7 +219,7 @@ platforms: { ### 9.2 编码方案 -按 [卡密加密说明.md](/Users/yml/codes/order-site-workspace/docs/91卡券/卡密加密说明.md:1) 实现: +按 [卡密加密说明.md](./卡密加密说明.md) 实现: - 算法:`AES` - 模式:`ECB` diff --git a/docs/91卡券/卡密加密说明.md b/docs/91卡券/卡密加密说明.md index 54caf5be..be7a134c 100644 --- a/docs/91卡券/卡密加密说明.md +++ b/docs/91卡券/卡密加密说明.md @@ -1,12 +1,12 @@ ### 简要描述: -- AES/加密模式ECB/填充PKCS7Padding/数据块128位 注意:加密密钥为开放平台的AppSecret(从open.agiso.com上查看) +- AES/加密模式 ECB / 填充 PKCS7Padding / 数据块 128 位。加密密钥使用开放平台分配的 AppSecret。 **假设cards为:** ``` [{"cardNo":"10001","cardPwd":"123456","expireTime":"2023-06-19 17:16:01"}] ``` -**假设开放平台的appSecret为:** 0a091b3aa4324435aab703142518a8f7(从open.agiso.com上查看) +**假设开放平台的 appSecret 为:** `00000000000000000000000000000000` ### .NET加密示例: @@ -121,4 +121,4 @@ public class Main { System.out.println("最终加密结果: " + encrypted); } } -``` \ No newline at end of file +``` diff --git a/docs/app信息.md b/docs/app信息.md deleted file mode 100644 index 858aa821..00000000 --- a/docs/app信息.md +++ /dev/null @@ -1,83 +0,0 @@ -order_cdk - -15173678868 -778899 - -AppId: 2026040753219154857 -AppSecret: tccxk5c7ppy7xpr43rvastceyydskfha - - -AccessToken: -TbAlds54ez66ateztecyprxtn6kb98w23ghy6r9c5yxt2zueknd -可将AccessToken复制给应用商! - - -咸鱼的 -AldsIdlefmykv7w6xdvgf9r2ymsxrmznux74tyaehc9pwygdnrgr4 - - -咸鱼店铺 羊小胖。 -AldsIdle4925bh8c9n3ka79fxauc9egk7uea6f6frfbbb5btvxpvu - - -拼接用户授权需访问url ,示例及参数说明如下: - - -https://alds.agiso.com/authorize.aspx?appId=2026040753219154857&state=order_cdk - - -https://alds.agiso.com/authorize.aspx?appId={$开发者应用的AppId}&state={$开发者自定义参数} - - - -https://open.agiso.com/document/#/alds/push/refundClosePush - -https://open.agiso.com/document/#/aldsIdle/guide - - - -目前这个系统的 /Users/yml/codes/order-site-backend -/Users/yml/codes/order-site-rewrite -前后端, 我如果想增加自动化 -1. 根据 订单创建成功后通知 获取订单信息, 然后根据订单信息等等匹配 需要的 cdk 等等信息 -2. 然后系统创建一个包含订单号 的连接, 可以自动 发给用户 -3. 用户收到链接后, 打开 通过qq或者wx 绑定自己的角色后, 系统可以后端自动提交cdk, 自动绑定, 截图 发给用户前端 - -这是我的初步设定 你分析合理性, 或者有哪些更好的方式 - - - ---- -admin / dev-admin-123456 -operator / dev-operator-123456 - - -DJQFf7Hg0VKY82JG76 已使用 -DJQFf7HgONCL4XD4EH 错误的 - -未使用 -DJPaMY6M0X1SFKAFQT -DJPaMY6M00CPQBEJV0 - - ----- -ngrok -ngrok http 80 -https://5cc8-193-176-84-38.ngrok-free.app - -https://5cc8-193-176-84-38.ngrok-free.app/api/v1/webhooks/agiso/trade - - - -https://221329.cc.cd/api/v1/webhooks/agiso/trade - ----- -服务器 生产域名见部署配置 - -调试 https://926d-193-176-84-20.ngrok-free.app/api/v1/webhooks/agiso/trade - - - -========== -https://123.207.217.176/#/home 发货 -账号 17665234375 密码 yaochao11 diff --git a/docs/backend-typescript-migration-plan.md b/docs/backend-typescript-migration-plan.md deleted file mode 100644 index 747c287e..00000000 --- a/docs/backend-typescript-migration-plan.md +++ /dev/null @@ -1,909 +0,0 @@ -# Backend TypeScript 迁移计划 - -最后更新:2026-05-21 - -## 结论 - -当前后端不建议整体重写为 Go。 - -更合适的路线是: - -1. 保留 Node.js + Express + Playwright + PostgreSQL 主栈 -2. 先把后端渐进迁移到 TypeScript -3. 同时拆分超大 service 文件 -4. 补足核心业务链路测试 - -这样可以先解决“可维护性”和“改动风险”问题,而不会额外引入一次高成本的跨语言重写。 - -## 为什么现在不直接重写 Go - -当前后端的主要复杂度并不来自语言本身,而是来自: - -- 订单、任务、库存、领取、自动发货、webhook 多条链路同时演进 -- Playwright 浏览器自动化本身就天然偏 Node 生态 -- 若整体换成 Go,浏览器自动化大概率仍需保留 Node worker -- 这样会把系统变成 Go + Node + Python 三段式,边界更多,联调更难 - -所以现阶段最有效的动作,不是换语言,而是先把现有 Node 后端“类型化、分层化、可测试化”。 - -## 当前主要维护痛点 - -从当前仓库状态看,风险主要集中在: - -- 少数超大编排文件已经承担过多职责 - - `apps/backend/src/services/admin/admin-service.js` - - `apps/backend/src/services/claim/claim-session-service.js` - - `apps/backend/src/services/order/webhook-service.js` - - `apps/backend/src/services/session/session.js` -- 领域对象靠运行时约定在 routes / services / repositories 之间传递 -- 当前自动化测试覆盖还偏薄,跨链路改动缺少回归保护 - -## 迁移目标 - -本次迁移不是为了“全部改成 .ts 才算完成”,而是为了达到下面几个目标: - -1. 让核心领域对象具备稳定的静态类型 -2. 让新增改动优先进入类型系统,而不是继续扩大纯 JS 面积 -3. 让超大 service 文件拆分时有类型边界可依赖 -4. 让 typecheck 和测试一起成为后端的标准校验步骤 - -## 分阶段计划 - -### 阶段 1:建立类型基础设施和构建链路 - -目标: - -- 引入后端 `tsconfig` -- 引入后端 `tsc -> dist` 构建链路 -- 开发和测试改为通过 `tsx` 支持 JS/TS 混合源码 -- 增加 `npm run typecheck` -- 先从最核心的共享配置和基础领域对象开始建类型 -- 生产 Docker 镜像运行编译后的 `dist` - -范围: - -- `runtimeConfig` -- 公共配置对象 -- 后续会继续补: - - admin DTO - - order / task / inventory 基础类型 - - webhook 解析结果类型 - -验收标准: - -- 后端可以执行 `npm run typecheck` -- 后端可以执行 `npm run build` -- `npm run dev` 继续运行源码,`npm run start` 运行 `dist/index.js` -- Docker 开发环境继续热更新,生产镜像只复制编译产物和运行依赖 - -### 阶段 2:按领域拆分超大 service - -目标: - -- 保持运行逻辑不变 -- 先把“巨石编排文件”拆成更小的用例编排模块 - -建议拆分顺序: - -1. `admin-service.js` - - `admin-order-service` - - `admin-task-service` - - `admin-inventory-service` - - `admin-webhook-service` -2. `claim-session-service.js` - - `claim-session-lifecycle` - - `claim-role-service` - - `claim-redeem-orchestrator` -3. `webhook-service.js` - - `webhook-parse` - - `webhook-validate` - - `webhook-process` - -### 阶段 3:扩大类型覆盖 - -目标: - -- 新增模块优先使用 `.ts` -- 旧模块逐步迁移,而不是一次性全改 -- 让 routes / services / repositories 之间共享同一套领域类型 - -建议优先顺序: - -1. `src/types/` 下沉淀共享领域模型 -2. repository 返回值显式类型化 -3. service 入参 / 出参类型化 -4. 再迁移最稳定的新模块到 `.ts` - -### 阶段 4:补核心回归测试 - -优先补这些主链路: - -1. webhook 入单与重放 -2. 库存预占 / 释放 / 换码 -3. claim 会话创建 / 关闭 / 切换 -4. 腾讯兑换结果分类 -5. 自动发货触发条件 - -## 已开始执行的第一步 - -本轮已经落地: - -1. backend 新增 `tsconfig.json` -2. backend 新增 `npm run typecheck` -3. 新增 `src/types/runtime-config.js` -4. `src/config/runtime.js` 已接入第一批类型检查 -5. 新增 `src/types/admin-read-models.js` -6. `src/services/admin/admin-service.js` 的订单 / 任务 / 库存 / webhook 读取返回模型已接入第二批类型检查 -7. 新增 `src/types/repository-rows.js` -8. `admin-service.js` 的核心读取映射函数参数,已开始明确依赖 repository 行模型 -9. `order / task / inventory / webhook / order-item / task-inventory-binding` repository 已补第一批返回类型 -10. backend `tsconfig.json` 已将上述 repository 纳入显式 `typecheck` 范围 -11. `npm --prefix apps/backend run typecheck` 已在 repository 扩围后通过 -12. 新增 `src/types/repository-inputs.js` -13. `order / task / inventory / webhook / order-item` repository 已开始显式使用共享输入类型 -14. `npm --prefix apps/backend run typecheck` 已在输入类型接入后继续通过 -15. 新增 `src/services/admin/admin-read-service.js`,开始承接后台查询型接口 -16. `orders / tasks / inventory / webhook-events` 管理路由已优先切到 `admin-read-service` -17. 读服务首轮拆分后,backend `typecheck` 继续通过 -18. 新增 `src/services/admin/admin-read-helpers.js`,开始承接读侧共享 helper -19. `admin-read-service.js` 已改为优先依赖 `admin-read-helpers.js`,不再直接依赖 `admin-service.js` -20. helper 下沉后,backend `typecheck` 继续通过 -21. `admin-service.js` 已开始复用 `admin-read-helpers.js`,并删除首批重复的读侧 helper -22. `order / task / inventory / webhook` repository 已补共享查询参数类型 -23. `npm --prefix apps/backend run typecheck` 已在查询参数类型接入后继续通过 -24. 新增 `src/types/admin-read-inputs.js`,开始承接后台读接口的 service 入参边界 -25. `admin-read-service.js` 的订单 / 任务 / 库存 / webhook 查询与详情入口已接入共享输入类型 -26. `npm --prefix apps/backend run typecheck` 已在 service 输入类型接入后继续通过 -27. 新增 `src/services/admin/admin-write-service.js`,开始承接后台库存写接口 -28. `inventory` 管理路由已切到 `admin-write-service`,`admin-service.js` 删除首批库存写侧实现 -29. 新增 `src/types/admin-write-inputs.js`,库存写接口已开始复用共享输入类型 -30. backend `typecheck` 已覆盖 `admin-write-service.js` -31. 新增 `src/types/admin-write-models.js`,库存写接口返回结构已接入共享响应类型 -32. `admin-write-service.js` 的 create / import / release / invalidate 已补返回值 JSDoc -33. `webhook replay` 与 `Agiso 店铺配置保存` 已下沉到 `admin-write-service.js` -34. `webhook-events / platform-config` 写路由已切到 `admin-write-service` -35. `admin-service.js` 删除第二批可独立的写侧实现,并保留兼容导出 -36. `task` 生命周期写操作第一批已下沉到 `admin-write-service.js` -37. `tasks` 管理路由已切换首批 task 写接口到 `admin-write-service` -38. 新增 task 写侧共享响应类型,task action / binding release 已接入 JSDoc -39. `retryAdminTask` 与 `completeAdminTaskManualDispatch` 已下沉到 `admin-write-service.js` -40. `tasks` 管理路由已全部切到 `admin-write-service` 承接 task 写接口 -41. `admin-service.js` 已删除 task 写侧主体实现,仅保留兼容导出 -42. 新增 `admin-platform-config-service.js`,开始承接 platform-config 整块能力 -43. `platform-config` 路由已切换到独立 service,不再经过 `admin-service.js` -44. `admin-service.js` 已删除平台配置相关读写与 helper,实现进一步收敛 -45. 新增 `admin-dashboard-service.js`,后台概览已独立 -46. 新增 `admin-message-delivery-service.js`,消息发送记录查询已独立 -47. `dashboard / message-deliveries` 路由已直接依赖独立 service -48. `admin-service.js` 已收敛为兼容导出层,不再直接承载后台业务实现 -49. 后台读 / 写 / 平台配置 / 概览 / 消息记录已分散到独立 service 模块 -50. 新增 `src/types/admin-route-inputs.js`,开始承接 `admin` 路由层的 query / body / params 共享输入边界 -51. `dashboard / inventory / orders / tasks / platform-config / message-deliveries / webhook-events` 路由已显式接入 `@ts-check` 与共享路由输入类型 -52. `src/routes/admin/shared.js` 已补齐通用 handler 的请求 / 审计签名,`adminSession` 扩展请求字段进入路由层类型检查 -53. 后台 `admin` 路由层首批已纳入 backend `typecheck` 范围,并验证通过 -54. 新增 `src/services/admin/admin-read-shared-helpers.js`,开始承接 viewer / task context / 权限判定 / 订单展示等跨读写共享 helper -55. `admin-read-service / admin-write-service / admin-platform-config-service / admin-service` 已改为优先依赖共享 helper 模块,`admin-read-helpers.js` 职责继续收敛 -56. `npm --prefix apps/backend run typecheck` 已在共享 helper 拆分后继续通过 -57. 新增 `src/services/admin/admin-task-read-helpers.js`,开始承接任务映射、binding summary、任务动作 payload 与订单绑定汇总 -58. `admin-read-service / admin-write-service / admin-service` 已将 task 相关 helper 改为直接依赖独立 task helper 模块 -59. `admin-read-helpers.js` 已进一步收敛到 webhook / inventory / order-list 三类能力 -60. `npm --prefix apps/backend run typecheck` 已在 task helper 拆分后继续通过 -61. `admin-read-helpers.js` 已完成最终拆分,并删除过渡文件 -62. 新增 `src/services/admin/admin-inventory-read-helpers.js`,库存读取映射与必需实体校验已独立 -63. 新增 `src/services/admin/admin-order-read-helpers.js` 与 `src/services/admin/admin-webhook-read-helpers.js`,订单列表汇总与 webhook 事件映射已按领域独立 -64. `admin-read-service / admin-write-service / admin-service` 已全部改为直接依赖 inventory / order / webhook / task / shared 五类 helper,读侧 helper 拆分阶段可以收口 - -## 2026-05-21 执行进展 - -本轮已落地: - -1. 新增 `tsconfig.build.json` -2. `npm run build` 输出 `dist`,并复制数据库 migration SQL -3. `npm run dev` 改为 `tsx watch --clear-screen=false src/index.ts` -4. `npm test` 改为 `node --import tsx --test ...` -5. `npm run db:migrate` 改为 `tsx src/db/migrate.ts` -6. `npm run start` 改为 `node dist/index.js` -7. 生产 Dockerfile 改为 builder 阶段编译,runtime 阶段复制 `dist` -8. 新增 `tsx` 和 `@types/pg` -9. 首批真实源码迁移到 `.ts`: - - `src/db/client.ts` - - `src/utils/time.ts` - - `src/utils/random.ts` - - `src/utils/money.ts` - - `src/utils/json.ts` - - `src/repositories/claim-token-repo.ts` - - `src/repositories/task-event-repo.ts` - - `src/repositories/admin-audit-log-repo.ts` -10. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` -11. `src/types/*.js` 已改写为真正的 `.ts` 类型导出文件,现有 JS JSDoc `import('...js').TypeName` 引用保持可用 -12. 低风险 repository 第二批已迁移到 `.ts`: - - `src/repositories/order-item-repo.ts` - - `src/repositories/message-delivery-repo.ts` - - `src/repositories/webhook-event-repo.ts` -13. `MessageDeliveryRow` 与列表查询结果已进入共享 repository row 类型 -14. 小型 repository 第三批已迁移到 `.ts`: - - `src/repositories/admin-user-repo.ts` - - `src/repositories/product-match-rule-repo.ts` - - `src/repositories/fulfillment-profile-repo.ts` -15. repository 第四批已迁移到 `.ts`: - - `src/repositories/order-repo.ts` - - `src/repositories/task-inventory-binding-repo.ts` -16. 核心库存 repository 已迁移到 `.ts`: - - `src/repositories/inventory-repo.ts` -17. 核心任务 repository 已迁移到 `.ts`: - - `src/repositories/task-repo.ts` -18. `TaskRow` 已补齐任务读取链路实际使用的主表、领取 token、腾讯上下文、库存绑定字段 -19. 核心 repository 迁移阶段已收口,Docker 内 `typecheck / build / test` 继续通过 -20. `runtime.js` 已拆分并迁移到 `.ts`: - - `src/config/runtime.ts` - - `src/config/runtime-env.ts` - - `src/config/runtime-merge.ts` -21. env 文件加载、env 值解析、默认配置加载、深合并逻辑已从 runtime 主入口分离 -22. Docker 内再次验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` -23. 高风险链路补测试: - - webhook 事件入库 payload 可稳定保留原始 headers/query/body,便于后续 replay - - 库存换码在“兑换码已使用且无替换库存”时进入等待库存状态,并记录已使用事件 - - Agiso 自动发货成功标记可从字符串 context 中识别,且会忽略无效 JSON -24. Docker 内验证通过: - - 相关 3 个测试文件共 14 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 125 个用例通过 -25. 服务层首批迁移到 `.ts`: - - `src/services/order/inventory-service.ts` -26. 库存服务的 reserve/release 输入、依赖注入函数、返回库存行已显式类型化 -27. Docker 内验证通过: - - `src/services/order/inventory-service.test.js` 共 5 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 125 个用例通过 -28. claim 换码服务迁移到 `.ts`: - - `src/services/claim/session/redeem.ts` -29. 换码流程的上下文、腾讯兑换返回、分类结果、尝试记录、错误状态、依赖注入函数已显式类型化 -30. Docker 内验证通过: - - claim 换码相关 2 个测试文件共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 125 个用例通过 -31. 订单 upsert 服务迁移到 `.ts`: - - `src/services/order/order-service.ts` -32. 外部订单事件、订单履约商品、订单状态合并结果、upsert 返回结构已显式类型化 -33. Docker 内验证通过: - - 订单 / webhook / open91 相关 3 个测试文件共 15 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 125 个用例通过 -34. 商品匹配服务迁移到 `.ts`: - - `src/services/order/product-match-service.ts` -35. 外部商品 item、匹配候选、解析后的履约商品、店铺候选与配置读取已显式类型化 -36. Docker 内验证通过: - - 商品匹配 / 订单 / webhook / bootstrap 相关 4 个测试文件共 13 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 125 个用例通过 -37. delivery task 服务迁移前补直接测试: - - 新增 `src/services/order/delivery-task-service.test.js` - - 新增 `syncDeliveryTasksForOrderWithDeps`,便于隔离 repository / 库存 / claim token / 通知依赖 - - 覆盖库存不足进入 `waiting_inventory`、人工履约进入 `manual_review`、快手云任务生成 claim token 三个关键分支 -38. Docker 内验证通过: - - `src/services/order/delivery-task-service.test.js` 共 3 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 128 个用例通过 -39. delivery task 服务迁移到 `.ts`: - - `src/services/order/delivery-task-service.ts` -40. 订单行、订单商品、履约 profile / requirement、依赖注入、任务上下文、JSON 配置读取已显式类型化 -41. Docker 内验证通过: - - delivery task / 订单 / webhook / open91 相关 4 个测试文件共 18 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 128 个用例通过 -42. claim 基础服务迁移到 `.ts`: - - `src/services/claim/claim-service.ts` -43. 领取 token 创建与 claim URL 生成已显式类型化,并在 token 写入失败时显式抛错 -44. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 128 个用例通过 -45. Agiso 自动发货服务迁移前补直接测试: - - 新增 `ensureAgisoXianyuAutoDeliveryForDeliveredTaskWithDeps`,便于隔离 task repository、HTTP 请求、发货确认与消息通知依赖 - - 覆盖订单下仍有任务未交付时跳过、配置缺失时记录 `skipped`、接口受理但未确认发货时记录 `failed` 三个关键分支 -46. Docker 内验证通过: - - `src/services/platforms/agiso/xianyu/auto-delivery-service.test.js` 共 9 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 131 个用例通过 -47. Agiso 自动发货服务迁移到 `.ts`: - - `src/services/platforms/agiso/xianyu/auto-delivery-service.ts` -48. 自动发货订单 / 任务形态、依赖注入、HTTP 响应、发货确认结果、上下文落库 payload 已显式类型化 -49. `tsconfig.json` 已将 Agiso 新增 `.ts` 文件纳入 `typecheck`,旧 Agiso `.js` 文件继续暂时排除 -50. Docker 内验证通过: - - `src/services/platforms/agiso/xianyu/auto-delivery-service.test.js` 共 9 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 131 个用例通过 -51. Agiso 消息发送服务迁移到 `.ts`: - - `src/services/platforms/agiso/xianyu/message-service.ts` -52. 消息订单 / 任务、消息配置、模板渲染、去重查询、发送请求、delivery 创建与更新 payload 已显式类型化 -53. Docker 内验证通过: - - `src/services/platforms/agiso/xianyu/message-service.test.js` 共 3 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 131 个用例通过 -54. Agiso 订单详情服务迁移前补直接测试: - - 新增 `src/services/platforms/agiso/xianyu/order-detail-service.test.js` - - 新增 `enrichAgisoXianyuTradeOrderWithDeps` 与 `queryAgisoXianyuOrderDetailWithDeps`,便于隔离订单详情 HTTP 请求 - - 覆盖发货状态识别、详情成功解析、业务失败、缺配置跳过、详情补全 webhook 订单五个关键分支 -55. 修复 Agiso 店铺配置白名单: - - `tradeDetailApiVersion` - - `tradeDetailTimeoutMs` -56. Docker 内验证通过: - - `src/services/platforms/agiso/xianyu/order-detail-service.test.js` 共 5 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 136 个用例通过 -57. Agiso 订单详情服务迁移到 `.ts`: - - `src/services/platforms/agiso/xianyu/order-detail-service.ts` -58. 订单详情补查入参、依赖注入、HTTP 响应、详情查询结果、发货状态、店铺配置、外部 SKU 解析结果已显式类型化 -59. Docker 内验证通过: - - `src/services/platforms/agiso/xianyu/order-detail-service.test.js` 共 5 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 136 个用例通过 -60. Agiso 店铺配置服务迁移到 `.ts`: - - `src/services/platforms/agiso/shop-config-service.ts` -61. Agiso 店铺配置文档、默认消息模板、店铺 token/API 配置、配置 map 归一化结果已显式类型化 -62. Docker 内验证通过: - - Agiso 配置 / 自动发货 / 消息 / 订单详情相关 5 个测试文件共 26 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 136 个用例通过 -63. webhook service 迁移前补编排测试: - - 新增 `executeAgisoTradeWebhookWithDeps`,便于隔离 webhook event repository、商品匹配、订单 upsert 与订单详情补查依赖 - - 覆盖验签失败落错误、未配置商品提前忽略、咸鱼订单补查后 upsert 三个关键分支 -64. Docker 内验证通过: - - `src/services/order/webhook-service.test.js` 共 9 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -65. webhook service 迁移到 `.ts`: - - `src/services/order/webhook-service.ts` -66. webhook 编排依赖注入边界已补最小类型,入口编排、解析、验签、忽略、补查、upsert 逻辑已进入 TypeScript 编译链路 -67. Docker 内验证通过: - - `src/services/order/webhook-service.test.js` 共 9 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -68. Agiso webhook 解析基础模块迁移到 `.ts`: - - `src/services/order/agiso-trade-parsing.ts` -69. Agiso webhook 原始 payload、订单号解析、商品来源数组提取已显式类型化 -70. Docker 内验证通过: - - `src/services/order/agiso-trade-parsing.test.js` 与 `src/services/order/webhook-service.test.js` 共 12 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -71. 腾讯浏览器会话兑换服务迁移到 `.ts`: - - `src/services/session/session-redeem.ts` -72. 会话兑换编排、验证码截图 / OCR payload、页面提交、弹窗结果解析、兑换结果分类已补轻量结构类型;`tsconfig.json` 已将 session 新增 `.ts` 文件纳入 `typecheck`,旧 session `.js` 文件继续暂时排除 -73. Docker 内验证通过: - - `src/services/session/session-redeem.test.js` 共 6 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -74. 腾讯浏览器会话 proof 基础模块迁移到 `.ts`: - - `src/services/session/session-proof-constants.ts` - - `src/services/session/session-proof-paths.ts` - - `src/services/session/session-proof-mode.ts` - - `src/services/session/session-proof-beijing-time.ts` -75. 兑换凭证模式、artifact 路径、北京时间截图浏览器上下文与截图返回值已显式类型化 -76. Docker 内验证通过: - - `src/services/session/session-proof.test.js` 共 4 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -77. 腾讯浏览器会话 proof 渲染 / 结果写入模块迁移到 `.ts`: - - `src/services/session/session-proof-html.ts` - - `src/services/session/session-proof-renderer.ts` - - `src/services/session/session-proof-result-writer.ts` -78. 凭证 HTML 输入、结果 JSON payload、浏览器截图合成上下文、页面弹窗渲染已显式类型化 -79. Docker 内验证通过: - - `src/services/session/session-proof.test.js` 共 4 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -80. 腾讯浏览器会话 proof 总编排迁移到 `.ts`: - - `src/services/session/session-proof.ts` -81. 兑换凭证保存入口、基础 / 完整 proof 分支、北京时间截图降级路径、artifact 返回值已显式类型化 -82. Docker 内验证通过: - - `src/services/session/session-proof.test.js` 共 4 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -83. 腾讯浏览器会话配置 / 状态 / payload 纯逻辑模块迁移到 `.ts`: - - `src/services/session/session-browser-config.ts` - - `src/services/session/session-state.ts` - - `src/services/session/session-payload.ts` -84. 登录类型、浏览器启动参数、默认视口、会话状态 / notice、二维码 TTL、redeem/review/artifact payload 已显式类型化;`buildSessionPayload` 对外暂保留动态返回以兼容仍未迁移的 JS 路由与 session 编排 -85. Docker 内验证通过: - - `src/services/session/session.test.js` 共 14 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -86. 腾讯浏览器会话 cookie / review / 登录共享 / 服务配置模块迁移到 `.ts`: - - `src/services/session/session-cookie-map.ts` - - `src/services/session/session-review.ts` - - `src/services/session/session-login-shared.ts` - - `src/services/session/session-service-config.ts` -87. cookie map、review 签名与截图、二维码下载、frame 等待、浏览器会话配置常量已显式类型化 -88. Docker 内验证通过: - - `src/services/session/session.test.js` 共 14 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -89. 腾讯浏览器会话 OCR / browser runtime 模块迁移到 `.ts`: - - `src/services/session/ocr.ts` - - `src/services/session/session-service-runtime.ts` -90. OCR HTTP payload / 响应、OCR 超时、浏览器预热、Playwright browser promise 生命周期、SessionServiceError 已显式类型化 -91. Docker 内验证通过: - - `src/services/session/session.test.js` 与 `src/services/session/session-redeem.test.js` 共 20 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -92. 腾讯浏览器会话内存 store 模块迁移到 `.ts`: - - `src/services/session/session-service-store.ts` -93. 浏览器会话对象、注册入参、关闭依赖、自动关闭 timer、session 状态持久化 payload 已显式类型化 -94. Docker 内验证通过: - - `src/services/session/session.test.js` 共 14 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -95. 腾讯浏览器会话页面模块迁移到 `.ts`: - - `src/services/session/session-page.ts` -96. 二维码截图重试、登录 tab 切换、host 状态提取、页面刷新、QQ/WX 二维码状态分发已显式类型化 -97. Docker 内验证通过: - - `src/services/session/session.test.js` 共 14 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -98. 腾讯浏览器 QQ 登录模块迁移到 `.ts`: - - `src/services/session/session-qq.ts` -99. QQ 登录 iframe、二维码 URL 提取 / 升级、远程下载 fallback、二维码 locator 与扫码状态已显式类型化 -100. Docker 内验证通过: - - `src/services/session/session.test.js` 共 14 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -101. 腾讯浏览器 WX 登录模块迁移到 `.ts`: - - `src/services/session/session-wx.ts` -102. WX 登录 iframe、快捷登录切换、二维码候选状态、远程下载 fallback、二维码 locator 与扫码状态已显式类型化 -103. Docker 内验证通过: - - `src/services/session/session.test.js` 共 14 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -104. 腾讯浏览器会话 activity 信息模块迁移到 `.ts`: - - `src/services/session/session-activity.ts` -105. 活动角色 / 表单 / 验证码 / 弹窗信息结构、登录态 presentation 同步、角色渲染触发与轮询已显式类型化 -106. Docker 内验证通过: - - `src/services/session/session.test.js` 共 14 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -107. 腾讯浏览器会话主编排迁移到 `.ts`: - - `src/services/session/session.ts` -108. 会话创建 / 刷新 / 重载 / 兑换 / 关闭入口已进入 TS 编译链路,`session-service-store.ts` 补齐主编排所需 browser context、page 与 presentation sync 字段类型 -109. `tsconfig.json` 已移除 `src/services/session/**/*.js` 排除项;除测试文件外,`src/services/session` 服务目录已全量纳入 TS 编译 -110. Docker 内验证通过: - - `src/services/session/session.test.js`、`src/services/session/session-redeem.test.js`、`src/services/session/session-proof.test.js` 共 24 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -111. 领取会话服务入口与分层模块迁移到 `.ts`: - - `src/services/claim/claim-session-service.ts` - - `src/services/claim/session/actions.ts` - - `src/services/claim/session/context.ts` - - `src/services/claim/session/lifecycle.ts` - - `src/services/claim/session/runtime.ts` - - `src/services/claim/session/shared.ts` -112. 领取上下文、会话生命周期、任务同步、角色确认、兑换入口与领取详情 payload 已进入 TS 编译链路;`lifecycle/runtime` 补齐动态 payload / patch 对象类型 -113. Docker 内验证通过: - - `src/services/claim/claim-session-service.test.js` 共 2 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -114. 快手 Cloud 领取页动作与轮询同步模块迁移到 `.ts`: - - `src/services/claim/kuaishou-cloud-claim-service.ts` - - `src/services/claim/kuaishou-cloud-sync-service.ts` -115. 快手 Cloud 核销码校验、指引图片路径、角色确认、领取页兑换触发与领取页轮询补同步已进入 TS 编译链路;核销 payload 补齐动态对象类型 -116. Docker 内验证通过: - - `src/services/claim/claim-session-service.test.js` 共 2 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -117. 订单履约配置模块迁移到 `.ts`: - - `src/services/order/fulfillment-binding-config-service.ts` - - `src/services/order/kuaishou-cloud-fulfillment-config-service.ts` -118. 订单履约绑定过滤、快手 Cloud 配置读取 / 保存 / 映射到履约绑定已进入 TS 编译链路;默认动态配置对象补齐类型 -119. Docker 内验证通过: - - `src/services/order/fulfillment-binding-config-service.test.js`、`src/services/order/kuaishou-cloud-fulfillment-config-service.test.js` 共 3 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -120. 后端 HTTP / 日志工具迁移到 `.ts`: - - `src/utils/http.ts` - - `src/utils/logger.ts` -121. 路由响应 payload、HTTP 错误分类 / 扩展字段、日志级别 / 文件名 / 过期清理 / 错误序列化已进入 TS 编译链路;`HttpErrorLike` 改为显式导出类型,logger 使用 type-only import 避免运行时循环依赖 -122. Docker 内验证通过: - - `src/utils/logger.test.js` 共 7 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -123. 91卡券 Open API 共享模块迁移到 `.ts`: - - `src/services/open-91/shared.ts` -124. 91 卡券配置读取、请求归一化、签名 / 验签、cards AES 加密、卡密响应构造与查询状态解析已进入 TS 编译链路;动态配置与请求 payload 补齐对象类型 -125. Docker 内验证通过: - - `src/services/open-91/shared.test.js` 共 6 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -126. 91卡券 Open API 下单 / 查询入口迁移到 `.ts`: - - `src/services/open-91/order-create-service.ts` - - `src/services/open-91/order-query-service.ts` -127. 91 卡券创建订单、待补配置队列、订单查询、领取链接 cards 生成与查询日志已进入 TS 编译链路 -128. Docker 内验证通过: - - `src/services/open-91/shared.test.js` 共 6 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -129. 91卡券平台订单服务迁移到 `.ts`: - - `src/services/platforms/ninetyone/order-service.ts` -130. 91 卡券 source event 构造、待补配置订单落库、后台重试 / 手动失败、后台订单列表映射已进入 TS 编译链路;动态 payload / config 与 SQL 参数数组补齐类型 -131. Docker 内验证通过: - - `src/services/platforms/ninetyone/order-service.test.js`、`src/services/open-91/shared.test.js` 共 7 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -132. 履约目录初始化服务迁移到 `.ts`: - - `src/services/bootstrap/fulfillment-bootstrap-service.ts` -133. 核心履约 profile 初始化、配置绑定同步、SKU 绑定与商品匹配规则重建已进入 TS 编译链路;profileMap、binding 与运行时 config 补齐动态对象类型 -134. Docker 内验证通过: - - `src/services/bootstrap/fulfillment-bootstrap-service.test.js` 共 2 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -135. 后台平台配置底座模块迁移到 `.ts`: - - `src/services/admin/platform-config/context.ts` - - `src/services/admin/platform-config/domain.ts` - - `src/services/admin/platform-config/mappers.ts` - - `src/services/admin/platform-config/validation.ts` -136. 后台平台配置上下文解析、展示映射、敏感信息脱敏、履约绑定校验与重复规则检测已进入 TS 编译链路;动态配置对象补齐通用类型,`isPlainObject` 改为类型守卫 -137. Docker 内验证通过: - - `src/services/admin/platform-config/context.test.js`、`domain.test.js`、`mappers.test.js`、`validation.test.js` 共 23 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -138. 后台平台配置观察 / 查询 / 写入辅助模块迁移到 `.ts`: - - `src/services/admin/platform-config/observed-products.ts` - - `src/services/admin/platform-config/fulfillment.ts` - - `src/services/admin/platform-config/writes.ts` -139. 后台观察商品列表、履约手动查询结果组装、Agiso 店铺消息配置写入与 Cloudtentacles 来源配置归一化已进入 TS 编译链路;查询依赖、payload 与配置 map 补齐动态对象类型 -140. Docker 内验证通过: - - `src/services/admin/platform-config/observed-products.test.js`、`fulfillment.test.js`、`writes.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -141. 后台 Cloudtentacles 配置展示模块迁移到 `.ts`: - - `src/services/admin/platform-config/cloudtentacles.ts` -142. Cloudtentacles 凭据 payload、会话 payload、持久化 session、登录 / 校验响应摘要已进入 TS 编译链路;来源、会话与响应对象补齐动态类型 -143. Docker 内验证通过: - - `src/services/admin/platform-config/cloudtentacles.test.js` 共 6 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -144. 后台平台配置薄服务包装层迁移到 `.ts`: - - `src/services/admin/platform-config/agiso-service.ts` - - `src/services/admin/platform-config/kuaishou-eticket-service.ts` - - `src/services/admin/platform-config/kuaishou-cloud-fulfillment-service.ts` - - `src/services/admin/platform-config/ninetyone-service.ts` -145. Agiso 店铺配置、快手电子券配置 / 查询 / 核销、快手 Cloud 履约配置、91 卡券后台订单操作入口已进入 TS 编译链路;payload / query 补齐动态对象类型 -146. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -147. 后台平台配置聚合入口、履约绑定服务、通知 / 定时任务服务迁移到 `.ts`: - - `src/services/admin/platform-config/service.ts` - - `src/services/admin/platform-config/fulfillment-bindings-service.ts` - - `src/services/admin/platform-config/notification-service.ts` -148. 旧履约绑定读写 / 手动订单查询、通知配置更新、测试通知、定时任务运行入口已进入 TS 编译链路;写入 payload、查询 payload、动态配置 map 与 jobId 补齐类型 -149. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -150. 后台 Cloudtentacles 配置编排服务迁移到 `.ts`: - - `src/services/admin/platform-config/cloudtentacles-service.ts` -151. Cloudtentacles 来源列表 / 批量保存 / 单来源保存 / 删除、短信登录、会话校验、商品目录、背包、虚拟号、完整调试流程后台入口已进入 TS 编译链路;各入口 payload 与 session map 补齐类型 -152. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -153. Cloudtentacles 平台底座模块迁移到 `.ts`: - - `src/services/platforms/cloudtentacles/shared.ts` - - `src/services/platforms/cloudtentacles/source-config-service.ts` - - `src/services/platforms/cloudtentacles/session-state-service.ts` - - `src/services/platforms/cloudtentacles/crypto-service.ts` -154. Cloudtentacles 运行时配置解析、URL / headers 构造、来源配置读写、会话状态读写、RSA 加密入口已进入 TS 编译链路;动态配置、会话 map、加密 payload 与 header map 补齐类型 -155. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -156. Cloudtentacles 平台 HTTP / 商品目录 / 背包 / 会话模块迁移到 `.ts`: - - `src/services/platforms/cloudtentacles/http-client.ts` - - `src/services/platforms/cloudtentacles/catalog-service.ts` - - `src/services/platforms/cloudtentacles/knapsack-service.ts` - - `src/services/platforms/cloudtentacles/session-service.ts` -157. Cloudtentacles Node HTTP 请求封装、业务错误通知、资产 / 分类 / SKU 查询、SKU 购买 / 发货、背包查询、短信验证码、登录与会话校验已进入 TS 编译链路;请求 options、HTTP response、payload 和返回数据映射补齐类型 -158. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -159. Cloudtentacles 完整调试流程服务迁移到 `.ts`: - - `src/services/platforms/cloudtentacles/debug-flow-service.ts` -160. Cloudtentacles 余额 / SKU / 背包校验、购买、申请虚拟号、生成登录码、获取验证码、校验验证码、获取兑换链接的后台调试串联流程已进入 TS 编译链路;流程 payload、步骤 runner、重试 options、错误包装补齐类型 -161. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -162. Cloudtentacles 虚拟号服务迁移到 `.ts`: - - `src/services/platforms/cloudtentacles/virtual-number-service.ts` -163. Cloudtentacles 虚拟号列表、申请、生成登录码、获取验证码、校验验证码、兑换链接、绑定信息、退还号码、AMS 兑换链接探测已进入 TS 编译链路;虚拟号 payload、AMS 签名参数、探测 response、header adapter 与动态响应对象补齐类型 -164. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -165. 通知服务模块迁移到 `.ts`: - - `src/services/notification/config-service.ts` - - `src/services/notification/bark-service.ts` - - `src/services/notification/notification-service.ts` - - `src/services/notification/domain-notifications.ts` -166. Bark 通知发送、通知配置读写、内部通知分发、业务域告警与冷却控制已进入 TS 编译链路;Bark input、通知 payload、接收人配置、错误上下文与冷却 map 补齐类型 -167. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -168. Scheduler 定时任务模块迁移到 `.ts`: - - `src/services/scheduler/config-service.ts` - - `src/services/scheduler/scheduler-service.ts` - - `src/services/scheduler/cloudtentacles-health-job.ts` -169. 定时任务配置归一化、运行态缓存、立即执行、重载调度、Cloudtentacles 余额健康检查与告警已进入 TS 编译链路;job 配置、timer map、runtime state、健康检查 payload 补齐类型 -170. Docker 内验证通过: - - `src/services/admin/platform-config/*.test.js` 共 37 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -171. 快手 Cloud 核心履约任务服务迁移到 `.ts`: - - `src/services/fulfillment/kuaishou-cloud-task-service.ts` -172. 快手 Cloud 绑定准备、过期链接刷新、绑定链接探测、角色信息刷新、cloudtentacles 发货、退还虚拟号、快手电子券核销、履约 flow 归一化与敏感信息脱敏已进入 TS 编译链路;入口 options、失败标记 input 与虚拟号准备 input 补齐动态对象类型 -173. Docker 内验证通过: - - `src/services/order/kuaishou-cloud-fulfillment-config-service.test.js` 相关用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -174. 后台 Admin 查询 / 审计 / 仪表盘 / 消息投递 / 写入口迁移到 `.ts`: - - `src/services/admin/admin-query-utils.ts` - - `src/services/admin/admin-audit-service.ts` - - `src/services/admin/admin-dashboard-service.ts` - - `src/services/admin/admin-message-delivery-service.ts` - - `src/services/admin/admin-write-service.ts` -175. Admin 分页与日期查询归一化、审计日志写入 / 查询、仪表盘汇总、消息投递列表、后台写操作聚合入口已进入 TS 编译链路;query、session、payload、映射 row 补齐动态对象类型 -176. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -177. 后台 Admin 读侧聚合与订单 / 库存 / Webhook 映射 helper 迁移到 `.ts`: - - `src/services/admin/admin-inventory-read-helpers.ts` - - `src/services/admin/admin-order-read-helpers.ts` - - `src/services/admin/admin-webhook-read-helpers.ts` - - `src/services/admin/admin-service.ts` -178. Admin 库存占用任务映射、订单商品摘要、Webhook 原始 payload 展开与后台服务聚合出口已进入 TS 编译链路;列表 row、Webhook options、动态 JSON record 与导出入口补齐类型 -179. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -180. 后台 Admin 写侧共享 helper 与 Webhook 重放入口迁移到 `.ts`: - - `src/services/admin/write/shared.ts` - - `src/services/admin/write/webhook-events.ts` -181. Admin 脱敏、任务库存组解析、辅助领取权限校验、任务 claim 链接补齐、手动发货结果归一化、Webhook 重放入口已进入 TS 编译链路;任务 row、viewer context、错误对象、entity id 与重放响应补齐类型 -182. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -183. 后台 Admin 库存写操作迁移到 `.ts`: - - `src/services/admin/write/inventory.ts` -184. Admin 库存新增、批量导入、释放预占库存、作废库存与导入行去重已进入 TS 编译链路;创建 / 导入 / 作废输入、entity id、mutation response、导入行规范化结果与库存 row 补齐类型 -185. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -186. 后台 Admin 读侧共享上下文 / 权限 helper 迁移到 `.ts`: - - `src/services/admin/admin-read-shared-helpers.ts` - - `src/services/admin/write/shared.ts` -187. Admin viewer context、敏感信息可见性、任务上下文解析、订单商品标题 / 发货模式解析、辅助领取权限判断、库存组访问控制与兑换 resolution 映射已进入 TS 编译链路;任务 row、订单商品 row、session input、动态 JSON record 与 viewer context 补齐类型,并让写侧 helper 复用共享 viewer context 类型 -188. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -189. 后台 Admin 任务读侧映射 helper 迁移到 `.ts`: - - `src/services/admin/admin-task-read-helpers.ts` -190. Admin 任务摘要 / 列表项 / 操作 payload、任务事件、任务库存绑定、任务绑定汇总 map、订单绑定状态汇总与 Agiso 自动发货订单摘要已进入 TS 编译链路;任务 row、绑定 row、事件 row、viewer context、绑定 summary、自动发货 summary 与动态 metadata 补齐类型 -191. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -192. 后台 Admin 读服务聚合入口迁移到 `.ts`: - - `src/services/admin/admin-read-service.ts` -193. Admin 订单列表 / 详情、任务列表 / 详情 / 截图、库存列表 / SKU 建议、Webhook 列表 / 详情聚合入口已进入 TS 编译链路;列表 query、viewer session、entity id、分页响应模型与详情动态聚合对象补齐类型 -194. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -195. 后台 Admin 任务写操作迁移到 `.ts`: - - `src/services/admin/write/task-actions.ts` -196. Admin 任务库存释放、绑定释放、领取链接重建、半自动确认 / 兑换、关闭任务、转人工复核、重试、人工履约回写已进入 TS 编译链路;entity id、viewer session、手动履约 input、action response、binding release response、依赖注入 close deps 与 task patch 补齐类型 -197. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -198. 后台 Admin 快手 Cloud 写侧 helper / actions 迁移到 `.ts`: - - `src/services/admin/write/kuaishou-cloud-helpers.ts` - - `src/services/admin/write/kuaishou-cloud-actions.ts` -199. 快手 Cloud flow 规范化、SKU / 背包资源匹配、VN Key 候选、绑定资源准备与回滚、准备绑定、发货、刷新角色、退号和快手核销动作已进入 TS 编译链路;cloud context、flow、SKU-like item、binding resources、prepared bind resource、dispatch input 与 action response 补齐类型 -200. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -201. 后台 Admin 鉴权与人工兑换服务迁移到 `.ts`: - - `src/services/admin/admin-auth-service.ts` - - `src/services/admin/admin-manual-redeem-service.ts` -202. 后台默认用户初始化、登录 / session token 验证、用户管理、角色 / 状态归一化、人工兑换任务创建、人工兑换 claim session 包装、确认角色 / 兑换 / 关闭操作已进入 TS 编译链路;admin user row、session、role/status、manual redeem input、entity id、viewer session 与动态详情响应补齐类型 -203. Docker 内验证通过: - - `src/services/admin/*.test.js` 共 8 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -204. `src/services/admin` 目录下非测试 `.js` 服务文件已全部迁移为 `.ts` -205. 快手电子券平台服务迁移到 `.ts`: - - `src/services/platforms/kuaishou-eticket/shared.ts` - - `src/services/platforms/kuaishou-eticket/http-client.ts` - - `src/services/platforms/kuaishou-eticket/source-config-service.ts` - - `src/services/platforms/kuaishou-eticket/info-service.ts` - - `src/services/platforms/kuaishou-eticket/consume-service.ts` -206. 快手小店核销配置、Node HTTP 请求、店铺来源配置读写、店铺稳定信息查询、电子券详情查询与核销 payload / result 映射已进入 TS 编译链路;config、headers、HTTP response、source/shop config、detail result 与动态 payload 补齐类型 -207. Docker 内验证通过: - - `src/services/platforms/kuaishou-eticket/*.test.js` 共 4 个用例通过 - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -208. `src/services` 目录下非测试 `.js` 服务文件已全部迁移为 `.ts` -209. 第一批后台 Admin 路由迁移到 `.ts`: - - `src/routes/admin/shared.ts` - - `src/routes/admin/auth.ts` - - `src/routes/admin/dashboard.ts` - - `src/routes/admin/users.ts` -210. 后台 JSON / 文件 handler、session 鉴权中间件、角色中间件、登录 / session / logout、概览摘要和后台用户管理路由已进入 TS 编译链路;Admin session、route request、审计 payload、用户 mutation result 与 handler options 补齐类型,并导出真实 `AdminSession` 给路由层复用 -211. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -212. 第二批后台 Admin 读侧 / 库存路由迁移到 `.ts`: - - `src/routes/admin/orders.ts` - - `src/routes/admin/inventory.ts` - - `src/routes/admin/message-deliveries.ts` - - `src/routes/admin/webhook-events.ts` - - `src/routes/admin/audit-logs.ts` -213. 后台订单列表 / 详情、库存列表 / SKU 建议 / 写操作、消息发送记录、Webhook 事件列表 / 详情 / 重放、审计日志路由已进入 TS 编译链路;route query、params、body、库存 mutation response 与 webhook replay response 补齐类型,审计 payload 缩进同步整理 -214. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -215. 后台人工兑换路由迁移到 `.ts`: - - `src/routes/admin/manual-redeem.ts` -216. 人工兑换 SKU 建议、任务创建 / 详情、登录会话创建 / 摘要 / 刷新 / 关闭、确认角色、启动兑换和关闭任务路由已进入 TS 编译链路;route query、params、body、session body 与人工兑换 mutation audit result 补齐类型 -217. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -218. 后台任务管理路由迁移到 `.ts`: - - `src/routes/admin/tasks.ts` -219. 后台任务列表 / 详情 / 截图、重试、库存释放、绑定释放、领取链接重建、客服确认 / 兑换、关闭、转人工、人工履约回写、快手 Cloud 准备 / 刷新角色 / 发货 / 退号路由已进入 TS 编译链路;route query、params、manual dispatch body、kuaishou cloud dispatch body、task action response、binding release response 与 manual dispatch response 补齐类型,并收敛 taskId / bindingId 解析 helper -220. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -221. 后台平台配置路由迁移到 `.ts`: - - `src/routes/admin/platform-config.ts` -222. Agiso 店铺、通知、定时任务、快手电子券、91 卡券订单、cloudtentacles 来源 / 登录 / 商品 / 背包 / 虚拟号 / debug flow、履约绑定和快手 Cloud 履约配置路由已进入 TS 编译链路;route body / params、Agiso 保存响应和审计动态结果补齐类型,并移除旧 JSDoc cast -223. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -224. `src/routes/admin` 目录下非测试 `.js` 路由文件已全部迁移为 `.ts` -225. 外层 API 路由迁移到 `.ts`: - - `src/routes/admin.ts` - - `src/routes/claims.ts` - - `src/routes/open-91.ts` - - `src/routes/tencent.ts` - - `src/routes/webhooks.ts` -226. Admin 聚合路由、领取页 / 快手 Cloud 领取动作、91 卡券开放接口、腾讯浏览器会话接口和 Agiso webhook 入口已进入 TS 编译链路;现阶段保持路由编排行为不变,依赖已迁移服务层类型进行约束 -227. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -228. `src/routes` 目录下非测试 `.js` 路由文件已全部迁移为 `.ts` -229. 后端入口与数据库迁移脚本迁移到 `.ts`: - - `src/index.ts` - - `src/db/migrate.ts` -230. `package.json` 源码运行脚本切到 `.ts` 入口:`dev`、`start:src` 和 `db:migrate`;依赖源码 TS 的开发脚本 `seed:dev-data`、`cleanup:dev-data`、`agiso:auto-delivery:test` 改由 `tsx` 执行,避免 plain node 直接加载源码 TS 失败 -231. 入口启动、健康检查、核心 bootstrap、browser / OCR 预热、优雅关闭、进程异常记录和 migration CLI 已进入 TS 编译链路;logger 的 detail 参数补齐可省略签名,HTTP server close promise 补齐 `Promise` -232. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -233. `apps/backend/src` 目录下非测试 `.js` 文件已全部迁移为 `.ts` -234. 后端开发脚本迁移到 `.ts`: - - `scripts/cleanup-dev-data.ts` - - `scripts/seed-dev-data.ts` - - `scripts/test-agiso-auto-delivery.ts` -235. `package.json` 中 `cleanup:dev-data`、`seed:dev-data`、`agiso:auto-delivery:test` 已指向 `.ts` 脚本;脚本帮助文案同步改为 npm script 形式 -236. Docker 内验证通过: - - `npm run cleanup:dev-data -- --help` - - `npm run seed:dev-data -- --help` - - `npm run agiso:auto-delivery:test -- --help` - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -237. 除 `dist`、`node_modules` 和测试文件外,`apps/backend` 目录下非测试 `.js` 文件已全部迁移为 `.ts` -238. 后端测试文件迁移到 `.test.ts`: - - `src/**/*.test.ts` 共 33 个测试文件 -239. `npm test` 改为同时查找 `.test.ts` / `.test.js`,`tsconfig.json` 与 `tsconfig.build.json` 排除 `.test.ts`,避免测试 mock 数据被生产编译约束 -240. Docker 内验证通过: - - `npm run typecheck` - - `npm run build` - - `npm test` 共 139 个用例通过 -241. 除 `dist` 和 `node_modules` 外,`apps/backend` 目录下 `.js` 文件已全部迁移完成 - -## 下一步建议 - -第一批继续推进时,建议按这个顺序: - -1. 继续迁移服务层中最核心、最常改的订单 / 履约 / claim 模块 -2. 逐步移除服务层 `@ts-nocheck`,优先处理 webhook service、自动发货 - -## 执行原则 - -- 不为迁移而迁移,优先迁移最常改、最容易改坏的链路 -- 不追求一口气全量改 `.ts` -- 优先建立“新代码进入类型系统”的机制 -- 每一步都要求可回滚、可验证、不中断现有开发流 diff --git a/docs/cloudflared_tunnel.txt b/docs/cloudflared_tunnel.txt deleted file mode 100644 index 348134b4..00000000 --- a/docs/cloudflared_tunnel.txt +++ /dev/null @@ -1,63 +0,0 @@ - -最快解决(强制使用 HTTP/2 协议)防止clash干扰 -cloudflared tunnel --protocol http2 run --url http://localhost:80 mac-mini-tunnel - - - -cloudflared tunnel create mac-mini-tunnel - -yml@ymlMacBook-Air ~ % cloudflared tunnel create mac-mini-tunnel -Tunnel credentials written to /Users/yml/.cloudflared/562f9639-71f2-44e0-a5ef-b34bd4e215e5.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel. - -Created tunnel mac-mini-tunnel with id 562f9639-71f2-44e0-a5ef-b34bd4e215e5 -yml@ymlMacBook-Air ~ % - - -221329.cc.cd - -4. # 例子:把 web.yourdomain.com 指向刚才创建的隧道 -cloudflared tunnel route dns mac-mini-tunnel 221329.cc.cd - - -5. 启动隧道(临时/测试) -如果你只是临时跑一个服务(比如你 OrbStack 里的容器映射到了本地 80 端口): - -cloudflared tunnel run --url http://localhost:80 mac-mini-tunnel - ------ -如果两台电脑**不会同时运行**(例如一台是公司的 iMac,一台是家里的 MacBook),那么处理起来就简单得多了。 - -在这种情况下,你可以直接采用 **“共用同一个 Tunnel ID”** 的方案。这在 Cloudflare 的术语中叫做多副本(Replicas),虽然你不是为了负载均衡,但它能完美解决你的需求。 - -### 实现方案:共用 Tunnel -你只需要确保两台电脑拥有完全一致的“身份令牌”和“配置文件”。 - -1. **迁移证书与密钥:** - * 在第一台电脑(已配置好)上,找到这两个文件: - * `~/.cloudflared/cert.pem`(登录证书) - * `~/.cloudflared/.json`(隧道的身份密钥) - * 将它们拷贝到第二台电脑的 `~/.cloudflared/` 目录下。 - -2. **同步配置文件:** - * 将 `config.yml` 也拷贝过去。 - * **注意:** 确保两台电脑上运行的本地服务端口是一致的(比如都是 `localhost:8080`)。 - -3. **直接运行:** - * 在任意一台电脑上运行 `cloudflared tunnel run <隧道名>` 即可。 - ---- - -### 这样做的优势 -* **域名无缝切换:** 你不需要在 Cloudflare 后台修改任何 DNS 记录。只要其中一台电脑开启了隧道,`example.yourdomain.com` 就会立即指向那台电脑。 -* **无需重复配置:** 所有的路由规则(Ingress rules)都是一致的,维护起来非常省心。 - -### 注意事项 -* **如果真的“不小心”同时运行了:** - Cloudflare 会把它们当成一个隧道的两个节点。流量会以类似“轮询”的方式随机分配到两台电脑上。如果这时你的两台电脑跑的服务内容不一样,访问者可能会看到一会儿是 A 电脑的内容,一会儿是 B 电脑的内容。 -* **路径一致性:** - 在 `config.yml` 中,`credentials-file` 的路径如果写的是绝对路径(如 `/Users/jack/...`),请确保两台电脑的用户名一致;如果不一致,记得修改配置文件里的路径。 - ---- - -**总结:** -既然不同时运行,那就把第二台电脑伪装成第一台电脑的“克隆体”。只需拷贝那几个关键文件,你就能实现在家、在公司用同一个域名访问不同的机器了。 \ No newline at end of file diff --git a/docs/cloudtentacles发货平台接入设计.md b/docs/cloudtentacles发货平台接入设计.md deleted file mode 100644 index 6abbdbee..00000000 --- a/docs/cloudtentacles发货平台接入设计.md +++ /dev/null @@ -1,733 +0,0 @@ -# cloudtentacles 外部履约平台接入设计 - -## 1. 背景 - -当前项目里现有链路大致分两层: - -- **订单来源层** - - `agiso`:Webhook 推送型; - - `91卡券`:开放接口下单型。 -- **履约执行层** - - 当前以内置人工发货、腾讯领取兑换等执行器为主。 - -现在新增一个发货相关的平台,当前已知入口为: - -- `https://123.207.217.176` -- 前端资源来自 `gp.playinjoy.com` -- 前端代码里根实例名显示为 `cloudtentacles` - -这个平台**不是订单数据源**,而是**订单创建后用于执行发货/兑换的外部履约平台**。 -它和订单来源平台的系统角色完全不同: - -- `91卡券`:订单来源 / 上游平台; -- `cloudtentacles`:履约执行 / 下游发货平台。 - -它的登录链路独立于订单来源: - -- 不是图片验证码识别; -- 是“账号 + 密码 + 手机号 + 短信验证码”登录; -- 登录参数不是明文提交,而是前端先做 `MD5 + RSA-OAEP(SHA-256)` 加密; -- 登录成功后不是 Cookie 会话,而是返回 `token`,后续通过 `Authorization` 请求头访问接口。 - -因此它应当作为**履约执行器能力**接入,不要按“来源平台”建模。 - ---- - -## 2. 当前已确认事实 - -### 2.1 证据来源 - -- HAR:`/Users/yml/Desktop/抓包/123.207.217.176.har` -- 前端代码:`tems/test1.js` -- 打包代码:`tems/index.93fe093c.js` - -### 2.2 已确认接口链路 - -1. 发送短信验证码 - `POST https://123.207.217.176/public/verif_code` - -2. 提交登录 - `POST https://123.207.217.176/public/login` - -3. 登录后探活接口 - - `POST /user/info` - - `GET /user/get_asset` - - `GET /user/get_permission` - -4. 当前 HAR 里还看到的业务接口 - - `GET /categories/get` - - `GET /sku/list` - -### 2.3 登录态机制 - -不是依赖 Cookie。 - -前端在登录成功后会把 `/public/login` 返回的 `data` 当成 token 保存,并在后续请求里自动带上: - -```http -Authorization: -deviceid: - -devicetype: 0 -``` - -### 2.4 登录参数的真实结构 - -根据 `tems/test1.js`,发验证码与登录都不是直接提交原始字段,而是先调用 `encryptWithPublicKey(...)`。 - -#### 发验证码原始参数 - -```js -{ - account: username, - phone: phone -} -``` - -#### 登录原始参数 - -```js -{ - account: username, - password: MD5(password), - phone: phone, - code: smsCode -} -``` - -#### 加密前最终明文 - -```js -{ - t: Date.now(), - r: Math.random().toString(16), - s: 'ct-client', - ...payload -} -``` - -然后: - -1. `JSON.stringify` -2. 使用 RSA-OAEP + SHA-256 公钥加密 -3. Base64 编码,作为 `covert` - -最终请求体: - -```json -{ - "covert": "", - "t": 1777726021956, - "r": "0.8601863c152d6" -} -``` - -### 2.5 密码处理 - -密码不是明文传输。 - -前端代码中: - -```js -password: cu(password) -``` - -而 `cu` 实际是: - -```js -MD5(password).toString(Hex) -``` - -即: - -- 先 `MD5` -- 再参与 RSA 加密 - ---- - -## 3. 设计目标 - -## 3.1 第一阶段目标 - -这一版只做“基础登录能力”,不直接做完整发货自动化: - -1. 能发送短信验证码; -2. 能使用账号、密码、手机号、短信验证码自动登录; -3. 能持久化保存该平台的履约配置; -4. 能在后台手动测试登录; -5. 能在登录后调用一个轻量探活接口确认登录成功; -6. 输出统一的会话对象,给后续“SKU 查询 / 背包读取 / 发货执行”复用。 - -## 3.2 第二阶段目标 - -后续逐步补: - -1. token 缓存与自动续登; -2. SKU/分类/背包读取; -3. 发货动作封装; -4. 发货结果记录与截图/证据保存; -5. 接成新的 `executor_key`,纳入现有履约任务执行链路; -6. 由“订单支付成功 / 任务就绪”触发自动发货。 - ---- - -## 4. 关键设计决策 - -## 4.1 领域定位 - -这里不应该新增 `provider = 'cloudtentacles'` 作为订单来源标识。 - -更合理的定位是: - -- 订单来源 `provider/platform/shopId` 仍然来自 `agiso` / `91卡券` -- `cloudtentacles` 属于**履约执行器 / 外部发货平台** - -因此它更适合进入这条链路: - -- `fulfillment_profiles.profile_key` -- `fulfillment_profiles.executor_key` -- 任务执行服务 - -建议后续新增类似: - -- `profileKey = 'cloudtentacles_dispatch'` -- `executorKey = 'cloudtentacles_dispatch'` - -而不是把它混进订单来源层。 - -## 4.2 接入模式 - -这个平台本质上是 **外部履约平台 + token 会话** 模式。 - -因此结构上可以先放在 `platforms/` 下管理其登录与 API 封装,但业务接入点要落到**履约执行层**: - -- 配置服务 -- 加密服务 -- HTTP 客户端 -- 登录/会话服务 -- 发货业务服务 -- 履约执行适配层 - -## 4.3 不建议照搬来源平台的原因 - -历史拉单平台链路核心是: - -- 打开登录页 -- 拉验证码图片 -- OCR -- 表单提交 -- Cookie 维持会话 - -而当前平台核心是: - -- 组装明文 -- MD5 密码 -- RSA 公钥加密 -- 请求登录接口 -- token 维持会话 - -所以如果把所有逻辑都塞进一个 `session-service.js`,后面会越来越乱。 -更合理的方式是把“加密”、“请求头”、“token 管理”单独拆开。 - -## 4.4 第一版不引入浏览器自动化 - -当前证据显示不需要浏览器: - -- HAR 中登录接口是纯 XHR; -- 参数生成逻辑已经从 JS 中还原; -- token 机制清晰; -- 没看到依赖浏览器页面上下文的动态签名。 - -因此第一版应坚持 **纯 HTTP 实现**。 - -只有后续遇到这些问题时,才考虑浏览器方案: - -- 服务端增加不可还原的前端签名; -- 短信验证码流程强依赖页面态; -- 登录成功但服务端对业务接口做浏览器环境校验。 - ---- - -## 5. 推荐目录结构 - -建议新增目录: - -`apps/backend/src/services/platforms/cloudtentacles/` - -同时第二阶段补一个执行适配入口,例如: - -`apps/backend/src/services/fulfillment/cloudtentacles-dispatch-service.js` - -### 5.1 第一阶段实际落地文件 - -#### `shared.js` - -职责: - -- 读取运行时配置; -- 规范化 baseUrl / 路径 / timeout; -- 构建 URL; -- 构建公共请求头; -- 统一设备头默认值。 - -建议内容: - -- `resolveCloudtentaclesConfig(overrides)` -- `buildCloudtentaclesUrl(baseUrl, pathname, searchParams?)` -- `buildCloudtentaclesHeaders({ token?, contentType? })` - -#### `crypto-service.js` - -职责: - -- 密码 MD5; -- 公钥 PEM 转 ArrayBuffer / Buffer; -- 组装 `t/r/s` 明文; -- 执行 RSA-OAEP(SHA-256) 加密; -- 返回 `{ covert, t, r }` - -建议暴露: - -- `md5CloudtentaclesPassword(password)` -- `encryptCloudtentaclesPayload(payload, options?)` - -这样后续不仅登录能用,发验证码、改密等其它加密接口也都能复用。 - -#### `http-client.js` - -职责: - -- 对 `fetch` 做一层轻封装; -- 统一 timeout; -- 自动带 `Authorization / deviceid / devicetype`; -- 统一解析平台响应格式; -- 统一抛出带平台上下文的错误。 - -建议暴露: - -- `cloudtentaclesRequest(path, options)` - -注意:第一版不用做成全局通用 HTTP 框架,只服务这个平台即可。 - -#### `session-service.js` - -职责: - -- 发送短信验证码; -- 使用短信验证码登录; -- 登录后调用 `/user/info` 验证会话; -- 返回标准会话对象。 - -建议暴露: - -- `sendCloudtentaclesSmsCode(payload)` -- `loginCloudtentaclesSession(payload)` -- `validateCloudtentaclesSession(payload)` - -建议会话对象: - -```js -{ - baseUrl, - token, - loggedInAt, - username, - phone, - userInfo, - permissions -} -``` - -#### `source-config-service.js` - -职责: - -- 读写履约平台配置文件; -- 管理默认账号、密码、手机号; -- 管理后续自动化开关预留字段。 - -建议文件: - -`apps/backend/data/cloudtentacles-sources.json` - -建议结构: - -```json -{ - "enabled": true, - "baseUrl": "https://123.207.217.176", - "username": "", - "password": "", - "phone": "", - "deviceId": "-", - "deviceType": 0 -} -``` - -### 5.2 第二阶段预留文件 - -这些先不一定创建实现,但目录命名先按这个方向约束: - -#### `catalog-service.js` - -- 分类 -- SKU -- 背包 -- 库存类读取 - -#### `delivery-service.js` - -- 发货动作 -- CDK / 虚拟物品使用 -- 回滚 / 失败重试 - -#### `record-service.js` - -- 交易记录 -- 发货记录 -- 订单对账 - -#### `auto-sync-service.js` - -- 定时探活 -- 自动续登 -- 预热会话 - -#### `apps/backend/src/services/fulfillment/cloudtentacles-dispatch-service.js` - -职责: - -- 接收履约任务; -- 读取任务绑定的库存 / 凭据; -- 调用 `platforms/cloudtentacles/*` 完成实际发货; -- 回写任务状态、发货结果、证据。 - ---- - -## 6. 配置设计 - -## 6.1 运行时配置 - -建议在: - -- `apps/backend/src/config/defaults.ts` -- `apps/backend/src/types/runtime-config.js` -- `apps/backend/src/config/runtime.js` - -增加: - -```js -platforms: { - cloudtentacles: { - baseUrl: 'https://123.207.217.176', - timeoutMs: 5000, - sendSmsPath: '/public/verif_code', - loginPath: '/public/login', - userInfoPath: '/user/info', - assetPath: '/user/get_asset', - permissionPath: '/user/get_permission', - publicKeyPem: '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----', - clientSource: 'ct-client', - deviceId: '-', - deviceType: 0, - }, -} -``` - -### 设计说明 - -- `publicKeyPem` 放运行时配置,而不是硬编码到 service; -- `clientSource` 默认是 `ct-client`; -- `deviceId / deviceType` 先允许配置,避免后面服务端开始校验时需要改代码。 - -## 6.2 持久化来源配置 - -建议先用数据文件落地,不急着进数据库。 - -建议文件: - -`apps/backend/data/cloudtentacles-sources.json` - -建议第一版结构: - -```json -{ - "enabled": true, - "baseUrl": "https://123.207.217.176", - "username": "", - "password": "", - "phone": "", - "deviceId": "-", - "deviceType": 0 -} -``` - -后续如果要支持多套账号,再演进为: - -```json -{ - "sources": [ - { - "sourceKey": "cloudtentacles-main", - "enabled": true, - "baseUrl": "https://123.207.217.176", - "username": "", - "password": "", - "phone": "", - "deviceId": "-", - "deviceType": 0 - } - ] -} -``` - -第一版先单来源,能明显降低 UI 和逻辑复杂度。 - ---- - -## 7. API 设计建议 - -建议先在管理后台补一组最小接口: - -### 7.1 配置读取 - -```http -GET /api/v1/admin/platform-config/cloudtentacles-source -``` - -返回: - -- 配置文件路径 -- 当前履约平台配置 - -### 7.2 配置保存 - -```http -POST /api/v1/admin/platform-config/cloudtentacles-source -``` - -用于保存: - -- 账号 -- 密码 -- 手机号 -- baseUrl -- 设备头默认值 - -### 7.3 发送短信验证码 - -```http -POST /api/v1/admin/platforms/cloudtentacles/send-sms-code -``` - -入参支持: - -- 使用已保存配置; -- 或临时覆盖账号/手机号/baseUrl。 - -### 7.4 手动登录测试 - -```http -POST /api/v1/admin/platforms/cloudtentacles/login -``` - -入参: - -- `username` -- `password` -- `phone` -- `code` - -返回: - -- `token` -- `userInfo` -- `permissions` -- `loggedInAt` - -### 7.5 会话探活测试 - -```http -POST /api/v1/admin/platforms/cloudtentacles/validate-session -``` - -入参: - -- `token` - -返回: - -- 是否有效 -- 用户信息 - ---- - -## 8. 后台 UI 设计建议 - -第一版 UI 不需要太复杂,应避免把“订单来源配置”和“履约平台配置”混在一起。 - -建议在“平台配置”页新增独立区块,归类到“履约平台”分组: - -### 8.1 履约平台配置区 - -字段: - -- 启用状态 -- baseUrl -- 账号 -- 密码 -- 手机号 -- deviceId -- deviceType - -操作: - -- 保存配置 - -### 8.2 登录测试区 - -字段: - -- 短信验证码输入框 - -操作: - -- 发送验证码 -- 执行登录 -- 验证当前 token - -### 8.3 调试结果区 - -显示: - -- token 是否返回 -- userInfo -- permissions -- 最近一次错误消息 - -注意: - -- 不要把这个平台和订单来源放在同一张混合表单里; -- 页面上要明确区分: - - 订单来源平台 - - 履约执行平台 -- 后面平台越来越多时,这个结构才能撑住。 - ---- - -## 9. 错误处理与日志建议 - -建议统一给这个平台加明确日志前缀: - -- `[cloudtentacles/crypto]` -- `[cloudtentacles/session]` -- `[cloudtentacles/http]` - -第一版重点记录: - -1. 发送验证码是否成功; -2. 登录是否成功; -3. `/user/info` 探活是否成功; -4. 平台返回的 `code/message`; -5. 不记录明文密码、短信验证码、完整 token。 - -建议在日志和接口返回里都做脱敏: - -- 手机号只显示部分; -- token 只显示前后几位; -- password 永不回显。 - ---- - -## 10. 与现有履约架构的关系 - -当前项目里的履约主链路已经是: - -1. 订单进入系统; -2. 根据 `provider/platform/shopId/sku` 命中 `order-fulfillment-bindings.json`; -3. 解析到 `fulfillment_profile`; -4. 创建 `delivery task`; -5. 根据 `executor_key` 决定后续执行方式。 - -所以 `cloudtentacles` 后续正确的接入位置是: - -- 第一阶段:只补平台登录能力; -- 第二阶段:新增 `cloudtentacles_dispatch` 执行器; -- 第三阶段:把某些 SKU 的履约绑定切到这个执行器。 - -也就是说: - -- `agiso/91卡券` 决定“订单从哪里来” -- `cloudtentacles` 决定“订单怎么发出去” - ---- - -## 11. 实施顺序 - -建议按这个顺序落地: - -### 第 1 步:后端基础模块 - -先实现: - -- `shared.js` -- `crypto-service.js` -- `http-client.js` -- `session-service.js` -- `source-config-service.js` - -目标: - -- 本地可完成发送验证码; -- 收到短信后可手动输入验证码登录; -- 登录后可拉 `/user/info`。 - -### 第 2 步:后台接口 - -增加: - -- 配置读取/保存 -- 发送验证码 -- 登录测试 -- token 探活 - -### 第 3 步:后台 UI - -增加: - -- 单独的平台配置区 -- 发送验证码与登录测试区 -- 调试反馈区 - -### 第 4 步:后续业务能力 - -登录能力稳定后,再补: - -- SKU/分类/背包读取 -- 发货动作 -- `cloudtentacles_dispatch` 执行器 -- 自动发货链路 - ---- - -## 12. 当前阶段结论 - -这个平台不是新的订单数据源,而是新的**外部履约能力**。 - -第一版接入重点不是立刻改主流程,而是先把 **可复用的登录能力** 做扎实。 - -最重要的不是把接口先堆进去,而是先把结构定对: - -- 历史拉单型平台:验证码图片 + Cookie -- `cloudtentacles` 型平台:短信码 + RSA 加密 + token - -二者都属于“后台登录型平台”,但在系统分层上不同: - -- `91卡券`:来源层 -- `cloudtentacles`:履约层 - -因此第一版推荐结论是: - -1. 作为独立履约平台能力接入; -2. 先做“配置 + 发验证码 + 登录 + 探活”; -3. 目录结构按“配置 / 加密 / HTTP / 会话 / 业务”拆开; -4. 后续通过新的 `executor_key` 接入履约任务执行,而不是改订单来源模型。 diff --git a/docs/frontend-optimization-plan.md b/docs/frontend-optimization-plan.md deleted file mode 100644 index d9ff7a8c..00000000 --- a/docs/frontend-optimization-plan.md +++ /dev/null @@ -1,524 +0,0 @@ -# apps/frontend 前端优化计划 - -## 背景 - -本计划基于当前 `apps/frontend` 代码现状整理。当前前端使用 Vue 3、Vite、TypeScript、Vue Router、Element Plus,已开启 TypeScript strict 相关检查,路由页面基本采用动态 import,`npm run build` 当前可通过。 - -当前主要问题不是功能不可用,而是后台管理页面增多后,列表页重复逻辑、请求稳定性、登录态安全、构建产物治理和工程规范需要系统化优化。 - -## 优化目标 - -- 提升后台页面的可维护性和复用性。 -- 减少列表页请求竞态和状态错乱风险。 -- 强化管理端登录态和开发服务器安全边界。 -- 规范构建产物和依赖拆包,提升缓存效果。 -- 补齐 lint / format / CI 质量门禁。 -- 为后续后台功能扩展降低开发成本。 - -## 当前观察 - -### 已确认现状 - -- `apps/frontend/package.json` 当前脚本包含 `dev`、`build`、`preview`、`typecheck`。 -- `apps/frontend/tsconfig.app.json` 已开启 `strict`、`noUnusedLocals`、`noUnusedParameters` 等检查。 -- `apps/frontend/src/router/index.ts` 已使用动态 import 拆分页面。 -- `apps/frontend/src/lib/http.ts` 统一封装 axios 请求和后台 401 处理。 -- 后台列表页普遍存在相同的 loading、error、pagination、load、reset 逻辑。 -- `apps/frontend/vite.config.ts` 当前 `server.host` 与 `server.allowedHosts` 配置偏开放。 -- 管理端 token 当前保存在 `localStorage`,`hasAdminSession()` 主要检查 token 是否存在。 - -### 构建验证 - -已执行: - -```bash -cd apps/frontend -npm run build -``` - -结果:构建成功。 - -## 优先级 P0:安全与稳定性 - -### 1. 收紧 Vite dev server 访问控制 - -涉及文件: - -- `apps/frontend/vite.config.ts` - -当前配置: - -```ts -server: { - host: true, - allowedHosts: true, -} -``` - -风险: - -- `allowedHosts: true` 会允许任意 Host 访问开发服务。 -- 如果配合公网隧道或局域网暴露,开发环境边界过宽。 - -建议方案: - -- 默认只允许本地访问。 -- 需要公网调试时通过环境变量显式开启。 -- 支持 Host 白名单,例如 `VITE_ALLOWED_HOSTS`。 - -建议配置方向: - -```ts -const allowedHosts = env.VITE_ALLOWED_HOSTS - ? env.VITE_ALLOWED_HOSTS.split(',').map((host) => host.trim()).filter(Boolean) - : ['localhost', '127.0.0.1'] - -server: { - host: env.VITE_DEV_HOST === 'true', - allowedHosts: env.VITE_ALLOW_ALL_HOSTS === 'true' ? true : allowedHosts, -} -``` - -验收标准: - -- 本地 `npm run dev` 正常。 -- 未设置环境变量时不默认允许任意 Host。 -- 需要公网调试时可以通过环境变量开启。 - -### 2. 完善管理端登录态过期判断 - -涉及文件: - -- `apps/frontend/src/utils/admin-auth.ts` -- `apps/frontend/src/router/index.ts` -- `apps/frontend/src/lib/http.ts` - -当前问题: - -- `hasAdminSession()` 只检查 token 是否存在。 -- `expiresAt` 已存储但前端路由守卫未主动判断是否过期。 -- `getAdminRole()` 在本地 role 缺失时默认返回 `operator`,权限默认值偏宽。 - -建议方案: - -- `hasAdminSession()` 校验 token 和 expiresAt。 -- token 过期时主动 `clearAdminSession()`。 -- `getAdminRole()` 默认值调整为最低权限,或返回空角色并让调用方处理。 -- 保持后端接口鉴权作为最终安全边界,前端仅用于体验优化。 - -验收标准: - -- 过期 token 刷新页面会跳转登录页。 -- role 缺失时不会默认获得 operator 权限。 -- 401 且错误码为认证失效时仍会清理会话。 - -### 3. 列表请求增加竞态保护 - -涉及页面: - -- `apps/frontend/src/views/admin/webhook-events/AdminWebhookEventsView.vue` -- `apps/frontend/src/views/admin/orders/AdminOrdersView.vue` -- `apps/frontend/src/views/admin/tasks/AdminTasksView.vue` -- `apps/frontend/src/views/admin/message-deliveries/AdminMessageDeliveriesView.vue` -- `apps/frontend/src/views/admin/users/AdminUsersView.vue` -- `apps/frontend/src/views/admin/audit-logs/AdminAuditLogsView.vue` -- `apps/frontend/src/views/admin/inventory/AdminInventoryView.vue` - -当前风险: - -- 用户连续查询、翻页或回车搜索时,旧请求可能晚于新请求返回并覆盖新结果。 - -建议方案: - -- 短期使用 `requestId` 忽略过期响应。 -- 中期在 HTTP 层或列表 composable 中支持 `AbortController`。 - -示例方向: - -```ts -let latestRequestId = 0 - -async function loadPage(page = pagination.value.page) { - const requestId = ++latestRequestId - loading.value = true - errorMessage.value = '' - - try { - const response = await fetchList(page) - if (requestId !== latestRequestId) return - - items.value = response.data.items - pagination.value = response.data.pagination - } catch (error) { - if (requestId !== latestRequestId) return - errorMessage.value = error instanceof Error ? error.message : '读取列表失败' - } finally { - if (requestId === latestRequestId) { - loading.value = false - } - } -} -``` - -验收标准: - -- 快速连续点击查询或分页时,页面最终展示最后一次请求结果。 -- loading 状态不会被旧请求提前关闭。 - -## 优先级 P1:后台列表页复用与体验 - -### 4. 抽取通用 `useAdminListPage` - -建议新增: - -- `apps/frontend/src/composables/useAdminListPage.ts` - -目标统一处理: - -- `loading` -- `errorMessage` -- `items` -- `pagination` -- `loadPage` -- `resetPageAndLoad` -- 请求竞态保护 -- 默认错误提示 -- 默认 `pageSize` - -适合改造页面: - -- Webhook 日志 -- 订单列表 -- 任务列表 -- 消息发送记录 -- 审计日志 -- 用户列表 -- 库存列表 - -预期收益: - -- 列表页脚本代码减少约 30% 到 50%。 -- 分页、查询、错误处理行为统一。 -- 后续增加 URL query 同步或请求取消时只需改一处。 - -验收标准: - -- 至少完成 2 个代表页面改造,例如 Webhook 日志和订单列表。 -- 改造后 `npm run typecheck` 与 `npm run build` 通过。 - -### 5. 筛选条件同步到 URL Query - -适合页面: - -- `AdminWebhookEventsView.vue` -- `AdminOrdersView.vue` -- `AdminTasksView.vue` -- `AdminMessageDeliveriesView.vue` -- `AdminAuditLogsView.vue` - -当前问题: - -- 刷新页面后筛选条件丢失。 -- 无法复制当前筛选链接给其他管理员。 - -建议方案: - -- 页面初始化时从 `route.query` 读取筛选条件和页码。 -- 查询、重置、分页时使用 `router.replace()` 更新 query。 -- 空筛选项不写入 URL。 - -验收标准: - -- 刷新页面保留筛选条件。 -- 分享 URL 后能恢复相同列表视图。 -- 重置筛选会清理相关 query。 - -### 6. 统一日期范围组件 - -当前观察: - -- 订单页已经使用 `type="daterange"`。 -- Webhook、审计日志等页面仍使用两个独立日期选择器。 - -建议方案: - -- 日志类、列表类页面统一使用 `el-date-picker type="daterange"`。 -- 内部统一映射为 `dateFrom` 和 `dateTo` API 参数。 - -验收标准: - -- Webhook 日志、审计日志、消息发送记录日期筛选交互一致。 -- API 参数保持兼容。 - -### 7. 统一筛选触发策略 - -当前问题: - -- 输入框通常支持 Enter 查询。 -- select/date 改变后多数页面不自动查询。 -- 不同列表页交互不完全一致。 - -建议二选一: - -- 方案 A:所有筛选项变更后不自动查询,统一点击“查询”。 -- 方案 B:select/date 变更自动查询,文本输入 Enter 或防抖查询。 - -建议优先方案 A,原因是后台列表数据量可能较大,可减少无意请求。 - -验收标准: - -- 后台列表页筛选交互一致。 -- 查询按钮与重置按钮行为一致。 - -## 优先级 P2:工程规范与类型质量 - -### 8. 增加 ESLint / Prettier - -涉及文件: - -- `apps/frontend/package.json` -- `apps/frontend/eslint.config.*` -- `apps/frontend/.prettierrc` 或等价配置 - -当前问题: - -- package scripts 未提供 lint / format。 -- 仅依赖 TypeScript 编译检查,无法覆盖 Vue 模板规范、Promise 处理、风格一致性等问题。 - -建议增加脚本: - -```json -{ - "scripts": { - "lint": "eslint . --ext .ts,.vue", - "format": "prettier --write .", - "format:check": "prettier --check ." - } -} -``` - -建议依赖: - -- `eslint` -- `@eslint/js` -- `typescript-eslint` -- `eslint-plugin-vue` -- `prettier` -- `eslint-config-prettier` - -验收标准: - -- `npm run lint` 可执行。 -- `npm run format:check` 可执行。 -- CI 至少执行 `typecheck`、`lint`、`build`。 - -### 9. 优化 HTTP 封装类型 - -涉及文件: - -- `apps/frontend/src/lib/http.ts` -- `apps/frontend/src/services/**/*` - -当前问题: - -```ts -return http.get>(url, { params }) as unknown as Promise> -``` - -由于 axios interceptor 返回 `response.data`,代码使用 `as unknown as` 消除类型差异。 - -建议方案: - -- 封装明确的 `request()`。 -- 统一返回 `Promise>`。 -- blob 请求单独封装。 - -目标: - -- 减少双重类型断言。 -- 服务层返回值更可信。 -- 错误类型可以逐步标准化。 - -验收标准: - -- `apiGet`、`apiPost`、`apiDelete` 不再依赖 `as unknown as`。 -- 现有 services 类型不退化。 -- `npm run typecheck` 通过。 - -## 优先级 P3:构建产物与性能 - -### 10. 分析并治理 bundle - -当前构建观察: - -- 构建成功。 -- 输出中出现较多 `css-*.js` 小 chunk。 -- Element Plus 相关依赖和样式可能存在进一步优化空间。 - -建议步骤: - -1. 引入 bundle 分析工具。 -2. 查看 Vue、Element Plus、lodash、qrcode、dayjs 等依赖占比。 -3. 评估是否需要配置 `manualChunks`。 -4. 检查 Element Plus 样式自动导入是否导致过多碎片 chunk。 - -可选工具: - -- `rollup-plugin-visualizer` -- Vite 官方构建输出分析 - -验收标准: - -- 输出一份主要 chunk 占比结论。 -- 明确是否需要手动拆分 vendor。 -- 优化后首屏关键 chunk 不变大。 - -### 11. 稳定 vendor chunk 拆分 - -建议方向: - -```ts -build: { - rollupOptions: { - output: { - manualChunks: { - 'vue-vendor': ['vue', 'vue-router'], - 'element-plus': ['element-plus'], - }, - }, - }, -} -``` - -注意事项: - -- 不建议盲目拆太细。 -- 需要结合 bundle 分析结果决定。 -- 后台页面较多时,可以考虑 admin 公共模块分组。 - -验收标准: - -- 构建产物命名更稳定。 -- 主要 vendor 包可长期缓存。 -- 页面懒加载不被破坏。 - -## 优先级 P4:大型页面拆分 - -### 12. 拆分超大 Vue 文件 - -当前行数较大的文件包括: - -- `apps/frontend/src/views/admin/fulfillment/AdminKuaishouCloudFulfillmentView.vue` -- `apps/frontend/src/views/admin/tasks/AdminTaskDetailView.vue` -- `apps/frontend/src/views/admin/fulfillment/AdminFulfillmentBindingsView.vue` -- `apps/frontend/src/views/admin/inventory/AdminInventoryView.vue` -- `apps/frontend/src/views/admin/platform-shops/AdminPlatformShopsView.vue` - -建议拆分维度: - -- 筛选区组件 -- 表格区组件 -- 表单区组件 -- 弹窗组件 -- 业务 composable -- 数据转换函数 - -验收标准: - -- 单个 Vue 文件尽量控制在 300 到 500 行以内。 -- 业务状态集中在 composable 或页面容器中。 -- 展示组件保持 props / emits 清晰。 - -## 分阶段执行计划 - -### 阶段一:安全与稳定性基线 - -范围: - -- 收紧 `vite.config.ts` dev server 配置。 -- `hasAdminSession()` 增加过期判断。 -- 给 Webhook 列表增加请求竞态保护。 - -验证: - -```bash -cd apps/frontend -npm run typecheck -npm run build -``` - -### 阶段二:列表页抽象 - -范围: - -- 新增 `useAdminListPage`。 -- 先改造 Webhook 日志和订单列表。 -- 确认抽象合理后推广到任务、消息、用户、审计日志。 - -验证: - -- 手动检查查询、重置、分页、错误提示。 -- `npm run typecheck` -- `npm run build` - -### 阶段三:筛选体验统一 - -范围: - -- 日期范围统一为 `daterange`。 -- 列表页 URL query 同步。 -- 统一查询触发策略。 - -验证: - -- 刷新页面保留筛选。 -- 分享链接可恢复筛选。 -- 重置筛选清理 URL。 - -### 阶段四:工程质量门禁 - -范围: - -- 增加 ESLint / Prettier。 -- 增加 lint / format:check 脚本。 -- CI 或本地验证流程加入 typecheck、lint、build。 - -验证: - -```bash -cd apps/frontend -npm run typecheck -npm run lint -npm run build -``` - -### 阶段五:构建与大型页面治理 - -范围: - -- Bundle 分析。 -- 评估并配置 manualChunks。 -- 拆分 900 行以上的大型 Vue 页面。 - -验证: - -- 构建成功。 -- 产物 chunk 数量和体积有明确对比。 -- 页面功能无回归。 - -## 风险与注意事项 - -- 列表页抽象不要一次性改造所有页面,建议先选 2 个页面试点。 -- URL query 同步要避免 watcher 循环触发请求。 -- token 存储机制如果改为 Cookie,需要后端配合,不建议前端单独推进。 -- manualChunks 需要基于分析结果调整,避免拆包过度导致请求数过多。 -- ESLint 首次接入可能暴露大量历史问题,建议先设置合理规则,再逐步收紧。 - -## 推荐近期落地清单 - -1. 修改 `vite.config.ts`,收紧 `allowedHosts`。 -2. 修改 `admin-auth.ts`,增加 token 过期判断。 -3. 在 `AdminWebhookEventsView.vue` 试点请求竞态保护和日期范围统一。 -4. 抽取 `useAdminListPage`,先改造 Webhook 和订单列表。 -5. 增加 ESLint / Prettier 基础配置。 -6. 引入 bundle 分析,确认 Element Plus 和 CSS chunk 优化方向。 diff --git a/docs/xianyu_api/咸鱼api.md b/docs/xianyu_api/咸鱼api.md deleted file mode 100644 index dbc383c2..00000000 --- a/docs/xianyu_api/咸鱼api.md +++ /dev/null @@ -1,101 +0,0 @@ -订单查询 - -简要描述: 接口调用示例 - - ¥高级 - 根据订单号,查询订单信息 - -请求URL: - - https://gw-api.agiso.com/aldsIdle/Order/Detail - -请求方式: - - POST - -公共Header: -Authorization - -是 - -string - -httpPost.addHeader("Authorization","Bearer "+ accessToken) -ApiVersion - -是 - -string - -httpPost.addHeader("ApiVersion", "1") - -公共参数: -timestamp - -是 - -Date - -时间戳,例如:1468476350。API服务端允许客户端请求最大时间误差为10分钟。 -sign - -是 - -string - -API输入参数签名结果,签名算法参照下面的介绍。 - -参数: -tid - -是 - -Long - -订单号 - -返回示例 - - { - "IsSuccess": true, - "Data": { - "biz_order_id": 1520087523676842500, // 订单号 - "buy_amount": 1, // 商品购买数量 - "buyer_nick": "地铁吃火锅当真", // 买家昵称(不唯一且买家可以自己更改) - "encryption_buyer_id": "RAzN8214YLDBs4AJxFJBYp5DdeHrBPKq4QsbFL", // 加密的买家id(唯一且不会改变) - "create_time": 1647677835000, // 订单创建时间,时间戳,毫秒 - "end_time": 1647677858000, // 订单完结时间,时间戳,毫秒 - "item": { // 商品信息 - "item_id": 669513624774, // 商品ID - "pic_url": "https://gw.alicdn.com/bao/uploaded/i4/O1CN01X6Nw841OaGN6dvZtx_!!0-fleamarket.jpg", // 商品图片,绝对途径 - "price": 1, // 商品价格,单位分 - "title": "测试宝贝5", // 商品标题 - "outer_id_sku": "XY02", // 商品外部编码(SKU维度) - "outer_id_spu": "XY01", // 商品外部编码(SPU维度) - }, - "order_status": 5, // 0:未知状态、1:订单已创建、2:订单已付款、3:已发货、4:交易成功、5:已退款、6:交易关闭 - "pay_time": 1647677841000, // 订单下单付款时间,时间戳,毫秒 - "payment": 1, // 实付金额, 单位分 - "post_fee": 0, // 邮费 - "seller_nick": "爱***网", // 卖家昵称(不唯一且买家可以自己更改) - "ship_time": 0, // 订单发货时间,时间戳,毫秒 - "sku": 0, // sku信息(格式: skuId|属性名:属性值;属性名:属性值) - "isRecharge":true, // 是否直冲标识 - "recharge_amount":"135xxxx", // 充值信息 - "isEticket":"true", // 是否囤囤券订单 - "coupon_eticket_info":[ // 核销码信息(囤囤券) - { - "code_id":"x222223", // 核销码 - "code_password":"123", // 核销码密码 - "code_status":"1", // 核销码状态 - "code_type":1, // 核销码类型 - "code_use_url":"http://localhost:26450/t/zbdjyu_9137A" // 核销码使用链接 - } - ] - }, - "Error_Code": 0, - "Error_Msg": "" - "AllowRetry": null, - "RequestId": "20220322142251106" - } - diff --git a/docs/xianyu_api/更新发货状态.md b/docs/xianyu_api/更新发货状态.md deleted file mode 100644 index 0dd10d06..00000000 --- a/docs/xianyu_api/更新发货状态.md +++ /dev/null @@ -1,50 +0,0 @@ - -更新发货状态 -简要描述: 接口调用示例 - -¥基础 -执行无物流发货,更新发货状态 -请求URL: - -https://gw-api.agiso.com/aldsIdle/Order/DummySend -请求方式: - -POST -公共Header: - -Authorization -是 -string -httpPost.addHeader("Authorization","Bearer "+ accessToken) -ApiVersion -是 -string -httpPost.addHeader("ApiVersion", "1") -公共参数: - -timestamp -是 -Date -时间戳,例如:1468476350。API服务端允许客户端请求最大时间误差为10分钟。 -sign -是 -string -API输入参数签名结果,签名算法参照下面的介绍。 -参数: - -tid -是 -Long -订单号 -返回示例 - - - { - "IsSuccess": true, - "Data": null - "Error_Code": 0, - "Error_Msg": "" - "AllowRetry": null, - "RequestId": "20221027142251106" - } - \ No newline at end of file diff --git a/docs/xianyu_api/确认收货后通知.md b/docs/xianyu_api/确认收货后通知.md deleted file mode 100644 index 245ae94f..00000000 --- a/docs/xianyu_api/确认收货后通知.md +++ /dev/null @@ -1,43 +0,0 @@ -确认收货后通知 -简要描述: 推送示例 - -确认收货后,推送对应消息。 -推送的签名请务必验证,以验证数据来源的合法性。验证方法参考以下说明。 -推送时,有可能消息重复推送。实际开发中,请一定要在使用消息前进行去重判断。主要依据是订单编号Tid和订单状态。 -推送方式,用jquery做示例:$.post('http://test.com/agiso?timestamp=11222212121&sign=f8aa165fc951f266667e0605d78b93af&aopic=32768', { json: '{"Tid":"592823138",......}' }) -推送参数: - -fromPlatform -string -Query/Get -平台,参数值:TbAcs,TbAlds,TbArs,Print,Acpr,PddAlds,AldsIdle,AldsJd,AldsDoudian,AldsKwai,AldsYouzan,AldsWeidian,AldsWxVideoShop,AldsXhs,Open -timestamp -Number -Query/Get -时间戳 -aopic -Number -Query/Get -推送类型,16:确认收货后; -sign -String -Query/Get -签名算法: -   将json和timestamp参数名和参数值组合起来(注意:json在前,timestamp在后),然后前后添加上AppSecret ,再进行Md5加密(加密算法参考接入指南-完整调用API示例代码中MD5算法)。 -例: -url:http://test.com/agiso?timestamp=11222212121&sign=f8aa165fc951f266667e0605d78b93af&aopic=256, -postData: { json: {"Tid":2067719225654838,"Status":"WAIT_BUYER_CONFIRM_GOODS",......,"TotalFee":"3.00"} }, -_appsecret: 9f8g9d78sg9d8f8ew9f89ds9f8ds9af8(开发者AppSecret), -连接后的串: 9f8g9d78sg9d8f8ew9f89ds9f8ds9af8json{"Tid":2067719225654838,"Status":"WAIT_BUYER_CONFIRM_GOODS",......,"TotalFee":"3.00"}timestamp112222121219f8g9d78sg9d8f8ew9f89ds9f8ds9af8 -再对连接后的字符串,进行MD5加密, -MD5结果: f8aa165fc951f266667e0605d78b93af(不区分大小写) -json -String -Form/Post -推送消息,如: -{ - "biz_order_id": 9112588, // 交易订单号 - "item_id": 1, // 商品Id - "order_status": 2,// 订单状态 0:未知状态、1:订单已创建、2:订单已付款、3:已发货、4:交易成功、5:已退款、6:交易关闭 - "seller_id": 1556356040640, // 闲鱼商家的Id -} \ No newline at end of file diff --git a/docs/咸鱼商品详情.logs b/docs/咸鱼商品详情.logs deleted file mode 100644 index 90a626a7..00000000 --- a/docs/咸鱼商品详情.logs +++ /dev/null @@ -1,31 +0,0 @@ -{ - "item_id": 1033324289962, - "seller_id": 2209880145223, - "MsgTypeDes": "订单已付款", - "biz_order_id": "2701827483088138281", - "order_status": 2, - "_agisoTradeDetail": { - "sku": "6046726460016|商品名称:奥利奥动作", - "item": { - "price": 70, - "title": "【自动发货】蛋仔派对奥利奥皮肤、奥利奥呦呦、奥利奥动作", - "item_id": 1033324289962, - "pic_url": "https://gw.alicdn.com/bao/uploaded/i1/2209880145223/O1CN01QAHaJL1oSBmQaGffk_!!4611686018427387207-53-xy_item.heic" - }, - "payment": 70, - "end_time": 0, - "pay_time": 1775953431000, - "post_fee": 0, - "isEticket": false, - "ship_time": 1775953434000, - "buy_amount": 1, - "buyer_nick": "梦里梦", - "isRecharge": false, - "create_time": 1775953408000, - "seller_nick": "大锤号商", - "biz_order_id": "2701827483088138281", - "order_status": 3, - "coupon_eticket_info": [], - "encryption_buyer_id": "enV7xJs5DRbJBzIH8uUUcg==" - } -} \ No newline at end of file diff --git a/docs/快手小店核销.md b/docs/快手小店核销.md deleted file mode 100644 index e1cfb3ac..00000000 --- a/docs/快手小店核销.md +++ /dev/null @@ -1,74 +0,0 @@ -快手小店 核销相关api - -查询核销信息 -curl -X POST 'https://s.kwaixiaodian.com/gateway/industry/eticket/consume/detail' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36' -H 'Accept: application/json' -H 'Content-Type: application/json' -H 'accept-language: zh-CN,zh;q=0.9' -H 'kpf: PC_WEB' -H 'kpn: KWAIXIAODIAN' -H 'ktrace-str: 3|My40NTgzNjk4Mjg2NzM2NzY5LjUyOTE3OTczLjE3Nzc2MjgwNzkwMzkuMTA2MQ==|My40NTgzNjk4Mjg2NzM2NzY5LjE2OTQ4MTU0LjE3Nzc2MjgwNzkwMzkuMTA2MA==|0|plateco-kfx-service|plateco|true|src:Js,seqn:175,rsi:b100c051-6d0f-4b74-bf7e-9184a8f8703f,path:/zone/industry/voucher/verify-list,rpi:a1478c9a0b' -H 'origin: https://s.kwaixiaodian.com' -H 'priority: u=1, i' -H 'referer: https://s.kwaixiaodian.com/zone/industry/voucher/verify-list' -H 'sec-ch-ua: "Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147"' -H 'sec-ch-ua-mobile: ?0' -H 'sec-ch-ua-platform: "Windows"' -H 'sec-fetch-dest: empty' -H 'sec-fetch-mode: cors' -H 'sec-fetch-site: same-origin' -H 'Cookie: _did=web_1426300268274CD9; did=web_ozkrrsevhb6yuztyk6m63vqqi5h2pzfl; __risk_web_device_id=cd52e12c1773406609757e71; sid=kuaishou.shop.b; sellerId=4269276762; bUserId=1000492186791; userId=4269276762; merchantSellerId=4269276762; merchantSessionKey=1777621574120_fbd47024d23e73fc4ad1a157ffece433; kuaishou.shop.b_st=ChJrdWFpc2hvdS5zaG9wLmIuc3QSoAFzGnewF-wCpt4rHi-D-pp8zPUp7HByKY0MlHkw-WV676zG7z09Y5i7d7URwmGC8CL13jN0fOGV7d3GfaH2XLH8d4p60z0Ms-dIX0bipkI0yUWHfgnWqv9VPa8HqVRqMLs2VGD82X9tAR3eN9PXu38AYg0a5kpawchGPb2tjcYgLgH5b5DnJgjipHqzWb8Ma8AcLOmryqCSg4ZHwO5dbVJHGhIdwFBlxRpZgyh6i0Do-DSRsroiIIayd1xA628OsvCY2qV1HjCrTvMVt-3LmXcU6rLKSzytKAUwAQ; kuaishou.shop.b_ph=38925ccb882ec5456dd1c6bcee3f87b7e740' -d '{"eTicketId":"86D01FB011B3701D"}' - -cookie 鉴权, 正常返回 -{ - "result": 1, - "error_msg": "成功", - "data": { - "eTicket": { - "uid": "4435885561", - "fulfillDetailId": "937948874561", - "sellerId": "4269276762", - "formToken": "1777716306154", - "validEndTime": 1780308306001, - "validStartTime": 1777716306001, - "leftReverseCount": 0, - "eTicketId": "F2E886B6CBF8E5F5", - "oid": "2612200246413561", - "totalCount": 1, - "leftCount": 1, - "status": "CONSUME_ORDER_CREATED" - }, - "goods": { - "itemId": "26376689045762", - "itemPicUrl": "https://p4-ec.ecukwai.com/bs2/image-kwaishop-product/ITEM_IMAGE-4269276762-24c2ae6e05df4efe898a016ff01ee511.jpg", - "itemTitle": "测试链接五排", - "price": "0.01", - "skuDesc": "测试1", - "skuId": "183856547654762" - } - }, - "serverTimestamp": 1777793083978, - "requestId": "777793083896272457" -} - -已经核销过显示 - -{ - "result": 21, - "error_msg": "券码已核销无法再次核销,请核实后重试", - "serverTimestamp": 1777792945247, - "requestId": "777792945205272457" -} - ----- -执行核销 - -curl -X POST 'https://s.kwaixiaodian.com/gateway/industry/eticket/consume' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36' -H 'Accept: application/json' -H 'Content-Type: application/json' -H 'accept-language: zh-CN,zh;q=0.9' -H 'kpf: PC_WEB' -H 'kpn: KWAIXIAODIAN' -H 'ktrace-str: 3|My40NTgzNjk4Mjg2NzM2NzY5LjU3MzgyNjc3LjE3Nzc2MjgyMTM4NTcuMTA2OQ==|My40NTgzNjk4Mjg2NzM2NzY5Ljk2NTIyNjY4LjE3Nzc2MjgyMTM4NTcuMTA2OA==|0|plateco-kfx-service|plateco|true|src:Js,seqn:175,rsi:b100c051-6d0f-4b74-bf7e-9184a8f8703f,path:/zone/industry/voucher/verify-list,rpi:a1478c9a0b' -H 'origin: https://s.kwaixiaodian.com' -H 'priority: u=1, i' -H 'referer: https://s.kwaixiaodian.com/zone/industry/voucher/verify-list' -H 'sec-ch-ua: "Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147"' -H 'sec-ch-ua-mobile: ?0' -H 'sec-ch-ua-platform: "Windows"' -H 'sec-fetch-dest: empty' -H 'sec-fetch-mode: cors' -H 'sec-fetch-site: same-origin' -H 'Cookie: _did=web_1426300268274CD9; did=web_ozkrrsevhb6yuztyk6m63vqqi5h2pzfl; __risk_web_device_id=cd52e12c1773406609757e71; sid=kuaishou.shop.b; sellerId=4269276762; bUserId=1000492186791; userId=4269276762; merchantSellerId=4269276762; merchantSessionKey=1777621574120_fbd47024d23e73fc4ad1a157ffece433; kuaishou.shop.b_st=ChJrdWFpc2hvdS5zaG9wLmIuc3QSoAFzGnewF-wCpt4rHi-D-pp8zPUp7HByKY0MlHkw-WV676zG7z09Y5i7d7URwmGC8CL13jN0fOGV7d3GfaH2XLH8d4p60z0Ms-dIX0bipkI0yUWHfgnWqv9VPa8HqVRqMLs2VGD82X9tAR3eN9PXu38AYg0a5kpawchGPb2tjcYgLgH5b5DnJgjipHqzWb8Ma8AcLOmryqCSg4ZHwO5dbVJHGhIdwFBlxRpZgyh6i0Do-DSRsroiIIayd1xA628OsvCY2qV1HjCrTvMVt-3LmXcU6rLKSzytKAUwAQ; kuaishou.shop.b_ph=38925ccb882ec5456dd1c6bcee3f87b7e740' -d '{ - "eTicketId": "F2E886B6CBF8E5F5", - "num": 1, - "storeId": "0", - "oid": "2612200246413561", - "formToken": "1777716306154" -}' - -返回示例 -核销完成 -{ - "result": 1, - "error_msg": "成功", - "serverTimestamp": 1777793112213, - "requestId": "777793112065709069" -} - - -已经核销过显示 -{ - "result": 21, - "error_msg": "券码已核销无法再次核销,请核实后重试", - "serverTimestamp": 1777628248539, - "requestId": "777628248507098573" -} \ No newline at end of file diff --git a/docs/是否过期判断.md b/docs/是否过期判断.md deleted file mode 100644 index c9d896ae..00000000 --- a/docs/是否过期判断.md +++ /dev/null @@ -1,58 +0,0 @@ -curl -X POST 'https://comm.ams.game.qq.com/ide/' -H 'User-Agent: Mozilla/5.0 (Linux; Android 12; M2012K11AC Build/SKQ1.211006.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/98.0.4758.102 MQQBrowser/6.2 TBS/046141 Mobile Safari/537.36 V1_AND_SQ_8.8.85_2674_YYB_D QQ/8.8.85.7685 NetType/WIFI WebP/0.3.0 Pixel/1080 StatusBarHeight/108 SimpleUISwitch/0 QQTheme/1000' -H 'Accept: application/json, text/plain, */*' -H 'Content-Type: application/x-www-form-urlencoded' -H 'accept-language: zh-CN,zh;q=0.9,fr;q=0.8,de;q=0.7,en;q=0.6' -H 'cache-control: no-cache' -H 'origin: https://gp.qq.com' -H 'pragma: no-cache' -H 'priority: u=1, i' -H 'referer: https://gp.qq.com/' -H 'sec-ch-ua: ""' -H 'sec-ch-ua-mobile: ?1' -H 'sec-ch-ua-platform: ""' -H 'sec-fetch-dest: empty' -H 'sec-fetch-mode: cors' -H 'sec-fetch-site: same-site' -H 'Cookie: RK=uMT6S1KV0W; ptcz=c5241ee891d01510c81130023879f9d68088e87c75cb94e6dcc439a0d0078bab; pgv_pvid=5513916356; eas_sid=a1t7G7I644L7p7O3w0S3Y7W1f0; pgv_info=ssid=s2668768060; tokenParams=%3FuserId%3D14987713343%26timestamp%3D1778739347%26nonce%3Dd593e045%26sign%3D43ed7de057afb340fc766de4404817f8396ec727; gpqqcomrouteLine=a20240828cmcc_a20240828cmcc_a20240828cmcc_a20240828cmcc_a20240828cmcc_a20240828cmcc_a20240828cmcc' --data-urlencode 'iChartId=323794' --data-urlencode 'iSubChartId=323794' --data-urlencode 'sIdeToken=z90Syo' --data-urlencode 'e_code=0' --data-urlencode 'g_code=0' --data-urlencode 'eas_url=http%3A%2F%2Fgp.qq.com%2Fcp%2Fa20240828cmcc%2F' --data-urlencode 'eas_refer=http%3A%2F%2Fnoreferrer%2F%3Freqid%3Da29ad787-5500-414c-8773-7723877f52c5%26version%3D27' --data-urlencode 'sMiloTag=AMS-gp-0514141601-VuK8ts-666311-1067699' --data-urlencode 'userId=14987713343' --data-urlencode 'timestamp=1778739347' --data-urlencode 'nonce=d593e045' --data-urlencode 'sign=43ed7de057afb340fc766de4404817f8396ec727' - -正常响应 -{ - "ret": 0, - "iRet": 0, - "sMsg": "ok", - "jData": { - "iRet": "0", - "sMsg": "ok", - "sBindInfo": { - "id": "213252", - "sUserId": "14987713343", - "sOpenId": "osewR0kiZgLUM7CTh2bIFsds9Yyo", - "iAreaId": "1", - "iPlatId": "1", - "sRoleId": "3177794957", - "sRoleName": "是海也是牛", - "iStatus": "1", - "iDate": "20260321", - "dtCreateTime": "2026-02-20 12:13:01", - "dtUpdateTime": "2026-03-21 10:47:03", - "hasBind": 1 - }, - "iStatus": "0" - }, - "sAmsSerial": "AMS-GP-0514141709-1UrrnM-666311-323794" -} - -签名过期 响应 -{ - "ret": 99998, - "iRet": 99998, - "sMsg": "签名已过期", - "jData": { - "ret": "99998", - "iRet": "99998", - "sMsg": "签名已过期", - "jData": { - "iRet": "99998", - "sMsg": "签名已过期" - }, - "arrErrNodeInfo": { - "nodeId": "nodeEnd", - "nodeType": "nodeEnd", - "errorCode": "99998" - }, - "sAmsSerial": "AMS-GP-0514141817-eN55LW-666311-323794", - "subChartAmsSerial": "AMS-GP-0514141817-eN55LW-666311-323794", - "timecost": 17 - }, - "arrErrNodeInfo": { - "nodeId": "4", - "nodeType": "nodeSubChart", - "errorCode": "99998" - }, - "sAmsSerial": "AMS-GP-0514141817-cZJfjw-666311-323794" -} \ No newline at end of file