smart-admin-web 10.20.1 → 10.22.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 (165) hide show
  1. package/dist/api/index.d.ts +19 -1
  2. package/dist/api/index.js +85 -66
  3. package/dist/api/index.js.map +1 -1
  4. package/dist/api/schema.d.ts +448 -1
  5. package/dist/assets/icons/ph-subset.json.js +1 -1
  6. package/dist/components/FormContainer/index.vue.js +87 -75
  7. package/dist/components/FormContainer/index.vue.js.map +1 -1
  8. package/dist/components/UserPicker/UserAvatar.vue.d.ts +8 -0
  9. package/dist/components/UserPicker/UserAvatar.vue.js +8 -0
  10. package/dist/components/UserPicker/UserAvatar.vue.js.map +1 -0
  11. package/dist/components/UserPicker/UserAvatar2.vue.js +38 -0
  12. package/dist/components/UserPicker/UserAvatar2.vue.js.map +1 -0
  13. package/dist/components/UserPicker/index.vue.js +1 -1
  14. package/dist/components/UserPicker/index2.vue.js +328 -186
  15. package/dist/components/UserPicker/index2.vue.js.map +1 -1
  16. package/dist/composables/authMenuRoute.d.ts +10 -0
  17. package/dist/composables/authMenuRoute.js +39 -23
  18. package/dist/composables/authMenuRoute.js.map +1 -1
  19. package/dist/composables/useModule.d.ts +3 -1
  20. package/dist/composables/useModule.js +44 -32
  21. package/dist/composables/useModule.js.map +1 -1
  22. package/dist/index.js +246 -242
  23. package/dist/layouts/components/SideNav.vue.js +2 -2
  24. package/dist/layouts/components/SideNav2.vue.js.map +1 -1
  25. package/dist/lib/runtime.js +1 -1
  26. package/dist/lib/watermark.d.ts +1 -1
  27. package/dist/locales/en-US.d.ts +68 -3
  28. package/dist/locales/en-US.js +74 -8
  29. package/dist/locales/en-US.js.map +1 -1
  30. package/dist/locales/kernelMenuTitles.js +1 -0
  31. package/dist/locales/kernelMenuTitles.js.map +1 -1
  32. package/dist/locales/zh-CN.d.ts +68 -3
  33. package/dist/locales/zh-CN.js +74 -8
  34. package/dist/locales/zh-CN.js.map +1 -1
  35. package/dist/router/viewRegistry.js +6 -6
  36. package/dist/router/viewRegistry.js.map +1 -1
  37. package/dist/style.css +1 -1
  38. package/dist/theme/naive-theme.js +80 -77
  39. package/dist/theme/naive-theme.js.map +1 -1
  40. package/dist/types/api.d.ts +91 -0
  41. package/dist/types/api.js +17 -15
  42. package/dist/types/api.js.map +1 -1
  43. package/dist/utils/shake.d.ts +1 -0
  44. package/dist/utils/shake.js +30 -0
  45. package/dist/utils/shake.js.map +1 -0
  46. package/dist/utils/tree.d.ts +15 -0
  47. package/dist/utils/tree.js +43 -29
  48. package/dist/utils/tree.js.map +1 -1
  49. package/dist/utils/treeCard.d.ts +6 -0
  50. package/dist/utils/treeCard.js +9 -0
  51. package/dist/utils/treeCard.js.map +1 -0
  52. package/dist/views/error/404.vue.js +2 -2
  53. package/dist/views/error/4042.vue.js +81 -24
  54. package/dist/views/error/4042.vue.js.map +1 -1
  55. package/dist/views/login/LoginForm.vue.js +2 -2
  56. package/dist/views/login/LoginForm2.vue.js +135 -135
  57. package/dist/views/login/LoginForm2.vue.js.map +1 -1
  58. package/dist/views/login/components/LoginDesk.vue.js +2 -2
  59. package/dist/views/login/components/LoginDesk2.vue.js +59 -47
  60. package/dist/views/login/components/LoginDesk2.vue.js.map +1 -1
  61. package/dist/views/login/components/LoginHeroPanel.vue.js +2 -2
  62. package/dist/views/login/components/LoginHeroPanel2.vue.js.map +1 -1
  63. package/dist/views/personal/notice2.vue.js +1 -1
  64. package/dist/views/personal/notice2.vue.js.map +1 -1
  65. package/dist/views/personal/sessions.vue.js +2 -2
  66. package/dist/views/personal/sessions2.vue.js +41 -40
  67. package/dist/views/personal/sessions2.vue.js.map +1 -1
  68. package/dist/views/system/ai-usage/index.vue.js +3 -3
  69. package/dist/views/system/ai-usage/index2.vue.js +13 -12
  70. package/dist/views/system/ai-usage/index2.vue.js.map +1 -1
  71. package/dist/views/system/config/components/AdvancedSection.vue.js +3 -3
  72. package/dist/views/system/config/components/AdvancedSection2.vue.js +2 -1
  73. package/dist/views/system/config/components/AdvancedSection2.vue.js.map +1 -1
  74. package/dist/views/system/dict/index.vue.js +2 -2
  75. package/dist/views/system/dict/index2.vue.js +12 -1
  76. package/dist/views/system/dict/index2.vue.js.map +1 -1
  77. package/dist/views/system/file/index2.vue.js +1 -0
  78. package/dist/views/system/file/index2.vue.js.map +1 -1
  79. package/dist/views/system/job/index.vue.js +3 -3
  80. package/dist/views/system/job/index2.vue.js +182 -181
  81. package/dist/views/system/job/index2.vue.js.map +1 -1
  82. package/dist/views/system/job-log/components/AttemptTable2.vue.js +8 -3
  83. package/dist/views/system/job-log/components/AttemptTable2.vue.js.map +1 -1
  84. package/dist/views/system/job-log/index.vue.js +1 -1
  85. package/dist/views/system/job-log/index2.vue.js +5 -5
  86. package/dist/views/system/job-log/index2.vue.js.map +1 -1
  87. package/dist/views/system/job-monitor/index.vue.js +2 -2
  88. package/dist/views/system/job-monitor/index2.vue.js +46 -46
  89. package/dist/views/system/job-monitor/index2.vue.js.map +1 -1
  90. package/dist/views/system/log/exception/index.vue.js +2 -2
  91. package/dist/views/system/log/exception/index2.vue.js +8 -5
  92. package/dist/views/system/log/exception/index2.vue.js.map +1 -1
  93. package/dist/views/system/log/login/index2.vue.js +21 -12
  94. package/dist/views/system/log/login/index2.vue.js.map +1 -1
  95. package/dist/views/system/log/op/index.vue.js +2 -2
  96. package/dist/views/system/log/op/index2.vue.js +50 -40
  97. package/dist/views/system/log/op/index2.vue.js.map +1 -1
  98. package/dist/views/system/menu/components/ButtonManager.vue.js +2 -2
  99. package/dist/views/system/menu/components/ButtonManager2.vue.js +45 -36
  100. package/dist/views/system/menu/components/ButtonManager2.vue.js.map +1 -1
  101. package/dist/views/system/menu/index.vue.js +1 -1
  102. package/dist/views/system/menu/index2.vue.js +162 -151
  103. package/dist/views/system/menu/index2.vue.js.map +1 -1
  104. package/dist/views/system/module/index.vue.js +1 -1
  105. package/dist/views/system/module/index2.vue.js +171 -117
  106. package/dist/views/system/module/index2.vue.js.map +1 -1
  107. package/dist/views/system/notice/index.vue.js +3 -3
  108. package/dist/views/system/notice/index2.vue.js +1 -0
  109. package/dist/views/system/notice/index2.vue.js.map +1 -1
  110. package/dist/views/system/org/index.vue.js +2 -2
  111. package/dist/views/system/org/index2.vue.js +204 -195
  112. package/dist/views/system/org/index2.vue.js.map +1 -1
  113. package/dist/views/system/position/index.vue.js +2 -2
  114. package/dist/views/system/position/index2.vue.js +57 -48
  115. package/dist/views/system/position/index2.vue.js.map +1 -1
  116. package/dist/views/system/recycle/index.vue.js +1 -1
  117. package/dist/views/system/recycle/index2.vue.js +3 -1
  118. package/dist/views/system/recycle/index2.vue.js.map +1 -1
  119. package/dist/views/system/role/components/GrantMenuSheet.vue.d.ts +2 -0
  120. package/dist/views/system/role/components/GrantMenuSheet.vue.js +2 -2
  121. package/dist/views/system/role/components/GrantMenuSheet2.vue.js +54 -49
  122. package/dist/views/system/role/components/GrantMenuSheet2.vue.js.map +1 -1
  123. package/dist/views/system/role/components/GrantMenuTable.vue.js +1 -1
  124. package/dist/views/system/role/components/GrantMenuTable2.vue.js +159 -195
  125. package/dist/views/system/role/components/GrantMenuTable2.vue.js.map +1 -1
  126. package/dist/views/system/role/components/grantMenuGroups.d.ts +54 -0
  127. package/dist/views/system/role/components/grantMenuGroups.js +116 -76
  128. package/dist/views/system/role/components/grantMenuGroups.js.map +1 -1
  129. package/dist/views/system/role/index.vue.js +2 -2
  130. package/dist/views/system/role/index2.vue.js +152 -145
  131. package/dist/views/system/role/index2.vue.js.map +1 -1
  132. package/dist/views/system/session/index2.vue.js +39 -35
  133. package/dist/views/system/session/index2.vue.js.map +1 -1
  134. package/dist/views/system/user/components/UserGrantEffectiveTable.vue.d.ts +10 -0
  135. package/dist/views/system/user/components/UserGrantEffectiveTable.vue.js +5 -0
  136. package/dist/views/system/user/components/UserGrantEffectiveTable.vue.js.map +1 -0
  137. package/dist/views/system/user/components/UserGrantEffectiveTable2.vue.js +96 -0
  138. package/dist/views/system/user/components/UserGrantEffectiveTable2.vue.js.map +1 -0
  139. package/dist/views/system/user/components/UserGrantMenuSheet.vue.d.ts +13 -0
  140. package/dist/views/system/user/components/UserGrantMenuSheet.vue.js +8 -0
  141. package/dist/views/system/user/components/UserGrantMenuSheet.vue.js.map +1 -0
  142. package/dist/views/system/user/components/UserGrantMenuSheet2.vue.js +216 -0
  143. package/dist/views/system/user/components/UserGrantMenuSheet2.vue.js.map +1 -0
  144. package/dist/views/system/user/components/UserGrantMenuTable.vue.d.ts +13 -0
  145. package/dist/views/system/user/components/UserGrantMenuTable.vue.js +8 -0
  146. package/dist/views/system/user/components/UserGrantMenuTable.vue.js.map +1 -0
  147. package/dist/views/system/user/components/UserGrantMenuTable2.vue.js +186 -0
  148. package/dist/views/system/user/components/UserGrantMenuTable2.vue.js.map +1 -0
  149. package/dist/views/system/user/components/UserGrantNodeRow.vue.d.ts +31 -0
  150. package/dist/views/system/user/components/UserGrantNodeRow.vue.js +8 -0
  151. package/dist/views/system/user/components/UserGrantNodeRow.vue.js.map +1 -0
  152. package/dist/views/system/user/components/UserGrantNodeRow2.vue.js +171 -0
  153. package/dist/views/system/user/components/UserGrantNodeRow2.vue.js.map +1 -0
  154. package/dist/views/system/user/components/UserGrantOverviewDrawer.vue.d.ts +21 -0
  155. package/dist/views/system/user/components/UserGrantOverviewDrawer.vue.js +5 -0
  156. package/dist/views/system/user/components/UserGrantOverviewDrawer.vue.js.map +1 -0
  157. package/dist/views/system/user/components/UserGrantOverviewDrawer2.vue.js +178 -0
  158. package/dist/views/system/user/components/UserGrantOverviewDrawer2.vue.js.map +1 -0
  159. package/dist/views/system/user/components/userGrantState.d.ts +64 -0
  160. package/dist/views/system/user/components/userGrantState.js +117 -0
  161. package/dist/views/system/user/components/userGrantState.js.map +1 -0
  162. package/dist/views/system/user/index.vue.js +2 -2
  163. package/dist/views/system/user/index2.vue.js +369 -295
  164. package/dist/views/system/user/index2.vue.js.map +1 -1
  165. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sources":["../../src/types/api.ts"],"sourcesContent":["// 接口出参领域类型(与后端 DTO 对齐)。API 层用它标注 unwrap<T> 的返回,视图直接消费。\nimport type { AppModule } from './menu'\n\n/** 登录/刷新出参(后端 LoginOutput)。 */\nexport interface LoginOutput {\n accessToken: string\n expiresAt: string\n refreshToken: string\n refreshExpiresAt: string\n userId: number\n account: string\n name: string\n /** 是否需强制改密(管理员建号/重置后首登为 true)。 */\n mustChangePassword: boolean\n /**\n * 会话交付模式(可选)。\n * - `body`:刷新令牌在 JSON 体(默认,前端 localStorage 持久化)\n * - `cookie`:刷新令牌在 HttpOnly Cookie,access 仅内存\n * 缺省时前端用 refreshToken 空串 + csrfRequired 兜底判定(见 stores/user.ts 的 isCookieSession)。\n */\n sessionMode?: 'body' | 'cookie' | string | null\n /**\n * 是否要求双提交 CSRF(`X-Smart-CSRF` + `smart_csrf` Cookie)。\n * Cookie 会话为 true;默认模式为 false/缺省。\n */\n csrfRequired?: boolean | null\n /** 是否超管;前端据此在 profile 接口故障时仍能正确 fail-open v-auth。 */\n isSuperAdmin?: boolean\n}\n\n/** 我的应用列表(后端 MyModulesOutput)。 */\nexport interface MyModulesOutput {\n modules: AppModule[]\n defaultModuleId?: number | null\n}\n\n/** 个人资料(后端 UserProfile)。 */\nexport interface UserProfile {\n id: number\n account: string\n name: string\n orgId?: number | null\n positionId?: number | null\n /** 机构名称(未分配/已删则 null) */\n orgName?: string | null\n /** 职位名称(未分配/已删则 null) */\n positionName?: string | null\n nickname?: string | null\n phone?: string | null\n email?: string | null\n /** 性别:字典 gender 的项 Value(\"1\"男/\"2\"女/\"0\"未知) */\n gender?: string | null\n /** 头像(文件签名直链 ViewUrl,直接进 img) */\n avatar?: string | null\n isSuperAdmin: boolean\n}\n\n/** 我的会话项(后端 MySessionItem;个人视角,isCurrent 标记本次请求所用会话)。 */\nexport interface MySessionItem {\n sessionId: string\n ip?: string | null\n userAgent?: string | null\n loginTime: string\n expiresAt: string\n isCurrent: boolean\n}\n\n/** 上一次成功登录的信息(后端 LastLoginOutput;排除本次,首次登录时接口整体返回 null)。 */\nexport interface LastLoginInfo {\n time: string\n ip?: string | null\n userAgent?: string | null\n}\n\n/** 工作台待办单条(后端 WorkbenchTodoItem)。 */\nexport interface WorkbenchTodoItem {\n id: number\n title: string\n description?: string | null\n url?: string | null\n createTime: string\n}\n\n/** 工作台待办摘要(后端 WorkbenchTodoSummary;内核默认恒空)。 */\nexport interface WorkbenchTodoSummary {\n totalCount: number\n items: WorkbenchTodoItem[]\n}\n\n/** 工作台快捷方式项(后端 UserShortcutItem;后端已按\"置顶优先+高频补位\"排好序)。 */\nexport interface UserShortcutItem {\n menuPath: string\n pinned: boolean\n title: string\n icon?: string | null\n}\n\n/** 后端统一分页结果 PagedList<T>。 */\nexport interface PagedList<T> {\n current: number\n size: number\n total: number\n pages: number\n items: T[]\n}\n\n/** 用户列表项(后端 UserItem;刻意不含密码)。 */\nexport interface UserItem {\n id: number\n account: string\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n orgId?: number | null\n positionId?: number | null\n directorId?: number | null\n orgName?: string | null\n positionName?: string | null\n directorName?: string | null\n enabled: boolean\n isSuperAdmin: boolean\n /** 管理员显式强制 TOTP(只能加严)。 */\n forceTotp?: boolean\n /** 是否已绑定 TOTP(只读)。 */\n totpEnabled?: boolean\n createTime: string\n}\n\n/** 模块/应用管理行(后端 SysModule;列表全字段)。 */\nexport interface ModuleRow {\n id: number\n code: string\n title: string\n icon?: string | null\n defaultRoute?: string | null\n /** 后端路由匹配前缀(如 sys/biz):菜单配按钮时权限路由下拉据此按应用软过滤;留空=不过滤。 */\n apiPrefix?: string | null\n sort: number\n enabled: boolean\n remark?: string | null\n createTime?: string\n}\n\n/** 工作台首页统计(后端 DashboardSummaryOutput)。趋势三条数组等长(近 7 日,含今天,无登录的日子为 0)。 */\nexport interface DashboardSummary {\n roles: number\n users: number\n perms: number\n onlineSessions: number\n trendDays: string[]\n trendLogins: number[]\n trendActiveUsers: number[]\n}\n\n/** 字典项消费投影(后端 SysDictItem;sort 归一为 number,甩掉 int64 序列化的 number|string 噪音)。 */\nexport interface DictItem {\n label: string\n value: string\n sort: number\n enabled: boolean\n}\n\n/** 模块新增/编辑入参(后端 ModuleInput)。 */\nexport interface ModuleInput {\n code: string\n title: string\n icon?: string | null\n defaultRoute?: string | null\n apiPrefix?: string | null\n sort: number\n enabled: boolean\n remark?: string | null\n}\n\n/** 系统配置行(后端 SysConfig;列表返回全字段,int64 收敛为 number)。 */\nexport interface SysConfig {\n id: number\n configKey: string\n configValue?: string | null\n name: string\n groupCode?: string | null\n sort: number\n remark?: string | null\n createTime?: string\n}\n\n/** 配置新增/编辑入参(后端 ConfigInput;configKey 创建后不可改)。 */\nexport interface ConfigInput {\n configKey: string\n configValue?: string | null\n name: string\n groupCode?: string | null\n sort: number\n remark?: string | null\n}\n\n/** 字典类型行(后端 SysDictType;Code 创建后不可改)。int64 收敛为 number。 */\nexport interface SysDictType {\n id: number\n code: string\n name: string\n sort: number\n enabled: boolean\n remark?: string | null\n createTime?: string\n}\n\n/** 字典项行(后端 SysDictItem;管理端分页含停用项,带 id——区别于下拉投影 DictItem)。int64 收敛为 number。 */\nexport interface SysDictItem {\n id: number\n dictTypeCode: string\n label: string\n value: string\n sort: number\n enabled: boolean\n createTime?: string\n}\n\n/** 字典类型新增/编辑入参(后端 DictTypeInput;code 创建后不可改,更新时服务端忽略)。 */\nexport interface DictTypeInput {\n code: string\n name: string\n sort: number\n enabled: boolean\n remark?: string | null\n}\n\n/** 字典项新增/编辑入参(后端 DictItemInput;dictTypeCode = 当前类型,表单隐藏)。 */\nexport interface DictItemInput {\n dictTypeCode: string\n label: string\n value: string\n sort: number\n enabled: boolean\n}\n\n/** 文件记录行(后端 SysFile;列表返回,int64 收敛为 number)。 */\nexport interface SysFile {\n id: number\n originalName: string\n storagePath: string\n extension: string\n contentType?: string | null\n sizeBytes: number\n fileHash?: string | null\n createTime?: string\n}\n\n/** 上传出参(后端 FileUploadOutput)。 */\nexport interface FileUploadOutput {\n id: number\n originalName: string\n /** 存储层相对路径。**别当 URL 用**:后端默认不静态托管上传目录,当 src 必然坏链。要展示图片用 viewUrl。 */\n storagePath: string\n sizeBytes: number\n fileHash?: string | null\n /** 签名直链(匿名可取、不可伪造),可直接塞进 `<img src>`;后端签发,前端不自己拼。 */\n viewUrl?: string | null\n}\n\n/** 分片上传初始化出参(后端 ChunkInitOutput)。 */\nexport interface ChunkInitOutput {\n /** 秒传命中(同内容哈希已存在,无需再传)。 */\n uploaded: boolean\n /** 秒传命中时的既有文件。 */\n file?: FileUploadOutput | null\n /** 上传会话 Id(= 文件哈希);非秒传时返回。 */\n uploadId?: string | null\n /** 服务端已收到的分片下标(断点续传:跳过已传)。 */\n receivedIndexes: number[]\n}\n\n/** 在线会话行(后端 OnlineSessionItem;只读 + 强退按 sessionId)。int64 收敛为 number。 */\nexport interface OnlineSessionItem {\n sessionId: string\n userId: number\n account: string\n ip?: string | null\n userAgent?: string | null\n loginTime?: string\n expiresAt?: string\n}\n\n/** 登录日志行(后端 SysLoginLog;只读,int64 收敛为 number)。 */\nexport interface SysLoginLog {\n id: number\n account: string\n success: boolean\n resultCode: number\n userId?: number | null\n name?: string | null\n ip?: string | null\n userAgent?: string | null\n createTime: string\n}\n\n/** 操作日志行(后端 SysOpLog;只读,分页项已含全字段,详情抽屉直接用行数据)。 */\nexport interface SysOpLog {\n id: number\n title: string\n httpMethod: string\n path: string\n paramJson?: string | null\n resultCode: number\n success: boolean\n exceptionMessage?: string | null\n elapsedMs: number\n operatorId?: number | null\n operatorName?: string | null\n ip?: string | null\n userAgent?: string | null\n createTime: string\n}\n\n/** 磁盘分区容量(后端 DiskInfo)。 */\nexport interface DiskInfo {\n name: string\n totalBytes: number\n freeBytes: number\n}\n\n/** 服务器运行快照(后端 ServerInfoOutput;进程/主机基础指标)。 */\nexport interface ServerInfoOutput {\n machineName: string\n osDescription: string\n frameworkDescription: string\n processArchitecture: string\n processorCount: number\n processUptimeSeconds: number\n processCpuPercent: number\n processWorkingSetBytes: number\n gcHeapBytes: number\n totalAvailableMemoryBytes: number\n threadCount: number\n disks: DiskInfo[]\n}\n\n/** 异常日志行(后端 SysExceptionLog;未捕获异常留痕,只读,分页项已含全字段)。 */\nexport interface SysExceptionLog {\n id: number\n httpMethod: string\n path: string\n traceId?: string | null\n exceptionType: string\n message?: string | null\n stackTrace?: string | null\n operatorId?: number | null\n operatorName?: string | null\n ip?: string | null\n userAgent?: string | null\n createTime: string\n}\n\n/** 机构行(后端 SysOrg;平铺,前端 buildTree)。int64 收敛为 number。 */\nexport interface SysOrg {\n id: number\n parentId: number\n name: string\n code: string\n category?: string | null\n sort: number\n enabled: boolean\n createTime?: string\n}\n\n/** 机构新增/编辑入参(后端 OrgInput;parentId 0=根,code 编辑禁用)。 */\nexport interface OrgInput {\n parentId: number\n name: string\n code: string\n category?: string | null\n sort: number\n enabled: boolean\n}\n\n/** 职位行(后端 SysPosition)。int64 收敛为 number。 */\nexport interface SysPosition {\n id: number\n name: string\n code: string\n sort: number\n enabled: boolean\n createTime?: string\n}\n\n/** 职位新增/编辑入参(后端 PositionInput;增改同一份字段,code 编辑禁用)。 */\nexport interface PositionInput {\n name: string\n code: string\n sort: number\n enabled: boolean\n}\n\n/** 角色行(后端 SysRole)。int64 收敛为 number。 */\nexport interface SysRole {\n id: number\n name: string\n code: string\n sort: number\n enabled: boolean\n remark?: string | null\n isDelegatable?: boolean | null\n createTime?: string\n}\n\n/** 角色新增/编辑入参(后端 RoleInput;增改同一份字段,code 编辑禁用)。 */\nexport interface RoleInput {\n name: string\n code: string\n sort: number\n enabled: boolean\n remark?: string | null\n isDelegatable?: boolean | null\n}\n\n/** 数据范围类型(后端 DataScopeType;存库为 int,枚举值须与后端一致)。 */\nexport enum DataScopeType {\n All = 1,\n Org = 2,\n OrgAndChildren = 3,\n Self = 4,\n Custom = 5,\n}\n\n/** 角色数据范围配置(后端 SysRoleDataScope;数据范围抽屉回显)。customOrgIds 逗号分隔。 */\nexport interface SysRoleDataScope {\n id: number\n roleId: number\n scopeType: DataScopeType\n customOrgIds: string\n}\n\n/** 新增用户入参(后端 AddUserInput;account 建后不可改,password 留空=系统生成随机强口令)。 */\nexport interface AddUserInput {\n account: string\n password?: string | null\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n orgId?: number | null\n positionId?: number | null\n directorId?: number | null\n enabled: boolean\n /** 建号即强制 TOTP。 */\n forceTotp?: boolean\n roleIds: number[]\n}\n\n/** 新增用户出参(后端 AddUserOutput):新 Id + 实际生效的初始口令明文——留空口令时是随机生成的,不展示给管理员就没人知道。 */\nexport interface AddUserOutput {\n id: number\n initialPassword: string\n}\n\n/** 一条可授权路由(后端 PermissionRouteItem);喂菜单表单权限码下拉,code 即写进 SysMenu.Permission 的值。 */\nexport interface PermissionRouteItem {\n code: string\n method: string\n path: string\n}\n\n/** 更新用户入参(后端 UpdateUserInput;无 account/password。roleIds 由 detail 原样带回避免清空)。 */\nexport interface UpdateUserInput {\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n orgId?: number | null\n positionId?: number | null\n directorId?: number | null\n enabled: boolean\n forceTotp?: boolean\n roleIds: number[]\n}\n\n/** 用户详情(后端 UserDetail;列表字段 + roleIds,编辑回显用)。 */\nexport interface UserDetail {\n id: number\n account: string\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n orgId?: number | null\n positionId?: number | null\n directorId?: number | null\n enabled: boolean\n isSuperAdmin: boolean\n forceTotp?: boolean\n totpEnabled?: boolean\n roleIds: number[]\n createTime?: string\n}\n\n/** 通知类型(后端 NoticeType;存库 int,枚举值须与后端一致)。 */\nexport enum NoticeType {\n Notice = 1,\n Announcement = 2,\n Message = 3,\n}\n\n/** 接收范围(后端 ReceiverType;All=0 对全体广播,Role/User 定向)。 */\nexport enum ReceiverType {\n All = 0,\n Role = 1,\n User = 2,\n}\n\n/**\n * 通知动作(后端 NoticeAction):前端渲染成正文下的按钮。url 以 /api/ 开头是接口调用(按 method 发请求),\n * 其它单个 / 开头的站内路径是页面跳转;协议相对 URL(//host、/\\host)发布时即被拒绝。\n * label 含 `.` 视为 i18n key。comment=true 先弹意见框,把 { comment } 作为请求体带上。\n */\nexport interface NoticeAction {\n label: string\n method: 'GET' | 'POST'\n url: string\n style?: 'primary' | 'default' | 'error' | null\n confirm?: boolean\n comment?: boolean\n}\n\n/** 通知行(后端 SysNotice;管理端列表全字段,int64 收敛为 number)。 */\nexport interface SysNotice {\n id: number\n title: string\n content?: string | null\n type: NoticeType\n createTime?: string\n /** 动作列表原文(JSON 数组);管理端只展示条数 */\n actionsJson?: string | null\n}\n\n/** 我的通知项(后端 NoticeMineItem;含当前用户已读标记)。 */\nexport interface NoticeMineItem {\n id: number\n title: string\n content?: string | null\n type: NoticeType\n publishTime: string\n isRead: boolean\n actions?: NoticeAction[] | null\n}\n\n/** 发布通知入参(后端 NoticePublishInput)。 */\nexport interface NoticePublishInput {\n title: string\n content?: string | null\n type: NoticeType\n /** 接收范围;缺省 All 广播全体。 */\n receiverType: ReceiverType\n /** 接收目标 Id(角色 Id 或用户 Id,取决于 receiverType);All 时忽略。 */\n receiverIds?: number[]\n /** 动作列表(可选,最多 5 条) */\n actions?: NoticeAction[] | null\n}\n\n// ── 导入 / 导出(与后端 Core DTO 对齐) ──\n\n/** 导入列声明。 */\nexport interface ImportColumn {\n key: string\n title: string\n required?: boolean\n dictTypeCode?: string | null\n hint?: string | null\n width?: number\n}\n\n/** 导出列声明(前端选列弹窗用;DefaultSelected 决定默认勾选)。 */\nexport interface ExportColumnDef {\n key: string\n title: string\n defaultSelected?: boolean\n}\n\n/** 单元格级错误:只带码,文案由前端 translateError(code) 渲染。 */\nexport interface CellError {\n columnKey: string\n code: number\n args?: Record<string, unknown> | null\n}\n\n/** 一行导入数据;单元格一律字符串。 */\nexport interface ImportRow {\n index: number\n cells: Record<string, string | null | undefined>\n errors: CellError[]\n}\n\n/** 预览 / 重验结果。 */\nexport interface ImportPreview {\n headers: string[]\n /** 表头文本 → 列 Key */\n mapping: Record<string, string>\n columns: ImportColumn[]\n rows: ImportRow[]\n total: number\n errorRows: number\n columnErrors: CellError[]\n}\n\n/** 重复处理策略(与后端 DuplicateStrategy 一致)。 */\nexport enum DuplicateStrategy {\n Skip = 0,\n Overwrite = 1,\n Error = 2,\n}\n\n/** 提交结果。 */\nexport interface ImportCommitResult {\n total: number\n inserted: number\n updated: number\n skipped: number\n failed: number\n failures: ImportRow[]\n}\n\n// ── 定时任务(与后端 SysJob/SysJobLog/JobInput 对齐) ──\n\n/** 载荷类型(后端 JobHandlerKind;存库 int)。 */\nexport enum JobHandlerKind {\n Compiled = 1,\n Http = 2,\n Sql = 3,\n}\n\n/** 触发类型(后端 JobTriggerKind)。 */\nexport enum JobTriggerKind {\n Cron = 1,\n Interval = 2,\n OneShot = 3,\n}\n\n/** 错过策略(后端 JobMisfireStrategy)。 */\nexport enum JobMisfireStrategy {\n Skip = 1,\n FireOnceNow = 2,\n}\n\n/** 并发模式(后端 JobConcurrencyMode;SerialSkip=上次未结束则跳过本次)。 */\nexport enum JobConcurrencyMode {\n SerialSkip = 1,\n Parallel = 2,\n}\n\n/** 任务状态(后端 JobStatus;无 Running 态——\"正在运行\"由未闭合执行记录推导)。 */\nexport enum JobStatus {\n Ready = 1,\n Paused = 2,\n Completed = 3,\n Panic = 4,\n}\n\n/** 单次执行结果(后端 JobRunStatus)。 */\nexport enum JobRunStatus {\n Running = 1,\n Success = 2,\n Failed = 3,\n Timeout = 4,\n Cancelled = 5,\n Skipped = 6,\n}\n\n/** 触发来源(后端 JobFireMode)。 */\nexport enum JobFireMode {\n Schedule = 1,\n Manual = 2,\n Misfire = 3,\n MissedSkipped = 4,\n}\n\n/** 任务行(后端 SysJob;page 返回整行,编辑表单直接用行数据回填)。 */\nexport interface SysJob {\n id: number\n code: string\n name: string\n handlerKind: JobHandlerKind\n handlerName: string\n /** 属性包 JSON(Dictionary<string,string?> 字符串化;HTTP 的 headers 值读取时已被掩码)。 */\n propsJson?: string | null\n triggerKind: JobTriggerKind\n cronExpression?: string | null\n intervalSeconds?: number | null\n oneShotTime?: string | null\n startTime?: string | null\n endTime?: string | null\n misfireStrategy: JobMisfireStrategy\n concurrencyMode: JobConcurrencyMode\n status: JobStatus\n nextRunTime?: string | null\n lastRunTime?: string | null\n numberOfRuns: number\n numberOfErrors: number\n consecutiveErrors: number\n timeoutSeconds: number\n retryCount: number\n retryIntervalSeconds: number\n failAlertThreshold: number\n alertByNotice: boolean\n alertEmails?: string | null\n isSystem: boolean\n remark?: string | null\n createTime?: string\n}\n\n/** 任务新增/编辑入参(后端 JobInput;code 仅新增时生效,更新被服务层忽略)。 */\nexport interface JobInput {\n code: string\n name: string\n handlerKind: JobHandlerKind\n /** 编译类填处理器标识;HTTP/SQL 由服务端固定填内置处理器名,传空即可。 */\n handlerName: string\n /** 属性包对象(非字符串!后端存成 propsJson;HTTP 的 headers 子键值对序列化成 JSON 字符串放 properties.headers)。 */\n properties?: Record<string, string> | null\n triggerKind: JobTriggerKind\n cronExpression?: string | null\n /** ≥5(<5 后端拒 47004)。 */\n intervalSeconds?: number | null\n oneShotTime?: string | null\n startTime?: string | null\n endTime?: string | null\n misfireStrategy: JobMisfireStrategy\n concurrencyMode: JobConcurrencyMode\n timeoutSeconds: number\n retryCount: number\n retryIntervalSeconds: number\n failAlertThreshold: number\n alertByNotice: boolean\n alertEmails?: string | null\n remark?: string | null\n}\n\n/** 执行记录行(后端 SysJobLog;endTime 为空 = 运行中,同 fireInstanceId 聚合重试)。 */\nexport interface SysJobLog {\n id: number\n jobId: number\n jobName: string\n fireInstanceId: number\n retryIndex: number\n fireMode: JobFireMode\n scheduledTime: string\n startTime: string\n endTime?: string | null\n runStatus: JobRunStatus\n elapsedMs: number\n nodeName: string\n killRequested: boolean\n messageText?: string | null\n errorText?: string | null\n createTime?: string\n}\n\n/** cron 预览结果(后端 CronPreviewOutput)。 */\nexport interface CronPreviewOutput {\n normalized: string\n occurrences: string[]\n /** 秒段等效每秒执行的告警(仅提示,不拦截)。 */\n everySecondWarning: boolean\n}\n\n/** 处理器清单(后端 JobHandlersOutput)。 */\nexport interface JobHandlersOutput {\n /** 已注册的编译类处理器名(IAdminJob.Name)。 */\n handlers: string[]\n /** SQL 载荷总闸(SmartAdmin:Jobs:Sql:Enabled);false 时前端禁选 SQL 并提示。 */\n sqlEnabled: boolean\n}\n\n/** 成败趋势的一天。 */\nexport interface JobTrendPoint {\n date: string\n success: number\n failed: number\n}\n\n/** 即将执行的一项。 */\nexport interface JobUpcomingItem {\n jobId: number\n name: string\n nextRunTime: string\n}\n\n/** 集群节点一行(角色由与锁行比对得出)。 */\nexport interface JobNodeItem {\n nodeName: string\n hostName: string\n isLeader: boolean\n lastHeartbeat: string\n workerId: number\n pid: number\n}\n\n/** 任务监控仪表盘(后端 JobDashboardOutput)。 */\nexport interface JobDashboard {\n todaySuccess: number\n todayFailed: number\n running: number\n totalJobs: number\n /** 按状态的任务数(键 = Ready/Paused/Completed/Panic)。 */\n statusCounts: Record<string, number>\n trend: JobTrendPoint[]\n upcoming: JobUpcomingItem[]\n nodes: JobNodeItem[]\n}\n\n// ── AI 管理(与后端 AiProviderModels/AiUsageModels 对齐;错误码文案在 error.ai.*,别重复) ──\n\n/** 厂商下的一个模型(后端 AiModelView)。 */\nexport interface AiModelView {\n id: number\n name: string\n displayName: string\n enabled: boolean\n isDefault: boolean\n contextWindow: number | null\n inputPrice: number | null\n outputPrice: number | null\n}\n\n/** 厂商行(后端 AiProviderView;列表/详情共用,apiKey 只回 hasApiKey + 掩码提示,不回明文)。 */\nexport interface AiProviderView {\n id: number\n code: string\n name: string\n preset: string\n protocol: string\n baseUrl: string\n authScheme: string\n apiKeyHint: string | null\n hasApiKey: boolean\n enabled: boolean\n sort: number\n remark: string | null\n models: AiModelView[]\n}\n\n/**\n * 模型新增/编辑入参(后端 AiModelInput;id 为 `null` = 新增该行)。\n * 后端定义为位置式 record——字段在请求体里必须都存在(可以是 null),不能整键省略,\n * 这里特意都不带 `?`,免得页面代码漏填导致类型能过编译、实际发请求时字段缺失。\n */\nexport interface AiModelInput {\n id: number | null\n name: string\n displayName: string\n enabled: boolean\n isDefault: boolean\n contextWindow: number | null\n inputPrice: number | null\n outputPrice: number | null\n}\n\n/** 厂商新增入参(后端 AiProviderAddInput;code 仅新增时填,apiKey 传 null 由后端拒绝/提示未配置)。 */\nexport interface AiProviderAddInput {\n code: string\n name: string\n preset: string\n baseUrl: string\n authScheme: string\n apiKey: string | null\n sort: number\n remark: string | null\n models: AiModelInput[]\n}\n\n/** 厂商编辑入参(后端 AiProviderUpdateInput;无 code——编辑禁用;apiKey 传 null = 不修改现有 Key)。 */\nexport interface AiProviderUpdateInput {\n code: string\n name: string\n baseUrl: string\n authScheme: string\n apiKey: string | null\n sort: number\n remark: string | null\n models: AiModelInput[]\n}\n\n/** 厂商预置(GET /api/v1/sys/ai/provider/presets,静态表,表单下拉用)。 */\nexport interface AiModelPreset {\n name: string\n displayName: string\n contextWindow?: number | null\n}\n\n/** 厂商预置(后端 AiProviderPresets.cs 落定的 11 个 code)。 */\nexport interface AiProviderPreset {\n code: string\n name: string\n protocol: string\n baseUrl: string\n authScheme: string\n models: AiModelPreset[]\n}\n\n/**\n * 后端 AiUsageSource 是普通枚举,没配 JsonStringEnumConverter,序列化按数字下发(System.Text.Json 默认行为)。\n * 1=Reported(上游上报的真实用量),2=Missing(上游没给,记 0 或估算兜底)。\n */\nexport const AI_USAGE_SOURCE = { Reported: 1, Missing: 2 } as const\nexport type AiUsageSourceValue = 1 | 2\n\n/** 一次调用的 Token 用量(后端 AiUsage;source 标记数值是上游上报还是估算兜底)。 */\nexport interface AiUsage {\n inputTokens: number\n outputTokens: number\n totalTokens: number\n source: AiUsageSourceValue\n}\n\n/** 测试连接结果(后端 AiTestResult)。 */\nexport interface AiTestResult {\n ok: boolean\n model?: string | null\n latencyMs: number\n usage?: AiUsage | null\n error?: string | null\n}\n\n/**\n * 用量统计分组维度(后端 AiUsageGroupBy,普通枚举,查询参按数字下发/上送)。\n * 1=Provider、2=Model、3=Scene、4=User。\n */\nexport const AI_USAGE_GROUP_BY = { Provider: 1, Model: 2, Scene: 3, User: 4 } as const\nexport type AiUsageGroupBy = 1 | 2 | 3 | 4\n\n/** 用量统计四格指标(后端 AiUsageTotals;failuresByErrorCode 键为 ErrorCode 数值)。 */\nexport interface AiUsageTotals {\n totalTokens: number\n inputTokens: number\n outputTokens: number\n callCount: number\n failureCount: number\n failuresByErrorCode: Record<number, number>\n}\n\n/** 分组维度下的一行(后端 AiUsageGroupRow)。 */\nexport interface AiUsageGroupRow {\n key: string\n label?: string | null\n inputTokens: number\n outputTokens: number\n callCount: number\n sharePercent: number\n avgLatencyMs: number\n}\n\n/** 用量统计汇总(后端 AiUsageSummary)。 */\nexport interface AiUsageSummary {\n totals: AiUsageTotals\n groups: AiUsageGroupRow[]\n}\n\n/** 用量趋势的一天(后端 AiUsageTrendPoint)。 */\nexport interface AiUsageTrendPoint {\n date: string\n inputTokens: number\n outputTokens: number\n callCount: number\n}\n\n/** 用量明细行(后端 SysAiUsageLog;只读,分页项已含全字段)。 */\nexport interface SysAiUsageLog {\n id: number\n providerId: number\n providerCode: string\n model: string\n scene: string\n userId?: number | null\n inputTokens: number\n outputTokens: number\n totalTokens: number\n usageSource: AiUsageSourceValue\n latencyMs: number\n success: boolean\n errorCode?: number | null\n errorMessage?: string | null\n streamed: boolean\n requestId?: string | null\n createTime: string\n}\n"],"names":["DataScopeType","NoticeType","ReceiverType","DuplicateStrategy","JobHandlerKind","JobTriggerKind","JobMisfireStrategy","JobConcurrencyMode","JobStatus","JobRunStatus","JobFireMode","AI_USAGE_SOURCE","AI_USAGE_GROUP_BY"],"mappings":"AAmaO,IAAKA,sBAAAA,OACVA,EAAAA,EAAA,MAAM,CAAA,IAAN,OACAA,EAAAA,EAAA,MAAM,CAAA,IAAN,OACAA,EAAAA,EAAA,iBAAiB,CAAA,IAAjB,kBACAA,EAAAA,EAAA,OAAO,CAAA,IAAP,QACAA,EAAAA,EAAA,SAAS,CAAA,IAAT,UALUA,IAAAA,KAAA,CAAA,CAAA,GAsFAC,sBAAAA,OACVA,EAAAA,EAAA,SAAS,CAAA,IAAT,UACAA,EAAAA,EAAA,eAAe,CAAA,IAAf,gBACAA,EAAAA,EAAA,UAAU,CAAA,IAAV,WAHUA,IAAAA,KAAA,CAAA,CAAA,GAOAC,sBAAAA,OACVA,EAAAA,EAAA,MAAM,CAAA,IAAN,OACAA,EAAAA,EAAA,OAAO,CAAA,IAAP,QACAA,EAAAA,EAAA,OAAO,CAAA,IAAP,QAHUA,IAAAA,KAAA,CAAA,CAAA,GAqGAC,sBAAAA,OACVA,EAAAA,EAAA,OAAO,CAAA,IAAP,QACAA,EAAAA,EAAA,YAAY,CAAA,IAAZ,aACAA,EAAAA,EAAA,QAAQ,CAAA,IAAR,SAHUA,IAAAA,KAAA,CAAA,CAAA,GAmBAC,sBAAAA,OACVA,EAAAA,EAAA,WAAW,CAAA,IAAX,YACAA,EAAAA,EAAA,OAAO,CAAA,IAAP,QACAA,EAAAA,EAAA,MAAM,CAAA,IAAN,OAHUA,IAAAA,KAAA,CAAA,CAAA,GAOAC,sBAAAA,OACVA,EAAAA,EAAA,OAAO,CAAA,IAAP,QACAA,EAAAA,EAAA,WAAW,CAAA,IAAX,YACAA,EAAAA,EAAA,UAAU,CAAA,IAAV,WAHUA,IAAAA,KAAA,CAAA,CAAA,GAOAC,sBAAAA,OACVA,EAAAA,EAAA,OAAO,CAAA,IAAP,QACAA,EAAAA,EAAA,cAAc,CAAA,IAAd,eAFUA,IAAAA,KAAA,CAAA,CAAA,GAMAC,sBAAAA,OACVA,EAAAA,EAAA,aAAa,CAAA,IAAb,cACAA,EAAAA,EAAA,WAAW,CAAA,IAAX,YAFUA,IAAAA,KAAA,CAAA,CAAA,GAMAC,sBAAAA,OACVA,EAAAA,EAAA,QAAQ,CAAA,IAAR,SACAA,EAAAA,EAAA,SAAS,CAAA,IAAT,UACAA,EAAAA,EAAA,YAAY,CAAA,IAAZ,aACAA,EAAAA,EAAA,QAAQ,CAAA,IAAR,SAJUA,IAAAA,KAAA,CAAA,CAAA,GAQAC,sBAAAA,OACVA,EAAAA,EAAA,UAAU,CAAA,IAAV,WACAA,EAAAA,EAAA,UAAU,CAAA,IAAV,WACAA,EAAAA,EAAA,SAAS,CAAA,IAAT,UACAA,EAAAA,EAAA,UAAU,CAAA,IAAV,WACAA,EAAAA,EAAA,YAAY,CAAA,IAAZ,aACAA,EAAAA,EAAA,UAAU,CAAA,IAAV,WANUA,IAAAA,KAAA,CAAA,CAAA,GAUAC,sBAAAA,OACVA,EAAAA,EAAA,WAAW,CAAA,IAAX,YACAA,EAAAA,EAAA,SAAS,CAAA,IAAT,UACAA,EAAAA,EAAA,UAAU,CAAA,IAAV,WACAA,EAAAA,EAAA,gBAAgB,CAAA,IAAhB,iBAJUA,IAAAA,KAAA,CAAA,CAAA;AA0OL,MAAMC,IAAkB,EAAE,UAAU,GAAG,SAAS,EAAA,GAwB1CC,IAAoB,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,EAAA;"}
