@fudanda/admin-antd 2.20261109.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 (97) 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-CfQx7jWq.js → App-nh6_qOo8.js} +5 -5
  4. package/dist/chunks/{App-CfQx7jWq.js.map → App-nh6_qOo8.js.map} +1 -1
  5. package/dist/chunks/{AppModal-CVoUC2t3.js → AppModal-CEouaU03.js} +2 -2
  6. package/dist/chunks/{AppModal-CVoUC2t3.js.map → AppModal-CEouaU03.js.map} +1 -1
  7. package/dist/chunks/{ArcBaseAdmin-DQyddbFC.js → ArcBaseAdmin-CX7fQz4x.js} +2 -2
  8. package/dist/chunks/{ArcBaseAdmin-DQyddbFC.js.map → ArcBaseAdmin-CX7fQz4x.js.map} +1 -1
  9. package/dist/chunks/{DepartmentsPage-CQx53QGE.js → DepartmentsPage-BdD9VfDI.js} +2 -2
  10. package/dist/chunks/{DepartmentsPage-CQx53QGE.js.map → DepartmentsPage-BdD9VfDI.js.map} +1 -1
  11. package/dist/chunks/{DictsPage-BGnamkWk.js → DictsPage-fxBdV1-3.js} +2 -2
  12. package/dist/chunks/{DictsPage-BGnamkWk.js.map → DictsPage-fxBdV1-3.js.map} +1 -1
  13. package/dist/chunks/{EntityContextRuntime-CbzeMNXR.js → EntityContextRuntime-CMhoj6qe.js} +2 -2
  14. package/dist/chunks/{EntityContextRuntime-CbzeMNXR.js.map → EntityContextRuntime-CMhoj6qe.js.map} +1 -1
  15. package/dist/chunks/EntityContextRuntime-Dc89ZSnM.js +1 -0
  16. package/dist/chunks/{ExportButton-sMPAV2hd.js → ExportButton-DGxB2tcu.js} +2 -2
  17. package/dist/chunks/{ExportButton-sMPAV2hd.js.map → ExportButton-DGxB2tcu.js.map} +1 -1
  18. package/dist/chunks/{FileViewerPreviewPanel-Rti7pUhU.js → FileViewerPreviewPanel-BMZ7FdKV.js} +3 -3
  19. package/dist/chunks/{FileViewerPreviewPanel-Rti7pUhU.js.map → FileViewerPreviewPanel-BMZ7FdKV.js.map} +1 -1
  20. package/dist/chunks/{FilesPage-D_iYsUwl.js → FilesPage-DrgWELKy.js} +3 -3
  21. package/dist/chunks/{FilesPage-D_iYsUwl.js.map → FilesPage-DrgWELKy.js.map} +1 -1
  22. package/dist/chunks/{IdentitySecurityPage-rDYX5ksX.js → IdentitySecurityPage-BjTKvr-O.js} +2 -2
  23. package/dist/chunks/{IdentitySecurityPage-rDYX5ksX.js.map → IdentitySecurityPage-BjTKvr-O.js.map} +1 -1
  24. package/dist/chunks/{LogStatsScaffold-CMIz4z0a.js → LogStatsScaffold-DaB0JeAN.js} +2 -2
  25. package/dist/chunks/{LogStatsScaffold-CMIz4z0a.js.map → LogStatsScaffold-DaB0JeAN.js.map} +1 -1
  26. package/dist/chunks/{LoginLogsPage-Bv5pPJb2.js → LoginLogsPage-VmYC7i6q.js} +2 -2
  27. package/dist/chunks/{LoginLogsPage-Bv5pPJb2.js.map → LoginLogsPage-VmYC7i6q.js.map} +1 -1
  28. package/dist/chunks/{LoginLogsTable-DYcTx2oR.js → LoginLogsTable-CULcc_e8.js} +2 -2
  29. package/dist/chunks/{LoginLogsTable-DYcTx2oR.js.map → LoginLogsTable-CULcc_e8.js.map} +1 -1
  30. package/dist/chunks/{MarkdownPreviewPanel-lqs6AsoN.js → MarkdownPreviewPanel-CBcPc7Wv.js} +2 -2
  31. package/dist/chunks/{MarkdownPreviewPanel-lqs6AsoN.js.map → MarkdownPreviewPanel-CBcPc7Wv.js.map} +1 -1
  32. package/dist/chunks/{MasterDetailLayout-B5uqvh98.js → MasterDetailLayout-ByIBpmkZ.js} +2 -2
  33. package/dist/chunks/{MasterDetailLayout-B5uqvh98.js.map → MasterDetailLayout-ByIBpmkZ.js.map} +1 -1
  34. package/dist/chunks/{McpSettingsPage-Cdej9Evi.js → McpSettingsPage-C5V_rj2V.js} +2 -2
  35. package/dist/chunks/{McpSettingsPage-Cdej9Evi.js.map → McpSettingsPage-C5V_rj2V.js.map} +1 -1
  36. package/dist/chunks/{MemberAssignmentSheet-AKvLbbYW.js → MemberAssignmentSheet-DL0fg1Yf.js} +2 -2
  37. package/dist/chunks/{MemberAssignmentSheet-AKvLbbYW.js.map → MemberAssignmentSheet-DL0fg1Yf.js.map} +1 -1
  38. package/dist/chunks/{MenuCommandPalette-ia0pSIFg.js → MenuCommandPalette-C2PvK3Gh.js} +2 -2
  39. package/dist/chunks/{MenuCommandPalette-ia0pSIFg.js.map → MenuCommandPalette-C2PvK3Gh.js.map} +1 -1
  40. package/dist/chunks/{MenusPage-Bh55bvKH.js → MenusPage-Bytd1HlW.js} +2 -2
  41. package/dist/chunks/{MenusPage-Bh55bvKH.js.map → MenusPage-Bytd1HlW.js.map} +1 -1
  42. package/dist/chunks/{MonacoPreviewPanel-CT_sjf7Z.js → MonacoPreviewPanel-BZrNIcFZ.js} +2 -2
  43. package/dist/chunks/{MonacoPreviewPanel-CT_sjf7Z.js.map → MonacoPreviewPanel-BZrNIcFZ.js.map} +1 -1
  44. package/dist/chunks/{NavListPanel-DMIUMh7q.js → NavListPanel-zwUDIYSP.js} +2 -2
  45. package/dist/chunks/{NavListPanel-DMIUMh7q.js.map → NavListPanel-zwUDIYSP.js.map} +1 -1
  46. package/dist/chunks/{OperationLogsPage-7XVfmhxP.js → OperationLogsPage-D2BQdGNp.js} +2 -2
  47. package/dist/chunks/{OperationLogsPage-7XVfmhxP.js.map → OperationLogsPage-D2BQdGNp.js.map} +1 -1
  48. package/dist/chunks/{OperationLogsTable-gp-WZxiF.js → OperationLogsTable-DaaON4QR.js} +3 -3
  49. package/dist/chunks/{OperationLogsTable-gp-WZxiF.js.map → OperationLogsTable-DaaON4QR.js.map} +1 -1
  50. package/dist/chunks/{PDFPreviewPanel-CyfhyWav.js → PDFPreviewPanel-CMmnWBKW.js} +3 -3
  51. package/dist/chunks/{PDFPreviewPanel-CyfhyWav.js.map → PDFPreviewPanel-CMmnWBKW.js.map} +1 -1
  52. package/dist/chunks/{PositionsPage-Bwua1vNV.js → PositionsPage-CBZITssT.js} +2 -2
  53. package/dist/chunks/{PositionsPage-Bwua1vNV.js.map → PositionsPage-CBZITssT.js.map} +1 -1
  54. package/dist/chunks/{PreferencesSheetBody-C80D3dOM.js → PreferencesSheetBody-B0poTPEA.js} +2 -2
  55. package/dist/chunks/{PreferencesSheetBody-C80D3dOM.js.map → PreferencesSheetBody-B0poTPEA.js.map} +1 -1
  56. package/dist/chunks/{ProfilePage-DeTw-59a.js → ProfilePage-DLhacdWt.js} +2 -2
  57. package/dist/chunks/{ProfilePage-DeTw-59a.js.map → ProfilePage-DLhacdWt.js.map} +1 -1
  58. package/dist/chunks/{ProjectInfoPage-Bqn3gfXa.js → ProjectInfoPage-CJpGxpu5.js} +2 -2
  59. package/dist/chunks/{ProjectInfoPage-Bqn3gfXa.js.map → ProjectInfoPage-CJpGxpu5.js.map} +1 -1
  60. package/dist/chunks/{RelationPanel-Bio-ig-l.js → RelationPanel-BsbfEDo2.js} +2 -2
  61. package/dist/chunks/{RelationPanel-Bio-ig-l.js.map → RelationPanel-BsbfEDo2.js.map} +1 -1
  62. package/dist/chunks/{RolesPage-fwUSs2HR.js → RolesPage-46dzdiah.js} +2 -2
  63. package/dist/chunks/{RolesPage-fwUSs2HR.js.map → RolesPage-46dzdiah.js.map} +1 -1
  64. package/dist/chunks/{SessionConflictModal-Dw4opoNP.js → SessionConflictModal-Bm38eExL.js} +2 -2
  65. package/dist/chunks/{SessionConflictModal-Dw4opoNP.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-Cy5-q-P6.js → SettingsPage-C32Vuizm.js} +2 -2
  69. package/dist/chunks/{SettingsPage-Cy5-q-P6.js.map → SettingsPage-C32Vuizm.js.map} +1 -1
  70. package/dist/chunks/{StatCard-BROG4NSp.js → StatCard-CRPfkSBY.js} +2 -2
  71. package/dist/chunks/{StatCard-BROG4NSp.js.map → StatCard-CRPfkSBY.js.map} +1 -1
  72. package/dist/chunks/{UserGroupsPage-CsTBkUPy.js → UserGroupsPage-08G5MdGm.js} +2 -2
  73. package/dist/chunks/{UserGroupsPage-CsTBkUPy.js.map → UserGroupsPage-08G5MdGm.js.map} +1 -1
  74. package/dist/chunks/{UserLogsPanels-3u8Z93YU.js → UserLogsPanels-nbIrMym9.js} +2 -2
  75. package/dist/chunks/{UserLogsPanels-3u8Z93YU.js.map → UserLogsPanels-nbIrMym9.js.map} +1 -1
  76. package/dist/chunks/{UserTransferSelect-ChLj4EkS.js → UserTransferSelect-C8betaWG.js} +2 -2
  77. package/dist/chunks/{UserTransferSelect-ChLj4EkS.js.map → UserTransferSelect-C8betaWG.js.map} +1 -1
  78. package/dist/chunks/{UsersPage-CfNnQJi4.js → UsersPage-BjTiNEqF.js} +2 -2
  79. package/dist/chunks/{UsersPage-CfNnQJi4.js.map → UsersPage-BjTiNEqF.js.map} +1 -1
  80. package/dist/chunks/{browser-BKLM0ThC-D0TgzKTC.js → browser-BKLM0ThC-Cp7Gi4-F.js} +1 -1
  81. package/dist/chunks/{code-BkkeN2fd.js → code-LswxAr98.js} +1 -1
  82. package/dist/chunks/{direct-engine-m32m22nx.js → direct-engine-Dv_6v4sx.js} +1 -1
  83. package/dist/chunks/{html-BGNWR_Bp.js → html-BokjxlLb.js} +1 -1
  84. package/dist/chunks/{line-CsTeuEcK.js → line-Bqh6atHH.js} +1 -1
  85. package/dist/chunks/{lrc-D6gjnGZ5.js → lrc-T5e1svZG.js} +1 -1
  86. package/dist/chunks/{markdown-BglUe9j8.js → markdown-BpWokN1s.js} +1 -1
  87. package/dist/chunks/{patch-C97Yl3jr.js → patch-BYVX5C9G.js} +1 -1
  88. package/dist/chunks/{worker-engine-B7_3qQVS.js → worker-engine-CtUAeI4G.js} +1 -1
  89. package/dist/index.js +1 -1
  90. package/dist/{src-DAkFn9SG.js → src-D6UlLiVN.js} +2 -2
  91. package/dist/{src-DAkFn9SG.js.map → src-D6UlLiVN.js.map} +1 -1
  92. package/package.json +9 -9
  93. package/dist/chunks/ApiTokensPage-DiRMgViD.js +0 -2
  94. package/dist/chunks/ApiTokensPage-DiRMgViD.js.map +0 -1
  95. package/dist/chunks/EntityContextRuntime-C9q95WDf.js +0 -1
  96. package/dist/chunks/SettingModuleDetail-I9CSJ-fh.js +0 -17
  97. package/dist/chunks/SettingModuleDetail-I9CSJ-fh.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"RelationPanel-Bio-ig-l.js","mappings":"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","names":["__iconData","__iconData$4","createLucideIcon","__iconData$3","__iconData$2","__iconData$1","EntityRefBadge","navigate","useNavigate","location","useLocation","openEntity","useContext","EntityNavigationContext","accessKey","useEntityAccessKey","open","setOpen","useState","title","children","entityTypeLabel","entityRef","capabilities","_Fragment","Button","event","route","entityDetailRoute","beginEntityRelationNavigation","entityRelationSourceUrl","Typography","Suspense","EntityContextSheet","RelationFilters","supported","section","Space","KeywordInput","search","DateRangeFilter","Checkbox","RelationSectionHeader","label","entityRelationLabel","presentation","RELATION_SUMMARY_PRESENTATION","summaryState","statusLabel","Icon","kindPresentation","RELATION_KIND_PRESENTATION","KindIcon","kindLabel","entityRelationKindLabel","Tooltip","RelationOriginHint","kind","item","parts","formatDateTime","RelationSectionView","_canManageLinks","queryClient","useQueryClient","refreshSection","query","contractKey","entityRelationsContract","entityType","entityKey","pages","items","page","degraded","sectionError","hasResponse","useEffect","active","filtered","onSummaryStateChange","filterToggle","RefreshCw","filters","Empty","List","entityStatusLabel","Tag","DateTimeText","RelationGroupItem","useListSearch","emptyRelationSearch","useFilterQuery","formatDateTimeRangeForApi","showFilters","setShowFilters","supportsFilters","useEntityRelationSection","Collapse","Filter","value","RelationGroups","viewState","EntityRelationViewStateContext","localActiveKeys","setLocalActiveKeys","activeKeys","setActiveKeys","defaultSummaryStates","useMemo","sections","summaryStates","setSummaryStates","updateSummaryState","useCallback","previous","sectionKey","state","keys","hideEmpty","RelationPanel","useEntityRelations","enabled","access","display","Spin","showAnchor","EyeOff","CircleCheck","CircleSlash2","CircleAlert","CircleOff","Link2","GitBranch","Zap","Activity"],"ignoreList":[0,1,2,3,4],"sources":["../../../../node_modules/lucide-react/dist/esm/icons/circle-alert.mjs","../../../../node_modules/lucide-react/dist/esm/icons/circle-off.mjs","../../../../node_modules/lucide-react/dist/esm/icons/circle-slash-2.mjs","../../../../node_modules/lucide-react/dist/esm/icons/git-branch.mjs","../../../../node_modules/lucide-react/dist/esm/icons/zap.mjs","../../src/components/entity-relations/EntityRefBadge.tsx","../../src/components/entity-relations/RelationFilters.tsx","../../src/components/entity-relations/RelationPanel.tsx"],"sourcesContent":[null,null,null,null,null,"import { Suspense, useContext, useState, type ReactNode } from 'react';\nimport { Button, Typography } from \"@/ui\";\nimport type { CanonicalEntityRef } from '@fudanda/shared/platform';\nimport { entityDetailRoute, entityTypeLabel } from \"@fudanda/react-core/utils/entity-relations\";\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport { beginEntityRelationNavigation, EntityNavigationContext, entityRelationSourceUrl } from \"@fudanda/react-core/components/entity-relations/entity-navigation\";\nimport { useEntityAccessKey } from \"@fudanda/react-core/hooks/queries/entity-relations\";\nimport { EntityContextSheet } from \"@/components/entity-relations/EntityRelationButton\";\nexport default function EntityRefBadge({ entityRef, capabilities, children }: {\n readonly entityRef: CanonicalEntityRef;\n readonly capabilities: {\n view: boolean;\n open: boolean;\n };\n readonly children?: ReactNode;\n}) {\n const navigate = useNavigate();\n const location = useLocation();\n const openEntity = useContext(EntityNavigationContext);\n const accessKey = JSON.stringify(useEntityAccessKey());\n const [open, setOpen] = useState(false);\n const title = children ?? `${entityTypeLabel(entityRef.type)} #${entityRef.key}`;\n if (!capabilities.view)\n return null;\n if (!capabilities.open)\n return <Typography.Text>{title}</Typography.Text>;\n return <>\n <Button theme=\"borderless\" size=\"small\" style={{ maxWidth: '100%', paddingLeft: 0, justifyContent: 'flex-start' }} onClick={(event) => {\n event.stopPropagation();\n if (openEntity) {\n openEntity(entityRef);\n return;\n }\n const route = entityDetailRoute(entityRef);\n if (route) {\n beginEntityRelationNavigation({\n url: entityRelationSourceUrl(location), locationKey: location.key, state: location.state, kind: 'page',\n pageScrollTop: document.querySelector<HTMLElement>('.admin-content')?.scrollTop ?? 0,\n }, route, accessKey, location.pathname);\n navigate(route);\n }\n else\n setOpen(true);\n }}><Typography.Text ellipsis={{ showTooltip: true }} style={{ color: 'inherit' }}>{title}</Typography.Text></Button>\n {open && <Suspense fallback={null}><EntityContextSheet entityRef={entityRef} onClose={() => setOpen(false)}/></Suspense>}\n </>;\n}\n","import { Button, Checkbox, Space } from \"@/ui\";\nimport type { EntityRelationSection } from '@fudanda/shared/platform';\nimport { DateRangeFilter, KeywordInput } from \"@/components/search-filters\";\nimport type { UseListSearchReturn } from \"@fudanda/react-core/hooks/useListSearch\";\nexport interface RelationSearchState {\n keyword: string;\n status: string | undefined;\n range: [\n Date,\n Date\n ] | null;\n attentionOnly: boolean;\n}\nexport default function RelationFilters({ section, search }: {\n readonly section: EntityRelationSection;\n readonly search: UseListSearchReturn<RelationSearchState>;\n}) {\n const supported = section.filters;\n return <Space wrap spacing={8} style={{ padding: '4px 0 12px', width: '100%' }}>\n {supported?.keyword && <KeywordInput aria-label=\"关联记录关键词\" placeholder=\"搜索关联记录\" {...search.bindKeyword('keyword')} width={180}/>}\n {supported?.dateRange && <DateRangeFilter {...search.bind('range')}/>}\n {supported?.attentionOnly && <Checkbox checked={search.draftParams.attentionOnly} onChange={(event) => search.setField('attentionOnly')(Boolean(event.target.checked))}>仅看需处理</Checkbox>}\n <Button size=\"small\" onClick={search.handleSearch}>查询</Button>\n <Button size=\"small\" theme=\"borderless\" onClick={search.handleReset}>重置</Button>\n </Space>;\n}\n","import { useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';\nimport { Button, Collapse, Empty, List, Space, Spin, Tag, Tooltip, Typography } from \"@/ui\";\nimport type { EntityRelationItem, EntityRelationKind, EntityRelationSection, EntityRelationSummaryState, CanonicalEntityType } from '@fudanda/shared/platform';\nimport { Activity, CircleAlert, CircleCheck, CircleOff, CircleSlash2, EyeOff, Filter, GitBranch, Link2, RefreshCw, Zap } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { entityRelationsContract } from '@fudanda/react-core/lib/native-operations';\nimport { contractKey } from \"@fudanda/react-core/lib/contract-query\";\nimport { useEntityAccessKey, useEntityRelationSection, useEntityRelations } from \"@fudanda/react-core/hooks/queries/entity-relations\";\nimport { entityRelationKindLabel, entityRelationLabel, entityStatusLabel } from \"@fudanda/react-core/utils/entity-relations\";\nimport DateTimeText from \"@/components/DateTimeText\";\nimport EntityRefBadge from \"@/components/entity-relations/EntityRefBadge\";\n\nimport { EntityRelationViewStateContext } from \"@fudanda/react-core/components/entity-relations/entity-navigation\";\nimport { formatDateTime, formatDateTimeRangeForApi } from \"@fudanda/react-core/utils/date\";\nimport { useListSearch } from \"@fudanda/react-core/hooks/useListSearch\";\nimport { useFilterQuery } from \"@fudanda/react-core/hooks/useFilterQuery\";\nimport RelationFilters, { type RelationSearchState } from \"@/components/entity-relations/RelationFilters\";\nconst emptyRelationSearch = (): RelationSearchState => ({ keyword: '', status: undefined, range: null, attentionOnly: false });\nconst RELATION_SUMMARY_PRESENTATION: Record<EntityRelationSummaryState, {\n readonly label: string;\n readonly Icon: LucideIcon;\n readonly color: string;\n}> = {\n 'has-data': { label: '有记录', Icon: CircleCheck, color: 'var(--arc-antd-color-success)' },\n empty: { label: '暂无记录', Icon: CircleSlash2, color: 'var(--arc-antd-color-tertiary)' },\n attention: { label: '需处理', Icon: CircleAlert, color: 'var(--arc-antd-color-warning)' },\n unavailable: { label: '暂不可用', Icon: CircleOff, color: 'var(--arc-antd-color-danger)' },\n};\nconst RELATION_KIND_PRESENTATION: Record<EntityRelationKind, {\n readonly Icon: LucideIcon;\n readonly color: string;\n}> = {\n direct: { Icon: Link2, color: 'var(--arc-antd-color-primary)' },\n derived: { Icon: GitBranch, color: 'var(--arc-antd-color-info)' },\n causal: { Icon: Zap, color: 'var(--arc-antd-color-warning)' },\n activity: { Icon: Activity, color: 'var(--arc-antd-color-tertiary)' },\n};\nfunction RelationSectionHeader({ section, summaryState }: {\n readonly section: EntityRelationSection;\n readonly summaryState: EntityRelationSummaryState;\n}) {\n const label = entityRelationLabel(section.labelKey, section.targetTypes);\n const presentation = RELATION_SUMMARY_PRESENTATION[summaryState];\n const statusLabel = `${label}:${presentation.label}`;\n const Icon = presentation.Icon;\n const kindPresentation = RELATION_KIND_PRESENTATION[section.kind];\n const KindIcon = kindPresentation.Icon;\n const kindLabel = `关联来源:${entityRelationKindLabel(section.kind)}`;\n return <Space spacing={6}>\n <Tooltip content={statusLabel}>\n <span role=\"img\" aria-label={statusLabel} style={{ color: presentation.color, display: 'inline-flex' }}>\n <Icon size={15} aria-hidden=\"true\"/>\n </span>\n </Tooltip>\n <Tooltip content={kindLabel}>\n <span role=\"img\" aria-label={kindLabel} style={{ color: kindPresentation.color, display: 'inline-flex' }}>\n <KindIcon size={14} aria-hidden=\"true\"/>\n </span>\n </Tooltip>\n <span>{label}</span>\n </Space>;\n}\nfunction RelationOriginHint({ section, item }: {\n readonly section: EntityRelationSection;\n readonly item: EntityRelationItem;\n}) {\n const kind = item.origin?.kind ?? section.kind;\n const kindPresentation = RELATION_KIND_PRESENTATION[kind];\n const Icon = kindPresentation.Icon;\n const parts = [`关联来源:${entityRelationKindLabel(kind)}`];\n if (item.origin?.explanation)\n parts.push(item.origin.explanation);\n if (item.origin?.eventType)\n parts.push(`来源事件:${item.origin.eventType}`);\n if (item.origin?.relatedAt)\n parts.push(`关联建立时间:${formatDateTime(item.origin.relatedAt)}`);\n if (item.occurredAt)\n parts.push(`记录时间:${formatDateTime(item.occurredAt)}`);\n const label = parts.join(' · ');\n return <Tooltip content={label}>\n <span role=\"img\" aria-label={label} style={{ color: kindPresentation.color, display: 'inline-flex' }}>\n <Icon size={14} aria-hidden=\"true\"/>\n </span>\n </Tooltip>;\n}\ninterface RelationPanelProps {\n readonly entityType: CanonicalEntityType;\n readonly entityKey: string | undefined;\n readonly enabled?: boolean;\n readonly showAnchor?: boolean;\n}\ntype RelationSectionQuery = ReturnType<typeof useEntityRelationSection>;\nfunction RelationSectionView({ entityType, entityKey, section, active, canManageLinks: _canManageLinks, onSummaryStateChange, query, filtered, filters, filterToggle }: {\n readonly entityType: CanonicalEntityType;\n readonly entityKey: string;\n readonly section: EntityRelationSection;\n readonly active: boolean;\n readonly canManageLinks: boolean;\n readonly onSummaryStateChange: (sectionKey: string, state: EntityRelationSummaryState) => void;\n readonly query: RelationSectionQuery;\n readonly filtered: boolean;\n readonly filters?: ReactNode;\n readonly filterToggle?: ReactNode;\n}) {\n const queryClient = useQueryClient();\n const refreshSection = () => {\n void query.refetch();\n // Attention considers the full visible set; a page of records cannot clear it by itself.\n void queryClient.invalidateQueries({ queryKey: contractKey(entityRelationsContract.describe, { params: { type: entityType, key: entityKey } }) });\n };\n const pages = query.data?.pages ?? [];\n const items = pages.flatMap((page) => page.items).filter((item) => item.capabilities.view);\n const degraded = pages.some((page) => page.degraded);\n const sectionError = query.isError;\n const hasResponse = query.data !== undefined;\n useEffect(() => {\n if (!active || query.isFetching || filtered)\n return;\n if (sectionError || degraded) {\n onSummaryStateChange(section.key, 'unavailable');\n return;\n }\n if (!hasResponse)\n return;\n onSummaryStateChange(section.key, items.length > 0 ? (section.summaryState === 'attention' ? 'attention' : 'has-data') : query.hasNextPage ? 'unavailable' : 'empty');\n }, [active, degraded, filtered, hasResponse, items.length, onSummaryStateChange, query.hasNextPage, query.isFetching, section.key, section.summaryState, sectionError]);\n const label = entityRelationLabel(section.labelKey, section.targetTypes);\n return <div style={{ position: 'relative' }}>\n {filterToggle && <span style={{ position: 'absolute', top: 0, right: 32, zIndex: 1, lineHeight: 0 }}>{filterToggle}</span>}\n <span style={{ position: 'absolute', top: 0, right: 0, zIndex: 1, lineHeight: 0 }}>\n <Tooltip content={`刷新${label}`}>\n <Button size=\"small\" theme=\"borderless\" icon={<RefreshCw size={14}/>} loading={query.isFetching} aria-label={`刷新${label}`} onClick={(event) => { event.stopPropagation(); refreshSection(); }}/>\n </Tooltip>\n </span>\n <div style={{ paddingTop: 4, paddingRight: filterToggle ? 64 : 32 }}>\n {filters}\n {(query.isError || degraded) && <Space wrap spacing={8}>\n <Typography.Text type=\"danger\">{degraded ? '部分关联记录暂时不可用' : '关联记录加载失败'}</Typography.Text>\n <Button size=\"small\" onClick={() => void (query.isFetchNextPageError ? query.fetchNextPage() : query.refetch())}>重试</Button>\n </Space>}\n {hasResponse && !sectionError && !degraded && items.length === 0 && <Empty description={query.hasNextPage ? '继续加载以查找可见的匹配记录' : filtered ? '没有符合筛选条件的关联记录' : '暂无关联记录'}/>}\n {items.length > 0 && <List size=\"small\" split dataSource={items} renderItem={(item) => <List.Item key={`${item.ref.type}:${item.ref.key}:${item.relationKey}`} main={<div style={{ minWidth: 0 }}>\n <Space wrap spacing={8}><EntityRefBadge entityRef={item.ref} capabilities={{ view: item.capabilities.view && section.capabilities.view, open: item.capabilities.open && section.capabilities.open }}>{item.title}</EntityRefBadge>\n <RelationOriginHint section={section} item={item}/>\n {entityStatusLabel(item.status) && <Tag size=\"small\">{entityStatusLabel(item.status)}</Tag>}</Space>\n {item.subtitle && <div><Typography.Text type=\"tertiary\">{item.subtitle}</Typography.Text></div>}\n {item.description && <div><Typography.Text type=\"tertiary\">{item.description}</Typography.Text></div>}\n {item.occurredAt && <div><Typography.Text type=\"tertiary\"><DateTimeText value={item.occurredAt}/></Typography.Text></div>}\n </div>}/>}/>}\n {query.hasNextPage && <Button size=\"small\" loading={query.isFetchingNextPage} onClick={() => void query.fetchNextPage()}>加载更多</Button>}\n </div>\n </div>;\n}\nfunction RelationGroupItem({ entityType, entityKey, section, active, summaryState, canManageLinks, onSummaryStateChange }: {\n readonly entityType: CanonicalEntityType;\n readonly entityKey: string;\n readonly section: EntityRelationSection;\n readonly active: boolean;\n readonly summaryState: EntityRelationSummaryState;\n readonly canManageLinks: boolean;\n readonly onSummaryStateChange: (sectionKey: string, state: EntityRelationSummaryState) => void;\n}) {\n const search = useListSearch({ defaults: emptyRelationSearch,\n listKey: contractKey(entityRelationsContract.section, { params: { type: entityType, key: entityKey, sectionKey: section.key }, query: {} }),\n });\n const filters = useFilterQuery({ keyword: search.submittedParams.keyword, status: search.submittedParams.status,\n ...formatDateTimeRangeForApi(search.submittedParams.range), attentionOnly: search.submittedParams.attentionOnly ? true : undefined });\n const filtered = Object.keys(filters).length > 0;\n const [showFilters, setShowFilters] = useState(filtered);\n const supportsFilters = Boolean(section.filters?.keyword || section.filters?.dateRange || section.filters?.attentionOnly);\n const query = useEntityRelationSection(entityType, entityKey, section.key, active, 5, filters);\n return <Collapse.Panel key={section.key} itemKey={section.key} header={<RelationSectionHeader section={section} summaryState={summaryState}/>}>\n <RelationSectionView entityType={entityType} entityKey={entityKey} section={section} active={active} canManageLinks={canManageLinks} onSummaryStateChange={onSummaryStateChange} query={query} filtered={filtered} filters={supportsFilters && showFilters ? <RelationFilters section={section} search={search}/> : undefined} filterToggle={supportsFilters ? <Tooltip content=\"筛选关联记录\"><Button size=\"small\" theme={filtered ? 'light' : 'borderless'} aria-label=\"筛选关联记录\" aria-expanded={showFilters} icon={<Filter size={14}/>} onClick={() => setShowFilters((value) => !value)}/></Tooltip> : undefined}/>\n </Collapse.Panel>;\n}\nfunction RelationGroups({ entityType, entityKey, sections, canManageLinks, hideEmpty }: {\n readonly entityType: CanonicalEntityType;\n readonly entityKey: string;\n readonly sections: EntityRelationSection[];\n readonly canManageLinks: boolean;\n readonly hideEmpty: boolean;\n}) {\n const viewState = useContext(EntityRelationViewStateContext);\n const [localActiveKeys, setLocalActiveKeys] = useState<string[]>([]);\n const activeKeys = viewState?.expandedGroups ?? localActiveKeys;\n const setActiveKeys = viewState?.setExpandedGroups ?? setLocalActiveKeys;\n const defaultSummaryStates = useMemo(() => Object.fromEntries(sections.map((section) => [section.key, section.summaryState])), [sections]);\n const [summaryStates, setSummaryStates] = useState<Record<string, EntityRelationSummaryState>>(() => Object.fromEntries(sections.map((section) => [section.key, section.summaryState])));\n useEffect(() => {\n setSummaryStates(defaultSummaryStates);\n }, [defaultSummaryStates]);\n const updateSummaryState = useCallback((sectionKey: string, state: EntityRelationSummaryState) => {\n setSummaryStates((previous) => previous[sectionKey] === state ? previous : { ...previous, [sectionKey]: state });\n }, []);\n return <Collapse activeKey={activeKeys} onChange={(keys) => setActiveKeys(Array.isArray(keys) ? keys.map(String) : [String(keys)])}>\n {sections.filter((section) => section.capabilities.view && (!hideEmpty || (summaryStates[section.key] ?? section.summaryState) !== 'empty')).map((section) => <RelationGroupItem key={section.key} entityType={entityType} entityKey={entityKey} section={section} active={activeKeys.includes(section.key)} summaryState={summaryStates[section.key] ?? 'unavailable'} canManageLinks={canManageLinks} onSummaryStateChange={updateSummaryState}/>)}\n </Collapse>;\n}\nexport default function RelationPanel({ entityType, entityKey, enabled = true, showAnchor = false }: RelationPanelProps) {\n const query = useEntityRelations(entityType, entityKey, enabled);\n const access = useEntityAccessKey();\n const display = useListSearch({ defaults: { hideEmpty: false }, listKey: ['entity-relation-display', entityType, entityKey, access], refetchOnSearch: false });\n if (!enabled || !entityKey)\n return null;\n if (query.isLoading)\n return <Spin size=\"small\"/>;\n if (query.isError)\n return <Space wrap><Typography.Text type=\"danger\">对象不可用或关联信息加载失败</Typography.Text><Button size=\"small\" onClick={() => void query.refetch()}>重试</Button></Space>;\n const sections = query.data?.sections ?? [];\n return <div style={{ paddingTop: 12 }}>\n {showAnchor && query.data && <Typography.Title heading={6}>{query.data.anchor.title}</Typography.Title>}\n <Space spacing={8} style={{ marginBottom: 8 }}>\n {false}\n <Tooltip content={display.submittedParams.hideEmpty ? '显示空分组' : '隐藏空分组'}><Button size=\"small\" theme={display.submittedParams.hideEmpty ? 'light' : 'borderless'} aria-label=\"隐藏空分组\" aria-pressed={display.submittedParams.hideEmpty} icon={<EyeOff size={14}/>} onClick={() => display.applySearch({ hideEmpty: !display.submittedParams.hideEmpty })}/></Tooltip>\n </Space>\n {sections.length === 0 ? <Empty description=\"暂无可见关联信息\"/> : <RelationGroups key={`groups:${entityType}:${entityKey}:${JSON.stringify(access)}`} entityType={entityType} entityKey={entityKey} sections={sections} canManageLinks={query.data?.canManageLinks ?? false} hideEmpty={display.submittedParams.hideEmpty}/>}\n </div>;\n}\n"]}
