openxiangda-cli 2.0.0-alpha.149 → 2.0.0-alpha.150
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda-cli",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.150",
|
|
4
4
|
"description": "Thin application-level CLI for OpenXiangda 2.0.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@oclif/core": "4.13.3",
|
|
24
|
-
"openxiangda-contracts": "2.0.0-alpha.
|
|
25
|
-
"openxiangda-devkit-core": "2.0.0-alpha.
|
|
26
|
-
"openxiangda-mcp": "2.0.0-alpha.
|
|
27
|
-
"openxiangda-skill-kit": "2.0.0-alpha.
|
|
24
|
+
"openxiangda-contracts": "2.0.0-alpha.77",
|
|
25
|
+
"openxiangda-devkit-core": "2.0.0-alpha.97",
|
|
26
|
+
"openxiangda-mcp": "2.0.0-alpha.97",
|
|
27
|
+
"openxiangda-skill-kit": "2.0.0-alpha.119"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"tsx": "4.23.12",
|
|
@@ -116,14 +116,14 @@ const adminPages = [
|
|
|
116
116
|
{
|
|
117
117
|
code: 'workflow:task',
|
|
118
118
|
kind: 'workflow-task',
|
|
119
|
-
path: '/
|
|
119
|
+
path: '/tasks/:taskId',
|
|
120
120
|
label: '审批任务',
|
|
121
121
|
navigationEligible: false,
|
|
122
122
|
},
|
|
123
123
|
{
|
|
124
124
|
code: 'workflow:instance',
|
|
125
125
|
kind: 'workflow-instance',
|
|
126
|
-
path: '/
|
|
126
|
+
path: '/workflows/:instanceId',
|
|
127
127
|
label: '流程详情',
|
|
128
128
|
navigationEligible: false,
|
|
129
129
|
},
|
|
@@ -184,7 +184,7 @@ const routeManifest = {
|
|
|
184
184
|
kind: 'workflow-task',
|
|
185
185
|
desktop: {
|
|
186
186
|
routeCode: 'workflow.task.desktop',
|
|
187
|
-
path: '/
|
|
187
|
+
path: '/tasks/:taskId',
|
|
188
188
|
surface: 'admin',
|
|
189
189
|
pathParams: ['taskId'],
|
|
190
190
|
requiresAuthentication: true,
|
|
@@ -202,7 +202,7 @@ const routeManifest = {
|
|
|
202
202
|
kind: 'workflow-instance',
|
|
203
203
|
desktop: {
|
|
204
204
|
routeCode: 'workflow.instance.desktop',
|
|
205
|
-
path: '/
|
|
205
|
+
path: '/workflows/:instanceId',
|
|
206
206
|
surface: 'admin',
|
|
207
207
|
pathParams: ['instanceId'],
|
|
208
208
|
requiresAuthentication: true,
|
|
@@ -17,7 +17,7 @@ function detailNavigation(custom = false) {
|
|
|
17
17
|
}
|
|
18
18
|
: {
|
|
19
19
|
custom: false,
|
|
20
|
-
desktopPath: `/
|
|
20
|
+
desktopPath: `/tasks/${taskId}`,
|
|
21
21
|
mobilePath: `/m/tasks/${taskId}`,
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -115,12 +115,12 @@ function surface(completed = false, customDetail = false) {
|
|
|
115
115
|
projectionDigest: 'c'.repeat(64),
|
|
116
116
|
},
|
|
117
117
|
businessDetail: {
|
|
118
|
-
status: '
|
|
118
|
+
status: 'stale',
|
|
119
119
|
resourceCode: 'purchase-orders',
|
|
120
120
|
resourceName: '采购申请',
|
|
121
121
|
recordId: 'purchase-1',
|
|
122
122
|
requestedRevision: 8,
|
|
123
|
-
sourceRevision:
|
|
123
|
+
sourceRevision: 9,
|
|
124
124
|
surface: {
|
|
125
125
|
mutationOwner: 'workflow',
|
|
126
126
|
fields: {
|
|
@@ -133,10 +133,26 @@ function surface(completed = false, customDetail = false) {
|
|
|
133
133
|
createCapabilities: [],
|
|
134
134
|
updateCapabilities: [],
|
|
135
135
|
},
|
|
136
|
+
internalVenue: {
|
|
137
|
+
label: '技术场地引用',
|
|
138
|
+
type: 'reference',
|
|
139
|
+
widget: 'reference',
|
|
140
|
+
section: '系统信息',
|
|
141
|
+
system: true,
|
|
142
|
+
readCapabilities: [],
|
|
143
|
+
createCapabilities: [],
|
|
144
|
+
updateCapabilities: [],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
detail: {
|
|
148
|
+
layout: 'sections',
|
|
149
|
+
fieldOrder: ['amount', 'internalVenue'],
|
|
136
150
|
},
|
|
137
|
-
detail: { layout: 'sections', fieldOrder: ['amount'] },
|
|
138
151
|
},
|
|
139
|
-
record: {
|
|
152
|
+
record: {
|
|
153
|
+
amount: 30000,
|
|
154
|
+
internalVenue: '77777777-7777-4777-8777-777777777777',
|
|
155
|
+
},
|
|
140
156
|
subtables: {},
|
|
141
157
|
projectionDigest: 'd'.repeat(64),
|
|
142
158
|
},
|
|
@@ -234,6 +250,7 @@ function timeline(completed = false) {
|
|
|
234
250
|
startedAt: '2026-08-25T01:00:00.000Z',
|
|
235
251
|
completedAt: '2026-08-25T01:00:00.000Z',
|
|
236
252
|
assignees: [],
|
|
253
|
+
operations: [],
|
|
237
254
|
},
|
|
238
255
|
{
|
|
239
256
|
key: 'manager',
|
|
@@ -244,6 +261,18 @@ function timeline(completed = false) {
|
|
|
244
261
|
startedAt: '2026-08-25T01:01:00.000Z',
|
|
245
262
|
completedAt: completed ? '2026-08-25T01:12:00.000Z' : null,
|
|
246
263
|
assignees: [{ userId: 'acceptance-user', displayName: '李明' }],
|
|
264
|
+
operations: [{
|
|
265
|
+
id: 'operation-transfer',
|
|
266
|
+
operation: 'transfer',
|
|
267
|
+
operationLabel: '转交',
|
|
268
|
+
actorUserId: 'acceptance-user',
|
|
269
|
+
actorDisplayName: '李明',
|
|
270
|
+
actingForUserId: null,
|
|
271
|
+
reason: '由值班负责人继续处理',
|
|
272
|
+
detail: {},
|
|
273
|
+
severity: 'normal',
|
|
274
|
+
createdAt: '2026-08-25T01:08:00.000Z',
|
|
275
|
+
}],
|
|
247
276
|
},
|
|
248
277
|
{
|
|
249
278
|
key: 'finance',
|
|
@@ -254,9 +283,21 @@ function timeline(completed = false) {
|
|
|
254
283
|
startedAt: null,
|
|
255
284
|
completedAt: null,
|
|
256
285
|
assignees: [{ userId: 'finance-user', displayName: '财务负责人' }],
|
|
286
|
+
operations: [],
|
|
257
287
|
},
|
|
258
288
|
],
|
|
259
|
-
items: [
|
|
289
|
+
items: [{
|
|
290
|
+
id: 'operation-transfer',
|
|
291
|
+
operation: 'transfer',
|
|
292
|
+
operationLabel: '转交',
|
|
293
|
+
actorUserId: 'acceptance-user',
|
|
294
|
+
actorDisplayName: '李明',
|
|
295
|
+
actingForUserId: null,
|
|
296
|
+
reason: '由值班负责人继续处理',
|
|
297
|
+
detail: {},
|
|
298
|
+
severity: 'normal',
|
|
299
|
+
createdAt: '2026-08-25T01:08:00.000Z',
|
|
300
|
+
}],
|
|
260
301
|
};
|
|
261
302
|
}
|
|
262
303
|
|
|
@@ -410,7 +451,11 @@ function todoPage() {
|
|
|
410
451
|
|
|
411
452
|
async function mockWorkflow(
|
|
412
453
|
page: Page,
|
|
413
|
-
options: {
|
|
454
|
+
options: {
|
|
455
|
+
commandConflict?: boolean;
|
|
456
|
+
forbidden?: boolean;
|
|
457
|
+
customDetail?: boolean;
|
|
458
|
+
} = {}
|
|
414
459
|
) {
|
|
415
460
|
let completed = false;
|
|
416
461
|
await page.route('**/service/**', async route => {
|
|
@@ -593,6 +638,15 @@ async function mockWorkflow(
|
|
|
593
638
|
expect(route.request().postDataJSON()).not.toHaveProperty(
|
|
594
639
|
'expectedInstanceVersion'
|
|
595
640
|
);
|
|
641
|
+
if (options.commandConflict) {
|
|
642
|
+
return route.fulfill({
|
|
643
|
+
status: 409,
|
|
644
|
+
contentType: 'application/json',
|
|
645
|
+
body: JSON.stringify(
|
|
646
|
+
envelope({ freshSurface: surface(false, options.customDetail) }, 409)
|
|
647
|
+
),
|
|
648
|
+
});
|
|
649
|
+
}
|
|
596
650
|
completed = true;
|
|
597
651
|
return route.fulfill({
|
|
598
652
|
contentType: 'application/json',
|
|
@@ -704,13 +758,48 @@ test('redirects a direct standard task URL to the declared custom detail page',
|
|
|
704
758
|
}) => {
|
|
705
759
|
await mockWorkflow(page, { customDetail: true });
|
|
706
760
|
await page.goto(
|
|
707
|
-
`/workflow-experience.e2e.html?initial=/
|
|
761
|
+
`/workflow-experience.e2e.html?initial=/tasks/${taskId}`
|
|
708
762
|
);
|
|
709
763
|
await expect(page.getByTestId('custom-workflow-detail')).toContainText(
|
|
710
764
|
`${instanceId} / ${taskId}`
|
|
711
765
|
);
|
|
712
766
|
});
|
|
713
767
|
|
|
768
|
+
test('renders a standalone desktop detail and redirects the legacy admin URL', async ({
|
|
769
|
+
page,
|
|
770
|
+
}) => {
|
|
771
|
+
await mockWorkflow(page);
|
|
772
|
+
await page.goto(
|
|
773
|
+
workflowFixtureUrl(`/admin/tasks/${taskId}?from=legacy#approval`),
|
|
774
|
+
);
|
|
775
|
+
await expect(page.locator('.oxa-workflow-desktop-standalone-page')).toBeVisible();
|
|
776
|
+
await expect(page).toHaveURL(
|
|
777
|
+
new RegExp(`/tasks/${taskId}\\?from=legacy#approval$`),
|
|
778
|
+
);
|
|
779
|
+
await expect(page.locator('.oxa-app-layout')).toHaveCount(0);
|
|
780
|
+
await expect(page.locator('.oxa-topbar')).toHaveCount(0);
|
|
781
|
+
await expect(page.getByText('¥30,000')).toBeVisible();
|
|
782
|
+
await expect(page.getByText('技术场地引用')).toHaveCount(0);
|
|
783
|
+
await expect(page.getByText('业务数据已变化')).toHaveCount(0);
|
|
784
|
+
await expect(page.getByText('流程信息')).toHaveCount(0);
|
|
785
|
+
await expect(page.getByText('操作记录')).toHaveCount(0);
|
|
786
|
+
await expect(page.getByText('由值班负责人继续处理')).toHaveCount(1);
|
|
787
|
+
await expect(page.getByRole('button', { name: /同\s*意/ })).toBeVisible();
|
|
788
|
+
await expect(page.getByRole('button', { name: /拒\s*绝/ })).toBeVisible();
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
test('shows a friendly refresh prompt only after a real command conflict', async ({
|
|
792
|
+
page,
|
|
793
|
+
}) => {
|
|
794
|
+
await mockWorkflow(page, { commandConflict: true });
|
|
795
|
+
await page.goto(workflowFixtureUrl(`/tasks/${taskId}`));
|
|
796
|
+
await expect(page.getByText('业务数据已变化')).toHaveCount(0);
|
|
797
|
+
await page.getByRole('button', { name: /同\s*意/ }).click();
|
|
798
|
+
await page.getByLabel('审批意见').fill('同意采购');
|
|
799
|
+
await page.getByRole('button', { name: '确认同意' }).click();
|
|
800
|
+
await expect(page.getByText('内容已更新,请刷新后重试')).toBeVisible();
|
|
801
|
+
});
|
|
802
|
+
|
|
714
803
|
test('renders the independent mobile task and executes only a Surface operation', async ({
|
|
715
804
|
page,
|
|
716
805
|
}) => {
|
|
@@ -718,7 +807,7 @@ test('renders the independent mobile task and executes only a Surface operation'
|
|
|
718
807
|
await page.setViewportSize({ width: 390, height: 844 });
|
|
719
808
|
await page.goto(`/workflow-experience.e2e.html?initial=/m/tasks/${taskId}`);
|
|
720
809
|
await expect(page.locator('.oxa-workflow-mobile-page')).toBeVisible();
|
|
721
|
-
await expect(page.getByText('¥
|
|
810
|
+
await expect(page.getByText('¥30,000')).toBeVisible();
|
|
722
811
|
await expect(page.getByText('财务负责人').first()).toBeVisible();
|
|
723
812
|
await expect(page.getByRole('button', { name: /同\s*意/ })).toBeVisible();
|
|
724
813
|
await page.getByRole('button', { name: /同\s*意/ }).click();
|
|
@@ -785,7 +874,7 @@ test('negotiates direct standard routes after BrowserRouter listener setup', asy
|
|
|
785
874
|
// context to the independent mobile renderer at the narrow width.
|
|
786
875
|
await page.setViewportSize({ width: 360, height: 844 });
|
|
787
876
|
await page.goto(
|
|
788
|
-
workflowFixtureUrl(`/
|
|
877
|
+
workflowFixtureUrl(`/tasks/${taskId}?from=todo#approval`),
|
|
789
878
|
);
|
|
790
879
|
await expect(page.locator('.oxa-workflow-detail-mobile-native')).toBeVisible();
|
|
791
880
|
await expect(page).toHaveURL(
|
|
@@ -793,7 +882,7 @@ test('negotiates direct standard routes after BrowserRouter listener setup', asy
|
|
|
793
882
|
);
|
|
794
883
|
|
|
795
884
|
await page.goto(
|
|
796
|
-
workflowFixtureUrl(`/
|
|
885
|
+
workflowFixtureUrl(`/workflows/${instanceId}?from=todo#timeline`),
|
|
797
886
|
);
|
|
798
887
|
await expect(page.locator('.oxa-workflow-detail-mobile-native')).toBeVisible();
|
|
799
888
|
await expect(page).toHaveURL(
|