smart-admin-web 10.5.0 → 10.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/dist/api/client.js.map +1 -1
  3. package/dist/api/index.d.ts +3 -3
  4. package/dist/api/index.js +2 -2
  5. package/dist/api/index.js.map +1 -1
  6. package/dist/components/DetailPage/index.vue.js +1 -1
  7. package/dist/components/DetailPage/index2.vue.js.map +1 -1
  8. package/dist/components/IconPicker/index.vue.js.map +1 -1
  9. package/dist/components/ImportWizard/index.vue.js +1 -1
  10. package/dist/components/ImportWizard/index2.vue.js.map +1 -1
  11. package/dist/components/TableZoomButton/index.vue.js.map +1 -1
  12. package/dist/composables/useConfirm.js.map +1 -1
  13. package/dist/composables/useLayoutMenu.js.map +1 -1
  14. package/dist/composables/useRealtime.d.ts +1 -1
  15. package/dist/composables/useRealtime.js.map +1 -1
  16. package/dist/createSmartAdmin.d.ts +2 -2
  17. package/dist/createSmartAdmin.js +15 -14
  18. package/dist/createSmartAdmin.js.map +1 -1
  19. package/dist/index.js +27 -26
  20. package/dist/layouts/default.vue.js +2 -2
  21. package/dist/layouts/default2.vue.js.map +1 -1
  22. package/dist/lib/icons.js.map +1 -1
  23. package/dist/lib/markdown.js.map +1 -1
  24. package/dist/lib/runtime.js +1 -1
  25. package/dist/locales/en-US.js +1 -1
  26. package/dist/locales/en-US.js.map +1 -1
  27. package/dist/locales/zh-CN.js +2 -2
  28. package/dist/locales/zh-CN.js.map +1 -1
  29. package/dist/router/detailRoutes.js.map +1 -1
  30. package/dist/router/index.js.map +1 -1
  31. package/dist/router/routes.js +1 -1
  32. package/dist/router/routes.js.map +1 -1
  33. package/dist/stores/user.d.ts +2 -2
  34. package/dist/stores/user.js.map +1 -1
  35. package/dist/style.css +1 -1
  36. package/dist/theme/mix.d.ts +3 -3
  37. package/dist/theme/mix.js.map +1 -1
  38. package/dist/types/api.d.ts +1 -1
  39. package/dist/types/api.js.map +1 -1
  40. package/dist/utils/url.d.ts +2 -0
  41. package/dist/utils/url.js +9 -3
  42. package/dist/utils/url.js.map +1 -1
  43. package/dist/views/error/404.vue.js +2 -2
  44. package/dist/views/error/4042.vue.js.map +1 -1
  45. package/dist/views/login/skins/SplitPanel.vue.js +1 -1
  46. package/dist/views/login/skins/SplitPanel2.vue.js.map +1 -1
  47. package/dist/views/system/log/op/index.vue.js +1 -1
  48. package/dist/views/system/log/op/index2.vue.js +1 -1
  49. package/dist/views/system/log/op/index2.vue.js.map +1 -1
  50. package/dist/views/system/menu/components/ButtonManager.vue.js +1 -1
  51. package/dist/views/system/menu/components/ButtonManager2.vue.js.map +1 -1
  52. package/dist/views/system/menu/components/MenuFormModal.vue.js +3 -3
  53. package/dist/views/system/menu/components/MenuFormModal2.vue.js.map +1 -1
  54. package/dist/views/system/menu/index.vue.js +2 -2
  55. package/dist/views/system/menu/index2.vue.js +6 -6
  56. package/dist/views/system/menu/index2.vue.js.map +1 -1
  57. package/dist/views/system/module/index.vue.js +2 -2
  58. package/dist/views/system/module/index2.vue.js +2 -2
  59. package/dist/views/system/module/index2.vue.js.map +1 -1
  60. package/dist/views/system/user/components/ResetPasswordModal.vue.js +1 -1
  61. package/dist/views/system/user/components/ResetPasswordModal2.vue.js.map +1 -1
  62. package/dist/views/system/user/components/UserFormModal.vue.js +1 -1
  63. package/dist/views/system/user/components/UserFormModal2.vue.js.map +1 -1
  64. package/package.json +1 -1
package/README.md CHANGED
@@ -65,7 +65,7 @@ import { SmartTable } from 'smart-naive-table'
65
65
 
66
66
  ## 版本
67
67
 
