openxiangda-cli 2.0.0-alpha.182 → 2.0.0-alpha.185

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 (50) hide show
  1. package/dist/base.js +2 -2
  2. package/dist/base.js.map +1 -1
  3. package/dist/commands/admin.d.ts.map +1 -1
  4. package/dist/commands/admin.js +5 -3
  5. package/dist/commands/admin.js.map +1 -1
  6. package/dist/commands/create.d.ts +1 -0
  7. package/dist/commands/create.d.ts.map +1 -1
  8. package/dist/commands/create.js +34 -16
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/dev.d.ts.map +1 -1
  11. package/dist/commands/dev.js +1 -1
  12. package/dist/commands/dev.js.map +1 -1
  13. package/dist/commands/login.js +1 -1
  14. package/dist/commands/login.js.map +1 -1
  15. package/dist/commands/spec.js +1 -1
  16. package/dist/commands/spec.js.map +1 -1
  17. package/package.json +5 -5
  18. package/template/AGENTS.md +2 -2
  19. package/template/apps/web/e2e/README.md +7 -0
  20. package/template/apps/web/package.json +2 -2
  21. package/template/apps/web/playwright.config.ts +3 -5
  22. package/template/apps/web/vite.config.ts +1 -9
  23. package/template/appspec/app.md +5 -1
  24. package/template/package.json +1 -1
  25. package/template/apps/web/data-api-live.e2e.html +0 -15
  26. package/template/apps/web/e2e/client-fixture.ts +0 -5
  27. package/template/apps/web/e2e/component-defaults-fixture.css +0 -15
  28. package/template/apps/web/e2e/data-api-live-fixture.tsx +0 -162
  29. package/template/apps/web/e2e/data-api-live.spec.ts +0 -144
  30. package/template/apps/web/e2e/field-protocol-fixture.tsx +0 -387
  31. package/template/apps/web/e2e/field-protocol.spec.ts +0 -285
  32. package/template/apps/web/e2e/mobile-files.spec.ts +0 -96
  33. package/template/apps/web/e2e/mobile-reference-fixture.tsx +0 -314
  34. package/template/apps/web/e2e/mobile-reference.spec.ts +0 -360
  35. package/template/apps/web/e2e/mobile-selection.spec.ts +0 -199
  36. package/template/apps/web/e2e/resource-experience-fixture.tsx +0 -491
  37. package/template/apps/web/e2e/resource-platform-mock.ts +0 -202
  38. package/template/apps/web/e2e/resources.spec.ts +0 -488
  39. package/template/apps/web/e2e/standard-admin.spec.ts +0 -511
  40. package/template/apps/web/e2e/workflow-entry-fixture.tsx +0 -107
  41. package/template/apps/web/e2e/workflow-entry.spec.ts +0 -556
  42. package/template/apps/web/e2e/workflow-experience-fixture.tsx +0 -338
  43. package/template/apps/web/e2e/workflow.spec.ts +0 -1265
  44. package/template/apps/web/field-protocol.e2e.html +0 -22
  45. package/template/apps/web/mobile-reference.e2e.html +0 -27
  46. package/template/apps/web/resource-experience.e2e.html +0 -16
  47. package/template/apps/web/scripts/check.mjs +0 -43
  48. package/template/apps/web/test/contracts.test.ts +0 -163
  49. package/template/apps/web/workflow-entry.e2e.html +0 -15
  50. package/template/apps/web/workflow-experience.e2e.html +0 -15