1
+ {"version":3,"file":"api.js","sources":["../../src/types/api.ts"],"sourcesContent":["// 接口出参领域类型(与后端 DTO 对齐)。API 层用它标注 unwrap<T> 的返回,视图直接消费。\nimport type { AppModule } from './menu'\n\n/** 登录/刷新出参(后端 LoginOutput)。 */\nexport interface LoginOutput {\n accessToken: string\n expiresAt: string\n refreshToken: string\n refreshExpiresAt: string\n userId: number\n account: string\n name: string\n /** 是否需强制改密(管理员建号/重置后首登为 true)。 */\n mustChangePassword: boolean\n /**\n * 会话交付模式(可选)。\n * - `body`:刷新令牌在 JSON 体(默认,前端 localStorage 持久化)\n * - `cookie`:刷新令牌在 HttpOnly Cookie,access 仅内存\n * 缺省时前端用 refreshToken 空串 + csrfRequired 兜底判定(见 stores/user.ts 的 isCookieSession)。\n */\n sessionMode?: 'body' | 'cookie' | string | null\n /**\n * 是否要求双提交 CSRF(`X-Smart-CSRF` + `smart_csrf` Cookie)。\n * Cookie 会话为 true;默认模式为 false/缺省。\n */\n csrfRequired?: boolean | null\n /** 是否超管;前端据此在 profile 接口故障时仍能正确 fail-open v-auth。 */\n isSuperAdmin?: boolean\n}\n\n/** 我的应用列表(后端 MyModulesOutput)。 */\nexport interface MyModulesOutput {\n modules: AppModule[]\n defaultModuleId?: number | null\n}\n\n/** 个人资料(后端 UserProfile)。 */\nexport interface UserProfile {\n id: number\n account: string\n name: string\n orgId?: number | null\n positionId?: number | null\n /** 机构名称(未分配/已删则 null) */\n orgName?: string | null\n /** 职位名称(未分配/已删则 null) */\n positionName?: string | null\n nickname?: string | null\n phone?: string | null\n email?: string | null\n /** 性别:字典 gender 的项 Value(\"1\"男/\"2\"女/\"0\"未知) */\n gender?: string | null\n /** 头像(文件签名直链 ViewUrl,直接进 img) */\n avatar?: string | null\n isSuperAdmin: boolean\n}\n\n/** 我的会话项(后端 MySessionItem;个人视角,isCurrent 标记本次请求所用会话)。 */\nexport interface MySessionItem {\n sessionId: string\n ip?: string | null\n userAgent?: string | null\n loginTime: string\n expiresAt: string\n isCurrent: boolean\n}\n\n/** 上一次成功登录的信息(后端 LastLoginOutput;排除本次,首次登录时接口整体返回 null)。 */\nexport interface LastLoginInfo {\n time: string\n ip?: string | null\n userAgent?: string | null\n}\n\n/** 工作台待办单条(后端 WorkbenchTodoItem)。 */\nexport interface WorkbenchTodoItem {\n id: number\n title: string\n description?: string | null\n url?: string | null\n createTime: string\n}\n\n/** 工作台待办摘要(后端 WorkbenchTodoSummary;内核默认恒空)。 */\nexport interface WorkbenchTodoSummary {\n totalCount: number\n items: WorkbenchTodoItem[]\n}\n\n/** 工作台快捷方式项(后端 UserShortcutItem;后端已按\"置顶优先+高频补位\"排好序)。 */\nexport interface UserShortcutItem {\n menuPath: string\n pinned: boolean\n title: string\n icon?: string | null\n}\n\n/** 后端统一分页结果 PagedList<T>。 */\nexport interface PagedList<T> {\n current: number\n size: number\n total: number\n pages: number\n items: T[]\n}\n\n/** 用户列表项(后端 UserItem;刻意不含密码)。 */\nexport interface UserItem {\n id: number\n account: string\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n orgId?: number | null\n positionId?: number | null\n directorId?: number | null\n orgName?: string | null\n positionName?: string | null\n directorName?: string | null\n enabled: boolean\n isSuperAdmin: boolean\n /** 管理员显式强制 TOTP(只能加严)。 */\n forceTotp?: boolean\n /** 是否已绑定 TOTP(只读)。 */\n totpEnabled?: boolean\n createTime: string\n}\n\n/** 模块/应用管理行(后端 SysModule;列表全字段)。 */\nexport interface ModuleRow {\n id: number\n code: string\n title: string\n icon?: string | null\n defaultRoute?: string | null\n /** 后端路由匹配前缀(如 sys/biz):菜单配按钮时权限路由下拉据此按应用软过滤;留空=不过滤。 */\n apiPrefix?: string | null\n sort: number\n enabled: boolean\n remark?: string | null\n /** 可转授:普通管理员能否单独授权本应用的菜单(内置 system 恒为 false)。 */\n isDelegatable?: boolean | null\n createTime?: string\n}\n\n/** 工作台首页统计(后端 DashboardSummaryOutput)。趋势三条数组等长(近 7 日,含今天,无登录的日子为 0)。 */\nexport interface DashboardSummary {\n roles: number\n users: number\n perms: number\n onlineSessions: number\n trendDays: string[]\n trendLogins: number[]\n trendActiveUsers: number[]\n}\n\n/** 字典项消费投影(后端 SysDictItem;sort 归一为 number,甩掉 int64 序列化的 number|string 噪音)。 */\nexport interface DictItem {\n label: string\n value: string\n sort: number\n enabled: boolean\n}\n\n/** 模块新增/编辑入参(后端 ModuleInput)。 */\nexport interface ModuleInput {\n code: string\n title: string\n icon?: string | null\n defaultRoute?: string | null\n apiPrefix?: string | null\n sort: number\n enabled: boolean\n remark?: string | null\n /** 可转授:普通管理员能否单独授权本应用的菜单(内置 system 恒为 false)。 */\n isDelegatable?: boolean | null\n}\n\n/** 用户单独授权的效果(后端 UserMenuEffect)。 */\nexport enum UserMenuEffect {\n Allow = 1,\n Deny = 2,\n}\n\n/** 单独授权的有效期状态(后端 UserMenuGrantStatus;作筛选条件时 Active 含 7 天内到期)。 */\nexport enum UserMenuGrantStatus {\n Active = 1,\n Expiring = 2,\n Expired = 3,\n}\n\n/** 一条单独授权记录(后端 UserMenuGrantItem)。时间是本地时间串 yyyy-MM-ddTHH:mm:ss。 */\nexport interface UserMenuGrantItem {\n menuId: number\n effect: UserMenuEffect\n expireTime?: string | null\n remark?: string | null\n grantorId?: number | null\n grantorName?: string | null\n grantTime: string\n updaterId?: number | null\n updaterName?: string | null\n updateTime?: string | null\n}\n\n/** 变更集里的一条新增或修改(后端 UserMenuGrantUpsert)。 */\nexport interface UserMenuGrantUpsert {\n menuId: number\n effect: UserMenuEffect\n expireTime?: string | null\n remark?: string | null\n}\n\n/** 被拒节点里仍然有效的权限码与携带它的有效节点(后端 UserMenuLeakedCode)。 */\nexport interface UserMenuLeakedCode {\n code: string\n carrierMenuIds: number[]\n}\n\n/** 一个菜单节点对目标用户是否有效、为什么(后端 UserMenuEffectiveNode)。 */\nexport interface UserMenuEffectiveNode {\n menuId: number\n moduleId?: number | null\n effective: boolean\n roles: string[]\n grant?: UserMenuEffect | null\n expireTime?: string | null\n expired: boolean\n deniedByAncestor: boolean\n grantable: boolean\n leakedCodes: UserMenuLeakedCode[]\n}\n\n/** 授权弹窗的模块清单项(后端 UserMenuModuleItem)。 */\nexport interface UserMenuModuleItem {\n id: number\n title: string\n delegatable: boolean\n}\n\n/** 授权弹窗一次取齐的数据(后端 UserMenuEffectiveOutput)。readOnlyReason 是错误码。 */\nexport interface UserMenuEffective {\n userId: number\n hasRoles: boolean\n targetEditable: boolean\n readOnlyReason?: number | null\n delegatedMaxDays?: number | null\n /** 委派授权的最晚到期日 yyyy-MM-dd(服务器本地日期 + 最长天数);不限时为空。日期选择器上限与保存前校验都按它算。 */\n delegatedMaxDate?: string | null\n modules: UserMenuModuleItem[]\n nodes: UserMenuEffectiveNode[]\n}\n\n/** 单独授权一览的一行(后端 UserMenuGrantPageItem)。 */\nexport interface UserMenuGrantPageItem {\n id: number\n userId: number\n userAccount: string\n userName: string\n menuId: number\n menuTitle: string\n moduleId?: number | null\n moduleTitle?: string | null\n effect: UserMenuEffect\n expireTime?: string | null\n status: UserMenuGrantStatus\n grantorId?: number | null\n grantorName?: string | null\n grantTime: string\n remark?: string | null\n}\n\n/** 系统配置行(后端 SysConfig;列表返回全字段,int64 收敛为 number)。 */\nexport interface SysConfig {\n id: number\n configKey: string\n configValue?: string | null\n name: string\n groupCode?: string | null\n sort: number\n remark?: string | null\n createTime?: string\n}\n\n/** 配置新增/编辑入参(后端 ConfigInput;configKey 创建后不可改)。 */\nexport interface ConfigInput {\n configKey: string\n configValue?: string | null\n name: string\n groupCode?: string | null\n sort: number\n remark?: string | null\n}\n\n/** 字典类型行(后端 SysDictType;Code 创建后不可改)。int64 收敛为 number。 */\nexport interface SysDictType {\n id: number\n code: string\n name: string\n sort: number\n enabled: boolean\n remark?: string | null\n createTime?: string\n}\n\n/** 字典项行(后端 SysDictItem;管理端分页含停用项,带 id——区别于下拉投影 DictItem)。int64 收敛为 number。 */\nexport interface SysDictItem {\n id: number\n dictTypeCode: string\n label: string\n value: string\n sort: number\n enabled: boolean\n createTime?: string\n}\n\n/** 字典类型新增/编辑入参(后端 DictTypeInput;code 创建后不可改,更新时服务端忽略)。 */\nexport interface DictTypeInput {\n code: string\n name: string\n sort: number\n enabled: boolean\n remark?: string | null\n}\n\n/** 字典项新增/编辑入参(后端 DictItemInput;dictTypeCode = 当前类型,表单隐藏)。 */\nexport interface DictItemInput {\n dictTypeCode: string\n label: string\n value: string\n sort: number\n enabled: boolean\n}\n\n/** 文件记录行(后端 SysFile;列表返回,int64 收敛为 number)。 */\nexport interface SysFile {\n id: number\n originalName: string\n storagePath: string\n extension: string\n contentType?: string | null\n sizeBytes: number\n fileHash?: string | null\n createTime?: string\n}\n\n/** 上传出参(后端 FileUploadOutput)。 */\nexport interface FileUploadOutput {\n id: number\n originalName: string\n /** 存储层相对路径。**别当 URL 用**:后端默认不静态托管上传目录,当 src 必然坏链。要展示图片用 viewUrl。 */\n storagePath: string\n sizeBytes: number\n fileHash?: string | null\n /** 签名直链(匿名可取、不可伪造),可直接塞进 `<img src>`;后端签发,前端不自己拼。 */\n viewUrl?: string | null\n}\n\n/** 分片上传初始化出参(后端 ChunkInitOutput)。 */\nexport interface ChunkInitOutput {\n /** 秒传命中(同内容哈希已存在,无需再传)。 */\n uploaded: boolean\n /** 秒传命中时的既有文件。 */\n file?: FileUploadOutput | null\n /** 上传会话 Id(= 文件哈希);非秒传时返回。 */\n uploadId?: string | null\n /** 服务端已收到的分片下标(断点续传:跳过已传)。 */\n receivedIndexes: number[]\n}\n\n/** 在线会话行(后端 OnlineSessionItem;只读 + 强退按 sessionId)。int64 收敛为 number。 */\nexport interface OnlineSessionItem {\n sessionId: string\n userId: number\n account: string\n ip?: string | null\n userAgent?: string | null\n loginTime?: string\n expiresAt?: string\n}\n\n/** 登录日志行(后端 SysLoginLog;只读,int64 收敛为 number)。 */\nexport interface SysLoginLog {\n id: number\n account: string\n success: boolean\n resultCode: number\n userId?: number | null\n name?: string | null\n ip?: string | null\n userAgent?: string | null\n createTime: string\n}\n\n/** 操作日志行(后端 SysOpLog;只读,分页项已含全字段,详情抽屉直接用行数据)。 */\nexport interface SysOpLog {\n id: number\n title: string\n httpMethod: string\n path: string\n paramJson?: string | null\n resultCode: number\n success: boolean\n exceptionMessage?: string | null\n elapsedMs: number\n operatorId?: number | null\n operatorName?: string | null\n ip?: string | null\n userAgent?: string | null\n createTime: string\n}\n\n/** 磁盘分区容量(后端 DiskInfo)。 */\nexport interface DiskInfo {\n name: string\n totalBytes: number\n freeBytes: number\n}\n\n/** 服务器运行快照(后端 ServerInfoOutput;进程/主机基础指标)。 */\nexport interface ServerInfoOutput {\n machineName: string\n osDescription: string\n frameworkDescription: string\n processArchitecture: string\n processorCount: number\n processUptimeSeconds: number\n processCpuPercent: number\n processWorkingSetBytes: number\n gcHeapBytes: number\n totalAvailableMemoryBytes: number\n threadCount: number\n disks: DiskInfo[]\n}\n\n/** 异常日志行(后端 SysExceptionLog;未捕获异常留痕,只读,分页项已含全字段)。 */\nexport interface SysExceptionLog {\n id: number\n httpMethod: string\n path: string\n traceId?: string | null\n exceptionType: string\n message?: string | null\n stackTrace?: string | null\n operatorId?: number | null\n operatorName?: string | null\n ip?: string | null\n userAgent?: string | null\n createTime: string\n}\n\n/** 机构行(后端 SysOrg;平铺,前端 buildTree)。int64 收敛为 number。 */\nexport interface SysOrg {\n id: number\n parentId: number\n name: string\n code: string\n category?: string | null\n sort: number\n enabled: boolean\n createTime?: string\n}\n\n/** 机构新增/编辑入参(后端 OrgInput;parentId 0=根,code 编辑禁用)。 */\nexport interface OrgInput {\n parentId: number\n name: string\n code: string\n category?: string | null\n sort: number\n enabled: boolean\n}\n\n/** 职位行(后端 SysPosition)。int64 收敛为 number。 */\nexport interface SysPosition {\n id: number\n name: string\n code: string\n sort: number\n enabled: boolean\n createTime?: string\n}\n\n/** 职位新增/编辑入参(后端 PositionInput;增改同一份字段,code 编辑禁用)。 */\nexport interface PositionInput {\n name: string\n code: string\n sort: number\n enabled: boolean\n}\n\n/** 角色行(后端 SysRole)。int64 收敛为 number。 */\nexport interface SysRole {\n id: number\n name: string\n code: string\n sort: number\n enabled: boolean\n remark?: string | null\n isDelegatable?: boolean | null\n /** 内置角色(种子里固定 Id 1–999):只有它们能被授系统菜单。 */\n isBuiltin?: boolean\n createTime?: string\n}\n\n/** 角色新增/编辑入参(后端 RoleInput;增改同一份字段,code 编辑禁用)。 */\nexport interface RoleInput {\n name: string\n code: string\n sort: number\n enabled: boolean\n remark?: string | null\n isDelegatable?: boolean | null\n}\n\n/** 数据范围类型(后端 DataScopeType;存库为 int,枚举值须与后端一致)。 */\nexport enum DataScopeType {\n All = 1,\n Org = 2,\n OrgAndChildren = 3,\n Self = 4,\n Custom = 5,\n}\n\n/** 角色数据范围配置(后端 SysRoleDataScope;数据范围抽屉回显)。customOrgIds 逗号分隔。 */\nexport interface SysRoleDataScope {\n id: number\n roleId: number\n scopeType: DataScopeType\n customOrgIds: string\n}\n\n/** 新增用户入参(后端 AddUserInput;account 建后不可改,password 留空=系统生成随机强口令)。 */\nexport interface AddUserInput {\n account: string\n password?: string | null\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n orgId?: number | null\n positionId?: number | null\n directorId?: number | null\n enabled: boolean\n /** 建号即强制 TOTP。 */\n forceTotp?: boolean\n roleIds: number[]\n}\n\n/** 新增用户出参(后端 AddUserOutput):新 Id + 实际生效的初始口令明文——留空口令时是随机生成的,不展示给管理员就没人知道。 */\nexport interface AddUserOutput {\n id: number\n initialPassword: string\n}\n\n/** 一条可授权路由(后端 PermissionRouteItem);喂菜单表单权限码下拉,code 即写进 SysMenu.Permission 的值。 */\nexport interface PermissionRouteItem {\n code: string\n method: string\n path: string\n}\n\n/** 更新用户入参(后端 UpdateUserInput;无 account/password。roleIds 由 detail 原样带回避免清空)。 */\nexport interface UpdateUserInput {\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n orgId?: number | null\n positionId?: number | null\n directorId?: number | null\n enabled: boolean\n forceTotp?: boolean\n roleIds: number[]\n}\n\n/** 用户详情(后端 UserDetail;列表字段 + roleIds,编辑回显用)。 */\nexport interface UserDetail {\n id: number\n account: string\n name: string\n nickname?: string | null\n phone?: string | null\n email?: string | null\n gender?: string | null\n avatar?: string | null\n orgId?: number | null\n positionId?: number | null\n directorId?: number | null\n enabled: boolean\n isSuperAdmin: boolean\n forceTotp?: boolean\n totpEnabled?: boolean\n roleIds: number[]\n createTime?: string\n}\n\n/** 通知类型(后端 NoticeType;存库 int,枚举值须与后端一致)。 */\nexport enum NoticeType {\n Notice = 1,\n Announcement = 2,\n Message = 3,\n}\n\n/** 接收范围(后端 ReceiverType;All=0 对全体广播,Role/User 定向)。 */\nexport enum ReceiverType {\n All = 0,\n Role = 1,\n User = 2,\n}\n\n/**\n * 通知动作(后端 NoticeAction):前端渲染成正文下的按钮。url 以 /api/ 开头是接口调用(按 method 发请求),\n * 其它单个 / 开头的站内路径是页面跳转;协议相对 URL(//host、/\\host)发布时即被拒绝。\n * label 含 `.` 视为 i18n key。comment=true 先弹意见框,把 { comment } 作为请求体带上。\n */\nexport interface NoticeAction {\n label: string\n method: 'GET' | 'POST'\n url: string\n style?: 'primary' | 'default' | 'error' | null\n confirm?: boolean\n comment?: boolean\n}\n\n/** 通知行(后端 SysNotice;管理端列表全字段,int64 收敛为 number)。 */\nexport interface SysNotice {\n id: number\n title: string\n content?: string | null\n type: NoticeType\n createTime?: string\n /** 动作列表原文(JSON 数组);管理端只展示条数 */\n actionsJson?: string | null\n}\n\n/** 我的通知项(后端 NoticeMineItem;含当前用户已读标记)。 */\nexport interface NoticeMineItem {\n id: number\n title: string\n content?: string | null\n type: NoticeType\n publishTime: string\n isRead: boolean\n actions?: NoticeAction[] | null\n}\n\n/** 发布通知入参(后端 NoticePublishInput)。 */\nexport interface NoticePublishInput {\n title: string\n content?: string | null\n type: NoticeType\n /** 接收范围;缺省 All 广播全体。 */\n receiverType: ReceiverType\n /** 接收目标 Id(角色 Id 或用户 Id,取决于 receiverType);All 时忽略。 */\n receiverIds?: number[]\n /** 动作列表(可选,最多 5 条) */\n actions?: NoticeAction[] | null\n}\n\n// ── 导入 / 导出(与后端 Core DTO 对齐) ──\n\n/** 导入列声明。 */\nexport interface ImportColumn {\n key: string\n title: string\n required?: boolean\n dictTypeCode?: string | null\n hint?: string | null\n width?: number\n}\n\n/** 导出列声明(前端选列弹窗用;DefaultSelected 决定默认勾选)。 */\nexport interface ExportColumnDef {\n key: string\n title: string\n defaultSelected?: boolean\n}\n\n/** 单元格级错误:只带码,文案由前端 translateError(code) 渲染。 */\nexport interface CellError {\n columnKey: string\n code: number\n args?: Record<string, unknown> | null\n}\n\n/** 一行导入数据;单元格一律字符串。 */\nexport interface ImportRow {\n index: number\n cells: Record<string, string | null | undefined>\n errors: CellError[]\n}\n\n/** 预览 / 重验结果。 */\nexport interface ImportPreview {\n headers: string[]\n /** 表头文本 → 列 Key */\n mapping: Record<string, string>\n columns: ImportColumn[]\n rows: ImportRow[]\n total: number\n errorRows: number\n columnErrors: CellError[]\n}\n\n/** 重复处理策略(与后端 DuplicateStrategy 一致)。 */\nexport enum DuplicateStrategy {\n Skip = 0,\n Overwrite = 1,\n Error = 2,\n}\n\n/** 提交结果。 */\nexport interface ImportCommitResult {\n total: number\n inserted: number\n updated: number\n skipped: number\n failed: number\n failures: ImportRow[]\n}\n\n// ── 定时任务(与后端 SysJob/SysJobLog/JobInput 对齐) ──\n\n/** 载荷类型(后端 JobHandlerKind;存库 int)。 */\nexport enum JobHandlerKind {\n Compiled = 1,\n Http = 2,\n Sql = 3,\n}\n\n/** 触发类型(后端 JobTriggerKind)。 */\nexport enum JobTriggerKind {\n Cron = 1,\n Interval = 2,\n OneShot = 3,\n}\n\n/** 错过策略(后端 JobMisfireStrategy)。 */\nexport enum JobMisfireStrategy {\n Skip = 1,\n FireOnceNow = 2,\n}\n\n/** 并发模式(后端 JobConcurrencyMode;SerialSkip=上次未结束则跳过本次)。 */\nexport enum JobConcurrencyMode {\n SerialSkip = 1,\n Parallel = 2,\n}\n\n/** 任务状态(后端 JobStatus;无 Running 态——\"正在运行\"由未闭合执行记录推导)。 */\nexport enum JobStatus {\n Ready = 1,\n Paused = 2,\n Completed = 3,\n Panic = 4,\n}\n\n/** 单次执行结果(后端 JobRunStatus)。 */\nexport enum JobRunStatus {\n Running = 1,\n Success = 2,\n Failed = 3,\n Timeout = 4,\n Cancelled = 5,\n Skipped = 6,\n}\n\n/** 触发来源(后端 JobFireMode)。 */\nexport enum JobFireMode {\n Schedule = 1,\n Manual = 2,\n Misfire = 3,\n MissedSkipped = 4,\n}\n\n/** 任务行(后端 SysJob;page 返回整行,编辑表单直接用行数据回填)。 */\nexport interface SysJob {\n id: number\n code: string\n name: string\n handlerKind: JobHandlerKind\n handlerName: string\n /** 属性包 JSON(Dictionary<string,string?> 字符串化;HTTP 的 headers 值读取时已被掩码)。 */\n propsJson?: string | null\n triggerKind: JobTriggerKind\n cronExpression?: string | null\n intervalSeconds?: number | null\n oneShotTime?: string | null\n startTime?: string | null\n endTime?: string | null\n misfireStrategy: JobMisfireStrategy\n concurrencyMode: JobConcurrencyMode\n status: JobStatus\n nextRunTime?: string | null\n lastRunTime?: string | null\n numberOfRuns: number\n numberOfErrors: number\n consecutiveErrors: number\n timeoutSeconds: number\n retryCount: number\n retryIntervalSeconds: number\n failAlertThreshold: number\n alertByNotice: boolean\n alertEmails?: string | null\n isSystem: boolean\n remark?: string | null\n createTime?: string\n}\n\n/** 任务新增/编辑入参(后端 JobInput;code 仅新增时生效,更新被服务层忽略)。 */\nexport interface JobInput {\n code: string\n name: string\n handlerKind: JobHandlerKind\n /** 编译类填处理器标识;HTTP/SQL 由服务端固定填内置处理器名,传空即可。 */\n handlerName: string\n /** 属性包对象(非字符串!后端存成 propsJson;HTTP 的 headers 子键值对序列化成 JSON 字符串放 properties.headers)。 */\n properties?: Record<string, string> | null\n triggerKind: JobTriggerKind\n cronExpression?: string | null\n /** ≥5(<5 后端拒 47004)。 */\n intervalSeconds?: number | null\n oneShotTime?: string | null\n startTime?: string | null\n endTime?: string | null\n misfireStrategy: JobMisfireStrategy\n concurrencyMode: JobConcurrencyMode\n timeoutSeconds: number\n retryCount: number\n retryIntervalSeconds: number\n failAlertThreshold: number\n alertByNotice: boolean\n alertEmails?: string | null\n remark?: string | null\n}\n\n/** 执行记录行(后端 SysJobLog;endTime 为空 = 运行中,同 fireInstanceId 聚合重试)。 */\nexport interface SysJobLog {\n id: number\n jobId: number\n jobName: string\n fireInstanceId: number\n retryIndex: number\n fireMode: JobFireMode\n scheduledTime: string\n startTime: string\n endTime?: string | null\n runStatus: JobRunStatus\n elapsedMs: number\n nodeName: string\n killRequested: boolean\n messageText?: string | null\n errorText?: string | null\n createTime?: string\n}\n\n/** cron 预览结果(后端 CronPreviewOutput)。 */\nexport interface CronPreviewOutput {\n normalized: string\n occurrences: string[]\n /** 秒段等效每秒执行的告警(仅提示,不拦截)。 */\n everySecondWarning: boolean\n}\n\n/** 处理器清单(后端 JobHandlersOutput)。 */\nexport interface JobHandlersOutput {\n /** 已注册的编译类处理器名(IAdminJob.Name)。 */\n handlers: string[]\n /** SQL 载荷总闸(SmartAdmin:Jobs:Sql:Enabled);false 时前端禁选 SQL 并提示。 */\n sqlEnabled: boolean\n}\n\n/** 成败趋势的一天。 */\nexport interface JobTrendPoint {\n date: string\n success: number\n failed: number\n}\n\n/** 即将执行的一项。 */\nexport interface JobUpcomingItem {\n jobId: number\n name: string\n nextRunTime: string\n}\n\n/** 集群节点一行(角色由与锁行比对得出)。 */\nexport interface JobNodeItem {\n nodeName: string\n hostName: string\n isLeader: boolean\n lastHeartbeat: string\n workerId: number\n pid: number\n}\n\n/** 任务监控仪表盘(后端 JobDashboardOutput)。 */\nexport interface JobDashboard {\n todaySuccess: number\n todayFailed: number\n running: number\n totalJobs: number\n /** 按状态的任务数(键 = Ready/Paused/Completed/Panic)。 */\n statusCounts: Record<string, number>\n trend: JobTrendPoint[]\n upcoming: JobUpcomingItem[]\n nodes: JobNodeItem[]\n}\n\n// ── AI 管理(与后端 AiProviderModels/AiUsageModels 对齐;错误码文案在 error.ai.*,别重复) ──\n\n/** 厂商下的一个模型(后端 AiModelView)。 */\nexport interface AiModelView {\n id: number\n name: string\n displayName: string\n enabled: boolean\n isDefault: boolean\n contextWindow: number | null\n inputPrice: number | null\n outputPrice: number | null\n}\n\n/** 厂商行(后端 AiProviderView;列表/详情共用,apiKey 只回 hasApiKey + 掩码提示,不回明文)。 */\nexport interface AiProviderView {\n id: number\n code: string\n name: string\n preset: string\n protocol: string\n baseUrl: string\n authScheme: string\n apiKeyHint: string | null\n hasApiKey: boolean\n enabled: boolean\n sort: number\n remark: string | null\n models: AiModelView[]\n}\n\n/**\n * 模型新增/编辑入参(后端 AiModelInput;id 为 `null` = 新增该行)。\n * 后端定义为位置式 record——字段在请求体里必须都存在(可以是 null),不能整键省略,\n * 这里特意都不带 `?`,免得页面代码漏填导致类型能过编译、实际发请求时字段缺失。\n */\nexport interface AiModelInput {\n id: number | null\n name: string\n displayName: string\n enabled: boolean\n isDefault: boolean\n contextWindow: number | null\n inputPrice: number | null\n outputPrice: number | null\n}\n\n/** 厂商新增入参(后端 AiProviderAddInput;code 仅新增时填,apiKey 传 null 由后端拒绝/提示未配置)。 */\nexport interface AiProviderAddInput {\n code: string\n name: string\n preset: string\n baseUrl: string\n authScheme: string\n apiKey: string | null\n sort: number\n remark: string | null\n models: AiModelInput[]\n}\n\n/** 厂商编辑入参(后端 AiProviderUpdateInput;无 code——编辑禁用;apiKey 传 null = 不修改现有 Key)。 */\nexport interface AiProviderUpdateInput {\n code: string\n name: string\n baseUrl: string\n authScheme: string\n apiKey: string | null\n sort: number\n remark: string | null\n models: AiModelInput[]\n}\n\n/** 厂商预置(GET /api/v1/sys/ai/provider/presets,静态表,表单下拉用)。 */\nexport interface AiModelPreset {\n name: string\n displayName: string\n contextWindow?: number | null\n}\n\n/** 厂商预置(后端 AiProviderPresets.cs 落定的 11 个 code)。 */\nexport interface AiProviderPreset {\n code: string\n name: string\n protocol: string\n baseUrl: string\n authScheme: string\n models: AiModelPreset[]\n}\n\n/**\n * 后端 AiUsageSource 是普通枚举,没配 JsonStringEnumConverter,序列化按数字下发(System.Text.Json 默认行为)。\n * 1=Reported(上游上报的真实用量),2=Missing(上游没给,记 0 或估算兜底)。\n */\nexport const AI_USAGE_SOURCE = { Reported: 1, Missing: 2 } as const\nexport type AiUsageSourceValue = 1 | 2\n\n/** 一次调用的 Token 用量(后端 AiUsage;source 标记数值是上游上报还是估算兜底)。 */\nexport interface AiUsage {\n inputTokens: number\n outputTokens: number\n totalTokens: number\n source: AiUsageSourceValue\n}\n\n/** 测试连接结果(后端 AiTestResult)。 */\nexport interface AiTestResult {\n ok: boolean\n model?: string | null\n latencyMs: number\n usage?: AiUsage | null\n error?: string | null\n}\n\n/**\n * 用量统计分组维度(后端 AiUsageGroupBy,普通枚举,查询参按数字下发/上送)。\n * 1=Provider、2=Model、3=Scene、4=User。\n */\nexport const AI_USAGE_GROUP_BY = { Provider: 1, Model: 2, Scene: 3, User: 4 } as const\nexport type AiUsageGroupBy = 1 | 2 | 3 | 4\n\n/** 用量统计四格指标(后端 AiUsageTotals;failuresByErrorCode 键为 ErrorCode 数值)。 */\nexport interface AiUsageTotals {\n totalTokens: number\n inputTokens: number\n outputTokens: number\n callCount: number\n failureCount: number\n failuresByErrorCode: Record<number, number>\n}\n\n/** 分组维度下的一行(后端 AiUsageGroupRow)。 */\nexport interface AiUsageGroupRow {\n key: string\n label?: string | null\n inputTokens: number\n outputTokens: number\n callCount: number\n sharePercent: number\n avgLatencyMs: number\n}\n\n/** 用量统计汇总(后端 AiUsageSummary)。 */\nexport interface AiUsageSummary {\n totals: AiUsageTotals\n groups: AiUsageGroupRow[]\n}\n\n/** 用量趋势的一天(后端 AiUsageTrendPoint)。 */\nexport interface AiUsageTrendPoint {\n date: string\n inputTokens: number\n outputTokens: number\n callCount: number\n}\n\n/** 用量明细行(后端 SysAiUsageLog;只读,分页项已含全字段)。 */\nexport interface SysAiUsageLog {\n id: number\n providerId: number\n providerCode: string\n model: string\n scene: string\n userId?: number | null\n inputTokens: number\n outputTokens: number\n totalTokens: number\n usageSource: AiUsageSourceValue\n latencyMs: number\n success: boolean\n errorCode?: number | null\n errorMessage?: string | null\n streamed: boolean\n requestId?: string | null\n createTime: string\n}\n"],"names":["UserMenuEffect","UserMenuGrantStatus","DataScopeType","NoticeType","ReceiverType","DuplicateStrategy","JobHandlerKind","JobTriggerKind","JobMisfireStrategy","JobConcurrencyMode","JobStatus","JobRunStatus","JobFireMode","AI_USAGE_SOURCE","AI_USAGE_GROUP_BY"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function shake(el: Element | null | undefined): void;
@@ -0,0 +1,30 @@
1
+ const r = "cubic-bezier(0.36, 0.07, 0.19, 0.97)", d = [
2
+ [0, 0],
3
+ [0.15, -9],
4
+ [0.3, 8],
5
+ [0.45, -6],
6
+ [0.6, 4],
7
+ [0.8, -2],
8
+ [1, 0]
9
+ ], u = 0.4, D = 0.7, a = /* @__PURE__ */ new WeakMap();
10
+ function m(n) {
11
+ var e, c;
12
+ if (!n || typeof n.animate != "function") return;
13
+ const t = !!((e = window.matchMedia) != null && e.call(window, "(prefers-reduced-motion: reduce)").matches), s = t ? u : 1;
14
+ (c = a.get(n)) == null || c.cancel(), a.set(
15
+ n,
16
+ n.animate(
17
+ // easing 写在每个关键帧上:作用于「本帧到下一帧」这一段,与 CSS 里 animation-timing-function 的语义一致
18
+ d.map(([i, o]) => ({
19
+ offset: i,
20
+ transform: o === 0 ? "none" : `translate3d(${+(o * s).toFixed(2)}px, 0, 0)`,
21
+ easing: r
22
+ })),
23
+ { duration: t ? 460 * D : 460 }
24
+ )
25
+ );
26
+ }
27
+ export {
28
+ m as shake
29
+ };
30
+ //# sourceMappingURL=shake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shake.js","sources":["../../src/utils/shake.ts"],"sourcesContent":["// 失败晃动:元素沿水平方向左右抖几下并逐渐收住(macOS 登录框 / 提示框拒绝输入时的做法)。\n// 登录失败、弹窗表单校验不过共用这一份,保证两处手感一致。\n//\n// 用 Web Animations API 而不是「加 class 触发 CSS 动画」,原因有两个:\n// - 全局有一条 prefers-reduced-motion 规则把所有 CSS 动画压到 0.01ms(styles/index.css),\n// 系统关了动画效果的机器(Windows 关「显示动画」、远程桌面、部分企业策略)上,\n// class 方案的晃动就整个消失,操作员只剩一条一闪而过的 toast;\n// - 连续失败要能重播:class 方案得先摘掉、等一帧再加回去,WAAPI 取消上一段再播即可。\n// 全局那条规则只管 CSS 动画与过渡,不会碰到这里显式传了时长的 WAAPI 动画。\n\nconst DURATION = 460\nconst EASING = 'cubic-bezier(0.36, 0.07, 0.19, 0.97)'\n// 位移(px)关键帧:幅度逐步收小,首尾回到原位,不回弹到别处\nconst STEPS: [offset: number, x: number][] = [\n [0, 0],\n [0.15, -9],\n [0.3, 8],\n [0.45, -6],\n [0.6, 4],\n [0.8, -2],\n [1, 0],\n]\n// 系统要求减少动态效果时,晃动不取消(它是唯一就地的失败反馈),但幅度与时长都收小:\n// 约 ±3.6px、0.32s 的轻微抖动,既看得见,又不是大幅位移。\nconst REDUCED_AMPLITUDE = 0.4\nconst REDUCED_DURATION = 0.7\n\nconst running = new WeakMap<Element, Animation>()\n\nexport function shake(el: Element | null | undefined): void {\n if (!el || typeof el.animate !== 'function') return\n const reduced = !!window.matchMedia?.('(prefers-reduced-motion: reduce)').matches\n const amp = reduced ? REDUCED_AMPLITUDE : 1\n running.get(el)?.cancel()\n running.set(\n el,\n el.animate(\n // easing 写在每个关键帧上:作用于「本帧到下一帧」这一段,与 CSS 里 animation-timing-function 的语义一致\n STEPS.map(([offset, x]) => ({\n offset,\n transform: x === 0 ? 'none' : `translate3d(${+(x * amp).toFixed(2)}px, 0, 0)`,\n easing: EASING,\n })),\n { duration: reduced ? DURATION * REDUCED_DURATION : DURATION },\n ),\n )\n}\n"],"names":["EASING","STEPS","REDUCED_AMPLITUDE","REDUCED_DURATION","running","shake","el","_a","_b","reduced","amp","offset","x"],"mappings":"AAWA,MAAMA,IAAS,wCAETC,IAAuC;AAAA,EAC3C,CAAC,GAAG,CAAC;AAAA,EACL,CAAC,MAAM,EAAE;AAAA,EACT,CAAC,KAAK,CAAC;AAAA,EACP,CAAC,MAAM,EAAE;AAAA,EACT,CAAC,KAAK,CAAC;AAAA,EACP,CAAC,KAAK,EAAE;AAAA,EACR,CAAC,GAAG,CAAC;AACP,GAGMC,IAAoB,KACpBC,IAAmB,KAEnBC,wBAAc,QAAA;AAEb,SAASC,EAAMC,GAAsC;AAnB5D,MAAAC,GAAAC;AAoBE,MAAI,CAACF,KAAM,OAAOA,EAAG,WAAY,WAAY;AAC7C,QAAMG,IAAU,CAAC,GAACF,IAAA,OAAO,eAAP,QAAAA,EAAA,aAAoB,oCAAoC,UACpEG,IAAMD,IAAUP,IAAoB;AAC1C,GAAAM,IAAAJ,EAAQ,IAAIE,CAAE,MAAd,QAAAE,EAAiB,UACjBJ,EAAQ;AAAA,IACNE;AAAA,IACAA,EAAG;AAAA;AAAA,MAEDL,EAAM,IAAI,CAAC,CAACU,GAAQC,CAAC,OAAO;AAAA,QAC1B,QAAAD;AAAA,QACA,WAAWC,MAAM,IAAI,SAAS,eAAe,EAAEA,IAAIF,GAAK,QAAQ,CAAC,CAAC;AAAA,QAClE,QAAQV;AAAA,MAAA,EACR;AAAA,MACF,EAAE,UAAUS,IAAU,MAAWN,IAAmB,IAAA;AAAA,IAAS;AAAA,EAC/D;AAEJ;"}
@@ -26,6 +26,21 @@ export declare function expandableIds<T extends {
26
26
  id: number;
27
27
  children?: T[];
28
28
  }>(nodes: T[]): number[];
29
+ /** 有子节点的根的 id —— 受控展开时用它播种"只展开一级":根展开、露出第二层,更深的层级仍收起。 */
30
+ export declare function rootExpandableIds<T extends {
31
+ id: number;
32
+ children?: T[];
33
+ }>(nodes: T[]): number[];
34
+ /**
35
+ * 树 → 深度优先平铺行(父在前、子紧随其后),每行带 depth(根 = 0),children 置空。
36
+ * 给窄档卡片列表用:smart-naive-table 的卡片模式只画传入的这一层行,不认 children,
37
+ * 树表在手机上要想看到子节点,就得由页面自己把整棵树摊成一列。行是浅拷贝,不改入参。
38
+ */
39
+ export declare function flattenTree<T extends {
40
+ children?: T[];
41
+ }>(nodes: T[], depth?: number): Array<T & {
42
+ depth: number;
43
+ }>;
29
44
  /** 收集 rootId 及其全部后代 id(平铺数组上按 parentId 迭代到不动点)。编辑机构选上级时剪自身子树防成环。 */
30
45
  export declare function collectSubtreeIds<T extends {
31
46
  id: number;
@@ -1,47 +1,61 @@
1
- function c(s) {
2
- const o = /* @__PURE__ */ new Map();
3
- for (const e of s) o.set(e.id, { ...e });
1
+ function d(o) {
2
+ const e = /* @__PURE__ */ new Map();
3
+ for (const t of o) e.set(t.id, { ...t });
4
4
  const n = [];
5
- for (const e of s) {
6
- const t = o.get(e.id), i = o.get(e.parentId);
7
- i ? (i.children ?? (i.children = [])).push(t) : n.push(t);
5
+ for (const t of o) {
6
+ const r = e.get(t.id), i = e.get(t.parentId);
7
+ i ? (i.children ?? (i.children = [])).push(r) : n.push(r);
8
8
  }
9
9
  return n;
10
10
  }
11
- function r(s, o) {
11
+ function s(o, e) {
12
12
  const n = [];
13
- for (const e of s) {
14
- if (o(e)) {
15
- n.push(e);
13
+ for (const t of o) {
14
+ if (e(t)) {
15
+ n.push(t);
16
16
  continue;
17
17
  }
18
- const t = r(e.children ?? [], o);
19
- t.length && n.push({ ...e, children: t });
18
+ const r = s(t.children ?? [], e);
19
+ r.length && n.push({ ...t, children: r });
20
20
  }
21
21
  return n;
22
22
  }
23
- function d(s) {
24
- const o = [], n = (e) => {
25
- var t;
26
- for (const i of e)
27
- (t = i.children) != null && t.length && (o.push(i.id), n(i.children));
23
+ function f(o) {
24
+ const e = [], n = (t) => {
25
+ var r;
26
+ for (const i of t)
27
+ (r = i.children) != null && r.length && (e.push(i.id), n(i.children));
28
28
  };
29
- return n(s), o;
29
+ return n(o), e;
30
30
  }
31
- function f(s, o) {
32
- const n = /* @__PURE__ */ new Set([o]);
33
- let e = !0;
34
- for (; e; ) {
35
- e = !1;
36
- for (const t of s)
37
- !n.has(t.id) && n.has(t.parentId) && (n.add(t.id), e = !0);
31
+ function l(o) {
32
+ return o.filter((e) => {
33
+ var n;
34
+ return (n = e.children) == null ? void 0 : n.length;
35
+ }).map((e) => e.id);
36
+ }
37
+ function c(o, e = 0) {
38
+ return o.flatMap((n) => [
39
+ { ...n, children: [], depth: e },
40
+ ...c(n.children ?? [], e + 1)
41
+ ]);
42
+ }
43
+ function u(o, e) {
44
+ const n = /* @__PURE__ */ new Set([e]);
45
+ let t = !0;
46
+ for (; t; ) {
47
+ t = !1;
48
+ for (const r of o)
49
+ !n.has(r.id) && n.has(r.parentId) && (n.add(r.id), t = !0);
38
50
  }
39
51
  return n;
40
52
  }
41
53
  export {
42
- c as buildTree,
43
- f as collectSubtreeIds,
44
- d as expandableIds,
45
- r as filterTree
54
+ d as buildTree,
55
+ u as collectSubtreeIds,
56
+ f as expandableIds,
57
+ s as filterTree,
58
+ c as flattenTree,
59
+ l as rootExpandableIds
46
60
  };
47
61
  //# sourceMappingURL=tree.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tree.js","sources":["../../src/utils/tree.ts"],"sourcesContent":["/** 平铺列表 → 树。按 parentId 挂到父的 children;根 = parentId 不在集合内(含 0)。\n * 原序保留(输入通常已按 sort、id 排好);孤儿(父不存在)兜底当根,不丢数据。\n * 两个消费点:OrgTreeSelect、机构管理页。 */\nexport type Tree<T> = T & { children?: Tree<T>[] }\n\nexport function buildTree<T extends { id: number; parentId: number }>(flat: T[]): Tree<T>[] {\n const map = new Map<number, Tree<T>>()\n for (const item of flat) map.set(item.id, { ...item })\n const roots: Tree<T>[] = []\n for (const item of flat) {\n const node = map.get(item.id)!\n const parent = map.get(item.parentId)\n if (parent) (parent.children ??= []).push(node)\n else roots.push(node)\n }\n return roots\n}\n\n/**\n * 按谓词剪枝:命中的节点保留(连同它的整棵子树——搜到一个目录,自然想看它下面有什么),\n * 未命中但有后代命中的节点作为**祖先链**保留(否则命中的节点在树里无处安放,只剩一堆没有上下文的叶子)。\n *\n * 命中节点返回的是**原对象引用**(零拷贝);只有\"仅因后代命中而保留\"的祖先才是浅拷贝(children 换成剪过的分支)。\n * 因此在搜索态下,直接往行对象上写值(`r.enabled = v`)对这些祖先行不会回写到源树 ——\n * 调用方要么改从源树写,要么变更后重拉(机构页选了后者,与它其余所有变更的做法一致)。\n *\n * 两个消费点:菜单管理页、机构管理页。\n */\nexport function filterTree<T extends { children?: T[] }>(\n nodes: T[],\n match: (node: T) => boolean,\n): T[] {\n const out: T[] = []\n for (const node of nodes) {\n if (match(node)) {\n out.push(node)\n continue\n }\n const kids = filterTree(node.children ?? [], match)\n if (kids.length) out.push({ ...node, children: kids })\n }\n return out\n}\n\n/** 收集树中所有\"可展开\"节点(有子节点)的 id —— 受控展开时用它播种\"全部展开\"。 */\nexport function expandableIds<T extends { id: number; children?: T[] }>(nodes: T[]): number[] {\n const ids: number[] = []\n const walk = (list: T[]) => {\n for (const n of list) {\n if (n.children?.length) {\n ids.push(n.id)\n walk(n.children)\n }\n }\n }\n walk(nodes)\n return ids\n}\n\n/** 收集 rootId 及其全部后代 id(平铺数组上按 parentId 迭代到不动点)。编辑机构选上级时剪自身子树防成环。 */\nexport function collectSubtreeIds<T extends { id: number; parentId: number }>(\n flat: T[],\n rootId: number,\n): Set<number> {\n const ids = new Set<number>([rootId])\n let grew = true\n while (grew) {\n grew = false\n for (const item of flat) {\n if (!ids.has(item.id) && ids.has(item.parentId)) {\n ids.add(item.id)\n grew = true\n }\n }\n }\n return ids\n}\n"],"names":["buildTree","flat","map","item","roots","node","parent","filterTree","nodes","match","out","kids","expandableIds","ids","walk","list","_a","n","collectSubtreeIds","rootId","grew"],"mappings":"AAKO,SAASA,EAAsDC,GAAsB;AAC1F,QAAMC,wBAAU,IAAA;AAChB,aAAWC,KAAQF,EAAM,CAAAC,EAAI,IAAIC,EAAK,IAAI,EAAE,GAAGA,GAAM;AACrD,QAAMC,IAAmB,CAAA;AACzB,aAAWD,KAAQF,GAAM;AACvB,UAAMI,IAAOH,EAAI,IAAIC,EAAK,EAAE,GACtBG,IAASJ,EAAI,IAAIC,EAAK,QAAQ;AACpC,IAAIG,KAASA,EAAO,aAAPA,EAAO,WAAa,CAAA,IAAI,KAAKD,CAAI,IACzCD,EAAM,KAAKC,CAAI;AAAA,EACtB;AACA,SAAOD;AACT;AAYO,SAASG,EACdC,GACAC,GACK;AACL,QAAMC,IAAW,CAAA;AACjB,aAAWL,KAAQG,GAAO;AACxB,QAAIC,EAAMJ,CAAI,GAAG;AACf,MAAAK,EAAI,KAAKL,CAAI;AACb;AAAA,IACF;AACA,UAAMM,IAAOJ,EAAWF,EAAK,YAAY,CAAA,GAAII,CAAK;AAClD,IAAIE,EAAK,UAAQD,EAAI,KAAK,EAAE,GAAGL,GAAM,UAAUM,GAAM;AAAA,EACvD;AACA,SAAOD;AACT;AAGO,SAASE,EAAwDJ,GAAsB;AAC5F,QAAMK,IAAgB,CAAA,GAChBC,IAAO,CAACC,MAAc;AA1CvB,QAAAC;AA2CH,eAAWC,KAAKF;AACd,OAAIC,IAAAC,EAAE,aAAF,QAAAD,EAAY,WACdH,EAAI,KAAKI,EAAE,EAAE,GACbH,EAAKG,EAAE,QAAQ;AAAA,EAGrB;AACA,SAAAH,EAAKN,CAAK,GACHK;AACT;AAGO,SAASK,EACdjB,GACAkB,GACa;AACb,QAAMN,IAAM,oBAAI,IAAY,CAACM,CAAM,CAAC;AACpC,MAAIC,IAAO;AACX,SAAOA,KAAM;AACX,IAAAA,IAAO;AACP,eAAWjB,KAAQF;AACjB,MAAI,CAACY,EAAI,IAAIV,EAAK,EAAE,KAAKU,EAAI,IAAIV,EAAK,QAAQ,MAC5CU,EAAI,IAAIV,EAAK,EAAE,GACfiB,IAAO;AAAA,EAGb;AACA,SAAOP;AACT;"}
1
+ {"version":3,"file":"tree.js","sources":["../../src/utils/tree.ts"],"sourcesContent":["/** 平铺列表 → 树。按 parentId 挂到父的 children;根 = parentId 不在集合内(含 0)。\n * 原序保留(输入通常已按 sort、id 排好);孤儿(父不存在)兜底当根,不丢数据。\n * 两个消费点:OrgTreeSelect、机构管理页。 */\nexport type Tree<T> = T & { children?: Tree<T>[] }\n\nexport function buildTree<T extends { id: number; parentId: number }>(flat: T[]): Tree<T>[] {\n const map = new Map<number, Tree<T>>()\n for (const item of flat) map.set(item.id, { ...item })\n const roots: Tree<T>[] = []\n for (const item of flat) {\n const node = map.get(item.id)!\n const parent = map.get(item.parentId)\n if (parent) (parent.children ??= []).push(node)\n else roots.push(node)\n }\n return roots\n}\n\n/**\n * 按谓词剪枝:命中的节点保留(连同它的整棵子树——搜到一个目录,自然想看它下面有什么),\n * 未命中但有后代命中的节点作为**祖先链**保留(否则命中的节点在树里无处安放,只剩一堆没有上下文的叶子)。\n *\n * 命中节点返回的是**原对象引用**(零拷贝);只有\"仅因后代命中而保留\"的祖先才是浅拷贝(children 换成剪过的分支)。\n * 因此在搜索态下,直接往行对象上写值(`r.enabled = v`)对这些祖先行不会回写到源树 ——\n * 调用方要么改从源树写,要么变更后重拉(机构页选了后者,与它其余所有变更的做法一致)。\n *\n * 两个消费点:菜单管理页、机构管理页。\n */\nexport function filterTree<T extends { children?: T[] }>(\n nodes: T[],\n match: (node: T) => boolean,\n): T[] {\n const out: T[] = []\n for (const node of nodes) {\n if (match(node)) {\n out.push(node)\n continue\n }\n const kids = filterTree(node.children ?? [], match)\n if (kids.length) out.push({ ...node, children: kids })\n }\n return out\n}\n\n/** 收集树中所有\"可展开\"节点(有子节点)的 id —— 受控展开时用它播种\"全部展开\"。 */\nexport function expandableIds<T extends { id: number; children?: T[] }>(nodes: T[]): number[] {\n const ids: number[] = []\n const walk = (list: T[]) => {\n for (const n of list) {\n if (n.children?.length) {\n ids.push(n.id)\n walk(n.children)\n }\n }\n }\n walk(nodes)\n return ids\n}\n\n/** 有子节点的根的 id —— 受控展开时用它播种\"只展开一级\":根展开、露出第二层,更深的层级仍收起。 */\nexport function rootExpandableIds<T extends { id: number; children?: T[] }>(nodes: T[]): number[] {\n return nodes.filter(n => n.children?.length).map(n => n.id)\n}\n\n/**\n * 树 → 深度优先平铺行(父在前、子紧随其后),每行带 depth(根 = 0),children 置空。\n * 给窄档卡片列表用:smart-naive-table 的卡片模式只画传入的这一层行,不认 children,\n * 树表在手机上要想看到子节点,就得由页面自己把整棵树摊成一列。行是浅拷贝,不改入参。\n */\nexport function flattenTree<T extends { children?: T[] }>(\n nodes: T[],\n depth = 0,\n): Array<T & { depth: number }> {\n return nodes.flatMap(node => [\n { ...node, children: [], depth } as T & { depth: number },\n ...flattenTree(node.children ?? [], depth + 1),\n ])\n}\n\n/** 收集 rootId 及其全部后代 id(平铺数组上按 parentId 迭代到不动点)。编辑机构选上级时剪自身子树防成环。 */\nexport function collectSubtreeIds<T extends { id: number; parentId: number }>(\n flat: T[],\n rootId: number,\n): Set<number> {\n const ids = new Set<number>([rootId])\n let grew = true\n while (grew) {\n grew = false\n for (const item of flat) {\n if (!ids.has(item.id) && ids.has(item.parentId)) {\n ids.add(item.id)\n grew = true\n }\n }\n }\n return ids\n}\n"],"names":["buildTree","flat","map","item","roots","node","parent","filterTree","nodes","match","out","kids","expandableIds","ids","walk","list","_a","n","rootExpandableIds","flattenTree","depth","collectSubtreeIds","rootId","grew"],"mappings":"AAKO,SAASA,EAAsDC,GAAsB;AAC1F,QAAMC,wBAAU,IAAA;AAChB,aAAWC,KAAQF,EAAM,CAAAC,EAAI,IAAIC,EAAK,IAAI,EAAE,GAAGA,GAAM;AACrD,QAAMC,IAAmB,CAAA;AACzB,aAAWD,KAAQF,GAAM;AACvB,UAAMI,IAAOH,EAAI,IAAIC,EAAK,EAAE,GACtBG,IAASJ,EAAI,IAAIC,EAAK,QAAQ;AACpC,IAAIG,KAASA,EAAO,aAAPA,EAAO,WAAa,CAAA,IAAI,KAAKD,CAAI,IACzCD,EAAM,KAAKC,CAAI;AAAA,EACtB;AACA,SAAOD;AACT;AAYO,SAASG,EACdC,GACAC,GACK;AACL,QAAMC,IAAW,CAAA;AACjB,aAAWL,KAAQG,GAAO;AACxB,QAAIC,EAAMJ,CAAI,GAAG;AACf,MAAAK,EAAI,KAAKL,CAAI;AACb;AAAA,IACF;AACA,UAAMM,IAAOJ,EAAWF,EAAK,YAAY,CAAA,GAAII,CAAK;AAClD,IAAIE,EAAK,UAAQD,EAAI,KAAK,EAAE,GAAGL,GAAM,UAAUM,GAAM;AAAA,EACvD;AACA,SAAOD;AACT;AAGO,SAASE,EAAwDJ,GAAsB;AAC5F,QAAMK,IAAgB,CAAA,GAChBC,IAAO,CAACC,MAAc;AA1CvB,QAAAC;AA2CH,eAAWC,KAAKF;AACd,OAAIC,IAAAC,EAAE,aAAF,QAAAD,EAAY,WACdH,EAAI,KAAKI,EAAE,EAAE,GACbH,EAAKG,EAAE,QAAQ;AAAA,EAGrB;AACA,SAAAH,EAAKN,CAAK,GACHK;AACT;AAGO,SAASK,EAA4DV,GAAsB;AAChG,SAAOA,EAAM,OAAO,CAAAS,MAAA;AAxDf,QAAAD;AAwDoB,YAAAA,IAAAC,EAAE,aAAF,gBAAAD,EAAY;AAAA,GAAM,EAAE,IAAI,CAAAC,MAAKA,EAAE,EAAE;AAC5D;AAOO,SAASE,EACdX,GACAY,IAAQ,GACsB;AAC9B,SAAOZ,EAAM,QAAQ,CAAAH,MAAQ;AAAA,IAC3B,EAAE,GAAGA,GAAM,UAAU,CAAA,GAAI,OAAAe,EAAA;AAAA,IACzB,GAAGD,EAAYd,EAAK,YAAY,CAAA,GAAIe,IAAQ,CAAC;AAAA,EAAA,CAC9C;AACH;AAGO,SAASC,EACdpB,GACAqB,GACa;AACb,QAAMT,IAAM,oBAAI,IAAY,CAACS,CAAM,CAAC;AACpC,MAAIC,IAAO;AACX,SAAOA,KAAM;AACX,IAAAA,IAAO;AACP,eAAWpB,KAAQF;AACjB,MAAI,CAACY,EAAI,IAAIV,EAAK,EAAE,KAAKU,EAAI,IAAIV,EAAK,QAAQ,MAC5CU,EAAI,IAAIV,EAAK,EAAE,GACfoB,IAAO;AAAA,EAGb;AACA,SAAOV;AACT;"}
@@ -0,0 +1,6 @@
1
+ import { VNodeChild } from 'vue';
2
+ /**
3
+ * 窄档卡片里没有树的缩进:按 `flattenTree` 给的 depth 给标题缩进,层级一眼可辨。
4
+ * 宽档的行没有 depth,原样返回,由表格自己画缩进与展开箭头。
5
+ */
6
+ export declare const indentByDepth: (row: object, content: VNodeChild) => VNodeChild;
@@ -0,0 +1,9 @@
1
+ import { h as n } from "vue";
2
+ const d = (e, t) => {
3
+ const p = e.depth;
4
+ return p ? n("span", { style: { paddingInlineStart: `${p * 16}px` } }, [t]) : t;
5
+ };
6
+ export {
7
+ d as indentByDepth
8
+ };
9
+ //# sourceMappingURL=treeCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treeCard.js","sources":["../../src/utils/treeCard.ts"],"sourcesContent":["import { h, type VNodeChild } from 'vue'\n\n/**\n * 窄档卡片里没有树的缩进:按 `flattenTree` 给的 depth 给标题缩进,层级一眼可辨。\n * 宽档的行没有 depth,原样返回,由表格自己画缩进与展开箭头。\n */\nexport const indentByDepth = (row: object, content: VNodeChild): VNodeChild => {\n const depth = (row as { depth?: number }).depth\n return depth\n ? h('span', { style: { paddingInlineStart: `${depth * 16}px` } }, [content])\n : content\n}\n"],"names":["indentByDepth","row","content","depth","h"],"mappings":";AAMO,MAAMA,IAAgB,CAACC,GAAaC,MAAoC;AAC7E,QAAMC,IAASF,EAA2B;AAC1C,SAAOE,IACHC,EAAE,QAAQ,EAAE,OAAO,EAAE,oBAAoB,GAAGD,IAAQ,EAAE,OAAK,GAAK,CAACD,CAAO,CAAC,IACzEA;AACN;"}
@@ -1,8 +1,8 @@
1
1
  import o from "./4042.vue.js";
2
2
  /* empty css */
3
3
  import t from "../../_virtual/_plugin-vue_export-helper.js";
4
- const f = /* @__PURE__ */ t(o, [["__scopeId", "data-v-67a3298f"]]);
4
+ const e = /* @__PURE__ */ t(o, [["__scopeId", "data-v-ce3af4ea"]]);
5
5
  export {
6
- f as default
6
+ e as default
7
7
  };
8
8
  //# sourceMappingURL=404.vue.js.map
@@ -1,33 +1,90 @@
1
- import { defineComponent as c, openBlock as d, createBlock as i, unref as t, withCtx as s, createElementVNode as o, toDisplayString as n, createVNode as p, createTextVNode as l } from "vue";
2
- import { useRouter as u } from "vue-router";
3
- import { NCard as m, NButton as f } from "naive-ui";
4
- import { useI18n as _ } from "vue-i18n";
5
- const x = {
1
+ import { defineComponent as V, computed as m, ref as C, watch as E, openBlock as r, createBlock as f, unref as e, withCtx as s, createElementVNode as i, toDisplayString as u, createElementBlock as I, createCommentVNode as v, createTextVNode as h, createVNode as O } from "vue";
2
+ import { useRoute as b, useRouter as z } from "vue-router";
3
+ import { useMessage as R, NCard as S, NButton as y } from "naive-ui";
4
+ import { useI18n as T } from "vue-i18n";
5
+ import { useAuthStore as $ } from "../../stores/auth.js";
6
+ import { useModule as D } from "../../composables/useModule.js";
7
+ import { translateMenuTitle as M } from "../../locales/menuTitle.js";
8
+ import { translateError as P } from "../../utils/error.js";
9
+ const j = {
6
10
  class: "nf",
7
11
  role: "status"
8
- }, k = { class: "msg" }, b = /* @__PURE__ */ c({
12
+ }, q = { class: "msg" }, G = {
13
+ key: 0,
14
+ class: "hint"
15
+ }, H = { class: "actions" }, ee = /* @__PURE__ */ V({
9
16
  __name: "404",
10
- setup(N) {
11
- const a = u(), { t: r } = _();
12
- return (g, e) => (d(), i(t(m), {
17
+ setup(J) {
18
+ const _ = b(), k = z(), N = R(), { t: a } = T(), c = $(), { findOwnerModule: A, switchModule: F } = D(), d = m(() => c.modules.length > 1), w = m(() => {
19
+ const n = c.modules.find((o) => o.id === c.currentModuleId);
20
+ return n ? M(n.title) : "";
21
+ }), t = C(null), g = m(() => t.value ? M(t.value.title) : ""), l = C(!1);
22
+ let x = 0;
23
+ E(
24
+ () => _.path,
25
+ async (n) => {
26
+ if (t.value = null, !d.value) return;
27
+ const o = ++x, p = await A(n);
28
+ o === x && (t.value = p);
29
+ },
30
+ { immediate: !0 }
31
+ );
32
+ async function B() {
33
+ if (!(!t.value || l.value)) {
34
+ l.value = !0;
35
+ try {
36
+ await F(t.value.id, _.fullPath);
37
+ } catch (n) {
38
+ N.error(P(n));
39
+ } finally {
40
+ l.value = !1;
41
+ }
42
+ }
43
+ }
44
+ return (n, o) => (r(), f(e(S), {
13
45
  class: "nf-card",
14
46
  "content-style": "padding: 40px 28px 36px"
15
47
  }, {
16
48
  default: s(() => [
17
- o("div", x, [
18
- e[1] || (e[1] = o("div", { class: "code" }, "404", -1)),
19
- o("div", k, n(t(r)("notFound.desc")), 1),
20
- p(t(f), {
21
- type: "primary",
22
- size: "large",
23
- class: "back",
24
- onClick: e[0] || (e[0] = (v) => t(a).replace("/"))
25
- }, {
26
- default: s(() => [
27
- l(n(t(r)("notFound.back")), 1)
28
- ]),
29
- _: 1
30
- })
49
+ i("div", j, [
50
+ o[2] || (o[2] = i("div", { class: "code" }, "404", -1)),
51
+ i("div", q, u(t.value ? e(a)("notFound.otherApp", { app: g.value }) : e(a)("notFound.desc")), 1),
52
+ d.value && w.value ? (r(), I("div", G, u(e(a)("notFound.currentApp", { app: w.value })), 1)) : v("", !0),
53
+ i("div", H, [
54
+ t.value ? (r(), f(e(y), {
55
+ key: 0,
56
+ type: "primary",
57
+ size: "large",
58
+ loading: l.value,
59
+ onClick: B
60
+ }, {
61
+ default: s(() => [
62
+ h(u(e(a)("notFound.switchAndOpen", { app: g.value })), 1)
63
+ ]),
64
+ _: 1
65
+ }, 8, ["loading"])) : v("", !0),
66
+ O(e(y), {
67
+ type: t.value ? "default" : "primary",
68
+ size: "large",
69
+ class: "back",
70
+ onClick: o[0] || (o[0] = (p) => e(k).replace("/"))
71
+ }, {
72
+ default: s(() => [
73
+ h(u(e(a)("notFound.back")), 1)
74
+ ]),
75
+ _: 1
76
+ }, 8, ["type"]),
77
+ d.value && !t.value ? (r(), f(e(y), {
78
+ key: 1,
79
+ text: "",
80
+ onClick: o[1] || (o[1] = (p) => e(k).push("/module"))
81
+ }, {
82
+ default: s(() => [
83
+ h(u(e(a)("app.switchModule")), 1)
84
+ ]),
85
+ _: 1
86
+ })) : v("", !0)
87
+ ])
31
88
  ])
32
89
  ]),
33
90
  _: 1
@@ -35,6 +92,6 @@ const x = {
35
92
  }
36
93
  });
37
94
  export {
38
- b as default
95
+ ee as default
39
96
  };
40
97
  //# sourceMappingURL=4042.vue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"4042.vue.js","sources":["../../../src/views/error/404.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useRouter } from 'vue-router'\nimport { NButton, NCard } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\n\nconst router = useRouter()\nconst { t } = useI18n()\n</script>\n\n<template>\n <!-- 404 挂在布局壳内:撑满内容区,居中块放进卡片里(文字直接压在画布柔光上对比度不够) -->\n <n-card class=\"nf-card\" content-style=\"padding: 40px 28px 36px\">\n <div class=\"nf\" role=\"status\">\n <div class=\"code\">404</div>\n <div class=\"msg\">{{ t('notFound.desc') }}</div>\n <n-button type=\"primary\" size=\"large\" class=\"back\" @click=\"router.replace('/')\">\n {{ t('notFound.back') }}\n </n-button>\n </div>\n </n-card>\n</template>\n\n<style scoped>\n/* 撑满 layout 的 .page 容器,而不是整个视口——404 挂在布局壳内 */\n.nf-card {\n min-height: 60vh;\n height: 100%;\n}\n.nf-card :deep(.n-card__content) {\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.nf {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n gap: 16px;\n}\n.code {\n font-size: 96px;\n font-weight: 800;\n line-height: 1;\n letter-spacing: -0.04em;\n color: var(--signal);\n}\n.msg {\n color: var(--text-2);\n font-size: 16px;\n}\n.back {\n min-width: 120px;\n}\n</style>\n"],"names":["router","useRouter","t","useI18n","_createBlock","_unref","NCard","_createElementVNode","_hoisted_1","_cache","_hoisted_2","_toDisplayString","_createVNode","NButton","$event"],"mappings":";;;;;;;;;;AAKA,UAAMA,IAASC,EAAA,GACT,EAAE,GAAAC,EAAA,IAAMC,EAAA;2BAKZC,EAQSC,EAAAC,CAAA,GAAA;AAAA,MARD,OAAM;AAAA,MAAU,iBAAc;AAAA,IAAA;iBACpC,MAMM;AAAA,QANNC,EAMM,OANNC,GAMM;AAAA,UALJC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAF,EAA2B,OAAA,EAAtB,OAAM,OAAA,GAAO,OAAG,EAAA;AAAA,UACrBA,EAA+C,OAA/CG,GAA+CC,EAA3BN,EAAAH,CAAA,EAAC,eAAA,CAAA,GAAA,CAAA;AAAA,UACrBU,EAEWP,EAAAQ,CAAA,GAAA;AAAA,YAFD,MAAK;AAAA,YAAU,MAAK;AAAA,YAAQ,OAAM;AAAA,YAAQ,SAAKJ,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAK,MAAET,EAAAL,CAAA,EAAO,QAAO,GAAA;AAAA,UAAA;uBACvE,MAAwB;AAAA,kBAArBK,EAAAH,CAAA,EAAC,eAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;;;;;;;"}
1
+ {"version":3,"file":"4042.vue.js","sources":["../../../src/views/error/404.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { NButton, NCard, useMessage } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport { useAuthStore } from '#/stores/auth'\nimport { useModule } from '#/composables/useModule'\nimport { translateMenuTitle } from '#/locales/menuTitle'\nimport { translateError } from '#/utils/error'\nimport type { AppModule } from '#/types/menu'\n\nconst route = useRoute()\nconst router = useRouter()\nconst message = useMessage()\nconst { t } = useI18n()\nconst auth = useAuthStore()\nconst { findOwnerModule, switchModule } = useModule()\n\n// 动态路由只注册当前应用的菜单:别的应用的页面地址(书签、第三方后台配的主页)在这里同样是 404。\n// 单应用部署没有\"别的应用\",也就不提应用、不反查。\nconst multiApp = computed(() => auth.modules.length > 1)\nconst currentApp = computed(() => {\n const m = auth.modules.find(x => x.id === auth.currentModuleId)\n return m ? translateMenuTitle(m.title) : ''\n})\n\nconst owner = ref<AppModule | null>(null)\nconst ownerName = computed(() => (owner.value ? translateMenuTitle(owner.value.title) : ''))\nconst switching = ref(false)\n\n// 同一个组件实例会随地址变化复用,较早发出的反查晚到时不能盖掉较新地址的结果\nlet lookup = 0\nwatch(\n () => route.path,\n async path => {\n owner.value = null\n if (!multiApp.value) return\n const mine = ++lookup\n const found = await findOwnerModule(path)\n if (mine === lookup) owner.value = found\n },\n { immediate: true },\n)\n\nasync function openInOwner() {\n if (!owner.value || switching.value) return\n switching.value = true\n try {\n await switchModule(owner.value.id, route.fullPath)\n } catch (e) {\n message.error(translateError(e))\n } finally {\n switching.value = false\n }\n}\n</script>\n\n<template>\n <!-- 404 挂在布局壳内:撑满内容区,居中块放进卡片里(文字直接压在画布柔光上对比度不够) -->\n <n-card class=\"nf-card\" content-style=\"padding: 40px 28px 36px\">\n <div class=\"nf\" role=\"status\">\n <div class=\"code\">404</div>\n <div class=\"msg\">\n {{ owner ? t('notFound.otherApp', { app: ownerName }) : t('notFound.desc') }}\n </div>\n <div v-if=\"multiApp && currentApp\" class=\"hint\">\n {{ t('notFound.currentApp', { app: currentApp }) }}\n </div>\n <div class=\"actions\">\n <n-button\n v-if=\"owner\"\n type=\"primary\"\n size=\"large\"\n :loading=\"switching\"\n @click=\"openInOwner\"\n >\n {{ t('notFound.switchAndOpen', { app: ownerName }) }}\n </n-button>\n <n-button\n :type=\"owner ? 'default' : 'primary'\"\n size=\"large\"\n class=\"back\"\n @click=\"router.replace('/')\"\n >\n {{ t('notFound.back') }}\n </n-button>\n <n-button v-if=\"multiApp && !owner\" text @click=\"router.push('/module')\">\n {{ t('app.switchModule') }}\n </n-button>\n </div>\n </div>\n </n-card>\n</template>\n\n<style scoped>\n/* 撑满 layout 的 .page 容器,而不是整个视口——404 挂在布局壳内 */\n.nf-card {\n min-height: 60vh;\n height: 100%;\n}\n.nf-card :deep(.n-card__content) {\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.nf {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n gap: 16px;\n}\n.code {\n font-size: 96px;\n font-weight: 800;\n line-height: 1;\n letter-spacing: -0.04em;\n color: var(--signal);\n}\n.msg {\n color: var(--text-2);\n font-size: 16px;\n}\n.hint {\n color: var(--text-3);\n font-size: 13px;\n}\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: 12px;\n}\n.back {\n min-width: 120px;\n}\n</style>\n"],"names":["route","useRoute","router","useRouter","message","useMessage","t","useI18n","auth","useAuthStore","findOwnerModule","switchModule","useModule","multiApp","computed","currentApp","m","x","translateMenuTitle","owner","ref","ownerName","switching","lookup","watch","path","mine","found","openInOwner","e","translateError","_createBlock","_unref","NCard","_createElementVNode","_hoisted_1","_cache","_hoisted_2","_toDisplayString","_openBlock","_createElementBlock","_hoisted_3","_hoisted_4","NButton","_createTextVNode","_createVNode","$event"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import o from "./LoginForm2.vue.js";
2
2
  /* empty css */
3
3
  import r from "../../_virtual/_plugin-vue_export-helper.js";
4
- const _ = /* @__PURE__ */ r(o, [["__scopeId", "data-v-367c227d"]]);
4
+ const f = /* @__PURE__ */ r(o, [["__scopeId", "data-v-2ee53f4e"]]);
5
5
  export {
6
- _ as default
6
+ f as default
7
7
  };
8
8
  //# sourceMappingURL=LoginForm.vue.js.map