@gadmin2n/schematics 0.0.142 → 0.0.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +5 -23
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts +4 -2
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/page-manage.ts +36 -1
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/agenda.seed.ts +14 -14
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/bootstrap.ts +18 -13
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/canvas.seed.ts +14 -14
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +1 -1
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +67 -404
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow.seed.ts +16 -40
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +12 -124
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.module.ts +3 -0
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/config/index.ts +0 -21
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.controller.ts +3 -10
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/codeRuntime.module.ts +1 -2
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-callback.controller.spec.ts +48 -0
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-callback.controller.ts +96 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.spec.ts +1 -59
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.ts +8 -43
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.dto.ts +0 -23
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.service.ts +2 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-wait.handler.ts +2 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/externalInteraction.module.ts +7 -3
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.controller.ts +2 -2
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.service.spec.ts +18 -123
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.service.ts +4 -0
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.controller.ts +3 -10
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/httpRequest.module.ts +1 -2
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.controller.ts +0 -10
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.dto.ts +12 -4
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.errors.ts +1 -1
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.external-decision.spec.ts +42 -209
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.ts +108 -225
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/humanApproval.module.ts +0 -2
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.ts +27 -22
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.dto.ts +9 -1
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/runtime-token.guard.spec.ts +30 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/runtime-token.guard.ts +8 -15
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +0 -2
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/runtime-connectivity-probe.service.spec.ts +14 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/runtime-connectivity-probe.service.ts +37 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.spec.ts +41 -0
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.ts +53 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.module.ts +7 -2
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/workflow-runtime-health.controller.ts +21 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.spec.ts +2 -2
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.spec.ts +16 -88
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.ts +23 -59
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.spec.ts +125 -39
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.ts +95 -28
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-handle-validator.ts +0 -20
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.spec.ts +23 -26
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.ts +6 -52
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +2 -2
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +24 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +26 -21
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.spec.ts +0 -1
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.ts +0 -1
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowRuntimeConfig/workflow-runtime-config.service.spec.ts +32 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowRuntimeConfig/workflow-runtime-config.service.ts +41 -0
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowRuntimeConfig/workflowRuntimeConfig.module.ts +10 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/server/tsconfig.build.json +10 -1
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +16 -12
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/PageHeader.tsx +1 -1
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/inspectorActions.ts +19 -19
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/color-mode/index.tsx +1 -1
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +15 -11
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +0 -6
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddDataModal.tsx +3 -3
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddPageModal.tsx +1 -1
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DeleteDataConfirm.tsx +1 -1
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/EditDataModal.tsx +1 -1
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +1 -0
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/workflow.json +85 -95
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json +85 -95
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +2 -2
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +21 -2
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/list.tsx +21 -2
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/inbox.tsx +14 -66
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +4 -4
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +3 -3
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +3 -3
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.test.tsx +29 -0
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +4 -2
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/EnhancedFlowRenderer.tsx +4 -6
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.test.tsx +3 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.tsx +3 -1
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +4 -6
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NewNodeDefaults.test.tsx +23 -92
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeOutputSummary.tsx +200 -0
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.test.tsx +61 -136
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +96 -195
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeTypeBadge.tsx +36 -0
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +5 -10
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +47 -22
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/create.tsx +7 -5
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/edit.tsx +8 -6
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-config.css +35 -0
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/default-widgets.tsx +1 -6
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApproverSourceEditor.tsx +1 -4
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.tsx +1 -1
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalRequestConfigEditor.tsx +1 -1
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalWaitConfigEditor.tsx +82 -259
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HttpRequestConfigEditor.tsx +1 -2
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.test.tsx +7 -6
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.tsx +77 -71
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.test.tsx +10 -57
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.tsx +8 -273
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.test.tsx +54 -0
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +110 -20
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/newNodeConfig.ts +4 -34
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.test.ts +3 -10
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.ts +2 -37
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +26 -2
  114. package/package.json +1 -1
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.controller.ts +0 -89
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.dto.ts +0 -68
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.service.spec.ts +0 -177
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.service.ts +0 -283
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approvalChannel.module.ts +0 -10
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/ApprovalChannelModal.test.tsx +0 -84
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/ApprovalChannelModal.tsx +0 -141
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/approval-channel.types.ts +0 -16
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/index.tsx +0 -210
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRequestTriggerConfigEditor.tsx +0 -39
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubmitApprovalResultConfigEditor.tsx +0 -104
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubmitExternalResultConfigEditor.tsx +0 -98
  127. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/AssignRolesModal.tsx +0 -0
  128. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/CreatePageModal.tsx +0 -0
  129. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/EditPageModal.tsx +0 -0
  130. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/PageDetailDrawer.tsx +0 -0
  131. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/PageFormModal.tsx +0 -0
  132. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/{Components → components}/CreateModal.tsx +0 -0
  133. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/{Components → components}/EditModal.tsx +0 -0
  134. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/{Components → components}/ResourceDetailDrawer.tsx +0 -0
  135. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/{Components → components}/modal.tsx +0 -0
  136. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/{Components → components}/CreateModal.tsx +0 -0
  137. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/{Components → components}/EditModal.tsx +0 -0
  138. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/{Components → components}/RoleDetailDrawer.tsx +0 -0
  139. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/{Components → components}/modal.tsx +0 -0
