com-angel-authorization 1.0.5 → 1.0.6

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.
@@ -233,16 +233,35 @@ import {
233
233
 
234
234
  // src/resources/types.ts
235
235
  var RESOURCE_TYPE_API = "api";
236
+ var MENU_TYPE_PAGE = "page";
237
+ var MENU_TYPE_MENU = "menu";
238
+ var MENU_TYPE_BUTTON = "button";
239
+ var MENU_LIST_TYPE_PARAM = "page,menu,button";
240
+ var ROOT_PARENT_ID = "0";
236
241
  var RESOURCE_STATUS_ENABLED = 1;
237
242
  var RESOURCE_STATUS_DISABLED = 0;
238
243
  var RESOURCE_STATUS_OPTIONS = [
239
244
  { label: "\u542F\u7528", value: RESOURCE_STATUS_ENABLED },
240
245
  { label: "\u7981\u7528", value: RESOURCE_STATUS_DISABLED }
241
246
  ];
247
+ var MENU_VISIBILITY_OPTIONS = [
248
+ { label: "\u663E\u793A", value: RESOURCE_STATUS_ENABLED },
249
+ { label: "\u9690\u85CF", value: RESOURCE_STATUS_DISABLED }
250
+ ];
242
251
  var RESOURCE_PRIVATE_OPTIONS = [
243
252
  { label: "\u662F", value: true },
244
253
  { label: "\u5426", value: false }
245
254
  ];
255
+ var MENU_TYPE_OPTIONS = [
256
+ { label: "\u76EE\u5F55", value: MENU_TYPE_PAGE },
257
+ { label: "\u83DC\u5355", value: MENU_TYPE_MENU },
258
+ { label: "\u6309\u94AE", value: MENU_TYPE_BUTTON }
259
+ ];
260
+ var MENU_TYPE_LABEL = {
261
+ page: "\u76EE\u5F55",
262
+ menu: "\u83DC\u5355",
263
+ button: "\u6309\u94AE"
264
+ };
246
265
 
247
266
  // src/utils/snowflake.ts
248
267
  var DEVICE_WORKER_ID_KEY = "hgams_device_worker_id";
@@ -387,6 +406,29 @@ function toBoolean(value) {
387
406
  }
388
407
  return false;
389
408
  }
409
+ function toStringArray(value) {
410
+ if (Array.isArray(value)) {
411
+ return value.map((item) => {
412
+ if (item && typeof item === "object") {
413
+ const row = item;
414
+ const id = row.resourceId ?? row.resource_id ?? row.id;
415
+ return id === void 0 || id === null ? "" : String(id);
416
+ }
417
+ return String(item ?? "");
418
+ }).filter(Boolean);
419
+ }
420
+ if (typeof value === "string" && value.trim()) {
421
+ return value.split(",").map((s) => s.trim()).filter(Boolean);
422
+ }
423
+ return [];
424
+ }
425
+ function toMenuType(value) {
426
+ const v = String(value ?? "").toLowerCase();
427
+ if (v === MENU_TYPE_PAGE || v === MENU_TYPE_MENU || v === MENU_TYPE_BUTTON) {
428
+ return v;
429
+ }
430
+ return MENU_TYPE_MENU;
431
+ }
390
432
  function mapAuthorizationResource(item) {
391
433
  if (!item || typeof item !== "object") return null;
392
434
  const row = item;
@@ -402,9 +444,31 @@ function mapAuthorizationResource(item) {
402
444
  description: String(row.description ?? row.desc ?? "")
403
445
  };
404
446
  }
