@gadmin2n/schematics 0.0.149 → 0.0.151
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/dist/lib/application/files/gadmin2-game-angle-demo/CODEBUDDY.md +125 -36
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +42 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/gitignore +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/.seed-timestamp +0 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +3 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/check-dev-env.js +218 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/page-manage.ts +78 -12
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +37 -67
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/config/index.ts +0 -17
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.controller.ts +46 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.controller.ts +60 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-callback.controller.ts +3 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.controller.ts +9 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.controller.ts +55 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.module.ts +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/permTransfer/page-transfer.service.ts +491 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/permTransfer/perm-transfer.dto.ts +213 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/permTransfer/perm-transfer.module.ts +28 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/permTransfer/resource-transfer.service.ts +137 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/permTransfer/role-transfer.service.ts +248 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/permTransfer/transfer-token.service.ts +65 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/permTransfer/user-transfer.service.ts +146 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.controller.ts +55 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.module.ts +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.controller.ts +55 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.module.ts +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/providers/user-group.provider.spec.ts +46 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/providers/user-group.provider.ts +3 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.ts +55 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.module.ts +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-cancellation.spec.ts +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.spec.ts +96 -14
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.ts +41 -41
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-database-function.spec.ts +36 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-database-function.ts +90 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-event-catalog.spec.ts +4 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-event-trigger.pg.spec.ts +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution-idempotency.spec.ts +115 -63
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-lifecycle-outbox.service.spec.ts +166 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-lifecycle-outbox.service.ts +217 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-lifecycle-runtime.controller.spec.ts +33 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-lifecycle-runtime.controller.ts +57 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-lifecycle.service.spec.ts +196 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-lifecycle.service.ts +125 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.controller.ts +9 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +148 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +12 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +14 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +75 -45
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.spec.ts +25 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/TransferExportModal.tsx +115 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/TransferImportModal.tsx +257 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +0 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +40 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/workflow.json +15 -13
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +40 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json +15 -13
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts +2 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +89 -65
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +51 -127
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/permissionReadme/index.tsx +53 -109
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +45 -41
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +51 -72
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/list.tsx +49 -40
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.test.tsx +16 -5
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ReadonlyNodePanel.test.tsx +28 -10
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.test.tsx +60 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +94 -12
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-instance-show.css +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/default-widgets.tsx +3 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +8 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/DbExecuteConfigEditor.tsx +167 -94
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/EventTriggerConfigEditor.tsx +95 -95
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/EventTriggerLifecycleConfigEditor.test.tsx +81 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/EventTriggerLifecycleConfigEditor.tsx +126 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SimplifiedNodeEditors.test.tsx +48 -52
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/forEachConnection.ts +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/newNodeConfig.ts +1 -3
- package/package.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/config/ac.config.ts +0 -24
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/SqlModal.tsx +0 -495
|
@@ -540,6 +540,12 @@
|
|
|
540
540
|
"conditionField": "Field for condition {{number}}",
|
|
541
541
|
"conditionOperator": "Comparison for condition {{number}}",
|
|
542
542
|
"conditionValue": "Value for condition {{number}}",
|
|
543
|
+
"failureCallbackTitle": "Workflow failure notification",
|
|
544
|
+
"failureCallbackDescription": "Reliably notify the business system after the Workflow finally fails. The business API must handle the event ID idempotently.",
|
|
545
|
+
"failureCallbackEnabled": "Notify business system",
|
|
546
|
+
"failureCallbackConnection": "Business system connection",
|
|
547
|
+
"failureCallbackPath": "Failure API path",
|
|
548
|
+
"failureCallbackLoadFailed": "Failed to load business system connections",
|
|
543
549
|
"selectConditionField": "Select a field",
|
|
544
550
|
"newDataField": "New data · {{field}}",
|
|
545
551
|
"oldDataField": "Previous data · {{field}}",
|
|
@@ -575,19 +581,13 @@
|
|
|
575
581
|
}
|
|
576
582
|
},
|
|
577
583
|
"database": {
|
|
578
|
-
"
|
|
579
|
-
"
|
|
580
|
-
"
|
|
581
|
-
"
|
|
582
|
-
"
|
|
583
|
-
"
|
|
584
|
-
"
|
|
585
|
-
"readWriteError": "Only one query, insert, update, or delete statement is allowed.",
|
|
586
|
-
"parameters": "Parameter values",
|
|
587
|
-
"parameter": "Parameter",
|
|
588
|
-
"value": "Value",
|
|
589
|
-
"parametersHint": "Values are used by $1, $2, and so on in order.",
|
|
590
|
-
"addParameter": "Add parameter value",
|
|
584
|
+
"function": "Database Function",
|
|
585
|
+
"functionHint": "Only Functions in workflow_api in the current GAdmin database are shown.",
|
|
586
|
+
"selectFunction": "Select a Function",
|
|
587
|
+
"loadFailed": "Could not load the Function catalog.",
|
|
588
|
+
"functionMissing": "This Function no longer exists. Select another Function.",
|
|
589
|
+
"returnType": "Return type: {{type}}",
|
|
590
|
+
"noArguments": "This Function has no arguments.",
|
|
591
591
|
"timeout": "Timeout",
|
|
592
592
|
"seconds": "seconds"
|
|
593
593
|
},
|
|
@@ -648,6 +648,7 @@
|
|
|
648
648
|
"noDescription": "No description",
|
|
649
649
|
"noConfiguration": "This instance has no configuration",
|
|
650
650
|
"configurationDescription": "Review the saved {{name}} execution parameters in read-only mode.",
|
|
651
|
+
"rawConfiguration": "Raw node configuration",
|
|
651
652
|
"referencedBy": "Referenced by",
|
|
652
653
|
"referencesDescription": "These Workflows currently use this reusable configuration.",
|
|
653
654
|
"noReferences": "No Workflows reference this instance",
|
|
@@ -1081,6 +1082,7 @@
|
|
|
1081
1082
|
"openTemporal": "Open in Temporal",
|
|
1082
1083
|
"cancel": "Cancel run",
|
|
1083
1084
|
"executionDetails": "Run information",
|
|
1085
|
+
"failedNode": "Failed node",
|
|
1084
1086
|
"cancellationRequestedBy": "Cancelled by",
|
|
1085
1087
|
"cancellationRequestedAt": "Cancelled at",
|
|
1086
1088
|
"cancellationReason": "Cancellation reason",
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json
CHANGED
|
@@ -374,5 +374,45 @@
|
|
|
374
374
|
"renameDuplicate": "名称已存在,请换一个",
|
|
375
375
|
"renameFailed": "重命名失败"
|
|
376
376
|
}
|
|
377
|
+
},
|
|
378
|
+
"transfer": {
|
|
379
|
+
"import": {
|
|
380
|
+
"title": "导入",
|
|
381
|
+
"fetchPreview": "获取并预览",
|
|
382
|
+
"confirm": "确认导入",
|
|
383
|
+
"urlHint": "粘贴源环境生成的导出 URL:",
|
|
384
|
+
"current": "当前环境",
|
|
385
|
+
"incoming": "源环境",
|
|
386
|
+
"importing": "正在导入…",
|
|
387
|
+
"pasteUrl": "请粘贴导出 URL",
|
|
388
|
+
"fetchFailed": "获取数据失败:{{status}}",
|
|
389
|
+
"expired": "导出链接已过期或无效,请在源环境重新生成。",
|
|
390
|
+
"unreachable": "无法访问源环境,请检查 URL 后重试。",
|
|
391
|
+
"success": "“{{name}}”导入成功!",
|
|
392
|
+
"failed": "导入失败",
|
|
393
|
+
"missingRefsTitle": "目标环境缺少以下引用,请先导入对应数据,否则无法确认导入:",
|
|
394
|
+
"missingRefType": {
|
|
395
|
+
"page": "页面",
|
|
396
|
+
"resource": "资源",
|
|
397
|
+
"parentPage": "父页面"
|
|
398
|
+
},
|
|
399
|
+
"conflictsTitle": "存在以下冲突,无法导入:",
|
|
400
|
+
"pageRoleHint": "页面已导入,但尚未授权给任何角色,菜单不会显示。请再导入对应角色,或在「角色管理」中为角色勾选该页面。"
|
|
401
|
+
},
|
|
402
|
+
"export": {
|
|
403
|
+
"title": "导出",
|
|
404
|
+
"copyUrl": "复制 URL",
|
|
405
|
+
"generating": "正在生成导出 URL…",
|
|
406
|
+
"urlHint": "导出 URL(30 分钟内有效),粘贴到目标环境的导入对话框:",
|
|
407
|
+
"failed": "生成导出 URL 失败",
|
|
408
|
+
"copied": "URL 已复制到剪贴板",
|
|
409
|
+
"scopeTitle": "本次导出的内容",
|
|
410
|
+
"scope": {
|
|
411
|
+
"user": "包含:账号、名称、所属角色、启用状态。不包含:API Key 等凭据(出于安全考虑不跨环境传输)。",
|
|
412
|
+
"role": "包含:角色基本信息、可访问页面列表(rolePages)、资源权限(roleResource)。注意:导入时引用的页面与资源必须已存在于目标环境,否则会被拦截。",
|
|
413
|
+
"page": "包含:该页面及其全部子页面、各页面与资源的绑定关系(pageResource)。不包含:角色对页面的授权(rolePages)—— 导入后需再导入对应角色,或在「角色管理」中授权,菜单才会显示。",
|
|
414
|
+
"resource": "包含:资源 code、名称、描述、公共资源标记。"
|
|
415
|
+
}
|
|
416
|
+
}
|
|
377
417
|
}
|
|
378
418
|
}
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json
CHANGED
|
@@ -540,6 +540,12 @@
|
|
|
540
540
|
"conditionField": "条件 {{number}} 的字段",
|
|
541
541
|
"conditionOperator": "条件 {{number}} 的判断方式",
|
|
542
542
|
"conditionValue": "条件 {{number}} 的比较值",
|
|
543
|
+
"failureCallbackTitle": "Workflow 失败通知",
|
|
544
|
+
"failureCallbackDescription": "Workflow 最终失败后,可靠通知业务系统收敛申请状态。业务接口必须按事件 ID 幂等处理。",
|
|
545
|
+
"failureCallbackEnabled": "通知业务系统",
|
|
546
|
+
"failureCallbackConnection": "业务系统连接",
|
|
547
|
+
"failureCallbackPath": "失败处理 API 路径",
|
|
548
|
+
"failureCallbackLoadFailed": "加载业务系统连接失败",
|
|
543
549
|
"selectConditionField": "选择字段",
|
|
544
550
|
"newDataField": "新数据 · {{field}}",
|
|
545
551
|
"oldDataField": "原数据 · {{field}}",
|
|
@@ -575,19 +581,13 @@
|
|
|
575
581
|
}
|
|
576
582
|
},
|
|
577
583
|
"database": {
|
|
578
|
-
"
|
|
579
|
-
"
|
|
580
|
-
"
|
|
581
|
-
"
|
|
582
|
-
"
|
|
583
|
-
"
|
|
584
|
-
"
|
|
585
|
-
"readWriteError": "只允许单条查询、新增、更新或删除语句。",
|
|
586
|
-
"parameters": "参数值",
|
|
587
|
-
"parameter": "参数",
|
|
588
|
-
"value": "值",
|
|
589
|
-
"parametersHint": "SQL 中的 $1、$2… 会依次使用这里的值。",
|
|
590
|
-
"addParameter": "添加参数值",
|
|
584
|
+
"function": "数据库 Function",
|
|
585
|
+
"functionHint": "只显示当前 GAdmin 数据库 workflow_api 中的 Function。",
|
|
586
|
+
"selectFunction": "选择 Function",
|
|
587
|
+
"loadFailed": "Function 列表加载失败。",
|
|
588
|
+
"functionMissing": "当前 Function 已不存在,请重新选择。",
|
|
589
|
+
"returnType": "返回类型:{{type}}",
|
|
590
|
+
"noArguments": "这个 Function 不需要参数。",
|
|
591
591
|
"timeout": "超时时间",
|
|
592
592
|
"seconds": "秒"
|
|
593
593
|
},
|
|
@@ -648,6 +648,7 @@
|
|
|
648
648
|
"noDescription": "暂无描述",
|
|
649
649
|
"noConfiguration": "此实例没有配置项",
|
|
650
650
|
"configurationDescription": "只读查看 {{name}} 当前保存的执行参数。",
|
|
651
|
+
"rawConfiguration": "原始节点配置",
|
|
651
652
|
"referencedBy": "引用此实例的工作流",
|
|
652
653
|
"referencesDescription": "以下 Workflow 当前正在使用这份可复用配置。",
|
|
653
654
|
"noReferences": "暂无工作流引用此实例",
|
|
@@ -1081,6 +1082,7 @@
|
|
|
1081
1082
|
"openTemporal": "在 Temporal 中查看",
|
|
1082
1083
|
"cancel": "取消运行",
|
|
1083
1084
|
"executionDetails": "运行信息",
|
|
1085
|
+
"failedNode": "失败节点",
|
|
1084
1086
|
"cancellationRequestedBy": "取消人",
|
|
1085
1087
|
"cancellationRequestedAt": "取消时间",
|
|
1086
1088
|
"cancellationReason": "取消原因",
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts
CHANGED
|
@@ -192,10 +192,11 @@ export function devShellPlugin(): Plugin {
|
|
|
192
192
|
let total = 0;
|
|
193
193
|
let tooLarge = false;
|
|
194
194
|
req.on('data', (chunk: Uint8Array) => {
|
|
195
|
+
if (tooLarge) return;
|
|
195
196
|
total += chunk.length;
|
|
196
197
|
if (total > UPLOAD_MAX_BYTES) {
|
|
197
198
|
tooLarge = true;
|
|
198
|
-
|
|
199
|
+
chunks.length = 0;
|
|
199
200
|
return;
|
|
200
201
|
}
|
|
201
202
|
chunks.push(chunk);
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx
CHANGED
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
* See: examples/ListPageExamples.tsx for all patterns
|
|
13
13
|
*/
|
|
14
14
|
import React, { useMemo } from 'react';
|
|
15
|
-
import { Table } from 'antd';
|
|
16
|
-
import {
|
|
15
|
+
import { Button, Card, Space, Table } from 'antd';
|
|
16
|
+
import { ArrowLeftOutlined } from '@ant-design/icons';
|
|
17
|
+
import { useTable, useImport } from '@refinedev/antd';
|
|
17
18
|
import {
|
|
18
19
|
HttpError,
|
|
19
20
|
IResourceComponentsProps,
|
|
@@ -41,7 +42,14 @@ import { agendaJobModel, useRelation } from 'generated/props/agendaJob/model';
|
|
|
41
42
|
import type { AgendaJob } from 'generated/types/prisma.types';
|
|
42
43
|
|
|
43
44
|
// Local imports
|
|
44
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
BulkActions,
|
|
47
|
+
ListPageHeader,
|
|
48
|
+
PageHeader,
|
|
49
|
+
RowActions,
|
|
50
|
+
SearchBar,
|
|
51
|
+
} from 'components';
|
|
52
|
+
import { PAGE_WRAPPER_STYLE, SEARCH_CARD_PROPS } from 'constants/layout';
|
|
45
53
|
import { getRowActionsColumnProps } from 'components/agentPanel';
|
|
46
54
|
import { requestHeaders } from 'helpers/login';
|
|
47
55
|
import { useBatchOperations } from 'hooks';
|
|
@@ -183,10 +191,53 @@ export const AgendaJobList: React.FC<IResourceComponentsProps> = () => {
|
|
|
183
191
|
};
|
|
184
192
|
|
|
185
193
|
return (
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
<div style={PAGE_WRAPPER_STYLE}>
|
|
195
|
+
{/* Header Card(带返回按钮,回到 Cron Jobs 页) */}
|
|
196
|
+
<PageHeader
|
|
197
|
+
title={
|
|
198
|
+
<Space size={4}>
|
|
199
|
+
<Button
|
|
200
|
+
type="text"
|
|
201
|
+
size="small"
|
|
202
|
+
icon={<ArrowLeftOutlined />}
|
|
203
|
+
onClick={() => navigate('/admin/agenda-jobs')}
|
|
204
|
+
/>
|
|
205
|
+
{t('agendaJob.titles.list', 'AgendaJobs')}
|
|
206
|
+
</Space>
|
|
207
|
+
}
|
|
208
|
+
extra={
|
|
209
|
+
<ListPageHeader
|
|
210
|
+
actions={[
|
|
211
|
+
...tableConfig.toolbar.actions,
|
|
212
|
+
...tableConfig.rowSelection.actions,
|
|
213
|
+
]}
|
|
214
|
+
importProps={importProps}
|
|
215
|
+
onExport={triggerExport}
|
|
216
|
+
exportLoading={exportLoading}
|
|
217
|
+
onRefresh={() => tableQuery.refetch()}
|
|
218
|
+
resourceName={resourceName}
|
|
219
|
+
/>
|
|
220
|
+
}
|
|
221
|
+
/>
|
|
222
|
+
|
|
223
|
+
{/* Search Card */}
|
|
224
|
+
<Card {...SEARCH_CARD_PROPS}>
|
|
225
|
+
<SearchBar
|
|
226
|
+
formProps={searchFormProps}
|
|
227
|
+
t={t}
|
|
228
|
+
resourceName={resourceName}
|
|
229
|
+
searchPlaceholder={searchPlaceholder}
|
|
230
|
+
// Render props examples (uncomment to customize):
|
|
231
|
+
// renderKeywordInput={(field, defaultInput) => <Input.Search placeholder={field.placeholder} />}
|
|
232
|
+
// renderSubmitButton={(defaultButton) => <Space>{defaultButton}<Button>Reset</Button></Space>}
|
|
233
|
+
// extraActions={<Button type="link">Advanced</Button>}
|
|
234
|
+
/>
|
|
235
|
+
</Card>
|
|
236
|
+
|
|
237
|
+
{/* Table Card */}
|
|
238
|
+
<Card className="card-table">
|
|
239
|
+
{/* BulkActions 无选中且非检查模式时返回 null,配合 .card-table > div:empty 隐藏空隙 */}
|
|
240
|
+
<div style={{ marginBottom: 16 }}>
|
|
190
241
|
<BulkActions
|
|
191
242
|
selectedRowKeys={batchOps.selectedRowKeys}
|
|
192
243
|
actions={tableConfig.rowSelection.actions}
|
|
@@ -203,65 +254,38 @@ export const AgendaJobList: React.FC<IResourceComponentsProps> = () => {
|
|
|
203
254
|
// renderSelectionCount={(count) => <Badge count={count}><Tag>Selected</Tag></Badge>}
|
|
204
255
|
// extraActions={<Button>Custom Action</Button>}
|
|
205
256
|
/>
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
...tableConfig.toolbar.actions,
|
|
211
|
-
...tableConfig.rowSelection.actions,
|
|
212
|
-
]}
|
|
213
|
-
importProps={importProps}
|
|
214
|
-
onExport={triggerExport}
|
|
215
|
-
exportLoading={exportLoading}
|
|
216
|
-
onRefresh={() => tableQuery.refetch()}
|
|
217
|
-
resourceName={resourceName}
|
|
218
|
-
/>
|
|
219
|
-
),
|
|
220
|
-
}}
|
|
221
|
-
>
|
|
222
|
-
{/* Search Bar */}
|
|
223
|
-
<SearchBar
|
|
224
|
-
formProps={searchFormProps}
|
|
225
|
-
t={t}
|
|
226
|
-
resourceName={resourceName}
|
|
227
|
-
searchPlaceholder={searchPlaceholder}
|
|
228
|
-
// Render props examples (uncomment to customize):
|
|
229
|
-
// renderKeywordInput={(field, defaultInput) => <Input.Search placeholder={field.placeholder} />}
|
|
230
|
-
// renderSubmitButton={(defaultButton) => <Space>{defaultButton}<Button>Reset</Button></Space>}
|
|
231
|
-
// extraActions={<Button type="link">Advanced</Button>}
|
|
232
|
-
/>
|
|
233
|
-
|
|
234
|
-
{/* Data Table */}
|
|
235
|
-
<Table {...tableProps} rowKey="id" rowSelection={batchOps.rowSelection}>
|
|
236
|
-
{columns.map((col) =>
|
|
237
|
-
getTableColumnV2({ col, context: columnContext }),
|
|
238
|
-
)}
|
|
239
|
-
|
|
240
|
-
{/* Actions Column */}
|
|
241
|
-
<Table.Column<AgendaJob>
|
|
242
|
-
title={t('table.actions')}
|
|
243
|
-
dataIndex="actions"
|
|
244
|
-
{...getRowActionsColumnProps(resourceName)}
|
|
245
|
-
render={(_, record) => (
|
|
246
|
-
<RowActions
|
|
247
|
-
record={record}
|
|
248
|
-
actions={tableConfig.rowActions.actions}
|
|
249
|
-
visibleNum={tableConfig.rowActions.visibleNum}
|
|
250
|
-
onUpdate={batchOps.updateOne}
|
|
251
|
-
updateLoading={batchOps.updateManyIsLoading}
|
|
252
|
-
t={t}
|
|
253
|
-
resourceName={resourceName}
|
|
254
|
-
// Render props examples (uncomment to customize):
|
|
255
|
-
// showClone={false}
|
|
256
|
-
// showDelete={false}
|
|
257
|
-
// renderEditButton={(id) => <Button type="link" size="small">Quick Edit</Button>}
|
|
258
|
-
// renderDeleteButton={(id) => <Popconfirm title="Sure?"><Button danger size="small">Remove</Button></Popconfirm>}
|
|
259
|
-
// extraPrimaryActions={<Button type="text" size="small">Quick View</Button>}
|
|
260
|
-
/>
|
|
257
|
+
</div>
|
|
258
|
+
<Table {...tableProps} rowKey="id" rowSelection={batchOps.rowSelection}>
|
|
259
|
+
{columns.map((col) =>
|
|
260
|
+
getTableColumnV2({ col, context: columnContext }),
|
|
261
261
|
)}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
262
|
+
|
|
263
|
+
{/* Actions Column */}
|
|
264
|
+
<Table.Column<AgendaJob>
|
|
265
|
+
title={t('table.actions')}
|
|
266
|
+
dataIndex="actions"
|
|
267
|
+
{...getRowActionsColumnProps(resourceName)}
|
|
268
|
+
render={(_, record) => (
|
|
269
|
+
<RowActions
|
|
270
|
+
record={record}
|
|
271
|
+
actions={tableConfig.rowActions.actions}
|
|
272
|
+
visibleNum={tableConfig.rowActions.visibleNum}
|
|
273
|
+
onUpdate={batchOps.updateOne}
|
|
274
|
+
updateLoading={batchOps.updateManyIsLoading}
|
|
275
|
+
t={t}
|
|
276
|
+
resourceName={resourceName}
|
|
277
|
+
// Render props examples (uncomment to customize):
|
|
278
|
+
// showClone={false}
|
|
279
|
+
// showDelete={false}
|
|
280
|
+
// renderEditButton={(id) => <Button type="link" size="small">Quick Edit</Button>}
|
|
281
|
+
// renderDeleteButton={(id) => <Popconfirm title="Sure?"><Button danger size="small">Remove</Button></Popconfirm>}
|
|
282
|
+
// extraPrimaryActions={<Button type="text" size="small">Quick View</Button>}
|
|
283
|
+
/>
|
|
284
|
+
)}
|
|
285
|
+
/>
|
|
286
|
+
</Table>
|
|
287
|
+
</Card>
|
|
288
|
+
</div>
|
|
265
289
|
);
|
|
266
290
|
};
|
|
267
291
|
|
|
@@ -6,7 +6,6 @@ import React, {
|
|
|
6
6
|
useState,
|
|
7
7
|
} from 'react';
|
|
8
8
|
import { DeleteButton, EditButton, useTable } from '@refinedev/antd';
|
|
9
|
-
import { useGetIdentity } from '@refinedev/core';
|
|
10
9
|
import {
|
|
11
10
|
Table,
|
|
12
11
|
Button,
|
|
@@ -28,7 +27,8 @@ import {
|
|
|
28
27
|
PlusOutlined,
|
|
29
28
|
EyeOutlined,
|
|
30
29
|
TeamOutlined,
|
|
31
|
-
|
|
30
|
+
ExportOutlined,
|
|
31
|
+
ImportOutlined,
|
|
32
32
|
} from '@ant-design/icons';
|
|
33
33
|
import {
|
|
34
34
|
DndContext,
|
|
@@ -63,7 +63,8 @@ import type {
|
|
|
63
63
|
} from './types';
|
|
64
64
|
import { usePageManagement } from './hooks/usePageManagement';
|
|
65
65
|
import { useTranslation } from 'react-i18next';
|
|
66
|
-
import {
|
|
66
|
+
import { TransferExportModal } from '@/components/TransferExportModal';
|
|
67
|
+
import { TransferImportModal } from '@/components/TransferImportModal';
|
|
67
68
|
import { PageHeader } from 'components';
|
|
68
69
|
import { PAGE_WRAPPER_STYLE } from 'constants/layout';
|
|
69
70
|
|
|
@@ -176,8 +177,7 @@ const DraggableRow: React.FC<DraggableRowProps> = ({ children, ...props }) => {
|
|
|
176
177
|
};
|
|
177
178
|
|
|
178
179
|
export const PageManagementListPage: React.FC = () => {
|
|
179
|
-
const { i18n } = useTranslation();
|
|
180
|
-
const { data: identity } = useGetIdentity<any>();
|
|
180
|
+
const { t, i18n } = useTranslation();
|
|
181
181
|
const { tableProps } = useTable({
|
|
182
182
|
resource: 'page',
|
|
183
183
|
pagination: {
|
|
@@ -382,109 +382,8 @@ export const PageManagementListPage: React.FC = () => {
|
|
|
382
382
|
const [activeTab, setActiveTab] = useState<string>('regular');
|
|
383
383
|
|
|
384
384
|
// State for SQL modal
|
|
385
|
-
const [
|
|
386
|
-
|
|
387
|
-
title: string;
|
|
388
|
-
sql: string;
|
|
389
|
-
}>({ open: false, title: '', sql: '' });
|
|
390
|
-
|
|
391
|
-
const handleShowSql = useCallback(
|
|
392
|
-
(record: any, hasChildren: boolean) => {
|
|
393
|
-
const pagesArray: any[] = Array.isArray(pageListData?.data)
|
|
394
|
-
? pageListData.data
|
|
395
|
-
: [];
|
|
396
|
-
|
|
397
|
-
// Build pageResources for the given page
|
|
398
|
-
const buildPageResources = (pageId: number) => {
|
|
399
|
-
const associationsArray: any[] = Array.isArray(
|
|
400
|
-
pageResourceAssociationsData?.data,
|
|
401
|
-
)
|
|
402
|
-
? pageResourceAssociationsData.data
|
|
403
|
-
: [];
|
|
404
|
-
return associationsArray
|
|
405
|
-
.filter(
|
|
406
|
-
(assoc: any) => safelyConvertToNumber(assoc?.pageId) === pageId,
|
|
407
|
-
)
|
|
408
|
-
.map((assoc: any) => {
|
|
409
|
-
const resourceId = safelyConvertToNumber(assoc?.resourceId);
|
|
410
|
-
// Prefer nested resource object, then fall back to the id-keyed lookup map (which includes code).
|
|
411
|
-
// The final fallback `String(resourceId)` should never be reached if availableResourcesData is loaded.
|
|
412
|
-
const resourceRecord =
|
|
413
|
-
assoc?.resource ??
|
|
414
|
-
(resourceId !== null ? resourceLookupByIdMap[resourceId] : null);
|
|
415
|
-
const resourceCode =
|
|
416
|
-
resourceRecord?.code ??
|
|
417
|
-
(resourceId !== null ? String(resourceId) : 'unknown');
|
|
418
|
-
const resourceName =
|
|
419
|
-
resourceRecord?.name ||
|
|
420
|
-
resourceRecord?.code ||
|
|
421
|
-
`Resource ${resourceId}`;
|
|
422
|
-
const actions = extractPermissionActionsFromAssociation(
|
|
423
|
-
assoc,
|
|
424
|
-
resourceRecord,
|
|
425
|
-
);
|
|
426
|
-
return { resourceCode, resourceName, actions };
|
|
427
|
-
});
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
const pageResources = buildPageResources(record.id);
|
|
431
|
-
|
|
432
|
-
// Collect child pages if this is a parent
|
|
433
|
-
const children: Array<{
|
|
434
|
-
page: any;
|
|
435
|
-
pageResources: Array<{
|
|
436
|
-
resourceCode: string;
|
|
437
|
-
resourceName: string;
|
|
438
|
-
actions: string[];
|
|
439
|
-
}>;
|
|
440
|
-
}> = [];
|
|
441
|
-
if (hasChildren) {
|
|
442
|
-
const childPages = pagesArray.filter(
|
|
443
|
-
(p: any) =>
|
|
444
|
-
safelyConvertToNumber(p?.parentId ?? p?.parent_id) === record.id,
|
|
445
|
-
);
|
|
446
|
-
for (const child of childPages) {
|
|
447
|
-
const childId = safelyConvertToNumber(child?.id);
|
|
448
|
-
if (childId === null) continue;
|
|
449
|
-
children.push({
|
|
450
|
-
page: child,
|
|
451
|
-
pageResources: buildPageResources(childId),
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// Resolve parent's code from the in-memory page list so the SQL uses a
|
|
457
|
-
// portable subquery (SELECT id … WHERE code = '…') instead of a raw
|
|
458
|
-
// numeric parentId that differs between environments.
|
|
459
|
-
const parentId = safelyConvertToNumber(
|
|
460
|
-
record?.parentId ?? record?.parent_id,
|
|
461
|
-
);
|
|
462
|
-
const parentPage =
|
|
463
|
-
parentId !== null
|
|
464
|
-
? pagesArray.find(
|
|
465
|
-
(p: any) => safelyConvertToNumber(p?.id) === parentId,
|
|
466
|
-
)
|
|
467
|
-
: null;
|
|
468
|
-
const recordWithParentCode = {
|
|
469
|
-
...record,
|
|
470
|
-
parentCode: parentPage?.code ?? null,
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
const sql = generatePageSql(
|
|
474
|
-
recordWithParentCode,
|
|
475
|
-
pageResources,
|
|
476
|
-
children,
|
|
477
|
-
{ authorId: identity?.userid, authorName: identity?.username },
|
|
478
|
-
);
|
|
479
|
-
setSqlModal({ open: true, title: `SQL — Page: ${record.name}`, sql });
|
|
480
|
-
},
|
|
481
|
-
[
|
|
482
|
-
pageListData,
|
|
483
|
-
pageResourceAssociationsData,
|
|
484
|
-
resourceLookupByIdMap,
|
|
485
|
-
identity,
|
|
486
|
-
],
|
|
487
|
-
);
|
|
385
|
+
const [exportEndpoint, setExportEndpoint] = useState<string | null>(null);
|
|
386
|
+
const [importOpen, setImportOpen] = useState(false);
|
|
488
387
|
|
|
489
388
|
// Ref for expand button click/double-click disambiguation
|
|
490
389
|
const expandClickTimer = useRef<number | null>(null);
|
|
@@ -973,12 +872,16 @@ export const PageManagementListPage: React.FC = () => {
|
|
|
973
872
|
setActiveModalState({ modalType: 'edit', targetPageId: record.id })
|
|
974
873
|
}
|
|
975
874
|
/>
|
|
976
|
-
<Tooltip title="
|
|
875
|
+
<Tooltip title="Export">
|
|
977
876
|
<Button
|
|
978
877
|
type="default"
|
|
979
878
|
size="small"
|
|
980
|
-
icon={<
|
|
981
|
-
onClick={() =>
|
|
879
|
+
icon={<ExportOutlined />}
|
|
880
|
+
onClick={() =>
|
|
881
|
+
setExportEndpoint(
|
|
882
|
+
`page/${encodeURIComponent(record.code)}/export-token`,
|
|
883
|
+
)
|
|
884
|
+
}
|
|
982
885
|
/>
|
|
983
886
|
</Tooltip>
|
|
984
887
|
{/* Only show delete button for leaf nodes (pages without children) */}
|
|
@@ -1186,17 +1089,25 @@ export const PageManagementListPage: React.FC = () => {
|
|
|
1186
1089
|
<PageHeader
|
|
1187
1090
|
title="Page mgnts"
|
|
1188
1091
|
extra={
|
|
1189
|
-
<
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1092
|
+
<Space>
|
|
1093
|
+
<Button
|
|
1094
|
+
icon={<ImportOutlined />}
|
|
1095
|
+
onClick={() => setImportOpen(true)}
|
|
1096
|
+
>
|
|
1097
|
+
Import
|
|
1098
|
+
</Button>
|
|
1099
|
+
<Button
|
|
1100
|
+
type="primary"
|
|
1101
|
+
onClick={() =>
|
|
1102
|
+
setActiveModalState({
|
|
1103
|
+
modalType: 'create',
|
|
1104
|
+
targetPageId: null,
|
|
1105
|
+
})
|
|
1106
|
+
}
|
|
1107
|
+
>
|
|
1108
|
+
Create Page
|
|
1109
|
+
</Button>
|
|
1110
|
+
</Space>
|
|
1200
1111
|
}
|
|
1201
1112
|
/>
|
|
1202
1113
|
|
|
@@ -1267,11 +1178,24 @@ export const PageManagementListPage: React.FC = () => {
|
|
|
1267
1178
|
/>
|
|
1268
1179
|
)}
|
|
1269
1180
|
|
|
1270
|
-
<
|
|
1271
|
-
open={
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1181
|
+
<TransferExportModal
|
|
1182
|
+
open={!!exportEndpoint}
|
|
1183
|
+
exportTokenEndpoint={exportEndpoint}
|
|
1184
|
+
entity="page"
|
|
1185
|
+
onClose={() => setExportEndpoint(null)}
|
|
1186
|
+
/>
|
|
1187
|
+
<TransferImportModal
|
|
1188
|
+
open={importOpen}
|
|
1189
|
+
onClose={() => setImportOpen(false)}
|
|
1190
|
+
onSuccess={() => {
|
|
1191
|
+
refetchPageList(pageListRequestQuery ?? {});
|
|
1192
|
+
refetchPageResourceAssociations(
|
|
1193
|
+
pageResourceAssociationRequestQuery ?? {},
|
|
1194
|
+
);
|
|
1195
|
+
}}
|
|
1196
|
+
previewEndpoint="page/import-preview"
|
|
1197
|
+
confirmEndpoint="page/import-confirm"
|
|
1198
|
+
successHint={t('transfer.import.pageRoleHint')}
|
|
1275
1199
|
/>
|
|
1276
1200
|
</div>
|
|
1277
1201
|
);
|