@@ -11,7 +11,10 @@ import { HumanApprovalService } from '../humanApproval/human-approval.service';
11
11
  import { validateDslGraph } from './dsl-validate.util';
12
12
  import { TemporalService } from './temporal.service';
13
13
  import { verifyWebhookSignature } from './webhook-signature.util';
14
- import { describeCallableWorkflow } from './workflow-callable';
14
+ import {
15
+ describeCallableWorkflow,
16
+ validateCallableWorkflow,
17
+ } from './workflow-callable';
15
18
  import { WorkflowCompilerService } from './workflow-compiler.service';
16
19
  import { DraftWorkflowDsl } from './workflow-compiler.types';
17
20
  import { validateWorkflowDataEdges } from './workflow-data-edge.util';
@@ -32,6 +35,23 @@ export class WorkflowService {
32
35
  private workflowCompiler: WorkflowCompilerService,
33
36
  ) {}
34
37
 
38
+ private validateCallableDraft(dsl: any): void {
39
+ if (
40
+ !Array.isArray(dsl?.nodes) ||
41
+ !dsl.nodes.some((node: any) => node?.type === 'callable_trigger')
42
+ )
43
+ return;
44
+ try {
45
+ validateCallableWorkflow(dsl);
46
+ } catch (error) {
47
+ throw new BadRequestException({
48
+ code: 'CALLABLE_WORKFLOW_INVALID',
49
+ message:
50
+ error instanceof Error ? error.message : '可调用 Workflow 配置无效',
51
+ });
52
+ }
53
+ }
54
+
35
55
  /**
36
56
  * Find the cron_trigger node config in a DSL, if any.
37
57
  * Returns null when no cron_trigger node or when its `cron` field is missing.
@@ -170,7 +190,7 @@ export class WorkflowService {
170
190
  return { items: enrichedItems, total };
171
191
  }
172
192
 
173
- async findCallableWorkflows(resultType = 'APPROVAL_SUBJECTS') {
193
+ async findCallableWorkflows() {
174
194
  const workflows = await this.prisma.workflow.findMany({
175
195
  where: { status: 'PUBLISHED', isEnabled: true },
176
196
  orderBy: { name: 'asc' },
@@ -185,19 +205,13 @@ export class WorkflowService {
185
205
  return workflows.flatMap((workflow) => {
186
206
  try {
187
207
  const descriptor = describeCallableWorkflow(workflow.versions[0]?.dsl);
188
- if (
189
- !descriptor ||
190
- descriptor.mode !== 'RETURN' ||
191
- descriptor.resultType !== resultType
192
- )
193
- return [];
208
+ if (!descriptor) return [];
194
209
  return [
195
210
  {
196
211
  id: String(workflow.id),
197
212
  name: workflow.name,
198
213
  description: workflow.description,
199
214
  inputParameters: descriptor.inputParameters,
200
- resultType: descriptor.resultType,
201
215
  },
202
216
  ];
203
217
  } catch {
@@ -218,20 +232,9 @@ export class WorkflowService {
218
232
  },
219
233
  },
220
234
  });
221
- const dispatchWorkflows: Array<{ id: string; name: string }> = [];
222
235
  const callbackWorkflows: Array<{ id: string; name: string }> = [];
223
236
  for (const workflow of workflows) {
224
237
  const dsl = workflow.versions[0]?.dsl;
225
- try {
226
- if (describeCallableWorkflow(dsl)?.mode === 'ONE_WAY') {
227
- dispatchWorkflows.push({
228
- id: String(workflow.id),
229
- name: workflow.name,
230
- });
231
- }
232
- } catch {
233
- // Invalid callable Workflows are not selectable.
234
- }
235
238
  const nodes =
236
239
  dsl &&
237
240
  typeof dsl === 'object' &&
@@ -248,7 +251,7 @@ export class WorkflowService {
248
251
  });
249
252
  }
250
253
  }
251
- return { dispatchWorkflows, callbackWorkflows };
254
+ return { dispatchWorkflows: [], callbackWorkflows };
252
255
  }
253
256
 
254
257
  async findOne(id: bigint) {
@@ -269,6 +272,7 @@ export class WorkflowService {
269
272
  data: { name: string; description?: string; dsl?: any },
270
273
  creator: string,
271
274
  ) {
275
+ this.validateCallableDraft(data.dsl);
272
276
  const workflow = await this.prisma.workflow.create({
273
277
  data: {
274
278
  name: data.name,
@@ -299,6 +303,7 @@ export class WorkflowService {
299
303
  },
300
304
  });
301
305
  if (!workflow) throw new NotFoundException('Workflow not found');
306
+ this.validateCallableDraft(dsl);
302
307
  const latestPublishedDsl = workflow.versions?.[0]?.dsl;
303
308
  const status =
304
309
  latestPublishedDsl && areWorkflowDslSourcesEqual(dsl, latestPublishedDsl)
@@ -8,7 +8,6 @@ describe('WidgetCatalogService', () => {
8
8
  catalog.assertUiSchemaSupported({
9
9
  webhook: { widget: 'external-request-config' },
10
10
  approvalResult: { widget: 'submit-approval-result-config' },
11
- externalResult: { widget: 'submit-external-result-config' },
12
11
  externalWait: { widget: 'external-wait-config' },
13
12
  callableInputs: { widget: 'callable-input-parameters' },
14
13
  approvalRequest: { widget: 'approval-request-trigger-config' },
@@ -16,7 +16,6 @@ const WORKFLOW_WIDGETS = [
16
16
  'return-result-config',
17
17
  'external-request-config',
18
18
  'submit-approval-result-config',
19
- 'submit-external-result-config',
20
19
  'external-wait-config',
21
20
  ] as const;
22
21
 
@@ -0,0 +1,32 @@
1
+ import { WorkflowRuntimeConfigService } from './workflow-runtime-config.service';
2
+
3
+ describe('WorkflowRuntimeConfigService', () => {
4
+ it('uses the service registration as the runtime source of truth', async () => {
5
+ const prisma = {
6
+ temporalTenantConfig: {
7
+ findFirst: jest.fn().mockResolvedValue({
8
+ namespace: 'gadmin-test',
9
+ runtimeToken: 'registered-runtime-token',
10
+ }),
11
+ },
12
+ };
13
+ const service = new WorkflowRuntimeConfigService(prisma as any);
14
+
15
+ await expect(service.getRequired()).resolves.toEqual({
16
+ namespace: 'gadmin-test',
17
+ runtimeToken: 'registered-runtime-token',
18
+ });
19
+ });
20
+
21
+ it('keeps runtime disabled until a service is registered', async () => {
22
+ const service = new WorkflowRuntimeConfigService({
23
+ temporalTenantConfig: {
24
+ findFirst: jest.fn().mockResolvedValue(null),
25
+ },
26
+ } as any);
27
+
28
+ await expect(service.getRequired()).rejects.toMatchObject({
29
+ response: { code: 'WORKFLOW_RUNTIME_NOT_REGISTERED' },
30
+ });
31
+ });
32
+ });
@@ -0,0 +1,41 @@
1
+ import {
2
+ BadRequestException,
3
+ Injectable,
4
+ ServiceUnavailableException,
5
+ } from '@nestjs/common';
6
+ import { PrismaService } from 'nestjs-prisma';
7
+
8
+ @Injectable()
9
+ export class WorkflowRuntimeConfigService {
10
+ constructor(private readonly prisma: PrismaService) {}
11
+
12
+ async getRequired() {
13
+ const config = await this.prisma.temporalTenantConfig.findFirst({
14
+ orderBy: { id: 'asc' },
15
+ select: {
16
+ namespace: true,
17
+ runtimeToken: true,
18
+ },
19
+ });
20
+ if (!config?.runtimeToken)
21
+ throw new ServiceUnavailableException({
22
+ code: 'WORKFLOW_RUNTIME_NOT_REGISTERED',
23
+ message: '请先在服务注册页面完成 Temporal 注册',
24
+ retryable: false,
25
+ });
26
+ return {
27
+ namespace: config.namespace,
28
+ runtimeToken: config.runtimeToken,
29
+ };
30
+ }
31
+
32
+ async assertTenant(tenantNamespace: string): Promise<void> {
33
+ const config = await this.getRequired();
34
+ if (tenantNamespace !== config.namespace)
35
+ throw new BadRequestException({
36
+ code: 'WORKFLOW_RUNTIME_TENANT_MISMATCH',
37
+ message: 'Runtime tenant does not match this application',
38
+ retryable: false,
39
+ });
40
+ }
41
+ }
@@ -0,0 +1,10 @@
1
+ import { Global, Module } from '@nestjs/common';
2
+ import { RuntimeTokenGuard } from '../humanApproval/runtime/runtime-token.guard';
3
+ import { WorkflowRuntimeConfigService } from './workflow-runtime-config.service';
4
+
5
+ @Global()
6
+ @Module({
7
+ providers: [WorkflowRuntimeConfigService, RuntimeTokenGuard],
8
+ exports: [WorkflowRuntimeConfigService, RuntimeTokenGuard],
9
+ })
10
+ export class WorkflowRuntimeConfigModule {}
@@ -1,4 +1,13 @@
1
1
  {
2
2
  "extends": "./tsconfig.json",
3
- "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
3
+ "exclude": [
4
+ "node_modules",
5
+ "test",
6
+ "dist",
7
+ "**/*spec.ts",
8
+ "src/generated/**/*.controller.ts",
9
+ "src/generated/**/*.module.ts",
10
+ "src/generated/**/*.service.ts",
11
+ "src/generated/**/*.form.validator.ts"
12
+ ]
4
13
  }
