|
@@ -9,6 +9,49 @@ import path from "path";
|
|
|
|
|
|
|
|
import basicSsl from "@vitejs/plugin-basic-ssl";
|
|
import basicSsl from "@vitejs/plugin-basic-ssl";
|
|
|
|
|
|
|
|
|
|
+// DMS token 的读取口径收在 harness/tools/dms-token.mjs(与本仓库的 DMS 脚本共用一份):
|
|
|
|
|
+// **显式参数 → 环境变量 → 本机文件 `.dms-token`**。
|
|
|
|
|
+// 关键是「每个请求现读」而不是启动时读一次 —— token 约 24 小时过期,以前换一次就要重启 dev server。
|
|
|
|
|
+import { DMS_TOKEN_FILE, readDmsToken, parseJwtPayload, describeDmsToken } from "./harness/tools/dms-token.mjs";
|
|
|
|
|
+
|
|
|
|
|
+/** 同一个状态只提醒一次,避免每个请求都刷屏 */
|
|
|
|
|
+let dmsTokenWarnedFor = "";
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * token 有问题时给出**明确**提示 —— 以前 token 过期是**静默失败**(DMS 写入不生效、
|
|
|
|
|
+ * 只有一条埋在别处控制台里的 warn),排查「为什么数据没存上」要花很久。
|
|
|
|
|
+ */
|
|
|
|
|
+const warnDmsTokenIfNeeded = (token: string): void => {
|
|
|
|
|
+ if (!token) {
|
|
|
|
|
+ if (dmsTokenWarnedFor === "missing") return;
|
|
|
|
|
+ dmsTokenWarnedFor = "missing";
|
|
|
|
|
+ console.warn(
|
|
|
|
|
+ `\n[dms] ⚠️ 没有 DMS token,DMS 读写(会话/问答记录/反馈)会失败,聊天本身不受影响。\n` +
|
|
|
|
|
+ `[dms] 最省事:在浏览器里复制 token,然后跑 \`npm run dms:token\`(从剪贴板读)。\n` +
|
|
|
|
|
+ `[dms] 文件位置:${DMS_TOKEN_FILE}\n`
|
|
|
|
|
+ );
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const exp = Number(parseJwtPayload(token)?.exp);
|
|
|
|
|
+ if (!Number.isFinite(exp)) return;
|
|
|
|
|
+ const leftMs = exp * 1000 - Date.now();
|
|
|
|
|
+ const at = new Date(exp * 1000).toLocaleString("zh-CN");
|
|
|
|
|
+ if (leftMs <= 0) {
|
|
|
|
|
+ if (dmsTokenWarnedFor === `expired:${exp}`) return;
|
|
|
|
|
+ dmsTokenWarnedFor = `expired:${exp}`;
|
|
|
|
|
+ console.warn(
|
|
|
|
|
+ `\n[dms] ⚠️ DMS token 已于 ${at} 过期(DMS 读写会失败)。复制新 token 后跑 \`npm run dms:token\`。\n`
|
|
|
|
|
+ );
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (leftMs < 2 * 3600 * 1000) {
|
|
|
|
|
+ const key = `soon:${exp}`;
|
|
|
|
|
+ if (dmsTokenWarnedFor === key) return;
|
|
|
|
|
+ dmsTokenWarnedFor = key;
|
|
|
|
|
+ console.warn(`\n[dms] ⏳ DMS token 将于 ${at} 过期(还剩 ${(leftMs / 3600000).toFixed(1)} 小时)。\n`);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
// https://vitejs.dev/config/
|
|
// https://vitejs.dev/config/
|
|
|
export default defineConfig(({ mode }) => {
|
|
export default defineConfig(({ mode }) => {
|
|
|
// 第三个参数传空串:不加前缀过滤,才能读到 DMS_TOKEN 这类非 VITE_ 前缀的变量
|
|
// 第三个参数传空串:不加前缀过滤,才能读到 DMS_TOKEN 这类非 VITE_ 前缀的变量
|
|
@@ -58,7 +101,19 @@ export default defineConfig(({ mode }) => {
|
|
|
target: env.VITE_DMS_TARGET || "http://121.43.55.7:10081",
|
|
target: env.VITE_DMS_TARGET || "http://121.43.55.7:10081",
|
|
|
changeOrigin: true,
|
|
changeOrigin: true,
|
|
|
rewrite: (path) => path.replace(/^\/dms-api/, "/dms"),
|
|
rewrite: (path) => path.replace(/^\/dms-api/, "/dms"),
|
|
|
- headers: env.DMS_TOKEN ? { token: env.DMS_TOKEN } : {},
|
|
|
|
|
|
|
+ // token 在**每个请求**现读(见 readDmsToken 的说明):换 token 不用重启 dev server。
|
|
|
|
|
+ // 用 configure 而不是静态 headers —— 后者的值在启动时就定死了。
|
|
|
|
|
+ configure: (proxy) => {
|
|
|
|
|
+ proxy.on("proxyReq", (proxyReq) => {
|
|
|
|
|
+ // 现读:换 token 后不需要重启 dev server
|
|
|
|
|
+ const token = readDmsToken(env.DMS_TOKEN);
|
|
|
|
|
+ if (token) {
|
|
|
|
|
+ // DMS 的鉴权头名就叫 token(不是 Authorization)
|
|
|
|
|
+ proxyReq.setHeader("token", token);
|
|
|
|
|
+ }
|
|
|
|
|
+ warnDmsTokenIfNeeded(token);
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
},
|
|
},
|
|
|
"/asr/": {
|
|
"/asr/": {
|
|
|
//匹配的路径
|
|
//匹配的路径
|