405
- function buildListUrl(params) {
447
+ function mapMenuResource(item) {
448
+ if (!item || typeof item !== "object") return null;
449
+ const row = item;
450
+ const resourceId = row.resourceId ?? row.resource_id ?? row.id;
451
+ if (resourceId === void 0 || resourceId === null || resourceId === "") return null;
452
+ const permissionPointIds = toStringArray(
453
+ row.permissionPointIds ?? row.permission_point_ids ?? row.permissionPoints ?? row.permissions
454
+ );
455
+ const permissionNamesRaw = row.permissionPointNames ?? row.permission_point_names ?? row.permissionNames;
456
+ const permissionPointNames = Array.isArray(permissionNamesRaw) ? permissionNamesRaw.map((n) => String(n ?? "")).filter(Boolean) : void 0;
457
+ const parentId = row.parentId ?? row.parent_id ?? ROOT_PARENT_ID;
458
+ return {
459
+ resourceId: String(resourceId),
460
+ parentId: parentId === void 0 || parentId === null ? ROOT_PARENT_ID : String(parentId),
461
+ type: toMenuType(row.type),
462
+ name: String(row.name ?? ""),
463
+ identification: String(row.identification ?? row.identity ?? row.path ?? ""),
464
+ permissionPointIds,
465
+ permissionPointNames,
466
+ status: toResourceStatus(row.status)
467
+ };
468
+ }
469
+ function buildListUrl(type, params) {
406
470
  const parts = [];
407
- appendQueryParam(parts, "type", RESOURCE_TYPE_API);
471
+ appendQueryParam(parts, "type", type);
408
472
  appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
409
473
  appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
410
474
  appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
@@ -431,12 +495,33 @@ function buildUpdateBody(values) {
431
495
  description: values.description.trim()
432
496
  };
433
497
  }
498
+ function buildCreateMenuBody(values, resourceId = getAppClientId()) {
499
+ return {
500
+ resourceId,
501
+ parentId: values.parentId || ROOT_PARENT_ID,
502
+ type: values.type,
503
+ name: values.name.trim(),
504
+ identification: values.identification.trim(),
505
+ permissionPointIds: [...values.permissionPointIds],
506
+ status: values.status
507
+ };
508
+ }
509
+ function buildUpdateMenuBody(values) {
510
+ return {
511
+ parentId: values.parentId || ROOT_PARENT_ID,
512
+ type: values.type,
513
+ name: values.name.trim(),
514
+ identification: values.identification.trim(),
515
+ permissionPointIds: [...values.permissionPointIds],
516
+ status: values.status
517
+ };
518
+ }
434
519
  function createAuthorizationResourceApi(request) {
435
520
  return {
436
521
  async list(params, signal) {
437
522
  const json = await request({
438
523
  method: "GET",
439
- url: buildListUrl(params),
524
+ url: buildListUrl(RESOURCE_TYPE_API, params),
440
525
  signal
441
526
  });
442
527
  const records = extractRecords(json).map(mapAuthorizationResource).filter((item) => item !== null);
@@ -471,6 +556,50 @@ function createAuthorizationResourceApi(request) {
471
556
  }
472
557
  };
473
558
  }
559
+ function createMenuResourceApi(request) {
560
+ const permissionApi = createAuthorizationResourceApi(request);
561
+ return {
562
+ async list(params, signal) {
563
+ const json = await request({
564
+ method: "GET",
565
+ url: buildListUrl(MENU_LIST_TYPE_PARAM, params),
566
+ signal
567
+ });
568
+ const records = extractRecords(json).map(mapMenuResource).filter((item) => item !== null);
569
+ const pagination = extractPagination(json);
570
+ return {
571
+ records,
572
+ ...pagination
573
+ };
574
+ },
575
+ listPermissionPoints(params, signal) {
576
+ return permissionApi.list(params, signal);
577
+ },
578
+ async create(values, signal) {
579
+ return request({
580
+ method: "POST",
581
+ url: "/authorization-resources",
582
+ body: buildCreateMenuBody(values),
583
+ signal
584
+ });
585
+ },
586
+ async update(resourceId, values, signal) {
587
+ return request({
588
+ method: "PATCH",
589
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}`,
590
+ body: buildUpdateMenuBody(values),
591
+ signal
592
+ });
593
+ },
594
+ async remove(resourceId, signal) {
595
+ return request({
596
+ method: "DELETE",
597
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}`,
598
+ signal
599
+ });
600
+ }
601
+ };
602
+ }
474
603
  function createDefaultResourceRequest(options = {}) {
475
604
  const baseUrl = (options.baseUrl ?? "").replace(/\/+$/, "");
476
605
  const credentials = options.credentials ?? "include";
@@ -1037,8 +1166,643 @@ var styles = {
1037
1166
  paddingTop: 4
1038
1167
  }
1039
1168
  };
1169
+
1170
+ // src/react/MenuManager.tsx
1171
+ import {
1172
+ useCallback as useCallback3,
1173
+ useEffect as useEffect3,
1174
+ useMemo as useMemo3,
1175
+ useState as useState3
1176
+ } from "react";
1177
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1178
+ var PAGE_SIZE_OPTIONS2 = ["10", "20", "50", "100"];
1179
+ var emptyForm2 = () => ({
1180
+ parentId: ROOT_PARENT_ID,
1181
+ type: MENU_TYPE_MENU,
1182
+ name: "",
1183
+ identification: "",
1184
+ permissionPointIds: [],
1185
+ status: RESOURCE_STATUS_ENABLED
1186
+ });
1187
+ function MenuManager({
1188
+ api,
1189
+ title = "\u83DC\u5355\u7BA1\u7406",
1190
+ pageSize: initialPageSize = "20",
1191
+ toolbarExtra
1192
+ }) {
1193
+ const [records, setRecords] = useState3([]);
1194
+ const [permissionPoints, setPermissionPoints] = useState3([]);
1195
+ const [loading, setLoading] = useState3(false);
1196
+ const [error, setError] = useState3("");
1197
+ const [pageSize, setPageSize] = useState3(initialPageSize);
1198
+ const [pageToken, setPageToken] = useState3("");
1199
+ const [hasPreviousPage, setHasPreviousPage] = useState3(false);
1200
+ const [hasNextPage, setHasNextPage] = useState3(false);
1201
+ const [dialogOpen, setDialogOpen] = useState3(false);
1202
+ const [editing, setEditing] = useState3(null);
1203
+ const [form, setForm] = useState3(emptyForm2);
1204
+ const [saving, setSaving] = useState3(false);
1205
+ const [deletingRow, setDeletingRow] = useState3(null);
1206
+ const [deleting, setDeleting] = useState3(false);
1207
+ const permissionNameMap = useMemo3(() => {
1208
+ const map = /* @__PURE__ */ new Map();
1209
+ permissionPoints.forEach((p) => map.set(p.resourceId, p.name || p.identification));
1210
+ return map;
1211
+ }, [permissionPoints]);
1212
+ const parentOptions = useMemo3(() => {
1213
+ return records.filter((row) => !editing || row.resourceId !== editing.resourceId).map((row) => ({
1214
+ value: row.resourceId,
1215
+ label: `${row.name}\uFF08${MENU_TYPE_LABEL[row.type]}\uFF09`
1216
+ }));
1217
+ }, [records, editing]);
1218
+ const loadList = useCallback3(
1219
+ async (direction = "current", token = pageToken) => {
1220
+ setLoading(true);
1221
+ setError("");
1222
+ try {
1223
+ const result = await api.list({
1224
+ pagination: {
1225
+ pageToken: token,
1226
+ pageSize,
1227
+ pageDirection: direction
1228
+ }
1229
+ });
1230
+ setRecords(result.records);
1231
+ setPageToken(result.pageToken);
1232
+ setHasPreviousPage(result.hasPreviousPage);
1233
+ setHasNextPage(result.hasNextPage);
1234
+ } catch (err) {
1235
+ setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u5931\u8D25");
1236
+ } finally {
1237
+ setLoading(false);
1238
+ }
1239
+ },
1240
+ [api, pageSize, pageToken]
1241
+ );
1242
+ const loadPermissionPoints = useCallback3(async () => {
1243
+ try {
1244
+ const result = await api.listPermissionPoints({
1245
+ pagination: { pageSize: "200", pageDirection: "current" }
1246
+ });
1247
+ setPermissionPoints(result.records);
1248
+ } catch {
1249
+ }
1250
+ }, [api]);
1251
+ useEffect3(() => {
1252
+ void loadList("current", "");
1253
+ void loadPermissionPoints();
1254
+ }, [api, pageSize]);
1255
+ const openCreate = () => {
1256
+ setEditing(null);
1257
+ setForm(emptyForm2());
1258
+ setDialogOpen(true);
1259
+ void loadPermissionPoints();
1260
+ };
1261
+ const openEdit = (row) => {
1262
+ setEditing(row);
1263
+ setForm({
1264
+ parentId: row.parentId || ROOT_PARENT_ID,
1265
+ type: row.type,
1266
+ name: row.name,
1267
+ identification: row.identification,
1268
+ permissionPointIds: [...row.permissionPointIds],
1269
+ status: row.status
1270
+ });
1271
+ setDialogOpen(true);
1272
+ void loadPermissionPoints();
1273
+ };
1274
+ const closeDialog = () => {
1275
+ if (saving) return;
1276
+ setDialogOpen(false);
1277
+ };
1278
+ const handleSubmit = async (event) => {
1279
+ event.preventDefault();
1280
+ if (!form.name.trim()) {
1281
+ setError("\u8BF7\u586B\u5199\u83DC\u5355\u540D\u79F0");
1282
+ return;
1283
+ }
1284
+ setSaving(true);
1285
+ setError("");
1286
+ try {
1287
+ if (editing) {
1288
+ await api.update(editing.resourceId, form);
1289
+ } else {
1290
+ await api.create(form);
1291
+ }
1292
+ setDialogOpen(false);
1293
+ await loadList("current", "");
1294
+ } catch (err) {
1295
+ setError(err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25");
1296
+ } finally {
1297
+ setSaving(false);
1298
+ }
1299
+ };
1300
+ const askDelete = (row) => setDeletingRow(row);
1301
+ const closeDeleteDialog = () => {
1302
+ if (!deleting) setDeletingRow(null);
1303
+ };
1304
+ const confirmDelete = async () => {
1305
+ if (!deletingRow) return;
1306
+ setDeleting(true);
1307
+ setError("");
1308
+ try {
1309
+ await api.remove(deletingRow.resourceId);
1310
+ setDeletingRow(null);
1311
+ await loadList("current", "");
1312
+ } catch (err) {
1313
+ setError(err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25");
1314
+ } finally {
1315
+ setDeleting(false);
1316
+ }
1317
+ };
1318
+ const togglePermission = (id) => {
1319
+ setForm((prev) => {
1320
+ const exists = prev.permissionPointIds.includes(id);
1321
+ return {
1322
+ ...prev,
1323
+ permissionPointIds: exists ? prev.permissionPointIds.filter((x) => x !== id) : [...prev.permissionPointIds, id]
1324
+ };
1325
+ });
1326
+ };
1327
+ const renderPermissionLabels = (row) => {
1328
+ if (row.permissionPointNames?.length) {
1329
+ return row.permissionPointNames.join("\u3001");
1330
+ }
1331
+ if (!row.permissionPointIds.length) return "\u2014";
1332
+ return row.permissionPointIds.map((id) => permissionNameMap.get(id) ?? id).join("\u3001");
1333
+ };
1334
+ return /* @__PURE__ */ jsxs2("div", { style: styles2.root, children: [
1335
+ /* @__PURE__ */ jsxs2("div", { style: styles2.toolbar, children: [
1336
+ /* @__PURE__ */ jsx3("h2", { style: styles2.title, children: title }),
1337
+ /* @__PURE__ */ jsxs2("div", { style: styles2.toolbarRight, children: [
1338
+ toolbarExtra,
1339
+ /* @__PURE__ */ jsx3("button", { type: "button", style: styles2.primaryBtn, onClick: openCreate, children: "\u65B0\u589E" })
1340
+ ] })
1341
+ ] }),
1342
+ error ? /* @__PURE__ */ jsx3("div", { style: styles2.error, children: error }) : null,
1343
+ /* @__PURE__ */ jsx3("div", { style: styles2.tableWrap, children: /* @__PURE__ */ jsxs2("table", { style: styles2.table, children: [
1344
+ /* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
1345
+ /* @__PURE__ */ jsx3("th", { style: styles2.th, children: "\u83DC\u5355\u540D\u79F0" }),
1346
+ /* @__PURE__ */ jsx3("th", { style: styles2.th, children: "\u8BF7\u6C42\u5730\u5740" }),
1347
+ /* @__PURE__ */ jsx3("th", { style: { ...styles2.th, width: 90 }, children: "\u7C7B\u578B" }),
1348
+ /* @__PURE__ */ jsx3("th", { style: { ...styles2.th, width: 80 }, children: "\u53EF\u89C1" }),
1349
+ /* @__PURE__ */ jsx3("th", { style: styles2.th, children: "\u6743\u9650\u6807\u8BC6" }),
1350
+ /* @__PURE__ */ jsx3("th", { style: { ...styles2.th, width: 140 }, children: "\u64CD\u4F5C" })
1351
+ ] }) }),
1352
+ /* @__PURE__ */ jsx3("tbody", { children: loading ? /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsx3("td", { colSpan: 6, style: styles2.empty, children: "\u52A0\u8F7D\u4E2D\u2026" }) }) : records.length === 0 ? /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsx3("td", { colSpan: 6, style: styles2.empty, children: "\u6682\u65E0\u6570\u636E" }) }) : records.map((row) => /* @__PURE__ */ jsxs2("tr", { children: [
1353
+ /* @__PURE__ */ jsx3("td", { style: styles2.td, children: row.name }),
1354
+ /* @__PURE__ */ jsx3("td", { style: styles2.td, children: /* @__PURE__ */ jsx3("code", { style: styles2.code, children: row.identification || "\u2014" }) }),
1355
+ /* @__PURE__ */ jsx3("td", { style: styles2.td, children: MENU_TYPE_LABEL[row.type] }),
1356
+ /* @__PURE__ */ jsx3("td", { style: styles2.td, children: /* @__PURE__ */ jsx3(
1357
+ "span",
1358
+ {
1359
+ style: {
1360
+ ...styles2.badge,
1361
+ background: row.status === RESOURCE_STATUS_ENABLED ? "#e8f7ef" : "#f4f4f5",
1362
+ color: row.status === RESOURCE_STATUS_ENABLED ? "#067647" : "#667085"
1363
+ },
1364
+ children: row.status === RESOURCE_STATUS_ENABLED ? "\u663E\u793A" : "\u9690\u85CF"
1365
+ }
1366
+ ) }),
1367
+ /* @__PURE__ */ jsx3("td", { style: styles2.td, children: renderPermissionLabels(row) }),
1368
+ /* @__PURE__ */ jsxs2("td", { style: styles2.td, children: [
1369
+ /* @__PURE__ */ jsx3("button", { type: "button", style: styles2.linkBtn, onClick: () => openEdit(row), children: "\u7F16\u8F91" }),
1370
+ /* @__PURE__ */ jsx3(
1371
+ "button",
1372
+ {
1373
+ type: "button",
1374
+ style: { ...styles2.linkBtn, color: "#d92d20" },
1375
+ onClick: () => askDelete(row),
1376
+ children: "\u5220\u9664"
1377
+ }
1378
+ )
1379
+ ] })
1380
+ ] }, row.resourceId)) })
1381
+ ] }) }),
1382
+ /* @__PURE__ */ jsxs2("div", { style: styles2.pagination, children: [
1383
+ /* @__PURE__ */ jsxs2("label", { style: styles2.pageSize, children: [
1384
+ "\u6BCF\u9875",
1385
+ /* @__PURE__ */ jsx3(
1386
+ "select",
1387
+ {
1388
+ value: pageSize,
1389
+ onChange: (e) => {
1390
+ setPageToken("");
1391
+ setPageSize(e.target.value);
1392
+ },
1393
+ style: styles2.select,
1394
+ children: PAGE_SIZE_OPTIONS2.map((size) => /* @__PURE__ */ jsx3("option", { value: size, children: size }, size))
1395
+ }
1396
+ )
1397
+ ] }),
1398
+ /* @__PURE__ */ jsxs2("div", { style: styles2.pageBtns, children: [
1399
+ /* @__PURE__ */ jsx3(
1400
+ "button",
1401
+ {
1402
+ type: "button",
1403
+ style: styles2.secondaryBtn,
1404
+ disabled: !hasPreviousPage || loading,
1405
+ onClick: () => void loadList("previous"),
1406
+ children: "\u4E0A\u4E00\u9875"
1407
+ }
1408
+ ),
1409
+ /* @__PURE__ */ jsx3(
1410
+ "button",
1411
+ {
1412
+ type: "button",
1413
+ style: styles2.secondaryBtn,
1414
+ disabled: !hasNextPage || loading,
1415
+ onClick: () => void loadList("next"),
1416
+ children: "\u4E0B\u4E00\u9875"
1417
+ }
1418
+ )
1419
+ ] })
1420
+ ] }),
1421
+ dialogOpen ? /* @__PURE__ */ jsx3("div", { style: styles2.mask, onClick: closeDialog, children: /* @__PURE__ */ jsxs2(
1422
+ "div",
1423
+ {
1424
+ style: { ...styles2.dialog, maxWidth: 520 },
1425
+ onClick: (e) => e.stopPropagation(),
1426
+ role: "dialog",
1427
+ "aria-modal": "true",
1428
+ children: [
1429
+ /* @__PURE__ */ jsxs2("div", { style: styles2.dialogHeader, children: [
1430
+ /* @__PURE__ */ jsx3("h3", { style: styles2.dialogTitle, children: editing ? "\u7F16\u8F91\u83DC\u5355" : "\u65B0\u589E\u83DC\u5355" }),
1431
+ /* @__PURE__ */ jsx3("button", { type: "button", style: styles2.iconBtn, onClick: closeDialog, "aria-label": "\u5173\u95ED", children: "\xD7" })
1432
+ ] }),
1433
+ /* @__PURE__ */ jsxs2("form", { style: styles2.form, onSubmit: (e) => void handleSubmit(e), children: [
1434
+ /* @__PURE__ */ jsxs2("label", { style: styles2.field, children: [
1435
+ /* @__PURE__ */ jsx3("span", { style: styles2.label, children: "\u4E0A\u7EA7\u83DC\u5355" }),
1436
+ /* @__PURE__ */ jsxs2(
1437
+ "select",
1438
+ {
1439
+ style: styles2.input,
1440
+ value: form.parentId,
1441
+ onChange: (e) => setForm((prev) => ({ ...prev, parentId: e.target.value })),
1442
+ children: [
1443
+ /* @__PURE__ */ jsx3("option", { value: ROOT_PARENT_ID, children: "\u6839\u76EE\u5F55" }),
1444
+ parentOptions.map((opt) => /* @__PURE__ */ jsx3("option", { value: opt.value, children: opt.label }, opt.value))
1445
+ ]
1446
+ }
1447
+ )
1448
+ ] }),
1449
+ /* @__PURE__ */ jsxs2("fieldset", { style: styles2.fieldset, children: [
1450
+ /* @__PURE__ */ jsx3("legend", { style: styles2.label, children: "\u83DC\u5355\u7C7B\u578B" }),
1451
+ /* @__PURE__ */ jsx3("div", { style: styles2.radioGroup, children: MENU_TYPE_OPTIONS.map((opt) => /* @__PURE__ */ jsxs2("label", { style: styles2.radioItem, children: [
1452
+ /* @__PURE__ */ jsx3(
1453
+ "input",
1454
+ {
1455
+ type: "radio",
1456
+ name: "menu-type",
1457
+ checked: form.type === opt.value,
1458
+ onChange: () => setForm((prev) => ({
1459
+ ...prev,
1460
+ type: opt.value
1461
+ }))
1462
+ }
1463
+ ),
1464
+ opt.label
1465
+ ] }, opt.value)) })
1466
+ ] }),
1467
+ /* @__PURE__ */ jsxs2("label", { style: styles2.field, children: [
1468
+ /* @__PURE__ */ jsx3("span", { style: styles2.label, children: "\u83DC\u5355\u540D\u79F0" }),
1469
+ /* @__PURE__ */ jsx3(
1470
+ "input",
1471
+ {
1472
+ style: styles2.input,
1473
+ value: form.name,
1474
+ onChange: (e) => setForm((prev) => ({ ...prev, name: e.target.value })),
1475
+ placeholder: "\u8BF7\u8F93\u5165\u83DC\u5355\u540D\u79F0",
1476
+ required: true
1477
+ }
1478
+ )
1479
+ ] }),
1480
+ /* @__PURE__ */ jsxs2("label", { style: styles2.field, children: [
1481
+ /* @__PURE__ */ jsx3("span", { style: styles2.label, children: "\u8BF7\u6C42\u5730\u5740" }),
1482
+ /* @__PURE__ */ jsx3(
1483
+ "input",
1484
+ {
1485
+ style: styles2.input,
1486
+ value: form.identification,
1487
+ onChange: (e) => setForm((prev) => ({ ...prev, identification: e.target.value })),
1488
+ placeholder: "\u5982 /system/user"
1489
+ }
1490
+ )
1491
+ ] }),
1492
+ /* @__PURE__ */ jsxs2("fieldset", { style: styles2.fieldset, children: [
1493
+ /* @__PURE__ */ jsx3("legend", { style: styles2.label, children: "\u6743\u9650\u6807\u8BC6" }),
1494
+ /* @__PURE__ */ jsx3("div", { style: styles2.multiSelect, children: permissionPoints.length === 0 ? /* @__PURE__ */ jsx3("div", { style: styles2.hint, children: "\u6682\u65E0\u6743\u9650\u70B9\uFF0C\u8BF7\u5148\u5728\u6743\u9650\u70B9\u7BA1\u7406\u4E2D\u65B0\u589E" }) : permissionPoints.map((p) => /* @__PURE__ */ jsxs2("label", { style: styles2.checkItem, children: [
1495
+ /* @__PURE__ */ jsx3(
1496
+ "input",
1497
+ {
1498
+ type: "checkbox",
1499
+ checked: form.permissionPointIds.includes(p.resourceId),
1500
+ onChange: () => togglePermission(p.resourceId)
1501
+ }
1502
+ ),
1503
+ /* @__PURE__ */ jsxs2("span", { children: [
1504
+ p.name,
1505
+ /* @__PURE__ */ jsx3("code", { style: { ...styles2.code, marginLeft: 6 }, children: p.identification })
1506
+ ] })
1507
+ ] }, p.resourceId)) })
1508
+ ] }),
1509
+ /* @__PURE__ */ jsxs2("fieldset", { style: styles2.fieldset, children: [
1510
+ /* @__PURE__ */ jsx3("legend", { style: styles2.label, children: "\u72B6\u6001" }),
1511
+ /* @__PURE__ */ jsx3("div", { style: styles2.radioGroup, children: MENU_VISIBILITY_OPTIONS.map((opt) => /* @__PURE__ */ jsxs2("label", { style: styles2.radioItem, children: [
1512
+ /* @__PURE__ */ jsx3(
1513
+ "input",
1514
+ {
1515
+ type: "radio",
1516
+ name: "menu-status",
1517
+ checked: form.status === opt.value,
1518
+ onChange: () => setForm((prev) => ({ ...prev, status: opt.value }))
1519
+ }
1520
+ ),
1521
+ opt.label
1522
+ ] }, opt.value)) })
1523
+ ] }),
1524
+ /* @__PURE__ */ jsxs2("div", { style: styles2.dialogFooter, children: [
1525
+ /* @__PURE__ */ jsx3("button", { type: "button", style: styles2.secondaryBtn, onClick: closeDialog, children: "\u53D6\u6D88" }),
1526
+ /* @__PURE__ */ jsx3("button", { type: "submit", style: styles2.primaryBtn, disabled: saving, children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58" })
1527
+ ] })
1528
+ ] })
1529
+ ]
1530
+ }
1531
+ ) }) : null,
1532
+ deletingRow ? /* @__PURE__ */ jsx3("div", { style: styles2.mask, onClick: closeDeleteDialog, children: /* @__PURE__ */ jsxs2(
1533
+ "div",
1534
+ {
1535
+ style: { ...styles2.dialog, maxWidth: 420 },
1536
+ onClick: (e) => e.stopPropagation(),
1537
+ role: "dialog",
1538
+ "aria-modal": "true",
1539
+ children: [
1540
+ /* @__PURE__ */ jsxs2("div", { style: styles2.dialogHeader, children: [
1541
+ /* @__PURE__ */ jsx3("h3", { style: styles2.dialogTitle, children: "\u786E\u8BA4\u5220\u9664" }),
1542
+ /* @__PURE__ */ jsx3(
1543
+ "button",
1544
+ {
1545
+ type: "button",
1546
+ style: styles2.iconBtn,
1547
+ onClick: closeDeleteDialog,
1548
+ "aria-label": "\u5173\u95ED",
1549
+ children: "\xD7"
1550
+ }
1551
+ )
1552
+ ] }),
1553
+ /* @__PURE__ */ jsxs2("div", { style: styles2.confirmBody, children: [
1554
+ /* @__PURE__ */ jsxs2("p", { style: styles2.confirmText, children: [
1555
+ "\u786E\u8BA4\u5220\u9664\u83DC\u5355\u300C",
1556
+ /* @__PURE__ */ jsx3("strong", { children: deletingRow.name }),
1557
+ "\u300D\u5417\uFF1F\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\u3002"
1558
+ ] }),
1559
+ /* @__PURE__ */ jsxs2("div", { style: styles2.dialogFooter, children: [
1560
+ /* @__PURE__ */ jsx3(
1561
+ "button",
1562
+ {
1563
+ type: "button",
1564
+ style: styles2.secondaryBtn,
1565
+ onClick: closeDeleteDialog,
1566
+ disabled: deleting,
1567
+ children: "\u53D6\u6D88"
1568
+ }
1569
+ ),
1570
+ /* @__PURE__ */ jsx3(
1571
+ "button",
1572
+ {
1573
+ type: "button",
1574
+ style: styles2.dangerBtn,
1575
+ onClick: () => void confirmDelete(),
1576
+ disabled: deleting,
1577
+ children: deleting ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u5220\u9664"
1578
+ }
1579
+ )
1580
+ ] })
1581
+ ] })
1582
+ ]
1583
+ }
1584
+ ) }) : null
1585
+ ] });
1586
+ }
1587
+ var styles2 = {
1588
+ root: {
1589
+ display: "flex",
1590
+ flexDirection: "column",
1591
+ gap: 16,
1592
+ padding: 16,
1593
+ color: "#101828",
1594
+ fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif'
1595
+ },
1596
+ toolbar: {
1597
+ display: "flex",
1598
+ alignItems: "center",
1599
+ justifyContent: "space-between",
1600
+ gap: 12
1601
+ },
1602
+ title: { margin: 0, fontSize: 18, fontWeight: 600 },
1603
+ toolbarRight: { display: "flex", alignItems: "center", gap: 8 },
1604
+ error: {
1605
+ padding: "10px 12px",
1606
+ borderRadius: 8,
1607
+ background: "#fef3f2",
1608
+ color: "#b42318",
1609
+ fontSize: 13
1610
+ },
1611
+ tableWrap: {
1612
+ overflow: "auto",
1613
+ border: "1px solid #eaecf0",
1614
+ borderRadius: 10,
1615
+ background: "#fff"
1616
+ },
1617
+ table: { width: "100%", borderCollapse: "collapse", minWidth: 820 },
1618
+ th: {
1619
+ textAlign: "left",
1620
+ padding: "12px 14px",
1621
+ fontSize: 13,
1622
+ fontWeight: 600,
1623
+ color: "#475467",
1624
+ background: "#f9fafb",
1625
+ borderBottom: "1px solid #eaecf0"
1626
+ },
1627
+ td: {
1628
+ padding: "12px 14px",
1629
+ fontSize: 14,
1630
+ borderBottom: "1px solid #f2f4f7",
1631
+ verticalAlign: "middle"
1632
+ },
1633
+ empty: { padding: 28, textAlign: "center", color: "#98a2b3", fontSize: 14 },
1634
+ code: {
1635
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
1636
+ fontSize: 13,
1637
+ background: "#f2f4f7",
1638
+ padding: "2px 6px",
1639
+ borderRadius: 4
1640
+ },
1641
+ badge: {
1642
+ display: "inline-block",
1643
+ padding: "2px 8px",
1644
+ borderRadius: 999,
1645
+ fontSize: 12,
1646
+ fontWeight: 500
1647
+ },
1648
+ linkBtn: {
1649
+ border: "none",
1650
+ background: "transparent",
1651
+ color: "#049BAD",
1652
+ cursor: "pointer",
1653
+ padding: "0 8px 0 0",
1654
+ fontSize: 13
1655
+ },
1656
+ pagination: {
1657
+ display: "flex",
1658
+ alignItems: "center",
1659
+ justifyContent: "space-between",
1660
+ gap: 12
1661
+ },
1662
+ pageSize: { display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "#475467" },
1663
+ pageBtns: { display: "flex", gap: 8 },
1664
+ primaryBtn: {
1665
+ border: "none",
1666
+ background: "#049BAD",
1667
+ color: "#fff",
1668
+ borderRadius: 8,
1669
+ padding: "8px 14px",
1670
+ cursor: "pointer",
1671
+ fontSize: 14
1672
+ },
1673
+ secondaryBtn: {
1674
+ border: "1px solid #d0d5dd",
1675
+ background: "#fff",
1676
+ color: "#344054",
1677
+ borderRadius: 8,
1678
+ padding: "8px 14px",
1679
+ cursor: "pointer",
1680
+ fontSize: 14
1681
+ },
1682
+ dangerBtn: {
1683
+ border: "none",
1684
+ background: "#d92d20",
1685
+ color: "#fff",
1686
+ borderRadius: 8,
1687
+ padding: "8px 14px",
1688
+ cursor: "pointer",
1689
+ fontSize: 14
1690
+ },
1691
+ select: {
1692
+ border: "1px solid #d0d5dd",
1693
+ borderRadius: 6,
1694
+ padding: "4px 8px",
1695
+ fontSize: 13,
1696
+ backgroundColor: "#ffffff",
1697
+ color: "#101828"
1698
+ },
1699
+ mask: {
1700
+ position: "fixed",
1701
+ inset: 0,
1702
+ background: "rgba(16, 24, 40, 0.45)",
1703
+ display: "flex",
1704
+ alignItems: "center",
1705
+ justifyContent: "center",
1706
+ zIndex: 1e3,
1707
+ padding: 16
1708
+ },
1709
+ dialog: {
1710
+ width: "100%",
1711
+ maxWidth: 480,
1712
+ background: "#fff",
1713
+ borderRadius: 12,
1714
+ boxShadow: "0 20px 40px rgba(16,24,40,0.18)",
1715
+ maxHeight: "90vh",
1716
+ overflow: "auto"
1717
+ },
1718
+ dialogHeader: {
1719
+ display: "flex",
1720
+ alignItems: "center",
1721
+ justifyContent: "space-between",
1722
+ padding: "14px 16px",
1723
+ borderBottom: "1px solid #eaecf0",
1724
+ position: "sticky",
1725
+ top: 0,
1726
+ background: "#fff",
1727
+ zIndex: 1
1728
+ },
1729
+ dialogTitle: { margin: 0, fontSize: 16, fontWeight: 600 },
1730
+ iconBtn: {
1731
+ border: "none",
1732
+ background: "transparent",
1733
+ fontSize: 22,
1734
+ lineHeight: 1,
1735
+ cursor: "pointer",
1736
+ color: "#667085"
1737
+ },
1738
+ form: { display: "flex", flexDirection: "column", gap: 12, padding: 16 },
1739
+ confirmBody: { display: "flex", flexDirection: "column", gap: 16, padding: 16 },
1740
+ confirmText: { margin: 0, fontSize: 14, color: "#344054", lineHeight: 1.6 },
1741
+ field: { display: "flex", flexDirection: "column", gap: 6 },
1742
+ fieldset: {
1743
+ margin: 0,
1744
+ padding: 0,
1745
+ border: "none",
1746
+ display: "flex",
1747
+ flexDirection: "column",
1748
+ gap: 8
1749
+ },
1750
+ label: { fontSize: 13, color: "#344054", fontWeight: 500 },
1751
+ input: {
1752
+ border: "1px solid #d0d5dd",
1753
+ borderRadius: 8,
1754
+ padding: "8px 10px",
1755
+ fontSize: 14,
1756
+ outline: "none",
1757
+ backgroundColor: "#ffffff",
1758
+ color: "#101828",
1759
+ boxSizing: "border-box",
1760
+ width: "100%"
1761
+ },
1762
+ radioGroup: { display: "flex", flexWrap: "wrap", gap: 16 },
1763
+ radioItem: {
1764
+ display: "flex",
1765
+ alignItems: "center",
1766
+ gap: 6,
1767
+ fontSize: 14,
1768
+ color: "#344054",
1769
+ cursor: "pointer"
1770
+ },
1771
+ multiSelect: {
1772
+ maxHeight: 160,
1773
+ overflow: "auto",
1774
+ border: "1px solid #eaecf0",
1775
+ borderRadius: 8,
1776
+ padding: 8,
1777
+ background: "#f9fafb"
1778
+ },
1779
+ checkItem: {
1780
+ display: "flex",
1781
+ alignItems: "center",
1782
+ gap: 8,
1783
+ padding: "6px 4px",
1784
+ fontSize: 13,
1785
+ color: "#344054",
1786
+ cursor: "pointer"
1787
+ },
1788
+ hint: { fontSize: 13, color: "#98a2b3", padding: 8 },
1789
+ dialogFooter: {
1790
+ display: "flex",
1791
+ justifyContent: "flex-end",
1792
+ gap: 8,
1793
+ paddingTop: 4
1794
+ }
1795
+ };
1040
1796
  export {
1041
1797
  Can,
1798
+ MENU_LIST_TYPE_PARAM,
1799
+ MENU_TYPE_BUTTON,
1800
+ MENU_TYPE_LABEL,
1801
+ MENU_TYPE_MENU,
1802
+ MENU_TYPE_OPTIONS,
1803
+ MENU_TYPE_PAGE,
1804
+ MENU_VISIBILITY_OPTIONS,
1805
+ MenuManager,
1042
1806
  PermissionProvider,
1043
1807
  PermissionStore,
1044
1808
  RESOURCE_PRIVATE_OPTIONS,
@@ -1046,18 +1810,23 @@ export {
1046
1810
  RESOURCE_STATUS_ENABLED,
1047
1811
  RESOURCE_STATUS_OPTIONS,
1048
1812
  RESOURCE_TYPE_API,
1813
+ ROOT_PARENT_ID,
1049
1814
  ResourceManager,
1050
1815
  appendQueryParam,
1051
1816
  buildCreateBody,
1817
+ buildCreateMenuBody,
1052
1818
  buildUpdateBody,
1819
+ buildUpdateMenuBody,
1053
1820
  createAuthorizationResourceApi,
1054
1821
  createDefaultResourceRequest,
1822
+ createMenuResourceApi,
1055
1823
  createPermissionStore,
1056
1824
  extractPagination,
1057
1825
  extractRecords,
1058
1826
  getAppClientId,
1059
1827
  getDeviceWorkerId,
1060
1828
  mapAuthorizationResource,
1829
+ mapMenuResource,
1061
1830
  snowyflake,
1062
1831
  useHasPermission,
1063
1832
  useHasRole,