@@ -15,23 +15,29 @@ temporal,现在已迁走",避免新同事/AI 找不到线索反复重建。
15
15
 
16
16
  1. 确认共享 temporal 已在本机或内网跑起来(本机方案见
17
17
  `common/gadmin2/temporal-shared/README.md`)
18
- 2. `cp server/.env server/.env.local` 并填入 6 个变量(下方清单)
19
- 3. 首次注册本项目为共享 temporal 的租户:`bash dev/register-tenant.sh`
20
- 4. `docker compose up -d` — 4 个 service 起来(postgres / server-init / server / web)
18
+ 2. `cp server/.env server/.env.local`,配置共享 Temporal 连接和
19
+ `INTEGRATION_SECRET_KEY`(下方清单)
20
+ 3. `docker compose up -d` — 4 个 service 起来(postgres / server-init / server / web)
21
+ 4. 在 Workflow 的“服务注册”页面注册本项目
21
22
  5. Web UI 触发 workflow → 到共享 temporal UI(默认 http://localhost:8080)查看
22
23
 
23
- ## `.env.local` 需要填的 6 个变量
24
+ ## `.env.local` 中保留的 Workflow 变量
24
25
 
25
26
  | 变量 | 用途 | 示例 |
26
27
  |------|------|------|
27
28
  | `TEMPORAL_ADDRESS` | 共享 temporal 的 gRPC 地址 | `localhost:7233` |
28
29
  | `TEMPORAL_NAMESPACE` | 本项目在共享 temporal 里的 namespace | `gadmin-test` |
29
- | `SHARED_TEMPORAL_ADMIN_URL` | 共享 temporal admin API | `http://localhost:8081` |
30
- | `SHARED_TEMPORAL_ADMIN_TOKEN` | admin API token | 问运维;32 hex |
31
- | `GADMIN_TENANT_NAMESPACE` | admin API 里 tenant 的 namespace(= `TEMPORAL_NAMESPACE`) | `gadmin-test` |
32
- | `SHARED_TENANT_DB_URL` | 共享 worker 视角看到的本项目 db url | `postgresql://kavenma:kavenma@host.containers.internal:5432/gadmin_demo` |
30
+ | `INTEGRATION_SECRET_KEY` | 加密集成凭据并签发连通性探针;32-byte base64 或 64 位十六进制 | 随机生成并妥善保存 |
33
31
 
34
- **为什么 `SHARED_TENANT_DB_URL` 与 `server/.env` 里的 `DATABASE_URL` 不同**:本项目内部
32
+ 以下配置改在“服务注册”页面填写,不再使用 Server 环境变量:共享 Temporal
33
+ 管理地址及 Token、租户 Namespace、Worker 访问数据库的 URL、Runtime API 地址、
34
+ Runtime Token。保存注册后 Workflow Runtime 自动启用。
35
+
36
+ “接收外部调用”和 MyOA 审批回调共用 Workflow 公共地址生成器。默认自动识别
37
+ 服务器可访问的网卡 IP;使用反向代理或固定域名时,可通过可选的
38
+ `WORKFLOW_PUBLIC_BASE_URL` 覆盖。
39
+
40
+ **为什么服务注册里的数据库 URL 与 `server/.env` 里的 `DATABASE_URL` 不同**:本项目内部
35
41
  服务(server / server-init)走 docker network 用 `postgresql://.../postgres:5432/gadmin_demo`;
36
42
  共享 worker 在独立 podman/docker 网络里,必须走 host 网络才能到达本项目的 PG,因此
37
43
  用 `host.containers.internal:5432` 或 `host.docker.internal:5432`。见设计文档 §2.2。
@@ -40,9 +46,7 @@ temporal,现在已迁走",避免新同事/AI 找不到线索反复重建。
40
46
 
41
47
  - 共享 temporal server 健康:`curl -s $TEMPORAL_ADDRESS/health` (7233 是 gRPC,不能直接
42
48
  curl;用 `docker compose ps` 看 `shared-temporal-server` 状态 healthy 更方便)
43
- - 共享 admin API:`curl -s $SHARED_TEMPORAL_ADMIN_URL/health/live` → `{"status":"ok"}`
44
- - 本项目租户已注册:`curl -sH "X-Admin-Token: $SHARED_TEMPORAL_ADMIN_TOKEN" \
45
- $SHARED_TEMPORAL_ADMIN_URL/admin/tenants | grep gadmin-test`
49
+ - 共享 admin API、数据库及 Runtime API:在“服务注册”抽屉中点击“测试连接”
46
50
 
47
51
  ## 回滚
48
52
 
@@ -13,7 +13,7 @@ interface PageHeaderProps {
13
13
 
14
14
  /**
15
15
  * 自定义页面统一的头部卡片:标题 + 副标题 + 右侧操作按钮。
16
- * 样式规范见 page-create-new skill(Header Card 压扁、Title level 4、副标题 12px)。
16
+ * 样式规范见 page-management skill(Header Card 压扁、Title level 4、副标题 12px)。
17
17
  */
18
18
  export const PageHeader: React.FC<PageHeaderProps> = ({
19
19
  title,
@@ -226,7 +226,7 @@ export function getInspectorActions(
226
226
  case 'list-column':
227
227
  return [
228
228
  {
229
- label: '不显示(仅页面)',
229
+ label: '不在页面中显示',
230
230
  skill: 'ui-config-update',
231
231
  promptTemplate: `隐藏 ${col(r, f)}(仅页面不显示)`,
232
232
  requiresConfirm: true,
@@ -323,7 +323,7 @@ export function getInspectorActions(
323
323
  '\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
324
324
  },
325
325
  {
326
- label: '自定义',
326
+ label: '自定义逻辑',
327
327
  skill: null,
328
328
  requiresInput: true,
329
329
  promptTemplate: `对 ${r} 列表中的 "${f}" 列进行修改`,
@@ -337,7 +337,7 @@ export function getInspectorActions(
337
337
  case 'form-field':
338
338
  return [
339
339
  {
340
- label: '不显示',
340
+ label: '不在页面中显示',
341
341
  skill: 'ui-config-update',
342
342
  promptTemplate: `隐藏 ${formF(r, f)}(仅页面不显示)`,
343
343
  requiresConfirm: true,
@@ -345,8 +345,8 @@ export function getInspectorActions(
345
345
  },
346
346
  {
347
347
  label: '彻底删除字段',
348
- skill: 'prisma-schema-update',
349
- promptTemplate: `彻底删除 ${formF(r, f)}:先用 prisma-schema-update 从数据库删除字段,再用 ui-config-update 从页面配置中移除该字段`,
348
+ skill: 'prisma-schema-management',
349
+ promptTemplate: `彻底删除 ${formF(r, f)}:先用 prisma-schema-management 从数据库删除字段,再用 ui-config-update 从页面配置中移除该字段`,
350
350
  requiresConfirm: true,
351
351
  confirmDescription: `将从数据库和表单页面中彻底删除 "${f}" 字段。此操作不可逆,字段的历史数据也将全部清除。`,
352
352
  },
@@ -406,14 +406,14 @@ export function getInspectorActions(
406
406
  },
407
407
  {
408
408
  label: '改为自动补全输入方式',
409
- skill: 'prisma-schema-update',
409
+ skill: 'prisma-schema-management',
410
410
  promptTemplate: `将 ${formF(r, f)} 改为 @FormItem(AutoComplete),建议值从后端已有数据动态加载`,
411
411
  requiresConfirm: true,
412
412
  confirmDescription: `将把 ${formF(r, f)} 的表单控件改为自动补全输入框(AutoComplete)。用户可以自由输入任意新值,同时系统会自动将该字段的历史值作为输入建议。`,
413
413
  },
414
414
  {
415
415
  label: '修改字段类型',
416
- skill: 'prisma-schema-update',
416
+ skill: 'prisma-schema-management',
417
417
  promptTemplate: `修改 ${formF(r, f)} 的表单控件类型(@FormItem 注解)`,
418
418
  promptPrefix: '修改为:',
419
419
  requiresInput: true,
@@ -457,7 +457,7 @@ export function getInspectorActions(
457
457
  '\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
458
458
  },
459
459
  {
460
- label: '自定义',
460
+ label: '自定义逻辑',
461
461
  skill: null,
462
462
  requiresInput: true,
463
463
  promptTemplate: `对 ${r} 表单中的 "${f}" 字段进行修改`,
@@ -471,7 +471,7 @@ export function getInspectorActions(
471
471
  case 'show-field':
472
472
  return [
473
473
  {
474
- label: '不显示',
474
+ label: '不在页面中显示',
475
475
  skill: 'ui-config-update',
476
476
  promptTemplate: `隐藏 ${showF(r, f)}`,
477
477
  requiresConfirm: true,
@@ -512,7 +512,7 @@ export function getInspectorActions(
512
512
  fieldSubMenu: 'add-before',
513
513
  },
514
514
  {
515
- label: '自定义',
515
+ label: '自定义逻辑',
516
516
  skill: null,
517
517
  requiresInput: true,
518
518
  promptTemplate: `对 ${r} 详情页的 "${f}" 字段进行修改`,
@@ -600,7 +600,7 @@ export function getInspectorActions(
600
600
  '\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
601
601
  },
602
602
  {
603
- label: '自定义',
603
+ label: '自定义逻辑',
604
604
  skill: null,
605
605
  requiresInput: true,
606
606
  promptTemplate: `对 ${r} 列表页的搜索栏进行修改`,
@@ -771,7 +771,7 @@ export function getInspectorActions(
771
771
  confirmDescription: `将在 ${r} 列表页工具栏中添加列显示/隐藏控制面板,用户可自定义显示哪些列。`,
772
772
  },
773
773
  {
774
- label: '自定义',
774
+ label: '自定义逻辑',
775
775
  skill: null,
776
776
  requiresInput: true,
777
777
  promptTemplate: `对 ${r} 列表页的工具栏区域(ListPageHeader 组件)进行修改`,
@@ -819,9 +819,9 @@ export function getInspectorActions(
819
819
  '\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
820
820
  },
821
821
  {
822
- label: '按条件显示 编辑 按钮 ',
822
+ label: '按条件显示某个按钮 ',
823
823
  skill: 'ui-config-update',
824
- promptTemplate: `为 ${r} 列表页的 编辑 按钮添加条件显示逻辑(EDIT)`,
824
+ promptTemplate: `为 ${r} 列表页操作栏的某个按钮添加条件显示逻辑`,
825
825
  promptPrefix: '显示条件:',
826
826
  requiresInput: true,
827
827
  inputPlaceholder:
@@ -830,7 +830,7 @@ export function getInspectorActions(
830
830
  '\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
831
831
  },
832
832
  {
833
- label: '自定义',
833
+ label: '自定义逻辑',
834
834
  skill: null,
835
835
  requiresInput: true,
836
836
  promptTemplate: `对 ${r} 列表页的行操作区域(RowActions 组件)进行修改`,
@@ -918,7 +918,7 @@ export function getInspectorActions(
918
918
  ],
919
919
  },
920
920
  {
921
- label: '自定义',
921
+ label: '自定义逻辑',
922
922
  skill: null,
923
923
  requiresInput: true,
924
924
  promptTemplate: `对 ${r} 列表页的批量操作区域(BulkActions 组件)进行修改`,
@@ -953,7 +953,7 @@ export function getInspectorActions(
953
953
  '\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
954
954
  },
955
955
  {
956
- label: '自定义',
956
+ label: '自定义逻辑',
957
957
  skill: null,
958
958
  requiresInput: true,
959
959
  promptTemplate: `对页面标题和 Logo 区域进行修改`,
@@ -1011,7 +1011,7 @@ export function getInspectorActions(
1011
1011
  '\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
1012
1012
  },
1013
1013
  {
1014
- label: '自定义',
1014
+ label: '自定义逻辑',
1015
1015
  skill: null,
1016
1016
  requiresInput: true,
1017
1017
  promptTemplate: `对顶部导航栏(App Header 组件)进行修改`,
@@ -1185,7 +1185,7 @@ export function getInspectorActions(
1185
1185
  confirmDescription: `将 ${r} 详情页设为只读模式,移除编辑、复制、删除按钮,用户只能查看不能修改。`,
1186
1186
  },
1187
1187
  {
1188
- label: '自定义',
1188
+ label: '自定义逻辑',
1189
1189
  skill: null,
1190
1190
  requiresInput: true,
1191
1191
  promptTemplate: `对 ${r} 详情页的操作工具栏(show header 区域)进行修改`,
@@ -70,7 +70,7 @@ const DEFAULT_MODE: ThemeMode = 'light';
70
70
  const DEFAULT_STYLE: ThemeStyleKey = 'standard';
71
71
  const DEFAULT_SIDER_THEME: SiderTheme = 'auto';
72
72
  const DEFAULT_MENU_LAYOUT: MenuLayoutMode = 'tree';
73
- const DEFAULT_MENU_SELECTION: MenuSelectionStyle = 'fill';
73
+ const DEFAULT_MENU_SELECTION: MenuSelectionStyle = 'indicator';
74
74
  const DEFAULT_MENU_EXPAND: MenuExpandMode = 'accordion';
75
75
 
76
76
  const readStorage = <T,>(
@@ -27,7 +27,7 @@ const { Text } = Typography;
27
27
  const { useToken } = theme;
28
28
 
29
29
  /**
30
- * Header 右侧操作簇:语言切换 + 外观设置入口 + 用户信息。
30
+ * Header 右侧操作簇:语言切换 + 用户信息。
31
31
  */
32
32
  export const HeaderActions: React.FC = () => {
33
33
  const { t } = useTranslation();
@@ -61,12 +61,14 @@ export const HeaderActions: React.FC = () => {
61
61
 
62
62
  return (
63
63
  <>
64
- <Button
65
- type="text"
66
- icon={<SettingOutlined />}
67
- aria-label={t('header.settings', 'Appearance')}
68
- onClick={() => setSettingsOpen(true)}
69
- />
64
+ {import.meta.env.DEV && (
65
+ <Button
66
+ type="text"
67
+ icon={<SettingOutlined />}
68
+ aria-label={t('header.settings', 'Appearance')}
69
+ onClick={() => setSettingsOpen(true)}
70
+ />
71
+ )}
70
72
 
71
73
  <Dropdown
72
74
  menu={langMenu}
@@ -100,10 +102,12 @@ export const HeaderActions: React.FC = () => {
100
102
  </Space>
101
103
  )}
102
104
 
103
- <SettingDrawer
104
- open={settingsOpen}
105
- onClose={() => setSettingsOpen(false)}
106
- />
105
+ {import.meta.env.DEV && (
106
+ <SettingDrawer
107
+ open={settingsOpen}
108
+ onClose={() => setSettingsOpen(false)}
109
+ />
110
+ )}
107
111
  </>
108
112
  );
109
113
  };
@@ -373,12 +373,6 @@ export const routeRegistry: Record<string, RouteEntry> = {
373
373
  () => import('routes/workflow/connections'),
374
374
  ),
375
375
  },
376
- workflow_approval_channels: {
377
- path: 'approval-channels',
378
- component: lazyWithReload(
379
- () => import('routes/workflow/approval-channels'),
380
- ),
381
- },
382
376
  approval_tasks: {
383
377
  path: 'approval-tasks',
384
378
  component: lazyWithReload(
@@ -102,7 +102,7 @@ export default function AddDataModal({ onConfirm, onCancel }: Props) {
102
102
  return;
103
103
  }
104
104
  onConfirm(
105
- '请帮我使用 prisma-schema-update skill 添加一个新的prisma model。\n\n以下是关于这个业务数据的描述:\n' +
105
+ '请帮我使用 prisma-schema-management skill 添加一个新的prisma model。\n\n以下是关于这个业务数据的描述:\n' +
106
106
  text,
107
107
  );
108
108
  } else if (activeTab === 'file') {
@@ -115,7 +115,7 @@ export default function AddDataModal({ onConfirm, onCancel }: Props) {
115
115
  return;
116
116
  }
117
117
  onConfirm(
118
- '请帮我使用 prisma-schema-update skill 添加一个新的prisma model。\n\n' +
118
+ '请帮我使用 prisma-schema-management skill 添加一个新的prisma model。\n\n' +
119
119
  '我提供了一份参考文件(CSV 格式),请读取它的列结构和示例数据,以此为基础设计数据表:\n' +
120
120
  uploadedPath +
121
121
  '\n\n补充说明:\n' +
@@ -127,7 +127,7 @@ export default function AddDataModal({ onConfirm, onCancel }: Props) {
127
127
  return;
128
128
  }
129
129
  const lines = [
130
- '请帮我使用 prisma-schema-update skill 添加一个新的prisma model。\n\n以下是我对这个业务数据的描述:\n',
130
+ '请帮我使用 prisma-schema-management skill 添加一个新的prisma model。\n\n以下是我对这个业务数据的描述:\n',
131
131
  ];
132
132
  GUIDED_QUESTIONS.forEach((q) => {
133
133
  if (answers[q.key]?.trim()) {
@@ -132,7 +132,7 @@ export default function AddPageModal({
132
132
  pages.find((p) => String(p.id) === selectedParent)?.code ||
133
133
  '';
134
134
  const lines = [
135
- '请帮我使用 page-create-new skill 添加一个新页面。\n\n以下是页面需求:\n',
135
+ '请帮我使用 page-management skill 添加一个新页面。\n\n以下是页面需求:\n',
136
136
  desc,
137
137
  ];
138
138
  if (uploadedImgPath) {
@@ -18,7 +18,7 @@ export default function DeleteDataConfirm({
18
18
  onConfirm(
19
19
  '请帮我删除' +
20
20
  (r ? ' ' + r : '') +
21
- ' 的数据表以及对应的管理页面。\n\n请按顺序执行:\n1. 使用 prisma-schema-update skill 删除 prisma model(两步安全操作:先注释掉字段/model,下次发版再彻底移除)并执行数据库迁移\n2. 使用 menu-management skill 从 t_page 表中移除对应的菜单记录\n3. 使用 permission-management skill 撤销所有角色对该页面的访问权限',
21
+ ' 的数据表以及对应的管理页面。\n\n请按顺序执行:\n1. 使用 prisma-schema-management skill 删除 prisma model(两步安全操作:先注释掉字段/model,下次发版再彻底移除)并执行数据库迁移\n2. 使用 menu-management skill 从 t_page 表中移除对应的菜单记录\n3. 使用 permission-management skill 撤销所有角色对该页面的访问权限',
22
22
  );
23
23
  }
24
24
 
@@ -49,7 +49,7 @@ export default function EditDataModal({
49
49
  return;
50
50
  }
51
51
  onConfirm(
52
- '请帮我使用 prisma-schema-update skill 修改' +
52
+ '请帮我使用 prisma-schema-management skill 修改' +
53
53
  (r ? ' ' + r : '') +
54
54
  ' 的 prisma model。\n\n以下是修改需求:\n' +
55
55
  text.trim(),
@@ -43,6 +43,7 @@ function snakeToCamel(str: string): string {
43
43
  // Icon 映射:page.code 到 React Icon 组件
44
44
  export const iconMapping: Record<string, React.ReactNode> = {
45
45
  dashboard: <DashboardOutlined />,
46
+ admin: <SettingOutlined />,
46
47
  administration: <SettingOutlined />,
47
48
  dataMngt: <DatabaseOutlined />,
48
49
  canvas: <BgColorsOutlined />,