@@ -1,338 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom/client';
3
- import {
4
- defineApplicationContributions,
5
- OpenXiangdaApplication,
6
- type AdminNavigationInput,
7
- type AdminPagesInput,
8
- type StandardApplicationTodoCenterProps,
9
- type StandardUserPageFrameProps,
10
- type StandardUserSurfaceContributions,
11
- } from 'openxiangda/react';
12
- import { useParams, useSearchParams } from 'react-router-dom';
13
- import { appCode } from '../../../packages/contracts/src/generated.js';
14
- import 'openxiangda/react/styles.css';
15
-
16
- const fixtureParams = new URLSearchParams(window.location.search);
17
- const standardSurfaceMode = fixtureParams.get('surfaces');
18
-
19
- const workflowDefinitions = [
20
- {
21
- code: 'purchase-approval',
22
- title: '采购审批',
23
- launch: { mode: 'standalone' },
24
- subject: {
25
- resourceCode: 'purchase-orders',
26
- factProjection: { amount: 'amount' },
27
- summaryFields: ['amount'],
28
- },
29
- processOperationCode: 'openxiangda.workflow.purchase-approval.submit',
30
- },
31
- ] as const;
32
-
33
- const resourceDefinitions = {
34
- 'purchase-orders': {
35
- code: 'purchase-orders',
36
- name: '采购申请',
37
- capabilities: {
38
- read: `app:${appCode}:data:purchase-orders:read`,
39
- create: `app:${appCode}:data:purchase-orders:create`,
40
- update: `app:${appCode}:data:purchase-orders:update`,
41
- delete: `app:${appCode}:data:purchase-orders:delete`,
42
- },
43
- surface: {
44
- mutationOwner: 'native',
45
- generated: { list: true, detail: true, create: true, update: true, delete: true },
46
- fields: {
47
- amount: {
48
- label: '申请金额',
49
- type: 'number.decimal',
50
- widget: 'money',
51
- requiredHint: true,
52
- readCapabilities: [`app:${appCode}:data:purchase-orders:read`],
53
- createCapabilities: [`app:${appCode}:data:purchase-orders:create`],
54
- updateCapabilities: [`app:${appCode}:data:purchase-orders:update`],
55
- },
56
- },
57
- form: { layout: 'flat', fieldOrder: ['amount'] },
58
- mobile: { enabled: true },
59
- },
60
- },
61
- } as const;
62
-
63
- const detailRoutes = {
64
- desktop: {
65
- code: 'purchase-detail',
66
- path: '/admin/operations/purchases/:instanceId',
67
- label: '采购审批详情',
68
- surface: 'admin',
69
- tabPersistence: 'none',
70
- keepAlive: 'none',
71
- },
72
- mobile: {
73
- code: 'purchase-detail-mobile',
74
- path: '/m/purchases/:instanceId',
75
- label: '移动采购审批详情',
76
- surface: 'user',
77
- tabPersistence: 'none',
78
- keepAlive: 'none',
79
- },
80
- } as const;
81
-
82
- function CustomWorkflowDetail() {
83
- const { instanceId } = useParams();
84
- const [search] = useSearchParams();
85
- return (
86
- <div data-testid="custom-workflow-detail">
87
- 自定义流程详情 {instanceId} / {search.get('taskId') || 'instance'}
88
- </div>
89
- );
90
- }
91
-
92
- function StandardFrame({
93
- back,
94
- canGoBack,
95
- children,
96
- device,
97
- pageKind,
98
- route,
99
- }: StandardUserPageFrameProps) {
100
- return (
101
- <section
102
- data-can-go-back={String(canGoBack)}
103
- data-page-kind={pageKind}
104
- data-route-code={route.routeCode}
105
- data-route-params={JSON.stringify(route.params)}
106
- data-testid={`standard-frame-${device}`}
107
- >
108
- <button onClick={back} type="button">返回</button>
109
- {children}
110
- </section>
111
- );
112
- }
113
-
114
- function CustomTodo({
115
- device,
116
- error,
117
- hasMore,
118
- items,
119
- loadMore,
120
- loading,
121
- loadingMore,
122
- openItem,
123
- query,
124
- refresh,
125
- setQuery,
126
- }: StandardApplicationTodoCenterProps) {
127
- return (
128
- <main data-testid={`custom-todo-${device}`}>
129
- <h1>{device === 'mobile' ? '移动应用待办' : '桌面应用待办'}</h1>
130
- <output data-testid="custom-todo-query">
131
- {query.view}/{String(query.unread)}/{query.keyword || 'all'}
132
- </output>
133
- {error ? <div role="alert">{error}</div> : null}
134
- <button onClick={() => void refresh()} type="button">刷新待办</button>
135
- <button
136
- onClick={() => setQuery({ unread: !query.unread })}
137
- type="button"
138
- >
139
- 切换未读
140
- </button>
141
- <ul aria-busy={loading || loadingMore}>
142
- {items.map(item => (
143
- <li key={item.messageId}>
144
- <button onClick={() => void openItem(item)} type="button">
145
- {item.title}
146
- </button>
147
- </li>
148
- ))}
149
- </ul>
150
- <button
151
- disabled={!hasMore || loadingMore}
152
- onClick={() => void loadMore()}
153
- type="button"
154
- >
155
- 加载更多
156
- </button>
157
- </main>
158
- );
159
- }
160
-
161
- function BrokenTodo(_props: StandardApplicationTodoCenterProps) {
162
- throw new Error('fixture standard user renderer failure');
163
- }
164
-
165
- const standardUserSurfaces: StandardUserSurfaceContributions | undefined =
166
- standardSurfaceMode
167
- ? {
168
- frame: { desktop: StandardFrame, mobile: StandardFrame },
169
- applicationTodoCenter: {
170
- desktop:
171
- standardSurfaceMode === 'error' ? BrokenTodo : CustomTodo,
172
- mobile: standardSurfaceMode === 'error' ? BrokenTodo : CustomTodo,
173
- },
174
- }
175
- : undefined;
176
-
177
- const applicationContributions = defineApplicationContributions(detailRoutes, {
178
- pages: {
179
- desktop: CustomWorkflowDetail,
180
- mobile: CustomWorkflowDetail,
181
- },
182
- ...(standardUserSurfaces ? { standardUserSurfaces } : {}),
183
- });
184
-
185
- const adminPages = [] as const satisfies AdminPagesInput;
186
-
187
- const routeManifest = {
188
- schemaVersion: 'openxiangda.application-route-manifest/v3',
189
- appCode,
190
- devicePolicy: {
191
- kind: 'viewport-family',
192
- mobileMaxWidthPx: 900,
193
- desktopMinWidthPx: 901,
194
- },
195
- rootEntry: { code: 'application-root', desktop: '/', mobile: '/m/' },
196
- authentication: {
197
- desktop: { routeCode: 'application-login', path: '/login' },
198
- mobile: { routeCode: 'application-login-mobile', path: '/m/login' },
199
- },
200
- routes: [
201
- {
202
- code: 'application:todo-center',
203
- kind: 'application-todo-center',
204
- desktop: {
205
- routeCode: 'application.todo-center.desktop',
206
- path: '/todos',
207
- surface: 'user',
208
- pathParams: [],
209
- requiresAuthentication: true,
210
- },
211
- mobile: {
212
- routeCode: 'application.todo-center.mobile',
213
- path: '/m/todos',
214
- surface: 'user',
215
- pathParams: [],
216
- requiresAuthentication: true,
217
- },
218
- },
219
- {
220
- code: 'workflow:work-center',
221
- kind: 'workflow-work-center',
222
- desktop: {
223
- routeCode: 'workflow.work.center.desktop',
224
- path: '/work-center',
225
- surface: 'user',
226
- pathParams: [],
227
- requiresAuthentication: true,
228
- },
229
- mobile: {
230
- routeCode: 'workflow.work.center.mobile',
231
- path: '/m/work-center',
232
- surface: 'user',
233
- pathParams: [],
234
- requiresAuthentication: true,
235
- },
236
- },
237
- {
238
- code: 'workflow:task',
239
- kind: 'workflow-task',
240
- desktop: {
241
- routeCode: 'workflow.task.desktop',
242
- path: '/tasks/:taskId',
243
- surface: 'user',
244
- pathParams: ['taskId'],
245
- requiresAuthentication: true,
246
- },
247
- mobile: {
248
- routeCode: 'workflow.task.mobile',
249
- path: '/m/tasks/:taskId',
250
- surface: 'user',
251
- pathParams: ['taskId'],
252
- requiresAuthentication: true,
253
- },
254
- },
255
- {
256
- code: 'workflow:instance',
257
- kind: 'workflow-instance',
258
- desktop: {
259
- routeCode: 'workflow.instance.desktop',
260
- path: '/workflows/:instanceId',
261
- surface: 'user',
262
- pathParams: ['instanceId'],
263
- requiresAuthentication: true,
264
- },
265
- mobile: {
266
- routeCode: 'workflow.instance.mobile',
267
- path: '/m/workflows/:instanceId',
268
- surface: 'user',
269
- pathParams: ['instanceId'],
270
- requiresAuthentication: true,
271
- },
272
- },
273
- {
274
- code: 'workflow:purchase-approval:launch',
275
- kind: 'workflow-launch',
276
- workflowCode: 'purchase-approval',
277
- desktop: {
278
- routeCode: 'workflow.purchase-approval.launch.desktop',
279
- path: '/workflows/:workflowCode/start',
280
- surface: 'user',
281
- pathParams: ['workflowCode'],
282
- requiresAuthentication: true,
283
- },
284
- mobile: {
285
- routeCode: 'workflow.purchase-approval.launch.mobile',
286
- path: '/m/workflows/:workflowCode/start',
287
- surface: 'user',
288
- pathParams: ['workflowCode'],
289
- requiresAuthentication: true,
290
- },
291
- },
292
- ],
293
- digest: '34cc08a02cd187a07d9e2d2f99c1080b5b86f3a4512f9e0f43ff4cb05b7195fa',
294
- } as const;
295
-
296
- const adminNavigation = [] as const satisfies AdminNavigationInput;
297
-
298
- const initialPath = fixtureParams.get('initial') || '/work-center';
299
- const runtimeBase = fixtureParams.get('base')?.trim();
300
- if (runtimeBase) {
301
- for (const [name, content] of [
302
- ['openxiangda-runtime-base', runtimeBase],
303
- ['openxiangda-app-code', appCode],
304
- ['openxiangda-environment', 'preproduction'],
305
- ] as const) {
306
- const meta =
307
- document.querySelector<HTMLMetaElement>(`meta[name="${name}"]`) ||
308
- document.createElement('meta');
309
- meta.name = name;
310
- meta.content = content;
311
- if (!meta.parentElement) document.head.appendChild(meta);
312
- }
313
- }
314
- if (location.pathname.endsWith('/workflow-experience.e2e.html')) {
315
- const stateToken = fixtureParams.get('state');
316
- history.replaceState(
317
- stateToken
318
- ? { usr: { routeNegotiationState: stateToken }, key: 'fixture-state' }
319
- : {},
320
- '',
321
- initialPath,
322
- );
323
- }
324
-
325
- ReactDOM.createRoot(document.getElementById('root')!).render(
326
- <React.StrictMode>
327
- <OpenXiangdaApplication
328
- appCode={appCode}
329
- appName="流程体验验收"
330
- adminNavigation={adminNavigation}
331
- adminPages={adminPages}
332
- routeManifest={routeManifest}
333
- contributions={applicationContributions}
334
- resourceDefinitions={resourceDefinitions}
335
- workflows={workflowDefinitions}
336
- />
337
- </React.StrictMode>
338
- );