@fudanda/admin-antd 2.20261107.1-beta.1 → 2.20261109.1-beta.2

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 (130) hide show
  1. package/dist/chunks/ApiTokensPage-w3JGRNQC.js +2 -0
  2. package/dist/chunks/ApiTokensPage-w3JGRNQC.js.map +1 -0
  3. package/dist/chunks/{App-BF96TQ_D.js → App-nh6_qOo8.js} +5 -5
  4. package/dist/chunks/{App-BF96TQ_D.js.map → App-nh6_qOo8.js.map} +1 -1
  5. package/dist/chunks/{AppModal-CLkMJ-96.js → AppModal-CEouaU03.js} +2 -2
  6. package/dist/chunks/{AppModal-CLkMJ-96.js.map → AppModal-CEouaU03.js.map} +1 -1
  7. package/dist/chunks/{ArcBaseAdmin--xQxd4tg.js → ArcBaseAdmin-CX7fQz4x.js} +2 -2
  8. package/dist/chunks/{ArcBaseAdmin--xQxd4tg.js.map → ArcBaseAdmin-CX7fQz4x.js.map} +1 -1
  9. package/dist/chunks/{DepartmentsPage-D6YVegPU.js → DepartmentsPage-BdD9VfDI.js} +2 -2
  10. package/dist/chunks/{DepartmentsPage-D6YVegPU.js.map → DepartmentsPage-BdD9VfDI.js.map} +1 -1
  11. package/dist/chunks/{DictsPage-uV3Uukwc.js → DictsPage-fxBdV1-3.js} +2 -2
  12. package/dist/chunks/{DictsPage-uV3Uukwc.js.map → DictsPage-fxBdV1-3.js.map} +1 -1
  13. package/dist/chunks/{EntityContextRuntime-DbjyzCtY.js → EntityContextRuntime-CMhoj6qe.js} +2 -2
  14. package/dist/chunks/{EntityContextRuntime-DbjyzCtY.js.map → EntityContextRuntime-CMhoj6qe.js.map} +1 -1
  15. package/dist/chunks/EntityContextRuntime-Dc89ZSnM.js +1 -0
  16. package/dist/chunks/{ExportButton-e2ybxuHb.js → ExportButton-DGxB2tcu.js} +2 -2
  17. package/dist/chunks/{ExportButton-e2ybxuHb.js.map → ExportButton-DGxB2tcu.js.map} +1 -1
  18. package/dist/chunks/{FileViewerPreviewPanel-BhI3pTi8.js → FileViewerPreviewPanel-BMZ7FdKV.js} +3 -3
  19. package/dist/chunks/{FileViewerPreviewPanel-BhI3pTi8.js.map → FileViewerPreviewPanel-BMZ7FdKV.js.map} +1 -1
  20. package/dist/chunks/{FilesPage-BI35mStl.js → FilesPage-DrgWELKy.js} +3 -3
  21. package/dist/chunks/{FilesPage-BI35mStl.js.map → FilesPage-DrgWELKy.js.map} +1 -1
  22. package/dist/chunks/IdentitySecurityPage-BjTKvr-O.js +9 -0
  23. package/dist/chunks/IdentitySecurityPage-BjTKvr-O.js.map +1 -0
  24. package/dist/chunks/{LogStatsScaffold-m0vVUXPh.js → LogStatsScaffold-DaB0JeAN.js} +2 -2
  25. package/dist/chunks/{LogStatsScaffold-m0vVUXPh.js.map → LogStatsScaffold-DaB0JeAN.js.map} +1 -1
  26. package/dist/chunks/{LoginLogsPage-BzBUR4Oo.js → LoginLogsPage-VmYC7i6q.js} +2 -2
  27. package/dist/chunks/{LoginLogsPage-BzBUR4Oo.js.map → LoginLogsPage-VmYC7i6q.js.map} +1 -1
  28. package/dist/chunks/{LoginLogsTable-BweUEjQX.js → LoginLogsTable-CULcc_e8.js} +2 -2
  29. package/dist/chunks/{LoginLogsTable-BweUEjQX.js.map → LoginLogsTable-CULcc_e8.js.map} +1 -1
  30. package/dist/chunks/{MarkdownPreviewPanel-C1OKSLmh.js → MarkdownPreviewPanel-CBcPc7Wv.js} +2 -2
  31. package/dist/chunks/{MarkdownPreviewPanel-C1OKSLmh.js.map → MarkdownPreviewPanel-CBcPc7Wv.js.map} +1 -1
  32. package/dist/chunks/{MasterDetailLayout-KVizcSNO.js → MasterDetailLayout-ByIBpmkZ.js} +2 -2
  33. package/dist/chunks/{MasterDetailLayout-KVizcSNO.js.map → MasterDetailLayout-ByIBpmkZ.js.map} +1 -1
  34. package/dist/chunks/{McpSettingsPage-Dhf0CbDN.js → McpSettingsPage-C5V_rj2V.js} +2 -2
  35. package/dist/chunks/{McpSettingsPage-Dhf0CbDN.js.map → McpSettingsPage-C5V_rj2V.js.map} +1 -1
  36. package/dist/chunks/{MemberAssignmentSheet-TYpnyA0z.js → MemberAssignmentSheet-DL0fg1Yf.js} +2 -2
  37. package/dist/chunks/{MemberAssignmentSheet-TYpnyA0z.js.map → MemberAssignmentSheet-DL0fg1Yf.js.map} +1 -1
  38. package/dist/chunks/{MenuCommandPalette-BcvpUfK7.js → MenuCommandPalette-C2PvK3Gh.js} +2 -2
  39. package/dist/chunks/{MenuCommandPalette-BcvpUfK7.js.map → MenuCommandPalette-C2PvK3Gh.js.map} +1 -1
  40. package/dist/chunks/{MenusPage-Dd7OLQYT.js → MenusPage-Bytd1HlW.js} +2 -2
  41. package/dist/chunks/{MenusPage-Dd7OLQYT.js.map → MenusPage-Bytd1HlW.js.map} +1 -1
  42. package/dist/chunks/{MonacoPreviewPanel-BW1j3ZTF.js → MonacoPreviewPanel-BZrNIcFZ.js} +2 -2
  43. package/dist/chunks/{MonacoPreviewPanel-BW1j3ZTF.js.map → MonacoPreviewPanel-BZrNIcFZ.js.map} +1 -1
  44. package/dist/chunks/{NavListPanel-Iz1RCkVw.js → NavListPanel-zwUDIYSP.js} +2 -2
  45. package/dist/chunks/{NavListPanel-Iz1RCkVw.js.map → NavListPanel-zwUDIYSP.js.map} +1 -1
  46. package/dist/chunks/{OperationLogsPage-Dt22tU4I.js → OperationLogsPage-D2BQdGNp.js} +2 -2
  47. package/dist/chunks/{OperationLogsPage-Dt22tU4I.js.map → OperationLogsPage-D2BQdGNp.js.map} +1 -1
  48. package/dist/chunks/{OperationLogsTable-B23Ry-2v.js → OperationLogsTable-DaaON4QR.js} +3 -3
  49. package/dist/chunks/{OperationLogsTable-B23Ry-2v.js.map → OperationLogsTable-DaaON4QR.js.map} +1 -1
  50. package/dist/chunks/{PDFPreviewPanel-kBPz5dQr.js → PDFPreviewPanel-CMmnWBKW.js} +3 -3
  51. package/dist/chunks/{PDFPreviewPanel-kBPz5dQr.js.map → PDFPreviewPanel-CMmnWBKW.js.map} +1 -1
  52. package/dist/chunks/{PositionsPage-BIKYQDB5.js → PositionsPage-CBZITssT.js} +2 -2
  53. package/dist/chunks/{PositionsPage-BIKYQDB5.js.map → PositionsPage-CBZITssT.js.map} +1 -1
  54. package/dist/chunks/{PreferencesSheetBody-D276rrp4.js → PreferencesSheetBody-B0poTPEA.js} +2 -2
  55. package/dist/chunks/{PreferencesSheetBody-D276rrp4.js.map → PreferencesSheetBody-B0poTPEA.js.map} +1 -1
  56. package/dist/chunks/{ProfilePage-DLftC6KZ.js → ProfilePage-DLhacdWt.js} +2 -2
  57. package/dist/chunks/{ProfilePage-DLftC6KZ.js.map → ProfilePage-DLhacdWt.js.map} +1 -1
  58. package/dist/chunks/{ProjectInfoPage-DkuBLC8t.js → ProjectInfoPage-CJpGxpu5.js} +2 -2
  59. package/dist/chunks/{ProjectInfoPage-DkuBLC8t.js.map → ProjectInfoPage-CJpGxpu5.js.map} +1 -1
  60. package/dist/chunks/{RelationPanel-B4BeO0Bz.js → RelationPanel-BsbfEDo2.js} +2 -2
  61. package/dist/chunks/{RelationPanel-B4BeO0Bz.js.map → RelationPanel-BsbfEDo2.js.map} +1 -1
  62. package/dist/chunks/{RolesPage-BhltU2Qm.js → RolesPage-46dzdiah.js} +2 -2
  63. package/dist/chunks/{RolesPage-BhltU2Qm.js.map → RolesPage-46dzdiah.js.map} +1 -1
  64. package/dist/chunks/{SessionConflictModal-3R8jdYkI.js → SessionConflictModal-Bm38eExL.js} +2 -2
  65. package/dist/chunks/{SessionConflictModal-3R8jdYkI.js.map → SessionConflictModal-Bm38eExL.js.map} +1 -1
  66. package/dist/chunks/SettingModuleDetail-BjxUJeH5.js +17 -0
  67. package/dist/chunks/SettingModuleDetail-BjxUJeH5.js.map +1 -0
  68. package/dist/chunks/{SettingsPage-DMzeDrnc.js → SettingsPage-C32Vuizm.js} +2 -2
  69. package/dist/chunks/{SettingsPage-DMzeDrnc.js.map → SettingsPage-C32Vuizm.js.map} +1 -1
  70. package/dist/chunks/{StatCard-C0xSZyiS.js → StatCard-CRPfkSBY.js} +2 -2
  71. package/dist/chunks/{StatCard-C0xSZyiS.js.map → StatCard-CRPfkSBY.js.map} +1 -1
  72. package/dist/chunks/{UserGroupsPage-DTJdszHl.js → UserGroupsPage-08G5MdGm.js} +2 -2
  73. package/dist/chunks/{UserGroupsPage-DTJdszHl.js.map → UserGroupsPage-08G5MdGm.js.map} +1 -1
  74. package/dist/chunks/{UserLogsPanels-z4UhQtgu.js → UserLogsPanels-nbIrMym9.js} +2 -2
  75. package/dist/chunks/{UserLogsPanels-z4UhQtgu.js.map → UserLogsPanels-nbIrMym9.js.map} +1 -1
  76. package/dist/chunks/{UserTransferSelect-BJNUXMhl.js → UserTransferSelect-C8betaWG.js} +2 -2
  77. package/dist/chunks/{UserTransferSelect-BJNUXMhl.js.map → UserTransferSelect-C8betaWG.js.map} +1 -1
  78. package/dist/chunks/{UsersPage--p68X2Yr.js → UsersPage-BjTiNEqF.js} +2 -2
  79. package/dist/chunks/{UsersPage--p68X2Yr.js.map → UsersPage-BjTiNEqF.js.map} +1 -1
  80. package/dist/chunks/{browser-BKLM0ThC-3Xar5rZw.js → browser-BKLM0ThC-Cp7Gi4-F.js} +1 -1
  81. package/dist/chunks/{code-P0HJS_q1.js → code-LswxAr98.js} +1 -1
  82. package/dist/chunks/{direct-engine-BYEscsGg.js → direct-engine-Dv_6v4sx.js} +1 -1
  83. package/dist/chunks/{html-B__1Vr_C.js → html-BokjxlLb.js} +1 -1
  84. package/dist/chunks/{line-DzLRZVEq.js → line-Bqh6atHH.js} +1 -1
  85. package/dist/chunks/{lrc-kf-TilFB.js → lrc-T5e1svZG.js} +1 -1
  86. package/dist/chunks/{markdown-xIo-vnKK.js → markdown-BpWokN1s.js} +1 -1
  87. package/dist/chunks/{patch-BEaX-xYV.js → patch-BYVX5C9G.js} +1 -1
  88. package/dist/chunks/{worker-engine-FCdIQLzN.js → worker-engine-CtUAeI4G.js} +1 -1
  89. package/dist/core/hooks/queries/settings.d.ts +6 -0
  90. package/dist/core/hooks/queries/settings.d.ts.map +1 -1
  91. package/dist/core/hooks/queries/settings.js +34 -25
  92. package/dist/core/hooks/queries/settings.js.map +1 -1
  93. package/dist/core/hooks/useAuth.d.ts +2 -0
  94. package/dist/core/hooks/useAuth.d.ts.map +1 -1
  95. package/dist/core/hooks/useAuth.js.map +1 -1
  96. package/dist/core/index.js +7 -7
  97. package/dist/core/lib/go-auth-api.d.ts +1 -1
  98. package/dist/core/lib/go-auth-api.d.ts.map +1 -1
  99. package/dist/core/lib/go-auth-api.js +12 -8
  100. package/dist/core/lib/go-auth-api.js.map +1 -1
  101. package/dist/core/lib/native-operations.d.ts +85 -4
  102. package/dist/core/lib/native-operations.d.ts.map +1 -1
  103. package/dist/core/lib/native-operations.js +1 -0
  104. package/dist/core/lib/native-operations.js.map +1 -1
  105. package/dist/core/providers/GoAuthProvider.d.ts.map +1 -1
  106. package/dist/core/providers/GoAuthProvider.js +191 -142
  107. package/dist/core/providers/GoAuthProvider.js.map +1 -1
  108. package/dist/core/session-renewal.d.ts +15 -0
  109. package/dist/core/session-renewal.d.ts.map +1 -0
  110. package/dist/core/session-renewal.js +95 -0
  111. package/dist/core/session-renewal.js.map +1 -0
  112. package/dist/core/session-transition.d.ts +2 -0
  113. package/dist/core/session-transition.d.ts.map +1 -1
  114. package/dist/core/session-transition.js +20 -7
  115. package/dist/core/session-transition.js.map +1 -1
  116. package/dist/core/session.d.ts +4 -0
  117. package/dist/core/session.d.ts.map +1 -1
  118. package/dist/core/session.js +88 -61
  119. package/dist/core/session.js.map +1 -1
  120. package/dist/index.js +1 -1
  121. package/dist/{src-C8_bzBi4.js → src-D6UlLiVN.js} +2 -2
  122. package/dist/{src-C8_bzBi4.js.map → src-D6UlLiVN.js.map} +1 -1
  123. package/package.json +9 -9
  124. package/dist/chunks/ApiTokensPage-DiRMgViD.js +0 -2
  125. package/dist/chunks/ApiTokensPage-DiRMgViD.js.map +0 -1
  126. package/dist/chunks/EntityContextRuntime-BOJySc1D.js +0 -1
  127. package/dist/chunks/IdentitySecurityPage-DW5ybVL4.js +0 -9
  128. package/dist/chunks/IdentitySecurityPage-DW5ybVL4.js.map +0 -1
  129. package/dist/chunks/SettingModuleDetail-Dppk9An1.js +0 -17
  130. package/dist/chunks/SettingModuleDetail-Dppk9An1.js.map +0 -1
