com-angel-authorization 1.0.14 → 1.0.15

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.
@@ -42,18 +42,24 @@ __export(react_exports, {
42
42
  ROOT_MENU_DEPTH: () => ROOT_MENU_DEPTH,
43
43
  ROOT_PARENT_ID: () => ROOT_PARENT_ID,
44
44
  ResourceManager: () => ResourceManager,
45
+ RoleManager: () => RoleManager,
45
46
  SYSTEM_ADMIN_DEFAULT_KEY: () => SYSTEM_ADMIN_DEFAULT_KEY,
46
47
  SYSTEM_ADMIN_MENU: () => SYSTEM_ADMIN_MENU,
47
48
  SystemAdmin: () => SystemAdmin,
48
49
  appendQueryParam: () => appendQueryParam,
49
50
  buildCreateBody: () => buildCreateBody,
50
51
  buildCreateMenuBody: () => buildCreateMenuBody,
52
+ buildCreateRoleBody: () => buildCreateRoleBody,
53
+ buildSavePermissionsBody: () => buildSavePermissionsBody,
51
54
  buildUpdateBody: () => buildUpdateBody,
52
55
  buildUpdateMenuBody: () => buildUpdateMenuBody,
56
+ buildUpdateRoleBody: () => buildUpdateRoleBody,
57
+ collectTreeResourceIds: () => collectTreeResourceIds,
53
58
  createAuthorizationResourceApi: () => createAuthorizationResourceApi,
54
59
  createDefaultResourceRequest: () => createDefaultResourceRequest,
55
60
  createMenuResourceApi: () => createMenuResourceApi,
56
61
  createPermissionStore: () => createPermissionStore,
62
+ createSystemRoleApi: () => createSystemRoleApi,
57
63
  extractPagination: () => extractPagination,
58
64
  extractRecords: () => extractRecords,
59
65
  getAppClientId: () => getAppClientId,
@@ -61,6 +67,9 @@ __export(react_exports, {
61
67
  isMenuLeaf: () => isMenuLeaf,
62
68
  mapAuthorizationResource: () => mapAuthorizationResource,
63
69
  mapMenuResource: () => mapMenuResource,
70
+ mapPermissionTreeNode: () => mapPermissionTreeNode,
71
+ mapRolePermissions: () => mapRolePermissions,
72
+ mapSystemRole: () => mapSystemRole,
64
73
  resolveMenuDepth: () => resolveMenuDepth,
65
74
  snowyflake: () => snowyflake,
66
75
  useHasPermission: () => useHasPermission,
@@ -2008,8 +2017,847 @@ var styles2 = {
2008
2017
  }
2009
2018
  };
2010
2019
 
2020
+ // src/react/RoleManager.tsx
2021
+ var import_react4 = require("react");
2022
+
2023
+ // src/roles/index.ts
2024
+ function mapSystemRole(item) {
2025
+ if (!item || typeof item !== "object") return null;
2026
+ const row = item;
2027
+ const roleId = row.roleId ?? row.role_id ?? row.id;
2028
+ if (roleId === void 0 || roleId === null || roleId === "") return null;
2029
+ return {
2030
+ roleId: String(roleId),
2031
+ name: String(row.name ?? ""),
2032
+ description: String(row.description ?? row.desc ?? "")
2033
+ };
2034
+ }
2035
+ function mapPermissionTreeNode(item) {
2036
+ if (!item || typeof item !== "object") return null;
2037
+ const row = item;
2038
+ const resourceId = row.resourceId ?? row.resource_id ?? row.id;
2039
+ if (resourceId === void 0 || resourceId === null || resourceId === "") return null;
2040
+ const rawChildren = row.children ?? row.childList ?? row.child_list ?? [];
2041
+ const children = Array.isArray(rawChildren) ? rawChildren.map(mapPermissionTreeNode).filter((node) => node !== null) : [];
2042
+ return {
2043
+ resourceId: String(resourceId),
2044
+ name: String(row.name ?? ""),
2045
+ children
2046
+ };
2047
+ }
2048
+ function asObject(value) {
2049
+ return value && typeof value === "object" ? value : null;
2050
+ }
2051
+ function mapRolePermissions(payload) {
2052
+ const envelope = asObject(payload) ?? {};
2053
+ const data = asObject(envelope.data) ?? envelope;
2054
+ const rawIds = data.resourceIds ?? data.resource_ids ?? [];
2055
+ const resourceIds = Array.isArray(rawIds) ? rawIds.map((id) => id === void 0 || id === null ? "" : String(id)).filter(Boolean) : [];
2056
+ const rawTree = data.resourceTree ?? data.resource_tree ?? [];
2057
+ const resourceTree = Array.isArray(rawTree) ? rawTree.map(mapPermissionTreeNode).filter((node) => node !== null) : [];
2058
+ return { resourceIds, resourceTree };
2059
+ }
2060
+ function collectTreeResourceIds(node) {
2061
+ return [node.resourceId, ...node.children.flatMap(collectTreeResourceIds)];
2062
+ }
2063
+ function buildListUrl2(params) {
2064
+ const parts = [];
2065
+ appendQueryParam(parts, "keyword", params?.keyword ?? "");
2066
+ appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
2067
+ appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
2068
+ appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
2069
+ return parts.length ? `/system/roles?${parts.join("&")}` : "/system/roles";
2070
+ }
2071
+ function buildCreateRoleBody(values) {
2072
+ return {
2073
+ name: values.name.trim(),
2074
+ description: values.description.trim()
2075
+ };
2076
+ }
2077
+ function buildUpdateRoleBody(values) {
2078
+ return {
2079
+ name: values.name.trim(),
2080
+ description: values.description.trim()
2081
+ };
2082
+ }
2083
+ function buildSavePermissionsBody(resourceIds) {
2084
+ return {
2085
+ resourceIds: [...new Set(resourceIds.map(String).filter(Boolean))]
2086
+ };
2087
+ }
2088
+ function createSystemRoleApi(request) {
2089
+ return {
2090
+ async list(params, signal) {
2091
+ const json = await request({
2092
+ method: "GET",
2093
+ url: buildListUrl2(params),
2094
+ signal
2095
+ });
2096
+ const records = extractRecords(json).map(mapSystemRole).filter((item) => item !== null);
2097
+ return {
2098
+ records,
2099
+ ...extractPagination(json)
2100
+ };
2101
+ },
2102
+ async create(values, signal) {
2103
+ return request({
2104
+ method: "POST",
2105
+ url: "/system/roles",
2106
+ body: buildCreateRoleBody(values),
2107
+ signal
2108
+ });
2109
+ },
2110
+ async update(roleId, values, signal) {
2111
+ return request({
2112
+ method: "PATCH",
2113
+ url: `/system/roles/${encodeURIComponent(roleId)}`,
2114
+ body: buildUpdateRoleBody(values),
2115
+ signal
2116
+ });
2117
+ },
2118
+ async remove(roleId, signal) {
2119
+ return request({
2120
+ method: "DELETE",
2121
+ url: `/system/roles/${encodeURIComponent(roleId)}`,
2122
+ signal
2123
+ });
2124
+ },
2125
+ async getPermissions(roleId, signal) {
2126
+ const json = await request({
2127
+ method: "GET",
2128
+ url: `/system/roles/${encodeURIComponent(roleId)}/permissions`,
2129
+ signal
2130
+ });
2131
+ return mapRolePermissions(json);
2132
+ },
2133
+ async savePermissions(roleId, resourceIds, signal) {
2134
+ return request({
2135
+ method: "POST",
2136
+ url: `/system/roles/${encodeURIComponent(roleId)}/permissions`,
2137
+ body: buildSavePermissionsBody(resourceIds),
2138
+ signal
2139
+ });
2140
+ }
2141
+ };
2142
+ }
2143
+
2144
+ // src/react/RoleManager.tsx
2145
+ var import_jsx_runtime4 = require("react/jsx-runtime");
2146
+ var PAGE_SIZE_OPTIONS3 = ["10", "20", "50", "100"];
2147
+ var emptyForm3 = () => ({
2148
+ name: "",
2149
+ description: ""
2150
+ });
2151
+ function countCheckedDescendants(node, checked) {
2152
+ let total = 0;
2153
+ let checkedCount = 0;
2154
+ const walk = (n) => {
2155
+ for (const child of n.children) {
2156
+ total += 1;
2157
+ if (checked.has(child.resourceId)) checkedCount += 1;
2158
+ walk(child);
2159
+ }
2160
+ };
2161
+ walk(node);
2162
+ return { total, checkedCount };
2163
+ }
2164
+ function RoleManager({
2165
+ api,
2166
+ title = "\u89D2\u8272\u7BA1\u7406",
2167
+ pageSize: initialPageSize = "20",
2168
+ toolbarExtra
2169
+ }) {
2170
+ const [records, setRecords] = (0, import_react4.useState)([]);
2171
+ const [loading, setLoading] = (0, import_react4.useState)(false);
2172
+ const [error, setError] = (0, import_react4.useState)("");
2173
+ const [keyword, setKeyword] = (0, import_react4.useState)("");
2174
+ const [keywordInput, setKeywordInput] = (0, import_react4.useState)("");
2175
+ const [pageSize, setPageSize] = (0, import_react4.useState)(initialPageSize);
2176
+ const [pageToken, setPageToken] = (0, import_react4.useState)("");
2177
+ const [hasPreviousPage, setHasPreviousPage] = (0, import_react4.useState)(false);
2178
+ const [hasNextPage, setHasNextPage] = (0, import_react4.useState)(false);
2179
+ const [dialogOpen, setDialogOpen] = (0, import_react4.useState)(false);
2180
+ const [editing, setEditing] = (0, import_react4.useState)(null);
2181
+ const [form, setForm] = (0, import_react4.useState)(emptyForm3);
2182
+ const [saving, setSaving] = (0, import_react4.useState)(false);
2183
+ const [deletingRow, setDeletingRow] = (0, import_react4.useState)(null);
2184
+ const [deleting, setDeleting] = (0, import_react4.useState)(false);
2185
+ const [authRole, setAuthRole] = (0, import_react4.useState)(null);
2186
+ const [authTree, setAuthTree] = (0, import_react4.useState)([]);
2187
+ const [authChecked, setAuthChecked] = (0, import_react4.useState)(() => /* @__PURE__ */ new Set());
2188
+ const [authExpanded, setAuthExpanded] = (0, import_react4.useState)({});
2189
+ const [authLoading, setAuthLoading] = (0, import_react4.useState)(false);
2190
+ const [authSaving, setAuthSaving] = (0, import_react4.useState)(false);
2191
+ const [authError, setAuthError] = (0, import_react4.useState)("");
2192
+ const loadList = (0, import_react4.useCallback)(
2193
+ async (direction = "current", token = pageToken) => {
2194
+ setLoading(true);
2195
+ setError("");
2196
+ try {
2197
+ const result = await api.list({
2198
+ keyword,
2199
+ pagination: {
2200
+ pageToken: token,
2201
+ pageSize,
2202
+ pageDirection: direction
2203
+ }
2204
+ });
2205
+ setRecords(result.records);
2206
+ setPageToken(result.pageToken);
2207
+ setHasPreviousPage(result.hasPreviousPage);
2208
+ setHasNextPage(result.hasNextPage);
2209
+ } catch (err) {
2210
+ setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u5931\u8D25");
2211
+ } finally {
2212
+ setLoading(false);
2213
+ }
2214
+ },
2215
+ [api, keyword, pageSize, pageToken]
2216
+ );
2217
+ (0, import_react4.useEffect)(() => {
2218
+ void loadList("current", "");
2219
+ }, [api, pageSize, keyword]);
2220
+ const handleSearch = () => {
2221
+ setPageToken("");
2222
+ setKeyword(keywordInput.trim());
2223
+ };
2224
+ const openCreate = () => {
2225
+ setEditing(null);
2226
+ setForm(emptyForm3());
2227
+ setDialogOpen(true);
2228
+ };
2229
+ const openEdit = (row) => {
2230
+ setEditing(row);
2231
+ setForm({
2232
+ name: row.name,
2233
+ description: row.description
2234
+ });
2235
+ setDialogOpen(true);
2236
+ };
2237
+ const closeDialog = () => {
2238
+ if (!saving) setDialogOpen(false);
2239
+ };
2240
+ const handleSubmit = async (event) => {
2241
+ event.preventDefault();
2242
+ if (!form.name.trim()) {
2243
+ setError("\u8BF7\u586B\u5199\u89D2\u8272\u540D\u79F0");
2244
+ return;
2245
+ }
2246
+ setSaving(true);
2247
+ setError("");
2248
+ try {
2249
+ if (editing) {
2250
+ await api.update(editing.roleId, form);
2251
+ } else {
2252
+ await api.create(form);
2253
+ }
2254
+ setDialogOpen(false);
2255
+ await loadList("current", "");
2256
+ } catch (err) {
2257
+ setError(err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25");
2258
+ } finally {
2259
+ setSaving(false);
2260
+ }
2261
+ };
2262
+ const askDelete = (row) => setDeletingRow(row);
2263
+ const closeDeleteDialog = () => {
2264
+ if (!deleting) setDeletingRow(null);
2265
+ };
2266
+ const confirmDelete = async () => {
2267
+ if (!deletingRow) return;
2268
+ setDeleting(true);
2269
+ setError("");
2270
+ try {
2271
+ await api.remove(deletingRow.roleId);
2272
+ setDeletingRow(null);
2273
+ await loadList("current", "");
2274
+ } catch (err) {
2275
+ setError(err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25");
2276
+ } finally {
2277
+ setDeleting(false);
2278
+ }
2279
+ };
2280
+ const openAuthorize = async (row) => {
2281
+ setAuthRole(row);
2282
+ setAuthTree([]);
2283
+ setAuthChecked(/* @__PURE__ */ new Set());
2284
+ setAuthExpanded({});
2285
+ setAuthError("");
2286
+ setAuthLoading(true);
2287
+ try {
2288
+ const result = await api.getPermissions(row.roleId);
2289
+ setAuthTree(result.resourceTree);
2290
+ setAuthChecked(new Set(result.resourceIds));
2291
+ const expanded = {};
2292
+ const walk = (nodes) => {
2293
+ for (const node of nodes) {
2294
+ if (node.children.length > 0) {
2295
+ expanded[node.resourceId] = true;
2296
+ walk(node.children);
2297
+ }
2298
+ }
2299
+ };
2300
+ walk(result.resourceTree);
2301
+ setAuthExpanded(expanded);
2302
+ } catch (err) {
2303
+ setAuthError(err instanceof Error ? err.message : "\u52A0\u8F7D\u6388\u6743\u6811\u5931\u8D25");
2304
+ } finally {
2305
+ setAuthLoading(false);
2306
+ }
2307
+ };
2308
+ const closeAuthorize = () => {
2309
+ if (!authSaving) {
2310
+ setAuthRole(null);
2311
+ setAuthError("");
2312
+ }
2313
+ };
2314
+ const toggleExpand = (resourceId) => {
2315
+ setAuthExpanded((prev) => ({ ...prev, [resourceId]: !prev[resourceId] }));
2316
+ };
2317
+ const toggleCheck = (node) => {
2318
+ setAuthChecked((prev) => {
2319
+ const next = new Set(prev);
2320
+ const ids = collectTreeResourceIds(node);
2321
+ const shouldCheck = !prev.has(node.resourceId);
2322
+ if (shouldCheck) {
2323
+ ids.forEach((id) => next.add(id));
2324
+ } else {
2325
+ ids.forEach((id) => next.delete(id));
2326
+ }
2327
+ return next;
2328
+ });
2329
+ };
2330
+ const saveAuthorize = async () => {
2331
+ if (!authRole) return;
2332
+ setAuthSaving(true);
2333
+ setAuthError("");
2334
+ try {
2335
+ await api.savePermissions(authRole.roleId, Array.from(authChecked));
2336
+ setAuthRole(null);
2337
+ } catch (err) {
2338
+ setAuthError(err instanceof Error ? err.message : "\u4FDD\u5B58\u6388\u6743\u5931\u8D25");
2339
+ } finally {
2340
+ setAuthSaving(false);
2341
+ }
2342
+ };
2343
+ const renderTreeNodes = (nodes, depth = 0) => nodes.map((node) => {
2344
+ const hasChildren = node.children.length > 0;
2345
+ const expanded = Boolean(authExpanded[node.resourceId]);
2346
+ const checked = authChecked.has(node.resourceId);
2347
+ const { total, checkedCount } = countCheckedDescendants(node, authChecked);
2348
+ const indeterminate = hasChildren && checkedCount > 0 && checkedCount < total && !checked;
2349
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
2350
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...styles3.treeRow, paddingLeft: 12 + depth * 20 }, children: [
2351
+ hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2352
+ "button",
2353
+ {
2354
+ type: "button",
2355
+ style: styles3.treeToggle,
2356
+ onClick: () => toggleExpand(node.resourceId),
2357
+ "aria-label": expanded ? "\u6536\u8D77" : "\u5C55\u5F00",
2358
+ children: expanded ? "\u25BC" : "\u25B6"
2359
+ }
2360
+ ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.treeSpacer }),
2361
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { style: styles3.treeLabel, children: [
2362
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2363
+ TreeCheckbox,
2364
+ {
2365
+ checked,
2366
+ indeterminate,
2367
+ onChange: () => toggleCheck(node)
2368
+ }
2369
+ ),
2370
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: node.name || node.resourceId })
2371
+ ] })
2372
+ ] }),
2373
+ hasChildren && expanded ? renderTreeNodes(node.children, depth + 1) : null
2374
+ ] }, node.resourceId);
2375
+ });
2376
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.root, children: [
2377
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.toolbar, children: [
2378
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { style: styles3.title, children: title }),
2379
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.toolbarRight, children: [
2380
+ toolbarExtra,
2381
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", style: styles3.primaryBtn, onClick: openCreate, children: "\u65B0\u589E\u89D2\u8272" })
2382
+ ] })
2383
+ ] }),
2384
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.searchBar, children: [
2385
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2386
+ "input",
2387
+ {
2388
+ style: { ...styles3.input, maxWidth: 260 },
2389
+ value: keywordInput,
2390
+ onChange: (e) => setKeywordInput(e.target.value),
2391
+ placeholder: "\u641C\u7D22\u89D2\u8272\u540D\u79F0 / \u63CF\u8FF0",
2392
+ onKeyDown: (e) => {
2393
+ if (e.key === "Enter") handleSearch();
2394
+ }
2395
+ }
2396
+ ),
2397
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", style: styles3.secondaryBtn, onClick: handleSearch, children: "\u67E5\u8BE2" }),
2398
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2399
+ "button",
2400
+ {
2401
+ type: "button",
2402
+ style: styles3.secondaryBtn,
2403
+ onClick: () => {
2404
+ setKeywordInput("");
2405
+ setKeyword("");
2406
+ setPageToken("");
2407
+ },
2408
+ children: "\u91CD\u7F6E"
2409
+ }
2410
+ )
2411
+ ] }),
2412
+ error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.error, children: error }) : null,
2413
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.tableWrap, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("table", { style: styles3.table, children: [
2414
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tr", { children: [
2415
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { style: styles3.th, children: "\u89D2\u8272\u540D\u79F0" }),
2416
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { style: styles3.th, children: "\u89D2\u8272\u63CF\u8FF0" }),
2417
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { style: { ...styles3.th, width: 200 }, children: "\u64CD\u4F5C" })
2418
+ ] }) }),
2419
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tbody", { children: loading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { colSpan: 3, style: styles3.empty, children: "\u52A0\u8F7D\u4E2D\u2026" }) }) : records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { colSpan: 3, style: styles3.empty, children: "\u6682\u65E0\u6570\u636E" }) }) : records.map((row) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tr", { children: [
2420
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { style: styles3.td, children: row.name }),
2421
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { style: styles3.td, children: row.description || "\u2014" }),
2422
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("td", { style: styles3.td, children: [
2423
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", style: styles3.linkBtn, onClick: () => openEdit(row), children: "\u7F16\u8F91" }),
2424
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2425
+ "button",
2426
+ {
2427
+ type: "button",
2428
+ style: styles3.linkBtn,
2429
+ onClick: () => void openAuthorize(row),
2430
+ children: "\u6388\u6743"
2431
+ }
2432
+ ),
2433
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2434
+ "button",
2435
+ {
2436
+ type: "button",
2437
+ style: { ...styles3.linkBtn, color: "#d92d20" },
2438
+ onClick: () => askDelete(row),
2439
+ children: "\u5220\u9664"
2440
+ }
2441
+ )
2442
+ ] })
2443
+ ] }, row.roleId)) })
2444
+ ] }) }),
2445
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.pagination, children: [
2446
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { style: styles3.pageSize, children: [
2447
+ "\u6BCF\u9875",
2448
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2449
+ "select",
2450
+ {
2451
+ value: pageSize,
2452
+ onChange: (e) => {
2453
+ setPageToken("");
2454
+ setPageSize(e.target.value);
2455
+ },
2456
+ style: styles3.select,
2457
+ children: PAGE_SIZE_OPTIONS3.map((size) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: size, children: size }, size))
2458
+ }
2459
+ )
2460
+ ] }),
2461
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.pageBtns, children: [
2462
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2463
+ "button",
2464
+ {
2465
+ type: "button",
2466
+ style: styles3.secondaryBtn,
2467
+ disabled: !hasPreviousPage || loading,
2468
+ onClick: () => void loadList("previous"),
2469
+ children: "\u4E0A\u4E00\u9875"
2470
+ }
2471
+ ),
2472
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2473
+ "button",
2474
+ {
2475
+ type: "button",
2476
+ style: styles3.secondaryBtn,
2477
+ disabled: !hasNextPage || loading,
2478
+ onClick: () => void loadList("next"),
2479
+ children: "\u4E0B\u4E00\u9875"
2480
+ }
2481
+ )
2482
+ ] })
2483
+ ] }),
2484
+ dialogOpen ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.mask, onClick: closeDialog, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2485
+ "div",
2486
+ {
2487
+ style: styles3.dialog,
2488
+ onClick: (e) => e.stopPropagation(),
2489
+ role: "dialog",
2490
+ "aria-modal": "true",
2491
+ children: [
2492
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.dialogHeader, children: [
2493
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { style: styles3.dialogTitle, children: editing ? "\u7F16\u8F91\u89D2\u8272" : "\u65B0\u589E\u89D2\u8272" }),
2494
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", style: styles3.iconBtn, onClick: closeDialog, "aria-label": "\u5173\u95ED", children: "\xD7" })
2495
+ ] }),
2496
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { style: styles3.form, onSubmit: (e) => void handleSubmit(e), children: [
2497
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { style: styles3.field, children: [
2498
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.label, children: "\u89D2\u8272\u540D\u79F0" }),
2499
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2500
+ "input",
2501
+ {
2502
+ style: styles3.input,
2503
+ value: form.name,
2504
+ onChange: (e) => setForm((prev) => ({ ...prev, name: e.target.value })),
2505
+ placeholder: "\u8BF7\u8F93\u5165\u89D2\u8272\u540D\u79F0",
2506
+ required: true
2507
+ }
2508
+ )
2509
+ ] }),
2510
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { style: styles3.field, children: [
2511
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.label, children: "\u89D2\u8272\u63CF\u8FF0" }),
2512
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2513
+ "textarea",
2514
+ {
2515
+ style: { ...styles3.input, minHeight: 88, resize: "vertical" },
2516
+ value: form.description,
2517
+ onChange: (e) => setForm((prev) => ({ ...prev, description: e.target.value })),
2518
+ placeholder: "\u8BF7\u8F93\u5165\u89D2\u8272\u63CF\u8FF0"
2519
+ }
2520
+ )
2521
+ ] }),
2522
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.dialogFooter, children: [
2523
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", style: styles3.secondaryBtn, onClick: closeDialog, children: "\u53D6\u6D88" }),
2524
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", style: styles3.primaryBtn, disabled: saving, children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58" })
2525
+ ] })
2526
+ ] })
2527
+ ]
2528
+ }
2529
+ ) }) : null,
2530
+ deletingRow ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.mask, onClick: closeDeleteDialog, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2531
+ "div",
2532
+ {
2533
+ style: { ...styles3.dialog, maxWidth: 420 },
2534
+ onClick: (e) => e.stopPropagation(),
2535
+ role: "dialog",
2536
+ "aria-modal": "true",
2537
+ children: [
2538
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.dialogHeader, children: [
2539
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { style: styles3.dialogTitle, children: "\u786E\u8BA4\u5220\u9664" }),
2540
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2541
+ "button",
2542
+ {
2543
+ type: "button",
2544
+ style: styles3.iconBtn,
2545
+ onClick: closeDeleteDialog,
2546
+ "aria-label": "\u5173\u95ED",
2547
+ children: "\xD7"
2548
+ }
2549
+ )
2550
+ ] }),
2551
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.confirmBody, children: [
2552
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { style: styles3.confirmText, children: [
2553
+ "\u786E\u8BA4\u5220\u9664\u89D2\u8272\u300C",
2554
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: deletingRow.name }),
2555
+ "\u300D\u5417\uFF1F\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\u3002"
2556
+ ] }),
2557
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.dialogFooter, children: [
2558
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2559
+ "button",
2560
+ {
2561
+ type: "button",
2562
+ style: styles3.secondaryBtn,
2563
+ onClick: closeDeleteDialog,
2564
+ disabled: deleting,
2565
+ children: "\u53D6\u6D88"
2566
+ }
2567
+ ),
2568
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2569
+ "button",
2570
+ {
2571
+ type: "button",
2572
+ style: styles3.dangerBtn,
2573
+ onClick: () => void confirmDelete(),
2574
+ disabled: deleting,
2575
+ children: deleting ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u5220\u9664"
2576
+ }
2577
+ )
2578
+ ] })
2579
+ ] })
2580
+ ]
2581
+ }
2582
+ ) }) : null,
2583
+ authRole ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.mask, onClick: closeAuthorize, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2584
+ "div",
2585
+ {
2586
+ style: { ...styles3.dialog, maxWidth: 560 },
2587
+ onClick: (e) => e.stopPropagation(),
2588
+ role: "dialog",
2589
+ "aria-modal": "true",
2590
+ children: [
2591
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.dialogHeader, children: [
2592
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h3", { style: styles3.dialogTitle, children: [
2593
+ "\u89D2\u8272\u6388\u6743 \u2014 ",
2594
+ authRole.name
2595
+ ] }),
2596
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2597
+ "button",
2598
+ {
2599
+ type: "button",
2600
+ style: styles3.iconBtn,
2601
+ onClick: closeAuthorize,
2602
+ "aria-label": "\u5173\u95ED",
2603
+ children: "\xD7"
2604
+ }
2605
+ )
2606
+ ] }),
2607
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.authBody, children: [
2608
+ authError ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.error, children: authError }) : null,
2609
+ authLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.empty, children: "\u52A0\u8F7D\u4E2D\u2026" }) : authTree.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.empty, children: "\u6682\u65E0\u53EF\u6388\u6743\u8D44\u6E90" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.treePanel, children: renderTreeNodes(authTree) }),
2610
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.dialogFooter, children: [
2611
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2612
+ "button",
2613
+ {
2614
+ type: "button",
2615
+ style: styles3.secondaryBtn,
2616
+ onClick: closeAuthorize,
2617
+ disabled: authSaving,
2618
+ children: "\u53D6\u6D88"
2619
+ }
2620
+ ),
2621
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2622
+ "button",
2623
+ {
2624
+ type: "button",
2625
+ style: styles3.primaryBtn,
2626
+ onClick: () => void saveAuthorize(),
2627
+ disabled: authLoading || authSaving,
2628
+ children: authSaving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58"
2629
+ }
2630
+ )
2631
+ ] })
2632
+ ] })
2633
+ ]
2634
+ }
2635
+ ) }) : null
2636
+ ] });
2637
+ }
2638
+ function TreeCheckbox({
2639
+ checked,
2640
+ indeterminate,
2641
+ onChange
2642
+ }) {
2643
+ const ref = (0, import_react4.useRef)(null);
2644
+ (0, import_react4.useEffect)(() => {
2645
+ if (ref.current) ref.current.indeterminate = indeterminate;
2646
+ }, [indeterminate]);
2647
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2648
+ "input",
2649
+ {
2650
+ ref,
2651
+ type: "checkbox",
2652
+ checked,
2653
+ onChange,
2654
+ style: styles3.checkbox
2655
+ }
2656
+ );
2657
+ }
2658
+ var styles3 = {
2659
+ root: {
2660
+ display: "flex",
2661
+ flexDirection: "column",
2662
+ gap: 16,
2663
+ padding: 16,
2664
+ color: "#101828",
2665
+ fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif'
2666
+ },
2667
+ toolbar: {
2668
+ display: "flex",
2669
+ alignItems: "center",
2670
+ justifyContent: "space-between",
2671
+ gap: 12
2672
+ },
2673
+ title: { margin: 0, fontSize: 18, fontWeight: 600 },
2674
+ toolbarRight: { display: "flex", alignItems: "center", gap: 8 },
2675
+ searchBar: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" },
2676
+ error: {
2677
+ padding: "10px 12px",
2678
+ borderRadius: 8,
2679
+ background: "#fef3f2",
2680
+ color: "#b42318",
2681
+ fontSize: 13
2682
+ },
2683
+ tableWrap: {
2684
+ overflow: "auto",
2685
+ border: "1px solid #eaecf0",
2686
+ borderRadius: 10,
2687
+ background: "#fff"
2688
+ },
2689
+ table: { width: "100%", borderCollapse: "collapse", minWidth: 560 },
2690
+ th: {
2691
+ textAlign: "left",
2692
+ padding: "12px 14px",
2693
+ fontSize: 13,
2694
+ fontWeight: 600,
2695
+ color: "#475467",
2696
+ background: "#f9fafb",
2697
+ borderBottom: "1px solid #eaecf0"
2698
+ },
2699
+ td: {
2700
+ padding: "12px 14px",
2701
+ fontSize: 14,
2702
+ borderBottom: "1px solid #f2f4f7",
2703
+ verticalAlign: "middle"
2704
+ },
2705
+ empty: { padding: 28, textAlign: "center", color: "#98a2b3", fontSize: 14 },
2706
+ linkBtn: {
2707
+ border: "none",
2708
+ background: "transparent",
2709
+ color: "#049BAD",
2710
+ cursor: "pointer",
2711
+ padding: "0 8px 0 0",
2712
+ fontSize: 13
2713
+ },
2714
+ pagination: {
2715
+ display: "flex",
2716
+ alignItems: "center",
2717
+ justifyContent: "space-between",
2718
+ gap: 12
2719
+ },
2720
+ pageSize: { display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "#475467" },
2721
+ pageBtns: { display: "flex", gap: 8 },
2722
+ primaryBtn: {
2723
+ border: "none",
2724
+ background: "#049BAD",
2725
+ color: "#fff",
2726
+ borderRadius: 8,
2727
+ padding: "8px 14px",
2728
+ cursor: "pointer",
2729
+ fontSize: 14
2730
+ },
2731
+ secondaryBtn: {
2732
+ border: "1px solid #d0d5dd",
2733
+ background: "#fff",
2734
+ color: "#344054",
2735
+ borderRadius: 8,
2736
+ padding: "8px 14px",
2737
+ cursor: "pointer",
2738
+ fontSize: 14
2739
+ },
2740
+ dangerBtn: {
2741
+ border: "none",
2742
+ background: "#d92d20",
2743
+ color: "#fff",
2744
+ borderRadius: 8,
2745
+ padding: "8px 14px",
2746
+ cursor: "pointer",
2747
+ fontSize: 14
2748
+ },
2749
+ select: {
2750
+ border: "1px solid #d0d5dd",
2751
+ borderRadius: 6,
2752
+ padding: "4px 8px",
2753
+ fontSize: 13,
2754
+ backgroundColor: "#ffffff",
2755
+ color: "#101828"
2756
+ },
2757
+ mask: {
2758
+ position: "fixed",
2759
+ inset: 0,
2760
+ background: "rgba(16, 24, 40, 0.45)",
2761
+ display: "flex",
2762
+ alignItems: "center",
2763
+ justifyContent: "center",
2764
+ zIndex: 1e3,
2765
+ padding: 16
2766
+ },
2767
+ dialog: {
2768
+ width: "100%",
2769
+ maxWidth: 480,
2770
+ background: "#fff",
2771
+ borderRadius: 12,
2772
+ boxShadow: "0 20px 40px rgba(16,24,40,0.18)"
2773
+ },
2774
+ dialogHeader: {
2775
+ display: "flex",
2776
+ alignItems: "center",
2777
+ justifyContent: "space-between",
2778
+ padding: "14px 16px",
2779
+ borderBottom: "1px solid #eaecf0"
2780
+ },
2781
+ dialogTitle: { margin: 0, fontSize: 16, fontWeight: 600 },
2782
+ iconBtn: {
2783
+ border: "none",
2784
+ background: "transparent",
2785
+ fontSize: 22,
2786
+ lineHeight: 1,
2787
+ cursor: "pointer",
2788
+ color: "#667085"
2789
+ },
2790
+ form: { display: "flex", flexDirection: "column", gap: 12, padding: 16 },
2791
+ confirmBody: { display: "flex", flexDirection: "column", gap: 16, padding: 16 },
2792
+ confirmText: { margin: 0, fontSize: 14, color: "#344054", lineHeight: 1.6 },
2793
+ authBody: { display: "flex", flexDirection: "column", gap: 12, padding: 16 },
2794
+ treePanel: {
2795
+ maxHeight: 420,
2796
+ overflow: "auto",
2797
+ border: "1px solid #eaecf0",
2798
+ borderRadius: 8,
2799
+ padding: "8px 0",
2800
+ background: "#fff"
2801
+ },
2802
+ treeRow: {
2803
+ display: "flex",
2804
+ alignItems: "center",
2805
+ gap: 6,
2806
+ minHeight: 32,
2807
+ paddingRight: 12
2808
+ },
2809
+ treeToggle: {
2810
+ border: "none",
2811
+ background: "transparent",
2812
+ width: 20,
2813
+ height: 20,
2814
+ padding: 0,
2815
+ cursor: "pointer",
2816
+ color: "#667085",
2817
+ fontSize: 10,
2818
+ flexShrink: 0
2819
+ },
2820
+ treeSpacer: { width: 20, flexShrink: 0 },
2821
+ treeLabel: {
2822
+ display: "inline-flex",
2823
+ alignItems: "center",
2824
+ gap: 8,
2825
+ fontSize: 14,
2826
+ color: "#101828",
2827
+ cursor: "pointer",
2828
+ userSelect: "none"
2829
+ },
2830
+ checkbox: {
2831
+ width: 16,
2832
+ height: 16,
2833
+ accentColor: "#049BAD",
2834
+ cursor: "pointer",
2835
+ colorScheme: "light",
2836
+ backgroundColor: "#ffffff"
2837
+ },
2838
+ field: { display: "flex", flexDirection: "column", gap: 6 },
2839
+ label: { fontSize: 13, color: "#344054", fontWeight: 500 },
2840
+ input: {
2841
+ border: "1px solid #d0d5dd",
2842
+ borderRadius: 8,
2843
+ padding: "8px 10px",
2844
+ fontSize: 14,
2845
+ outline: "none",
2846
+ backgroundColor: "#ffffff",
2847
+ color: "#101828",
2848
+ boxSizing: "border-box",
2849
+ width: "100%"
2850
+ },
2851
+ dialogFooter: {
2852
+ display: "flex",
2853
+ justifyContent: "flex-end",
2854
+ gap: 8,
2855
+ paddingTop: 4
2856
+ }
2857
+ };
2858
+
2011
2859
  // src/react/SystemAdmin.tsx
