upload-policy-library.mjs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. /**
  2. * 把本地政策库(`public/merchant-agent/policies_public.v2.json`)**上传到 DMS 文件服务**,
  3. * 打印出它的**相对路径**与**可访问地址** —— 那个地址就是前端的"远端政策接口"。
  4. *
  5. * 用户 2026-09-24 的要求:
  6. * 「把 policies_public.v2.json 上传到 DMS,记住那个路径,那个路径就是新的远端政策接口,
  7. * 后续先从那个接口拿,拿不到再用本地的兜底,最终目标是不再依赖原来的政策相关接口。」
  8. *
  9. * 用的是**已有的上传模块**(`src/network/api/dms/file-upload.ts`,与附件上传同一份实现、
  10. * 同一套实测契约:multipart 五个字段全必填);路径本身取不到,要拼 DMS 代理前缀才能访问
  11. * (见 `buildDmsFileDisplayUrl` 的注释与实测结论)。
  12. *
  13. * 怎么跑(需要 dev server 起着,代理负责补 `/dms` 前缀并注入 token):
  14. * node harness/tools/upload-policy-library.mjs # 默认打 https://localhost:8083/dms
  15. * node harness/tools/upload-policy-library.mjs https://host/dms # 也可以显式给代理地址
  16. *
  17. * 跑完把打印出来的「相对路径」写进 `.env.*` 的 `VITE_POLICY_REMOTE_URL`(拼好代理前缀的那份)。
  18. */
  19. process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // dev server 是自签证书
  20. const base = String(process.argv[2] || 'https://localhost:8083/dms').replace(/\/+$/, '');
  21. globalThis.VITE_DMS_API = base;
  22. const { uploadDmsAttachment, buildDmsFileDisplayUrl } = await import('./_dms.mjs');
  23. const { readFileSync } = await import('node:fs');
  24. const LOCAL_FILE = 'public/merchant-agent/policies_public.v2.json';
  25. const bytes = readFileSync(LOCAL_FILE);
  26. const list = JSON.parse(bytes.toString('utf8'));
  27. console.log(`上传 ${LOCAL_FILE}(${(bytes.length / 1024).toFixed(0)} KB / ${Array.isArray(list) ? list.length : '?'} 条)`);
  28. console.log(`经代理 ${base}(代理负责补 /dms 前缀并注入 token)`);
  29. const file = new File([bytes], 'policies_public.v2.json', { type: 'application/json' });
  30. const relativePath = await uploadDmsAttachment(file, { isImage: false });
  31. const displayUrl = buildDmsFileDisplayUrl(relativePath);
  32. console.log('\n相对路径(发给后端那种,也是 DMS 里存的位置):');
  33. console.log(' ' + relativePath);
  34. console.log('可访问地址(前端实际 fetch 的,拼了代理前缀):');
  35. console.log(' ' + displayUrl);
  36. // 立刻自检一次:这个地址真的能取回同一份 JSON(不是 404、也不是 HTML 兜底)
  37. const response = await fetch(displayUrl);
  38. const contentType = response.headers.get('content-type') || '';
  39. const text = await response.text();
  40. let parsed = null;
  41. try {
  42. parsed = JSON.parse(text);
  43. } catch {
  44. /* 下面报出来 */
  45. }
  46. const count = Array.isArray(parsed) ? parsed.length : null;
  47. console.log('\n自检:');
  48. console.log(` HTTP ${response.status} · content-type=${contentType}`);
  49. console.log(` 条数=${count ?? '(解析失败)'}${count === list.length ? ' ✓ 与本地一致' : ' ✗ 与本地不一致!'}`);
  50. if (count !== list.length) {
  51. console.error(' ⚠️ 远端内容与本地不一致,先别写进 VITE_POLICY_REMOTE_URL');
  52. process.exit(1);
  53. }
  54. console.log('\n把下面这行写进 .env.development / .env.production(生产换成 nginx 映射的同源路径):');
  55. console.log(` VITE_POLICY_REMOTE_URL="${displayUrl}"`);