@@ -0,0 +1,2 @@
1
+ import{n as e}from"./rolldown-runtime-Bruge11p.js";import{E as t,It as n,M as r,O as i,R as a,Rt as o,T as s,U as c,f as l,m as u,r as d,t as f,vt as p,yt as m,zt as h}from"./clipboard-dpqHdCyy.js";import{i as g,n as _}from"./feedback-B1UL2ETz.js";import{n as v,t as ee}from"./circle-check-big-BacE3WpZ.js";import{n as y,t as b}from"./plus-C_Qg8uc3.js";import{n as te,t as x}from"./useCrudOperationColumn-CPAzNGXp.js";import{n as ne}from"./listTableProps-BAghXGb4.js";import{i as S,n as C,r as w}from"./table-columns-CvT6OHd2.js";import{a as T,o as re,r as E,t as D}from"./EditFormModal-DVQksS9R.js";import{n as O,t as k}from"./ConfigurableTable-8sYmeul2.js";import{useEffect as A,useState as j}from"react";import{Fragment as M,jsx as N,jsxs as P}from"react/jsx-runtime";import{abortSubmit as F}from"@fudanda/admin-antd/core/lib/abort-submit";import{useLocation as I}from"react-router-dom";import{usePagination as L}from"@fudanda/admin-antd/core/hooks/usePagination";import{useAuth as R}from"@fudanda/admin-antd/core/hooks/useAuth";import{TOKEN_PERMISSION_KIND_LABELS as z,tokenPermissionGroups as B,tokenPermissionPreset as V,tokenPermissionPreview as H,useApiKeyPermissions as U,useApiTokenDetail as W,useApiTokenSecret as G,useDeleteApiToken as K,useProfileApiTokens as q,useSaveApiToken as J}from"@fudanda/admin-antd/core/hooks/queries/profile";function Y({permissions:e}){let t=H(e);return/* @__PURE__ */ P(`div`,{className:`token-permission-preview`,children:[/* @__PURE__ */ P(`p`,{role:`status`,children:[`已选 `,new Set(e).size,` 项权限 · 内置 MCP 工具 `,t.tools.length,` 项 · 已知 API 接口 `,t.operations.length,` 项`]}),/* @__PURE__ */ N(`p`,{children:`实际访问仍受账号当前权限、数据范围和宿主已开放接口限制。这些权限也可用于普通 API,MCP 查询预设不限制 API Key 的接入方式。`}),t.tools.length>0&&/* @__PURE__ */ N(`div`,{className:`token-permission-tools`,children:t.tools.map(e=>/* @__PURE__ */ P(i,{children:[e.label,` `,/* @__PURE__ */ N(`code`,{children:e.name})]},e.name))}),t.operations.length>0&&/* @__PURE__ */ P(`details`,{children:[/* @__PURE__ */ N(`summary`,{children:`查看已知 API 接口`}),/* @__PURE__ */ N(`ul`,{children:t.operations.map(e=>/* @__PURE__ */ N(`li`,{children:/* @__PURE__ */ P(`code`,{children:[e.method,` `,e.path]})},e.id))})]}),t.extensions.length>0&&/* @__PURE__ */ P(`p`,{children:[`扩展权限的具体能力请核对宿主说明:`,t.extensions.join(`、`),`。`]})]})}function ie({permissions:e}){return/* @__PURE__ */ P(M,{children:[B(e).map(e=>/* @__PURE__ */ P(`section`,{className:`token-permission-group`,children:[/* @__PURE__ */ N(`h4`,{children:e.label}),e.items.map(e=>/* @__PURE__ */ P(`div`,{className:`token-permission-row`,children:[/* @__PURE__ */ P(`span`,{className:`token-permission-label`,children:[e.label,/* @__PURE__ */ N(`code`,{children:e.code})]}),/* @__PURE__ */ N(i,{className:`token-permission-kind`,children:z[e.kind]})]},e.code))]},e.label)),/* @__PURE__ */ N(Y,{permissions:e})]})}function ae({permissions:e,onDetails:t}){let n=B(e);return/* @__PURE__ */ P(`div`,{className:`token-permission-summary`,children:[/* @__PURE__ */ N(`span`,{children:e.length?`${new Set(e).size} 项 · ${n.slice(0,3).map(e=>e.label).join(`、`)}${n.length>3?`等`:``}`:`未授予权限`}),/* @__PURE__ */ N(u,{theme:`borderless`,size:`small`,onClick:t,children:`查看范围`})]})}function oe({value:e=[],onChange:t,permissions:n,disabled:r}){let[a,c]=j(``),d=B(n,a),f=new Set(e),p=e=>t?.(V(n,e)),m=(n,r)=>t?.(r?[.../* @__PURE__ */ new Set([...e,n])]:e.filter(e=>e!==n));return/* @__PURE__ */ P(`div`,{className:`token-permission-picker`,children:[/* @__PURE__ */ P(s,{wrap:!0,children:[/* @__PURE__ */ N(u,{size:`small`,disabled:r||!V(n,`mcp`).length,onClick:()=>p(`mcp`),children:`MCP 查询`}),/* @__PURE__ */ N(u,{size:`small`,disabled:r||!V(n,`read`).length,onClick:()=>p(`read`),children:`API 只读`}),/* @__PURE__ */ N(u,{size:`small`,disabled:r||!e.length,onClick:()=>t?.([]),children:`清空选择`})]}),/* @__PURE__ */ N(`p`,{className:`token-permission-hint`,children:`快捷选择会替换当前勾选;也可逐项自定义。只读按已知接口判断,未知扩展权限需手动选择。`}),/* @__PURE__ */ N(h,{"aria-label":`搜索权限`,placeholder:`搜索模块、中文名称或权限代码`,value:a,onChange:c,showClear:!0,disabled:r}),/* @__PURE__ */ P(`div`,{className:`token-permission-options`,"aria-label":`可授予权限`,children:[d.map(e=>/* @__PURE__ */ P(`fieldset`,{className:`token-permission-group`,children:[/* @__PURE__ */ N(`legend`,{children:e.label}),e.items.map(e=>/* @__PURE__ */ P(`div`,{className:`token-permission-row`,children:[/* @__PURE__ */ N(o,{disabled:r,checked:f.has(e.code),onChange:t=>m(e.code,!!t.target.checked),children:/* @__PURE__ */ P(`span`,{className:`token-permission-label`,children:[e.label,/* @__PURE__ */ N(`code`,{children:e.code})]})}),/* @__PURE__ */ N(i,{className:`token-permission-kind`,children:z[e.kind]})]},e.code))]},e.label)),!d.length&&/* @__PURE__ */ N(`p`,{children:n.length?`没有匹配的权限,已选项仍然保留。`:`当前没有可授予的权限。`})]}),e.some(e=>!n.includes(e))&&/* @__PURE__ */ N(l,{type:`warning`,description:`部分已选权限当前不可授予,请清空并重新选择。`}),/* @__PURE__ */ N(Y,{permissions:e})]})}var X;function Z(){return(Z=e((()=>{r(),X=c(oe)})))()}function se(){let{user:e}=R(),n=e.id,r=I().pathname===`/system/api-tokens`,[i,o]=j(null),s=G(n,r),c=s.value,[d,m]=j(!1),h=q(r),v=L({resetKey:n}),y=U(r),x=J(n,r),S=K(),T=re({save:{mutateAsync:({id:e,values:t})=>x.mutateAsync({id:e,values:t}),isPending:x.isPending},useDetail:W,toValues:e=>({name:e.name,expiresAt:`expiresAt`in e?e.expiresAt:void 0,permissions:`permissions`in e?e.permissions:[]}),beforeSave:e=>{let t=e.name.trim();return t||(g.error(`请填写 API Key 名称`),F(`validation`)),e.permissions?.length||(g.error(`请选择 API Key 权限`),F(`validation`)),{name:t,...e.expiresAt?{expiresAt:new Date(e.expiresAt).toISOString()}:{},permissions:e.permissions}},defaults:{name:``,permissions:[]},successMessage:({isEdit:e})=>e?`API Key 已更新`:null,onSaved:e=>{e&&`token`in e&&(m(!1),s.showCreated(e))}}),E=T.close;A(()=>{E(),o(null),m(!1)},[r,n,E]);async function O(e){await S.mutateAsync({params:{id:e}}),g.success(`API Key 已撤销`)}function M(e){f(e).then(e=>{e?(m(!0),setTimeout(()=>m(!1),2e3)):g.error(`复制失败,请手动复制`)})}let z=te({edit:e=>T.openEdit(e),remove:e=>O(e.id),title:`确定要撤销该 API Key 吗?`,content:`撤销后将无法恢复,使用该 API Key 的调用将立即失效。`,successMessage:null,removeLabel:`撤销`,width:200,extra:e=>[{key:`view`,label:`查看 API Key`,disabled:!e.canReveal,onClick:()=>{m(!1),s.reveal(e.id)}}]});return/* @__PURE__ */ P(`div`,{className:`page-container page-container--stretch`,children:[/* @__PURE__ */ P(Q,{type:`tertiary`,size:`small`,style:{display:`block`},children:[`API Key 可通过 `,/* @__PURE__ */ N(`code`,{children:`Authorization: Bearer <API_KEY>`}),` 头访问 API,每人最多 20 个。`]}),/* @__PURE__ */ N(k,{...ne(h,{pagination:v.buildPagination}),headerTitle:`API Key`,toolBarRender:()=>[/* @__PURE__ */ N(u,{type:`primary`,icon:/* @__PURE__ */ N(b,{size:14}),onClick:T.openCreate,children:`新建 API Key`},`create`)],columns:[{title:`名称`,dataIndex:`name`,minWidth:150,render:e=>/* @__PURE__ */ N(Q,{strong:!0,children:e})},{title:`权限范围`,dataIndex:`permissions`,width:260,render:(e,t)=>/* @__PURE__ */ N(ae,{permissions:e,onDetails:()=>o(t)})},{title:`API Key 前缀`,dataIndex:`tokenPrefix`,width:180,render:(e,t)=>/* @__PURE__ */ P(`div`,{children:[/* @__PURE__ */ N(`code`,{style:{fontSize:12},children:e}),!t.canReveal&&/* @__PURE__ */ N(`div`,{children:/* @__PURE__ */ N(Q,{type:`tertiary`,size:`small`,children:`仅存摘要,无法查看原文`})})]})},w(`最后使用`,`lastUsedAt`,{empty:`未使用`}),w(`过期时间`,`expiresAt`,{empty:`永久有效`}),C,z]}),r&&/* @__PURE__ */ P(D,{modal:T,title:T.isEdit?`编辑 API Key`:`新建 API Key`,okText:T.isEdit?`保存`:`创建`,cancelText:`取消`,width:740,centered:!0,formProps:{labelPosition:`top`},okButtonProps:{...T.modalProps.okButtonProps,disabled:T.detailLoading||y.isPending||!!y.error},children:[/* @__PURE__ */ N(a.Input,{field:`name`,maxLength:64,label:`名称`,placeholder:`如:本地开发、CI/CD 环境`,rules:[{required:!0,message:`请填写 API Key 名称`}],style:{width:`100%`}}),y.error&&/* @__PURE__ */ N(l,{type:`danger`,description:/* @__PURE__ */ P(`span`,{children:[`权限范围加载失败。`,/* @__PURE__ */ N(u,{theme:`borderless`,onClick:()=>void y.refetch(),children:`重试`})]})}),/* @__PURE__ */ N(X,{field:`permissions`,label:`权限范围`,permissions:y.data??[],disabled:y.isPending||!!y.error,rules:[{validator:(e,t)=>Array.isArray(t)&&t.length>0,message:`请选择至少一项权限`}],extraText:`API Key 权限不会超过账号当前权限;权限撤销、停用和改密后立即失效。`}),/* @__PURE__ */ N(a.DatePicker,{field:`expiresAt`,label:`过期时间`,type:`dateTime`,placeholder:`不填则永久有效`,style:{width:`100%`},disabledDate:e=>!!e&&e<new Date((/* @__PURE__ */ new Date()).setHours(0,0,0,0))})]}),/* @__PURE__ */ N(_,{title:i?`API Key 权限范围 · ${i.name}`:`API Key 权限范围`,visible:r&&!!i,onCancel:()=>o(null),footer:/* @__PURE__ */ N(u,{onClick:()=>o(null),children:`关闭`}),width:740,centered:!0,children:i&&/* @__PURE__ */ N(ie,{permissions:i.permissions})}),/* @__PURE__ */ P(_,{title:s.created?`API Key 创建成功`:`查看 API Key`,visible:r&&(!!c||s.pending),closeOnEsc:!0,onCancel:s.close,footer:/* @__PURE__ */ N(u,{type:`primary`,onClick:s.close,children:`关闭`}),width:520,centered:!0,children:[/* @__PURE__ */ N(Q,{type:`warning`,style:{display:`block`,marginBottom:12,padding:`8px 12px`,background:`var(--arc-antd-color-warning-light-default)`,borderRadius:`var(--arc-antd-border-radius-medium)`},children:c?.canReveal?`请妥善保管此 API Key,可在列表中再次查看或复制。`:`请立即复制并安全保存此 API Key,关闭后将无法再次查看完整内容。`}),s.pending&&/* @__PURE__ */ N(t,{}),c&&/* @__PURE__ */ P(`div`,{className:`token-display`,children:[/* @__PURE__ */ N(`code`,{style:{flex:1,wordBreak:`break-all`,fontSize:12,lineHeight:1.6},children:c.token}),/* @__PURE__ */ N(u,{icon:N(d?ee:p,{size:14}),type:d?`tertiary`:`primary`,onClick:()=>M(c.token),style:{flexShrink:0},children:d?`已复制`:`复制`})]})]})]})}var Q;function $(){return($=e((()=>{y(),m(),v(),r(),O(),E(),x(),T(),d(),S(),Z(),{Text:Q}=n})))()}$();export{se as default};
2
+ //# sourceMappingURL=ApiTokensPage-w3JGRNQC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiTokensPage-w3JGRNQC.js","mappings":"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","names":["TokenPermissionPreview","preview","tokenPermissionPreview","permissions","Tag","tool","operation","TokenPermissionDetails","_Fragment","tokenPermissionGroups","group","item","TOKEN_PERMISSION_KIND_LABELS","TokenPermissionSummary","groups","Button","onDetails","TokenPermissionPicker","keyword","setKeyword","useState","selected","value","selectPreset","onChange","tokenPermissionPreset","preset","toggle","checked","code","Space","disabled","Input","Checkbox","event","Banner","withField","ApiTokensPage","useAuth","ownerId","user","active","useLocation","scopeToken","setScopeToken","tokenSecret","useApiTokenSecret","createdToken","tokenCopied","setTokenCopied","apiTokensQuery","useProfileApiTokens","tokenPagination","usePagination","keyPermissionsQuery","useApiKeyPermissions","saveTokenMutation","useSaveApiToken","deleteTokenMutation","useDeleteApiToken","tokenModal","useEditModal","useApiTokenDetail","record","name","values","Toast","abortSubmit","isEdit","saved","closeEditor","useEffect","handleDeleteToken","copyToken","copyText","token","ok","tokenOperationColumn","useCrudOperationColumn","Text","ConfigurableTable","listTableProps","Plus","v","dateTimeColumn","createdAtColumn","EditFormModal","Form","FormTokenPermissionPicker","date","Modal","Spin","jsx","CheckCircle","Copy","Typography"],"ignoreList":[],"sources":["../../src/pages/system/api-tokens/TokenPermissionPicker.tsx","../../src/pages/system/api-tokens/ApiTokensPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Banner, Button, Checkbox, Input, Space, Tag, withField } from '@/ui';\nimport {\n tokenPermissionGroups, tokenPermissionPreset,\n tokenPermissionPreview, TOKEN_PERMISSION_KIND_LABELS,\n} from '@fudanda/react-core/hooks/queries/profile';\n\ninterface PickerProps {\n value?: string[];\n onChange?: (value: string[]) => void;\n permissions: readonly string[];\n disabled?: boolean;\n}\n\nexport function TokenPermissionPreview({ permissions }: { readonly permissions: readonly string[] }) {\n const preview = tokenPermissionPreview(permissions);\n return <div className=\"token-permission-preview\">\n <p role=\"status\">已选 {new Set(permissions).size} 项权限 · 内置 MCP 工具 {preview.tools.length} 项 · 已知 API 接口 {preview.operations.length} 项</p>\n <p>实际访问仍受账号当前权限、数据范围和宿主已开放接口限制。这些权限也可用于普通 API,MCP 查询预设不限制 API Key 的接入方式。</p>\n {preview.tools.length > 0 && <div className=\"token-permission-tools\">{preview.tools.map(tool => <Tag key={tool.name}>{tool.label} <code>{tool.name}</code></Tag>)}</div>}\n {preview.operations.length > 0 && <details><summary>查看已知 API 接口</summary><ul>{preview.operations.map(operation => <li key={operation.id}><code>{operation.method} {operation.path}</code></li>)}</ul></details>}\n {preview.extensions.length > 0 && <p>扩展权限的具体能力请核对宿主说明:{preview.extensions.join('、')}。</p>}\n </div>;\n}\n\nexport function TokenPermissionDetails({ permissions }: { readonly permissions: readonly string[] }) {\n return <>\n {tokenPermissionGroups(permissions).map(group => <section className=\"token-permission-group\" key={group.label}>\n <h4>{group.label}</h4>\n {group.items.map(item => <div className=\"token-permission-row\" key={item.code}>\n <span className=\"token-permission-label\">{item.label}<code>{item.code}</code></span>\n <Tag className=\"token-permission-kind\">{TOKEN_PERMISSION_KIND_LABELS[item.kind]}</Tag>\n </div>)}\n </section>)}\n <TokenPermissionPreview permissions={permissions}/>\n </>;\n}\n\nexport function TokenPermissionSummary({ permissions, onDetails }: {\n readonly permissions: readonly string[];\n readonly onDetails: () => void;\n}) {\n const groups = tokenPermissionGroups(permissions);\n return <div className=\"token-permission-summary\">\n <span>{permissions.length ? `${new Set(permissions).size} 项 · ${groups.slice(0, 3).map(group => group.label).join('、')}${groups.length > 3 ? '等' : ''}` : '未授予权限'}</span>\n <Button theme=\"borderless\" size=\"small\" onClick={onDetails}>查看范围</Button>\n </div>;\n}\n\nexport function TokenPermissionPicker({ value = [], onChange, permissions, disabled }: Readonly<PickerProps>) {\n const [keyword, setKeyword] = useState('');\n const groups = tokenPermissionGroups(permissions, keyword);\n const selected = new Set(value);\n const selectPreset = (preset: 'mcp' | 'read') => onChange?.(tokenPermissionPreset(permissions, preset));\n const toggle = (code: string, checked: boolean) => onChange?.(checked ? [...new Set([...value, code])] : value.filter(item => item !== code));\n return <div className=\"token-permission-picker\">\n <Space wrap>\n <Button size=\"small\" disabled={disabled || !tokenPermissionPreset(permissions, 'mcp').length} onClick={() => selectPreset('mcp')}>MCP 查询</Button>\n <Button size=\"small\" disabled={disabled || !tokenPermissionPreset(permissions, 'read').length} onClick={() => selectPreset('read')}>API 只读</Button>\n <Button size=\"small\" disabled={disabled || !value.length} onClick={() => onChange?.([])}>清空选择</Button>\n </Space>\n <p className=\"token-permission-hint\">快捷选择会替换当前勾选;也可逐项自定义。只读按已知接口判断,未知扩展权限需手动选择。</p>\n <Input aria-label=\"搜索权限\" placeholder=\"搜索模块、中文名称或权限代码\" value={keyword} onChange={setKeyword} showClear disabled={disabled}/>\n <div className=\"token-permission-options\" aria-label=\"可授予权限\">\n {groups.map(group => <fieldset className=\"token-permission-group\" key={group.label}>\n <legend>{group.label}</legend>\n {group.items.map(item => <div className=\"token-permission-row\" key={item.code}>\n <Checkbox disabled={disabled} checked={selected.has(item.code)} onChange={event => toggle(item.code, Boolean(event.target.checked))}>\n <span className=\"token-permission-label\">{item.label}<code>{item.code}</code></span>\n </Checkbox>\n <Tag className=\"token-permission-kind\">{TOKEN_PERMISSION_KIND_LABELS[item.kind]}</Tag>\n </div>)}\n </fieldset>)}\n {!groups.length && <p>{permissions.length ? '没有匹配的权限,已选项仍然保留。' : '当前没有可授予的权限。'}</p>}\n </div>\n {value.some(code => !permissions.includes(code)) && <Banner type=\"warning\" description=\"部分已选权限当前不可授予,请清空并重新选择。\"/>}\n <TokenPermissionPreview permissions={value}/>\n </div>;\n}\n\nexport const FormTokenPermissionPicker = withField(TokenPermissionPicker);\n","import { useEffect, useState } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { Plus, Copy, CheckCircle } from 'lucide-react';\nimport type { UserApiToken, UserApiTokenCreated } from '@fudanda/shared/identity';\nimport { useAuth } from '@fudanda/react-core/hooks/useAuth';\nimport { usePagination } from '@fudanda/react-core/hooks/usePagination';\nimport { abortSubmit } from '@fudanda/react-core/lib/abort-submit';\nimport { useSaveApiToken, useApiTokenDetail, useApiTokenSecret, useDeleteApiToken, useProfileApiTokens, useApiKeyPermissions } from '@fudanda/react-core/hooks/queries/profile';\nimport { Form, Button, Typography, Toast, Spin, Modal, Banner } from '@/ui';\nimport ConfigurableTable from '@/components/ConfigurableTable';\nimport { EditFormModal } from '@/components/EditFormModal';\nimport { listTableProps, useCrudOperationColumn } from '@/components/list-page';\nimport { useEditModal } from '@/hooks/useEditModal';\nimport { copyText } from '@/utils/clipboard';\nimport { createdAtColumn, dateTimeColumn } from '@/utils/table-columns';\nimport { FormTokenPermissionPicker, TokenPermissionDetails, TokenPermissionSummary } from './TokenPermissionPicker';\nimport './ApiTokensPage.css';\n\nconst { Text } = Typography;\n\nexport default function ApiTokensPage() {\n const { user } = useAuth();\n const ownerId = user!.id;\n const active = useLocation().pathname === '/system/api-tokens';\n const [scopeToken, setScopeToken] = useState<UserApiToken | null>(null);\n const tokenSecret = useApiTokenSecret(ownerId, active);\n const createdToken = tokenSecret.value;\n const [tokenCopied, setTokenCopied] = useState(false);\n const apiTokensQuery = useProfileApiTokens(active);\n const tokenPagination = usePagination({ resetKey: ownerId });\n const keyPermissionsQuery = useApiKeyPermissions(active);\n const saveTokenMutation = useSaveApiToken(ownerId, active);\n const deleteTokenMutation = useDeleteApiToken();\n // Secret responses stay in the open dialog, outside shared query caches.\n const tokenModal = useEditModal<UserApiToken | UserApiTokenCreated, {\n name: string;\n expiresAt?: Date | string | null;\n permissions?: string[];\n }, {\n name: string;\n expiresAt?: string;\n permissions: string[];\n }>({\n save: {\n mutateAsync: ({ id, values }) => saveTokenMutation.mutateAsync({ id, values }),\n isPending: saveTokenMutation.isPending,\n },\n useDetail: useApiTokenDetail,\n toValues: (record) => ({ name: record.name, expiresAt: 'expiresAt' in record ? record.expiresAt : undefined, permissions: 'permissions' in record ? record.permissions : [] }),\n beforeSave: (values) => {\n const name = values.name.trim();\n if (!name) {\n Toast.error('请填写 API Key 名称');\n abortSubmit('validation');\n }\n if (!values.permissions?.length) {\n Toast.error('请选择 API Key 权限');\n abortSubmit('validation');\n }\n return { name, ...(values.expiresAt ? { expiresAt: new Date(values.expiresAt).toISOString() } : {}), ...({ permissions: values.permissions }) };\n },\n defaults: { name: '', permissions: [] },\n successMessage: ({ isEdit }) => isEdit ? 'API Key 已更新' : null,\n onSaved: (saved) => { if (saved && 'token' in saved) { setTokenCopied(false); tokenSecret.showCreated(saved); } },\n });\n const closeEditor = tokenModal.close;\n useEffect(() => {\n closeEditor();\n setScopeToken(null);\n setTokenCopied(false);\n }, [active, ownerId, closeEditor]);\n async function handleDeleteToken(id: number) {\n await deleteTokenMutation.mutateAsync({ params: { id } });\n Toast.success('API Key 已撤销');\n }\n function copyToken(token: string) {\n void copyText(token).then((ok) => {\n if (!ok) {\n Toast.error('复制失败,请手动复制');\n return;\n }\n setTokenCopied(true);\n setTimeout(() => setTokenCopied(false), 2000);\n });\n }\n const tokenOperationColumn = useCrudOperationColumn<UserApiToken>({\n edit: (record) => tokenModal.openEdit(record),\n remove: (record) => handleDeleteToken(record.id),\n title: '确定要撤销该 API Key 吗?',\n content: '撤销后将无法恢复,使用该 API Key 的调用将立即失效。',\n successMessage: null,\n removeLabel: '撤销',\n width: 200,\n extra: (record) => [{ key: 'view', label: '查看 API Key', disabled: !record.canReveal,\n onClick: () => { setTokenCopied(false); void tokenSecret.reveal(record.id); } }],\n });\n return <div className=\"page-container page-container--stretch\">\n <Text type=\"tertiary\" size=\"small\" style={{ display: 'block' }}>\n API Key 可通过 <code>{'Authorization: Bearer <API_KEY>'}</code> 头访问 API,每人最多 20 个。\n </Text>\n <ConfigurableTable<UserApiToken> {...listTableProps(apiTokensQuery, { pagination: tokenPagination.buildPagination })}\n headerTitle=\"API Key\"\n toolBarRender={() => [<Button key=\"create\" type=\"primary\" icon={<Plus size={14}/>} onClick={tokenModal.openCreate}>新建 API Key</Button>]}\n columns={[\n { title: '名称', dataIndex: 'name', minWidth: 150, render: (v: string) => <Text strong>{v}</Text> },\n { title: '权限范围', dataIndex: 'permissions', width: 260, render: (permissions: string[], token: UserApiToken) => <TokenPermissionSummary permissions={permissions} onDetails={() => setScopeToken(token)}/> },\n { title: 'API Key 前缀', dataIndex: 'tokenPrefix', width: 180, render: (v: string, record: UserApiToken) => <div><code style={{ fontSize: 12 }}>{v}</code>{!record.canReveal && <div><Text type=\"tertiary\" size=\"small\">仅存摘要,无法查看原文</Text></div>}</div> },\n dateTimeColumn<NonNullable<typeof apiTokensQuery.data>[number]>('最后使用', 'lastUsedAt', { empty: '未使用' }),\n dateTimeColumn<NonNullable<typeof apiTokensQuery.data>[number]>('过期时间', 'expiresAt', { empty: '永久有效' }),\n createdAtColumn,\n tokenOperationColumn,\n ]}/>\n {/* ── 新建 API Key Modal ──────────────────────────────────────────────────────────────── */}\n {active && <EditFormModal modal={tokenModal} title={tokenModal.isEdit ? '编辑 API Key' : '新建 API Key'} okText={tokenModal.isEdit ? '保存' : '创建'} cancelText=\"取消\" width={740} centered formProps={{ labelPosition: 'top' }} okButtonProps={{ ...tokenModal.modalProps.okButtonProps, disabled: tokenModal.detailLoading || keyPermissionsQuery.isPending || Boolean(keyPermissionsQuery.error) }}>\n <Form.Input field=\"name\" maxLength={64} label=\"名称\" placeholder=\"如:本地开发、CI/CD 环境\" rules={[{ required: true, message: '请填写 API Key 名称' }]} style={{ width: '100%' }}/>\n {keyPermissionsQuery.error && <Banner type=\"danger\" description={<span>权限范围加载失败。<Button theme=\"borderless\" onClick={() => void keyPermissionsQuery.refetch()}>重试</Button></span>}/>}\n <FormTokenPermissionPicker field=\"permissions\" label=\"权限范围\" permissions={keyPermissionsQuery.data ?? []} disabled={keyPermissionsQuery.isPending || Boolean(keyPermissionsQuery.error)} rules={[{ validator: (_rule, value) => Array.isArray(value) && value.length > 0, message: '请选择至少一项权限' }]} extraText=\"API Key 权限不会超过账号当前权限;权限撤销、停用和改密后立即失效。\"/>\n <Form.DatePicker field=\"expiresAt\" label=\"过期时间\" type=\"dateTime\" placeholder=\"不填则永久有效\" style={{ width: '100%' }} disabledDate={(date) => !!date && date < new Date(new Date().setHours(0, 0, 0, 0))}/>\n </EditFormModal>}\n\n <Modal title={scopeToken ? `API Key 权限范围 · ${scopeToken.name}` : 'API Key 权限范围'} visible={active && !!scopeToken} onCancel={() => setScopeToken(null)} footer={<Button onClick={() => setScopeToken(null)}>关闭</Button>} width={740} centered>\n {scopeToken && <TokenPermissionDetails permissions={scopeToken.permissions}/>}\n </Modal>\n\n {/* ── 创建成功展示完整 API Key ──────────────────────────────────────────── */}\n <Modal title={tokenSecret.created ? 'API Key 创建成功' : '查看 API Key'} visible={active && (!!createdToken || tokenSecret.pending)} closeOnEsc onCancel={tokenSecret.close} footer={<Button type=\"primary\" onClick={tokenSecret.close}>关闭</Button>} width={520} centered>\n <Text type=\"warning\" style={{ display: 'block', marginBottom: 12, padding: '8px 12px', background: 'var(--arc-antd-color-warning-light-default)', borderRadius: 'var(--arc-antd-border-radius-medium)' }}>\n {createdToken?.canReveal ? '请妥善保管此 API Key,可在列表中再次查看或复制。' : '请立即复制并安全保存此 API Key,关闭后将无法再次查看完整内容。'}\n </Text>\n {tokenSecret.pending && <Spin />}\n {createdToken && (<div className=\"token-display\">\n <code style={{ flex: 1, wordBreak: 'break-all', fontSize: 12, lineHeight: 1.6 }}>{createdToken.token}</code>\n <Button icon={tokenCopied ? <CheckCircle size={14}/> : <Copy size={14}/>} type={tokenCopied ? 'tertiary' : 'primary'} onClick={() => copyToken(createdToken.token)} style={{ flexShrink: 0 }}>\n {tokenCopied ? '已复制' : '复制'}\n </Button>\n </div>)}\n </Modal>\n </div>;\n}\n"]}