openxiangda-cli 2.0.0-alpha.183 → 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.
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +5 -3
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/spec.js +1 -1
- package/dist/commands/spec.js.map +1 -1
- package/package.json +5 -5
- package/template/AGENTS.md +2 -2
- package/template/apps/web/e2e/README.md +7 -0
- package/template/apps/web/package.json +2 -2
- package/template/apps/web/playwright.config.ts +3 -5
- package/template/apps/web/vite.config.ts +1 -9
- package/template/appspec/app.md +5 -1
- package/template/package.json +1 -1
- package/template/apps/web/data-api-live.e2e.html +0 -15
- package/template/apps/web/e2e/client-fixture.ts +0 -5
- package/template/apps/web/e2e/component-defaults-fixture.css +0 -15
- package/template/apps/web/e2e/data-api-live-fixture.tsx +0 -162
- package/template/apps/web/e2e/data-api-live.spec.ts +0 -144
- package/template/apps/web/e2e/field-protocol-fixture.tsx +0 -387
- package/template/apps/web/e2e/field-protocol.spec.ts +0 -285
- package/template/apps/web/e2e/mobile-files.spec.ts +0 -96
- package/template/apps/web/e2e/mobile-reference-fixture.tsx +0 -314
- package/template/apps/web/e2e/mobile-reference.spec.ts +0 -360
- package/template/apps/web/e2e/mobile-selection.spec.ts +0 -199
- package/template/apps/web/e2e/resource-experience-fixture.tsx +0 -491
- package/template/apps/web/e2e/resource-platform-mock.ts +0 -202
- package/template/apps/web/e2e/resources.spec.ts +0 -488
- package/template/apps/web/e2e/standard-admin.spec.ts +0 -511
- package/template/apps/web/e2e/workflow-entry-fixture.tsx +0 -107
- package/template/apps/web/e2e/workflow-entry.spec.ts +0 -556
- package/template/apps/web/e2e/workflow-experience-fixture.tsx +0 -338
- package/template/apps/web/e2e/workflow.spec.ts +0 -1265
- package/template/apps/web/field-protocol.e2e.html +0 -22
- package/template/apps/web/mobile-reference.e2e.html +0 -27
- package/template/apps/web/resource-experience.e2e.html +0 -16
- package/template/apps/web/scripts/check.mjs +0 -43
- package/template/apps/web/test/contracts.test.ts +0 -163
- package/template/apps/web/workflow-entry.e2e.html +0 -15
- package/template/apps/web/workflow-experience.e2e.html +0 -15
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { expect, test, type Page } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
const field = (page: Page, name: string) => page.locator(`[data-field-code="${name}"]`);
|
|
4
|
-
const file = (name: string) => ({ name, mimeType: 'text/plain', buffer: Buffer.from('acceptance') });
|
|
5
|
-
async function submit(page: Page) {
|
|
6
|
-
await page.getByRole('button', { name: '验证表单', exact: true }).click();
|
|
7
|
-
await expect(page.locator('[data-saved-values]')).not.toBeEmpty();
|
|
8
|
-
return JSON.parse(await page.locator('[data-saved-values]').innerText());
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
test.describe('mobile managed files', () => {
|
|
12
|
-
test.beforeEach(async ({ page }) => {
|
|
13
|
-
await page.setViewportSize({ width: 390, height: 844 });
|
|
14
|
-
await page.route('**/china-divisions/**', route => route.fulfill({ json: [] }));
|
|
15
|
-
await page.route('**/files/*/content?**', route => route.fulfill({ contentType: 'image/svg+xml', body:
|
|
16
|
-
'<svg xmlns="http://www.w3.org/2000/svg" width="640" height="480" viewBox="0 0 640 480"><rect width="640" height="480" fill="#f1f3f5"/><circle cx="470" cy="120" r="45" fill="#c6d3df"/><path d="M0 480L220 180L410 480M230 480L450 250L640 480" fill="#95a9bb"/><text x="30" y="50" font-family="sans-serif" font-size="24" fill="#34495e">Image preview fixture</text></svg>' }));
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test('failed uploads retry, removed pending results stay removed and limits do not truncate', async ({ page }, info) => {
|
|
20
|
-
const errors: string[] = [];
|
|
21
|
-
page.on('pageerror', error => errors.push(error.message));
|
|
22
|
-
let attempts = 0;
|
|
23
|
-
let release!: () => void;
|
|
24
|
-
const held = new Promise<void>(resolve => { release = resolve; });
|
|
25
|
-
await page.route('**/__field-upload-fixture', async route => {
|
|
26
|
-
const name = decodeURIComponent(route.request().headers()['x-file-name']);
|
|
27
|
-
if (name === '待移除.txt') await held;
|
|
28
|
-
if (name === '重试.txt' && ++attempts === 1) return route.fulfill({ status: 503, body: '网络暂不可用,请重试。已填写内容会保留。' });
|
|
29
|
-
await route.fulfill({ status: 204 });
|
|
30
|
-
});
|
|
31
|
-
await page.goto('/field-protocol.e2e.html?mode=mobile&controlledUploads=1');
|
|
32
|
-
const attachment = field(page, '附件');
|
|
33
|
-
await attachment.locator('input[type=file]').setInputFiles(file('重试.txt'));
|
|
34
|
-
await expect(attachment.getByRole('alert')).toContainText('网络暂不可用');
|
|
35
|
-
await expect(attachment.locator('.ant-btn')).toHaveCount(0);
|
|
36
|
-
await expect(attachment.locator('input[type=file]')).toBeHidden();
|
|
37
|
-
await attachment.scrollIntoViewIfNeeded();
|
|
38
|
-
await page.screenshot({ path: info.outputPath('mobile-file-retry.png') });
|
|
39
|
-
await attachment.getByRole('button', { name: '重试', exact: true }).click();
|
|
40
|
-
await expect(attachment.getByRole('button', { name: '预览重试.txt', exact: true })).toBeVisible();
|
|
41
|
-
expect(attempts).toBe(2);
|
|
42
|
-
await attachment.locator('input[type=file]').setInputFiles(file('待移除.txt'));
|
|
43
|
-
const pending = attachment.locator('.oxa-mobile-upload-card');
|
|
44
|
-
await expect(pending).toContainText('上传中');
|
|
45
|
-
await pending.getByRole('button', { name: '移除', exact: true }).click();
|
|
46
|
-
release();
|
|
47
|
-
await expect(attachment.locator('.oxa-mobile-upload-card')).toHaveCount(0);
|
|
48
|
-
await attachment.locator('input[type=file]').setInputFiles([file('超额一.txt'), file('超额二.txt')]);
|
|
49
|
-
await expect(attachment.getByRole('alert')).toContainText('还可选择 1 个文件');
|
|
50
|
-
const saved = await submit(page);
|
|
51
|
-
expect(saved['附件'].map((item: { name: string }) => item.name)).toEqual(['验收附件.pdf', '重试.txt']);
|
|
52
|
-
await page.getByRole('button', { name: '重新载入已保存值' }).click();
|
|
53
|
-
await expect(attachment.getByRole('button', { name: '预览重试.txt', exact: true })).toBeVisible();
|
|
54
|
-
await attachment.getByRole('button', { name: '移除重试.txt', exact: true }).click();
|
|
55
|
-
expect((await submit(page))['附件']).toHaveLength(1);
|
|
56
|
-
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true);
|
|
57
|
-
expect(errors).toEqual([]);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('mobile image preview, close and attachment download use existing file APIs', async ({ page }, info) => {
|
|
61
|
-
const errors: string[] = [];
|
|
62
|
-
page.on('pageerror', error => errors.push(error.message));
|
|
63
|
-
await page.route('**/files/*/preview?**', route => route.fulfill({ json: {
|
|
64
|
-
canPreview: true, previewType: 'image', file: { name: '验收图片.png' },
|
|
65
|
-
} }));
|
|
66
|
-
await page.goto('/field-protocol.e2e.html?mode=mobile');
|
|
67
|
-
const images = field(page, '图片');
|
|
68
|
-
await expect(images.getByRole('button', { name: '上传图片', exact: true })).toBeVisible();
|
|
69
|
-
await images.locator('input[type=file]').setInputFiles({ name: '第二张.png', mimeType: 'image/png', buffer: Buffer.from('fixture-image') });
|
|
70
|
-
await expect(images.getByRole('button', { name: '预览第二张.png', exact: true })).toBeVisible();
|
|
71
|
-
await expect(images.getByRole('button', { name: '预览验收图片.png', exact: true })).toBeVisible();
|
|
72
|
-
await images.getByRole('button', { name: '预览第二张.png', exact: true }).click();
|
|
73
|
-
await expect(page.getByRole('button', { name: '关闭预览', exact: true })).toBeVisible();
|
|
74
|
-
await expect(page.locator('.ant-image-preview')).toHaveCount(0);
|
|
75
|
-
await expect(page.locator('.adm-image-viewer-indicator')).toHaveText('2 / 2');
|
|
76
|
-
await expect(page.locator('.adm-image-viewer-image-wrapper img').last()).toHaveJSProperty('naturalWidth', 640);
|
|
77
|
-
await page.screenshot({ path: info.outputPath('mobile-image-preview.png') });
|
|
78
|
-
const imageDownload = page.waitForEvent('download');
|
|
79
|
-
await page.getByRole('button', { name: '下载', exact: true }).click();
|
|
80
|
-
expect((await imageDownload).suggestedFilename()).toBe('第二张.png');
|
|
81
|
-
await page.getByRole('button', { name: '关闭预览', exact: true }).click();
|
|
82
|
-
await expect(page.getByRole('button', { name: '关闭预览', exact: true })).toHaveCount(0);
|
|
83
|
-
let downloadAttempts = 0;
|
|
84
|
-
await page.route('**/files/11111111-1111-4111-8111-111111111111/content?**', route => {
|
|
85
|
-
downloadAttempts += 1;
|
|
86
|
-
return downloadAttempts === 1 ? route.fulfill({ status: 503, body: 'Unavailable' }) : route.fulfill({ body: 'download acceptance', contentType: 'application/pdf' });
|
|
87
|
-
});
|
|
88
|
-
await field(page, '附件').getByRole('button', { name: '下载验收附件.pdf', exact: true }).click();
|
|
89
|
-
await expect(page.getByText('FILE_CONTENT_READ_FAILED: HTTP_503', { exact: true })).toBeVisible();
|
|
90
|
-
await expect(field(page, '附件').getByRole('button', { name: '预览验收附件.pdf', exact: true })).toBeVisible();
|
|
91
|
-
const download = page.waitForEvent('download');
|
|
92
|
-
await field(page, '附件').getByRole('button', { name: '下载验收附件.pdf', exact: true }).click();
|
|
93
|
-
expect((await download).suggestedFilename()).toBe('验收附件.pdf');
|
|
94
|
-
expect(errors).toEqual([]);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import ReactDOM from 'react-dom/client';
|
|
3
|
-
import { BrowserRouter } from 'react-router-dom';
|
|
4
|
-
import { App, ConfigProvider, Form } from 'antd';
|
|
5
|
-
import {
|
|
6
|
-
RuntimeBoundary,
|
|
7
|
-
OpenXiangdaResourceDefinitionsProvider,
|
|
8
|
-
} from 'openxiangda/react';
|
|
9
|
-
import {
|
|
10
|
-
MobileSurfaceFieldControl,
|
|
11
|
-
SubtableField,
|
|
12
|
-
buildSubtableOperations,
|
|
13
|
-
fieldValueForData,
|
|
14
|
-
type SurfaceField,
|
|
15
|
-
type SurfaceFieldRenderers,
|
|
16
|
-
type SubtableDraftRow,
|
|
17
|
-
} from 'openxiangda/field-kit';
|
|
18
|
-
import { Button } from 'openxiangda/mobile';
|
|
19
|
-
import type { DataResourceSurface, DataFileRef } from 'openxiangda/core';
|
|
20
|
-
import 'openxiangda/react/styles.css';
|
|
21
|
-
|
|
22
|
-
const options = ['选项一', '选项二', '选项三'].map((label, index) => ({
|
|
23
|
-
label,
|
|
24
|
-
value: String(index + 1),
|
|
25
|
-
}));
|
|
26
|
-
const field = (
|
|
27
|
-
key: string,
|
|
28
|
-
type: string,
|
|
29
|
-
widget: string,
|
|
30
|
-
extra = {}
|
|
31
|
-
): SurfaceField =>
|
|
32
|
-
({
|
|
33
|
-
key,
|
|
34
|
-
label: key,
|
|
35
|
-
type,
|
|
36
|
-
widget,
|
|
37
|
-
readCapabilities: [],
|
|
38
|
-
createCapabilities: [],
|
|
39
|
-
updateCapabilities: [],
|
|
40
|
-
...extra,
|
|
41
|
-
} as SurfaceField);
|
|
42
|
-
const childFields = {
|
|
43
|
-
choice: field('choice', 'option.single', 'select', {
|
|
44
|
-
label: '下拉单选',
|
|
45
|
-
options,
|
|
46
|
-
}),
|
|
47
|
-
quantity: field('quantity', 'number.integer', 'number', {
|
|
48
|
-
label: '数值',
|
|
49
|
-
requiredHint: true,
|
|
50
|
-
scale: 0,
|
|
51
|
-
}),
|
|
52
|
-
name: field('name', 'text.short', 'text', {
|
|
53
|
-
label: '单行文本',
|
|
54
|
-
requiredHint: true,
|
|
55
|
-
}),
|
|
56
|
-
parent_id: field('parent_id', 'uuid', 'text'),
|
|
57
|
-
row_order: field('row_order', 'number.integer', 'number'),
|
|
58
|
-
};
|
|
59
|
-
const childSurface: DataResourceSurface = {
|
|
60
|
-
mutationOwner: 'native',
|
|
61
|
-
generated: {
|
|
62
|
-
list: true,
|
|
63
|
-
detail: true,
|
|
64
|
-
create: true,
|
|
65
|
-
update: true,
|
|
66
|
-
delete: true,
|
|
67
|
-
},
|
|
68
|
-
fields: childFields,
|
|
69
|
-
};
|
|
70
|
-
const definitions = {
|
|
71
|
-
'form-items': {
|
|
72
|
-
code: 'form-items',
|
|
73
|
-
name: '表单明细',
|
|
74
|
-
capabilities: {
|
|
75
|
-
read: 'read',
|
|
76
|
-
create: 'create',
|
|
77
|
-
update: 'update',
|
|
78
|
-
delete: 'delete',
|
|
79
|
-
},
|
|
80
|
-
surface: childSurface,
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
const groups = [
|
|
84
|
-
{
|
|
85
|
-
title: '基础信息',
|
|
86
|
-
fields: [
|
|
87
|
-
field('单行文本', 'text.short', 'text'),
|
|
88
|
-
field('多行文本', 'text.long', 'textarea'),
|
|
89
|
-
field('数值', 'number.integer', 'number', { scale: 0 }),
|
|
90
|
-
field('评分', 'number.integer', 'rating'),
|
|
91
|
-
field('单选', 'option.single', 'radio', { options }),
|
|
92
|
-
field('复选', 'option.multiple', 'checkbox', { options }),
|
|
93
|
-
],
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
title: '选择与时间',
|
|
97
|
-
fields: [
|
|
98
|
-
field('下拉单选', 'option.single', 'select', { options }),
|
|
99
|
-
field('下拉复选', 'option.multiple', 'multi-select', { options }),
|
|
100
|
-
field('日期', 'date', 'date'),
|
|
101
|
-
field('日期时间', 'datetime', 'datetime'),
|
|
102
|
-
field('日期区间', 'date-range', 'date-range', {
|
|
103
|
-
rangeBoundary: 'closed',
|
|
104
|
-
}),
|
|
105
|
-
field('日期时间区间', 'datetime-range', 'datetime-range', {
|
|
106
|
-
rangeBoundary: 'closed',
|
|
107
|
-
}),
|
|
108
|
-
],
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
title: '文件与明细',
|
|
112
|
-
fields: [
|
|
113
|
-
field('图片上传', 'image', 'image', {
|
|
114
|
-
maxCount: 3,
|
|
115
|
-
maxSizeMb: 20,
|
|
116
|
-
accept: ['image/*'],
|
|
117
|
-
}),
|
|
118
|
-
field('附件', 'file', 'attachment', { maxCount: 3, maxSizeMb: 20 }),
|
|
119
|
-
field('流水号', 'serial-number', 'readonly'),
|
|
120
|
-
field('子表单', 'subtable', 'subtable', {
|
|
121
|
-
subtable: {
|
|
122
|
-
resourceCode: 'form-items',
|
|
123
|
-
foreignKey: 'parent_id',
|
|
124
|
-
orderField: 'row_order',
|
|
125
|
-
maxRows: 3,
|
|
126
|
-
},
|
|
127
|
-
}),
|
|
128
|
-
],
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
title: '位置与确认',
|
|
132
|
-
fields: [
|
|
133
|
-
field('地址', 'address', 'address'),
|
|
134
|
-
field('定位', 'location', 'location'),
|
|
135
|
-
field('级联选择', 'cascade.single', 'cascade', {
|
|
136
|
-
options: [
|
|
137
|
-
{
|
|
138
|
-
label: '部门',
|
|
139
|
-
value: 'department',
|
|
140
|
-
children: [
|
|
141
|
-
{ label: 'A部门', value: 'a' },
|
|
142
|
-
{ label: 'B部门', value: 'b' },
|
|
143
|
-
],
|
|
144
|
-
},
|
|
145
|
-
],
|
|
146
|
-
}),
|
|
147
|
-
field('手写签名', 'signature', 'signature'),
|
|
148
|
-
field('富文本', 'text.rich', 'rich-text'),
|
|
149
|
-
],
|
|
150
|
-
},
|
|
151
|
-
];
|
|
152
|
-
const file: DataFileRef = {
|
|
153
|
-
schemaVersion: 'openxiangda.data-file-ref/v2',
|
|
154
|
-
id: '11111111-1111-4111-8111-111111111111',
|
|
155
|
-
name: '使用说明.pdf',
|
|
156
|
-
size: 12680,
|
|
157
|
-
contentType: 'application/pdf',
|
|
158
|
-
};
|
|
159
|
-
const image: DataFileRef = {
|
|
160
|
-
...file,
|
|
161
|
-
id: '22222222-2222-4222-8222-222222222222',
|
|
162
|
-
name: '活动图片.png',
|
|
163
|
-
contentType: 'image/png',
|
|
164
|
-
width: 640,
|
|
165
|
-
height: 480,
|
|
166
|
-
};
|
|
167
|
-
const initialRows: SubtableDraftRow[] = [
|
|
168
|
-
{
|
|
169
|
-
key: 'item-1',
|
|
170
|
-
id: 'item-1',
|
|
171
|
-
revision: 4,
|
|
172
|
-
state: 'persisted',
|
|
173
|
-
data: { choice: options[2], quantity: 11, name: '测试记录' },
|
|
174
|
-
originalData: { choice: options[2], quantity: 11, name: '测试记录' },
|
|
175
|
-
originalOrder: 0,
|
|
176
|
-
},
|
|
177
|
-
];
|
|
178
|
-
const initial = {
|
|
179
|
-
评分: 3,
|
|
180
|
-
单选: options[1],
|
|
181
|
-
复选: options.slice(1),
|
|
182
|
-
图片上传: [image],
|
|
183
|
-
附件: [file],
|
|
184
|
-
子表单: initialRows,
|
|
185
|
-
日期: '2026-09-05',
|
|
186
|
-
日期时间: '2026-09-05T09:45:33.000Z',
|
|
187
|
-
日期区间: { start: '2026-09-05', end: '2026-09-08' },
|
|
188
|
-
日期时间区间: {
|
|
189
|
-
start: '2026-09-05T09:00:00.000Z',
|
|
190
|
-
end: '2026-09-08T10:00:00.000Z',
|
|
191
|
-
},
|
|
192
|
-
富文本: '<p>已有<strong>格式内容</strong></p>',
|
|
193
|
-
};
|
|
194
|
-
const renderers: SurfaceFieldRenderers = {
|
|
195
|
-
signer: { value: 'acceptance-user', label: '王老师' },
|
|
196
|
-
upload: async (_field, file) => {
|
|
197
|
-
const response = await fetch('/__reference-upload-fixture', { method: 'POST', body: file, headers: { 'x-file-name': encodeURIComponent(file.name) } });
|
|
198
|
-
if (!response.ok) throw new Error('上传失败');
|
|
199
|
-
return response.json();
|
|
200
|
-
},
|
|
201
|
-
renderSubtable: ({ field, disabled, operation, recordId }) => (
|
|
202
|
-
<SubtableField
|
|
203
|
-
mobile
|
|
204
|
-
field={field}
|
|
205
|
-
disabled={disabled}
|
|
206
|
-
operation={operation}
|
|
207
|
-
parentRecordId={recordId}
|
|
208
|
-
/>
|
|
209
|
-
),
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
function MobileReferenceForm() {
|
|
213
|
-
const [form] = Form.useForm();
|
|
214
|
-
const [saved, setSaved] = useState<unknown>();
|
|
215
|
-
const [operations, setOperations] = useState<unknown>();
|
|
216
|
-
const [notice, setNotice] = useState('');
|
|
217
|
-
return (
|
|
218
|
-
<main className="oxa-mobile-entry oxa-mobile-scope reference-form">
|
|
219
|
-
<header className="oxa-mobile-header">
|
|
220
|
-
<h3>未命名表单</h3>
|
|
221
|
-
</header>
|
|
222
|
-
<Form
|
|
223
|
-
className="oxa-mobile-form"
|
|
224
|
-
form={form}
|
|
225
|
-
initialValues={initial}
|
|
226
|
-
onFinish={values => {
|
|
227
|
-
setSaved(
|
|
228
|
-
Object.fromEntries(
|
|
229
|
-
groups
|
|
230
|
-
.flatMap(group => group.fields)
|
|
231
|
-
.map(item => [
|
|
232
|
-
item.key,
|
|
233
|
-
fieldValueForData(item, values[item.key]),
|
|
234
|
-
])
|
|
235
|
-
)
|
|
236
|
-
);
|
|
237
|
-
setOperations(
|
|
238
|
-
buildSubtableOperations({
|
|
239
|
-
rows: values.子表单,
|
|
240
|
-
childResourceCode: 'form-items',
|
|
241
|
-
childSurface,
|
|
242
|
-
foreignKey: 'parent_id',
|
|
243
|
-
orderField: 'row_order',
|
|
244
|
-
maxRows: 3,
|
|
245
|
-
parent: { operation: 'update', id: 'parent-1' },
|
|
246
|
-
canWrite: () => true,
|
|
247
|
-
canDelete: true,
|
|
248
|
-
})
|
|
249
|
-
);
|
|
250
|
-
setNotice('提交成功');
|
|
251
|
-
}}
|
|
252
|
-
>
|
|
253
|
-
<div className="reference-content">
|
|
254
|
-
{groups.map(group => (
|
|
255
|
-
<section key={group.title} aria-label={group.title}>
|
|
256
|
-
<h2 className="reference-group-title">{group.title}</h2>
|
|
257
|
-
<div className="reference-group">
|
|
258
|
-
{group.fields.map(field => (
|
|
259
|
-
<div data-field-code={field.key} key={field.key}>
|
|
260
|
-
<MobileSurfaceFieldControl
|
|
261
|
-
field={field}
|
|
262
|
-
operation="create"
|
|
263
|
-
resourceCode="field-records"
|
|
264
|
-
renderers={renderers}
|
|
265
|
-
/>
|
|
266
|
-
</div>
|
|
267
|
-
))}
|
|
268
|
-
</div>
|
|
269
|
-
</section>
|
|
270
|
-
))}
|
|
271
|
-
{notice && (
|
|
272
|
-
<div className="reference-notice" role="status">
|
|
273
|
-
{notice}
|
|
274
|
-
</div>
|
|
275
|
-
)}
|
|
276
|
-
</div>
|
|
277
|
-
<footer className="oxa-actions">
|
|
278
|
-
<Button
|
|
279
|
-
onClick={() => {
|
|
280
|
-
sessionStorage.setItem(
|
|
281
|
-
'mobile-reference-draft',
|
|
282
|
-
JSON.stringify(form.getFieldsValue())
|
|
283
|
-
);
|
|
284
|
-
setNotice('已暂存');
|
|
285
|
-
}}
|
|
286
|
-
>
|
|
287
|
-
暂存
|
|
288
|
-
</Button>
|
|
289
|
-
<Button color="primary" type="submit">
|
|
290
|
-
提交
|
|
291
|
-
</Button>
|
|
292
|
-
</footer>
|
|
293
|
-
<output data-saved-values>{JSON.stringify(saved)}</output>
|
|
294
|
-
<output data-operations>{JSON.stringify(operations)}</output>
|
|
295
|
-
</Form>
|
|
296
|
-
</main>
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
301
|
-
<React.StrictMode>
|
|
302
|
-
<ConfigProvider>
|
|
303
|
-
<App>
|
|
304
|
-
<BrowserRouter>
|
|
305
|
-
<RuntimeBoundary>
|
|
306
|
-
<OpenXiangdaResourceDefinitionsProvider definitions={definitions}>
|
|
307
|
-
<MobileReferenceForm />
|
|
308
|
-
</OpenXiangdaResourceDefinitionsProvider>
|
|
309
|
-
</RuntimeBoundary>
|
|
310
|
-
</BrowserRouter>
|
|
311
|
-
</App>
|
|
312
|
-
</ConfigProvider>
|
|
313
|
-
</React.StrictMode>
|
|
314
|
-
);
|