1
+ {"version":3,"file":"RelationPanel-BsbfEDo2.js","mappings":"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","names":["__iconData","__iconData$4","createLucideIcon","__iconData$3","__iconData$2","__iconData$1","EntityRefBadge","navigate","useNavigate","location","useLocation","openEntity","useContext","EntityNavigationContext","accessKey","useEntityAccessKey","open","setOpen","useState","title","children","entityTypeLabel","entityRef","capabilities","_Fragment","Button","event","route","entityDetailRoute","beginEntityRelationNavigation","entityRelationSourceUrl","Typography","Suspense","EntityContextSheet","RelationFilters","supported","section","Space","KeywordInput","search","DateRangeFilter","Checkbox","RelationSectionHeader","label","entityRelationLabel","presentation","RELATION_SUMMARY_PRESENTATION","summaryState","statusLabel","Icon","kindPresentation","RELATION_KIND_PRESENTATION","KindIcon","kindLabel","entityRelationKindLabel","Tooltip","RelationOriginHint","kind","item","parts","formatDateTime","RelationSectionView","_canManageLinks","queryClient","useQueryClient","refreshSection","query","contractKey","entityRelationsContract","entityType","entityKey","pages","items","page","degraded","sectionError","hasResponse","useEffect","active","filtered","onSummaryStateChange","filterToggle","RefreshCw","filters","Empty","List","entityStatusLabel","Tag","DateTimeText","RelationGroupItem","useListSearch","emptyRelationSearch","useFilterQuery","formatDateTimeRangeForApi","showFilters","setShowFilters","supportsFilters","useEntityRelationSection","Collapse","Filter","value","RelationGroups","viewState","EntityRelationViewStateContext","localActiveKeys","setLocalActiveKeys","activeKeys","setActiveKeys","defaultSummaryStates","useMemo","sections","summaryStates","setSummaryStates","updateSummaryState","useCallback","previous","sectionKey","state","keys","hideEmpty","RelationPanel","useEntityRelations","enabled","access","display","Spin","showAnchor","EyeOff","CircleCheck","CircleSlash2","CircleAlert","CircleOff","Link2","GitBranch","Zap","Activity"],"ignoreList":[0,1,2,3,4],"sources":["../../../../node_modules/lucide-react/dist/esm/icons/circle-alert.mjs","../../../../node_modules/lucide-react/dist/esm/icons/circle-off.mjs","../../../../node_modules/lucide-react/dist/esm/icons/circle-slash-2.mjs","../../../../node_modules/lucide-react/dist/esm/icons/git-branch.mjs","../../../../node_modules/lucide-react/dist/esm/icons/zap.mjs","../../src/components/entity-relations/EntityRefBadge.tsx","../../src/components/entity-relations/RelationFilters.tsx","../../src/components/entity-relations/RelationPanel.tsx"],"sourcesContent":[null,null,null,null,null,"import { Suspense, useContext, useState, type ReactNode } from 'react';\nimport { Button, Typography } from \"@/ui\";\nimport type { CanonicalEntityRef } from '@fudanda/shared/platform';\nimport { entityDetailRoute, entityTypeLabel } from \"@fudanda/react-core/utils/entity-relations\";\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport { beginEntityRelationNavigation, EntityNavigationContext, entityRelationSourceUrl } from \"@fudanda/react-core/components/entity-relations/entity-navigation\";\nimport { useEntityAccessKey } from \"@fudanda/react-core/hooks/queries/entity-relations\";\nimport { EntityContextSheet } from \"@/components/entity-relations/EntityRelationButton\";\nexport default function EntityRefBadge({ entityRef, capabilities, children }: {\n readonly entityRef: CanonicalEntityRef;\n readonly capabilities: {\n view: boolean;\n open: boolean;\n };\n readonly children?: ReactNode;\n}) {\n const navigate = useNavigate();\n const location = useLocation();\n const openEntity = useContext(EntityNavigationContext);\n const accessKey = JSON.stringify(useEntityAccessKey());\n const [open, setOpen] = useState(false);\n const title = children ?? `${entityTypeLabel(entityRef.type)} #${entityRef.key}`;\n if (!capabilities.view)\n return null;\n if (!capabilities.open)\n return <Typography.Text>{title}</Typography.Text>;\n return <>\n <Button theme=\"borderless\" size=\"small\" style={{ maxWidth: '100%', paddingLeft: 0, justifyContent: 'flex-start' }} onClick={(event) => {\n event.stopPropagation();\n if (openEntity) {\n openEntity(entityRef);\n return;\n }\n const route = entityDetailRoute(entityRef);\n if (route) {\n beginEntityRelationNavigation({\n url: entityRelationSourceUrl(location), locationKey: location.key, state: location.state, kind: 'page',\n pageScrollTop: document.querySelector<HTMLElement>('.admin-content')?.scrollTop ?? 0,\n }, route, accessKey, location.pathname);\n navigate(route);\n }\n else\n setOpen(true);\n }}><Typography.Text ellipsis={{ showTooltip: true }} style={{ color: 'inherit' }}>{title}</Typography.Text></Button>\n {open && <Suspense fallback={null}><EntityContextSheet entityRef={entityRef} onClose={() => setOpen(false)}/></Suspense>}\n </>;\n}\n","import { Button, Checkbox, Space } from \"@/ui\";\nimport type { EntityRelationSection } from '@fudanda/shared/platform';\nimport { DateRangeFilter, KeywordInput } from \"@/components/search-filters\";\nimport type { UseListSearchReturn } from \"@fudanda/react-core/hooks/useListSearch\";\nexport interface RelationSearchState {\n keyword: string;\n status: string | undefined;\n range: [\n Date,\n Date\n ] | null;\n attentionOnly: boolean;\n}\nexport default function RelationFilters({ section, search }: {\n readonly section: EntityRelationSection;\n readonly search: UseListSearchReturn<RelationSearchState>;\n}) {\n const supported = section.filters;\n return <Space wrap spacing={8} style={{ padding: '4px 0 12px', width: '100%' }}>\n {supported?.keyword && <KeywordInput aria-label=\"关联记录关键词\" placeholder=\"搜索关联记录\" {...search.bindKeyword('keyword')} width={180}/>}\n {supported?.dateRange && <DateRangeFilter {...search.bind('range')}/>}\n {supported?.attentionOnly && <Checkbox checked={search.draftParams.attentionOnly} onChange={(event) => search.setField('attentionOnly')(Boolean(event.target.checked))}>仅看需处理</Checkbox>}\n <Button size=\"small\" onClick={search.handleSearch}>查询</Button>\n <Button size=\"small\" theme=\"borderless\" onClick={search.handleReset}>重置</Button>\n </Space>;\n}\n","import { useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';\nimport { Button, Collapse, Empty, List, Space, Spin, Tag, Tooltip, Typography } from \"@/ui\";\nimport type { EntityRelationItem, EntityRelationKind, EntityRelationSection, EntityRelationSummaryState, CanonicalEntityType } from '@fudanda/shared/platform';\nimport { Activity, CircleAlert, CircleCheck, CircleOff, CircleSlash2, EyeOff, Filter, GitBranch, Link2, RefreshCw, Zap } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { entityRelationsContract } from '@fudanda/react-core/lib/native-operations';\nimport { contractKey } from \"@fudanda/react-core/lib/contract-query\";\nimport { useEntityAccessKey, useEntityRelationSection, useEntityRelations } from \"@fudanda/react-core/hooks/queries/entity-relations\";\nimport { entityRelationKindLabel, entityRelationLabel, entityStatusLabel } from \"@fudanda/react-core/utils/entity-relations\";\nimport DateTimeText from \"@/components/DateTimeText\";\nimport EntityRefBadge from \"@/components/entity-relations/EntityRefBadge\";\n\nimport { EntityRelationViewStateContext } from \"@fudanda/react-core/components/entity-relations/entity-navigation\";\nimport { formatDateTime, formatDateTimeRangeForApi } from \"@fudanda/react-core/utils/date\";\nimport { useListSearch } from \"@fudanda/react-core/hooks/useListSearch\";\nimport { useFilterQuery } from \"@fudanda/react-core/hooks/useFilterQuery\";\nimport RelationFilters, { type RelationSearchState } from \"@/components/entity-relations/RelationFilters\";\nconst emptyRelationSearch = (): RelationSearchState => ({ keyword: '', status: undefined, range: null, attentionOnly: false });\nconst RELATION_SUMMARY_PRESENTATION: Record<EntityRelationSummaryState, {\n readonly label: string;\n readonly Icon: LucideIcon;\n readonly color: string;\n}> = {\n 'has-data': { label: '有记录', Icon: CircleCheck, color: 'var(--arc-antd-color-success)' },\n empty: { label: '暂无记录', Icon: CircleSlash2, color: 'var(--arc-antd-color-tertiary)' },\n attention: { label: '需处理', Icon: CircleAlert, color: 'var(--arc-antd-color-warning)' },\n unavailable: { label: '暂不可用', Icon: CircleOff, color: 'var(--arc-antd-color-danger)' },\n};\nconst RELATION_KIND_PRESENTATION: Record<EntityRelationKind, {\n readonly Icon: LucideIcon;\n readonly color: string;\n}> = {\n direct: { Icon: Link2, color: 'var(--arc-antd-color-primary)' },\n derived: { Icon: GitBranch, color: 'var(--arc-antd-color-info)' },\n causal: { Icon: Zap, color: 'var(--arc-antd-color-warning)' },\n activity: { Icon: Activity, color: 'var(--arc-antd-color-tertiary)' },\n};\nfunction RelationSectionHeader({ section, summaryState }: {\n readonly section: EntityRelationSection;\n readonly summaryState: EntityRelationSummaryState;\n}) {\n const label = entityRelationLabel(section.labelKey, section.targetTypes);\n const presentation = RELATION_SUMMARY_PRESENTATION[summaryState];\n const statusLabel = `${label}:${presentation.label}`;\n const Icon = presentation.Icon;\n const kindPresentation = RELATION_KIND_PRESENTATION[section.kind];\n const KindIcon = kindPresentation.Icon;\n const kindLabel = `关联来源:${entityRelationKindLabel(section.kind)}`;\n return <Space spacing={6}>\n <Tooltip content={statusLabel}>\n <span role=\"img\" aria-label={statusLabel} style={{ color: presentation.color, display: 'inline-flex' }}>\n <Icon size={15} aria-hidden=\"true\"/>\n </span>\n </Tooltip>\n <Tooltip content={kindLabel}>\n <span role=\"img\" aria-label={kindLabel} style={{ color: kindPresentation.color, display: 'inline-flex' }}>\n <KindIcon size={14} aria-hidden=\"true\"/>\n </span>\n </Tooltip>\n <span>{label}</span>\n </Space>;\n}\nfunction RelationOriginHint({ section, item }: {\n readonly section: EntityRelationSection;\n readonly item: EntityRelationItem;\n}) {\n const kind = item.origin?.kind ?? section.kind;\n const kindPresentation = RELATION_KIND_PRESENTATION[kind];\n const Icon = kindPresentation.Icon;\n const parts = [`关联来源:${entityRelationKindLabel(kind)}`];\n if (item.origin?.explanation)\n parts.push(item.origin.explanation);\n if (item.origin?.eventType)\n parts.push(`来源事件:${item.origin.eventType}`);\n if (item.origin?.relatedAt)\n parts.push(`关联建立时间:${formatDateTime(item.origin.relatedAt)}`);\n if (item.occurredAt)\n parts.push(`记录时间:${formatDateTime(item.occurredAt)}`);\n const label = parts.join(' · ');\n return <Tooltip content={label}>\n <span role=\"img\" aria-label={label} style={{ color: kindPresentation.color, display: 'inline-flex' }}>\n <Icon size={14} aria-hidden=\"true\"/>\n </span>\n </Tooltip>;\n}\ninterface RelationPanelProps {\n readonly entityType: CanonicalEntityType;\n readonly entityKey: string | undefined;\n readonly enabled?: boolean;\n readonly showAnchor?: boolean;\n}\ntype RelationSectionQuery = ReturnType<typeof useEntityRelationSection>;\nfunction RelationSectionView({ entityType, entityKey, section, active, canManageLinks: _canManageLinks, onSummaryStateChange, query, filtered, filters, filterToggle }: {\n readonly entityType: CanonicalEntityType;\n readonly entityKey: string;\n readonly section: EntityRelationSection;\n readonly active: boolean;\n readonly canManageLinks: boolean;\n readonly onSummaryStateChange: (sectionKey: string, state: EntityRelationSummaryState) => void;\n readonly query: RelationSectionQuery;\n readonly filtered: boolean;\n readonly filters?: ReactNode;\n readonly filterToggle?: ReactNode;\n}) {\n const queryClient = useQueryClient();\n const refreshSection = () => {\n void query.refetch();\n // Attention considers the full visible set; a page of records cannot clear it by itself.\n void queryClient.invalidateQueries({ queryKey: contractKey(entityRelationsContract.describe, { params: { type: entityType, key: entityKey } }) });\n };\n const pages = query.data?.pages ?? [];\n const items = pages.flatMap((page) => page.items).filter((item) => item.capabilities.view);\n const degraded = pages.some((page) => page.degraded);\n const sectionError = query.isError;\n const hasResponse = query.data !== undefined;\n useEffect(() => {\n if (!active || query.isFetching || filtered)\n return;\n if (sectionError || degraded) {\n onSummaryStateChange(section.key, 'unavailable');\n return;\n }\n if (!hasResponse)\n return;\n onSummaryStateChange(section.key, items.length > 0 ? (section.summaryState === 'attention' ? 'attention' : 'has-data') : query.hasNextPage ? 'unavailable' : 'empty');\n }, [active, degraded, filtered, hasResponse, items.length, onSummaryStateChange, query.hasNextPage, query.isFetching, section.key, section.summaryState, sectionError]);\n const label = entityRelationLabel(section.labelKey, section.targetTypes);\n return <div style={{ position: 'relative' }}>\n {filterToggle && <span style={{ position: 'absolute', top: 0, right: 32, zIndex: 1, lineHeight: 0 }}>{filterToggle}</span>}\n <span style={{ position: 'absolute', top: 0, right: 0, zIndex: 1, lineHeight: 0 }}>\n <Tooltip content={`刷新${label}`}>\n <Button size=\"small\" theme=\"borderless\" icon={<RefreshCw size={14}/>} loading={query.isFetching} aria-label={`刷新${label}`} onClick={(event) => { event.stopPropagation(); refreshSection(); }}/>\n </Tooltip>\n </span>\n <div style={{ paddingTop: 4, paddingRight: filterToggle ? 64 : 32 }}>\n {filters}\n {(query.isError || degraded) && <Space wrap spacing={8}>\n <Typography.Text type=\"danger\">{degraded ? '部分关联记录暂时不可用' : '关联记录加载失败'}</Typography.Text>\n <Button size=\"small\" onClick={() => void (query.isFetchNextPageError ? query.fetchNextPage() : query.refetch())}>重试</Button>\n </Space>}\n {hasResponse && !sectionError && !degraded && items.length === 0 && <Empty description={query.hasNextPage ? '继续加载以查找可见的匹配记录' : filtered ? '没有符合筛选条件的关联记录' : '暂无关联记录'}/>}\n {items.length > 0 && <List size=\"small\" split dataSource={items} renderItem={(item) => <List.Item key={`${item.ref.type}:${item.ref.key}:${item.relationKey}`} main={<div style={{ minWidth: 0 }}>\n <Space wrap spacing={8}><EntityRefBadge entityRef={item.ref} capabilities={{ view: item.capabilities.view && section.capabilities.view, open: item.capabilities.open && section.capabilities.open }}>{item.title}</EntityRefBadge>\n <RelationOriginHint section={section} item={item}/>\n {entityStatusLabel(item.status) && <Tag size=\"small\">{entityStatusLabel(item.status)}</Tag>}</Space>\n {item.subtitle && <div><Typography.Text type=\"tertiary\">{item.subtitle}</Typography.Text></div>}\n {item.description && <div><Typography.Text type=\"tertiary\">{item.description}</Typography.Text></div>}\n {item.occurredAt && <div><Typography.Text type=\"tertiary\"><DateTimeText value={item.occurredAt}/></Typography.Text></div>}\n </div>}/>}/>}\n {query.hasNextPage && <Button size=\"small\" loading={query.isFetchingNextPage} onClick={() => void query.fetchNextPage()}>加载更多</Button>}\n </div>\n </div>;\n}\nfunction RelationGroupItem({ entityType, entityKey, section, active, summaryState, canManageLinks, onSummaryStateChange }: {\n readonly entityType: CanonicalEntityType;\n readonly entityKey: string;\n readonly section: EntityRelationSection;\n readonly active: boolean;\n readonly summaryState: EntityRelationSummaryState;\n readonly canManageLinks: boolean;\n readonly onSummaryStateChange: (sectionKey: string, state: EntityRelationSummaryState) => void;\n}) {\n const search = useListSearch({ defaults: emptyRelationSearch,\n listKey: contractKey(entityRelationsContract.section, { params: { type: entityType, key: entityKey, sectionKey: section.key }, query: {} }),\n });\n const filters = useFilterQuery({ keyword: search.submittedParams.keyword, status: search.submittedParams.status,\n ...formatDateTimeRangeForApi(search.submittedParams.range), attentionOnly: search.submittedParams.attentionOnly ? true : undefined });\n const filtered = Object.keys(filters).length > 0;\n const [showFilters, setShowFilters] = useState(filtered);\n const supportsFilters = Boolean(section.filters?.keyword || section.filters?.dateRange || section.filters?.attentionOnly);\n const query = useEntityRelationSection(entityType, entityKey, section.key, active, 5, filters);\n return <Collapse.Panel key={section.key} itemKey={section.key} header={<RelationSectionHeader section={section} summaryState={summaryState}/>}>\n <RelationSectionView entityType={entityType} entityKey={entityKey} section={section} active={active} canManageLinks={canManageLinks} onSummaryStateChange={onSummaryStateChange} query={query} filtered={filtered} filters={supportsFilters && showFilters ? <RelationFilters section={section} search={search}/> : undefined} filterToggle={supportsFilters ? <Tooltip content=\"筛选关联记录\"><Button size=\"small\" theme={filtered ? 'light' : 'borderless'} aria-label=\"筛选关联记录\" aria-expanded={showFilters} icon={<Filter size={14}/>} onClick={() => setShowFilters((value) => !value)}/></Tooltip> : undefined}/>\n </Collapse.Panel>;\n}\nfunction RelationGroups({ entityType, entityKey, sections, canManageLinks, hideEmpty }: {\n readonly entityType: CanonicalEntityType;\n readonly entityKey: string;\n readonly sections: EntityRelationSection[];\n readonly canManageLinks: boolean;\n readonly hideEmpty: boolean;\n}) {\n const viewState = useContext(EntityRelationViewStateContext);\n const [localActiveKeys, setLocalActiveKeys] = useState<string[]>([]);\n const activeKeys = viewState?.expandedGroups ?? localActiveKeys;\n const setActiveKeys = viewState?.setExpandedGroups ?? setLocalActiveKeys;\n const defaultSummaryStates = useMemo(() => Object.fromEntries(sections.map((section) => [section.key, section.summaryState])), [sections]);\n const [summaryStates, setSummaryStates] = useState<Record<string, EntityRelationSummaryState>>(() => Object.fromEntries(sections.map((section) => [section.key, section.summaryState])));\n useEffect(() => {\n setSummaryStates(defaultSummaryStates);\n }, [defaultSummaryStates]);\n const updateSummaryState = useCallback((sectionKey: string, state: EntityRelationSummaryState) => {\n setSummaryStates((previous) => previous[sectionKey] === state ? previous : { ...previous, [sectionKey]: state });\n }, []);\n return <Collapse activeKey={activeKeys} onChange={(keys) => setActiveKeys(Array.isArray(keys) ? keys.map(String) : [String(keys)])}>\n {sections.filter((section) => section.capabilities.view && (!hideEmpty || (summaryStates[section.key] ?? section.summaryState) !== 'empty')).map((section) => <RelationGroupItem key={section.key} entityType={entityType} entityKey={entityKey} section={section} active={activeKeys.includes(section.key)} summaryState={summaryStates[section.key] ?? 'unavailable'} canManageLinks={canManageLinks} onSummaryStateChange={updateSummaryState}/>)}\n </Collapse>;\n}\nexport default function RelationPanel({ entityType, entityKey, enabled = true, showAnchor = false }: RelationPanelProps) {\n const query = useEntityRelations(entityType, entityKey, enabled);\n const access = useEntityAccessKey();\n const display = useListSearch({ defaults: { hideEmpty: false }, listKey: ['entity-relation-display', entityType, entityKey, access], refetchOnSearch: false });\n if (!enabled || !entityKey)\n return null;\n if (query.isLoading)\n return <Spin size=\"small\"/>;\n if (query.isError)\n return <Space wrap><Typography.Text type=\"danger\">对象不可用或关联信息加载失败</Typography.Text><Button size=\"small\" onClick={() => void query.refetch()}>重试</Button></Space>;\n const sections = query.data?.sections ?? [];\n return <div style={{ paddingTop: 12 }}>\n {showAnchor && query.data && <Typography.Title heading={6}>{query.data.anchor.title}</Typography.Title>}\n <Space spacing={8} style={{ marginBottom: 8 }}>\n {false}\n <Tooltip content={display.submittedParams.hideEmpty ? '显示空分组' : '隐藏空分组'}><Button size=\"small\" theme={display.submittedParams.hideEmpty ? 'light' : 'borderless'} aria-label=\"隐藏空分组\" aria-pressed={display.submittedParams.hideEmpty} icon={<EyeOff size={14}/>} onClick={() => display.applySearch({ hideEmpty: !display.submittedParams.hideEmpty })}/></Tooltip>\n </Space>\n {sections.length === 0 ? <Empty description=\"暂无可见关联信息\"/> : <RelationGroups key={`groups:${entityType}:${entityKey}:${JSON.stringify(access)}`} entityType={entityType} entityKey={entityKey} sections={sections} canManageLinks={query.data?.canManageLinks ?? false} hideEmpty={display.submittedParams.hideEmpty}/>}\n </div>;\n}\n"]}
@@ -1,2 +1,2 @@
1
- import{n as e}from"./rolldown-runtime-Bruge11p.js";import{$ as t,E as n,M as r,Q as i,R as a,a as o,i as s,nt as c,st as l}from"./clipboard-dpqHdCyy.js";import{i as u,r as d}from"./feedback-B1UL2ETz.js";import{r as f,s as p}from"./toolbar-controls-CrM8hKZg.js";import{n as ee,t as m}from"./useStatusToggle-D7g3Ew35.js";import{n as te,t as h}from"./useCrudOperationColumn-CPAzNGXp.js";import{n as ne,t as g}from"./useListPage-BPw-KZCv.js";import{i as re,n as ie,s as _}from"./table-columns-CvT6OHd2.js";import{a as v,i as ae,o as oe,r as y,t as se}from"./EditFormModal-DVQksS9R.js";import{n as b,t as ce}from"./ConfigurableTable-8sYmeul2.js";import{n as x,t as S}from"./AppModal-CVoUC2t3.js";import{n as C,t as le}from"./ExportButton-sMPAV2hd.js";import{i as w,n as T,r as ue,t as de}from"./UserTransferSelect-ChLj4EkS.js";import{n as fe,t as E}from"./webmcp-crud-D-Dz8BY4.js";import{a as D,i as pe,n as me,r as O}from"./DataScopePanel-BCsm8Lz8.js";import{useCallback as k,useEffect as A,useMemo as j,useRef as M,useState as N}from"react";import{jsx as P,jsxs as F}from"react/jsx-runtime";import{enumValueOf as he}from"@fudanda/client/core";import{useDictItems as ge}from"@fudanda/admin-antd/core/hooks/useDictItems";import{departmentContract as _e,roleContract as I}from"@fudanda/admin-antd/core/lib/native-operations";import{usePermission as ve}from"@fudanda/admin-antd/core/hooks/usePermission";import{useAllUsers as ye}from"@fudanda/admin-antd/core/hooks/queries/users";import{useMenuTree as be}from"@fudanda/admin-antd/core/hooks/queries/menus";import{DATA_SCOPES as xe}from"@fudanda/client/identity";import{departmentTreeToTreeData as Se,useDepartmentTree as Ce}from"@fudanda/admin-antd/core/hooks/queries/departments";import{useAssignRoleMenus as we,useAssignRoleUsers as Te,useDeleteRoles as Ee,useRoleDetail as L,useRoleList as De,useRoleUsers as Oe,useSaveRole as R,useUpdateRoleDataScope as ke}from"@fudanda/admin-antd/core/hooks/queries/roles";function Ae({visible:e,session:t,roleId:n,detail:r,isSuccess:i,isFetching:a}){let[o,s]=N(null),c=M({visible:e,session:t,roleId:n});c.current={visible:e,session:t,roleId:n};let l=M(!0);A(()=>(l.current=!0,()=>{l.current=!1}),[]);let u=e&&o?.session===t&&o.roleId===n,d=u&&i&&!a&&r?.id===n;A(()=>{e&&n!==void 0&&i&&!a&&r?.id===n&&s(e=>e?.session===t&&e.roleId===n?e:{session:t,roleId:n,menuIds:[...r.menuIds??[]]})},[e,t,n,r,i,a]);let f=k(e=>{d&&s(r=>r?.session===t&&r.roleId===n?{...r,menuIds:[...e]}:r)},[d,t,n]),p=k(async(e,r)=>{let i=()=>l.current&&c.current.visible&&c.current.session===t&&c.current.roleId===n;if(d&&n!==void 0&&i()){try{await e(n,[...o?.menuIds??[]])}catch(e){if(i())throw e;return}i()&&r()}},[o,d,n,t]);return{menuIds:u?o.menuIds:[],onChange:f,submit:p,initialized:u,isReady:d}}function z(){return(z=e((()=>{})))()}function B(){let{hasPermission:e}=ve(),{options:t}=ge(`common_status`),r=ne({contract:I,useList:De}),{tableProps:o,filterQuery:l}=r,[p,m]=N(!1),[h,g]=N(null),[re,v]=N(0),[y,b]=N(!1),[x,C]=N(null),[w,T]=N([]),[E,D]=N(!1),[O,k]=N(null),[M,z]=N(`all`),[B,V]=N([]),H=be({enabled:p}),U=L(h?.id,p),W=Ae({visible:p,session:re,roleId:h?.id,detail:U.data,isSuccess:U.isSuccess,isFetching:U.isFetching}),G=ye({enabled:y}),K=Oe(x?.id,y),q=L(O?.id,E),J=Ce(),Y=j(()=>J.data??[],[J.data]),je=R(),X=oe({entityName:`角色`,save:ae(je,{create:I.create.input.shape.body,update:I.update.input.shape.body}),useDetail:L,defaults:{status:`enabled`},toValues:e=>({name:e.name,code:e.code,description:e.description??void 0,deptScopeIds:e.deptScopeIds,status:e.status}),beforeSave:(e,{editing:t})=>({...e,description:e.description||void 0,...t?{clearFields:e.description?[]:[`description`]}:{}})}),Me=X.editing,Ne=R(),Z=Ee();fe({resource:`roles`,title:`角色`,permission:`system:role`,hasPermission:e,modal:X,list:I.list,detail:I.detail,create:I.create.input.shape.body,update:I.update.input.shape.body,createFields:[`name`,`code`,`description`,`deptScopeIds`,`status`],updateFields:[`name`,`code`,`description`,`deptScopeIds`,`status`,`clearFields`],updateClearFields:[`description`],fields:[`id`,`name`,`code`,`description`,`deptScopeIds`,`status`,`createdAt`,`updatedAt`],filters:l,remove:e=>Z.mutateAsync([e]),busy:p||y||E,guardRecord:(e,t)=>{if(t===`delete`&&e.code===`super_admin`)throw Error(`超级管理员角色不允许删除`)},guardValues:(e,t)=>{if(t?.code===`super_admin`&&e.status===`disabled`)throw Error(`超级管理员角色不允许禁用`)},lookups:[{name:`departments`,title:`部门`,operation:_e.flat,permission:`system:department:list`,fields:[`id`,`parentId`,`name`]}]});let Q=we(),$=W.isReady&&H.isSuccess&&!H.isFetching&&!Q.isPending,Pe=Te(),Fe=ke(),Ie=ee({toggle:(e,t)=>Ne.mutateAsync({id:e.id,values:{status:t?`enabled`:`disabled`}}),confirmDisable:e=>({danger:!0,title:`确认禁用角色「${e.name}」?`,content:`禁用后持有该角色的用户将不能登录。`,okText:`确认禁用`}),disabled:t=>t.code===`super_admin`||!e(`system:role:update`),messages:{disabled:`已禁用`}});A(()=>{y&&T((K.data??[]).map(e=>e.id))},[y,K.data]),A(()=>{E&&q.data&&V(q.data.deptScopeIds??[])},[E,q.data]);let Le=e=>{v(e=>e+1),g(e),m(!0)},Re=async()=>{h&&$&&await W.submit((e,t)=>Q.mutateAsync({params:{id:e},body:{menuIds:t}}),()=>{u.success(`菜单权限已更新`),m(!1)})},ze=j(()=>{let e=[],t=n=>{n.forEach(n=>{e.push(n),n.children&&t(n.children)})};return t(Y),e},[Y]),Be=j(()=>G.data??[],[G.data]),Ve=e=>{C(e),b(!0)},He=async()=>{x&&(await Pe.mutateAsync({params:{id:x.id},body:{userIds:w}}),u.success(`用户分配已更新`),b(!1))},Ue=e=>{k(e),z(e.dataScope??`all`),V([]),D(!0)},We=async()=>{if(!O)return;let e=he(xe,M)??`all`;await Fe.mutateAsync({params:{id:O.id},body:e===`custom`?{dataScope:e,deptScopeIds:B}:{dataScope:e}}),u.success(`数据权限已更新`),D(!1)},Ge=te({permission:`system:role`,edit:X,remove:Z,title:`确认删除此角色?`,disabled:{remove:e=>e.code===`super_admin`,reason:`超级管理员角色不允许删除`},extraBetween:t=>[{key:`menu`,label:`菜单权限`,hidden:!e(`system:role:assign`),onClick:()=>Le(t)}],extraAfter:t=>[{key:`users`,label:`分配用户`,hidden:!e(`system:role:assign`),onClick:()=>Ve(t)},{key:`dataScope`,label:`数据权限`,hidden:!e(`system:role:update`),onClick:()=>Ue(t)}],width:260,desktopInlineKeys:[`edit`,`menu`,`delete`]}),Ke=[{title:`角色名称`,dataIndex:`name`,width:160,render:_},{title:`角色编码`,dataIndex:`code`,width:160,render:_},{title:`描述`,dataIndex:`description`,minWidth:200,render:(e,t)=>_(t.description)},{title:`数据权限`,dataIndex:`dataScope`,width:140,align:`center`,render:e=>({all:`全部数据`,dept:`本部门及以下`,self:`仅本人数据`})[e]??e},{title:`用户`,dataIndex:`userPreview`,width:180,render:(e,t)=>/* @__PURE__ */ P(ue,{preview:t.userPreview,count:t.userCount,scope:{type:`role`,id:t.id,name:t.name}})},ie,Ie.column(),Ge];return/* @__PURE__ */ F(`div`,{className:`page-container`,children:[/* @__PURE__ */ P(ce,{searchConfig:i({page:r,filters:[`keyword`,`status`,[`startTime`,`endTime`]],overrides:{startTime:e=>/* @__PURE__ */ P(c,{placeholder:[`开始时间`,`结束时间`],...e.bindRange([`startTime`,`endTime`])})},create:/* @__PURE__ */ P(f,{permission:`system:role:create`,onClick:X.openCreate}),actions:/* @__PURE__ */ P(le,{entity:`system.roles`,query:l}),filterTitle:`角色筛选`,actionTitle:`角色操作`}),columns:Ke,...o}),/* @__PURE__ */ F(se,{modal:X,width:480,children:[/* @__PURE__ */ P(a.Input,{field:`name`,label:`角色名称`,placeholder:`请输入角色名称`,rules:[{required:!0,message:`请输入角色名称`}]}),/* @__PURE__ */ P(a.Input,{field:`code`,label:`角色编码`,placeholder:`请输入角色编码`,rules:[{required:!0,message:`请输入角色编码`}]}),/* @__PURE__ */ P(a.Input,{field:`description`,label:`描述`,placeholder:`请输入描述`}),/* @__PURE__ */ P(a.TreeSelect,{field:`deptScopeIds`,label:`管理范围`,placeholder:`默认全员(用于工作流「角色」审批人按部门过滤)`,multiple:!0,filterTreeNode:!0,treeData:Se(Y),style:{width:`100%`}}),/* @__PURE__ */ P(a.Select,{field:`status`,label:`状态`,style:{width:`100%`},disabled:Me?.code===`super_admin`,optionList:t,placeholder:`请选择状态`})]}),/* @__PURE__ */ P(S,{title:`分配菜单权限 — ${h?.name}`,visible:p,onCancel:()=>m(!1),onOk:Re,okButtonProps:{disabled:!$,loading:Q.isPending},width:640,children:/* @__PURE__ */ P(pe,{allMenus:H.data??[],checkedMenuIds:W.menuIds,onChange:W.onChange,loading:Q.isPending||H.isFetching||U.isFetching||U.isSuccess&&!W.initialized})}),/* @__PURE__ */ P(S,{title:`数据权限 — ${O?.name}`,visible:E,onCancel:()=>D(!1),onOk:We,okButtonProps:{disabled:!q.isSuccess,loading:Fe.isPending},width:400,children:/* @__PURE__ */ P(me,{dataScope:M,deptScopeIds:B,deptTree:Y,onScopeChange:e=>z(e??`all`),onDeptIdsChange:V,loading:J.isFetching||q.isFetching})}),/* @__PURE__ */ P(d,{title:/* @__PURE__ */ F(`span`,{children:[`分配用户 — `,x?.name]}),visible:y,onCancel:()=>b(!1),width:720,footer:/* @__PURE__ */ P(s,{onCancel:()=>b(!1),onOk:He,okText:`保存`,loading:Pe.isPending,disabled:!K.isSuccess||!G.isSuccess}),children:G.isFetching||K.isFetching?/* @__PURE__ */ P(`div`,{style:{display:`flex`,justifyContent:`center`,padding:40},children:/* @__PURE__ */ P(n,{})}):/* @__PURE__ */ P(de,{dataSource:Be,value:w,onChange:T,departments:ze})})]})}function V(){return(V=e((()=>{r(),T(),w(),C(),x(),b(),re(),D(),O(),v(),p(),l(),t(),m(),h(),o(),g(),y(),E(),z()})))()}V();export{B as default};
2
- //# sourceMappingURL=RolesPage-fwUSs2HR.js.map
1
+ import{n as e}from"./rolldown-runtime-Bruge11p.js";import{$ as t,E as n,M as r,Q as i,R as a,a as o,i as s,nt as c,st as l}from"./clipboard-dpqHdCyy.js";import{i as u,r as d}from"./feedback-B1UL2ETz.js";import{r as f,s as p}from"./toolbar-controls-CrM8hKZg.js";import{n as ee,t as m}from"./useStatusToggle-D7g3Ew35.js";import{n as te,t as h}from"./useCrudOperationColumn-CPAzNGXp.js";import{n as ne,t as g}from"./useListPage-BPw-KZCv.js";import{i as re,n as ie,s as _}from"./table-columns-CvT6OHd2.js";import{a as v,i as ae,o as oe,r as y,t as se}from"./EditFormModal-DVQksS9R.js";import{n as b,t as ce}from"./ConfigurableTable-8sYmeul2.js";import{n as x,t as S}from"./AppModal-CEouaU03.js";import{n as C,t as le}from"./ExportButton-DGxB2tcu.js";import{i as w,n as T,r as ue,t as de}from"./UserTransferSelect-C8betaWG.js";import{n as fe,t as E}from"./webmcp-crud-D-Dz8BY4.js";import{a as D,i as pe,n as me,r as O}from"./DataScopePanel-BCsm8Lz8.js";import{useCallback as k,useEffect as A,useMemo as j,useRef as M,useState as N}from"react";import{jsx as P,jsxs as F}from"react/jsx-runtime";import{enumValueOf as he}from"@fudanda/client/core";import{useDictItems as ge}from"@fudanda/admin-antd/core/hooks/useDictItems";import{departmentContract as _e,roleContract as I}from"@fudanda/admin-antd/core/lib/native-operations";import{usePermission as ve}from"@fudanda/admin-antd/core/hooks/usePermission";import{useAllUsers as ye}from"@fudanda/admin-antd/core/hooks/queries/users";import{useMenuTree as be}from"@fudanda/admin-antd/core/hooks/queries/menus";import{DATA_SCOPES as xe}from"@fudanda/client/identity";import{departmentTreeToTreeData as Se,useDepartmentTree as Ce}from"@fudanda/admin-antd/core/hooks/queries/departments";import{useAssignRoleMenus as we,useAssignRoleUsers as Te,useDeleteRoles as Ee,useRoleDetail as L,useRoleList as De,useRoleUsers as Oe,useSaveRole as R,useUpdateRoleDataScope as ke}from"@fudanda/admin-antd/core/hooks/queries/roles";function Ae({visible:e,session:t,roleId:n,detail:r,isSuccess:i,isFetching:a}){let[o,s]=N(null),c=M({visible:e,session:t,roleId:n});c.current={visible:e,session:t,roleId:n};let l=M(!0);A(()=>(l.current=!0,()=>{l.current=!1}),[]);let u=e&&o?.session===t&&o.roleId===n,d=u&&i&&!a&&r?.id===n;A(()=>{e&&n!==void 0&&i&&!a&&r?.id===n&&s(e=>e?.session===t&&e.roleId===n?e:{session:t,roleId:n,menuIds:[...r.menuIds??[]]})},[e,t,n,r,i,a]);let f=k(e=>{d&&s(r=>r?.session===t&&r.roleId===n?{...r,menuIds:[...e]}:r)},[d,t,n]),p=k(async(e,r)=>{let i=()=>l.current&&c.current.visible&&c.current.session===t&&c.current.roleId===n;if(d&&n!==void 0&&i()){try{await e(n,[...o?.menuIds??[]])}catch(e){if(i())throw e;return}i()&&r()}},[o,d,n,t]);return{menuIds:u?o.menuIds:[],onChange:f,submit:p,initialized:u,isReady:d}}function z(){return(z=e((()=>{})))()}function B(){let{hasPermission:e}=ve(),{options:t}=ge(`common_status`),r=ne({contract:I,useList:De}),{tableProps:o,filterQuery:l}=r,[p,m]=N(!1),[h,g]=N(null),[re,v]=N(0),[y,b]=N(!1),[x,C]=N(null),[w,T]=N([]),[E,D]=N(!1),[O,k]=N(null),[M,z]=N(`all`),[B,V]=N([]),H=be({enabled:p}),U=L(h?.id,p),W=Ae({visible:p,session:re,roleId:h?.id,detail:U.data,isSuccess:U.isSuccess,isFetching:U.isFetching}),G=ye({enabled:y}),K=Oe(x?.id,y),q=L(O?.id,E),J=Ce(),Y=j(()=>J.data??[],[J.data]),je=R(),X=oe({entityName:`角色`,save:ae(je,{create:I.create.input.shape.body,update:I.update.input.shape.body}),useDetail:L,defaults:{status:`enabled`},toValues:e=>({name:e.name,code:e.code,description:e.description??void 0,deptScopeIds:e.deptScopeIds,status:e.status}),beforeSave:(e,{editing:t})=>({...e,description:e.description||void 0,...t?{clearFields:e.description?[]:[`description`]}:{}})}),Me=X.editing,Ne=R(),Z=Ee();fe({resource:`roles`,title:`角色`,permission:`system:role`,hasPermission:e,modal:X,list:I.list,detail:I.detail,create:I.create.input.shape.body,update:I.update.input.shape.body,createFields:[`name`,`code`,`description`,`deptScopeIds`,`status`],updateFields:[`name`,`code`,`description`,`deptScopeIds`,`status`,`clearFields`],updateClearFields:[`description`],fields:[`id`,`name`,`code`,`description`,`deptScopeIds`,`status`,`createdAt`,`updatedAt`],filters:l,remove:e=>Z.mutateAsync([e]),busy:p||y||E,guardRecord:(e,t)=>{if(t===`delete`&&e.code===`super_admin`)throw Error(`超级管理员角色不允许删除`)},guardValues:(e,t)=>{if(t?.code===`super_admin`&&e.status===`disabled`)throw Error(`超级管理员角色不允许禁用`)},lookups:[{name:`departments`,title:`部门`,operation:_e.flat,permission:`system:department:list`,fields:[`id`,`parentId`,`name`]}]});let Q=we(),$=W.isReady&&H.isSuccess&&!H.isFetching&&!Q.isPending,Pe=Te(),Fe=ke(),Ie=ee({toggle:(e,t)=>Ne.mutateAsync({id:e.id,values:{status:t?`enabled`:`disabled`}}),confirmDisable:e=>({danger:!0,title:`确认禁用角色「${e.name}」?`,content:`禁用后持有该角色的用户将不能登录。`,okText:`确认禁用`}),disabled:t=>t.code===`super_admin`||!e(`system:role:update`),messages:{disabled:`已禁用`}});A(()=>{y&&T((K.data??[]).map(e=>e.id))},[y,K.data]),A(()=>{E&&q.data&&V(q.data.deptScopeIds??[])},[E,q.data]);let Le=e=>{v(e=>e+1),g(e),m(!0)},Re=async()=>{h&&$&&await W.submit((e,t)=>Q.mutateAsync({params:{id:e},body:{menuIds:t}}),()=>{u.success(`菜单权限已更新`),m(!1)})},ze=j(()=>{let e=[],t=n=>{n.forEach(n=>{e.push(n),n.children&&t(n.children)})};return t(Y),e},[Y]),Be=j(()=>G.data??[],[G.data]),Ve=e=>{C(e),b(!0)},He=async()=>{x&&(await Pe.mutateAsync({params:{id:x.id},body:{userIds:w}}),u.success(`用户分配已更新`),b(!1))},Ue=e=>{k(e),z(e.dataScope??`all`),V([]),D(!0)},We=async()=>{if(!O)return;let e=he(xe,M)??`all`;await Fe.mutateAsync({params:{id:O.id},body:e===`custom`?{dataScope:e,deptScopeIds:B}:{dataScope:e}}),u.success(`数据权限已更新`),D(!1)},Ge=te({permission:`system:role`,edit:X,remove:Z,title:`确认删除此角色?`,disabled:{remove:e=>e.code===`super_admin`,reason:`超级管理员角色不允许删除`},extraBetween:t=>[{key:`menu`,label:`菜单权限`,hidden:!e(`system:role:assign`),onClick:()=>Le(t)}],extraAfter:t=>[{key:`users`,label:`分配用户`,hidden:!e(`system:role:assign`),onClick:()=>Ve(t)},{key:`dataScope`,label:`数据权限`,hidden:!e(`system:role:update`),onClick:()=>Ue(t)}],width:260,desktopInlineKeys:[`edit`,`menu`,`delete`]}),Ke=[{title:`角色名称`,dataIndex:`name`,width:160,render:_},{title:`角色编码`,dataIndex:`code`,width:160,render:_},{title:`描述`,dataIndex:`description`,minWidth:200,render:(e,t)=>_(t.description)},{title:`数据权限`,dataIndex:`dataScope`,width:140,align:`center`,render:e=>({all:`全部数据`,dept:`本部门及以下`,self:`仅本人数据`})[e]??e},{title:`用户`,dataIndex:`userPreview`,width:180,render:(e,t)=>/* @__PURE__ */ P(ue,{preview:t.userPreview,count:t.userCount,scope:{type:`role`,id:t.id,name:t.name}})},ie,Ie.column(),Ge];return/* @__PURE__ */ F(`div`,{className:`page-container`,children:[/* @__PURE__ */ P(ce,{searchConfig:i({page:r,filters:[`keyword`,`status`,[`startTime`,`endTime`]],overrides:{startTime:e=>/* @__PURE__ */ P(c,{placeholder:[`开始时间`,`结束时间`],...e.bindRange([`startTime`,`endTime`])})},create:/* @__PURE__ */ P(f,{permission:`system:role:create`,onClick:X.openCreate}),actions:/* @__PURE__ */ P(le,{entity:`system.roles`,query:l}),filterTitle:`角色筛选`,actionTitle:`角色操作`}),columns:Ke,...o}),/* @__PURE__ */ F(se,{modal:X,width:480,children:[/* @__PURE__ */ P(a.Input,{field:`name`,label:`角色名称`,placeholder:`请输入角色名称`,rules:[{required:!0,message:`请输入角色名称`}]}),/* @__PURE__ */ P(a.Input,{field:`code`,label:`角色编码`,placeholder:`请输入角色编码`,rules:[{required:!0,message:`请输入角色编码`}]}),/* @__PURE__ */ P(a.Input,{field:`description`,label:`描述`,placeholder:`请输入描述`}),/* @__PURE__ */ P(a.TreeSelect,{field:`deptScopeIds`,label:`管理范围`,placeholder:`默认全员(用于工作流「角色」审批人按部门过滤)`,multiple:!0,filterTreeNode:!0,treeData:Se(Y),style:{width:`100%`}}),/* @__PURE__ */ P(a.Select,{field:`status`,label:`状态`,style:{width:`100%`},disabled:Me?.code===`super_admin`,optionList:t,placeholder:`请选择状态`})]}),/* @__PURE__ */ P(S,{title:`分配菜单权限 — ${h?.name}`,visible:p,onCancel:()=>m(!1),onOk:Re,okButtonProps:{disabled:!$,loading:Q.isPending},width:640,children:/* @__PURE__ */ P(pe,{allMenus:H.data??[],checkedMenuIds:W.menuIds,onChange:W.onChange,loading:Q.isPending||H.isFetching||U.isFetching||U.isSuccess&&!W.initialized})}),/* @__PURE__ */ P(S,{title:`数据权限 — ${O?.name}`,visible:E,onCancel:()=>D(!1),onOk:We,okButtonProps:{disabled:!q.isSuccess,loading:Fe.isPending},width:400,children:/* @__PURE__ */ P(me,{dataScope:M,deptScopeIds:B,deptTree:Y,onScopeChange:e=>z(e??`all`),onDeptIdsChange:V,loading:J.isFetching||q.isFetching})}),/* @__PURE__ */ P(d,{title:/* @__PURE__ */ F(`span`,{children:[`分配用户 — `,x?.name]}),visible:y,onCancel:()=>b(!1),width:720,footer:/* @__PURE__ */ P(s,{onCancel:()=>b(!1),onOk:He,okText:`保存`,loading:Pe.isPending,disabled:!K.isSuccess||!G.isSuccess}),children:G.isFetching||K.isFetching?/* @__PURE__ */ P(`div`,{style:{display:`flex`,justifyContent:`center`,padding:40},children:/* @__PURE__ */ P(n,{})}):/* @__PURE__ */ P(de,{dataSource:Be,value:w,onChange:T,departments:ze})})]})}function V(){return(V=e((()=>{r(),T(),w(),C(),x(),b(),re(),D(),O(),v(),p(),l(),t(),m(),h(),o(),g(),y(),E(),z()})))()}V();export{B as default};
2
+ //# sourceMappingURL=RolesPage-46dzdiah.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RolesPage-fwUSs2HR.js","mappings":"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","names":["useRoleMenuDraft","draft","setDraft","useState","current","useRef","mounted","useEffect","initialized","visible","session","roleId","isReady","isSuccess","isFetching","detail","onChange","useCallback","menuIds","submit","belongsToOpening","save","error","onSaved","RolesPage","usePermission","statusOptions","useDictItems","page","useListPage","roleContract","useRoleList","menuModalVisible","setMenuModalVisible","menuRole","setMenuRole","menuSession","setMenuSession","userModalVisible","setUserModalVisible","userRole","setUserRole","assignedUserIds","setAssignedUserIds","dataScopeModalVisible","setDataScopeModalVisible","dataScopeRole","setDataScopeRole","selectedDataScope","setSelectedDataScope","selectedDeptScopeIds","setSelectedDeptScopeIds","menuTreeQuery","useMenuTree","menuRoleDetailQuery","useRoleDetail","menuDraft","allUsersQuery","useAllUsers","roleUsersQuery","useRoleUsers","dataScopeRoleDetailQuery","deptTreeQuery","useDepartmentTree","deptTree","useMemo","saveMutation","useSaveRole","roleModal","useEditModal","formSaveMutation","role","values","editing","editingRole","toggleStatusMutation","deleteMutation","useDeleteRoles","useStandardWebMcpCrudAdapter","filterQuery","id","action","record","departmentContract","assignMenusMutation","useAssignRoleMenus","canAssignMenus","assignUsersMutation","useAssignRoleUsers","updateDataScopeMutation","useUpdateRoleDataScope","status","useStatusToggle","enabled","hasPermission","u","openMenuModal","handleAssignMenus","Toast","flatDepts","result","flatten","items","d","allUsers","openUserModal","handleAssignUsers","openDataScopeModal","handleSaveDataScope","dataScope","enumValueOf","DATA_SCOPES","operationColumn","useCrudOperationColumn","row","columns","renderEllipsis","v","UserPreviewCell","createdAtColumn","ConfigurableTable","buildTableSearch","DateRangeFilter","p","CreateButton","ExportButton","tableProps","EditFormModal","Form","departmentTreeToTreeData","AppModal","MenuPermissionPanel","DataScopePanel","SideSheet","ModalFooter","Spin","UserTransferSelect"],"ignoreList":[],"sources":["../../src/pages/system/roles/useRoleMenuDraft.ts","../../src/pages/system/roles/RolesPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\ntype RoleMenuDetail = { id: number; menuIds?: readonly number[] | null };\ntype Draft = { session: number; roleId: number; menuIds: number[] };\n\n/** Each opening owns one draft; background detail refreshes never replace it. */\nexport function useRoleMenuDraft({ visible, session, roleId, detail, isSuccess, isFetching }: {\n visible: boolean;\n session: number;\n roleId: number | undefined;\n detail: RoleMenuDetail | undefined;\n isSuccess: boolean;\n isFetching: boolean;\n}) {\n const [draft, setDraft] = useState<Draft | null>(null);\n const current = useRef({ visible, session, roleId });\n current.current = { visible, session, roleId };\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => { mounted.current = false; };\n }, []);\n const initialized = visible && draft?.session === session && draft.roleId === roleId;\n const isReady = initialized && isSuccess && !isFetching && detail?.id === roleId;\n\n useEffect(() => {\n if (!visible || roleId === undefined || !isSuccess || isFetching || detail?.id !== roleId)\n return;\n setDraft(current => current?.session === session && current.roleId === roleId\n ? current\n : { session, roleId, menuIds: [...(detail.menuIds ?? [])] });\n }, [visible, session, roleId, detail, isSuccess, isFetching]);\n\n const onChange = useCallback((menuIds: number[]) => {\n if (!isReady)\n return;\n setDraft(current => current?.session === session && current.roleId === roleId\n ? { ...current, menuIds: [...menuIds] }\n : current);\n }, [isReady, session, roleId]);\n\n const submit = useCallback(async (\n save: (id: number, menuIds: number[]) => Promise<unknown>,\n onSaved: () => void,\n ) => {\n const belongsToOpening = () => mounted.current && current.current.visible\n && current.current.session === session && current.current.roleId === roleId;\n if (!isReady || roleId === undefined || !belongsToOpening())\n return;\n try {\n await save(roleId, [...(draft?.menuIds ?? [])]);\n }\n catch (error) {\n if (belongsToOpening())\n throw error;\n return;\n }\n if (belongsToOpening())\n onSaved();\n }, [draft, isReady, roleId, session]);\n\n return { menuIds: initialized ? draft.menuIds : [], onChange, submit, initialized, isReady };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { Form, Toast, Spin, SideSheet } from \"@/ui\";\nimport { DATA_SCOPES, type CreateRoleInput, type Role, type Department } from '@fudanda/shared/identity';\nimport { roleContract, departmentContract } from '@fudanda/react-core/lib/native-operations';\nimport { enumValueOf } from '@fudanda/shared/core';\nimport { UserTransferSelect } from \"@/components/UserTransferSelect\";\nimport type { UserTransferUser } from \"@/components/UserTransferSelect\";\nimport { UserPreviewCell } from \"@/components/UserPreviewCell\";\nimport ExportButton from \"@/components/ExportButton\";\nimport { AppModal } from \"@/components/AppModal\";\nimport ConfigurableTable from \"@/components/ConfigurableTable\";\nimport { usePermission } from \"@fudanda/react-core/hooks/usePermission\";\nimport { useDictItems } from \"@fudanda/react-core/hooks/useDictItems\";\nimport type { ColumnProps } from \"@/ui\";\nimport { createdAtColumn, renderEllipsis } from \"@/utils/table-columns\";\nimport { MenuPermissionPanel } from \"@/components/permissions/MenuPermissionPanel\";\nimport { DataScopePanel } from \"@/components/permissions/DataScopePanel\";\nimport { departmentTreeToTreeData, useDepartmentTree } from \"@fudanda/react-core/hooks/queries/departments\";\nimport { useMenuTree } from \"@fudanda/react-core/hooks/queries/menus\";\nimport { useAllUsers } from \"@fudanda/react-core/hooks/queries/users\";\nimport { useEditModal, formSaveMutation } from \"@/hooks/useEditModal\";\nimport { useAssignRoleMenus, useAssignRoleUsers, useDeleteRoles, useRoleDetail, useRoleList, useRoleUsers, useSaveRole, useUpdateRoleDataScope } from \"@fudanda/react-core/hooks/queries/roles\";\nimport { CreateButton } from \"@/components/toolbar-controls\";\nimport { DateRangeFilter } from \"@/components/search-filters\";\nimport { buildTableSearch, useStatusToggle, useCrudOperationColumn } from \"@/components/list-page/index\";\nimport ModalFooter from \"@/components/ModalFooter\";\nimport { useListPage } from \"@/hooks/useListPage\";\nimport { EditFormModal } from \"@/components/EditFormModal\";\nimport { useStandardWebMcpCrudAdapter } from '@/webmcp-crud';\nimport { useRoleMenuDraft } from './useRoleMenuDraft';\nexport default function RolesPage() {\n const { hasPermission } = usePermission();\n const { options: statusOptions } = useDictItems('common_status');\n const page = useListPage({\n contract: roleContract,\n useList: useRoleList,\n });\n const { tableProps, filterQuery } = page;\n const [menuModalVisible, setMenuModalVisible] = useState(false);\n const [menuRole, setMenuRole] = useState<Role | null>(null);\n const [menuSession, setMenuSession] = useState(0);\n const [userModalVisible, setUserModalVisible] = useState(false);\n const [userRole, setUserRole] = useState<Role | null>(null);\n const [assignedUserIds, setAssignedUserIds] = useState<number[]>([]);\n const [dataScopeModalVisible, setDataScopeModalVisible] = useState(false);\n const [dataScopeRole, setDataScopeRole] = useState<Role | null>(null);\n const [selectedDataScope, setSelectedDataScope] = useState<string>('all');\n const [selectedDeptScopeIds, setSelectedDeptScopeIds] = useState<number[]>([]);\n const menuTreeQuery = useMenuTree({ enabled: menuModalVisible });\n const menuRoleDetailQuery = useRoleDetail(menuRole?.id, menuModalVisible);\n const menuDraft = useRoleMenuDraft({ visible: menuModalVisible, session: menuSession, roleId: menuRole?.id,\n detail: menuRoleDetailQuery.data, isSuccess: menuRoleDetailQuery.isSuccess, isFetching: menuRoleDetailQuery.isFetching });\n const allUsersQuery = useAllUsers({ enabled: userModalVisible });\n const roleUsersQuery = useRoleUsers(userRole?.id, userModalVisible);\n const dataScopeRoleDetailQuery = useRoleDetail(dataScopeRole?.id, dataScopeModalVisible);\n const deptTreeQuery = useDepartmentTree();\n const deptTree = useMemo(() => deptTreeQuery.data ?? [], [deptTreeQuery.data]);\n const saveMutation = useSaveRole();\n const roleModal = useEditModal<Role, Partial<CreateRoleInput>>({\n entityName: '角色',\n save: formSaveMutation(saveMutation, { create: roleContract.create.input.shape.body, update: roleContract.update.input.shape.body }),\n useDetail: useRoleDetail,\n defaults: { status: 'enabled' },\n // 记录里的 null 描述在表单中视为未填\n toValues: (role) => ({ name: role.name, code: role.code, description: role.description ?? undefined, deptScopeIds: role.deptScopeIds, status: role.status }),\n beforeSave: (values, { editing }) => ({ ...values, description: values.description || undefined, ...(editing ? { clearFields: values.description ? [] : ['description'] } : {}) }),\n });\n const editingRole = roleModal.editing;\n const toggleStatusMutation = useSaveRole();\n const deleteMutation = useDeleteRoles();\n useStandardWebMcpCrudAdapter({ resource: 'roles', title: '角色', permission: 'system:role', hasPermission, modal: roleModal,\n list: roleContract.list, detail: roleContract.detail, create: roleContract.create.input.shape.body, update: roleContract.update.input.shape.body,\n createFields: ['name', 'code', 'description', 'deptScopeIds', 'status'], updateFields: ['name', 'code', 'description', 'deptScopeIds', 'status', 'clearFields'], updateClearFields: ['description'],\n fields: ['id', 'name', 'code', 'description', 'deptScopeIds', 'status', 'createdAt', 'updatedAt'], filters: filterQuery,\n remove: id => deleteMutation.mutateAsync([id]), busy: menuModalVisible || userModalVisible || dataScopeModalVisible, guardRecord: (record, action) => { if (action === 'delete' && record.code === 'super_admin') throw new Error('超级管理员角色不允许删除'); },\n guardValues: (values, record) => { if (record?.code === 'super_admin' && values.status === 'disabled') throw new Error('超级管理员角色不允许禁用'); },\n lookups: [{ name: 'departments', title: '部门', operation: departmentContract.flat, permission: 'system:department:list', fields: ['id', 'parentId', 'name'] }] });\n const assignMenusMutation = useAssignRoleMenus();\n const canAssignMenus = menuDraft.isReady && menuTreeQuery.isSuccess && !menuTreeQuery.isFetching && !assignMenusMutation.isPending;\n const assignUsersMutation = useAssignRoleUsers();\n const updateDataScopeMutation = useUpdateRoleDataScope();\n const status = useStatusToggle<Role>({\n toggle: (role, enabled) => toggleStatusMutation.mutateAsync({ id: role.id, values: { status: enabled ? 'enabled' : 'disabled' } }),\n confirmDisable: (role) => ({ danger: true, title: `确认禁用角色「${role.name}」?`, content: '禁用后持有该角色的用户将不能登录。', okText: '确认禁用' }),\n disabled: (role) => role.code === 'super_admin' || !hasPermission('system:role:update'),\n messages: { disabled: '已禁用' },\n });\n useEffect(() => {\n if (userModalVisible)\n setAssignedUserIds((roleUsersQuery.data ?? []).map((u) => u.id));\n }, [userModalVisible, roleUsersQuery.data]);\n useEffect(() => {\n if (dataScopeModalVisible && dataScopeRoleDetailQuery.data) {\n setSelectedDeptScopeIds(dataScopeRoleDetailQuery.data.deptScopeIds ?? []);\n }\n }, [dataScopeModalVisible, dataScopeRoleDetailQuery.data]);\n const openMenuModal = (role: Role) => {\n setMenuSession(session => session + 1);\n setMenuRole(role);\n setMenuModalVisible(true);\n };\n const handleAssignMenus = async () => {\n if (!menuRole || !canAssignMenus)\n return;\n await menuDraft.submit((id, menuIds) => assignMenusMutation.mutateAsync({ params: { id }, body: { menuIds } }), () => {\n Toast.success('菜单权限已更新');\n setMenuModalVisible(false);\n });\n };\n // 扁平化部门列表(供分配用户组件的树形视图使用)\n const flatDepts = useMemo<Department[]>(() => {\n const result: Department[] = [];\n const flatten = (items: Department[]) => {\n items.forEach((d) => {\n result.push(d);\n if (d.children)\n flatten(d.children);\n });\n };\n flatten(deptTree);\n return result;\n }, [deptTree]);\n const allUsers = useMemo<UserTransferUser[]>(() => allUsersQuery.data ?? [], [allUsersQuery.data]);\n const openUserModal = (role: Role) => {\n setUserRole(role);\n setUserModalVisible(true);\n };\n const handleAssignUsers = async () => {\n if (!userRole)\n return;\n await assignUsersMutation.mutateAsync({ params: { id: userRole.id }, body: { userIds: assignedUserIds } });\n Toast.success('用户分配已更新');\n setUserModalVisible(false);\n };\n const openDataScopeModal = (role: Role) => {\n setDataScopeRole(role);\n setSelectedDataScope(role.dataScope ?? 'all');\n setSelectedDeptScopeIds([]);\n setDataScopeModalVisible(true);\n };\n const handleSaveDataScope = async () => {\n if (!dataScopeRole)\n return;\n // 面板以宽 string 维护选中值,提交前收窄为数据范围枚举\n const dataScope = enumValueOf(DATA_SCOPES, selectedDataScope) ?? 'all';\n await updateDataScopeMutation.mutateAsync({\n params: { id: dataScopeRole.id },\n body: dataScope === 'custom' ? { dataScope, deptScopeIds: selectedDeptScopeIds } : { dataScope },\n });\n Toast.success('数据权限已更新');\n setDataScopeModalVisible(false);\n };\n const operationColumn = useCrudOperationColumn<Role>({\n permission: 'system:role',\n edit: roleModal,\n remove: deleteMutation,\n title: '确认删除此角色?',\n disabled: { remove: (row) => row.code === 'super_admin', reason: '超级管理员角色不允许删除' },\n extraBetween: (row) => [\n {\n key: 'menu',\n label: '菜单权限',\n hidden: !hasPermission('system:role:assign'),\n onClick: () => openMenuModal(row),\n },\n ],\n extraAfter: (row) => [\n {\n key: 'users',\n label: '分配用户',\n hidden: !hasPermission('system:role:assign'),\n onClick: () => openUserModal(row),\n },\n {\n key: 'dataScope',\n label: '数据权限',\n hidden: !hasPermission('system:role:update'),\n onClick: () => openDataScopeModal(row),\n },\n ],\n width: 260,\n desktopInlineKeys: ['edit', 'menu', 'delete'],\n });\n const columns: ColumnProps<Role>[] = [\n { title: '角色名称', dataIndex: 'name', width: 160, render: renderEllipsis },\n { title: '角色编码', dataIndex: 'code', width: 160, render: renderEllipsis },\n { title: '描述', dataIndex: 'description', minWidth: 200, render: (_v, record) => renderEllipsis(record.description) },\n {\n title: '数据权限',\n dataIndex: 'dataScope',\n width: 140,\n align: 'center',\n render: (v: string) => {\n const map: Record<string, string> = { all: '全部数据', dept: '本部门及以下', self: '仅本人数据' };\n return map[v] ?? v;\n },\n },\n {\n title: '用户',\n dataIndex: 'userPreview',\n width: 180,\n render: (_: unknown, record: Role) => <UserPreviewCell preview={record.userPreview} count={record.userCount} scope={{ type: 'role', id: record.id, name: record.name }}/>,\n },\n createdAtColumn,\n status.column(),\n operationColumn,\n ];\n return (<div className=\"page-container\">\n\n\n <ConfigurableTable<Role> searchConfig={buildTableSearch({\n page: (page),\n filters: (['keyword', 'status', ['startTime', 'endTime']]),\n overrides: ({\n startTime: (p) => <DateRangeFilter placeholder={[\"开始时间\", \"结束时间\"]} {...p.bindRange(['startTime', 'endTime'])}/>,\n }),\n create: (<CreateButton permission=\"system:role:create\" onClick={roleModal.openCreate}/>),\n actions: (<ExportButton entity=\"system.roles\" query={filterQuery}/>),\n filterTitle: \"角色筛选\",\n actionTitle: \"角色操作\"\n })} columns={columns} {...tableProps}/>\n\n {/* 创建/编辑 Modal */}\n <EditFormModal modal={roleModal} width={480}>\n <Form.Input field=\"name\" label=\"角色名称\" placeholder=\"请输入角色名称\" rules={[{ required: true, message: '请输入角色名称' }]}/>\n <Form.Input field=\"code\" label=\"角色编码\" placeholder=\"请输入角色编码\" rules={[{ required: true, message: '请输入角色编码' }]}/>\n <Form.Input field=\"description\" label=\"描述\" placeholder=\"请输入描述\"/>\n <Form.TreeSelect field=\"deptScopeIds\" label=\"管理范围\" placeholder=\"默认全员(用于工作流「角色」审批人按部门过滤)\" multiple filterTreeNode treeData={departmentTreeToTreeData(deptTree)} style={{ width: '100%' }}/>\n <Form.Select field=\"status\" label=\"状态\" style={{ width: '100%' }} disabled={editingRole?.code === 'super_admin'} optionList={statusOptions} placeholder=\"请选择状态\"/>\n </EditFormModal>\n\n {/* 菜单权限 Modal */}\n <AppModal title={`分配菜单权限 — ${menuRole?.name}`} visible={menuModalVisible} onCancel={() => setMenuModalVisible(false)} onOk={handleAssignMenus} okButtonProps={{ disabled: !canAssignMenus, loading: assignMenusMutation.isPending }} width={640}>\n <MenuPermissionPanel allMenus={menuTreeQuery.data ?? []} checkedMenuIds={menuDraft.menuIds} onChange={menuDraft.onChange} loading={assignMenusMutation.isPending || menuTreeQuery.isFetching || menuRoleDetailQuery.isFetching || (menuRoleDetailQuery.isSuccess && !menuDraft.initialized)}/>\n </AppModal>\n\n {/* 数据权限 Modal */}\n <AppModal title={`数据权限 — ${dataScopeRole?.name}`} visible={dataScopeModalVisible} onCancel={() => setDataScopeModalVisible(false)} onOk={handleSaveDataScope} okButtonProps={{ disabled: !dataScopeRoleDetailQuery.isSuccess, loading: updateDataScopeMutation.isPending }} width={400}>\n <DataScopePanel dataScope={selectedDataScope} deptScopeIds={selectedDeptScopeIds} deptTree={deptTree} onScopeChange={(v) => setSelectedDataScope(v ?? 'all')} onDeptIdsChange={setSelectedDeptScopeIds} loading={deptTreeQuery.isFetching || dataScopeRoleDetailQuery.isFetching}/>\n </AppModal>\n\n {/* 分配用户 SideSheet */}\n <SideSheet title={<span>分配用户 — {userRole?.name}</span>} visible={userModalVisible} onCancel={() => setUserModalVisible(false)} width={720} footer={(<ModalFooter onCancel={() => setUserModalVisible(false)} onOk={handleAssignUsers} okText=\"保存\" loading={assignUsersMutation.isPending} disabled={!roleUsersQuery.isSuccess || !allUsersQuery.isSuccess}/>)}>\n {allUsersQuery.isFetching || roleUsersQuery.isFetching ? (<div style={{ display: 'flex', justifyContent: 'center', padding: 40 }}>\n <Spin />\n </div>) : (<UserTransferSelect dataSource={allUsers} value={assignedUserIds} onChange={setAssignedUserIds} departments={flatDepts}/>)}\n </SideSheet>\n </div>);\n}\n"]}
1
+ {"version":3,"file":"RolesPage-46dzdiah.js","mappings":"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","names":["useRoleMenuDraft","draft","setDraft","useState","current","useRef","mounted","useEffect","initialized","visible","session","roleId","isReady","isSuccess","isFetching","detail","onChange","useCallback","menuIds","submit","belongsToOpening","save","error","onSaved","RolesPage","usePermission","statusOptions","useDictItems","page","useListPage","roleContract","useRoleList","menuModalVisible","setMenuModalVisible","menuRole","setMenuRole","menuSession","setMenuSession","userModalVisible","setUserModalVisible","userRole","setUserRole","assignedUserIds","setAssignedUserIds","dataScopeModalVisible","setDataScopeModalVisible","dataScopeRole","setDataScopeRole","selectedDataScope","setSelectedDataScope","selectedDeptScopeIds","setSelectedDeptScopeIds","menuTreeQuery","useMenuTree","menuRoleDetailQuery","useRoleDetail","menuDraft","allUsersQuery","useAllUsers","roleUsersQuery","useRoleUsers","dataScopeRoleDetailQuery","deptTreeQuery","useDepartmentTree","deptTree","useMemo","saveMutation","useSaveRole","roleModal","useEditModal","formSaveMutation","role","values","editing","editingRole","toggleStatusMutation","deleteMutation","useDeleteRoles","useStandardWebMcpCrudAdapter","filterQuery","id","action","record","departmentContract","assignMenusMutation","useAssignRoleMenus","canAssignMenus","assignUsersMutation","useAssignRoleUsers","updateDataScopeMutation","useUpdateRoleDataScope","status","useStatusToggle","enabled","hasPermission","u","openMenuModal","handleAssignMenus","Toast","flatDepts","result","flatten","items","d","allUsers","openUserModal","handleAssignUsers","openDataScopeModal","handleSaveDataScope","dataScope","enumValueOf","DATA_SCOPES","operationColumn","useCrudOperationColumn","row","columns","renderEllipsis","v","UserPreviewCell","createdAtColumn","ConfigurableTable","buildTableSearch","DateRangeFilter","p","CreateButton","ExportButton","tableProps","EditFormModal","Form","departmentTreeToTreeData","AppModal","MenuPermissionPanel","DataScopePanel","SideSheet","ModalFooter","Spin","UserTransferSelect"],"ignoreList":[],"sources":["../../src/pages/system/roles/useRoleMenuDraft.ts","../../src/pages/system/roles/RolesPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\ntype RoleMenuDetail = { id: number; menuIds?: readonly number[] | null };\ntype Draft = { session: number; roleId: number; menuIds: number[] };\n\n/** Each opening owns one draft; background detail refreshes never replace it. */\nexport function useRoleMenuDraft({ visible, session, roleId, detail, isSuccess, isFetching }: {\n visible: boolean;\n session: number;\n roleId: number | undefined;\n detail: RoleMenuDetail | undefined;\n isSuccess: boolean;\n isFetching: boolean;\n}) {\n const [draft, setDraft] = useState<Draft | null>(null);\n const current = useRef({ visible, session, roleId });\n current.current = { visible, session, roleId };\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => { mounted.current = false; };\n }, []);\n const initialized = visible && draft?.session === session && draft.roleId === roleId;\n const isReady = initialized && isSuccess && !isFetching && detail?.id === roleId;\n\n useEffect(() => {\n if (!visible || roleId === undefined || !isSuccess || isFetching || detail?.id !== roleId)\n return;\n setDraft(current => current?.session === session && current.roleId === roleId\n ? current\n : { session, roleId, menuIds: [...(detail.menuIds ?? [])] });\n }, [visible, session, roleId, detail, isSuccess, isFetching]);\n\n const onChange = useCallback((menuIds: number[]) => {\n if (!isReady)\n return;\n setDraft(current => current?.session === session && current.roleId === roleId\n ? { ...current, menuIds: [...menuIds] }\n : current);\n }, [isReady, session, roleId]);\n\n const submit = useCallback(async (\n save: (id: number, menuIds: number[]) => Promise<unknown>,\n onSaved: () => void,\n ) => {\n const belongsToOpening = () => mounted.current && current.current.visible\n && current.current.session === session && current.current.roleId === roleId;\n if (!isReady || roleId === undefined || !belongsToOpening())\n return;\n try {\n await save(roleId, [...(draft?.menuIds ?? [])]);\n }\n catch (error) {\n if (belongsToOpening())\n throw error;\n return;\n }\n if (belongsToOpening())\n onSaved();\n }, [draft, isReady, roleId, session]);\n\n return { menuIds: initialized ? draft.menuIds : [], onChange, submit, initialized, isReady };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { Form, Toast, Spin, SideSheet } from \"@/ui\";\nimport { DATA_SCOPES, type CreateRoleInput, type Role, type Department } from '@fudanda/shared/identity';\nimport { roleContract, departmentContract } from '@fudanda/react-core/lib/native-operations';\nimport { enumValueOf } from '@fudanda/shared/core';\nimport { UserTransferSelect } from \"@/components/UserTransferSelect\";\nimport type { UserTransferUser } from \"@/components/UserTransferSelect\";\nimport { UserPreviewCell } from \"@/components/UserPreviewCell\";\nimport ExportButton from \"@/components/ExportButton\";\nimport { AppModal } from \"@/components/AppModal\";\nimport ConfigurableTable from \"@/components/ConfigurableTable\";\nimport { usePermission } from \"@fudanda/react-core/hooks/usePermission\";\nimport { useDictItems } from \"@fudanda/react-core/hooks/useDictItems\";\nimport type { ColumnProps } from \"@/ui\";\nimport { createdAtColumn, renderEllipsis } from \"@/utils/table-columns\";\nimport { MenuPermissionPanel } from \"@/components/permissions/MenuPermissionPanel\";\nimport { DataScopePanel } from \"@/components/permissions/DataScopePanel\";\nimport { departmentTreeToTreeData, useDepartmentTree } from \"@fudanda/react-core/hooks/queries/departments\";\nimport { useMenuTree } from \"@fudanda/react-core/hooks/queries/menus\";\nimport { useAllUsers } from \"@fudanda/react-core/hooks/queries/users\";\nimport { useEditModal, formSaveMutation } from \"@/hooks/useEditModal\";\nimport { useAssignRoleMenus, useAssignRoleUsers, useDeleteRoles, useRoleDetail, useRoleList, useRoleUsers, useSaveRole, useUpdateRoleDataScope } from \"@fudanda/react-core/hooks/queries/roles\";\nimport { CreateButton } from \"@/components/toolbar-controls\";\nimport { DateRangeFilter } from \"@/components/search-filters\";\nimport { buildTableSearch, useStatusToggle, useCrudOperationColumn } from \"@/components/list-page/index\";\nimport ModalFooter from \"@/components/ModalFooter\";\nimport { useListPage } from \"@/hooks/useListPage\";\nimport { EditFormModal } from \"@/components/EditFormModal\";\nimport { useStandardWebMcpCrudAdapter } from '@/webmcp-crud';\nimport { useRoleMenuDraft } from './useRoleMenuDraft';\nexport default function RolesPage() {\n const { hasPermission } = usePermission();\n const { options: statusOptions } = useDictItems('common_status');\n const page = useListPage({\n contract: roleContract,\n useList: useRoleList,\n });\n const { tableProps, filterQuery } = page;\n const [menuModalVisible, setMenuModalVisible] = useState(false);\n const [menuRole, setMenuRole] = useState<Role | null>(null);\n const [menuSession, setMenuSession] = useState(0);\n const [userModalVisible, setUserModalVisible] = useState(false);\n const [userRole, setUserRole] = useState<Role | null>(null);\n const [assignedUserIds, setAssignedUserIds] = useState<number[]>([]);\n const [dataScopeModalVisible, setDataScopeModalVisible] = useState(false);\n const [dataScopeRole, setDataScopeRole] = useState<Role | null>(null);\n const [selectedDataScope, setSelectedDataScope] = useState<string>('all');\n const [selectedDeptScopeIds, setSelectedDeptScopeIds] = useState<number[]>([]);\n const menuTreeQuery = useMenuTree({ enabled: menuModalVisible });\n const menuRoleDetailQuery = useRoleDetail(menuRole?.id, menuModalVisible);\n const menuDraft = useRoleMenuDraft({ visible: menuModalVisible, session: menuSession, roleId: menuRole?.id,\n detail: menuRoleDetailQuery.data, isSuccess: menuRoleDetailQuery.isSuccess, isFetching: menuRoleDetailQuery.isFetching });\n const allUsersQuery = useAllUsers({ enabled: userModalVisible });\n const roleUsersQuery = useRoleUsers(userRole?.id, userModalVisible);\n const dataScopeRoleDetailQuery = useRoleDetail(dataScopeRole?.id, dataScopeModalVisible);\n const deptTreeQuery = useDepartmentTree();\n const deptTree = useMemo(() => deptTreeQuery.data ?? [], [deptTreeQuery.data]);\n const saveMutation = useSaveRole();\n const roleModal = useEditModal<Role, Partial<CreateRoleInput>>({\n entityName: '角色',\n save: formSaveMutation(saveMutation, { create: roleContract.create.input.shape.body, update: roleContract.update.input.shape.body }),\n useDetail: useRoleDetail,\n defaults: { status: 'enabled' },\n // 记录里的 null 描述在表单中视为未填\n toValues: (role) => ({ name: role.name, code: role.code, description: role.description ?? undefined, deptScopeIds: role.deptScopeIds, status: role.status }),\n beforeSave: (values, { editing }) => ({ ...values, description: values.description || undefined, ...(editing ? { clearFields: values.description ? [] : ['description'] } : {}) }),\n });\n const editingRole = roleModal.editing;\n const toggleStatusMutation = useSaveRole();\n const deleteMutation = useDeleteRoles();\n useStandardWebMcpCrudAdapter({ resource: 'roles', title: '角色', permission: 'system:role', hasPermission, modal: roleModal,\n list: roleContract.list, detail: roleContract.detail, create: roleContract.create.input.shape.body, update: roleContract.update.input.shape.body,\n createFields: ['name', 'code', 'description', 'deptScopeIds', 'status'], updateFields: ['name', 'code', 'description', 'deptScopeIds', 'status', 'clearFields'], updateClearFields: ['description'],\n fields: ['id', 'name', 'code', 'description', 'deptScopeIds', 'status', 'createdAt', 'updatedAt'], filters: filterQuery,\n remove: id => deleteMutation.mutateAsync([id]), busy: menuModalVisible || userModalVisible || dataScopeModalVisible, guardRecord: (record, action) => { if (action === 'delete' && record.code === 'super_admin') throw new Error('超级管理员角色不允许删除'); },\n guardValues: (values, record) => { if (record?.code === 'super_admin' && values.status === 'disabled') throw new Error('超级管理员角色不允许禁用'); },\n lookups: [{ name: 'departments', title: '部门', operation: departmentContract.flat, permission: 'system:department:list', fields: ['id', 'parentId', 'name'] }] });\n const assignMenusMutation = useAssignRoleMenus();\n const canAssignMenus = menuDraft.isReady && menuTreeQuery.isSuccess && !menuTreeQuery.isFetching && !assignMenusMutation.isPending;\n const assignUsersMutation = useAssignRoleUsers();\n const updateDataScopeMutation = useUpdateRoleDataScope();\n const status = useStatusToggle<Role>({\n toggle: (role, enabled) => toggleStatusMutation.mutateAsync({ id: role.id, values: { status: enabled ? 'enabled' : 'disabled' } }),\n confirmDisable: (role) => ({ danger: true, title: `确认禁用角色「${role.name}」?`, content: '禁用后持有该角色的用户将不能登录。', okText: '确认禁用' }),\n disabled: (role) => role.code === 'super_admin' || !hasPermission('system:role:update'),\n messages: { disabled: '已禁用' },\n });\n useEffect(() => {\n if (userModalVisible)\n setAssignedUserIds((roleUsersQuery.data ?? []).map((u) => u.id));\n }, [userModalVisible, roleUsersQuery.data]);\n useEffect(() => {\n if (dataScopeModalVisible && dataScopeRoleDetailQuery.data) {\n setSelectedDeptScopeIds(dataScopeRoleDetailQuery.data.deptScopeIds ?? []);\n }\n }, [dataScopeModalVisible, dataScopeRoleDetailQuery.data]);\n const openMenuModal = (role: Role) => {\n setMenuSession(session => session + 1);\n setMenuRole(role);\n setMenuModalVisible(true);\n };\n const handleAssignMenus = async () => {\n if (!menuRole || !canAssignMenus)\n return;\n await menuDraft.submit((id, menuIds) => assignMenusMutation.mutateAsync({ params: { id }, body: { menuIds } }), () => {\n Toast.success('菜单权限已更新');\n setMenuModalVisible(false);\n });\n };\n // 扁平化部门列表(供分配用户组件的树形视图使用)\n const flatDepts = useMemo<Department[]>(() => {\n const result: Department[] = [];\n const flatten = (items: Department[]) => {\n items.forEach((d) => {\n result.push(d);\n if (d.children)\n flatten(d.children);\n });\n };\n flatten(deptTree);\n return result;\n }, [deptTree]);\n const allUsers = useMemo<UserTransferUser[]>(() => allUsersQuery.data ?? [], [allUsersQuery.data]);\n const openUserModal = (role: Role) => {\n setUserRole(role);\n setUserModalVisible(true);\n };\n const handleAssignUsers = async () => {\n if (!userRole)\n return;\n await assignUsersMutation.mutateAsync({ params: { id: userRole.id }, body: { userIds: assignedUserIds } });\n Toast.success('用户分配已更新');\n setUserModalVisible(false);\n };\n const openDataScopeModal = (role: Role) => {\n setDataScopeRole(role);\n setSelectedDataScope(role.dataScope ?? 'all');\n setSelectedDeptScopeIds([]);\n setDataScopeModalVisible(true);\n };\n const handleSaveDataScope = async () => {\n if (!dataScopeRole)\n return;\n // 面板以宽 string 维护选中值,提交前收窄为数据范围枚举\n const dataScope = enumValueOf(DATA_SCOPES, selectedDataScope) ?? 'all';\n await updateDataScopeMutation.mutateAsync({\n params: { id: dataScopeRole.id },\n body: dataScope === 'custom' ? { dataScope, deptScopeIds: selectedDeptScopeIds } : { dataScope },\n });\n Toast.success('数据权限已更新');\n setDataScopeModalVisible(false);\n };\n const operationColumn = useCrudOperationColumn<Role>({\n permission: 'system:role',\n edit: roleModal,\n remove: deleteMutation,\n title: '确认删除此角色?',\n disabled: { remove: (row) => row.code === 'super_admin', reason: '超级管理员角色不允许删除' },\n extraBetween: (row) => [\n {\n key: 'menu',\n label: '菜单权限',\n hidden: !hasPermission('system:role:assign'),\n onClick: () => openMenuModal(row),\n },\n ],\n extraAfter: (row) => [\n {\n key: 'users',\n label: '分配用户',\n hidden: !hasPermission('system:role:assign'),\n onClick: () => openUserModal(row),\n },\n {\n key: 'dataScope',\n label: '数据权限',\n hidden: !hasPermission('system:role:update'),\n onClick: () => openDataScopeModal(row),\n },\n ],\n width: 260,\n desktopInlineKeys: ['edit', 'menu', 'delete'],\n });\n const columns: ColumnProps<Role>[] = [\n { title: '角色名称', dataIndex: 'name', width: 160, render: renderEllipsis },\n { title: '角色编码', dataIndex: 'code', width: 160, render: renderEllipsis },\n { title: '描述', dataIndex: 'description', minWidth: 200, render: (_v, record) => renderEllipsis(record.description) },\n {\n title: '数据权限',\n dataIndex: 'dataScope',\n width: 140,\n align: 'center',\n render: (v: string) => {\n const map: Record<string, string> = { all: '全部数据', dept: '本部门及以下', self: '仅本人数据' };\n return map[v] ?? v;\n },\n },\n {\n title: '用户',\n dataIndex: 'userPreview',\n width: 180,\n render: (_: unknown, record: Role) => <UserPreviewCell preview={record.userPreview} count={record.userCount} scope={{ type: 'role', id: record.id, name: record.name }}/>,\n },\n createdAtColumn,\n status.column(),\n operationColumn,\n ];\n return (<div className=\"page-container\">\n\n\n <ConfigurableTable<Role> searchConfig={buildTableSearch({\n page: (page),\n filters: (['keyword', 'status', ['startTime', 'endTime']]),\n overrides: ({\n startTime: (p) => <DateRangeFilter placeholder={[\"开始时间\", \"结束时间\"]} {...p.bindRange(['startTime', 'endTime'])}/>,\n }),\n create: (<CreateButton permission=\"system:role:create\" onClick={roleModal.openCreate}/>),\n actions: (<ExportButton entity=\"system.roles\" query={filterQuery}/>),\n filterTitle: \"角色筛选\",\n actionTitle: \"角色操作\"\n })} columns={columns} {...tableProps}/>\n\n {/* 创建/编辑 Modal */}\n <EditFormModal modal={roleModal} width={480}>\n <Form.Input field=\"name\" label=\"角色名称\" placeholder=\"请输入角色名称\" rules={[{ required: true, message: '请输入角色名称' }]}/>\n <Form.Input field=\"code\" label=\"角色编码\" placeholder=\"请输入角色编码\" rules={[{ required: true, message: '请输入角色编码' }]}/>\n <Form.Input field=\"description\" label=\"描述\" placeholder=\"请输入描述\"/>\n <Form.TreeSelect field=\"deptScopeIds\" label=\"管理范围\" placeholder=\"默认全员(用于工作流「角色」审批人按部门过滤)\" multiple filterTreeNode treeData={departmentTreeToTreeData(deptTree)} style={{ width: '100%' }}/>\n <Form.Select field=\"status\" label=\"状态\" style={{ width: '100%' }} disabled={editingRole?.code === 'super_admin'} optionList={statusOptions} placeholder=\"请选择状态\"/>\n </EditFormModal>\n\n {/* 菜单权限 Modal */}\n <AppModal title={`分配菜单权限 — ${menuRole?.name}`} visible={menuModalVisible} onCancel={() => setMenuModalVisible(false)} onOk={handleAssignMenus} okButtonProps={{ disabled: !canAssignMenus, loading: assignMenusMutation.isPending }} width={640}>\n <MenuPermissionPanel allMenus={menuTreeQuery.data ?? []} checkedMenuIds={menuDraft.menuIds} onChange={menuDraft.onChange} loading={assignMenusMutation.isPending || menuTreeQuery.isFetching || menuRoleDetailQuery.isFetching || (menuRoleDetailQuery.isSuccess && !menuDraft.initialized)}/>\n </AppModal>\n\n {/* 数据权限 Modal */}\n <AppModal title={`数据权限 — ${dataScopeRole?.name}`} visible={dataScopeModalVisible} onCancel={() => setDataScopeModalVisible(false)} onOk={handleSaveDataScope} okButtonProps={{ disabled: !dataScopeRoleDetailQuery.isSuccess, loading: updateDataScopeMutation.isPending }} width={400}>\n <DataScopePanel dataScope={selectedDataScope} deptScopeIds={selectedDeptScopeIds} deptTree={deptTree} onScopeChange={(v) => setSelectedDataScope(v ?? 'all')} onDeptIdsChange={setSelectedDeptScopeIds} loading={deptTreeQuery.isFetching || dataScopeRoleDetailQuery.isFetching}/>\n </AppModal>\n\n {/* 分配用户 SideSheet */}\n <SideSheet title={<span>分配用户 — {userRole?.name}</span>} visible={userModalVisible} onCancel={() => setUserModalVisible(false)} width={720} footer={(<ModalFooter onCancel={() => setUserModalVisible(false)} onOk={handleAssignUsers} okText=\"保存\" loading={assignUsersMutation.isPending} disabled={!roleUsersQuery.isSuccess || !allUsersQuery.isSuccess}/>)}>\n {allUsersQuery.isFetching || roleUsersQuery.isFetching ? (<div style={{ display: 'flex', justifyContent: 'center', padding: 40 }}>\n <Spin />\n </div>) : (<UserTransferSelect dataSource={allUsers} value={assignedUserIds} onChange={setAssignedUserIds} departments={flatDepts}/>)}\n </SideSheet>\n </div>);\n}\n"]}
@@ -1,2 +1,2 @@
1
- import{n as e}from"./rolldown-runtime-Bruge11p.js";import{It as t,M as n,m as r}from"./clipboard-dpqHdCyy.js";import{a as i,i as a,r as o,t as s}from"./SessionClientTag-ht0d4JHq.js";import{n as c,t as l}from"./DateTimeText-DldSUPjX.js";import{C as u,S as d}from"./App-CfQx7jWq.js";import{n as f,t as p}from"./AppModal-CVoUC2t3.js";import{jsx as m,jsxs as h}from"react/jsx-runtime";function g({conflict:e,loading:t,onConfirm:n,onCancel:a}){let o=e?.sessions??[];return/* @__PURE__ */ h(p,{title:`该账号已在其他设备登录`,visible:e!==null,onCancel:a,maskClosable:!1,width:440,footer:/* @__PURE__ */ h(`div`,{className:`session-conflict-footer`,children:[/* @__PURE__ */ m(r,{theme:`borderless`,type:`tertiary`,onClick:a,disabled:t,children:`取消`}),/* @__PURE__ */ m(r,{type:`danger`,theme:`solid`,loading:t,onClick:n,children:`下线其他设备并登录`})]}),children:[/* @__PURE__ */ h(`div`,{className:`session-conflict-intro`,children:[/* @__PURE__ */ m(d,{size:18,"aria-hidden":!0}),/* @__PURE__ */ h(_,{type:`secondary`,children:[`受安全策略限制,该账号最多同时在 `,e?.maxSessions??1,` 处登录。下线以下设备后即可继续;如不是您本人的登录,请尽快修改密码。`]})]}),/* @__PURE__ */ m(`ul`,{className:`session-conflict-list`,"aria-label":`占用名额的设备`,children:o.map((e,t)=>/* @__PURE__ */ h(`li`,{className:`session-conflict-item`,children:[/* @__PURE__ */ m(s,{client:e.client,size:20,className:`session-conflict-icon`}),/* @__PURE__ */ h(`div`,{className:`session-conflict-body`,children:[/* @__PURE__ */ m(`div`,{className:`session-conflict-title`,children:/* @__PURE__ */ h(_,{strong:!0,children:[i(e.client),` · `,e.browser,` / `,e.os]})}),/* @__PURE__ */ h(_,{type:`tertiary`,size:`small`,className:`session-conflict-meta`,children:[`IP: ${e.ip}`,` · `,`登录 `,/* @__PURE__ */ m(l,{value:e.loginAt}),` · `,`活跃 `,/* @__PURE__ */ m(l,{value:e.lastActiveAt})]})]})]},`${e.ip}-${e.loginAt}-${t}`))})]})}var _;function v(){return(v=e((()=>{n(),u(),f(),c(),a(),o(),{Text:_}=t})))()}v();export{g as default};
2
- //# sourceMappingURL=SessionConflictModal-Dw4opoNP.js.map
1
+ import{n as e}from"./rolldown-runtime-Bruge11p.js";import{It as t,M as n,m as r}from"./clipboard-dpqHdCyy.js";import{a as i,i as a,r as o,t as s}from"./SessionClientTag-ht0d4JHq.js";import{n as c,t as l}from"./DateTimeText-DldSUPjX.js";import{C as u,S as d}from"./App-nh6_qOo8.js";import{n as f,t as p}from"./AppModal-CEouaU03.js";import{jsx as m,jsxs as h}from"react/jsx-runtime";function g({conflict:e,loading:t,onConfirm:n,onCancel:a}){let o=e?.sessions??[];return/* @__PURE__ */ h(p,{title:`该账号已在其他设备登录`,visible:e!==null,onCancel:a,maskClosable:!1,width:440,footer:/* @__PURE__ */ h(`div`,{className:`session-conflict-footer`,children:[/* @__PURE__ */ m(r,{theme:`borderless`,type:`tertiary`,onClick:a,disabled:t,children:`取消`}),/* @__PURE__ */ m(r,{type:`danger`,theme:`solid`,loading:t,onClick:n,children:`下线其他设备并登录`})]}),children:[/* @__PURE__ */ h(`div`,{className:`session-conflict-intro`,children:[/* @__PURE__ */ m(d,{size:18,"aria-hidden":!0}),/* @__PURE__ */ h(_,{type:`secondary`,children:[`受安全策略限制,该账号最多同时在 `,e?.maxSessions??1,` 处登录。下线以下设备后即可继续;如不是您本人的登录,请尽快修改密码。`]})]}),/* @__PURE__ */ m(`ul`,{className:`session-conflict-list`,"aria-label":`占用名额的设备`,children:o.map((e,t)=>/* @__PURE__ */ h(`li`,{className:`session-conflict-item`,children:[/* @__PURE__ */ m(s,{client:e.client,size:20,className:`session-conflict-icon`}),/* @__PURE__ */ h(`div`,{className:`session-conflict-body`,children:[/* @__PURE__ */ m(`div`,{className:`session-conflict-title`,children:/* @__PURE__ */ h(_,{strong:!0,children:[i(e.client),` · `,e.browser,` / `,e.os]})}),/* @__PURE__ */ h(_,{type:`tertiary`,size:`small`,className:`session-conflict-meta`,children:[`IP: ${e.ip}`,` · `,`登录 `,/* @__PURE__ */ m(l,{value:e.loginAt}),` · `,`活跃 `,/* @__PURE__ */ m(l,{value:e.lastActiveAt})]})]})]},`${e.ip}-${e.loginAt}-${t}`))})]})}var _;function v(){return(v=e((()=>{n(),u(),f(),c(),a(),o(),{Text:_}=t})))()}v();export{g as default};
2
+ //# sourceMappingURL=SessionConflictModal-Bm38eExL.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionConflictModal-Dw4opoNP.js","names":["__esmMin","Typography","init_ui","Button","sessionClientLabel","init_session_client_label","init_SessionClientTag","SessionClientIcon","init_DateTimeText","DateTimeText","init_shield_alert","ShieldAlert","init_AppModal","AppModal","SessionConflictModal","sessions","conflict","onCancel","loading","onConfirm","Text","s","index","init_SessionConflictModal$1"],"sources":["../../src/pages/login/SessionConflictModal.css","../../src/pages/login/SessionConflictModal.tsx"],"sourcesContent":["/* 登录页:会话并发冲突确认弹层 */\n.session-conflict-intro {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n margin-bottom: 14px;\n line-height: 1.6;\n}\n\n.session-conflict-intro svg {\n flex: none;\n margin-top: 3px;\n color: var(--arc-antd-color-danger);\n}\n\n.session-conflict-list {\n margin: 0;\n padding: 0;\n list-style: none;\n border: 1px solid var(--arc-antd-color-border);\n border-radius: var(--arc-antd-border-radius-medium);\n max-height: 260px;\n overflow-y: auto;\n}\n\n.session-conflict-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px 14px;\n}\n\n.session-conflict-item + .session-conflict-item {\n border-top: 1px solid var(--arc-antd-color-border);\n}\n\n.session-conflict-icon {\n flex: none;\n margin-top: 2px;\n color: var(--arc-antd-color-text-2);\n}\n\n.session-conflict-body {\n min-width: 0;\n flex: 1;\n}\n\n.session-conflict-title {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.session-conflict-meta {\n display: block;\n overflow-wrap: anywhere;\n}\n\n.session-conflict-footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n","import { Button, Typography } from \"@/ui\";\nimport { ShieldAlert } from 'lucide-react';\nimport type { ApiSessionConflict as SessionConflict } from '@fudanda/shared/api/identity';\nimport AppModal from \"@/components/AppModal\";\nimport DateTimeText from \"@/components/DateTimeText\";\nimport { sessionClientLabel } from '@/components/session-client-label';\nimport { SessionClientIcon } from \"@/components/SessionClientTag\";\nimport \"@/pages/login/SessionConflictModal.css\";\nconst { Text } = Typography;\ninterface SessionConflictModalProps {\n readonly conflict: SessionConflict | null;\n readonly loading?: boolean;\n /** 用户确认下线其它设备并继续登录 */\n readonly onConfirm: () => void;\n readonly onCancel: () => void;\n}\n/**\n * 会话并发「拒绝新登录」命中时的确认弹层:展示占用名额的既有设备,用户可选择下线它们并继续登录(凭票据,不必重输密码)。\n * 密码 / MFA / 企业 SSO / 第三方 OAuth 四条路径都在登录页收口到这一个弹层。\n */\nexport default function SessionConflictModal({ conflict, loading, onConfirm, onCancel }: SessionConflictModalProps) {\n const sessions = conflict?.sessions ?? [];\n return (<AppModal title=\"该账号已在其他设备登录\" visible={conflict !== null} onCancel={onCancel} maskClosable={false} width={440} footer={(<div className=\"session-conflict-footer\">\n <Button theme=\"borderless\" type=\"tertiary\" onClick={onCancel} disabled={loading}>取消</Button>\n <Button type=\"danger\" theme=\"solid\" loading={loading} onClick={onConfirm}>下线其他设备并登录</Button>\n </div>)}>\n <div className=\"session-conflict-intro\">\n <ShieldAlert size={18} aria-hidden/>\n <Text type=\"secondary\">\n 受安全策略限制,该账号最多同时在 {conflict?.maxSessions ?? 1} 处登录。下线以下设备后即可继续;如不是您本人的登录,请尽快修改密码。\n </Text>\n </div>\n <ul className=\"session-conflict-list\" aria-label=\"占用名额的设备\">\n {sessions.map((s, index) => (<li key={`${s.ip}-${s.loginAt}-${index}`} className=\"session-conflict-item\">\n <SessionClientIcon client={s.client} size={20} className=\"session-conflict-icon\"/>\n <div className=\"session-conflict-body\">\n <div className=\"session-conflict-title\">\n <Text strong>{sessionClientLabel(s.client)} · {s.browser} / {s.os}</Text>\n </div>\n <Text type=\"tertiary\" size=\"small\" className=\"session-conflict-meta\">\n {`IP: ${s.ip}`}\n {' · '}登录 <DateTimeText value={s.loginAt}/>\n {' · '}活跃 <DateTimeText value={s.lastActiveAt}/>\n </Text>\n </div>\n </li>))}\n </ul>\n </AppModal>);\n}\n"],"mappings":"A,6XCoBA,SAAwBc,EAAqB,CAAE,WAAU,UAAS,YAAW,YAAuC,CAChH,IAAMC,EAAWC,GAAU,UAAY,CAAC,EACxC,MAAQ,kBAACH,EAAD,CAAU,MAAM,cAAc,QAASG,IAAa,KAAgB,WAAU,aAAc,GAAO,MAAO,IAAK,OAAS,kBAAC,MAAD,CAAK,UAAU,0BAAf,SAAA,CAC1H,kBAACb,EAAD,CAAQ,MAAM,aAAa,KAAK,WAAW,QAASc,EAAU,SAAUC,EAAS,SAAA,IAAU,CAAA,EAC3F,kBAACf,EAAD,CAAQ,KAAK,SAAS,MAAM,QAAiB,UAAS,QAASgB,EAAW,SAAA,WAAiB,CAAA,CACxF,C,GAHD,SAAA,CAIN,kBAAC,MAAD,CAAK,UAAU,yBAAf,SAAA,CACE,kBAACR,EAAD,CAAa,KAAM,GAAI,cAAA,EAAY,CAAA,EACnC,kBAACS,EAAD,CAAM,KAAK,YAAX,SAAA,CAAuB,oBACHJ,GAAU,aAAe,EAAE,qCACzC,CACH,CAAA,CAAA,CACL,CAAA,EAAA,kBAAC,KAAD,CAAI,UAAU,wBAAwB,aAAW,UAC9C,SAAAD,EAAS,KAAK,EAAG,IAAW,kBAAC,KAAD,CAA0C,UAAU,wBAApD,SAAA,CACzB,kBAACR,EAAD,CAAmB,OAAQc,EAAE,OAAQ,KAAM,GAAI,UAAU,uBAAwB,CAAA,EACjF,kBAAC,MAAD,CAAK,UAAU,wBAAf,SAAA,CACE,kBAAC,MAAD,CAAK,UAAU,yBACb,SAAA,kBAACD,EAAD,CAAM,OAAA,GAAN,SAAA,CAAchB,EAAmBiB,EAAE,MAAM,EAAE,MAAIA,EAAE,QAAQ,MAAIA,EAAE,EAAS,C,EACrE,CAAA,EACL,kBAACD,EAAD,CAAM,KAAK,WAAW,KAAK,QAAQ,UAAU,wBAA7C,SAAA,CACG,OAAOC,EAAE,KACT,MAAM,MAAG,kBAACZ,EAAD,CAAc,MAAOY,EAAE,OAAS,CAAA,EACzC,MAAM,MAAG,kBAACZ,EAAD,CAAc,MAAOY,EAAE,YAAc,CAAA,CAC3C,CACH,CAAA,CAAA,CACH,CAAA,CAAA,CAZgC,EAAA,GAAGA,EAAE,GAAG,GAAGA,EAAE,QAAQ,GAAGC,GAYxD,CAAE,CACN,CAAA,CACI,C,EACd,C,4DAxCQ,SAASrB,C"}
1
+ {"version":3,"file":"SessionConflictModal-Bm38eExL.js","names":["__esmMin","Typography","init_ui","Button","sessionClientLabel","init_session_client_label","init_SessionClientTag","SessionClientIcon","init_DateTimeText","DateTimeText","init_shield_alert","ShieldAlert","init_AppModal","AppModal","SessionConflictModal","sessions","conflict","onCancel","loading","onConfirm","Text","s","index","init_SessionConflictModal$1"],"sources":["../../src/pages/login/SessionConflictModal.css","../../src/pages/login/SessionConflictModal.tsx"],"sourcesContent":["/* 登录页:会话并发冲突确认弹层 */\n.session-conflict-intro {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n margin-bottom: 14px;\n line-height: 1.6;\n}\n\n.session-conflict-intro svg {\n flex: none;\n margin-top: 3px;\n color: var(--arc-antd-color-danger);\n}\n\n.session-conflict-list {\n margin: 0;\n padding: 0;\n list-style: none;\n border: 1px solid var(--arc-antd-color-border);\n border-radius: var(--arc-antd-border-radius-medium);\n max-height: 260px;\n overflow-y: auto;\n}\n\n.session-conflict-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px 14px;\n}\n\n.session-conflict-item + .session-conflict-item {\n border-top: 1px solid var(--arc-antd-color-border);\n}\n\n.session-conflict-icon {\n flex: none;\n margin-top: 2px;\n color: var(--arc-antd-color-text-2);\n}\n\n.session-conflict-body {\n min-width: 0;\n flex: 1;\n}\n\n.session-conflict-title {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.session-conflict-meta {\n display: block;\n overflow-wrap: anywhere;\n}\n\n.session-conflict-footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n","import { Button, Typography } from \"@/ui\";\nimport { ShieldAlert } from 'lucide-react';\nimport type { ApiSessionConflict as SessionConflict } from '@fudanda/shared/api/identity';\nimport AppModal from \"@/components/AppModal\";\nimport DateTimeText from \"@/components/DateTimeText\";\nimport { sessionClientLabel } from '@/components/session-client-label';\nimport { SessionClientIcon } from \"@/components/SessionClientTag\";\nimport \"@/pages/login/SessionConflictModal.css\";\nconst { Text } = Typography;\ninterface SessionConflictModalProps {\n readonly conflict: SessionConflict | null;\n readonly loading?: boolean;\n /** 用户确认下线其它设备并继续登录 */\n readonly onConfirm: () => void;\n readonly onCancel: () => void;\n}\n/**\n * 会话并发「拒绝新登录」命中时的确认弹层:展示占用名额的既有设备,用户可选择下线它们并继续登录(凭票据,不必重输密码)。\n * 密码 / MFA / 企业 SSO / 第三方 OAuth 四条路径都在登录页收口到这一个弹层。\n */\nexport default function SessionConflictModal({ conflict, loading, onConfirm, onCancel }: SessionConflictModalProps) {\n const sessions = conflict?.sessions ?? [];\n return (<AppModal title=\"该账号已在其他设备登录\" visible={conflict !== null} onCancel={onCancel} maskClosable={false} width={440} footer={(<div className=\"session-conflict-footer\">\n <Button theme=\"borderless\" type=\"tertiary\" onClick={onCancel} disabled={loading}>取消</Button>\n <Button type=\"danger\" theme=\"solid\" loading={loading} onClick={onConfirm}>下线其他设备并登录</Button>\n </div>)}>\n <div className=\"session-conflict-intro\">\n <ShieldAlert size={18} aria-hidden/>\n <Text type=\"secondary\">\n 受安全策略限制,该账号最多同时在 {conflict?.maxSessions ?? 1} 处登录。下线以下设备后即可继续;如不是您本人的登录,请尽快修改密码。\n </Text>\n </div>\n <ul className=\"session-conflict-list\" aria-label=\"占用名额的设备\">\n {sessions.map((s, index) => (<li key={`${s.ip}-${s.loginAt}-${index}`} className=\"session-conflict-item\">\n <SessionClientIcon client={s.client} size={20} className=\"session-conflict-icon\"/>\n <div className=\"session-conflict-body\">\n <div className=\"session-conflict-title\">\n <Text strong>{sessionClientLabel(s.client)} · {s.browser} / {s.os}</Text>\n </div>\n <Text type=\"tertiary\" size=\"small\" className=\"session-conflict-meta\">\n {`IP: ${s.ip}`}\n {' · '}登录 <DateTimeText value={s.loginAt}/>\n {' · '}活跃 <DateTimeText value={s.lastActiveAt}/>\n </Text>\n </div>\n </li>))}\n </ul>\n </AppModal>);\n}\n"],"mappings":"A,6XCoBA,SAAwBc,EAAqB,CAAE,WAAU,UAAS,YAAW,YAAuC,CAChH,IAAMC,EAAWC,GAAU,UAAY,CAAC,EACxC,MAAQ,kBAACH,EAAD,CAAU,MAAM,cAAc,QAASG,IAAa,KAAgB,WAAU,aAAc,GAAO,MAAO,IAAK,OAAS,kBAAC,MAAD,CAAK,UAAU,0BAAf,SAAA,CAC1H,kBAACb,EAAD,CAAQ,MAAM,aAAa,KAAK,WAAW,QAASc,EAAU,SAAUC,EAAS,SAAA,IAAU,CAAA,EAC3F,kBAACf,EAAD,CAAQ,KAAK,SAAS,MAAM,QAAiB,UAAS,QAASgB,EAAW,SAAA,WAAiB,CAAA,CACxF,C,GAHD,SAAA,CAIN,kBAAC,MAAD,CAAK,UAAU,yBAAf,SAAA,CACE,kBAACR,EAAD,CAAa,KAAM,GAAI,cAAA,EAAY,CAAA,EACnC,kBAACS,EAAD,CAAM,KAAK,YAAX,SAAA,CAAuB,oBACHJ,GAAU,aAAe,EAAE,qCACzC,CACH,CAAA,CAAA,CACL,CAAA,EAAA,kBAAC,KAAD,CAAI,UAAU,wBAAwB,aAAW,UAC9C,SAAAD,EAAS,KAAK,EAAG,IAAW,kBAAC,KAAD,CAA0C,UAAU,wBAApD,SAAA,CACzB,kBAACR,EAAD,CAAmB,OAAQc,EAAE,OAAQ,KAAM,GAAI,UAAU,uBAAwB,CAAA,EACjF,kBAAC,MAAD,CAAK,UAAU,wBAAf,SAAA,CACE,kBAAC,MAAD,CAAK,UAAU,yBACb,SAAA,kBAACD,EAAD,CAAM,OAAA,GAAN,SAAA,CAAchB,EAAmBiB,EAAE,MAAM,EAAE,MAAIA,EAAE,QAAQ,MAAIA,EAAE,EAAS,C,EACrE,CAAA,EACL,kBAACD,EAAD,CAAM,KAAK,WAAW,KAAK,QAAQ,UAAU,wBAA7C,SAAA,CACG,OAAOC,EAAE,KACT,MAAM,MAAG,kBAACZ,EAAD,CAAc,MAAOY,EAAE,OAAS,CAAA,EACzC,MAAM,MAAG,kBAACZ,EAAD,CAAc,MAAOY,EAAE,YAAc,CAAA,CAC3C,CACH,CAAA,CAAA,CACH,CAAA,CAAA,CAZgC,EAAA,GAAGA,EAAE,GAAG,GAAGA,EAAE,QAAQ,GAAGC,GAYxD,CAAE,CACN,CAAA,CACI,C,EACd,C,4DAxCQ,SAASrB,C"}
@@ -0,0 +1,17 @@
1
+ import{n as e}from"./rolldown-runtime-Bruge11p.js";import{A as t,Bt as n,E as r,It as i,M as a,N as o,O as s,Rt as c,T as l,Ut as u,Wt as d,b as f,bt as p,dt as m,f as h,g,it as _,j as v,m as y,n as b,r as x,rt as ee,st as te,ut as ne,xt as S,zt as C}from"./clipboard-dpqHdCyy.js";import{i as w}from"./feedback-B1UL2ETz.js";import{n as T,t as E}from"./MasterDetailLayout-ByIBpmkZ.js";import{a as re,i as ie,s as D}from"./toolbar-controls-CrM8hKZg.js";import{n as ae,t as oe}from"./save-CSrPWJxC.js";import{a as se,i as ce,n as le,o as ue,r as de,s as fe,t as pe}from"./schemas-CVYuqWs9.js";import{n as me,t as he}from"./rendered-slot-G6nvF0nR.js";import{n as ge,t as _e}from"./SearchToolbar-KtXD_Wgr.js";import{n as ve,t as ye}from"./webmcp-control-BR0YABIY.js";import{a as be,o as xe}from"./App-nh6_qOo8.js";import{i as Se,r as Ce}from"./ArcBaseAdmin-CX7fQz4x.js";import{a as O,i as k,o as A,r as j}from"./SettingRow-Bh2bBjdL.js";import{Fragment as we,useEffect as Te,useMemo as M,useRef as Ee,useState as De}from"react";import{useAdminTitle as Oe}from"@fudanda/admin-antd/core/admin/runtime";import{Fragment as N,jsx as P,jsxs as F}from"react/jsx-runtime";import{Alert as ke,Button as Ae,Space as je,Switch as Me,Typography as I}from"antd";import{GoaError as Ne}from"@fudanda/client";import{goTransport as L}from"@fudanda/admin-antd/core/lib/go-transport";import{Link as Pe}from"react-router-dom";import{settingsContract as Fe,settingsWriteOperations as Ie}from"@fudanda/admin-antd/core/lib/native-operations";import{usePermission as Le}from"@fudanda/admin-antd/core/hooks/usePermission";import{useRenderedSlot as Re}from"@fudanda/admin-antd/core/hooks/useRenderedSlot";import{useListSearch as ze}from"@fudanda/admin-antd/core/hooks/useListSearch";import{useCurrentUserMenuTree as Be,useMenuTree as Ve}from"@fudanda/admin-antd/core/hooks/queries/menus";import{settingsKeys as He,useSaveSettings as Ue,useSettings as We}from"@fudanda/admin-antd/core/hooks/queries/settings";import{THEME_COLOR_PRESETS as Ge}from"@fudanda/admin-antd/core/lib/theme-color";import{textMatches as Ke}from"@fudanda/admin-antd/core/utils/pinyin";import{usePinyinReady as qe}from"@fudanda/admin-antd/core/hooks/usePinyinReady";import{canOverridePreference as R,defaultPreferences as Je,describePreferenceCondition as Ye,getPreferenceValue as z,isPreferenceApplicable as Xe,preferenceDefinitions as B,preferenceGroups as V,resolvePreferences as Ze,setPreferenceValue as H}from"@fudanda/client/preferences";import{CAPTCHA_COMPLEXITY_LABELS as Qe,SETTINGS_MODULES as $e}from"@fudanda/client/settings";import{foundationSettingSchemas as et}from"@fudanda/client/settings/foundation";import{mcpTools as tt}from"@fudanda/client/api/mcp-tools";var U,W;function G(){return(G=e((()=>{
2
+ /**
3
+ * @license lucide-react v1.67.0 - ISC
4
+ *
5
+ * This source code is licensed under the ISC license.
6
+ * See the LICENSE file in the root directory of this source tree.
7
+ */
8
+ S(),U={name:`external-link`,size:24,node:[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]},U.node,W=p(U)})))()}var K,nt;function rt(){return(rt=e((()=>{
9
+ /**
10
+ * @license lucide-react v1.67.0 - ISC
11
+ *
12
+ * This source code is licensed under the ISC license.
13
+ * See the LICENSE file in the root directory of this source tree.
14
+ */
15
+ S(),K={name:`image-plus`,size:24,node:[[`path`,{d:`M16 5h6`,key:`1vod17`}],[`path`,{d:`M19 2v6`,key:`4bpg5p`}],[`path`,{d:`M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5`,key:`1ue2ih`}],[`path`,{d:`m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21`,key:`1xmnt7`}],[`circle`,{cx:`9`,cy:`9`,r:`2`,key:`af1f0g`}]]},K.node,nt=p(K)})))()}function it({primary:e,filters:t,onRefresh:n,refreshing:r,onReset:i,actions:a,mobileActions:o,extra:s,filterTitle:c,actionTitle:l,className:u}){let d=n?/* @__PURE__ */ P(ie,{onClick:n,loading:r}):null,f=Re(),p=q(a)||q(s)?/* @__PURE__ */ F(N,{children:[/* @__PURE__ */ P(he,{ref:f.probeRef,children:a}),s]}):void 0;return/* @__PURE__ */ P(_e,{className:u,primary:/* @__PURE__ */ F(N,{children:[e,t,d,i?/* @__PURE__ */ P(re,{onClick:i}):null]}),actions:p,mobilePrimary:/* @__PURE__ */ F(N,{children:[e,d]}),mobileFilters:q(t)?t:void 0,mobileActions:o??(f.rendered?a:!1),filterTitle:c,actionTitle:l,onFilterReset:i})}var q;function at(){return(at=e((()=>{ge(),D(),me(),q=e=>!!e})))()}var ot;function st(){return(st=e((()=>{ot={captchaEnabled:{title:`登录验证码`,description:`开启后登录必须输入图形验证码`},captchaComplexity:{title:`验证码复杂度`,description:`仅在开启登录验证码后生效`},uploadValidateType:{title:`校验真实文件类型`,description:`基于 magic bytes 识别,防止伪造 MIME type 绕过校验`},uploadAllowedTypes:{title:`允许的 MIME 类型`,description:`支持通配符(如 image/*);填 * 或 */* 放行全部类型`},uploadMaxSizeMb:{title:`单文件大小上限(MB)`,description:`0 表示不限制;超过的上传(含分片)将被拒绝`},chunkThresholdMb:{title:`分片上传阈值(MB)`,description:`超过该大小的文件走分片上传 + 断点续传,不超过则单请求上传;受反向代理请求体上限约束`},chunkSizeMb:{title:`分片大小(MB)`,description:`服务端裁定的分片基线,不低于对象存储要求的最小分片;文件过大时自动上调以不超过片数上限`},watermark:{title:`水印`},"watermark.enabled":{title:`页面水印`,description:`开启后全站叠加水印(防截图泄漏)`},"watermark.content":{title:`水印文本`,description:`留空则显示当前用户名`},"watermark.fontSize":{title:`字体大小(px)`},"watermark.opacity":{title:`透明度(1-100)`},preferencesEntryEnabled:{title:`偏好设置入口`,description:`显示在用户头像下拉菜单,关闭后隐藏“偏好设置”(含锁屏密码设置)`}}})))()}function J(e){return(e.def.checks??[]).map(e=>e._zod.def)}function Y(e){if(e instanceof de)return Y(e.unwrap());if(e instanceof pe)return Object.values(e.enum).filter(e=>typeof e==`string`);if(e instanceof ce){let t=[...e.values];return t.every(e=>typeof e==`string`)?t:void 0}if(e instanceof ue){let t=e.options.map(e=>Y(e));return t.every(e=>e!==void 0)?t.flat():void 0}if(e instanceof le){let t=Y(e.def.left),n=Y(e.def.right);return t&&n?t.filter(e=>n.includes(e)):t??n}}function X(e){let t=e,n={},r=!1;for(;;){let e=t.meta();if(e&&(e.title||e.description)&&!n.title&&(n={title:e.title,description:e.description}),t instanceof de){let e=t.unwrap();if(!(e instanceof se))return{meta:n,leaf:{kind:`unknown`}};t=e;continue}let i=t.def;if(i.type===`nullable`&&(r=!0),(i.type==="default"||i.type===`prefault`||i.type===`optional`||i.type===`nullable`)&&i.innerType)t=i.innerType;else break}let i=t.def,a=Y(t);if(a?.length)return{meta:n,leaf:{kind:`enum`,options:a}};switch(i.type){case`boolean`:return{meta:n,leaf:{kind:`boolean`}};case`number`:{let e=J(t),i=e.find(e=>e.check===`greater_than`),a=e.find(e=>e.check===`less_than`),o=e.some(e=>e.check===`number_format`)||t.def.format===`safeint`,s=(e,t)=>e?.value===void 0?void 0:e.inclusive===!1&&o?e.value+t:e.value;return{meta:n,leaf:{kind:`number`,int:o,min:s(i,1),max:s(a,-1),nullable:r}}}case`enum`:return{meta:n,leaf:{kind:`enum`,options:Object.values(i.entries??{})}};case`string`:return{meta:n,leaf:{kind:`string`,maxLength:J(t).find(e=>e.check===`max_length`)?.maximum}};case`array`:{let e=i.element?X(i.element):null;return e?.leaf.kind===`string`||e?.leaf.kind===`enum`?{meta:n,leaf:{kind:`string-array`,maxItems:J(t).find(e=>e.check===`max_length`)?.maximum}}:{meta:n,leaf:{kind:`unknown`}}}case`object`:return{meta:n,leaf:{kind:`object`,shape:t.shape}};default:return{meta:n,leaf:{kind:`unknown`}}}}function ct(e,t){return JSON.stringify(e)===JSON.stringify(t)}function lt(e,t,n){if(t.length===1)return{...e,[t[0]]:n};let[r,...i]=t,a=e[r]??{};return{...e,[r]:lt(a,i,n)}}function ut(e,t){return t.reduce((e,t)=>e&&typeof e==`object`?e[t]:void 0,e)}function dt({schema:e,value:r,inheritedValue:i,onChange:a,disabled:o,allowRevert:s=!0,enumLabels:c,excludeFields:l,fieldLabels:f}){let p=(e,t)=>a(lt(r,e,t)),m=(e,a)=>{let l=e.join(`.`),m=ut(r,e),h=i?ut(i,e):void 0,g=i!==void 0&&!ct(m,h),_=s&&g&&!o?/* @__PURE__ */ P(y,{size:`small`,theme:`borderless`,onClick:()=>p(e,h),children:`恢复继承`}):null,v=a.meta.title??f?.[l]?.title??e[e.length-1],b;switch(a.leaf.kind){case`boolean`:b=/* @__PURE__ */ P(d,{checked:!!m,disabled:o,onChange:t=>p(e,t)});break;case`number`:{let{min:t,max:r,int:i,nullable:s}=a.leaf;b=/* @__PURE__ */ P(n,{style:{width:160},min:t,max:r,precision:i?0:void 0,disabled:o,value:typeof m==`number`?m:void 0,placeholder:s?`留空 = 未设置`:void 0,onChange:t=>{typeof t==`number`&&Number.isFinite(t)?p(e,i?Math.trunc(t):t):s&&p(e,null)}});break}case`enum`:b=/* @__PURE__ */ P(u,{style:{width:200},disabled:o,value:typeof m==`string`?m:void 0,optionList:a.leaf.options.map(e=>({value:e,label:c?.[l]?.[e]??e})),onChange:t=>p(e,t)});break;case`string`:b=/* @__PURE__ */ P(C,{style:{width:280},disabled:o,maxLength:a.leaf.maxLength,value:typeof m==`string`?m:``,onChange:t=>p(e,t)});break;case`string-array`:b=/* @__PURE__ */ P(t,{style:{width:360,maxWidth:`100%`},disabled:o,max:a.leaf.maxItems,value:Array.isArray(m)?m:[],allowDuplicates:!1,separator:[`,`,` `,`
16
+ `],addOnBlur:!0,placeholder:`输入后按回车添加`,onChange:t=>p(e,t)});break;default:b=/* @__PURE__ */ P(`span`,{style:{color:`var(--arc-antd-color-text-2)`},children:`该字段类型暂不支持在通用设置页编辑`})}return/* @__PURE__ */ P(k,{title:v,description:a.meta.description??f?.[l]?.description,control:b,overridden:g,extra:_},l)},h=(e,t)=>{let n=Object.entries(e).filter(([e])=>!l?.includes([...t,e].join(`.`))),r=n.filter(([,e])=>X(e).leaf.kind!==`object`),i=n.filter(([,e])=>X(e).leaf.kind===`object`);return/* @__PURE__ */ F(N,{children:[r.map(([e,n],r)=>/* @__PURE__ */ F(we,{children:[r>0?/* @__PURE__ */ P(j,{}):null,m([...t,e],X(n))]},e)),i.map(([e,n])=>{let r=X(n);return r.leaf.kind===`object`?/* @__PURE__ */ P(O,{title:r.meta.title??f?.[[...t,e].join(`.`)]?.title??e,description:r.meta.description??f?.[[...t,e].join(`.`)]?.description,children:h(r.leaf.shape,[...t,e])},e):null})]})},g=X(e);return/* @__PURE__ */ P(`div`,{children:g.leaf.kind===`object`?h(g.leaf.shape,[]):null})}function ft(){return(ft=e((()=>{a(),fe(),A()})))()}function pt(e){return M(()=>{let t=[],n=(e,r)=>{for(let i of e){if(i.type===`menu`&&i.path&&i.status===`enabled`&&i.visible){let e=i.isExternal&&i.embed?`/embed/${i.id}`:i.path;t.push({id:i.id,title:i.title,path:e,icon:i.icon,breadcrumb:r})}i.children?.length&&n(i.children,i.type===`directory`?[...r,i.title]:r)}};return n(e,[]),t},[e])}function Z(){return(Z=e((()=>{})))()}function Q(e,t){return!R(t,e)||z(e.defaults,t)!==z(Je,t)}function mt({value:e,disabled:t,onChange:n,label:r}){let i=Ge.find(t=>t.key===e),a=i?.light.primary??e,o=Ge.map(e=>({value:e.key,label:e.name}));return i||o.push({value:e,label:e}),/* @__PURE__ */ F(`div`,{className:`preference-policy-editor__color`,children:[/* @__PURE__ */ P(u,{"aria-label":r,value:e,optionList:o,disabled:t,onChange:e=>{typeof e==`string`&&n(e)}}),/* @__PURE__ */ P(g,{alpha:!1,usePopover:!0,value:g.colorStringToValue(a),onChange:e=>{t||n(e.hex)},children:/* @__PURE__ */ P(`button`,{type:`button`,className:`preference-policy-editor__swatch`,disabled:t,"aria-label":`自定义主题色`,title:`自定义主题色`,style:{backgroundColor:a}})})]})}function ht({value:e,onChange:t,disabled:r}){let{hasPermission:a}=Le(),o=a(`system:menu:list`),s=Ve({enabled:o}),p=Be(),m=pt(s.data??p.data??[]),{draftParams:g,bind:b,setField:x,handleReset:te}=ze({defaults:gt,listKey:He.module(`ui`),refetchOnSearch:!1}),S=M(()=>{let t=[{value:`/`,label:`首页(默认)`}],n=/* @__PURE__ */ new Set([`/`]);for(let e of m)!e.path.startsWith(`/`)||e.path.startsWith(`//`)||n.has(e.path)||(n.add(e.path),t.push({value:e.path,label:[...e.breadcrumb,e.title].join(` / `)}));let r=e.defaults.homePath;return n.has(r)||t.push({value:r,label:`${r}(当前已配置)`}),t},[m,e.defaults.homePath]),w=qe(),T=M(()=>{let t=g.keyword.trim();return B.filter(n=>g.group&&n.group!==g.group||g.changedOnly&&!Q(e,n.path)||g.lockedOnly&&R(n.path,e)?!1:!t||[n.label,n.path,n.description,V.find(e=>e.id===n.group)?.label,n.applicableWhen&&Ye(n.applicableWhen)].filter(Boolean).some(e=>Ke(String(e),t)))},[g,e,w]),E=B.filter(t=>Q(e,t.path)).length,re=B.filter(t=>!R(t.path,e)).length,ie=Ze(e,{});function D(n,r){t({...e,defaults:H(e.defaults,n,r)})}function ae(n){t({defaults:H(e.defaults,n,z(Je,n)),allowUserOverride:H(e.allowUserOverride,n,!0)})}function oe(t){let{path:i,kind:a}=t,c=z(e.defaults,i),l=`${t.label}默认值`;return a===`boolean`?/* @__PURE__ */ P(u,{"aria-label":l,value:String(c),optionList:vt,disabled:r,onChange:e=>D(i,e===`true`)}):a===`number`?/* @__PURE__ */ P(n,{"aria-label":l,value:typeof c==`number`?c:void 0,min:t.min,max:t.max,step:t.step??1,precision:t.step&&t.step<1?void 0:0,suffix:t.unit,disabled:r,onChange:e=>{typeof e==`number`&&Number.isFinite(e)&&D(i,e)}}):a===`color`?/* @__PURE__ */ P(mt,{value:String(c),disabled:r,label:l,onChange:e=>D(i,e)}):a===`home-path`?/* @__PURE__ */ P(u,{"aria-label":l,value:String(c),optionList:S,filter:!0,disabled:r,loading:o?s.isFetching:p.isFetching,onChange:e=>{typeof e==`string`&&D(i,e)}}):a===`select`?/* @__PURE__ */ P(u,{"aria-label":l,value:typeof c==`number`?c:String(c),optionList:[...t.options??[]],disabled:r,onChange:e=>{(typeof e==`string`||typeof e==`number`)&&D(i,e)}}):/* @__PURE__ */ P(C,{"aria-label":l,value:String(c),disabled:r,onChange:e=>D(i,e)})}function se(e){let t=Xe(e.path,ie);return/* @__PURE__ */ F(`span`,{className:`preference-policy-editor__description`,children:[e.description?/* @__PURE__ */ P(`span`,{children:e.description}):null,e.applicableWhen?/* @__PURE__ */ F(`span`,{children:[`适用条件:`,Ye(e.applicableWhen)]}):null,t?null:/* @__PURE__ */ P(`span`,{className:`preference-policy-editor__hint`,children:`当前系统默认组合不满足条件,满足条件后生效。`}),e.path===`homePath`?/* @__PURE__ */ F(`span`,{children:[`用户无权访问指定页面时回到可访问的首页。`,o?``:`当前仅列出你可访问的页面。`]}):null]})}return/* @__PURE__ */ P(`div`,{className:`preference-policy-editor`,children:/* @__PURE__ */ F(O,{title:`偏好策略`,description:`设置每项偏好的系统默认值,并决定用户是否可以修改。`,children:[/* @__PURE__ */ P(h,{type:`info`,closeIcon:null,className:`preference-policy-editor__intro`,description:`禁止用户修改的项目会在个人偏好中隐藏并使用系统值;子项是否显示取决于父项的生效值。更改将在保存后统一生效。`}),/* @__PURE__ */ P(it,{primary:/* @__PURE__ */ P(_,{placeholder:`搜索偏好名称 / 说明`,...b(`keyword`)}),filters:/* @__PURE__ */ F(N,{children:[/* @__PURE__ */ P(ee,{placeholder:`全部分组`,items:_t,...b(`group`)}),/* @__PURE__ */ P(c,{checked:g.changedOnly,onChange:e=>x(`changedOnly`)(!!e.target.checked),children:`仅看已调整`}),/* @__PURE__ */ P(c,{checked:g.lockedOnly,onChange:e=>x(`lockedOnly`)(!!e.target.checked),children:`仅看禁止修改`})]}),onReset:te}),/* @__PURE__ */ F(i.Text,{type:`tertiary`,size:`small`,children:[`共 `,B.length,` 项 · 已调整 `,E,` 项 · 禁止修改 `,re,` 项 · 当前显示 `,T.length,` 项`]}),T.length===0?/* @__PURE__ */ P(f,{description:`没有符合筛选条件的偏好`}):null,V.map(n=>{let i=T.filter(e=>e.group===n.id);return i.length===0?null:/* @__PURE__ */ F(O,{title:n.label,children:[/* @__PURE__ */ F(`div`,{className:`preference-policy-editor__head`,"aria-hidden":`true`,children:[/* @__PURE__ */ P(`span`,{children:`偏好设置`}),/* @__PURE__ */ F(`div`,{className:`preference-policy-editor__controls`,children:[/* @__PURE__ */ P(`span`,{children:`系统默认值`}),/* @__PURE__ */ P(`span`,{children:`用户可修改`}),/* @__PURE__ */ P(`span`,{})]})]}),i.map((n,i)=>/* @__PURE__ */ F(we,{children:[i>0?/* @__PURE__ */ P(j,{}):null,/* @__PURE__ */ P(`div`,{className:`preference-policy-editor__row`,"data-preference-path":n.path,children:/* @__PURE__ */ P(k,{title:n.label,description:se(n),style:{flexWrap:`wrap`},control:/* @__PURE__ */ F(`div`,{className:`preference-policy-editor__controls`,children:[/* @__PURE__ */ F(`div`,{className:`preference-policy-editor__value`,children:[/* @__PURE__ */ P(`span`,{className:`preference-policy-editor__mobile-label`,children:`系统默认值`}),oe(n)]}),/* @__PURE__ */ F(`div`,{className:`preference-policy-editor__override`,children:[/* @__PURE__ */ P(`span`,{className:`preference-policy-editor__mobile-label`,children:`用户可修改`}),/* @__PURE__ */ P(d,{"aria-label":`${n.label}用户可修改`,disabled:r,checked:R(n.path,e),onChange:r=>t({...e,allowUserOverride:H(e.allowUserOverride,n.path,r)})})]}),/* @__PURE__ */ P(v,{content:`恢复内置默认值并允许用户修改`,children:/* @__PURE__ */ P(l,{children:/* @__PURE__ */ P(y,{theme:`borderless`,size:`small`,"aria-label":`恢复${n.label}内置策略`,icon:/* @__PURE__ */ P(ne,{size:14}),disabled:r||!Q(e,n.path),onClick:()=>ae(n.path)})})})]})})})]},n.path))]},n.id)})]})})}var gt,_t,vt;function yt(){return(yt=e((()=>{a(),m(),at(),te(),A(),Z(),gt={keyword:``,group:void 0,changedOnly:!1,lockedOnly:!1},_t=V.map(e=>({value:e.id,label:e.label})),vt=[{value:`true`,label:`开启`},{value:`false`,label:`关闭`}]})))()}function bt({value:e,disabled:t,uploading:n,onChange:r,onUploadingChange:i}){let a=Se(),s=Ee(null);return Te(()=>()=>{s.current?.abort()},[]),/* @__PURE__ */ F(N,{children:[/* @__PURE__ */ P(k,{title:/* @__PURE__ */ P(`label`,{htmlFor:`website-name`,children:`网站名称`}),description:`应用于登录页、管理台和浏览器标题。留空时沿用宿主默认名称。`,control:/* @__PURE__ */ P(C,{id:`website-name`,style:{width:280},maxLength:80,showClear:!0,disabled:t,value:e.name,placeholder:a?.name||`沿用宿主默认名称`,onChange:e=>r({name:e})})}),/* @__PURE__ */ P(j,{}),/* @__PURE__ */ P(k,{title:`网站 Logo`,description:`支持 PNG、JPEG,最大 2 MB,尺寸不超过 4096 × 4096。保存后生效。`,control:/* @__PURE__ */ F(`div`,{style:{display:`flex`,flexDirection:`column`,alignItems:`center`,gap:12},children:[/* @__PURE__ */ P(`div`,{style:{width:96,height:96,padding:12,border:`1px solid var(--arc-antd-color-border)`,borderRadius:`var(--semi-border-radius-medium)`,display:`grid`,placeItems:`center`},children:e.logoUrl?/* @__PURE__ */ P(`img`,{src:L.resolveURL(e.logoUrl),alt:`网站 Logo 预览`,style:{width:`100%`,height:`100%`,objectFit:`contain`}}):/* @__PURE__ */ P(be,{size:64,hostDefault:!0})}),/* @__PURE__ */ P(o,{accept:`image/png,image/jpeg`,showUploadList:!1,disabled:t||n,customRequest:e=>{let t=new AbortController;return s.current?.abort(),s.current=t,i(!0),L.upload(Fe.uploadLogo,{body:{file:e.file}},{signal:t.signal}).then(n=>{t.signal.aborted||(r({logoUrl:n.logoUrl}),e.onSuccess?.(n))}).catch(n=>{if(t.signal.aborted)return;let r=n instanceof Error?n:/* @__PURE__ */ Error(`Logo 上传失败`);w.error(r.message),e.onError?.(r)}).finally(()=>{s.current===t&&!t.signal.aborted&&(s.current=null,i(!1))}),{abort:()=>t.abort()}},beforeUpload:({file:e})=>Number(e.size)>2097152||![`image/png`,`image/jpeg`].includes(e.fileInstance?.type??``)?(w.error(`请选择不超过 2 MB 的 PNG 或 JPEG 图片`),!1):!0,children:/* @__PURE__ */ P(y,{icon:/* @__PURE__ */ P(nt,{size:14}),disabled:t||n,loading:n,children:e.logoUrl?`更换 Logo`:`上传 Logo`})}),e.logoUrl?/* @__PURE__ */ P(y,{size:`small`,theme:`borderless`,disabled:t||n,onClick:()=>r({logoUrl:``}),children:`恢复默认 Logo`}):/* @__PURE__ */ P(`span`,{style:{color:`var(--arc-antd-color-text-2)`,fontSize:12},children:`使用宿主默认 Logo`})]})})]})}function xt(){return(xt=e((()=>{a(),rt(),A(),xe(),Ce()})))()}function St({value:e,disabled:t,onChange:n}){let r=ve(),i=Oe(),a=new URL(L.resolveURL(`/api/v1/mcp`),window.location.origin).href,o=JSON.stringify({"http-server-1":{transport:`streamable_http`,enabled:!0,display_name:i,default_open:!0,url:a,headers:{Authorization:`Bearer <API_KEY>`}}},null,2);return/* @__PURE__ */ F(N,{children:[/* @__PURE__ */ P(k,{title:`启用 MCP`,description:`向外部客户端提供只读工具。保存后立即生效,关闭后拒绝新的 MCP 请求。`,control:/* @__PURE__ */ P(Me,{"aria-label":`启用 MCP`,checked:e.enabled,disabled:t,onChange:e=>n({enabled:e})})}),/* @__PURE__ */ P(j,{}),/* @__PURE__ */ P(k,{title:`启用 WebMCP`,description:`已登录且未锁屏的管理台自动加载浏览器工具,沿用当前账号权限,删除操作仍需确认。保存后同步到已打开的页面。`,control:/* @__PURE__ */ P(Me,{"aria-label":`启用 WebMCP`,checked:e.webMcpEnabled,disabled:t,onChange:e=>n({webMcpEnabled:e})})}),e.webMcpEnabled&&r&&!r.configured?/* @__PURE__ */ P(ke,{type:`warning`,title:`当前宿主尚未接入 WebMCP`,description:`请先在宿主装配可选的 WebMCP 入口,接入后跟随此系统开关。`}):null,r?.status===`error`?/* @__PURE__ */ P(ke,{type:`error`,title:`WebMCP 加载失败`,description:`请检查管理台资源并刷新页面重试。`}):null,/* @__PURE__ */ P(I.Title,{level:5,children:`MCP 连接`}),/* @__PURE__ */ F(je,{wrap:!0,style:{marginBottom:12},children:[/* @__PURE__ */ P(I.Text,{code:!0,style:{overflowWrap:`anywhere`},children:a}),/* @__PURE__ */ P(Ae,{onClick:()=>void b(a),children:`复制地址`})]}),/* @__PURE__ */ F(I.Paragraph,{children:[`客户端选择 Streamable HTTP,通过 Authorization 请求头携带 API Key。前往`,/* @__PURE__ */ P(Pe,{to:`/system/api-tokens`,children:`AI 与集成 → API Key`}),`创建和管理凭据;可用工具由账号权限与 API Key 范围共同决定。`]}),/* @__PURE__ */ F(I.Paragraph,{type:`secondary`,children:[`将示例中的 `,/* @__PURE__ */ P(I.Text,{code:!0,children:`<API_KEY>`}),` 替换为有效的 API Key 后使用。`]}),/* @__PURE__ */ P(`pre`,{"aria-label":`MCP 连接配置示例`,style:{padding:16,whiteSpace:`pre-wrap`,overflowWrap:`anywhere`,background:`var(--arc-antd-color-fill-0)`,borderRadius:`var(--semi-border-radius-medium)`},children:o}),/* @__PURE__ */ P(Ae,{onClick:()=>void b(o),children:`复制连接示例`}),/* @__PURE__ */ P(I.Title,{level:5,children:`只读工具`}),/* @__PURE__ */ P(`ul`,{children:tt.map(e=>/* @__PURE__ */ F(`li`,{children:[/* @__PURE__ */ P(I.Text,{children:e.title}),` `,/* @__PURE__ */ P(I.Text,{type:`secondary`,children:e.name})]},e.name))}),/* @__PURE__ */ P(I.Paragraph,{type:`secondary`,children:`MCP 与 WebMCP 独立控制。宿主已配置桌面 Relay 时,桥接跟随 WebMCP 开关启停;连接状态以客户端实际列出工具为准。`})]})}function Ct(){return(Ct=e((()=>{A(),x(),ye()})))()}function wt({module:e,meta:t}){let n=$e[e],i=We(e),a=Ue(e),o=i.data,[c,l]=De(null),[u,d]=De(!1);Te(()=>{l(null),d(!1)},[o?.version]);let f=M(()=>c??o?.effective??null,[c,o]),p=c!==null&&JSON.stringify(c)!==JSON.stringify(o?.effective),m=e===`ui`&&f?f:null,g=e===`ui`&&o?o.effective:null,_=m&&g?B.filter(({path:e})=>z(m.preferences.defaults,e)!==z(g.preferences.defaults,e)||z(m.preferences.allowUserOverride,e)!==z(g.preferences.allowUserOverride,e)):[],v=_.filter(({path:e})=>m&&!z(m.preferences.allowUserOverride,e)).length;async function b(){if(!o||!f||!t.canWrite)return;let n=e===`website`?{...f,name:f.name.trim()}:f,r=Ie[e].input.safeParse({body:{version:o.version,data:n}});if(r.success)try{await a.mutateAsync(r.data),l(null),w.success(`设置已保存`)}catch(e){e instanceof Ne&&e.status===409&&(l(null),i.refetch())}else{let e=r.error.issues[0];w.error(`${e.path.join(`.`)||`表单`}:${e.message}`)}}return/* @__PURE__ */ P(E.Body,{padding:24,children:/* @__PURE__ */ F(`div`,{style:{maxWidth:e===`ui`?1040:760},children:[/* @__PURE__ */ F(`div`,{style:{display:`flex`,alignItems:`flex-start`,justifyContent:`space-between`,gap:16,marginBottom:8},children:[/* @__PURE__ */ F(`div`,{children:[/* @__PURE__ */ P(Tt,{heading:5,style:{margin:0},children:n.title}),/* @__PURE__ */ P($,{type:`tertiary`,children:n.description})]}),!t.page&&t.canWrite?/* @__PURE__ */ P(y,{theme:`solid`,icon:/* @__PURE__ */ P(oe,{size:14}),loading:a.isPending,disabled:!p||u,onClick:()=>void b(),children:`保存`}):null]}),/* @__PURE__ */ F(`div`,{style:{display:`flex`,gap:8,flexWrap:`wrap`,marginBottom:12},children:[/* @__PURE__ */ P(s,{color:`grey`,children:`系统级`}),o?/* @__PURE__ */ F(s,{children:[`版本 `,o.version]}):null,t.overriddenCount>0?/* @__PURE__ */ F(s,{color:`orange`,children:[t.overriddenCount,` 项覆盖`]}):null,o?.updatedAt?/* @__PURE__ */ F($,{type:`tertiary`,size:`small`,children:[`最后修改 `,o.updatedAt]}):null]}),t.page?/* @__PURE__ */ P(h,{type:`info`,closeIcon:null,description:/* @__PURE__ */ F(`span`,{children:[`该模块有专用设置页面,请前往`,/* @__PURE__ */ F(Pe,{to:t.page,style:{margin:`0 4px`,display:`inline-flex`,alignItems:`center`,gap:4},children:[n.title,/* @__PURE__ */ P(W,{size:12})]}),`修改。`]})}):null,!t.page&&!t.canWrite?/* @__PURE__ */ P(h,{type:`warning`,closeIcon:null,description:t.scope===`platform`?`平台级设置仅平台管理员可修改,当前为只读。`:`当前账号没有修改权限,当前为只读。`}):null,_.length>0?/* @__PURE__ */ P(h,{type:`info`,closeIcon:null,description:`待保存 ${_.length} 项偏好策略,其中 ${v} 项将统一使用系统值;允许修改的项目保留用户已有选择。`}):null,i.error?/* @__PURE__ */ P(h,{type:`danger`,closeIcon:null,description:/* @__PURE__ */ F(`span`,{children:[`设置加载失败。`,/* @__PURE__ */ P(y,{theme:`borderless`,onClick:()=>void i.refetch(),children:`重试`})]})}):null,/* @__PURE__ */ P(r,{spinning:i.isLoading,children:o&&f?/* @__PURE__ */ F(N,{children:[e===`website`?/* @__PURE__ */ P(bt,{value:f,disabled:!!t.page||!t.canWrite||a.isPending,uploading:u,onUploadingChange:d,onChange:e=>l(t=>({...o.effective,...t,...e}))},o.version):e===`mcp`?/* @__PURE__ */ P(St,{value:f,disabled:!t.canWrite||a.isPending,onChange:e=>l({...f,...e})}):/* @__PURE__ */ P(dt,{schema:et[e],excludeFields:e===`ui`?[`preferences`]:void 0,fieldLabels:ot,value:f,inheritedValue:o.inherited,onChange:e=>l({...f,...e}),disabled:!!t.page||!t.canWrite,enumLabels:Et}),m?/* @__PURE__ */ P(ht,{value:m.preferences,onChange:e=>l({...f,preferences:e}),disabled:!t.canWrite}):null]}):null})]})})}var $,Tt,Et;function Dt(){return(Dt=e((()=>{a(),G(),ae(),T(),st(),ft(),yt(),xt(),Ct(),{Text:$,Title:Tt}=i,Et={captchaComplexity:Qe}})))()}export{G as i,Dt as n,W as r,wt as t};
17
+ //# sourceMappingURL=SettingModuleDetail-BjxUJeH5.js.map