2012
- var import_react4 = require("react");
2860
+ var import_react5 = require("react");
2013
2861
 
2014
2862
  // src/admin/menu.ts
2015
2863
  var SYSTEM_ADMIN_MENU = {
@@ -2017,44 +2865,46 @@ var SYSTEM_ADMIN_MENU = {
2017
2865
  label: "\u7CFB\u7EDF\u7BA1\u7406",
2018
2866
  children: [
2019
2867
  { key: "menu", label: "\u83DC\u5355\u7BA1\u7406" },
2020
- { key: "resource", label: "\u6743\u9650\u70B9\u7BA1\u7406" }
2868
+ { key: "resource", label: "\u6743\u9650\u70B9\u7BA1\u7406" },
2869
+ { key: "role", label: "\u89D2\u8272\u7BA1\u7406" }
2021
2870
  ]
2022
2871
  };
2023
2872
  var SYSTEM_ADMIN_DEFAULT_KEY = "menu";
2024
2873
 
2025
2874
  // src/react/SystemAdmin.tsx
2026
- var import_jsx_runtime4 = require("react/jsx-runtime");
2875
+ var import_jsx_runtime5 = require("react/jsx-runtime");
2027
2876
  function SystemAdmin({
2028
2877
  menuApi,
2029
2878
  resourceApi,
2879
+ roleApi,
2030
2880
  defaultActiveKey = SYSTEM_ADMIN_DEFAULT_KEY,
2031
2881
  activeKey: controlledKey,
2032
2882
  onActiveKeyChange,
2033
2883
  title = SYSTEM_ADMIN_MENU.label,
2034
2884
  toolbarExtra
2035
2885
  }) {
2036
- const [innerKey, setInnerKey] = (0, import_react4.useState)(defaultActiveKey);
2886
+ const [innerKey, setInnerKey] = (0, import_react5.useState)(defaultActiveKey);
2037
2887
  const activeKey = controlledKey ?? innerKey;
2038
2888
  const setActiveKey = (key) => {
2039
2889
  if (controlledKey === void 0) setInnerKey(key);
2040
2890
  onActiveKeyChange?.(key);
2041
2891
  };
2042
- const activeLabel = (0, import_react4.useMemo)(
2892
+ const activeLabel = (0, import_react5.useMemo)(
2043
2893
  () => SYSTEM_ADMIN_MENU.children.find((item) => item.key === activeKey)?.label ?? "",
2044
2894
  [activeKey]
2045
2895
  );
2046
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.root, children: [
2047
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("aside", { style: styles3.sidebar, children: [
2048
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.sidebarTitle, children: title }),
2049
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("nav", { style: styles3.nav, children: SYSTEM_ADMIN_MENU.children.map((item) => {
2896
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles4.root, children: [
2897
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("aside", { style: styles4.sidebar, children: [
2898
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.sidebarTitle, children: title }),
2899
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("nav", { style: styles4.nav, children: SYSTEM_ADMIN_MENU.children.map((item) => {
2050
2900
  const active = item.key === activeKey;
2051
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2901
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2052
2902
  "button",
2053
2903
  {
2054
2904
  type: "button",
2055
2905
  style: {
2056
- ...styles3.navItem,
2057
- ...active ? styles3.navItemActive : null
2906
+ ...styles4.navItem,
2907
+ ...active ? styles4.navItemActive : null
2058
2908
  },
2059
2909
  onClick: () => setActiveKey(item.key),
2060
2910
  children: item.label
@@ -2063,20 +2913,20 @@ function SystemAdmin({
2063
2913
  );
2064
2914
  }) })
2065
2915
  ] }),
2066
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("main", { style: styles3.content, children: [
2067
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.contentHeader, children: [
2068
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.breadcrumb, children: [
2069
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.breadcrumbParent, children: title }),
2070
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.breadcrumbSep, children: "/" }),
2071
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.breadcrumbCurrent, children: activeLabel })
2916
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("main", { style: styles4.content, children: [
2917
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles4.contentHeader, children: [
2918
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles4.breadcrumb, children: [
2919
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.breadcrumbParent, children: title }),
2920
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.breadcrumbSep, children: "/" }),
2921
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.breadcrumbCurrent, children: activeLabel })
2072
2922
  ] }),
2073
2923
  toolbarExtra
2074
2924
  ] }),
2075
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.panel, children: activeKey === "menu" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MenuManager, { api: menuApi, title: "\u83DC\u5355\u7BA1\u7406" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ResourceManager, { api: resourceApi, title: "\u6743\u9650\u70B9\u7BA1\u7406" }) })
2925
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.panel, children: activeKey === "menu" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MenuManager, { api: menuApi, title: "\u83DC\u5355\u7BA1\u7406" }) : activeKey === "resource" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ResourceManager, { api: resourceApi, title: "\u6743\u9650\u70B9\u7BA1\u7406" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RoleManager, { api: roleApi, title: "\u89D2\u8272\u7BA1\u7406" }) })
2076
2926
  ] })
