openxiangda 1.0.11 → 1.0.13
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.
package/lib/cli.js
CHANGED
|
@@ -1325,6 +1325,9 @@ async function permission(args) {
|
|
|
1325
1325
|
fail('用法: openxiangda permission page-group-create <groupCode> --name <text> [--menu-codes <menuCode...>|--page-codes <pageCode...>|--form-codes <formCode...>|--menu-ids <id...>]');
|
|
1326
1326
|
}
|
|
1327
1327
|
const target = getWorkspaceTarget(config, profileName, flags);
|
|
1328
|
+
const roles = splitList(flags.roles);
|
|
1329
|
+
const menuFormUuids = resolvePagePermissionMenuTargets(target.bound, flags);
|
|
1330
|
+
const runtimeAliasTargets = resolvePagePermissionRuntimeAliasTargets(target.bound, flags);
|
|
1328
1331
|
const data = await requestWithAuth(
|
|
1329
1332
|
config,
|
|
1330
1333
|
target.profileName,
|
|
@@ -1333,14 +1336,38 @@ async function permission(args) {
|
|
|
1333
1336
|
method: 'POST',
|
|
1334
1337
|
body: {
|
|
1335
1338
|
name,
|
|
1336
|
-
roles
|
|
1337
|
-
menuFormUuids
|
|
1339
|
+
roles,
|
|
1340
|
+
menuFormUuids,
|
|
1338
1341
|
},
|
|
1339
1342
|
}
|
|
1340
1343
|
);
|
|
1341
1344
|
if (data?.id) savePagePermissionGroupResource(target, groupCode, data.id, { name });
|
|
1342
|
-
|
|
1343
|
-
|
|
1345
|
+
let runtimeAliasData = null;
|
|
1346
|
+
if (runtimeAliasTargets.length > 0) {
|
|
1347
|
+
const runtimeAliasGroupCode = `${groupCode}__runtime_aliases`;
|
|
1348
|
+
const runtimeAliasName = `${name}(运行时别名)`;
|
|
1349
|
+
runtimeAliasData = await requestWithAuth(
|
|
1350
|
+
config,
|
|
1351
|
+
target.profileName,
|
|
1352
|
+
`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/page-permission-groups`,
|
|
1353
|
+
{
|
|
1354
|
+
method: 'POST',
|
|
1355
|
+
body: {
|
|
1356
|
+
name: runtimeAliasName,
|
|
1357
|
+
roles,
|
|
1358
|
+
menuFormUuids: runtimeAliasTargets,
|
|
1359
|
+
},
|
|
1360
|
+
}
|
|
1361
|
+
);
|
|
1362
|
+
if (runtimeAliasData?.id) {
|
|
1363
|
+
savePagePermissionGroupResource(target, runtimeAliasGroupCode, runtimeAliasData.id, {
|
|
1364
|
+
name: runtimeAliasName,
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
const output = runtimeAliasData ? { ...data, runtimeAliasGroup: runtimeAliasData } : data;
|
|
1369
|
+
if (flags.json) return writeJson(output);
|
|
1370
|
+
print(JSON.stringify(output, null, 2));
|
|
1344
1371
|
return;
|
|
1345
1372
|
}
|
|
1346
1373
|
|
|
@@ -1918,26 +1945,46 @@ function resolvePagePermissionMenuTargets(bound, flags = {}) {
|
|
|
1918
1945
|
|
|
1919
1946
|
function resolveMenuPermissionTargets(bound, menuCode) {
|
|
1920
1947
|
const menuEntry = bound.resources?.menus?.[menuCode];
|
|
1921
|
-
const menuId = resolveMenuId(bound, menuCode);
|
|
1922
1948
|
if (menuEntry?.formUuid) return [menuEntry.formUuid];
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
if (menuEntry?.pageId || menuEntry?.pageCode || menuEntry?.routeKey || menuEntry?.legacyFormUuid) {
|
|
1926
|
-
return unique([menuId, ...resolveCodePagePermissionAliases(bound, menuEntry)]);
|
|
1927
|
-
}
|
|
1928
|
-
return [menuId];
|
|
1949
|
+
if (menuEntry?.pageId) return [menuEntry.pageId];
|
|
1950
|
+
return [resolveMenuId(bound, menuCode)];
|
|
1929
1951
|
}
|
|
1930
1952
|
|
|
1931
1953
|
function resolvePagePermissionTargets(bound, pageCode) {
|
|
1954
|
+
const menuEntry = findPagePermissionMenuEntry(bound, pageCode);
|
|
1955
|
+
if (menuEntry?.pageId) {
|
|
1956
|
+
return [menuEntry.pageId];
|
|
1957
|
+
}
|
|
1958
|
+
fail(`页面 ${pageCode} 未找到已绑定代码页菜单。请先发布/创建菜单,或直接传 --menu-form-uuids/--menu-ids。`);
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
function resolvePagePermissionRuntimeAliasTargets(bound, flags = {}) {
|
|
1962
|
+
const fromMenuCodes = splitList(flags['menu-codes']).flatMap(code => resolveMenuPermissionRuntimeAliases(bound, code));
|
|
1963
|
+
const fromPageCodes = splitList(flags['page-codes']).flatMap(code => resolvePagePermissionRuntimeAliases(bound, code));
|
|
1964
|
+
return unique([...fromMenuCodes, ...fromPageCodes].filter(Boolean));
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
function resolveMenuPermissionRuntimeAliases(bound, menuCode) {
|
|
1968
|
+
const menuEntry = bound.resources?.menus?.[menuCode];
|
|
1969
|
+
if (!menuEntry || menuEntry.formUuid) return [];
|
|
1970
|
+
if (menuEntry.pageId || menuEntry.pageCode || menuEntry.routeKey || menuEntry.legacyFormUuid) {
|
|
1971
|
+
return resolveCodePagePermissionAliases(bound, menuEntry);
|
|
1972
|
+
}
|
|
1973
|
+
return [];
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
function resolvePagePermissionRuntimeAliases(bound, pageCode) {
|
|
1977
|
+
const menuEntry = findPagePermissionMenuEntry(bound, pageCode);
|
|
1978
|
+
if (menuEntry?.menuId) return resolveCodePagePermissionAliases(bound, menuEntry, pageCode);
|
|
1979
|
+
fail(`页面 ${pageCode} 未找到已绑定菜单。请先发布/创建菜单,或直接传 --menu-codes/--menu-ids。`);
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
function findPagePermissionMenuEntry(bound, pageCode) {
|
|
1932
1983
|
const pageId = resolveOptionalPageId(bound, pageCode);
|
|
1933
|
-
|
|
1984
|
+
return findMenuEntry(bound, entry => {
|
|
1934
1985
|
if (!entry) return false;
|
|
1935
1986
|
return entry.pageId === pageId || entry.pageCode === pageCode || entry.routeKey === pageCode;
|
|
1936
1987
|
});
|
|
1937
|
-
if (menuEntry?.menuId) {
|
|
1938
|
-
return unique([menuEntry.menuId, ...resolveCodePagePermissionAliases(bound, menuEntry, pageCode)]);
|
|
1939
|
-
}
|
|
1940
|
-
fail(`页面 ${pageCode} 未找到已绑定菜单。请先发布/创建菜单,或直接传 --menu-codes/--menu-ids。`);
|
|
1941
1988
|
}
|
|
1942
1989
|
|
|
1943
1990
|
function resolveCodePagePermissionAliases(bound, menuEntry = {}, pageCode) {
|
|
@@ -1954,9 +2001,11 @@ function resolveCodePagePermissionAliases(bound, menuEntry = {}, pageCode) {
|
|
|
1954
2001
|
});
|
|
1955
2002
|
return unique([
|
|
1956
2003
|
pageCode,
|
|
2004
|
+
menuEntry.menuId,
|
|
1957
2005
|
menuEntry.pageCode,
|
|
1958
2006
|
menuEntry.routeKey,
|
|
1959
2007
|
menuEntry.legacyFormUuid,
|
|
2008
|
+
pageEntry?.pageId,
|
|
1960
2009
|
pageEntry?.pageCode,
|
|
1961
2010
|
pageEntry?.routeKey,
|
|
1962
2011
|
pageEntry?.legacyFormUuid,
|
|
@@ -369,11 +369,11 @@ Body:
|
|
|
369
369
|
{
|
|
370
370
|
"name": "销售可见页面",
|
|
371
371
|
"roles": ["sales"],
|
|
372
|
-
"menuFormUuids": ["FORM_XXX", "
|
|
372
|
+
"menuFormUuids": ["FORM_XXX", "PAGE_ID_FOR_CODE_PAGE"]
|
|
373
373
|
}
|
|
374
374
|
```
|
|
375
375
|
|
|
376
|
-
An empty `menuFormUuids` array means all menus/pages are visible to the matched roles. For form menus this field can contain form UUIDs. For custom code page menus,
|
|
376
|
+
An empty `menuFormUuids` array means all menus/pages are visible to the matched roles. For form menus this field can contain form UUIDs. For custom code page menus, the user-facing permission group should contain the code page `pageId`, which is what the platform permission editor uses for tree check state. Because the current `/view` runtime guard also checks menu IDs, route keys, and legacy `PAGE_...` aliases, OpenXiangda CLI `--page-codes` / `--menu-codes` creates a companion `(运行时别名)` page permission group for those aliases instead of mixing them into the editable menu group.
|
|
377
377
|
|
|
378
378
|
### GET `/apps/:appType/page-permission-groups/:groupId`
|
|
379
379
|
|
|
@@ -19,14 +19,26 @@ Role IDs are platform-specific. Store them only in `.openxiangda/state.json` und
|
|
|
19
19
|
## Page Permission Groups
|
|
20
20
|
|
|
21
21
|
Page permission groups map role codes to visible menu targets. Form menus use their `FORM_...`
|
|
22
|
-
form UUIDs
|
|
23
|
-
|
|
22
|
+
form UUIDs. Custom code page/display menus need split targets because current platform
|
|
23
|
+
surfaces check different identifiers: the admin edit tree expects page IDs, while `/view`
|
|
24
|
+
runtime checks menu IDs, route keys, and legacy `PAGE_...` aliases.
|
|
24
25
|
|
|
25
26
|
```json
|
|
26
27
|
{
|
|
27
28
|
"name": "销售页面",
|
|
28
29
|
"roles": ["sales"],
|
|
29
|
-
"menuFormUuids": ["FORM_CUSTOMER", "FORM_ORDER", "
|
|
30
|
+
"menuFormUuids": ["FORM_CUSTOMER", "FORM_ORDER", "PAGE_ID_FOR_CODE_PAGE"]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
For custom code pages, keep the user-facing group editable by storing only page IDs, then add a
|
|
35
|
+
companion runtime alias group with the same roles:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"name": "销售页面(运行时别名)",
|
|
40
|
+
"roles": ["sales"],
|
|
41
|
+
"menuFormUuids": ["MENU_ID_FOR_CODE_PAGE", "CODE_PAGE_ROUTE_KEY", "PAGE_LEGACY_FORM_UUID"]
|
|
30
42
|
}
|
|
31
43
|
```
|
|
32
44
|
|
|
@@ -35,7 +47,7 @@ Rules:
|
|
|
35
47
|
- `roles: []` means all roles can match.
|
|
36
48
|
- `menuFormUuids: []` means all menus/pages are visible to matched roles.
|
|
37
49
|
- Prefer `--form-codes` in CLI for form menus so each profile resolves its own form UUIDs.
|
|
38
|
-
- Prefer `--page-codes` or `--menu-codes` in CLI for custom code page menus. The CLI writes
|
|
50
|
+
- Prefer `--page-codes` or `--menu-codes` in CLI for custom code page menus. The CLI writes page IDs to the editable group and creates the companion `(运行时别名)` group automatically.
|
|
39
51
|
|
|
40
52
|
## Form Permission Groups
|
|
41
53
|
|
|
@@ -43,7 +43,7 @@ openxiangda permission page-group-create sales_pages --name "销售页面" --rol
|
|
|
43
43
|
openxiangda permission page-group-create portal_pages --name "门户页面" --page-codes portal_pc,portal_mobile --profile dev
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
Use `--page-codes` or `--menu-codes` for custom code page menus; the CLI resolves
|
|
46
|
+
Use `--page-codes` or `--menu-codes` for custom code page menus; the CLI resolves the editable permission group to the published code page `pageId`, and creates a companion `(运行时别名)` group for the menu ID, route key, and legacy `PAGE_...` alias required by the platform's current `/view` guard and custom-page bootstrap checks. Use `--form-codes` for form menus; the CLI resolves forms to profile-local form UUIDs. Empty target lists mean all menus/pages are visible to matched roles.
|
|
47
47
|
|
|
48
48
|
## Form Permission Groups
|
|
49
49
|
|