68
- 版本号与 NuGet 包 `SmartAdmin` 一致:主版本 = 内核所用的 .NET 主版本,次版本加功能,修订号修 bug。内置页照同一版后端的接口写,所以 `package.json` 里精确钉住版本、不带 `^`;升级时 `Directory.Packages.props` 与 `package.json` 填同一个数字,改动见 [CHANGELOG](https://github.com/SmartCode-X/SmartAdmin/blob/main/CHANGELOG.md)。
68
+ 版本号与 NuGet 包 `SmartAdmin` 一致:主版本 = 内核所用的 .NET 主版本,次版本加功能,修订号修 bug。内置页照同一版后端的接口写,所以 `package.json` 里精确钉住版本、不带 `^`;升级时后端的 `SmartAdmin` 包与前端的 `smart-admin-web` 填同一个数字,改动见 [CHANGELOG](https://github.com/SmartCode-X/SmartAdmin/blob/main/CHANGELOG.md)。
69
69
 
70
70
  ## 文档
71
71
 
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sources":["../../src/api/client.ts"],"sourcesContent":["import createClient, { type Client, type Middleware } from 'openapi-fetch'\nimport type { paths } from './schema'\nimport { useUserStore } from '#/stores/user'\nimport { runtime } from '#/lib/runtime'\nimport { REAUTH_REQUIRED_CODE, REAUTH_RETRY_HEADER, requestReauth } from './reauthGate'\n\n// 默认空 apiBase = 同源:schema 的 path 键已含 /api/v1,dev 下由 Vite proxy 反代到后端(默认 :5100),\n// 生产下由 nginx 反代或后端自己托管 dist(见 docs/deployment.md 路线 A/B)。\n// 只有前端与 API 真的不同源(CDN / 独立域名)时才需要 createSmartAdmin({ apiBase: 'https://api.example.com' }),\n// 此时后端还必须配 SmartAdmin:Api:Cors:AllowedOrigins(默认 deny-all)。\n\n/**\n * 请求超时:没有超时的话,后端卡死或链路半开时 fetch 会一直挂着 —— 页面永远转圈,\n * 按钮的 loading 永不结束,用户只能刷新。\n * 默认 30 秒;上传/分片/导出/导入提交这类天然慢的调用在 api 层显式传 `timeout: LONG_TIMEOUT_MS`。\n */\nexport const DEFAULT_TIMEOUT_MS = 30_000\nexport const LONG_TIMEOUT_MS = 10 * 60_000\n\n/** 与后端 AuthCookieNames 对齐(禁硬编码纪律的前端镜像)。 */\nconst CSRF_COOKIE = 'smart_csrf'\nconst CSRF_HEADER = 'X-Smart-CSRF'\n\n/**\n * 读 document.cookie 中的可读 Cookie(双提交 CSRF 的 smart_csrf)。\n * HttpOnly 的 smart_rt 读不到,只能靠 credentials 自动携带。\n */\nexport function readCookie(name: string): string {\n if (typeof document === 'undefined') return ''\n const parts = document.cookie.split(';')\n for (const part of parts) {\n const i = part.indexOf('=')\n if (i < 0) continue\n const k = part.slice(0, i).trim()\n if (k === name) return decodeURIComponent(part.slice(i + 1).trim())\n }\n return ''\n}\n\n/** 写请求是否需要附 CSRF(有可读 CSRF Cookie 即附;无 Cookie 时不附)。 */\nfunction isMutating(method: string): boolean {\n const m = method.toUpperCase()\n return m !== 'GET' && m !== 'HEAD' && m !== 'OPTIONS'\n}\n\nfunction attachCsrf(headers: Headers) {\n const csrf = readCookie(CSRF_COOKIE)\n if (csrf) headers.set(CSRF_HEADER, csrf)\n}\n\n/**\n * 给每个请求装超时闸。必须**最先**注册:后面的重放中间件要克隆最终的 Request,顺序反了就克隆到旧的那份。\n *\n * 调用方传的 `signal` 依然生效 —— 这里用 `AbortSignal.any` 把它和超时信号并起来,谁先响算谁,\n * 不是把调用方的取消能力顶掉。单次调用要放宽时限就多传一个 `timeout`(毫秒),\n * openapi-fetch 会把它这类自定义键原样挂到 Request 上(见其 InitParam 的 `[key: string]: unknown`)。\n */\nconst timeoutMiddleware: Middleware = {\n onRequest({ request }) {\n const ms = (request as Request & { timeout?: unknown }).timeout\n const limit = typeof ms === 'number' && ms > 0 ? ms : DEFAULT_TIMEOUT_MS\n return new Request(request, {\n signal: AbortSignal.any([request.signal, AbortSignal.timeout(limit)]),\n })\n },\n}\n\n/** 请求前注入 Bearer + 写操作 CSRF。请求时读 store,始终拿最新令牌。 */\nconst authMiddleware: Middleware = {\n async onRequest({ request }) {\n const token = useUserStore().accessToken\n if (token) request.headers.set('Authorization', `Bearer ${token}`)\n if (isMutating(request.method)) attachCsrf(request.headers)\n return request\n },\n}\n\n// 令牌过期重放:Request 的 body 是一次性流,首次 fetch 就被消费,直接重放会丢 body\n//(GET 无 body 不受影响,但令牌恰好在一次 POST/PUT 时过期就会丢请求体)。\n// 发出前克隆一份副本(clone 会 tee body 流,与原请求各读各的),重放时用这份未消费的副本。\n// 键是发出前的 Request 实例(openapi-fetch 把它一路带到 onResponse),WeakMap 随请求回收自动清理。\nconst replayable = new WeakMap<Request, Request>()\n\n// 并发 401 合流到同一次刷新。\nlet refreshing: Promise<boolean> | null = null\n\n/** 单飞静默刷新;路由守卫 F5 重建 Cookie 会话时也可调用。 */\nexport function refreshOnce(): Promise<boolean> {\n refreshing ??= doRefresh().finally(() => {\n refreshing = null\n })\n return refreshing\n}\n\n/**\n * 确保有可用 accessToken:已有则 true;Cookie 会话或 body refresh 则尝试静默刷新。\n * 供路由守卫在 F5/深链时恢复内存令牌。\n */\nexport async function ensureAccessToken(): Promise<boolean> {\n const user = useUserStore()\n if (user.accessToken) return true\n if (!user.cookieSession && !user.refreshToken) return false\n return refreshOnce()\n}\n\nasync function doRefresh(): Promise<boolean> {\n const user = useUserStore()\n // Cookie 会话:body 不带 refresh(服务端读 smart_rt);body 模式:必须有 refreshToken\n if (!user.cookieSession && !user.refreshToken) return false\n\n const headers: Record<string, string> = {}\n if (user.cookieSession || readCookie(CSRF_COOKIE)) {\n const csrf = readCookie(CSRF_COOKIE)\n if (csrf) headers[CSRF_HEADER] = csrf\n }\n\n const { data, error } = await bare.POST('/api/v1/auth/refresh', {\n // Cookie 模式刷新令牌在 HttpOnly Cookie 里,body 的 refreshToken 留空:服务端 body 为空才读 Cookie\n body: user.cookieSession ? { refreshToken: '' } : { refreshToken: user.refreshToken },\n headers,\n })\n const env = data as { code?: number; data?: unknown } | undefined\n if (error || !env || env.code !== 0 || !env.data) return false\n user.setSession(env.data as Parameters<typeof user.setSession>[0])\n return true\n}\n\n/** 401 → 刷新一次并重放原请求;刷新失败 → 清会话 + 跳登录。 */\nconst refreshMiddleware: Middleware = {\n onRequest({ request }) {\n // 带 body 的写请求发出前存一份可重放副本(GET/HEAD 无 body,不必克隆)。\n if (request.method !== 'GET' && request.method !== 'HEAD')\n replayable.set(request, request.clone())\n return request\n },\n async onResponse({ request, response }) {\n if (response.status !== 401) return response\n const url = request.url\n if (url.includes('/api/v1/auth/refresh') || url.includes('/api/v1/auth/login')) return response\n\n const ok = await refreshOnce()\n if (!ok) {\n useUserStore().clear()\n const { useAuthStore } = await import('#/stores/auth')\n useAuthStore().reset()\n const { router, resetRouter } = await import('#/router') // 惰性引入,避免与 router 静态循环依赖\n resetRouter()\n if (router.currentRoute.value.path !== '/login') router.replace('/login')\n return response\n }\n // 重放:优先用发出前的克隆副本(body 未被消费),无副本的 GET 直接用原请求;裸 fetch 绕过中间件,手动补新令牌 + CSRF。\n const base = replayable.get(request) ?? request\n const retry = new Request(base, { headers: new Headers(base.headers), credentials: 'include' })\n retry.headers.set('Authorization', `Bearer ${useUserStore().accessToken}`)\n if (isMutating(retry.method)) attachCsrf(retry.headers)\n return fetch(retry)\n },\n}\n\n/**\n * 403 + 40024(ReauthRequired) → 弹再认证 → 成功后重放一次。\n * 与 refresh 同形:依赖 onRequest 预克隆 body;重试头防死循环。\n */\nconst reauthMiddleware: Middleware = {\n async onResponse({ request, response }) {\n if (response.status !== 403) return response\n if (request.headers.get(REAUTH_RETRY_HEADER) === '1') return response\n if (request.url.includes('/api/v1/auth/reauth') || request.url.includes('/api/v1/auth/login')) {\n return response\n }\n\n let code: number | undefined\n try {\n const body = (await response.clone().json()) as { code?: number }\n code = body?.code\n } catch {\n return response\n }\n if (code !== REAUTH_REQUIRED_CODE) return response\n\n const granted = await requestReauth()\n if (!granted) return response\n\n const base = replayable.get(request) ?? request\n const retry = new Request(base, { headers: new Headers(base.headers), credentials: 'include' })\n const token = useUserStore().accessToken\n if (token) retry.headers.set('Authorization', `Bearer ${token}`)\n if (isMutating(retry.method)) attachCsrf(retry.headers)\n retry.headers.set(REAUTH_RETRY_HEADER, '1')\n return fetch(retry)\n },\n}\n\n/** 内核同款中间件链:超时必须最先(后面两个要克隆最终 Request 做重放)→ Bearer + CSRF → 401 刷新重放 → 40024 再认证。 */\nfunction attachMiddlewares<P extends {}>(c: Client<P>): Client<P> {\n c.use(timeoutMiddleware)\n c.use(authMiddleware)\n c.use(refreshMiddleware)\n c.use(reauthMiddleware)\n return c\n}\n\n/**\n * 按调用时的 runtime.apiBase 取客户端。客户端大多在模块顶层创建(`export const client = createApiClient()`),\n * 那时 createSmartAdmin 可能还没跑、apiBase 尚未落定;所以每次调用前核对一次,变了就按新地址重建,\n * 调用方后加的中间件(use)一并带过去。\n */\nfunction followApiBase<P extends {}>(build: (baseUrl: string) => Client<P>): Client<P> {\n let base = runtime.apiBase\n let inner = build(base)\n const added: Middleware[] = []\n const current = () => {\n if (base !== runtime.apiBase) {\n base = runtime.apiBase\n inner = build(base)\n if (added.length) inner.use(...added)\n }\n return inner\n }\n return new Proxy({} as Client<P>, {\n get(_target, key) {\n if (key === 'use')\n return (...mw: Middleware[]) => {\n added.push(...mw)\n current().use(...mw)\n }\n if (key === 'eject')\n return (...mw: Middleware[]) => {\n for (const m of mw) {\n const i = added.indexOf(m)\n if (i >= 0) added.splice(i, 1)\n }\n current().eject(...mw)\n }\n const c = current() as unknown as Record<PropertyKey, unknown>\n const v = c[key]\n return typeof v === 'function' ? (v as (...args: unknown[]) => unknown).bind(c) : v\n },\n })\n}\n\n/**\n * 消费方自己端点的类型化客户端:与内核 client 同 apiBase、同一条中间件链,只是 paths 换成自己生成的 schema。\n * credentials:'include'——Cookie 会话(Session:CookieMode)静默刷新/登出依赖 HttpOnly refresh Cookie;\n * 同源默认也会带 Cookie,显式 include 覆盖 apiBase 跨源场景(需后端 CORS AllowCredentials)。\n */\nexport function createApiClient<P extends {}>(): Client<P> {\n return followApiBase(baseUrl =>\n attachMiddlewares(createClient<P>({ baseUrl, credentials: 'include' })),\n )\n}\n\n/** 内核客户端(内核端点的 paths)。 */\nexport const client = createApiClient<paths>()\n\n// 刷新专用客户端:不挂刷新中间件,避免刷新自身 401 触发递归;\n// 但也要有超时闸:它挂住时路由守卫会一起卡在 ensureAccessToken 上,整页停在白屏。\nconst bare = followApiBase(baseUrl => {\n const c = createClient<paths>({ baseUrl, credentials: 'include' })\n c.use(timeoutMiddleware)\n return c\n})\n"],"names":["DEFAULT_TIMEOUT_MS","LONG_TIMEOUT_MS","CSRF_COOKIE","CSRF_HEADER","readCookie","name","parts","part","i","isMutating","method","m","attachCsrf","headers","csrf","timeoutMiddleware","request","ms","limit","authMiddleware","token","useUserStore","replayable","refreshing","refreshOnce","doRefresh","ensureAccessToken","user","data","error","bare","env","refreshMiddleware","response","url","useAuthStore","router","resetRouter","base","retry","reauthMiddleware","REAUTH_RETRY_HEADER","code","body","REAUTH_REQUIRED_CODE","requestReauth","attachMiddlewares","c","followApiBase","build","runtime","inner","added","current","_target","key","mw","v","createApiClient","baseUrl","createClient","client"],"mappings":";;;;AAgBO,MAAMA,IAAqB,KACrBC,IAAkB,KAAK,KAG9BC,IAAc,cACdC,IAAc;AAMb,SAASC,EAAWC,GAAsB;AAC/C,MAAI,OAAO,WAAa,IAAa,QAAO;AAC5C,QAAMC,IAAQ,SAAS,OAAO,MAAM,GAAG;AACvC,aAAWC,KAAQD,GAAO;AACxB,UAAME,IAAID,EAAK,QAAQ,GAAG;AAC1B,QAAIC,IAAI,EAAG;AAEX,QADUD,EAAK,MAAM,GAAGC,CAAC,EAAE,KAAA,MACjBH,EAAM,QAAO,mBAAmBE,EAAK,MAAMC,IAAI,CAAC,EAAE,MAAM;AAAA,EACpE;AACA,SAAO;AACT;AAGA,SAASC,EAAWC,GAAyB;AAC3C,QAAMC,IAAID,EAAO,YAAA;AACjB,SAAOC,MAAM,SAASA,MAAM,UAAUA,MAAM;AAC9C;AAEA,SAASC,EAAWC,GAAkB;AACpC,QAAMC,IAAOV,EAAWF,CAAW;AACnC,EAAIY,KAAMD,EAAQ,IAAIV,GAAaW,CAAI;AACzC;AASA,MAAMC,IAAgC;AAAA,EACpC,UAAU,EAAE,SAAAC,KAAW;AACrB,UAAMC,IAAMD,EAA4C,SAClDE,IAAQ,OAAOD,KAAO,YAAYA,IAAK,IAAIA,IAAKjB;AACtD,WAAO,IAAI,QAAQgB,GAAS;AAAA,MAC1B,QAAQ,YAAY,IAAI,CAACA,EAAQ,QAAQ,YAAY,QAAQE,CAAK,CAAC,CAAC;AAAA,IAAA,CACrE;AAAA,EACH;AACF,GAGMC,IAA6B;AAAA,EACjC,MAAM,UAAU,EAAE,SAAAH,KAAW;AAC3B,UAAMI,IAAQC,IAAe;AAC7B,WAAID,KAAOJ,EAAQ,QAAQ,IAAI,iBAAiB,UAAUI,CAAK,EAAE,GAC7DX,EAAWO,EAAQ,MAAM,KAAGJ,EAAWI,EAAQ,OAAO,GACnDA;AAAA,EACT;AACF,GAMMM,wBAAiB,QAAA;AAGvB,IAAIC,IAAsC;AAGnC,SAASC,IAAgC;AAC9C,SAAAD,UAAeE,IAAY,QAAQ,MAAM;AACvC,IAAAF,IAAa;AAAA,EACf,CAAC,IACMA;AACT;AAMA,eAAsBG,IAAsC;AAC1D,QAAMC,IAAON,EAAA;AACb,SAAIM,EAAK,cAAoB,KACzB,CAACA,EAAK,iBAAiB,CAACA,EAAK,eAAqB,KAC/CH,EAAA;AACT;AAEA,eAAeC,IAA8B;AAC3C,QAAME,IAAON,EAAA;AAEb,MAAI,CAACM,EAAK,iBAAiB,CAACA,EAAK,aAAc,QAAO;AAEtD,QAAMd,IAAkC,CAAA;AACxC,MAAIc,EAAK,iBAAiBvB,EAAWF,CAAW,GAAG;AACjD,UAAMY,IAAOV,EAAWF,CAAW;AACnC,IAAIY,MAAMD,EAAQV,CAAW,IAAIW;AAAA,EACnC;AAEA,QAAM,EAAE,MAAAc,GAAM,OAAAC,EAAA,IAAU,MAAMC,EAAK,KAAK,wBAAwB;AAAA;AAAA,IAE9D,MAAMH,EAAK,gBAAgB,EAAE,cAAc,OAAO,EAAE,cAAcA,EAAK,aAAA;AAAA,IACvE,SAAAd;AAAA,EAAA,CACD,GACKkB,IAAMH;AACZ,SAAIC,KAAS,CAACE,KAAOA,EAAI,SAAS,KAAK,CAACA,EAAI,OAAa,MACzDJ,EAAK,WAAWI,EAAI,IAA6C,GAC1D;AACT;AAGA,MAAMC,IAAgC;AAAA,EACpC,UAAU,EAAE,SAAAhB,KAAW;AAErB,WAAIA,EAAQ,WAAW,SAASA,EAAQ,WAAW,UACjDM,EAAW,IAAIN,GAASA,EAAQ,MAAA,CAAO,GAClCA;AAAA,EACT;AAAA,EACA,MAAM,WAAW,EAAE,SAAAA,GAAS,UAAAiB,KAAY;AACtC,QAAIA,EAAS,WAAW,IAAK,QAAOA;AACpC,UAAMC,IAAMlB,EAAQ;AACpB,QAAIkB,EAAI,SAAS,sBAAsB,KAAKA,EAAI,SAAS,oBAAoB,EAAG,QAAOD;AAGvF,QAAI,CADO,MAAMT,EAAA,GACR;AACP,MAAAH,EAAA,EAAe,MAAA;AACf,YAAM,EAAE,cAAAc,EAAA,IAAiB,MAAM,OAAO,mBAAe;AACrD,MAAAA,EAAA,EAAe,MAAA;AACf,YAAM,EAAE,QAAAC,GAAQ,aAAAC,MAAgB,MAAM,OAAO,oBAAU;AACvD,aAAAA,EAAA,GACID,EAAO,aAAa,MAAM,SAAS,YAAUA,EAAO,QAAQ,QAAQ,GACjEH;AAAA,IACT;AAEA,UAAMK,IAAOhB,EAAW,IAAIN,CAAO,KAAKA,GAClCuB,IAAQ,IAAI,QAAQD,GAAM,EAAE,SAAS,IAAI,QAAQA,EAAK,OAAO,GAAG,aAAa,WAAW;AAC9F,WAAAC,EAAM,QAAQ,IAAI,iBAAiB,UAAUlB,EAAA,EAAe,WAAW,EAAE,GACrEZ,EAAW8B,EAAM,MAAM,KAAG3B,EAAW2B,EAAM,OAAO,GAC/C,MAAMA,CAAK;AAAA,EACpB;AACF,GAMMC,IAA+B;AAAA,EACnC,MAAM,WAAW,EAAE,SAAAxB,GAAS,UAAAiB,KAAY;AAGtC,QAFIA,EAAS,WAAW,OACpBjB,EAAQ,QAAQ,IAAIyB,CAAmB,MAAM,OAC7CzB,EAAQ,IAAI,SAAS,qBAAqB,KAAKA,EAAQ,IAAI,SAAS,oBAAoB;AAC1F,aAAOiB;AAGT,QAAIS;AACJ,QAAI;AACF,YAAMC,IAAQ,MAAMV,EAAS,MAAA,EAAQ,KAAA;AACrC,MAAAS,IAAOC,KAAA,gBAAAA,EAAM;AAAA,IACf,QAAQ;AACN,aAAOV;AAAA,IACT;AAIA,QAHIS,MAASE,KAGT,CADY,MAAMC,EAAA,EACR,QAAOZ;AAErB,UAAMK,IAAOhB,EAAW,IAAIN,CAAO,KAAKA,GAClCuB,IAAQ,IAAI,QAAQD,GAAM,EAAE,SAAS,IAAI,QAAQA,EAAK,OAAO,GAAG,aAAa,WAAW,GACxFlB,IAAQC,IAAe;AAC7B,WAAID,KAAOmB,EAAM,QAAQ,IAAI,iBAAiB,UAAUnB,CAAK,EAAE,GAC3DX,EAAW8B,EAAM,MAAM,KAAG3B,EAAW2B,EAAM,OAAO,GACtDA,EAAM,QAAQ,IAAIE,GAAqB,GAAG,GACnC,MAAMF,CAAK;AAAA,EACpB;AACF;AAGA,SAASO,EAAgCC,GAAyB;AAChE,SAAAA,EAAE,IAAIhC,CAAiB,GACvBgC,EAAE,IAAI5B,CAAc,GACpB4B,EAAE,IAAIf,CAAiB,GACvBe,EAAE,IAAIP,CAAgB,GACfO;AACT;AAOA,SAASC,EAA4BC,GAAkD;AACrF,MAAIX,IAAOY,EAAQ,SACfC,IAAQF,EAAMX,CAAI;AACtB,QAAMc,IAAsB,CAAA,GACtBC,IAAU,OACVf,MAASY,EAAQ,YACnBZ,IAAOY,EAAQ,SACfC,IAAQF,EAAMX,CAAI,GACdc,EAAM,UAAQD,EAAM,IAAI,GAAGC,CAAK,IAE/BD;AAET,SAAO,IAAI,MAAM,IAAiB;AAAA,IAChC,IAAIG,GAASC,GAAK;AAChB,UAAIA,MAAQ;AACV,eAAO,IAAIC,MAAqB;AAC9B,UAAAJ,EAAM,KAAK,GAAGI,CAAE,GAChBH,EAAA,EAAU,IAAI,GAAGG,CAAE;AAAA,QACrB;AACF,UAAID,MAAQ;AACV,eAAO,IAAIC,MAAqB;AAC9B,qBAAW7C,KAAK6C,GAAI;AAClB,kBAAMhD,IAAI4C,EAAM,QAAQzC,CAAC;AACzB,YAAIH,KAAK,KAAG4C,EAAM,OAAO5C,GAAG,CAAC;AAAA,UAC/B;AACA,UAAA6C,EAAA,EAAU,MAAM,GAAGG,CAAE;AAAA,QACvB;AACF,YAAMT,IAAIM,EAAA,GACJI,IAAIV,EAAEQ,CAAG;AACf,aAAO,OAAOE,KAAM,aAAcA,EAAsC,KAAKV,CAAC,IAAIU;AAAA,IACpF;AAAA,EAAA,CACD;AACH;AAOO,SAASC,IAA2C;AACzD,SAAOV;AAAA,IAAc,CAAAW,MACnBb,EAAkBc,EAAgB,EAAE,SAAAD,GAAS,aAAa,WAAW,CAAC;AAAA,EAAA;AAE1E;AAGO,MAAME,IAASH,EAAA,GAIhB5B,IAAOkB,EAAc,CAAAW,MAAW;AACpC,QAAMZ,IAAIa,EAAoB,EAAE,SAAAD,GAAS,aAAa,WAAW;AACjE,SAAAZ,EAAE,IAAIhC,CAAiB,GAChBgC;AACT,CAAC;"}
1
+ {"version":3,"file":"client.js","sources":["../../src/api/client.ts"],"sourcesContent":["import createClient, { type Client, type Middleware } from 'openapi-fetch'\nimport type { paths } from './schema'\nimport { useUserStore } from '#/stores/user'\nimport { runtime } from '#/lib/runtime'\nimport { REAUTH_REQUIRED_CODE, REAUTH_RETRY_HEADER, requestReauth } from './reauthGate'\n\n// 默认空 apiBase = 同源:schema 的 path 键已含 /api/v1,dev 下由 Vite proxy 反代到后端(默认 :5100),\n// 生产下由 nginx 反代或后端自己托管 dist(见文档站部署指南的路线 A / B)。\n// 只有前端与 API 真的不同源(CDN / 独立域名)时才需要 createSmartAdmin({ apiBase: 'https://api.example.com' }),\n// 此时后端还必须配 SmartAdmin:Api:Cors:AllowedOrigins(默认 deny-all)。\n\n/**\n * 请求超时:没有超时的话,后端卡死或链路半开时 fetch 会一直挂着 —— 页面永远转圈,\n * 按钮的 loading 永不结束,用户只能刷新。\n * 默认 30 秒;上传/分片/导出/导入提交这类天然慢的调用在 api 层显式传 `timeout: LONG_TIMEOUT_MS`。\n */\nexport const DEFAULT_TIMEOUT_MS = 30_000\nexport const LONG_TIMEOUT_MS = 10 * 60_000\n\n/** 与后端 AuthCookieNames 对齐(禁硬编码纪律的前端镜像)。 */\nconst CSRF_COOKIE = 'smart_csrf'\nconst CSRF_HEADER = 'X-Smart-CSRF'\n\n/**\n * 读 document.cookie 中的可读 Cookie(双提交 CSRF 的 smart_csrf)。\n * HttpOnly 的 smart_rt 读不到,只能靠 credentials 自动携带。\n */\nexport function readCookie(name: string): string {\n if (typeof document === 'undefined') return ''\n const parts = document.cookie.split(';')\n for (const part of parts) {\n const i = part.indexOf('=')\n if (i < 0) continue\n const k = part.slice(0, i).trim()\n if (k === name) return decodeURIComponent(part.slice(i + 1).trim())\n }\n return ''\n}\n\n/** 写请求是否需要附 CSRF(有可读 CSRF Cookie 即附;无 Cookie 时不附)。 */\nfunction isMutating(method: string): boolean {\n const m = method.toUpperCase()\n return m !== 'GET' && m !== 'HEAD' && m !== 'OPTIONS'\n}\n\nfunction attachCsrf(headers: Headers) {\n const csrf = readCookie(CSRF_COOKIE)\n if (csrf) headers.set(CSRF_HEADER, csrf)\n}\n\n/**\n * 给每个请求装超时闸。必须**最先**注册:后面的重放中间件要克隆最终的 Request,顺序反了就克隆到旧的那份。\n *\n * 调用方传的 `signal` 依然生效 —— 这里用 `AbortSignal.any` 把它和超时信号并起来,谁先响算谁,\n * 不是把调用方的取消能力顶掉。单次调用要放宽时限就多传一个 `timeout`(毫秒),\n * openapi-fetch 会把它这类自定义键原样挂到 Request 上(见其 InitParam 的 `[key: string]: unknown`)。\n */\nconst timeoutMiddleware: Middleware = {\n onRequest({ request }) {\n const ms = (request as Request & { timeout?: unknown }).timeout\n const limit = typeof ms === 'number' && ms > 0 ? ms : DEFAULT_TIMEOUT_MS\n return new Request(request, {\n signal: AbortSignal.any([request.signal, AbortSignal.timeout(limit)]),\n })\n },\n}\n\n/** 请求前注入 Bearer + 写操作 CSRF。请求时读 store,始终拿最新令牌。 */\nconst authMiddleware: Middleware = {\n async onRequest({ request }) {\n const token = useUserStore().accessToken\n if (token) request.headers.set('Authorization', `Bearer ${token}`)\n if (isMutating(request.method)) attachCsrf(request.headers)\n return request\n },\n}\n\n// 令牌过期重放:Request 的 body 是一次性流,首次 fetch 就被消费,直接重放会丢 body\n//(GET 无 body 不受影响,但令牌恰好在一次 POST/PUT 时过期就会丢请求体)。\n// 发出前克隆一份副本(clone 会 tee body 流,与原请求各读各的),重放时用这份未消费的副本。\n// 键是发出前的 Request 实例(openapi-fetch 把它一路带到 onResponse),WeakMap 随请求回收自动清理。\nconst replayable = new WeakMap<Request, Request>()\n\n// 并发 401 合流到同一次刷新。\nlet refreshing: Promise<boolean> | null = null\n\n/** 单飞静默刷新;路由守卫 F5 重建 Cookie 会话时也可调用。 */\nexport function refreshOnce(): Promise<boolean> {\n refreshing ??= doRefresh().finally(() => {\n refreshing = null\n })\n return refreshing\n}\n\n/**\n * 确保有可用 accessToken:已有则 true;Cookie 会话或 body refresh 则尝试静默刷新。\n * 供路由守卫在 F5/深链时恢复内存令牌。\n */\nexport async function ensureAccessToken(): Promise<boolean> {\n const user = useUserStore()\n if (user.accessToken) return true\n if (!user.cookieSession && !user.refreshToken) return false\n return refreshOnce()\n}\n\nasync function doRefresh(): Promise<boolean> {\n const user = useUserStore()\n // Cookie 会话:body 不带 refresh(服务端读 smart_rt);body 模式:必须有 refreshToken\n if (!user.cookieSession && !user.refreshToken) return false\n\n const headers: Record<string, string> = {}\n if (user.cookieSession || readCookie(CSRF_COOKIE)) {\n const csrf = readCookie(CSRF_COOKIE)\n if (csrf) headers[CSRF_HEADER] = csrf\n }\n\n const { data, error } = await bare.POST('/api/v1/auth/refresh', {\n // Cookie 模式刷新令牌在 HttpOnly Cookie 里,body 的 refreshToken 留空:服务端 body 为空才读 Cookie\n body: user.cookieSession ? { refreshToken: '' } : { refreshToken: user.refreshToken },\n headers,\n })\n const env = data as { code?: number; data?: unknown } | undefined\n if (error || !env || env.code !== 0 || !env.data) return false\n user.setSession(env.data as Parameters<typeof user.setSession>[0])\n return true\n}\n\n/** 401 → 刷新一次并重放原请求;刷新失败 → 清会话 + 跳登录。 */\nconst refreshMiddleware: Middleware = {\n onRequest({ request }) {\n // 带 body 的写请求发出前存一份可重放副本(GET/HEAD 无 body,不必克隆)。\n if (request.method !== 'GET' && request.method !== 'HEAD')\n replayable.set(request, request.clone())\n return request\n },\n async onResponse({ request, response }) {\n if (response.status !== 401) return response\n const url = request.url\n if (url.includes('/api/v1/auth/refresh') || url.includes('/api/v1/auth/login')) return response\n\n const ok = await refreshOnce()\n if (!ok) {\n useUserStore().clear()\n const { useAuthStore } = await import('#/stores/auth')\n useAuthStore().reset()\n const { router, resetRouter } = await import('#/router') // 惰性引入,避免与 router 静态循环依赖\n resetRouter()\n if (router.currentRoute.value.path !== '/login') router.replace('/login')\n return response\n }\n // 重放:优先用发出前的克隆副本(body 未被消费),无副本的 GET 直接用原请求;裸 fetch 绕过中间件,手动补新令牌 + CSRF。\n const base = replayable.get(request) ?? request\n const retry = new Request(base, { headers: new Headers(base.headers), credentials: 'include' })\n retry.headers.set('Authorization', `Bearer ${useUserStore().accessToken}`)\n if (isMutating(retry.method)) attachCsrf(retry.headers)\n return fetch(retry)\n },\n}\n\n/**\n * 403 + 40024(ReauthRequired) → 弹再认证 → 成功后重放一次。\n * 与 refresh 同形:依赖 onRequest 预克隆 body;重试头防死循环。\n */\nconst reauthMiddleware: Middleware = {\n async onResponse({ request, response }) {\n if (response.status !== 403) return response\n if (request.headers.get(REAUTH_RETRY_HEADER) === '1') return response\n if (request.url.includes('/api/v1/auth/reauth') || request.url.includes('/api/v1/auth/login')) {\n return response\n }\n\n let code: number | undefined\n try {\n const body = (await response.clone().json()) as { code?: number }\n code = body?.code\n } catch {\n return response\n }\n if (code !== REAUTH_REQUIRED_CODE) return response\n\n const granted = await requestReauth()\n if (!granted) return response\n\n const base = replayable.get(request) ?? request\n const retry = new Request(base, { headers: new Headers(base.headers), credentials: 'include' })\n const token = useUserStore().accessToken\n if (token) retry.headers.set('Authorization', `Bearer ${token}`)\n if (isMutating(retry.method)) attachCsrf(retry.headers)\n retry.headers.set(REAUTH_RETRY_HEADER, '1')\n return fetch(retry)\n },\n}\n\n/** 内核同款中间件链:超时必须最先(后面两个要克隆最终 Request 做重放)→ Bearer + CSRF → 401 刷新重放 → 40024 再认证。 */\nfunction attachMiddlewares<P extends {}>(c: Client<P>): Client<P> {\n c.use(timeoutMiddleware)\n c.use(authMiddleware)\n c.use(refreshMiddleware)\n c.use(reauthMiddleware)\n return c\n}\n\n/**\n * 按调用时的 runtime.apiBase 取客户端。客户端大多在模块顶层创建(`export const client = createApiClient()`),\n * 那时 createSmartAdmin 可能还没跑、apiBase 尚未落定;所以每次调用前核对一次,变了就按新地址重建,\n * 调用方后加的中间件(use)一并带过去。\n */\nfunction followApiBase<P extends {}>(build: (baseUrl: string) => Client<P>): Client<P> {\n let base = runtime.apiBase\n let inner = build(base)\n const added: Middleware[] = []\n const current = () => {\n if (base !== runtime.apiBase) {\n base = runtime.apiBase\n inner = build(base)\n if (added.length) inner.use(...added)\n }\n return inner\n }\n return new Proxy({} as Client<P>, {\n get(_target, key) {\n if (key === 'use')\n return (...mw: Middleware[]) => {\n added.push(...mw)\n current().use(...mw)\n }\n if (key === 'eject')\n return (...mw: Middleware[]) => {\n for (const m of mw) {\n const i = added.indexOf(m)\n if (i >= 0) added.splice(i, 1)\n }\n current().eject(...mw)\n }\n const c = current() as unknown as Record<PropertyKey, unknown>\n const v = c[key]\n return typeof v === 'function' ? (v as (...args: unknown[]) => unknown).bind(c) : v\n },\n })\n}\n\n/**\n * 消费方自己端点的类型化客户端:与内核 client 同 apiBase、同一条中间件链,只是 paths 换成自己生成的 schema。\n * credentials:'include'——Cookie 会话(Session:CookieMode)静默刷新/登出依赖 HttpOnly refresh Cookie;\n * 同源默认也会带 Cookie,显式 include 覆盖 apiBase 跨源场景(需后端 CORS AllowCredentials)。\n */\nexport function createApiClient<P extends {}>(): Client<P> {\n return followApiBase(baseUrl =>\n attachMiddlewares(createClient<P>({ baseUrl, credentials: 'include' })),\n )\n}\n\n/** 内核客户端(内核端点的 paths)。 */\nexport const client = createApiClient<paths>()\n\n// 刷新专用客户端:不挂刷新中间件,避免刷新自身 401 触发递归;\n// 但也要有超时闸:它挂住时路由守卫会一起卡在 ensureAccessToken 上,整页停在白屏。\nconst bare = followApiBase(baseUrl => {\n const c = createClient<paths>({ baseUrl, credentials: 'include' })\n c.use(timeoutMiddleware)\n return c\n})\n"],"names":["DEFAULT_TIMEOUT_MS","LONG_TIMEOUT_MS","CSRF_COOKIE","CSRF_HEADER","readCookie","name","parts","part","i","isMutating","method","m","attachCsrf","headers","csrf","timeoutMiddleware","request","ms","limit","authMiddleware","token","useUserStore","replayable","refreshing","refreshOnce","doRefresh","ensureAccessToken","user","data","error","bare","env","refreshMiddleware","response","url","useAuthStore","router","resetRouter","base","retry","reauthMiddleware","REAUTH_RETRY_HEADER","code","body","REAUTH_REQUIRED_CODE","requestReauth","attachMiddlewares","c","followApiBase","build","runtime","inner","added","current","_target","key","mw","v","createApiClient","baseUrl","createClient","client"],"mappings":"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"}
@@ -81,7 +81,7 @@ export declare function toPage<T>(res: Parameters<typeof unwrap>[0]): {
81
81
  total: number;
82
82
  };
83
83
  /**
84
- * 下载 xlsx 等二进制:parseAs blob + 手查 ok(坑 2:unwrap 假定 JSON 信封)。
84
+ * 下载 xlsx 等二进制:parseAs blob + 手查 ok(unwrap 假定 JSON 信封,接不了二进制)。
85
85
  * AdminExceptionFilter 对业务失败仍回 HTTP 200 + JSON 信封,故还要辨 content-type /
86
86
  * 是否以 `{` 开头,避免把错误信封当 xlsx 触发下载。
87
87
  *
@@ -287,7 +287,7 @@ export declare const userApi: {
287
287
  importTemplate: () => Promise<Blob>;
288
288
  /**
289
289
  * 上传 xlsx 预览校验。multipart:`file` + 可选 `mapping`(JSON 字符串:表头→列 Key)。
290
- * bodySerializer 建 FormData(坑 3:与 fileApi.upload 同型)。
290
+ * bodySerializer 建 FormData(与 fileApi.upload 同型)。
291
291
  */
292
292
  importPreview: (file: File, mapping?: Record<string, string>) => Promise<ImportPreview>;
293
293
  /** 对前端改过的行重新校验(不碰文件)。 */
@@ -449,7 +449,7 @@ export declare const logApi: {
449
449
  opClear: () => Promise<boolean>;
450
450
  /**
451
451
  * 导出操作日志 xlsx。筛选与 opPage 同源 + `columns` 逗号分隔列 Key。
452
- * 返回 blob(坑 2);不进信封。
452
+ * 返回 blob,不进信封。
453
453
  */
454
454
  opExport: (params: {
455
455
  title?: string;
package/dist/api/index.js CHANGED
@@ -224,7 +224,7 @@ const C = {
224
224
  importTemplate: () => s.GET("/api/v1/sys/user/import/template", { parseAs: "blob" }).then((e) => v(e)),
225
225
  /**
226
226
  * 上传 xlsx 预览校验。multipart:`file` + 可选 `mapping`(JSON 字符串:表头→列 Key)。
227
- * bodySerializer 建 FormData(坑 3:与 fileApi.upload 同型)。
227
+ * bodySerializer 建 FormData(与 fileApi.upload 同型)。
228
228
  */
229
229
  importPreview: (e, t) => s.POST("/api/v1/sys/user/import/preview", {
230
230
  timeout: l,
@@ -398,7 +398,7 @@ const B = {
398
398
  opClear: () => s.DELETE("/api/v1/sys/log/op", {}).then((e) => a(e)),
399
399
  /**
400
400
  * 导出操作日志 xlsx。筛选与 opPage 同源 + `columns` 逗号分隔列 Key。
401
- * 返回 blob(坑 2);不进信封。
401
+ * 返回 blob,不进信封。
402
402
  */
403
403
  opExport: (e) => s.GET("/api/v1/sys/log/op/export", {
404
404
  timeout: l,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/api/index.ts"],"sourcesContent":["// 平台内核 API + 给域模块复用的原语(unwrap/ApiError/pageParams/toPage/listQuery/dayRange)。\n// 应用的业务端点写在自己的 src/api/<域>.ts 里,从 smart-admin-web 导入这些原语与 createApiClient。\n// 这些原语是包的公开导出,包内没有调用方是设计如此,别当未使用代码清掉。\nimport { client, LONG_TIMEOUT_MS } from './client'\nimport { runtime } from '#/lib/runtime'\nimport type { components } from './schema'\nimport type {\n AddUserInput,\n AddUserOutput,\n ChunkInitOutput,\n ConfigInput,\n CronPreviewOutput,\n DashboardSummary,\n DataScopeType,\n DictItem,\n DictItemInput,\n DictTypeInput,\n DuplicateStrategy,\n FileUploadOutput,\n ImportCommitResult,\n ImportPreview,\n ImportRow,\n JobDashboard,\n JobHandlersOutput,\n JobInput,\n LoginOutput,\n ModuleInput,\n ModuleRow,\n MyModulesOutput,\n MySessionItem,\n NoticeMineItem,\n NoticePublishInput,\n OnlineSessionItem,\n OrgInput,\n PagedList,\n PermissionRouteItem,\n PositionInput,\n RoleInput,\n ServerInfoOutput,\n SysConfig,\n SysDictItem,\n SysDictType,\n SysExceptionLog,\n SysFile,\n SysJob,\n SysJobLog,\n SysLoginLog,\n SysNotice,\n SysOpLog,\n SysOrg,\n SysPosition,\n SysRole,\n SysRoleDataScope,\n UpdateUserInput,\n UserDetail,\n UserItem,\n UserProfile,\n} from '#/types/api'\nimport type { MenuInput, MenuNode, MenuTreeNode } from '#/types/menu'\n\n/** 业务错误(含后端 code / msgKey);视图 catch 后经 translateError 展示。 */\nexport class ApiError extends Error {\n code: number\n msgKey?: string\n args?: Record<string, unknown>\n constructor(code: number, msgKey?: string, args?: Record<string, unknown>, message?: string) {\n super(message ?? msgKey ?? `Error ${code}`)\n this.name = 'ApiError'\n this.code = code\n this.msgKey = msgKey\n this.args = args\n }\n}\n\ninterface Envelope {\n code?: number\n msgKey?: string\n args?: Record<string, unknown>\n message?: string\n data?: unknown\n}\n\n/**\n * 解包 openapi-fetch 结果,同时容忍两种形状:\n * - 2xx:body 是 Result<T> 信封;code!==0 抛 ApiError,否则返回 data.data。\n * - 非 2xx:enveloped(401/403/429)有 code → 抛带 code 的 ApiError;\n * ProblemDetails(400 校验 / 500)无 code → 抛 status + title/detail。\n */\nexport function unwrap<T>(res: { data?: unknown; error?: unknown; response: Response }): T {\n const { data, error, response } = res\n if (error !== undefined && error !== null) {\n const env = error as Envelope\n if (typeof env.code === 'number') {\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n }\n const pd = error as { title?: string; detail?: string }\n throw new ApiError(\n response.status,\n undefined,\n undefined,\n pd.title ?? pd.detail ?? response.statusText,\n )\n }\n const env = (data ?? {}) as Envelope\n if (typeof env.code === 'number' && env.code !== 0) {\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n }\n return env.data as T\n}\n\n/**\n * 按「方法 + 站内路径」调一个运行期才知道 url 的接口(通知动作按钮这类场景),\n * 走同一套中间件(令牌 / CSRF / 刷新重放 / 超时)与信封解包。url 必须是 /api/ 开头的站内路径,\n * 调用方先用 lib/noticeActions 的 classifyNoticeAction 把关。\n */\nexport function callApi<T = unknown>(\n method: 'GET' | 'POST',\n url: string,\n body?: unknown,\n): Promise<T> {\n // openapi-fetch 的 request 只认 schema 里的路径字面量;这里的 url 来自数据,类型上放开一次。\n const request = client.request as unknown as (\n m: string,\n u: string,\n init?: { body?: unknown },\n ) => Promise<{ data?: unknown; error?: unknown; response: Response }>\n return request(method, url, body === undefined ? undefined : { body }).then(r => unwrap<T>(r))\n}\n\n/**\n * 分页三件套复用(每个列表端点都重复):\n * - 前端 {page,pageSize} → 后端 record 属性 {Current,Size}(PascalCase;ASP.NET 绑定大小写不敏感但类型要 Pascal)。\n * `...pageParams(p)` 展进各端点自己的 PascalCase 过滤条件,查询对象仍逐端点强类型校验(不走 any)。\n * - 后端 PagedList<T>({current,size,total,items}) → SmartTable fetcher 契约的 {items,total}。\n *\n * 二者连同 unwrap/ApiError 一起从包入口导出,是<b>应用写自己 API 模块的接缝</b>:应用的 `src/api/<域>.ts`\n * 从 smart-admin-web 导入它们,分页端点就与内核端点同一套映射。包内没有别的调用方也必须留着,别当未使用导出清掉。\n */\nexport const pageParams = (p: { page: number; pageSize: number }) => ({\n Current: p.page,\n Size: p.pageSize,\n})\n\n/**\n * 「编号 + 名称 + 关键字 + 排序」这套列表参数是后端 CRUD 模板的默认产出,二十来个端点逐字重复。\n * 不带 Keyword 的端点用 `Omit<ListParams, 'keyword'>`,别把不存在的过滤条件写进签名骗调用方。\n */\nexport interface ListParams {\n page: number\n pageSize: number\n keyword?: string\n number?: string\n name?: string\n sortField?: string\n sortOrder?: string\n}\n\n/**\n * ListParams → 后端 PascalCase 查询串。\n * undefined 字段由 openapi-fetch 的 querySerializer 直接跳过,所以不带 keyword 的端点复用它也不会多发参数。\n */\nexport const listQuery = (p: ListParams) => ({\n ...pageParams(p),\n Keyword: p.keyword,\n Number: p.number,\n Name: p.name,\n SortField: p.sortField,\n SortOrder: p.sortOrder,\n})\n\n/**\n * SmartTable 的 daterange 控件回传 `[开始, 结束]`(YYYY-MM-DD),后端要拆成两个参数。\n * 结束日必须补 23:59:59,否则\"筛到今天\"会把今天已经发生的数据全部漏掉(纯日期串等价于当天 00:00:00)。\n * 各域 API 模块的参数名不同(XxxStart/XxxEnd),所以这里只回中性的 start/end 由调用方改名。\n */\nexport const dayRange = (range?: [string, string] | null) => {\n if (!range || range.length !== 2) return { start: undefined, end: undefined }\n return { start: range[0] || undefined, end: range[1] ? `${range[1]} 23:59:59` : undefined }\n}\n\nexport function toPage<T>(res: Parameters<typeof unwrap>[0]): { items: T[]; total: number } {\n const p = unwrap<PagedList<T>>(res)\n return { items: p.items, total: p.total }\n}\n\n/**\n * 下载 xlsx 等二进制:parseAs blob + 手查 ok(坑 2:unwrap 假定 JSON 信封)。\n * AdminExceptionFilter 对业务失败仍回 HTTP 200 + JSON 信封,故还要辨 content-type /\n * 是否以 `{` 开头,避免把错误信封当 xlsx 触发下载。\n *\n * 与 unwrap/pageParams/toPage 一样是<b>应用接缝</b>:应用 `src/api/<域>.ts` 的导出端点从 smart-admin-web 导入它,\n * 别在自己文件里再抄一份错误信封嗅探(抄漏一个分支就会把失败信封当 xlsx 存到用户磁盘上)。\n */\nexport async function unwrapDownload(res: {\n data?: unknown\n error?: unknown\n response: Response\n}): Promise<Blob> {\n const { data, error, response } = res\n if (!response.ok) {\n const env = (error ?? {}) as Envelope\n if (typeof env.code === 'number')\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n throw new ApiError(response.status, undefined, undefined, response.statusText)\n }\n const blob = data as Blob\n const ct = response.headers.get('content-type') ?? ''\n if (ct.includes('spreadsheet') || ct.includes('octet-stream')) return blob\n // 200 + application/json = 业务失败信封(导出行数超限等)\n if (ct.includes('json') || ct.includes('text/plain')) {\n const env = JSON.parse(await blob.text()) as Envelope\n if (typeof env.code === 'number' && env.code !== 0) {\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n }\n } else {\n // content-type 缺失时嗅探:xlsx 是 zip(`PK`),信封以 `{` 开头\n const head = new Uint8Array(await blob.slice(0, 1).arrayBuffer())\n if (head[0] === 0x7b /* { */) {\n const env = JSON.parse(await blob.text()) as Envelope\n if (typeof env.code === 'number' && env.code !== 0) {\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n }\n }\n }\n return blob\n}\n\n/**\n * 归一 ImportPreview:int64/int 序列化噪音 → number,缺省数组补齐。\n * 与 unwrap/unwrapDownload 一样是<b>应用接缝</b>:应用 `src/api/<域>.ts` 接自己的导入端点时从 smart-admin-web 导入它,\n * 别各自抄一份归一逻辑 —— 漏一个 Number() 就会让 ImportWizard 的错误计数错位。\n */\nexport function normalizePreview(raw: ImportPreview): ImportPreview {\n return {\n headers: raw.headers ?? [],\n mapping: raw.mapping ?? {},\n columns: (raw.columns ?? []).map(c => ({\n key: c.key,\n title: c.title,\n required: c.required,\n dictTypeCode: c.dictTypeCode,\n hint: c.hint,\n width: c.width != null ? Number(c.width) : undefined,\n })),\n rows: (raw.rows ?? []).map(normalizeRow),\n total: Number(raw.total ?? 0),\n errorRows: Number(raw.errorRows ?? 0),\n columnErrors: (raw.columnErrors ?? []).map(e => ({\n columnKey: e.columnKey,\n code: Number(e.code),\n args: e.args,\n })),\n }\n}\n\nfunction normalizeRow(r: ImportRow): ImportRow {\n return {\n index: Number(r.index ?? 0),\n cells: { ...r.cells },\n errors: (r.errors ?? []).map(e => ({\n columnKey: e.columnKey,\n code: Number(e.code),\n args: e.args,\n })),\n }\n}\n\nexport function normalizeCommit(raw: ImportCommitResult): ImportCommitResult {\n return {\n total: Number(raw.total ?? 0),\n inserted: Number(raw.inserted ?? 0),\n updated: Number(raw.updated ?? 0),\n skipped: Number(raw.skipped ?? 0),\n failed: Number(raw.failed ?? 0),\n failures: (raw.failures ?? []).map(normalizeRow),\n }\n}\n\n/**\n * 回传行:schema 把 cells 标成 `Record<string, string>`(无 null),而运行时/编辑态允许空。\n * 发送前把 null/undefined 收成 `''`,避免 openapi-fetch 类型卡死。\n * 同为应用接缝,见 normalizePreview 上的说明。\n */\nexport function toWireRows(rows: ImportRow[]) {\n return rows.map(r => {\n const cells: Record<string, string> = {}\n for (const [k, v] of Object.entries(r.cells ?? {})) cells[k] = v ?? ''\n return {\n index: r.index,\n cells,\n errors: r.errors.map(e => ({\n columnKey: e.columnKey,\n code: e.code,\n args: e.args as Record<string, never> | null | undefined,\n })),\n }\n })\n}\n\nexport const authApi = {\n login: (body: { account: string; password: string; captchaId?: string; captchaCode?: string }) =>\n client.POST('/api/v1/auth/login', { body }).then(r => unwrap<LoginOutput>(r)),\n logout: () => client.POST('/api/v1/auth/logout', {}).then(r => unwrap<boolean>(r)),\n captcha: () =>\n client\n .GET('/api/v1/auth/captcha', {})\n .then(r => unwrap<{ captchaId: string; svg: string; type?: string }>(r)),\n /** 短信二次验证:凭密码登录 40009 信令下发的挑战 Id + 短信码完成登录。 */\n smsChallengeLogin: (body: { challengeId: string; code: string }) =>\n client.POST('/api/v1/auth/login/sms', { body }).then(r => unwrap<LoginOutput>(r)),\n /** 短信二次验证:重发验证码(服务端冷却/日上限,过频抛 40008)。 */\n smsChallengeResend: (body: { challengeId: string }) =>\n client\n .POST('/api/v1/auth/login/sms/resend', { body })\n .then(r => unwrap<{ expiresSeconds: number; resendSeconds: number }>(r)),\n /** TOTP 二次验证完成登录(40018 / SSO totpChallenge);走 openapi-fetch → CSRF/credentials 中间件生效。 */\n totpChallengeLogin: (body: { challengeId: string; code: string }) =>\n client.POST('/api/v1/auth/login/totp', { body }).then(r => unwrap<LoginOutput>(r)),\n /** 短时再认证(高危写操作 40024 后由中间件唤起;窗口约 5 分钟)。 */\n reauth: (body: { method?: string; totpCode?: string; password?: string }) =>\n client.POST('/api/v1/auth/reauth', { body }).then(r => unwrap<void>(r)),\n /** 免密登录发码(图形验证码启用时须携带;响应不区分手机号是否存在,防枚举)。 */\n smsLoginSend: (body: { phone: string; captchaId?: string; captchaCode?: string }) =>\n client\n .POST('/api/v1/auth/sms/send', { body })\n .then(r => unwrap<{ expiresSeconds: number; resendSeconds: number }>(r)),\n /** 免密登录:手机号 + 短信码换令牌。 */\n smsLogin: (body: { phone: string; code: string }) =>\n client.POST('/api/v1/auth/sms/login', { body }).then(r => unwrap<LoginOutput>(r)),\n}\n\n/** TOTP 自助绑定 / 恢复 / 管理员清除(ADR 0006;无邀请路径)。 */\nexport const mfaApi = {\n bindStart: (body: components['schemas']['TotpBindStartInput']) =>\n client\n .POST('/api/v1/auth/mfa/bind/start', { body })\n .then(r => unwrap<components['schemas']['TotpBindStartOutput']>(r)),\n bindComplete: (body: components['schemas']['TotpBindCompleteInput']) =>\n client\n .POST('/api/v1/auth/mfa/bind/complete', { body })\n .then(r => unwrap<components['schemas']['TotpBindCompleteOutput']>(r)),\n recovery: (body: components['schemas']['TotpRecoveryInput']) =>\n client.POST('/api/v1/auth/mfa/recovery', { body }).then(r => unwrap<void>(r)),\n clear: (body: components['schemas']['TotpClearMfaInput']) =>\n client.POST('/api/v1/sys/mfa/clear', { body }).then(r => unwrap<void>(r)),\n}\n\n/** 高敏权限自定义追加(内核默认只读;写操作须 reauth)。 */\nexport const highSensApi = {\n list: () =>\n client\n .GET('/api/v1/sys/mfa/high-sensitivity', {})\n .then(r => unwrap<components['schemas']['HighSensitivityPermissionList']>(r)),\n add: (body: components['schemas']['HighSensitivityPermissionInput']) =>\n client\n .POST('/api/v1/sys/mfa/high-sensitivity', { body })\n .then(r => unwrap<components['schemas']['HighSensitivityPermissionItem']>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/mfa/high-sensitivity/{id}', { params: { path: { id } } })\n .then(r => unwrap<void>(r)),\n}\n\nexport interface ExternalProvider {\n code: string\n displayName: string\n icon?: string | null\n}\n\n/** 管理端:全部已注册 provider(含已禁用)+ enabled / linkByAccount 两个运营开关。 */\nexport interface ExternalProviderAdmin extends ExternalProvider {\n enabled: boolean\n linkByAccount: boolean\n}\n\nexport interface ExternalBinding {\n provider: string\n displayName?: string | null\n boundAt: string\n}\n\n// 外部登录 / SSO。登录:providers 点亮按钮 → 顶层导航到 authorizeUrl(后端 302 跳 IdP)→ 回调页 exchange 换令牌。\n// 绑定(个人中心):bindStart 拿授权 URL 跳转 → 同一回调把外部身份绑到当前用户;bindings 查、unbind 解绑。\nexport const externalAuthApi = {\n /** 登录页可用的外部登录方式(启用的);空数组 = 不显 SSO 区。 */\n providers: () =>\n client.GET('/api/v1/auth/external/providers', {}).then(r => unwrap<ExternalProvider[]>(r)),\n /** 管理端全量列表(含已禁用);系统配置「第三方登录」Tab。 */\n providersAll: () =>\n client\n .GET('/api/v1/auth/external/providers/all', {})\n .then(r => unwrap<ExternalProviderAdmin[]>(r)),\n /** 发起某 provider 登录的 URL(顶层浏览器导航,不走 fetch —— 后端 302 跳 IdP)。 */\n authorizeUrl: (code: string) =>\n `${runtime.apiBase}/api/v1/auth/external/${encodeURIComponent(code)}/authorize`,\n /** 一次性票据换令牌(登录回调后);票据无效/过期/已用抛 40014。 */\n exchange: (ticket: string) =>\n client\n .POST('/api/v1/auth/external/exchange', { body: { ticket } })\n .then(r => unwrap<LoginOutput>(r)),\n /** 认领未绑定 SSO 的 pending-link(账密登录后);票据无效 40014,已被他人绑 40017。 */\n claimPendingLink: (pendingLink: string) =>\n client\n .POST('/api/v1/auth/external/pending-link/claim', { body: { pendingLink } })\n .then(r => unwrap<boolean>(r)),\n /** 我的外部账号绑定列表(个人中心)。 */\n bindings: () =>\n client.GET('/api/v1/auth/external/bindings', {}).then(r => unwrap<ExternalBinding[]>(r)),\n /** 发起绑定:返回授权 URL,前端跳转开始 OAuth 往返(回调把身份绑到当前用户)。 */\n bindStart: (code: string) =>\n client\n .POST('/api/v1/auth/external/{provider}/bind', { params: { path: { provider: code } } })\n .then(r => unwrap<{ authorizeUrl: string }>(r)),\n /** 解绑某 provider 的外部账号。 */\n unbind: (code: string) =>\n client\n .DELETE('/api/v1/auth/external/{provider}/binding', { params: { path: { provider: code } } })\n .then(r => unwrap<boolean>(r)),\n}\n\nexport const dashboardApi = {\n /** 工作台首页统计([ActiveSession]:任何登录用户可取,无需权限码)。 */\n summary: () => client.GET('/api/v1/dashboard/summary', {}).then(r => unwrap<DashboardSummary>(r)),\n}\n\nexport const personalApi = {\n modules: () => client.GET('/api/v1/personal/modules', {}).then(r => unwrap<MyModulesOutput>(r)),\n menu: (moduleId: number) =>\n client\n .GET('/api/v1/personal/menu', { params: { query: { moduleId } } })\n .then(r => unwrap<MenuNode[]>(r)),\n setDefaultModule: (moduleId: number) =>\n client\n .PUT('/api/v1/personal/default-module', { body: { moduleId } })\n .then(r => unwrap<boolean>(r)),\n profile: () => client.GET('/api/v1/personal/profile', {}).then(r => unwrap<UserProfile>(r)),\n /** 改自己的资料(全量替换语义:缺字段即置空,前端整表单提交)。 */\n updateProfile: (body: {\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n }) => client.PUT('/api/v1/personal/profile', { body }).then(r => unwrap<boolean>(r)),\n /** 我的活跃会话列表(个人视角;isCurrent = 本次请求所用会话)。 */\n sessions: () => client.GET('/api/v1/personal/sessions', {}).then(r => unwrap<MySessionItem[]>(r)),\n /** 下线自己的某个会话;他人的/不存在的一律 42024(不区分,防探测)。 */\n kickSession: (sessionId: string) =>\n client\n .DELETE('/api/v1/personal/sessions/{sessionId}', { params: { path: { sessionId } } })\n .then(r => unwrap<boolean>(r)),\n updatePassword: (body: { oldPassword: string; newPassword: string }) =>\n client.PUT('/api/v1/personal/password', { body }).then(r => unwrap<boolean>(r)),\n /** 当前用户权限码集合(= 规范化路由);喂给 authStore.permissionCodes 驱动 v-auth。超管返回空集。 */\n permissions: () => client.GET('/api/v1/personal/permissions', {}).then(r => unwrap<string[]>(r)),\n}\n\n// 用户管理:CRUD + 启停 / 重置密码 + xlsx 导入导出。\nexport const userApi = {\n /** 归一后端 PagedList<UserItem>({current,size,total,items}) → SmartTable fetcher 契约的 {items,total}。 */\n page: (params: {\n page: number\n pageSize: number\n account?: string\n name?: string\n orgId?: number\n roleId?: number\n sortField?: string\n sortOrder?: string\n }) =>\n client\n .GET('/api/v1/sys/user/page', {\n // 查询参数名沿用后端 record 属性(PascalCase);ASP.NET 绑定大小写不敏感,类型要求 PascalCase。\n // roleId:角色反查(「这个角色有哪些人」/ 删角色前报人数)复用本端点,不另开接口。\n // sortField/sortOrder:SmartTable 排序;后端按实体列白名单校验(非法忽略回退默认),见 PagedListExtensions.OrderBySafe。\n params: {\n query: {\n ...pageParams(params),\n Account: params.account,\n Name: params.name,\n OrgId: params.orgId,\n RoleId: params.roleId,\n SortField: params.sortField,\n SortOrder: params.sortOrder,\n },\n },\n })\n .then(r => toPage<UserItem>(r)),\n /** 用户详情(含 roleIds,编辑回显 + 提交时原样带回避免清空角色)。 */\n detail: (id: number) =>\n client\n .GET('/api/v1/sys/user/{id}', { params: { path: { id } } })\n .then(r => unwrap<UserDetail>(r)),\n /** 新增用户;返回新 Id + 实际生效的初始口令(留空 password 时后端随机生成,不接住就没人知道这个号的密码)。 */\n add: (body: AddUserInput) =>\n client.POST('/api/v1/sys/user', { body }).then(r => unwrap<AddUserOutput>(r)),\n update: (id: number, body: UpdateUserInput) =>\n client\n .PUT('/api/v1/sys/user/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/user/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量软删除;集合含超管后端整体拒绝(SuperAdminProtected)。 */\n batchRemove: (ids: number[]) =>\n client.POST('/api/v1/sys/user/batch-delete', { body: { ids } }).then(r => unwrap<boolean>(r)),\n /** 重置密码;返回实际生效的初始密码(newPassword 留空 = 后端默认初始密码)。 */\n resetPassword: (id: number, newPassword?: string | null) =>\n client\n .PUT('/api/v1/sys/user/{id}/password', {\n params: { path: { id } },\n body: { newPassword: newPassword || null },\n })\n .then(r => unwrap<string>(r)),\n /** 专用启停端点(非全量 update)。 */\n setEnabled: (id: number, enabled: boolean) =>\n client\n .PUT('/api/v1/sys/user/{id}/enabled', { params: { path: { id } }, body: { enabled } })\n .then(r => unwrap<boolean>(r)),\n\n // ── 导入 / 导出 ──\n\n /** 下载用户导入模板(xlsx)。[ActiveSession],无需独立权限码。 */\n importTemplate: () =>\n client\n .GET('/api/v1/sys/user/import/template', { parseAs: 'blob' })\n .then(r => unwrapDownload(r)),\n\n /**\n * 上传 xlsx 预览校验。multipart:`file` + 可选 `mapping`(JSON 字符串:表头→列 Key)。\n * bodySerializer 建 FormData(坑 3:与 fileApi.upload 同型)。\n */\n importPreview: (file: File, mapping?: Record<string, string>) =>\n client\n .POST('/api/v1/sys/user/import/preview', {\n timeout: LONG_TIMEOUT_MS,\n body: {\n file: file as unknown as string,\n mapping: mapping ? JSON.stringify(mapping) : undefined,\n },\n bodySerializer: body => {\n const b = body as unknown as { file: File; mapping?: string }\n const fd = new FormData()\n fd.append('file', b.file)\n if (b.mapping) fd.append('mapping', b.mapping)\n return fd\n },\n })\n .then(r => normalizePreview(unwrap<ImportPreview>(r))),\n\n /** 对前端改过的行重新校验(不碰文件)。 */\n importValidate: (rows: ImportRow[]) =>\n client\n .POST('/api/v1/sys/user/import/validate', {\n timeout: LONG_TIMEOUT_MS,\n body: { rows: toWireRows(rows) },\n })\n .then(r => normalizePreview(unwrap<ImportPreview>(r))),\n\n /** 下载错误报告 xlsx(原列 +「错误原因」列)。 */\n importErrorReport: (rows: ImportRow[]) =>\n client\n .POST('/api/v1/sys/user/import/error-report', {\n timeout: LONG_TIMEOUT_MS,\n body: { rows: toWireRows(rows) },\n parseAs: 'blob',\n })\n .then(r => unwrapDownload(r)),\n\n /** 按策略提交导入(部分提交:有错行跳过;服务端重校验,不信任前端 Errors)。 */\n importCommit: (rows: ImportRow[], strategy: DuplicateStrategy = 0) =>\n client\n .POST('/api/v1/sys/user/import/commit', {\n timeout: LONG_TIMEOUT_MS,\n body: { rows: toWireRows(rows), strategy },\n })\n .then(r => normalizeCommit(unwrap<ImportCommitResult>(r))),\n\n /**\n * 导出用户 xlsx。筛选条件与列表同源(Account/Name/OrgId/RoleId…)+ `columns` 逗号分隔列 Key。\n * 返回 blob,不进信封。\n */\n export: (params: {\n account?: string\n name?: string\n orgId?: number\n roleId?: number\n enabled?: boolean\n sortField?: string\n sortOrder?: string\n /** 逗号分隔列 Key;缺省 = 档案 DefaultSelected */\n columns?: string\n }) =>\n client\n .GET('/api/v1/sys/user/export', {\n timeout: LONG_TIMEOUT_MS,\n params: {\n query: {\n Account: params.account,\n Name: params.name,\n OrgId: params.orgId,\n RoleId: params.roleId,\n Enabled: params.enabled,\n SortField: params.sortField,\n SortOrder: params.sortOrder,\n columns: params.columns,\n },\n },\n parseAs: 'blob',\n })\n .then(r => unwrapDownload(r)),\n}\n\n// 机构管理:树形机构 CRUD + 子树复制,list 平铺返回由前端 buildTree 拼树。\nexport const orgApi = {\n /** 全部机构(平铺,按 Sort、Id 排序)。前端 buildTree 拼树。下拉 / 树表复用。 */\n list: () => client.GET('/api/v1/sys/org/list', {}).then(r => unwrap<SysOrg[]>(r)),\n add: (body: OrgInput) =>\n client.POST('/api/v1/sys/org/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: OrgInput) =>\n client\n .PUT('/api/v1/sys/org/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/org/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 复制机构子树(整支克隆挂到源节点同级),返回新根 Id。 */\n copy: (id: number, body?: { name?: string }) =>\n client\n .POST('/api/v1/sys/org/{id}/copy', { params: { path: { id } }, body: body })\n .then(r => unwrap<number>(r)),\n}\n\n// 职位管理:普通 CRUD;岗位与机构无关联。\nexport const positionApi = {\n /** 职位分页;搜索键 name → PascalCase Name;sortField/sortOrder → 后端安全排序。下拉(拉大页)/ SmartTable 复用。 */\n page: (params: {\n page: number\n pageSize: number\n name?: string\n sortField?: string\n sortOrder?: string\n }) =>\n client\n .GET('/api/v1/sys/position/page', {\n params: {\n query: {\n ...pageParams(params),\n Name: params.name,\n SortField: params.sortField,\n SortOrder: params.sortOrder,\n },\n },\n })\n .then(r => toPage<SysPosition>(r)),\n add: (body: PositionInput) =>\n client.POST('/api/v1/sys/position/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: PositionInput) =>\n client\n .PUT('/api/v1/sys/position/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/position/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 角色管理:CRUD + 菜单授权 / 数据范围 / 关联用户三块设置。\nexport const roleApi = {\n /** 角色分页;搜索键 name → PascalCase Name。列表用 + 用户/授权页拉一大页当下拉源。 */\n page: (params: { page: number; pageSize: number; name?: string }) =>\n client\n .GET('/api/v1/sys/role/page', {\n params: { query: { ...pageParams(params), Name: params.name } },\n })\n .then(r => toPage<SysRole>(r)),\n add: (body: RoleInput) =>\n client.POST('/api/v1/sys/role/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: RoleInput) =>\n client\n .PUT('/api/v1/sys/role/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/role/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量删除角色(各自级联清关联)。 */\n batchRemove: (ids: number[]) =>\n client.POST('/api/v1/sys/role/batch-delete', { body: { ids } }).then(r => unwrap<boolean>(r)),\n /** 某角色当前授予的菜单 Id 集合(授权抽屉回显)。 */\n getMenus: (id: number) =>\n client\n .GET('/api/v1/sys/role/{id}/menus', { params: { path: { id } } })\n .then(r => unwrap<number[]>(r)),\n /** 全量设置角色授予的菜单(空数组 = 收回全部)。 */\n setMenus: (roleId: number, menuIds: number[]) =>\n client\n .PUT('/api/v1/sys/role/menu', { body: { roleId, menuIds } })\n .then(r => unwrap<boolean>(r)),\n /** 某角色的数据范围配置(未配置返回 null)。 */\n getDataScope: (id: number) =>\n client\n .GET('/api/v1/sys/role/{id}/datascope', { params: { path: { id } } })\n .then(r => unwrap<SysRoleDataScope | null>(r)),\n /** 设置角色数据范围;customOrgIds 仅 scopeType=Custom(5)时有意义。 */\n setDataScope: (roleId: number, scopeType: DataScopeType, customOrgIds?: number[]) =>\n client\n .PUT('/api/v1/sys/role/datascope', { body: { roleId, scopeType, customOrgIds } })\n .then(r => unwrap<boolean>(r)),\n /** 某角色当前关联的用户 Id 集合(授权用户抽屉回显)。 */\n getUsers: (id: number) =>\n client\n .GET('/api/v1/sys/role/{id}/users', { params: { path: { id } } })\n .then(r => unwrap<number[]>(r)),\n /** 全量设置角色关联的用户(空数组 = 收回全部)。 */\n setUsers: (roleId: number, userIds: number[]) =>\n client\n .PUT('/api/v1/sys/role/users', { body: { roleId, userIds } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 应用(模块)管理:CRUD,门户多应用切换的应用清单来源。\nexport const moduleApi = {\n list: () => client.GET('/api/v1/sys/module/list', {}).then(r => unwrap<ModuleRow[]>(r)),\n add: (body: ModuleInput) =>\n client.POST('/api/v1/sys/module/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: ModuleInput) =>\n client\n .PUT('/api/v1/sys/module/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/module/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 系统配置:key/value 分页 CRUD + 按分组批量取/存(结构化表单用)+ 站点信息 / 密码策略两个匿名可读端点。\nexport const configApi = {\n /** 归一后端 PagedList<SysConfig> → SmartTable {items,total};搜索键 configKey/name/groupCode → PascalCase 查询参。 */\n page: (params: {\n page: number\n pageSize: number\n configKey?: string\n name?: string\n groupCode?: string\n excludedGroupCodes?: string[]\n }) =>\n client\n .GET('/api/v1/sys/config/page', {\n params: {\n query: {\n ...pageParams(params),\n ConfigKey: params.configKey,\n Name: params.name,\n GroupCode: params.groupCode,\n ExcludedGroupCodes: params.excludedGroupCodes,\n },\n },\n })\n .then(r => toPage<SysConfig>(r)),\n add: (body: ConfigInput) =>\n client.POST('/api/v1/sys/config', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: ConfigInput) =>\n client\n .PUT('/api/v1/sys/config/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/config/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /**\n * 取某分组下全部配置(完整行,含 id/key/value),供分类配置中心结构化表单回填。\n * 逐页取全:结构化表单按键回写,漏取的字段会拿默认值把库里的真实值覆盖掉。\n */\n listByGroup: async (group: string) => {\n const all: SysConfig[] = []\n for (let current = 1; ; current++) {\n const page = await client\n .GET('/api/v1/sys/config/page', {\n params: { query: { Current: current, Size: 100, GroupCode: group } },\n })\n .then(r => unwrap<PagedList<SysConfig>>(r))\n all.push(...page.items)\n if (page.items.length === 0 || all.length >= page.total) return all\n }\n },\n /** 批量按键回写配置值(结构化表单保存);仅更新已存在键,未知键后端忽略。 */\n saveBatch: (items: { configKey: string; configValue?: string | null }[]) =>\n client.PUT('/api/v1/sys/config/batch', { body: items }).then(r => unwrap<boolean>(r)),\n /** 站点信息(匿名可读:站点标题/副标题/版权等品牌展示白名单)。 */\n siteInfo: () =>\n client.GET('/api/v1/sys/config/site', {}).then(r =>\n unwrap<{\n title?: string | null\n subtitle?: string | null\n copyright?: string | null\n copyrightUrl?: string | null\n logo?: string | null\n captchaEnabled?: boolean\n smsLoginEnabled?: boolean\n }>(r),\n ),\n /** 当前生效密码策略(任何登录用户可读);改密页据此展示真实规则清单,免配置读权限。 */\n passwordPolicy: () =>\n client.GET('/api/v1/sys/config/password-policy', {}).then(r =>\n unwrap<{\n minLength: number\n requireUpper: boolean\n requireLower: boolean\n requireDigit: boolean\n requireSpecial: boolean\n }>(r),\n ),\n}\n\n/** 日志端点用的参数名是 StartTime/EndTime;拆分与补 23:59:59 的理由见 dayRange。 */\nfunction splitRange(range?: [string, string] | null) {\n const { start, end } = dayRange(range)\n return { StartTime: start, EndTime: end }\n}\n\n// 日志查询:登录 / 操作 / 异常三类日志各自的分页与清空;操作日志另支持导出 xlsx。\nexport const logApi = {\n /** 登录日志分页;账号模糊 + 成败 + 时间范围。 */\n loginPage: (params: {\n page: number\n pageSize: number\n account?: string\n success?: boolean\n createTime?: [string, string] | null\n }) =>\n client\n .GET('/api/v1/sys/log/login/page', {\n params: {\n query: {\n ...pageParams(params),\n Account: params.account,\n Success: params.success,\n ...splitRange(params.createTime),\n },\n },\n })\n .then(r => toPage<SysLoginLog>(r)),\n /** 清空登录日志(硬删,不可恢复)。 */\n loginClear: () => client.DELETE('/api/v1/sys/log/login', {}).then(r => unwrap<boolean>(r)),\n /** 操作日志分页;操作名模糊 + 成败 + 操作人(精确)+ 接口路径(模糊)+ 时间范围——审计要能答\"谁在什么时候干了什么\"。 */\n opPage: (params: {\n page: number\n pageSize: number\n title?: string\n success?: boolean\n operatorId?: number\n path?: string\n createTime?: [string, string] | null\n }) =>\n client\n .GET('/api/v1/sys/log/op/page', {\n params: {\n query: {\n ...pageParams(params),\n Title: params.title,\n Success: params.success,\n OperatorId: params.operatorId,\n Path: params.path,\n ...splitRange(params.createTime),\n },\n },\n })\n .then(r => toPage<SysOpLog>(r)),\n /** 清空操作日志(硬删,不可恢复)。 */\n opClear: () => client.DELETE('/api/v1/sys/log/op', {}).then(r => unwrap<boolean>(r)),\n /**\n * 导出操作日志 xlsx。筛选与 opPage 同源 + `columns` 逗号分隔列 Key。\n * 返回 blob(坑 2);不进信封。\n */\n opExport: (params: {\n title?: string\n success?: boolean\n operatorId?: number\n path?: string\n createTime?: [string, string] | null\n columns?: string\n }) =>\n client\n .GET('/api/v1/sys/log/op/export', {\n timeout: LONG_TIMEOUT_MS,\n params: {\n query: {\n Title: params.title,\n Success: params.success,\n OperatorId: params.operatorId,\n Path: params.path,\n ...splitRange(params.createTime),\n columns: params.columns,\n },\n },\n parseAs: 'blob',\n })\n .then(r => unwrapDownload(r)),\n /** 异常日志分页;接口路径模糊 + 异常类型模糊 + 时间范围。 */\n exceptionPage: (params: {\n page: number\n pageSize: number\n path?: string\n exceptionType?: string\n createTime?: [string, string] | null\n }) =>\n client\n .GET('/api/v1/sys/log/exception/page', {\n params: {\n query: {\n ...pageParams(params),\n Path: params.path,\n ExceptionType: params.exceptionType,\n ...splitRange(params.createTime),\n },\n },\n })\n .then(r => toPage<SysExceptionLog>(r)),\n /** 清空异常日志(硬删,不可恢复)。 */\n exceptionClear: () =>\n client.DELETE('/api/v1/sys/log/exception', {}).then(r => unwrap<boolean>(r)),\n}\n\n// 服务器监控:只读运行快照。\nexport const monitorApi = {\n /** 服务器运行快照(CPU/内存/磁盘/运行时;后端含一次约 500ms 的 CPU 采样)。 */\n server: () => client.GET('/api/v1/sys/monitor/server', {}).then(r => unwrap<ServerInfoOutput>(r)),\n}\n\n// 缓存管理:定向失效动作(只清不看——缓存含明文 OTP、键含 PII,故后端无键浏览/取值端点)。flush* 返回被清条数。\nexport const cacheApi = {\n /** 清全部用户的权限/数据范围缓存(返回被清用户数)。 */\n flushAuth: () => client.POST('/api/v1/sys/cache/flush-auth', {}).then(r => unwrap<number>(r)),\n /** 清全部字典项缓存(返回被清字典类型数)。 */\n flushDict: () => client.POST('/api/v1/sys/cache/flush-dict', {}).then(r => unwrap<number>(r)),\n /** 清全部系统配置缓存(返回被清配置项数)。 */\n flushConfig: () => client.POST('/api/v1/sys/cache/flush-config', {}).then(r => unwrap<number>(r)),\n /** 递增门户代际,令所有用户的门户菜单/模块缓存整体失效(返回新代际值)。 */\n rebuildPortal: () =>\n client.POST('/api/v1/sys/cache/rebuild-portal', {}).then(r => unwrap<number>(r)),\n}\n\n// 字典下拉数据源(公开只读):按类型编码取启用项,不含 id;喂 stores/dict 缓存,与 dictAdminApi 的管理端读取不能互换。\nexport const dictApi = {\n /** 按类型编码取字典项(服务端已按 sort 排序)。归一 int64 序列化噪音 → DictItem 投影,供 stores/dict 缓存消费。 */\n items: (typeCode: string) =>\n client\n .GET('/api/v1/sys/dict/items/{typeCode}', { params: { path: { typeCode } } })\n .then(r =>\n unwrap<{ label?: string; value?: string; sort?: number | string; enabled?: boolean }[]>(r),\n )\n .then(list =>\n list.map((i): DictItem => ({\n label: i.label ?? '',\n value: i.value ?? '',\n sort: Number(i.sort ?? 0),\n enabled: i.enabled ?? true,\n })),\n ),\n}\n\n// 字典管理端(受权限保护):类型 + 字典项 CRUD,含停用项、带 id;下拉展示走 dictApi,两者不能互相替代。\nexport const dictAdminApi = {\n /** 字典类型分页;搜索键 code/name → PascalCase Code/Name 查询参。 */\n typePage: (params: { page: number; pageSize: number; code?: string; name?: string }) =>\n client\n .GET('/api/v1/sys/dict/type/page', {\n params: { query: { ...pageParams(params), Code: params.code, Name: params.name } },\n })\n .then(r => toPage<SysDictType>(r)),\n typeAdd: (body: DictTypeInput) =>\n client.POST('/api/v1/sys/dict/type', { body }).then(r => unwrap<number>(r)),\n typeUpdate: (id: number, body: DictTypeInput) =>\n client\n .PUT('/api/v1/sys/dict/type/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n typeRemove: (id: number) =>\n client\n .DELETE('/api/v1/sys/dict/type/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量删除字典类型(各自级联删项)。 */\n typeBatchRemove: (ids: number[]) =>\n client\n .POST('/api/v1/sys/dict/type/batch-delete', { body: { ids } })\n .then(r => unwrap<boolean>(r)),\n /** 某类型下的字典项(管理端:含停用、带 id;非下拉缓存源)。ponytail: 拉一页 200(Api:MaxPageSize 上限),字典项数量小,真超再分页。 */\n items: (typeCode: string) =>\n client\n .GET('/api/v1/sys/dict/item/page', {\n params: { query: { TypeCode: typeCode, Current: 1, Size: 200 } },\n })\n .then(r => unwrap<PagedList<SysDictItem>>(r))\n .then(p => p.items),\n itemAdd: (body: DictItemInput) =>\n client.POST('/api/v1/sys/dict/item', { body }).then(r => unwrap<number>(r)),\n itemUpdate: (id: number, body: DictItemInput) =>\n client\n .PUT('/api/v1/sys/dict/item/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n itemRemove: (id: number) =>\n client\n .DELETE('/api/v1/sys/dict/item/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量删除字典项。 */\n itemBatchRemove: (ids: number[]) =>\n client\n .POST('/api/v1/sys/dict/item/batch-delete', { body: { ids } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 文件管理:分页 / 上传 / 下载 / 删除,外加分片断点续传上传一整套。\nexport const fileApi = {\n /** 文件分页;搜索键 originalName → 后端 FileName 模糊过滤。 */\n page: (params: { page: number; pageSize: number; originalName?: string }) =>\n client\n .GET('/api/v1/sys/file/page', {\n params: { query: { ...pageParams(params), FileName: params.originalName } },\n })\n .then(r => toPage<SysFile>(r)),\n /** 上传单个文件:bodySerializer 建 FormData(字段名 file),openapi-fetch 对 FormData 不注入 json header,浏览器自动补 boundary(client.ts 无需改)。 */\n upload: (file: File) =>\n client\n .POST('/api/v1/sys/file/upload', {\n timeout: LONG_TIMEOUT_MS,\n body: { file: file as unknown as string },\n bodySerializer: body => {\n const fd = new FormData()\n fd.append('file', (body as unknown as { file: File }).file)\n return fd\n },\n })\n .then(r => unwrap<FileUploadOutput>(r)),\n /** 下载:parseAs blob 取原始字节(非信封,不套 unwrap);Bearer 由 client 拦截器自动带。 */\n download: (id: number) =>\n client\n .GET('/api/v1/sys/file/{id}/download', {\n timeout: LONG_TIMEOUT_MS,\n params: { path: { id } },\n parseAs: 'blob',\n })\n .then(r => {\n if (!r.response.ok)\n throw new ApiError(r.response.status, undefined, undefined, r.response.statusText)\n return r.data as Blob\n }),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/file/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量软删除文件记录(物理文件保留)。 */\n batchRemove: (ids: number[]) =>\n client.POST('/api/v1/sys/file/batch-delete', { body: { ids } }).then(r => unwrap<boolean>(r)),\n // ── 分片 / 断点续传上传 ──\n /** 分片初始化:秒传探测 + 已收分片(断点续传)。 */\n chunkInit: (body: {\n fileHash: string\n fileName: string\n totalSize: number\n chunkCount: number\n }) => client.POST('/api/v1/sys/file/chunk/init', { body }).then(r => unwrap<ChunkInitOutput>(r)),\n /** 上传单个分片(multipart:uploadId + index + chunk),同 upload 用 bodySerializer 建 FormData。 */\n chunkUpload: (uploadId: string, index: number, chunk: Blob) =>\n client\n .POST('/api/v1/sys/file/chunk', {\n timeout: LONG_TIMEOUT_MS,\n body: { uploadId, index, chunk: chunk as unknown as string },\n bodySerializer: body => {\n const b = body as unknown as { uploadId: string; index: number; chunk: Blob }\n const fd = new FormData()\n fd.append('uploadId', b.uploadId)\n fd.append('index', String(b.index))\n fd.append('chunk', b.chunk)\n return fd\n },\n })\n .then(r => unwrap<boolean>(r)),\n /** 完成:触发服务端合并 + 哈希校验 + 三道关 + 落库。 */\n chunkComplete: (body: {\n uploadId: string\n fileHash: string\n fileName: string\n chunkCount: number\n }) =>\n client\n .POST('/api/v1/sys/file/chunk/complete', { timeout: LONG_TIMEOUT_MS, body })\n .then(r => unwrap<FileUploadOutput>(r)),\n}\n\n// 在线会话:只读分页 + 按 sessionId 强制下线。\nexport const sessionApi = {\n /** 在线会话分页(只读)。后端仅支持按 UserId 过滤,这里不带业务搜索。 */\n online: (params: { page: number; pageSize: number }) =>\n client\n .GET('/api/v1/sys/session/online', { params: { query: pageParams(params) } })\n .then(r => toPage<OnlineSessionItem>(r)),\n /** 强制下线:按 sessionId 踢会话。 */\n kick: (sessionId: string) =>\n client\n .DELETE('/api/v1/sys/session/{sessionId}', { params: { path: { sessionId } } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 系统通知:管理端发布 / 撤回 + 用户端分页拉取 / 标记已读。\nexport const noticeApi = {\n // ── 管理端 ──\n /** 管理端分页(全量);搜索键 title/type → PascalCase 查询参。 */\n page: (params: { page: number; pageSize: number; title?: string; type?: number }) =>\n client\n .GET('/api/v1/sys/notice/page', {\n params: { query: { ...pageParams(params), Title: params.title, Type: params.type } },\n })\n .then(r => toPage<SysNotice>(r)),\n publish: (body: NoticePublishInput) =>\n client.POST('/api/v1/sys/notice', { body }).then(r => unwrap<number>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/notice/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n // ── 用户端(任何登录用户) ──\n /** 我的通知分页(含已读标记);onlyUnread 供\"未读\"页签用。 */\n mine: (params: { page: number; pageSize: number; onlyUnread?: boolean }) =>\n client\n .GET('/api/v1/sys/notice/mine', {\n params: { query: { ...pageParams(params), OnlyUnread: params.onlyUnread } },\n })\n .then(r => toPage<NoticeMineItem>(r)),\n /** 当前用户未读通知数(顶栏角标轮询)。 */\n unreadCount: () => client.GET('/api/v1/sys/notice/unread-count', {}).then(r => unwrap<number>(r)),\n markRead: (id: number) =>\n client\n .PUT('/api/v1/sys/notice/{id}/read', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n markAllRead: () => client.PUT('/api/v1/sys/notice/read-all', {}).then(r => unwrap<boolean>(r)),\n}\n\n// 菜单管理:菜单树 CRUD + 可授权路由清单(喂菜单表单「权限码」下拉)。\nexport const menuApi = {\n tree: () => client.GET('/api/v1/sys/menu/tree', {}).then(r => unwrap<MenuTreeNode[]>(r)),\n /** 可授权路由清单(后端 EndpointDataSource 实时算出,含消费方自建控制器);喂菜单表单「权限码」下拉,免手敲。 */\n routes: () =>\n client.GET('/api/v1/sys/menu/routes', {}).then(r => unwrap<PermissionRouteItem[]>(r)),\n add: (body: MenuInput) =>\n client.POST('/api/v1/sys/menu/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: MenuInput) =>\n client\n .PUT('/api/v1/sys/menu/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/menu/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// ── 定时任务 ──────────────────────────────\n\n// 定时任务:CRUD + 启停 / 手动执行一次 / cron 预览 / 处理器清单,外加执行记录查询、终止与监控仪表盘。\nexport const jobApi = {\n /** 任务分页;搜索键 name/status/handlerKind → PascalCase 查询参。行含全列,编辑表单直接用行数据。 */\n page: (params: {\n page: number\n pageSize: number\n name?: string\n status?: number\n handlerKind?: number\n sortField?: string\n sortOrder?: string\n }) =>\n client\n .GET('/api/v1/sys/job/page', {\n params: {\n query: {\n ...pageParams(params),\n Name: params.name,\n Status: params.status,\n HandlerKind: params.handlerKind,\n SortField: params.sortField,\n SortOrder: params.sortOrder,\n },\n },\n })\n .then(r => toPage<SysJob>(r)),\n add: (body: JobInput) => client.POST('/api/v1/sys/job', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: JobInput) =>\n client\n .PUT('/api/v1/sys/job/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/job/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量删除(命中内置任务后端整批拒绝 47014)。 */\n batchRemove: (ids: number[]) =>\n client.POST('/api/v1/sys/job/batch-delete', { body: { ids } }).then(r => unwrap<boolean>(r)),\n /** 专用启停端点:true=恢复调度并重算下次执行时刻(顺带清连败计数),false=暂停。 */\n setEnabled: (id: number, enabled: boolean) =>\n client\n .PUT('/api/v1/sys/job/{id}/enabled', { params: { path: { id }, query: { enabled } } })\n .then(r => unwrap<boolean>(r)),\n /** 执行一次(收到请求的副本本机执行,不经选主、不影响调度节奏)。 */\n run: (id: number) =>\n client\n .POST('/api/v1/sys/job/{id}/run', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** cron 预览([ActiveSession] 任何登录用户可用;POST 因 cron 含 `? #` 走 query 有转义坑)。 */\n previewCron: (body: { cron: string; count?: number; from?: string | null }) =>\n client.POST('/api/v1/sys/job/preview-cron', { body }).then(r => unwrap<CronPreviewOutput>(r)),\n /** 已注册的编译处理器清单(表单下拉数据源,免手打 HandlerName)。 */\n handlers: () =>\n client.GET('/api/v1/sys/job/handlers', {}).then(r => unwrap<JobHandlersOutput>(r)),\n /**\n * 执行记录分页。startRange 是 SmartTable daterange 的 [开始, 结束] 日期串,\n * 拆成后端 StartFrom/StartTo,结束日补 23:59:59(同 splitRange 的理由,但参数名不同,不复用)。\n */\n logPage: (params: {\n page: number\n pageSize: number\n jobId?: number\n runStatus?: number\n startRange?: [string, string] | null\n fireInstanceId?: number\n }) =>\n client\n .GET('/api/v1/sys/job/log/page', {\n params: {\n query: {\n ...pageParams(params),\n JobId: params.jobId,\n RunStatus: params.runStatus,\n FireInstanceId: params.fireInstanceId,\n StartFrom: params.startRange?.[0] || undefined,\n StartTo: params.startRange?.[1] ? `${params.startRange[1]} 23:59:59` : undefined,\n },\n },\n })\n .then(r => toPage<SysJobLog>(r)),\n /** 终止一次执行(跨节点写终止旗标,目标节点最迟 KillPollSeconds 后停)。 */\n kill: (logId: number) =>\n client\n .POST('/api/v1/sys/job/log/{id}/kill', { params: { path: { id: logId } } })\n .then(r => unwrap<boolean>(r)),\n /** 清空执行记录(硬删;运行中的一律保留),返回删除行数。 */\n logClear: (body: { beforeDays?: number | null; jobId?: number | null }) =>\n client.POST('/api/v1/sys/job/log/clear', { body }).then(r => unwrap<number>(r)),\n /** 监控仪表盘(今日成败/在飞/趋势/即将执行/集群节点)。 */\n dashboard: () => client.GET('/api/v1/sys/job/dashboard', {}).then(r => unwrap<JobDashboard>(r)),\n}\n\n// ── 回收站 ────────────────────────────────────────────────────────\n\nexport interface RecycleBinItem {\n id: number\n name: string\n code: string | null\n deletedAt: string | null\n deletedBy: number | null\n}\n\nexport const recycleApi = {\n page: (type: string) => (params: { page: number; pageSize: number }) =>\n client\n .GET('/api/v1/sys/recycle/{type}/page', {\n params: { path: { type }, query: pageParams(params) },\n })\n .then(r => toPage<RecycleBinItem>(r)),\n restore: (type: string, id: number) =>\n client\n .POST('/api/v1/sys/recycle/{type}/{id}/restore', { params: { path: { type, id } } })\n .then(r => unwrap<boolean>(r)),\n purge: (type: string, id: number) =>\n client\n .DELETE('/api/v1/sys/recycle/{type}/{id}', { params: { path: { type, id } } })\n .then(r => unwrap<boolean>(r)),\n}\n"],"names":["ApiError","code","msgKey","args","message","__publicField","unwrap","res","data","error","response","env","pd","callApi","method","url","body","request","client","r","pageParams","p","listQuery","dayRange","range","toPage","unwrapDownload","blob","ct","normalizePreview","raw","c","normalizeRow","e","normalizeCommit","toWireRows","rows","cells","k","v","authApi","mfaApi","highSensApi","id","externalAuthApi","runtime","ticket","pendingLink","dashboardApi","personalApi","moduleId","sessionId","userApi","params","ids","newPassword","enabled","file","mapping","LONG_TIMEOUT_MS","b","fd","strategy","orgApi","positionApi","roleApi","roleId","menuIds","scopeType","customOrgIds","userIds","moduleApi","configApi","group","all","current","page","items","splitRange","start","end","logApi","monitorApi","cacheApi","dictApi","typeCode","list","dictAdminApi","fileApi","uploadId","index","chunk","sessionApi","noticeApi","menuApi","jobApi","_a","_b","logId","recycleApi","type"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/api/index.ts"],"sourcesContent":["// 平台内核 API + 给域模块复用的原语(unwrap/ApiError/pageParams/toPage/listQuery/dayRange)。\n// 应用的业务端点写在自己的 src/api/<域>.ts 里,从 smart-admin-web 导入这些原语与 createApiClient。\n// 这些原语是包的公开导出,包内没有调用方是设计如此,别当未使用代码清掉。\nimport { client, LONG_TIMEOUT_MS } from './client'\nimport { runtime } from '#/lib/runtime'\nimport type { components } from './schema'\nimport type {\n AddUserInput,\n AddUserOutput,\n ChunkInitOutput,\n ConfigInput,\n CronPreviewOutput,\n DashboardSummary,\n DataScopeType,\n DictItem,\n DictItemInput,\n DictTypeInput,\n DuplicateStrategy,\n FileUploadOutput,\n ImportCommitResult,\n ImportPreview,\n ImportRow,\n JobDashboard,\n JobHandlersOutput,\n JobInput,\n LoginOutput,\n ModuleInput,\n ModuleRow,\n MyModulesOutput,\n MySessionItem,\n NoticeMineItem,\n NoticePublishInput,\n OnlineSessionItem,\n OrgInput,\n PagedList,\n PermissionRouteItem,\n PositionInput,\n RoleInput,\n ServerInfoOutput,\n SysConfig,\n SysDictItem,\n SysDictType,\n SysExceptionLog,\n SysFile,\n SysJob,\n SysJobLog,\n SysLoginLog,\n SysNotice,\n SysOpLog,\n SysOrg,\n SysPosition,\n SysRole,\n SysRoleDataScope,\n UpdateUserInput,\n UserDetail,\n UserItem,\n UserProfile,\n} from '#/types/api'\nimport type { MenuInput, MenuNode, MenuTreeNode } from '#/types/menu'\n\n/** 业务错误(含后端 code / msgKey);视图 catch 后经 translateError 展示。 */\nexport class ApiError extends Error {\n code: number\n msgKey?: string\n args?: Record<string, unknown>\n constructor(code: number, msgKey?: string, args?: Record<string, unknown>, message?: string) {\n super(message ?? msgKey ?? `Error ${code}`)\n this.name = 'ApiError'\n this.code = code\n this.msgKey = msgKey\n this.args = args\n }\n}\n\ninterface Envelope {\n code?: number\n msgKey?: string\n args?: Record<string, unknown>\n message?: string\n data?: unknown\n}\n\n/**\n * 解包 openapi-fetch 结果,同时容忍两种形状:\n * - 2xx:body 是 Result<T> 信封;code!==0 抛 ApiError,否则返回 data.data。\n * - 非 2xx:enveloped(401/403/429)有 code → 抛带 code 的 ApiError;\n * ProblemDetails(400 校验 / 500)无 code → 抛 status + title/detail。\n */\nexport function unwrap<T>(res: { data?: unknown; error?: unknown; response: Response }): T {\n const { data, error, response } = res\n if (error !== undefined && error !== null) {\n const env = error as Envelope\n if (typeof env.code === 'number') {\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n }\n const pd = error as { title?: string; detail?: string }\n throw new ApiError(\n response.status,\n undefined,\n undefined,\n pd.title ?? pd.detail ?? response.statusText,\n )\n }\n const env = (data ?? {}) as Envelope\n if (typeof env.code === 'number' && env.code !== 0) {\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n }\n return env.data as T\n}\n\n/**\n * 按「方法 + 站内路径」调一个运行期才知道 url 的接口(通知动作按钮这类场景),\n * 走同一套中间件(令牌 / CSRF / 刷新重放 / 超时)与信封解包。url 必须是 /api/ 开头的站内路径,\n * 调用方先用 lib/noticeActions 的 classifyNoticeAction 把关。\n */\nexport function callApi<T = unknown>(\n method: 'GET' | 'POST',\n url: string,\n body?: unknown,\n): Promise<T> {\n // openapi-fetch 的 request 只认 schema 里的路径字面量;这里的 url 来自数据,类型上放开一次。\n const request = client.request as unknown as (\n m: string,\n u: string,\n init?: { body?: unknown },\n ) => Promise<{ data?: unknown; error?: unknown; response: Response }>\n return request(method, url, body === undefined ? undefined : { body }).then(r => unwrap<T>(r))\n}\n\n/**\n * 分页三件套复用(每个列表端点都重复):\n * - 前端 {page,pageSize} → 后端 record 属性 {Current,Size}(PascalCase;ASP.NET 绑定大小写不敏感但类型要 Pascal)。\n * `...pageParams(p)` 展进各端点自己的 PascalCase 过滤条件,查询对象仍逐端点强类型校验(不走 any)。\n * - 后端 PagedList<T>({current,size,total,items}) → SmartTable fetcher 契约的 {items,total}。\n *\n * 二者连同 unwrap/ApiError 一起从包入口导出,是<b>应用写自己 API 模块的接缝</b>:应用的 `src/api/<域>.ts`\n * 从 smart-admin-web 导入它们,分页端点就与内核端点同一套映射。包内没有别的调用方也必须留着,别当未使用导出清掉。\n */\nexport const pageParams = (p: { page: number; pageSize: number }) => ({\n Current: p.page,\n Size: p.pageSize,\n})\n\n/**\n * 「编号 + 名称 + 关键字 + 排序」这套列表参数是后端 CRUD 模板的默认产出,二十来个端点逐字重复。\n * 不带 Keyword 的端点用 `Omit<ListParams, 'keyword'>`,别把不存在的过滤条件写进签名骗调用方。\n */\nexport interface ListParams {\n page: number\n pageSize: number\n keyword?: string\n number?: string\n name?: string\n sortField?: string\n sortOrder?: string\n}\n\n/**\n * ListParams → 后端 PascalCase 查询串。\n * undefined 字段由 openapi-fetch 的 querySerializer 直接跳过,所以不带 keyword 的端点复用它也不会多发参数。\n */\nexport const listQuery = (p: ListParams) => ({\n ...pageParams(p),\n Keyword: p.keyword,\n Number: p.number,\n Name: p.name,\n SortField: p.sortField,\n SortOrder: p.sortOrder,\n})\n\n/**\n * SmartTable 的 daterange 控件回传 `[开始, 结束]`(YYYY-MM-DD),后端要拆成两个参数。\n * 结束日必须补 23:59:59,否则\"筛到今天\"会把今天已经发生的数据全部漏掉(纯日期串等价于当天 00:00:00)。\n * 各域 API 模块的参数名不同(XxxStart/XxxEnd),所以这里只回中性的 start/end 由调用方改名。\n */\nexport const dayRange = (range?: [string, string] | null) => {\n if (!range || range.length !== 2) return { start: undefined, end: undefined }\n return { start: range[0] || undefined, end: range[1] ? `${range[1]} 23:59:59` : undefined }\n}\n\nexport function toPage<T>(res: Parameters<typeof unwrap>[0]): { items: T[]; total: number } {\n const p = unwrap<PagedList<T>>(res)\n return { items: p.items, total: p.total }\n}\n\n/**\n * 下载 xlsx 等二进制:parseAs blob + 手查 ok(unwrap 假定 JSON 信封,接不了二进制)。\n * AdminExceptionFilter 对业务失败仍回 HTTP 200 + JSON 信封,故还要辨 content-type /\n * 是否以 `{` 开头,避免把错误信封当 xlsx 触发下载。\n *\n * 与 unwrap/pageParams/toPage 一样是<b>应用接缝</b>:应用 `src/api/<域>.ts` 的导出端点从 smart-admin-web 导入它,\n * 别在自己文件里再抄一份错误信封嗅探(抄漏一个分支就会把失败信封当 xlsx 存到用户磁盘上)。\n */\nexport async function unwrapDownload(res: {\n data?: unknown\n error?: unknown\n response: Response\n}): Promise<Blob> {\n const { data, error, response } = res\n if (!response.ok) {\n const env = (error ?? {}) as Envelope\n if (typeof env.code === 'number')\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n throw new ApiError(response.status, undefined, undefined, response.statusText)\n }\n const blob = data as Blob\n const ct = response.headers.get('content-type') ?? ''\n if (ct.includes('spreadsheet') || ct.includes('octet-stream')) return blob\n // 200 + application/json = 业务失败信封(导出行数超限等)\n if (ct.includes('json') || ct.includes('text/plain')) {\n const env = JSON.parse(await blob.text()) as Envelope\n if (typeof env.code === 'number' && env.code !== 0) {\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n }\n } else {\n // content-type 缺失时嗅探:xlsx 是 zip(`PK`),信封以 `{` 开头\n const head = new Uint8Array(await blob.slice(0, 1).arrayBuffer())\n if (head[0] === 0x7b /* { */) {\n const env = JSON.parse(await blob.text()) as Envelope\n if (typeof env.code === 'number' && env.code !== 0) {\n throw new ApiError(env.code, env.msgKey, env.args, env.message)\n }\n }\n }\n return blob\n}\n\n/**\n * 归一 ImportPreview:int64/int 序列化噪音 → number,缺省数组补齐。\n * 与 unwrap/unwrapDownload 一样是<b>应用接缝</b>:应用 `src/api/<域>.ts` 接自己的导入端点时从 smart-admin-web 导入它,\n * 别各自抄一份归一逻辑 —— 漏一个 Number() 就会让 ImportWizard 的错误计数错位。\n */\nexport function normalizePreview(raw: ImportPreview): ImportPreview {\n return {\n headers: raw.headers ?? [],\n mapping: raw.mapping ?? {},\n columns: (raw.columns ?? []).map(c => ({\n key: c.key,\n title: c.title,\n required: c.required,\n dictTypeCode: c.dictTypeCode,\n hint: c.hint,\n width: c.width != null ? Number(c.width) : undefined,\n })),\n rows: (raw.rows ?? []).map(normalizeRow),\n total: Number(raw.total ?? 0),\n errorRows: Number(raw.errorRows ?? 0),\n columnErrors: (raw.columnErrors ?? []).map(e => ({\n columnKey: e.columnKey,\n code: Number(e.code),\n args: e.args,\n })),\n }\n}\n\nfunction normalizeRow(r: ImportRow): ImportRow {\n return {\n index: Number(r.index ?? 0),\n cells: { ...r.cells },\n errors: (r.errors ?? []).map(e => ({\n columnKey: e.columnKey,\n code: Number(e.code),\n args: e.args,\n })),\n }\n}\n\nexport function normalizeCommit(raw: ImportCommitResult): ImportCommitResult {\n return {\n total: Number(raw.total ?? 0),\n inserted: Number(raw.inserted ?? 0),\n updated: Number(raw.updated ?? 0),\n skipped: Number(raw.skipped ?? 0),\n failed: Number(raw.failed ?? 0),\n failures: (raw.failures ?? []).map(normalizeRow),\n }\n}\n\n/**\n * 回传行:schema 把 cells 标成 `Record<string, string>`(无 null),而运行时/编辑态允许空。\n * 发送前把 null/undefined 收成 `''`,避免 openapi-fetch 类型卡死。\n * 同为应用接缝,见 normalizePreview 上的说明。\n */\nexport function toWireRows(rows: ImportRow[]) {\n return rows.map(r => {\n const cells: Record<string, string> = {}\n for (const [k, v] of Object.entries(r.cells ?? {})) cells[k] = v ?? ''\n return {\n index: r.index,\n cells,\n errors: r.errors.map(e => ({\n columnKey: e.columnKey,\n code: e.code,\n args: e.args as Record<string, never> | null | undefined,\n })),\n }\n })\n}\n\nexport const authApi = {\n login: (body: { account: string; password: string; captchaId?: string; captchaCode?: string }) =>\n client.POST('/api/v1/auth/login', { body }).then(r => unwrap<LoginOutput>(r)),\n logout: () => client.POST('/api/v1/auth/logout', {}).then(r => unwrap<boolean>(r)),\n captcha: () =>\n client\n .GET('/api/v1/auth/captcha', {})\n .then(r => unwrap<{ captchaId: string; svg: string; type?: string }>(r)),\n /** 短信二次验证:凭密码登录 40009 信令下发的挑战 Id + 短信码完成登录。 */\n smsChallengeLogin: (body: { challengeId: string; code: string }) =>\n client.POST('/api/v1/auth/login/sms', { body }).then(r => unwrap<LoginOutput>(r)),\n /** 短信二次验证:重发验证码(服务端冷却/日上限,过频抛 40008)。 */\n smsChallengeResend: (body: { challengeId: string }) =>\n client\n .POST('/api/v1/auth/login/sms/resend', { body })\n .then(r => unwrap<{ expiresSeconds: number; resendSeconds: number }>(r)),\n /** TOTP 二次验证完成登录(40018 / SSO totpChallenge);走 openapi-fetch → CSRF/credentials 中间件生效。 */\n totpChallengeLogin: (body: { challengeId: string; code: string }) =>\n client.POST('/api/v1/auth/login/totp', { body }).then(r => unwrap<LoginOutput>(r)),\n /** 短时再认证(高危写操作 40024 后由中间件唤起;窗口约 5 分钟)。 */\n reauth: (body: { method?: string; totpCode?: string; password?: string }) =>\n client.POST('/api/v1/auth/reauth', { body }).then(r => unwrap<void>(r)),\n /** 免密登录发码(图形验证码启用时须携带;响应不区分手机号是否存在,防枚举)。 */\n smsLoginSend: (body: { phone: string; captchaId?: string; captchaCode?: string }) =>\n client\n .POST('/api/v1/auth/sms/send', { body })\n .then(r => unwrap<{ expiresSeconds: number; resendSeconds: number }>(r)),\n /** 免密登录:手机号 + 短信码换令牌。 */\n smsLogin: (body: { phone: string; code: string }) =>\n client.POST('/api/v1/auth/sms/login', { body }).then(r => unwrap<LoginOutput>(r)),\n}\n\n/** TOTP 自助绑定 / 恢复 / 管理员清除(ADR 0006;无邀请路径)。 */\nexport const mfaApi = {\n bindStart: (body: components['schemas']['TotpBindStartInput']) =>\n client\n .POST('/api/v1/auth/mfa/bind/start', { body })\n .then(r => unwrap<components['schemas']['TotpBindStartOutput']>(r)),\n bindComplete: (body: components['schemas']['TotpBindCompleteInput']) =>\n client\n .POST('/api/v1/auth/mfa/bind/complete', { body })\n .then(r => unwrap<components['schemas']['TotpBindCompleteOutput']>(r)),\n recovery: (body: components['schemas']['TotpRecoveryInput']) =>\n client.POST('/api/v1/auth/mfa/recovery', { body }).then(r => unwrap<void>(r)),\n clear: (body: components['schemas']['TotpClearMfaInput']) =>\n client.POST('/api/v1/sys/mfa/clear', { body }).then(r => unwrap<void>(r)),\n}\n\n/** 高敏权限自定义追加(内核默认只读;写操作须 reauth)。 */\nexport const highSensApi = {\n list: () =>\n client\n .GET('/api/v1/sys/mfa/high-sensitivity', {})\n .then(r => unwrap<components['schemas']['HighSensitivityPermissionList']>(r)),\n add: (body: components['schemas']['HighSensitivityPermissionInput']) =>\n client\n .POST('/api/v1/sys/mfa/high-sensitivity', { body })\n .then(r => unwrap<components['schemas']['HighSensitivityPermissionItem']>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/mfa/high-sensitivity/{id}', { params: { path: { id } } })\n .then(r => unwrap<void>(r)),\n}\n\nexport interface ExternalProvider {\n code: string\n displayName: string\n icon?: string | null\n}\n\n/** 管理端:全部已注册 provider(含已禁用)+ enabled / linkByAccount 两个运营开关。 */\nexport interface ExternalProviderAdmin extends ExternalProvider {\n enabled: boolean\n linkByAccount: boolean\n}\n\nexport interface ExternalBinding {\n provider: string\n displayName?: string | null\n boundAt: string\n}\n\n// 外部登录 / SSO。登录:providers 点亮按钮 → 顶层导航到 authorizeUrl(后端 302 跳 IdP)→ 回调页 exchange 换令牌。\n// 绑定(个人中心):bindStart 拿授权 URL 跳转 → 同一回调把外部身份绑到当前用户;bindings 查、unbind 解绑。\nexport const externalAuthApi = {\n /** 登录页可用的外部登录方式(启用的);空数组 = 不显 SSO 区。 */\n providers: () =>\n client.GET('/api/v1/auth/external/providers', {}).then(r => unwrap<ExternalProvider[]>(r)),\n /** 管理端全量列表(含已禁用);系统配置「第三方登录」Tab。 */\n providersAll: () =>\n client\n .GET('/api/v1/auth/external/providers/all', {})\n .then(r => unwrap<ExternalProviderAdmin[]>(r)),\n /** 发起某 provider 登录的 URL(顶层浏览器导航,不走 fetch —— 后端 302 跳 IdP)。 */\n authorizeUrl: (code: string) =>\n `${runtime.apiBase}/api/v1/auth/external/${encodeURIComponent(code)}/authorize`,\n /** 一次性票据换令牌(登录回调后);票据无效/过期/已用抛 40014。 */\n exchange: (ticket: string) =>\n client\n .POST('/api/v1/auth/external/exchange', { body: { ticket } })\n .then(r => unwrap<LoginOutput>(r)),\n /** 认领未绑定 SSO 的 pending-link(账密登录后);票据无效 40014,已被他人绑 40017。 */\n claimPendingLink: (pendingLink: string) =>\n client\n .POST('/api/v1/auth/external/pending-link/claim', { body: { pendingLink } })\n .then(r => unwrap<boolean>(r)),\n /** 我的外部账号绑定列表(个人中心)。 */\n bindings: () =>\n client.GET('/api/v1/auth/external/bindings', {}).then(r => unwrap<ExternalBinding[]>(r)),\n /** 发起绑定:返回授权 URL,前端跳转开始 OAuth 往返(回调把身份绑到当前用户)。 */\n bindStart: (code: string) =>\n client\n .POST('/api/v1/auth/external/{provider}/bind', { params: { path: { provider: code } } })\n .then(r => unwrap<{ authorizeUrl: string }>(r)),\n /** 解绑某 provider 的外部账号。 */\n unbind: (code: string) =>\n client\n .DELETE('/api/v1/auth/external/{provider}/binding', { params: { path: { provider: code } } })\n .then(r => unwrap<boolean>(r)),\n}\n\nexport const dashboardApi = {\n /** 工作台首页统计([ActiveSession]:任何登录用户可取,无需权限码)。 */\n summary: () => client.GET('/api/v1/dashboard/summary', {}).then(r => unwrap<DashboardSummary>(r)),\n}\n\nexport const personalApi = {\n modules: () => client.GET('/api/v1/personal/modules', {}).then(r => unwrap<MyModulesOutput>(r)),\n menu: (moduleId: number) =>\n client\n .GET('/api/v1/personal/menu', { params: { query: { moduleId } } })\n .then(r => unwrap<MenuNode[]>(r)),\n setDefaultModule: (moduleId: number) =>\n client\n .PUT('/api/v1/personal/default-module', { body: { moduleId } })\n .then(r => unwrap<boolean>(r)),\n profile: () => client.GET('/api/v1/personal/profile', {}).then(r => unwrap<UserProfile>(r)),\n /** 改自己的资料(全量替换语义:缺字段即置空,前端整表单提交)。 */\n updateProfile: (body: {\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n }) => client.PUT('/api/v1/personal/profile', { body }).then(r => unwrap<boolean>(r)),\n /** 我的活跃会话列表(个人视角;isCurrent = 本次请求所用会话)。 */\n sessions: () => client.GET('/api/v1/personal/sessions', {}).then(r => unwrap<MySessionItem[]>(r)),\n /** 下线自己的某个会话;他人的/不存在的一律 42024(不区分,防探测)。 */\n kickSession: (sessionId: string) =>\n client\n .DELETE('/api/v1/personal/sessions/{sessionId}', { params: { path: { sessionId } } })\n .then(r => unwrap<boolean>(r)),\n updatePassword: (body: { oldPassword: string; newPassword: string }) =>\n client.PUT('/api/v1/personal/password', { body }).then(r => unwrap<boolean>(r)),\n /** 当前用户权限码集合(= 规范化路由);喂给 authStore.permissionCodes 驱动 v-auth。超管返回空集。 */\n permissions: () => client.GET('/api/v1/personal/permissions', {}).then(r => unwrap<string[]>(r)),\n}\n\n// 用户管理:CRUD + 启停 / 重置密码 + xlsx 导入导出。\nexport const userApi = {\n /** 归一后端 PagedList<UserItem>({current,size,total,items}) → SmartTable fetcher 契约的 {items,total}。 */\n page: (params: {\n page: number\n pageSize: number\n account?: string\n name?: string\n orgId?: number\n roleId?: number\n sortField?: string\n sortOrder?: string\n }) =>\n client\n .GET('/api/v1/sys/user/page', {\n // 查询参数名沿用后端 record 属性(PascalCase);ASP.NET 绑定大小写不敏感,类型要求 PascalCase。\n // roleId:角色反查(「这个角色有哪些人」/ 删角色前报人数)复用本端点,不另开接口。\n // sortField/sortOrder:SmartTable 排序;后端按实体列白名单校验(非法忽略回退默认),见 PagedListExtensions.OrderBySafe。\n params: {\n query: {\n ...pageParams(params),\n Account: params.account,\n Name: params.name,\n OrgId: params.orgId,\n RoleId: params.roleId,\n SortField: params.sortField,\n SortOrder: params.sortOrder,\n },\n },\n })\n .then(r => toPage<UserItem>(r)),\n /** 用户详情(含 roleIds,编辑回显 + 提交时原样带回避免清空角色)。 */\n detail: (id: number) =>\n client\n .GET('/api/v1/sys/user/{id}', { params: { path: { id } } })\n .then(r => unwrap<UserDetail>(r)),\n /** 新增用户;返回新 Id + 实际生效的初始口令(留空 password 时后端随机生成,不接住就没人知道这个号的密码)。 */\n add: (body: AddUserInput) =>\n client.POST('/api/v1/sys/user', { body }).then(r => unwrap<AddUserOutput>(r)),\n update: (id: number, body: UpdateUserInput) =>\n client\n .PUT('/api/v1/sys/user/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/user/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量软删除;集合含超管后端整体拒绝(SuperAdminProtected)。 */\n batchRemove: (ids: number[]) =>\n client.POST('/api/v1/sys/user/batch-delete', { body: { ids } }).then(r => unwrap<boolean>(r)),\n /** 重置密码;返回实际生效的初始密码(newPassword 留空 = 后端默认初始密码)。 */\n resetPassword: (id: number, newPassword?: string | null) =>\n client\n .PUT('/api/v1/sys/user/{id}/password', {\n params: { path: { id } },\n body: { newPassword: newPassword || null },\n })\n .then(r => unwrap<string>(r)),\n /** 专用启停端点(非全量 update)。 */\n setEnabled: (id: number, enabled: boolean) =>\n client\n .PUT('/api/v1/sys/user/{id}/enabled', { params: { path: { id } }, body: { enabled } })\n .then(r => unwrap<boolean>(r)),\n\n // ── 导入 / 导出 ──\n\n /** 下载用户导入模板(xlsx)。[ActiveSession],无需独立权限码。 */\n importTemplate: () =>\n client\n .GET('/api/v1/sys/user/import/template', { parseAs: 'blob' })\n .then(r => unwrapDownload(r)),\n\n /**\n * 上传 xlsx 预览校验。multipart:`file` + 可选 `mapping`(JSON 字符串:表头→列 Key)。\n * bodySerializer 建 FormData(与 fileApi.upload 同型)。\n */\n importPreview: (file: File, mapping?: Record<string, string>) =>\n client\n .POST('/api/v1/sys/user/import/preview', {\n timeout: LONG_TIMEOUT_MS,\n body: {\n file: file as unknown as string,\n mapping: mapping ? JSON.stringify(mapping) : undefined,\n },\n bodySerializer: body => {\n const b = body as unknown as { file: File; mapping?: string }\n const fd = new FormData()\n fd.append('file', b.file)\n if (b.mapping) fd.append('mapping', b.mapping)\n return fd\n },\n })\n .then(r => normalizePreview(unwrap<ImportPreview>(r))),\n\n /** 对前端改过的行重新校验(不碰文件)。 */\n importValidate: (rows: ImportRow[]) =>\n client\n .POST('/api/v1/sys/user/import/validate', {\n timeout: LONG_TIMEOUT_MS,\n body: { rows: toWireRows(rows) },\n })\n .then(r => normalizePreview(unwrap<ImportPreview>(r))),\n\n /** 下载错误报告 xlsx(原列 +「错误原因」列)。 */\n importErrorReport: (rows: ImportRow[]) =>\n client\n .POST('/api/v1/sys/user/import/error-report', {\n timeout: LONG_TIMEOUT_MS,\n body: { rows: toWireRows(rows) },\n parseAs: 'blob',\n })\n .then(r => unwrapDownload(r)),\n\n /** 按策略提交导入(部分提交:有错行跳过;服务端重校验,不信任前端 Errors)。 */\n importCommit: (rows: ImportRow[], strategy: DuplicateStrategy = 0) =>\n client\n .POST('/api/v1/sys/user/import/commit', {\n timeout: LONG_TIMEOUT_MS,\n body: { rows: toWireRows(rows), strategy },\n })\n .then(r => normalizeCommit(unwrap<ImportCommitResult>(r))),\n\n /**\n * 导出用户 xlsx。筛选条件与列表同源(Account/Name/OrgId/RoleId…)+ `columns` 逗号分隔列 Key。\n * 返回 blob,不进信封。\n */\n export: (params: {\n account?: string\n name?: string\n orgId?: number\n roleId?: number\n enabled?: boolean\n sortField?: string\n sortOrder?: string\n /** 逗号分隔列 Key;缺省 = 档案 DefaultSelected */\n columns?: string\n }) =>\n client\n .GET('/api/v1/sys/user/export', {\n timeout: LONG_TIMEOUT_MS,\n params: {\n query: {\n Account: params.account,\n Name: params.name,\n OrgId: params.orgId,\n RoleId: params.roleId,\n Enabled: params.enabled,\n SortField: params.sortField,\n SortOrder: params.sortOrder,\n columns: params.columns,\n },\n },\n parseAs: 'blob',\n })\n .then(r => unwrapDownload(r)),\n}\n\n// 机构管理:树形机构 CRUD + 子树复制,list 平铺返回由前端 buildTree 拼树。\nexport const orgApi = {\n /** 全部机构(平铺,按 Sort、Id 排序)。前端 buildTree 拼树。下拉 / 树表复用。 */\n list: () => client.GET('/api/v1/sys/org/list', {}).then(r => unwrap<SysOrg[]>(r)),\n add: (body: OrgInput) =>\n client.POST('/api/v1/sys/org/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: OrgInput) =>\n client\n .PUT('/api/v1/sys/org/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/org/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 复制机构子树(整支克隆挂到源节点同级),返回新根 Id。 */\n copy: (id: number, body?: { name?: string }) =>\n client\n .POST('/api/v1/sys/org/{id}/copy', { params: { path: { id } }, body: body })\n .then(r => unwrap<number>(r)),\n}\n\n// 职位管理:普通 CRUD;岗位与机构无关联。\nexport const positionApi = {\n /** 职位分页;搜索键 name → PascalCase Name;sortField/sortOrder → 后端安全排序。下拉(拉大页)/ SmartTable 复用。 */\n page: (params: {\n page: number\n pageSize: number\n name?: string\n sortField?: string\n sortOrder?: string\n }) =>\n client\n .GET('/api/v1/sys/position/page', {\n params: {\n query: {\n ...pageParams(params),\n Name: params.name,\n SortField: params.sortField,\n SortOrder: params.sortOrder,\n },\n },\n })\n .then(r => toPage<SysPosition>(r)),\n add: (body: PositionInput) =>\n client.POST('/api/v1/sys/position/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: PositionInput) =>\n client\n .PUT('/api/v1/sys/position/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/position/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 角色管理:CRUD + 菜单授权 / 数据范围 / 关联用户三块设置。\nexport const roleApi = {\n /** 角色分页;搜索键 name → PascalCase Name。列表用 + 用户/授权页拉一大页当下拉源。 */\n page: (params: { page: number; pageSize: number; name?: string }) =>\n client\n .GET('/api/v1/sys/role/page', {\n params: { query: { ...pageParams(params), Name: params.name } },\n })\n .then(r => toPage<SysRole>(r)),\n add: (body: RoleInput) =>\n client.POST('/api/v1/sys/role/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: RoleInput) =>\n client\n .PUT('/api/v1/sys/role/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/role/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量删除角色(各自级联清关联)。 */\n batchRemove: (ids: number[]) =>\n client.POST('/api/v1/sys/role/batch-delete', { body: { ids } }).then(r => unwrap<boolean>(r)),\n /** 某角色当前授予的菜单 Id 集合(授权抽屉回显)。 */\n getMenus: (id: number) =>\n client\n .GET('/api/v1/sys/role/{id}/menus', { params: { path: { id } } })\n .then(r => unwrap<number[]>(r)),\n /** 全量设置角色授予的菜单(空数组 = 收回全部)。 */\n setMenus: (roleId: number, menuIds: number[]) =>\n client\n .PUT('/api/v1/sys/role/menu', { body: { roleId, menuIds } })\n .then(r => unwrap<boolean>(r)),\n /** 某角色的数据范围配置(未配置返回 null)。 */\n getDataScope: (id: number) =>\n client\n .GET('/api/v1/sys/role/{id}/datascope', { params: { path: { id } } })\n .then(r => unwrap<SysRoleDataScope | null>(r)),\n /** 设置角色数据范围;customOrgIds 仅 scopeType=Custom(5)时有意义。 */\n setDataScope: (roleId: number, scopeType: DataScopeType, customOrgIds?: number[]) =>\n client\n .PUT('/api/v1/sys/role/datascope', { body: { roleId, scopeType, customOrgIds } })\n .then(r => unwrap<boolean>(r)),\n /** 某角色当前关联的用户 Id 集合(授权用户抽屉回显)。 */\n getUsers: (id: number) =>\n client\n .GET('/api/v1/sys/role/{id}/users', { params: { path: { id } } })\n .then(r => unwrap<number[]>(r)),\n /** 全量设置角色关联的用户(空数组 = 收回全部)。 */\n setUsers: (roleId: number, userIds: number[]) =>\n client\n .PUT('/api/v1/sys/role/users', { body: { roleId, userIds } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 应用(模块)管理:CRUD,门户多应用切换的应用清单来源。\nexport const moduleApi = {\n list: () => client.GET('/api/v1/sys/module/list', {}).then(r => unwrap<ModuleRow[]>(r)),\n add: (body: ModuleInput) =>\n client.POST('/api/v1/sys/module/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: ModuleInput) =>\n client\n .PUT('/api/v1/sys/module/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/module/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 系统配置:key/value 分页 CRUD + 按分组批量取/存(结构化表单用)+ 站点信息 / 密码策略两个匿名可读端点。\nexport const configApi = {\n /** 归一后端 PagedList<SysConfig> → SmartTable {items,total};搜索键 configKey/name/groupCode → PascalCase 查询参。 */\n page: (params: {\n page: number\n pageSize: number\n configKey?: string\n name?: string\n groupCode?: string\n excludedGroupCodes?: string[]\n }) =>\n client\n .GET('/api/v1/sys/config/page', {\n params: {\n query: {\n ...pageParams(params),\n ConfigKey: params.configKey,\n Name: params.name,\n GroupCode: params.groupCode,\n ExcludedGroupCodes: params.excludedGroupCodes,\n },\n },\n })\n .then(r => toPage<SysConfig>(r)),\n add: (body: ConfigInput) =>\n client.POST('/api/v1/sys/config', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: ConfigInput) =>\n client\n .PUT('/api/v1/sys/config/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/config/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /**\n * 取某分组下全部配置(完整行,含 id/key/value),供分类配置中心结构化表单回填。\n * 逐页取全:结构化表单按键回写,漏取的字段会拿默认值把库里的真实值覆盖掉。\n */\n listByGroup: async (group: string) => {\n const all: SysConfig[] = []\n for (let current = 1; ; current++) {\n const page = await client\n .GET('/api/v1/sys/config/page', {\n params: { query: { Current: current, Size: 100, GroupCode: group } },\n })\n .then(r => unwrap<PagedList<SysConfig>>(r))\n all.push(...page.items)\n if (page.items.length === 0 || all.length >= page.total) return all\n }\n },\n /** 批量按键回写配置值(结构化表单保存);仅更新已存在键,未知键后端忽略。 */\n saveBatch: (items: { configKey: string; configValue?: string | null }[]) =>\n client.PUT('/api/v1/sys/config/batch', { body: items }).then(r => unwrap<boolean>(r)),\n /** 站点信息(匿名可读:站点标题/副标题/版权等品牌展示白名单)。 */\n siteInfo: () =>\n client.GET('/api/v1/sys/config/site', {}).then(r =>\n unwrap<{\n title?: string | null\n subtitle?: string | null\n copyright?: string | null\n copyrightUrl?: string | null\n logo?: string | null\n captchaEnabled?: boolean\n smsLoginEnabled?: boolean\n }>(r),\n ),\n /** 当前生效密码策略(任何登录用户可读);改密页据此展示真实规则清单,免配置读权限。 */\n passwordPolicy: () =>\n client.GET('/api/v1/sys/config/password-policy', {}).then(r =>\n unwrap<{\n minLength: number\n requireUpper: boolean\n requireLower: boolean\n requireDigit: boolean\n requireSpecial: boolean\n }>(r),\n ),\n}\n\n/** 日志端点用的参数名是 StartTime/EndTime;拆分与补 23:59:59 的理由见 dayRange。 */\nfunction splitRange(range?: [string, string] | null) {\n const { start, end } = dayRange(range)\n return { StartTime: start, EndTime: end }\n}\n\n// 日志查询:登录 / 操作 / 异常三类日志各自的分页与清空;操作日志另支持导出 xlsx。\nexport const logApi = {\n /** 登录日志分页;账号模糊 + 成败 + 时间范围。 */\n loginPage: (params: {\n page: number\n pageSize: number\n account?: string\n success?: boolean\n createTime?: [string, string] | null\n }) =>\n client\n .GET('/api/v1/sys/log/login/page', {\n params: {\n query: {\n ...pageParams(params),\n Account: params.account,\n Success: params.success,\n ...splitRange(params.createTime),\n },\n },\n })\n .then(r => toPage<SysLoginLog>(r)),\n /** 清空登录日志(硬删,不可恢复)。 */\n loginClear: () => client.DELETE('/api/v1/sys/log/login', {}).then(r => unwrap<boolean>(r)),\n /** 操作日志分页;操作名模糊 + 成败 + 操作人(精确)+ 接口路径(模糊)+ 时间范围——审计要能答\"谁在什么时候干了什么\"。 */\n opPage: (params: {\n page: number\n pageSize: number\n title?: string\n success?: boolean\n operatorId?: number\n path?: string\n createTime?: [string, string] | null\n }) =>\n client\n .GET('/api/v1/sys/log/op/page', {\n params: {\n query: {\n ...pageParams(params),\n Title: params.title,\n Success: params.success,\n OperatorId: params.operatorId,\n Path: params.path,\n ...splitRange(params.createTime),\n },\n },\n })\n .then(r => toPage<SysOpLog>(r)),\n /** 清空操作日志(硬删,不可恢复)。 */\n opClear: () => client.DELETE('/api/v1/sys/log/op', {}).then(r => unwrap<boolean>(r)),\n /**\n * 导出操作日志 xlsx。筛选与 opPage 同源 + `columns` 逗号分隔列 Key。\n * 返回 blob,不进信封。\n */\n opExport: (params: {\n title?: string\n success?: boolean\n operatorId?: number\n path?: string\n createTime?: [string, string] | null\n columns?: string\n }) =>\n client\n .GET('/api/v1/sys/log/op/export', {\n timeout: LONG_TIMEOUT_MS,\n params: {\n query: {\n Title: params.title,\n Success: params.success,\n OperatorId: params.operatorId,\n Path: params.path,\n ...splitRange(params.createTime),\n columns: params.columns,\n },\n },\n parseAs: 'blob',\n })\n .then(r => unwrapDownload(r)),\n /** 异常日志分页;接口路径模糊 + 异常类型模糊 + 时间范围。 */\n exceptionPage: (params: {\n page: number\n pageSize: number\n path?: string\n exceptionType?: string\n createTime?: [string, string] | null\n }) =>\n client\n .GET('/api/v1/sys/log/exception/page', {\n params: {\n query: {\n ...pageParams(params),\n Path: params.path,\n ExceptionType: params.exceptionType,\n ...splitRange(params.createTime),\n },\n },\n })\n .then(r => toPage<SysExceptionLog>(r)),\n /** 清空异常日志(硬删,不可恢复)。 */\n exceptionClear: () =>\n client.DELETE('/api/v1/sys/log/exception', {}).then(r => unwrap<boolean>(r)),\n}\n\n// 服务器监控:只读运行快照。\nexport const monitorApi = {\n /** 服务器运行快照(CPU/内存/磁盘/运行时;后端含一次约 500ms 的 CPU 采样)。 */\n server: () => client.GET('/api/v1/sys/monitor/server', {}).then(r => unwrap<ServerInfoOutput>(r)),\n}\n\n// 缓存管理:定向失效动作(只清不看——缓存含明文 OTP、键含 PII,故后端无键浏览/取值端点)。flush* 返回被清条数。\nexport const cacheApi = {\n /** 清全部用户的权限/数据范围缓存(返回被清用户数)。 */\n flushAuth: () => client.POST('/api/v1/sys/cache/flush-auth', {}).then(r => unwrap<number>(r)),\n /** 清全部字典项缓存(返回被清字典类型数)。 */\n flushDict: () => client.POST('/api/v1/sys/cache/flush-dict', {}).then(r => unwrap<number>(r)),\n /** 清全部系统配置缓存(返回被清配置项数)。 */\n flushConfig: () => client.POST('/api/v1/sys/cache/flush-config', {}).then(r => unwrap<number>(r)),\n /** 递增门户代际,令所有用户的门户菜单/模块缓存整体失效(返回新代际值)。 */\n rebuildPortal: () =>\n client.POST('/api/v1/sys/cache/rebuild-portal', {}).then(r => unwrap<number>(r)),\n}\n\n// 字典下拉数据源(公开只读):按类型编码取启用项,不含 id;喂 stores/dict 缓存,与 dictAdminApi 的管理端读取不能互换。\nexport const dictApi = {\n /** 按类型编码取字典项(服务端已按 sort 排序)。归一 int64 序列化噪音 → DictItem 投影,供 stores/dict 缓存消费。 */\n items: (typeCode: string) =>\n client\n .GET('/api/v1/sys/dict/items/{typeCode}', { params: { path: { typeCode } } })\n .then(r =>\n unwrap<{ label?: string; value?: string; sort?: number | string; enabled?: boolean }[]>(r),\n )\n .then(list =>\n list.map((i): DictItem => ({\n label: i.label ?? '',\n value: i.value ?? '',\n sort: Number(i.sort ?? 0),\n enabled: i.enabled ?? true,\n })),\n ),\n}\n\n// 字典管理端(受权限保护):类型 + 字典项 CRUD,含停用项、带 id;下拉展示走 dictApi,两者不能互相替代。\nexport const dictAdminApi = {\n /** 字典类型分页;搜索键 code/name → PascalCase Code/Name 查询参。 */\n typePage: (params: { page: number; pageSize: number; code?: string; name?: string }) =>\n client\n .GET('/api/v1/sys/dict/type/page', {\n params: { query: { ...pageParams(params), Code: params.code, Name: params.name } },\n })\n .then(r => toPage<SysDictType>(r)),\n typeAdd: (body: DictTypeInput) =>\n client.POST('/api/v1/sys/dict/type', { body }).then(r => unwrap<number>(r)),\n typeUpdate: (id: number, body: DictTypeInput) =>\n client\n .PUT('/api/v1/sys/dict/type/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n typeRemove: (id: number) =>\n client\n .DELETE('/api/v1/sys/dict/type/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量删除字典类型(各自级联删项)。 */\n typeBatchRemove: (ids: number[]) =>\n client\n .POST('/api/v1/sys/dict/type/batch-delete', { body: { ids } })\n .then(r => unwrap<boolean>(r)),\n /** 某类型下的字典项(管理端:含停用、带 id;非下拉缓存源)。ponytail: 拉一页 200(Api:MaxPageSize 上限),字典项数量小,真超再分页。 */\n items: (typeCode: string) =>\n client\n .GET('/api/v1/sys/dict/item/page', {\n params: { query: { TypeCode: typeCode, Current: 1, Size: 200 } },\n })\n .then(r => unwrap<PagedList<SysDictItem>>(r))\n .then(p => p.items),\n itemAdd: (body: DictItemInput) =>\n client.POST('/api/v1/sys/dict/item', { body }).then(r => unwrap<number>(r)),\n itemUpdate: (id: number, body: DictItemInput) =>\n client\n .PUT('/api/v1/sys/dict/item/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n itemRemove: (id: number) =>\n client\n .DELETE('/api/v1/sys/dict/item/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量删除字典项。 */\n itemBatchRemove: (ids: number[]) =>\n client\n .POST('/api/v1/sys/dict/item/batch-delete', { body: { ids } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 文件管理:分页 / 上传 / 下载 / 删除,外加分片断点续传上传一整套。\nexport const fileApi = {\n /** 文件分页;搜索键 originalName → 后端 FileName 模糊过滤。 */\n page: (params: { page: number; pageSize: number; originalName?: string }) =>\n client\n .GET('/api/v1/sys/file/page', {\n params: { query: { ...pageParams(params), FileName: params.originalName } },\n })\n .then(r => toPage<SysFile>(r)),\n /** 上传单个文件:bodySerializer 建 FormData(字段名 file),openapi-fetch 对 FormData 不注入 json header,浏览器自动补 boundary(client.ts 无需改)。 */\n upload: (file: File) =>\n client\n .POST('/api/v1/sys/file/upload', {\n timeout: LONG_TIMEOUT_MS,\n body: { file: file as unknown as string },\n bodySerializer: body => {\n const fd = new FormData()\n fd.append('file', (body as unknown as { file: File }).file)\n return fd\n },\n })\n .then(r => unwrap<FileUploadOutput>(r)),\n /** 下载:parseAs blob 取原始字节(非信封,不套 unwrap);Bearer 由 client 拦截器自动带。 */\n download: (id: number) =>\n client\n .GET('/api/v1/sys/file/{id}/download', {\n timeout: LONG_TIMEOUT_MS,\n params: { path: { id } },\n parseAs: 'blob',\n })\n .then(r => {\n if (!r.response.ok)\n throw new ApiError(r.response.status, undefined, undefined, r.response.statusText)\n return r.data as Blob\n }),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/file/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量软删除文件记录(物理文件保留)。 */\n batchRemove: (ids: number[]) =>\n client.POST('/api/v1/sys/file/batch-delete', { body: { ids } }).then(r => unwrap<boolean>(r)),\n // ── 分片 / 断点续传上传 ──\n /** 分片初始化:秒传探测 + 已收分片(断点续传)。 */\n chunkInit: (body: {\n fileHash: string\n fileName: string\n totalSize: number\n chunkCount: number\n }) => client.POST('/api/v1/sys/file/chunk/init', { body }).then(r => unwrap<ChunkInitOutput>(r)),\n /** 上传单个分片(multipart:uploadId + index + chunk),同 upload 用 bodySerializer 建 FormData。 */\n chunkUpload: (uploadId: string, index: number, chunk: Blob) =>\n client\n .POST('/api/v1/sys/file/chunk', {\n timeout: LONG_TIMEOUT_MS,\n body: { uploadId, index, chunk: chunk as unknown as string },\n bodySerializer: body => {\n const b = body as unknown as { uploadId: string; index: number; chunk: Blob }\n const fd = new FormData()\n fd.append('uploadId', b.uploadId)\n fd.append('index', String(b.index))\n fd.append('chunk', b.chunk)\n return fd\n },\n })\n .then(r => unwrap<boolean>(r)),\n /** 完成:触发服务端合并 + 哈希校验 + 三道关 + 落库。 */\n chunkComplete: (body: {\n uploadId: string\n fileHash: string\n fileName: string\n chunkCount: number\n }) =>\n client\n .POST('/api/v1/sys/file/chunk/complete', { timeout: LONG_TIMEOUT_MS, body })\n .then(r => unwrap<FileUploadOutput>(r)),\n}\n\n// 在线会话:只读分页 + 按 sessionId 强制下线。\nexport const sessionApi = {\n /** 在线会话分页(只读)。后端仅支持按 UserId 过滤,这里不带业务搜索。 */\n online: (params: { page: number; pageSize: number }) =>\n client\n .GET('/api/v1/sys/session/online', { params: { query: pageParams(params) } })\n .then(r => toPage<OnlineSessionItem>(r)),\n /** 强制下线:按 sessionId 踢会话。 */\n kick: (sessionId: string) =>\n client\n .DELETE('/api/v1/sys/session/{sessionId}', { params: { path: { sessionId } } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// 系统通知:管理端发布 / 撤回 + 用户端分页拉取 / 标记已读。\nexport const noticeApi = {\n // ── 管理端 ──\n /** 管理端分页(全量);搜索键 title/type → PascalCase 查询参。 */\n page: (params: { page: number; pageSize: number; title?: string; type?: number }) =>\n client\n .GET('/api/v1/sys/notice/page', {\n params: { query: { ...pageParams(params), Title: params.title, Type: params.type } },\n })\n .then(r => toPage<SysNotice>(r)),\n publish: (body: NoticePublishInput) =>\n client.POST('/api/v1/sys/notice', { body }).then(r => unwrap<number>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/notice/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n // ── 用户端(任何登录用户) ──\n /** 我的通知分页(含已读标记);onlyUnread 供\"未读\"页签用。 */\n mine: (params: { page: number; pageSize: number; onlyUnread?: boolean }) =>\n client\n .GET('/api/v1/sys/notice/mine', {\n params: { query: { ...pageParams(params), OnlyUnread: params.onlyUnread } },\n })\n .then(r => toPage<NoticeMineItem>(r)),\n /** 当前用户未读通知数(顶栏角标轮询)。 */\n unreadCount: () => client.GET('/api/v1/sys/notice/unread-count', {}).then(r => unwrap<number>(r)),\n markRead: (id: number) =>\n client\n .PUT('/api/v1/sys/notice/{id}/read', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n markAllRead: () => client.PUT('/api/v1/sys/notice/read-all', {}).then(r => unwrap<boolean>(r)),\n}\n\n// 菜单管理:菜单树 CRUD + 可授权路由清单(喂菜单表单「权限码」下拉)。\nexport const menuApi = {\n tree: () => client.GET('/api/v1/sys/menu/tree', {}).then(r => unwrap<MenuTreeNode[]>(r)),\n /** 可授权路由清单(后端 EndpointDataSource 实时算出,含消费方自建控制器);喂菜单表单「权限码」下拉,免手敲。 */\n routes: () =>\n client.GET('/api/v1/sys/menu/routes', {}).then(r => unwrap<PermissionRouteItem[]>(r)),\n add: (body: MenuInput) =>\n client.POST('/api/v1/sys/menu/add', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: MenuInput) =>\n client\n .PUT('/api/v1/sys/menu/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/menu/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n}\n\n// ── 定时任务 ──────────────────────────────\n\n// 定时任务:CRUD + 启停 / 手动执行一次 / cron 预览 / 处理器清单,外加执行记录查询、终止与监控仪表盘。\nexport const jobApi = {\n /** 任务分页;搜索键 name/status/handlerKind → PascalCase 查询参。行含全列,编辑表单直接用行数据。 */\n page: (params: {\n page: number\n pageSize: number\n name?: string\n status?: number\n handlerKind?: number\n sortField?: string\n sortOrder?: string\n }) =>\n client\n .GET('/api/v1/sys/job/page', {\n params: {\n query: {\n ...pageParams(params),\n Name: params.name,\n Status: params.status,\n HandlerKind: params.handlerKind,\n SortField: params.sortField,\n SortOrder: params.sortOrder,\n },\n },\n })\n .then(r => toPage<SysJob>(r)),\n add: (body: JobInput) => client.POST('/api/v1/sys/job', { body }).then(r => unwrap<number>(r)),\n update: (id: number, body: JobInput) =>\n client\n .PUT('/api/v1/sys/job/{id}', { params: { path: { id } }, body })\n .then(r => unwrap<boolean>(r)),\n remove: (id: number) =>\n client\n .DELETE('/api/v1/sys/job/{id}', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** 批量删除(命中内置任务后端整批拒绝 47014)。 */\n batchRemove: (ids: number[]) =>\n client.POST('/api/v1/sys/job/batch-delete', { body: { ids } }).then(r => unwrap<boolean>(r)),\n /** 专用启停端点:true=恢复调度并重算下次执行时刻(顺带清连败计数),false=暂停。 */\n setEnabled: (id: number, enabled: boolean) =>\n client\n .PUT('/api/v1/sys/job/{id}/enabled', { params: { path: { id }, query: { enabled } } })\n .then(r => unwrap<boolean>(r)),\n /** 执行一次(收到请求的副本本机执行,不经选主、不影响调度节奏)。 */\n run: (id: number) =>\n client\n .POST('/api/v1/sys/job/{id}/run', { params: { path: { id } } })\n .then(r => unwrap<boolean>(r)),\n /** cron 预览([ActiveSession] 任何登录用户可用;POST 因 cron 含 `? #` 走 query 有转义坑)。 */\n previewCron: (body: { cron: string; count?: number; from?: string | null }) =>\n client.POST('/api/v1/sys/job/preview-cron', { body }).then(r => unwrap<CronPreviewOutput>(r)),\n /** 已注册的编译处理器清单(表单下拉数据源,免手打 HandlerName)。 */\n handlers: () =>\n client.GET('/api/v1/sys/job/handlers', {}).then(r => unwrap<JobHandlersOutput>(r)),\n /**\n * 执行记录分页。startRange 是 SmartTable daterange 的 [开始, 结束] 日期串,\n * 拆成后端 StartFrom/StartTo,结束日补 23:59:59(同 splitRange 的理由,但参数名不同,不复用)。\n */\n logPage: (params: {\n page: number\n pageSize: number\n jobId?: number\n runStatus?: number\n startRange?: [string, string] | null\n fireInstanceId?: number\n }) =>\n client\n .GET('/api/v1/sys/job/log/page', {\n params: {\n query: {\n ...pageParams(params),\n JobId: params.jobId,\n RunStatus: params.runStatus,\n FireInstanceId: params.fireInstanceId,\n StartFrom: params.startRange?.[0] || undefined,\n StartTo: params.startRange?.[1] ? `${params.startRange[1]} 23:59:59` : undefined,\n },\n },\n })\n .then(r => toPage<SysJobLog>(r)),\n /** 终止一次执行(跨节点写终止旗标,目标节点最迟 KillPollSeconds 后停)。 */\n kill: (logId: number) =>\n client\n .POST('/api/v1/sys/job/log/{id}/kill', { params: { path: { id: logId } } })\n .then(r => unwrap<boolean>(r)),\n /** 清空执行记录(硬删;运行中的一律保留),返回删除行数。 */\n logClear: (body: { beforeDays?: number | null; jobId?: number | null }) =>\n client.POST('/api/v1/sys/job/log/clear', { body }).then(r => unwrap<number>(r)),\n /** 监控仪表盘(今日成败/在飞/趋势/即将执行/集群节点)。 */\n dashboard: () => client.GET('/api/v1/sys/job/dashboard', {}).then(r => unwrap<JobDashboard>(r)),\n}\n\n// ── 回收站 ────────────────────────────────────────────────────────\n\nexport interface RecycleBinItem {\n id: number\n name: string\n code: string | null\n deletedAt: string | null\n deletedBy: number | null\n}\n\nexport const recycleApi = {\n page: (type: string) => (params: { page: number; pageSize: number }) =>\n client\n .GET('/api/v1/sys/recycle/{type}/page', {\n params: { path: { type }, query: pageParams(params) },\n })\n .then(r => toPage<RecycleBinItem>(r)),\n restore: (type: string, id: number) =>\n client\n .POST('/api/v1/sys/recycle/{type}/{id}/restore', { params: { path: { type, id } } })\n .then(r => unwrap<boolean>(r)),\n purge: (type: string, id: number) =>\n client\n .DELETE('/api/v1/sys/recycle/{type}/{id}', { params: { path: { type, id } } })\n .then(r => unwrap<boolean>(r)),\n}\n"],"names":["ApiError","code","msgKey","args","message","__publicField","unwrap","res","data","error","response","env","pd","callApi","method","url","body","request","client","r","pageParams","p","listQuery","dayRange","range","toPage","unwrapDownload","blob","ct","normalizePreview","raw","c","normalizeRow","e","normalizeCommit","toWireRows","rows","cells","k","v","authApi","mfaApi","highSensApi","id","externalAuthApi","runtime","ticket","pendingLink","dashboardApi","personalApi","moduleId","sessionId","userApi","params","ids","newPassword","enabled","file","mapping","LONG_TIMEOUT_MS","b","fd","strategy","orgApi","positionApi","roleApi","roleId","menuIds","scopeType","customOrgIds","userIds","moduleApi","configApi","group","all","current","page","items","splitRange","start","end","logApi","monitorApi","cacheApi","dictApi","typeCode","list","dictAdminApi","fileApi","uploadId","index","chunk","sessionApi","noticeApi","menuApi","jobApi","_a","_b","logId","recycleApi","type"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import o from "./index2.vue.js";
2
2
  /* empty css */
3
3
  import t from "../../_virtual/_plugin-vue_export-helper.js";
4
- const p = /* @__PURE__ */ t(o, [["__scopeId", "data-v-e99908b8"]]);
4
+ const p = /* @__PURE__ */ t(o, [["__scopeId", "data-v-6733c96a"]]);
5
5
  export {
6
6
  p as default
7
7
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index2.vue.js","sources":["../../../src/components/DetailPage/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 详情页外壳:返回按钮 + 标题 + actions 插槽 + body 插槽。\n// 补偿非菜单详情路由的空面包屑(菜单树里没这条路由 → 头部面包屑为空,故详情页自带标题/返回)。\n// @back 交父级决定语义:路由态 = 关标签回列表(见 views/system/user/detail.vue);就地态 = 清列表页的详情状态。\nimport { NButton, NSpin } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport AppIcon from '#/components/AppIcon.vue'\n\nwithDefaults(defineProps<{ title?: string; loading?: boolean; showBack?: boolean }>(), {\n showBack: true,\n})\ndefineEmits<{ back: [] }>()\nconst { t } = useI18n()\n</script>\n\n<template>\n <div class=\"detail-page\">\n <div class=\"detail-header\">\n <n-button\n v-if=\"showBack\"\n quaternary\n size=\"small\"\n :aria-label=\"t('common.back')\"\n @click=\"$emit('back')\"\n >\n <template #icon><AppIcon icon=\"ph:arrow-left\" :size=\"18\" /></template>\n </n-button>\n <h2 class=\"detail-title\">{{ title }}</h2>\n <div class=\"detail-actions\"><slot name=\"actions\" /></div>\n </div>\n <n-spin :show=\"loading\">\n <div class=\"detail-body\"><slot /></div>\n </n-spin>\n </div>\n</template>\n\n<style scoped>\n.detail-page {\n display: flex;\n flex-direction: column;\n gap: var(--gap-card, 16px);\n}\n.detail-header {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.detail-title {\n margin: 0;\n font-size: var(--font-size-lg, 18px);\n font-weight: 600;\n color: var(--color-text-primary);\n}\n.detail-actions {\n margin-left: auto;\n}\n</style>\n"],"names":["t","useI18n","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","__props","_createBlock","_unref","NButton","$emit","_createVNode","AppIcon","_hoisted_3","_toDisplayString","_hoisted_4","_renderSlot","_ctx","NSpin","_hoisted_5"],"mappings":";;;;;;;;;;;;;AAYA,UAAM,EAAE,GAAAA,EAAA,IAAMC,EAAA;sBAIZC,EAAA,GAAAC,EAiBM,OAjBNC,GAiBM;AAAA,MAhBJC,EAYM,OAZNC,GAYM;AAAA,QAVIC,EAAA,iBADRC,EAQWC,EAAAC,CAAA,GAAA;AAAA;UANT,YAAA;AAAA,UACA,MAAK;AAAA,UACJ,cAAYD,EAAAT,CAAA,EAAC,aAAA;AAAA,UACb,gCAAOW,EAAAA,MAAK,MAAA;AAAA,QAAA;UAEF,QAAK,MAA2C;AAAA,YAA3CC,EAA2CC,GAAA;AAAA,cAAlC,MAAK;AAAA,cAAiB,MAAM;AAAA,YAAA;;;;QAEvDR,EAAyC,MAAzCS,GAAyCC,EAAbR,EAAA,KAAK,GAAA,CAAA;AAAA,QACjCF,EAAyD,OAAzDW,GAAyD;AAAA,UAA7BC,EAAuBC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,QAAA;;MAErDN,EAESH,EAAAU,CAAA,GAAA,EAFA,MAAMZ,EAAA,WAAO;AAAA,mBACpB,MAAuC;AAAA,UAAvCF,EAAuC,OAAvCe,GAAuC;AAAA,YAAdH,EAAQC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,UAAA;;;;;;;"}
1
+ {"version":3,"file":"index2.vue.js","sources":["../../../src/components/DetailPage/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 详情页外壳:返回按钮 + 标题 + actions 插槽 + body 插槽。\n// 补偿非菜单详情路由的空面包屑(菜单树里没这条路由 → 头部面包屑为空,故详情页自带标题/返回)。\n// @back 交父级决定语义:路由态 = 关标签回列表;就地态 = 清列表页的详情状态(骨架见 skills/create-page-variant/detail.md)。\nimport { NButton, NSpin } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport AppIcon from '#/components/AppIcon.vue'\n\nwithDefaults(defineProps<{ title?: string; loading?: boolean; showBack?: boolean }>(), {\n showBack: true,\n})\ndefineEmits<{ back: [] }>()\nconst { t } = useI18n()\n</script>\n\n<template>\n <div class=\"detail-page\">\n <div class=\"detail-header\">\n <n-button\n v-if=\"showBack\"\n quaternary\n size=\"small\"\n :aria-label=\"t('common.back')\"\n @click=\"$emit('back')\"\n >\n <template #icon><AppIcon icon=\"ph:arrow-left\" :size=\"18\" /></template>\n </n-button>\n <h2 class=\"detail-title\">{{ title }}</h2>\n <div class=\"detail-actions\"><slot name=\"actions\" /></div>\n </div>\n <n-spin :show=\"loading\">\n <div class=\"detail-body\"><slot /></div>\n </n-spin>\n </div>\n</template>\n\n<style scoped>\n.detail-page {\n display: flex;\n flex-direction: column;\n gap: var(--gap-card, 16px);\n}\n.detail-header {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.detail-title {\n margin: 0;\n font-size: var(--font-size-lg, 18px);\n font-weight: 600;\n color: var(--color-text-primary);\n}\n.detail-actions {\n margin-left: auto;\n}\n</style>\n"],"names":["t","useI18n","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","__props","_createBlock","_unref","NButton","$emit","_createVNode","AppIcon","_hoisted_3","_toDisplayString","_hoisted_4","_renderSlot","_ctx","NSpin","_hoisted_5"],"mappings":";;;;;;;;;;;;;AAYA,UAAM,EAAE,GAAAA,EAAA,IAAMC,EAAA;sBAIZC,EAAA,GAAAC,EAiBM,OAjBNC,GAiBM;AAAA,MAhBJC,EAYM,OAZNC,GAYM;AAAA,QAVIC,EAAA,iBADRC,EAQWC,EAAAC,CAAA,GAAA;AAAA;UANT,YAAA;AAAA,UACA,MAAK;AAAA,UACJ,cAAYD,EAAAT,CAAA,EAAC,aAAA;AAAA,UACb,gCAAOW,EAAAA,MAAK,MAAA;AAAA,QAAA;UAEF,QAAK,MAA2C;AAAA,YAA3CC,EAA2CC,GAAA;AAAA,cAAlC,MAAK;AAAA,cAAiB,MAAM;AAAA,YAAA;;;;QAEvDR,EAAyC,MAAzCS,GAAyCC,EAAbR,EAAA,KAAK,GAAA,CAAA;AAAA,QACjCF,EAAyD,OAAzDW,GAAyD;AAAA,UAA7BC,EAAuBC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,QAAA;;MAErDN,EAESH,EAAAU,CAAA,GAAA,EAFA,MAAMZ,EAAA,WAAO;AAAA,mBACpB,MAAuC;AAAA,UAAvCF,EAAuC,OAAvCe,GAAuC;AAAA,YAAdH,EAAQC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,UAAA;;;;;;;"}