2077
2927
  ] });
2078
2928
  }
2079
- var styles3 = {
2929
+ var styles4 = {
2080
2930
  root: {
2081
2931
  display: "flex",
2082
2932
  minHeight: 560,
@@ -2173,18 +3023,24 @@ var styles3 = {
2173
3023
  ROOT_MENU_DEPTH,
2174
3024
  ROOT_PARENT_ID,
2175
3025
  ResourceManager,
3026
+ RoleManager,
2176
3027
  SYSTEM_ADMIN_DEFAULT_KEY,
2177
3028
  SYSTEM_ADMIN_MENU,
2178
3029
  SystemAdmin,
2179
3030
  appendQueryParam,
2180
3031
  buildCreateBody,
2181
3032
  buildCreateMenuBody,
3033
+ buildCreateRoleBody,
3034
+ buildSavePermissionsBody,
2182
3035
  buildUpdateBody,
2183
3036
  buildUpdateMenuBody,
3037
+ buildUpdateRoleBody,
3038
+ collectTreeResourceIds,
2184
3039
  createAuthorizationResourceApi,
2185
3040
  createDefaultResourceRequest,
2186
3041
  createMenuResourceApi,
2187
3042
  createPermissionStore,
3043
+ createSystemRoleApi,
2188
3044
  extractPagination,
2189
3045
  extractRecords,
2190
3046
  getAppClientId,
@@ -2192,6 +3048,9 @@ var styles3 = {
2192
3048
  isMenuLeaf,
2193
3049
  mapAuthorizationResource,
2194
3050
  mapMenuResource,
3051
+ mapPermissionTreeNode,
3052
+ mapRolePermissions,
3053
+ mapSystemRole,
2195
3054
  resolveMenuDepth,
2196
3055
  snowyflake,
2197
3056
  useHasPermission,