openyida 2026.5.21 → 2026.5.25
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/README.md +5 -1
- package/bin/yida.js +7 -1
- package/lib/app/app-list.js +20 -1
- package/lib/app/check-page.js +2 -2
- package/lib/app/compile.js +3 -2
- package/lib/app/externalize-form.js +642 -0
- package/lib/app/import-app.js +39 -11
- package/lib/app/page-compat.js +258 -2
- package/lib/app/page-compiler.js +4 -1
- package/lib/app/page-linter.js +271 -0
- package/lib/app/publish.js +3 -2
- package/lib/auth/cdp-browser-login.js +7 -3
- package/lib/auth/login.js +2 -3
- package/lib/core/command-manifest.js +3 -0
- package/lib/core/copy.js +50 -8
- package/lib/core/env-manager.js +24 -16
- package/lib/core/locales/ar.js +7 -0
- package/lib/core/locales/de.js +7 -0
- package/lib/core/locales/en.js +7 -0
- package/lib/core/locales/es.js +7 -0
- package/lib/core/locales/fr.js +7 -0
- package/lib/core/locales/hi.js +7 -0
- package/lib/core/locales/ja.js +7 -0
- package/lib/core/locales/ko.js +7 -0
- package/lib/core/locales/pt.js +7 -0
- package/lib/core/locales/vi.js +7 -0
- package/lib/core/locales/zh-HK.js +7 -0
- package/lib/core/locales/zh.js +7 -0
- package/lib/core/utils.js +2 -2
- package/lib/process/configure-process.js +552 -20
- package/package.json +1 -1
- package/project/pages/src/demo-agent-chatbox.oyd.jsx +78 -3
- package/scripts/e2e-real/full-runner.js +257 -8
- package/scripts/e2e-real/skill-coverage.js +2 -2
- package/yida-skills/SKILL.md +1 -1
- package/yida-skills/skills/yida-chart/SKILL.md +1 -1
- package/yida-skills/skills/yida-create-process/SKILL.md +3 -2
- package/yida-skills/skills/yida-custom-page/SKILL.md +7 -2
- package/yida-skills/skills/yida-custom-page/examples/attachment-upload.js +14 -12
- package/yida-skills/skills/yida-custom-page/references/attachment-upload-guide.md +3 -1
- package/yida-skills/skills/yida-custom-page/references/coding-guide.md +4 -0
- package/yida-skills/skills/yida-custom-page/references/component-jsx-guide.md +31 -22
- package/yida-skills/skills/yida-dashboard/SKILL.md +10 -9
- package/yida-skills/skills/yida-dashboard/references/interaction-patterns.md +2 -0
- package/yida-skills/skills/yida-dashboard/references/pitfalls.md +13 -4
- package/yida-skills/skills/yida-dashboard/references/structure-and-layout.md +1 -1
- package/yida-skills/skills/yida-ppt-slider/SKILL.md +47 -37
- package/yida-skills/skills/yida-ppt-slider/references/examples.md +5 -4
- package/yida-skills/skills/yida-process-rule/SKILL.md +93 -3
- package/yida-skills/skills/yida-process-rule/references/official-component-nodes.md +93 -0
- package/yida-skills/skills/yida-publish-page/SKILL.md +6 -4
|
@@ -59,7 +59,10 @@ var KNOWLEDGE_CACHE_STALE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
|
59
59
|
var REMOTE_SYNC_DEBOUNCE_MS = 2500;
|
|
60
60
|
var REMOTE_SYNC_MIN_INTERVAL_MS = 6000;
|
|
61
61
|
var REMOTE_MAX_SESSIONS = 20;
|
|
62
|
-
var REMOTE_MAX_MESSAGES_PER_SESSION =
|
|
62
|
+
var REMOTE_MAX_MESSAGES_PER_SESSION = 400;
|
|
63
|
+
var MESSAGE_RENDER_INITIAL_COUNT = 40;
|
|
64
|
+
var MESSAGE_RENDER_STEP = 30;
|
|
65
|
+
var MESSAGE_SCROLL_TOP_THRESHOLD = 36;
|
|
63
66
|
var KNOWLEDGE_DOC_PAGE_PATH = '/s/openyida-doc';
|
|
64
67
|
var OPENYIDA_DOCS_URL = 'https://openyida.ai/docs';
|
|
65
68
|
var YIDA_DOCS_URL = 'https://docs.aliwork.com/docs/developer/learning';
|
|
@@ -404,6 +407,7 @@ var _customState = {
|
|
|
404
407
|
isSending: false,
|
|
405
408
|
statusText: 'Qwen 就绪',
|
|
406
409
|
markdownReady: false,
|
|
410
|
+
messageRenderCount: MESSAGE_RENDER_INITIAL_COUNT,
|
|
407
411
|
sequence: 3,
|
|
408
412
|
ready: false,
|
|
409
413
|
};
|
|
@@ -811,6 +815,28 @@ function getSessionMessages(sessionId) {
|
|
|
811
815
|
return (_customState.messages && _customState.messages[sessionId]) || [];
|
|
812
816
|
}
|
|
813
817
|
|
|
818
|
+
function getMessageRenderCount(total) {
|
|
819
|
+
var count = Number(_customState.messageRenderCount || MESSAGE_RENDER_INITIAL_COUNT);
|
|
820
|
+
if (!Number.isFinite(count) || count < MESSAGE_RENDER_INITIAL_COUNT) {
|
|
821
|
+
count = MESSAGE_RENDER_INITIAL_COUNT;
|
|
822
|
+
}
|
|
823
|
+
return Math.min(Math.max(count, MESSAGE_RENDER_INITIAL_COUNT), total || 0);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
function getRenderableMessages(messages) {
|
|
827
|
+
var list = messages || [];
|
|
828
|
+
var count = getMessageRenderCount(list.length);
|
|
829
|
+
if (count >= list.length) {
|
|
830
|
+
return list;
|
|
831
|
+
}
|
|
832
|
+
return list.slice(list.length - count);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
function hasMoreEarlierMessages(messages) {
|
|
836
|
+
var list = messages || [];
|
|
837
|
+
return getMessageRenderCount(list.length) < list.length;
|
|
838
|
+
}
|
|
839
|
+
|
|
814
840
|
function isBlankNewTaskSession(session, messageMap) {
|
|
815
841
|
if (!session || !session.id) {
|
|
816
842
|
return false;
|
|
@@ -2554,6 +2580,7 @@ function normalizePersistedState(parsed) {
|
|
|
2554
2580
|
provider: 'yida-text',
|
|
2555
2581
|
widgetOpen: false,
|
|
2556
2582
|
confirmCard: null,
|
|
2583
|
+
messageRenderCount: MESSAGE_RENDER_INITIAL_COUNT,
|
|
2557
2584
|
sequence: Number(parsed.sequence || 3),
|
|
2558
2585
|
};
|
|
2559
2586
|
}
|
|
@@ -2966,6 +2993,31 @@ export function scrollChatToBottom() {
|
|
|
2966
2993
|
}, 80);
|
|
2967
2994
|
}
|
|
2968
2995
|
|
|
2996
|
+
export function handleMessageListScroll(e) {
|
|
2997
|
+
var list = e && e.currentTarget ? e.currentTarget : null;
|
|
2998
|
+
if (!list || list.scrollTop > MESSAGE_SCROLL_TOP_THRESHOLD) {
|
|
2999
|
+
return;
|
|
3000
|
+
}
|
|
3001
|
+
var messages = getActiveMessages();
|
|
3002
|
+
var currentCount = getMessageRenderCount(messages.length);
|
|
3003
|
+
if (currentCount >= messages.length) {
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
3006
|
+
var previousScrollHeight = list.scrollHeight;
|
|
3007
|
+
var previousScrollTop = list.scrollTop;
|
|
3008
|
+
var nextCount = Math.min(messages.length, currentCount + MESSAGE_RENDER_STEP);
|
|
3009
|
+
this.setCustomState({
|
|
3010
|
+
messageRenderCount: nextCount,
|
|
3011
|
+
statusText: nextCount >= messages.length ? '已加载全部历史' : '已加载更早消息',
|
|
3012
|
+
});
|
|
3013
|
+
setTimeout(function() {
|
|
3014
|
+
var nextList = document.getElementById('agent-chatbox-message-list');
|
|
3015
|
+
if (nextList) {
|
|
3016
|
+
nextList.scrollTop = nextList.scrollHeight - previousScrollHeight + previousScrollTop;
|
|
3017
|
+
}
|
|
3018
|
+
}, 40);
|
|
3019
|
+
}
|
|
3020
|
+
|
|
2969
3021
|
export function ensureTailwind() {
|
|
2970
3022
|
var self = this;
|
|
2971
3023
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
@@ -3162,6 +3214,7 @@ export function loadRemoteWorkspace() {
|
|
|
3162
3214
|
restored.statusText = '已加载云端会话';
|
|
3163
3215
|
restored.toolRuns = prependToolRun('remote.load', 'done', '宜搭表单');
|
|
3164
3216
|
self.setCustomState(restored);
|
|
3217
|
+
self.scrollChatToBottom();
|
|
3165
3218
|
} else {
|
|
3166
3219
|
self.setCustomState({
|
|
3167
3220
|
remoteLoaded: true,
|
|
@@ -3967,6 +4020,7 @@ export function switchSession(sessionId) {
|
|
|
3967
4020
|
this.setCustomState({
|
|
3968
4021
|
activeSessionId: sessionId,
|
|
3969
4022
|
activeProjectId: session && session.projectId ? session.projectId : '',
|
|
4023
|
+
messageRenderCount: MESSAGE_RENDER_INITIAL_COUNT,
|
|
3970
4024
|
draft: '',
|
|
3971
4025
|
widgetDraft: '',
|
|
3972
4026
|
pendingImage: null,
|
|
@@ -3979,6 +4033,7 @@ export function switchSession(sessionId) {
|
|
|
3979
4033
|
projectMenuOpenId: '',
|
|
3980
4034
|
statusText: '会话已打开',
|
|
3981
4035
|
});
|
|
4036
|
+
this.scrollChatToBottom();
|
|
3982
4037
|
this.focusMainComposerInput();
|
|
3983
4038
|
}
|
|
3984
4039
|
|
|
@@ -4001,6 +4056,7 @@ export function createSession(projectId) {
|
|
|
4001
4056
|
messages: compacted.messages,
|
|
4002
4057
|
activeSessionId: reusableId,
|
|
4003
4058
|
activeProjectId: targetProjectId,
|
|
4059
|
+
messageRenderCount: MESSAGE_RENDER_INITIAL_COUNT,
|
|
4004
4060
|
projectOpenMap: nextProjectOpenMap,
|
|
4005
4061
|
draft: '',
|
|
4006
4062
|
widgetDraft: '',
|
|
@@ -4034,6 +4090,7 @@ export function createSession(projectId) {
|
|
|
4034
4090
|
messages: nextMessages,
|
|
4035
4091
|
activeSessionId: sessionId,
|
|
4036
4092
|
activeProjectId: targetProjectId,
|
|
4093
|
+
messageRenderCount: MESSAGE_RENDER_INITIAL_COUNT,
|
|
4037
4094
|
projectOpenMap: nextProjectOpenMap,
|
|
4038
4095
|
draft: '',
|
|
4039
4096
|
widgetDraft: '',
|
|
@@ -4455,6 +4512,7 @@ export function archiveSession(sessionId) {
|
|
|
4455
4512
|
sessions: sessions,
|
|
4456
4513
|
messages: messages,
|
|
4457
4514
|
activeSessionId: activeSessionId,
|
|
4515
|
+
messageRenderCount: MESSAGE_RENDER_INITIAL_COUNT,
|
|
4458
4516
|
sessionMenuOpenId: '',
|
|
4459
4517
|
sessionMoveOpenId: '',
|
|
4460
4518
|
statusText: '已归档',
|
|
@@ -4506,6 +4564,7 @@ export function commitDeleteSession(sessionId) {
|
|
|
4506
4564
|
sessions: sessions,
|
|
4507
4565
|
messages: messages,
|
|
4508
4566
|
activeSessionId: activeSessionId,
|
|
4567
|
+
messageRenderCount: MESSAGE_RENDER_INITIAL_COUNT,
|
|
4509
4568
|
sessionMenuOpenId: '',
|
|
4510
4569
|
sessionMoveOpenId: '',
|
|
4511
4570
|
actionDialog: null,
|
|
@@ -6610,6 +6669,8 @@ export function renderJsx() {
|
|
|
6610
6669
|
var viewportWidth = typeof window !== 'undefined' && window.innerWidth ? window.innerWidth : 1280;
|
|
6611
6670
|
var isMobile = viewportWidth <= 760 || (this.utils && this.utils.isMobile ? this.utils.isMobile() : false);
|
|
6612
6671
|
var messages = getActiveMessages();
|
|
6672
|
+
var visibleMessages = getRenderableMessages(messages);
|
|
6673
|
+
var hasMoreMessages = hasMoreEarlierMessages(messages);
|
|
6613
6674
|
var shellStyle = isMobile ? styles.mobileShell : (_customState.sidebarCollapsed ? Object.assign({}, styles.shell, styles.shellCollapsed) : styles.shell);
|
|
6614
6675
|
|
|
6615
6676
|
return (
|
|
@@ -6623,8 +6684,13 @@ export function renderJsx() {
|
|
|
6623
6684
|
{this.renderChatHeader(isMobile)}
|
|
6624
6685
|
{this.renderBridgePanel(isMobile)}
|
|
6625
6686
|
{messages.length ? (
|
|
6626
|
-
<div id="agent-chatbox-message-list" className={tw.messageList} style={styles.messageList}>
|
|
6627
|
-
{
|
|
6687
|
+
<div id="agent-chatbox-message-list" className={tw.messageList} style={styles.messageList} onScroll={(e) => { self.handleMessageListScroll(e); }}>
|
|
6688
|
+
{hasMoreMessages ? (
|
|
6689
|
+
<div style={styles.historyLoader}>
|
|
6690
|
+
向上滚动加载更早消息
|
|
6691
|
+
</div>
|
|
6692
|
+
) : null}
|
|
6693
|
+
{visibleMessages.map((message) => self.renderMessage(message))}
|
|
6628
6694
|
{_customState.confirmCard ? (
|
|
6629
6695
|
<div className={tw.messageRow} style={styles.messageRow}>
|
|
6630
6696
|
{this.renderInlineConfirmCard()}
|
|
@@ -8746,6 +8812,15 @@ styles = Object.assign({}, styles, {
|
|
|
8746
8812
|
gap: 18,
|
|
8747
8813
|
alignItems: 'center',
|
|
8748
8814
|
},
|
|
8815
|
+
historyLoader: {
|
|
8816
|
+
width: '100%',
|
|
8817
|
+
maxWidth: 840,
|
|
8818
|
+
textAlign: 'center',
|
|
8819
|
+
color: '#8f8f8f',
|
|
8820
|
+
fontSize: 12,
|
|
8821
|
+
lineHeight: '28px',
|
|
8822
|
+
padding: '2px 0 8px',
|
|
8823
|
+
},
|
|
8749
8824
|
messageListEmpty: {
|
|
8750
8825
|
justifyContent: 'center',
|
|
8751
8826
|
paddingTop: 0,
|
|
@@ -193,6 +193,176 @@ function buildAppendCharts(formUuid, fields) {
|
|
|
193
193
|
];
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
function buildFieldBehaviorList(fields, editableLabels = []) {
|
|
197
|
+
const editable = new Set(editableLabels);
|
|
198
|
+
return (fields || []).map((field) => ({
|
|
199
|
+
fieldId: field.fieldId,
|
|
200
|
+
fieldBehavior: editable.has(field.label) ? 'NORMAL' : 'READONLY',
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function ensureProcessFields(fields) {
|
|
205
|
+
if (!fields || fields.length === 0) {
|
|
206
|
+
throw new Error('Process stage requires form schema fields; include the form stage before process');
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
textField: fieldByLabel(fields, 'E2E Text'),
|
|
210
|
+
numberField: fieldByLabel(fields, 'E2E Number'),
|
|
211
|
+
statusField: fieldByLabel(fields, 'E2E Status'),
|
|
212
|
+
notesField: fields.find((field) => field.label === 'E2E Notes') || null,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function buildProcessCreateDefinition(fields) {
|
|
217
|
+
const processFields = ensureProcessFields(fields);
|
|
218
|
+
const editableNotes = processFields.notesField ? ['E2E Notes'] : ['E2E Text'];
|
|
219
|
+
const readonlyBehavior = buildFieldBehaviorList(fields);
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
nodes: [
|
|
223
|
+
{
|
|
224
|
+
type: 'operator',
|
|
225
|
+
name: 'E2E 资料补充',
|
|
226
|
+
executor: 'originator',
|
|
227
|
+
formConfig: {
|
|
228
|
+
behaviorList: buildFieldBehaviorList(fields, editableNotes),
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
type: 'parallel',
|
|
233
|
+
name: 'E2E 并行会审',
|
|
234
|
+
branches: [
|
|
235
|
+
{
|
|
236
|
+
name: 'E2E 业务审批',
|
|
237
|
+
childNodes: [
|
|
238
|
+
{
|
|
239
|
+
type: 'approval',
|
|
240
|
+
name: 'E2E 业务审批',
|
|
241
|
+
approver: 'originator',
|
|
242
|
+
formConfig: { behaviorList: readonlyBehavior },
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: 'E2E 财务审批',
|
|
248
|
+
childNodes: [
|
|
249
|
+
{
|
|
250
|
+
type: 'approval',
|
|
251
|
+
name: 'E2E 财务审批',
|
|
252
|
+
approver: 'originator',
|
|
253
|
+
formConfig: { behaviorList: readonlyBehavior },
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
type: 'carbon',
|
|
261
|
+
name: 'E2E 流程抄送',
|
|
262
|
+
approver: 'originator',
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function buildProcessRuleDefinition(fields) {
|
|
269
|
+
const processFields = ensureProcessFields(fields);
|
|
270
|
+
const readonlyBehavior = buildFieldBehaviorList(fields);
|
|
271
|
+
const editableStatus = buildFieldBehaviorList(fields, ['E2E Status']);
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
nodes: [
|
|
275
|
+
{
|
|
276
|
+
type: 'approval',
|
|
277
|
+
name: 'E2E 发起人复核',
|
|
278
|
+
approver: 'originator',
|
|
279
|
+
formConfig: { behaviorList: readonlyBehavior },
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
type: 'route',
|
|
283
|
+
conditions: [
|
|
284
|
+
{
|
|
285
|
+
name: 'E2E 数字大于 0',
|
|
286
|
+
rules: [
|
|
287
|
+
{
|
|
288
|
+
fieldId: processFields.numberField.fieldId,
|
|
289
|
+
fieldName: processFields.numberField.label,
|
|
290
|
+
componentType: processFields.numberField.componentName,
|
|
291
|
+
op: 'GreaterThan',
|
|
292
|
+
value: 0,
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
childNodes: [
|
|
296
|
+
{
|
|
297
|
+
type: 'operator',
|
|
298
|
+
name: 'E2E 状态确认',
|
|
299
|
+
executor: 'originator',
|
|
300
|
+
formConfig: { behaviorList: editableStatus },
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
type: 'carbon',
|
|
308
|
+
name: 'E2E 结果抄送',
|
|
309
|
+
approver: 'originator',
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function buildOfficialProcessNodeFixture(context = {}) {
|
|
316
|
+
return {
|
|
317
|
+
publishable: false,
|
|
318
|
+
note: 'Fixture only: advanced official nodes require real tenant-specific props before publishing.',
|
|
319
|
+
nodes: [
|
|
320
|
+
{
|
|
321
|
+
type: 'connector',
|
|
322
|
+
name: 'E2E Connector placeholder',
|
|
323
|
+
connectorRules: {
|
|
324
|
+
connectorId: 'G-CONN-E2E',
|
|
325
|
+
actionId: 'G-ACT-E2E',
|
|
326
|
+
connector: { mode: 1 },
|
|
327
|
+
inputs: { assignments: [] },
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
componentName: 'GetSingleDataNode',
|
|
332
|
+
name: 'E2E Get data placeholder',
|
|
333
|
+
getData: { sourceId: context.formUuid || 'FORM-E2E', quantity: 1, assignments: [] },
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
componentName: 'JavaScriptNode',
|
|
337
|
+
name: 'E2E JavaScript placeholder',
|
|
338
|
+
JavaScript: { action: { code: 'return inputs;' }, outputs: [] },
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
componentName: 'SendMessageNode',
|
|
342
|
+
name: 'E2E Message placeholder',
|
|
343
|
+
sendMessageRules: { messageType: 'workNotice', messageInfo: { title: 'E2E', content: 'Process fixture' } },
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
componentName: 'CycleContainer',
|
|
347
|
+
name: 'E2E Cycle placeholder',
|
|
348
|
+
cycleContainerRules: { sourceId: 'node-source-placeholder' },
|
|
349
|
+
children: [
|
|
350
|
+
{
|
|
351
|
+
componentName: 'JavaScriptNode',
|
|
352
|
+
name: 'E2E Cycle child',
|
|
353
|
+
JavaScript: { action: { code: 'return inputs;' }, outputs: [] },
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
componentName: 'AINode',
|
|
359
|
+
name: 'E2E AI placeholder',
|
|
360
|
+
workFlowRules: { flowId: 'FLOW-E2E', outputs: [], yidaFieldIdList: [] },
|
|
361
|
+
},
|
|
362
|
+
],
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
196
366
|
function buildResultApp(context, resultAppName) {
|
|
197
367
|
if (!context.appType) {return null;}
|
|
198
368
|
const baseUrl = 'https://www.aliwork.com';
|
|
@@ -454,11 +624,17 @@ var CHECKS = [
|
|
|
454
624
|
'Report and form resource IDs displayed'
|
|
455
625
|
];
|
|
456
626
|
|
|
627
|
+
var TIME_FILTERS = ['今日', '本周', '本月', '全链路'];
|
|
628
|
+
|
|
629
|
+
function captureLabel(style) {
|
|
630
|
+
return <span className="sl-no-capture" style={style}>截图</span>;
|
|
631
|
+
}
|
|
632
|
+
|
|
457
633
|
function kpiCard(item, index) {
|
|
458
634
|
var colors = ['#2563eb', '#16a34a', '#7c3aed', '#d97706'];
|
|
459
635
|
return (
|
|
460
636
|
<div key={item.label} style={{ background: '#fff', border: '1px solid #d9e2ef', borderRadius: 8, padding: 18, minHeight: 126, position: 'relative' }}>
|
|
461
|
-
|
|
637
|
+
{captureLabel({ position: 'absolute', top: 12, right: 12, height: 28, lineHeight: '28px', border: '1px solid #d0d7e2', borderRadius: 6, background: '#fff', color: '#344054', padding: '0 10px', fontSize: 13, fontWeight: 800 })}
|
|
462
638
|
<div style={{ color: '#64748b', fontSize: 13, fontWeight: 700 }}>{item.label}</div>
|
|
463
639
|
<div style={{ marginTop: 16 }}><span style={{ color: colors[index % colors.length], fontSize: 34, fontWeight: 850 }}>{item.value}</span><span style={{ color: '#667085', marginLeft: 6 }}>{item.unit}</span></div>
|
|
464
640
|
<div style={{ marginTop: 8, color: '#16a34a', fontSize: 13, fontWeight: 800 }}>{item.trend}</div>
|
|
@@ -471,7 +647,7 @@ function chartPanel(title, rows) {
|
|
|
471
647
|
<section style={{ background: '#fff', border: '1px solid #d9e2ef', borderRadius: 8, padding: 18, minHeight: 238 }}>
|
|
472
648
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
|
|
473
649
|
<div style={{ fontSize: 18, fontWeight: 850 }}>{title}</div>
|
|
474
|
-
|
|
650
|
+
{captureLabel({ display: 'inline-flex', alignItems: 'center', height: 30, border: '1px solid #d0d7e2', borderRadius: 6, background: '#fff', color: '#344054', padding: '0 10px', fontSize: 13, fontWeight: 800 })}
|
|
475
651
|
</div>
|
|
476
652
|
{rows.map(function (row) {
|
|
477
653
|
return (
|
|
@@ -486,6 +662,7 @@ function chartPanel(title, rows) {
|
|
|
486
662
|
}
|
|
487
663
|
|
|
488
664
|
export default function Page() {
|
|
665
|
+
const [activeFilter, setActiveFilter] = useState('全链路');
|
|
489
666
|
return (
|
|
490
667
|
<div style={{ minHeight: '100vh', background: '#f4f7fb', color: '#172033', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', padding: 28, boxSizing: 'border-box' }}>
|
|
491
668
|
<div style={{ maxWidth: 1280, margin: '0 auto' }}>
|
|
@@ -498,7 +675,7 @@ export default function Page() {
|
|
|
498
675
|
<div style={{ background: '#dcfce7', color: '#166534', border: '1px solid #86efac', borderRadius: 999, padding: '8px 14px', fontWeight: 850, fontSize: 13 }}>PASSED</div>
|
|
499
676
|
</header>
|
|
500
677
|
<section style={{ display: 'flex', flexWrap: 'wrap', gap: 10, background: '#fff', border: '1px solid #d9e2ef', borderRadius: 8, padding: 12, marginBottom: 14 }}>
|
|
501
|
-
{
|
|
678
|
+
{TIME_FILTERS.map(function (label) { return <button key={label} type="button" onClick={() => setActiveFilter(label)} style={{ height: 32, padding: '0 12px', border: label === activeFilter ? '1px solid #2563eb' : '1px solid #d0d7e2', borderRadius: 6, background: label === activeFilter ? '#eff6ff' : '#fff', color: label === activeFilter ? '#1d4ed8' : '#344054', fontWeight: 800 }}>{label}</button>; })}
|
|
502
679
|
</section>
|
|
503
680
|
<section style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(210px, 1fr))', gap: 14, marginBottom: 14 }}>{KPIS.map(kpiCard)}</section>
|
|
504
681
|
<section style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))', gap: 14, marginBottom: 14 }}>
|
|
@@ -556,8 +733,11 @@ var RISKS = [
|
|
|
556
733
|
{ level: '中', title: '华南费用率偏高', owner: '财务 BP', action: '复盘费用结构' }
|
|
557
734
|
];
|
|
558
735
|
|
|
736
|
+
var BUSINESS_TIME_FILTERS = ['今日', '本周', '本月', 'FY2026'];
|
|
737
|
+
var BUSINESS_REGION_FILTERS = ['全球', '华东', '华南', '海外'];
|
|
738
|
+
|
|
559
739
|
function captureButton() {
|
|
560
|
-
return <
|
|
740
|
+
return <span className="sl-no-capture" style={{ display: 'inline-flex', alignItems: 'center', height: 28, border: '1px solid rgba(255,255,255,0.28)', borderRadius: 999, background: 'rgba(255,255,255,0.12)', color: '#fff', padding: '0 12px', fontWeight: 800, fontSize: 13 }}>截图</span>;
|
|
561
741
|
}
|
|
562
742
|
|
|
563
743
|
function kpiCard(item) {
|
|
@@ -577,7 +757,7 @@ function chartPanel(item, index) {
|
|
|
577
757
|
<section key={item.title} style={{ borderRadius: 18, padding: 18, background: '#ffffff', border: '1px solid #eadfd4', minHeight: 220, boxShadow: '0 14px 36px rgba(121,85,54,0.10)' }}>
|
|
578
758
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
|
|
579
759
|
<h3 style={{ margin: 0, color: '#1f2937', fontSize: 17, fontWeight: 900 }}>{item.title}</h3>
|
|
580
|
-
<
|
|
760
|
+
<span className="sl-no-capture" style={{ display: 'inline-flex', alignItems: 'center', height: 28, border: '1px solid #fed7aa', borderRadius: 999, background: '#fff7ed', color: '#c2410c', padding: '0 10px', fontWeight: 800, fontSize: 13 }}>截图</span>
|
|
581
761
|
</div>
|
|
582
762
|
{item.rows.map(function (row) {
|
|
583
763
|
return (
|
|
@@ -597,12 +777,14 @@ function riskRow(item) {
|
|
|
597
777
|
<span style={{ display: 'inline-flex', width: 32, height: 32, borderRadius: 999, background: item.level === '高' ? '#ef4444' : '#f59e0b', color: '#fff', alignItems: 'center', justifyContent: 'center', fontWeight: 900 }}>{item.level}</span>
|
|
598
778
|
<strong style={{ color: '#fff' }}>{item.title}</strong>
|
|
599
779
|
<span style={{ color: '#cbd5e1' }}>{item.owner}</span>
|
|
600
|
-
<
|
|
780
|
+
<span className="sl-no-capture" style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', height: 30, border: '1px solid rgba(255,255,255,0.26)', borderRadius: 999, background: 'rgba(255,255,255,0.10)', color: '#fff', fontWeight: 800 }}>{item.action}</span>
|
|
601
781
|
</div>
|
|
602
782
|
);
|
|
603
783
|
}
|
|
604
784
|
|
|
605
785
|
export default function Page() {
|
|
786
|
+
const [activeTime, setActiveTime] = useState('FY2026');
|
|
787
|
+
const [activeRegion, setActiveRegion] = useState('全球');
|
|
606
788
|
return (
|
|
607
789
|
<main style={{ minHeight: '100vh', background: 'linear-gradient(135deg, #fff7ed 0%, #eff6ff 42%, #f8fafc 100%)', padding: 28, boxSizing: 'border-box', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' }}>
|
|
608
790
|
<div style={{ maxWidth: 1440, margin: '0 auto' }}>
|
|
@@ -622,9 +804,9 @@ export default function Page() {
|
|
|
622
804
|
</header>
|
|
623
805
|
|
|
624
806
|
<section style={{ display: 'flex', flexWrap: 'wrap', gap: 10, alignItems: 'center', padding: 14, borderRadius: 18, background: 'rgba(255,255,255,0.84)', border: '1px solid #e5e7eb', marginBottom: 18 }}>
|
|
625
|
-
{
|
|
807
|
+
{BUSINESS_TIME_FILTERS.map(function (label) { return <button key={label} type="button" onClick={() => setActiveTime(label)} style={{ height: 34, border: label === activeTime ? '1px solid #f97316' : '1px solid #cbd5e1', borderRadius: 999, background: label === activeTime ? '#fff7ed' : '#fff', color: label === activeTime ? '#c2410c' : '#334155', padding: '0 14px', fontWeight: 850 }}>{label}</button>; })}
|
|
626
808
|
<span style={{ color: '#94a3b8' }}>|</span>
|
|
627
|
-
{
|
|
809
|
+
{BUSINESS_REGION_FILTERS.map(function (label) { return <button key={label} type="button" onClick={() => setActiveRegion(label)} style={{ height: 34, border: '1px solid #dbeafe', borderRadius: 999, background: label === activeRegion ? '#eff6ff' : '#fff', color: '#1d4ed8', padding: '0 14px', fontWeight: 850 }}>{label}</button>; })}
|
|
628
810
|
</section>
|
|
629
811
|
|
|
630
812
|
<section style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 16, marginBottom: 18 }}>{KPIS.map(kpiCard)}</section>
|
|
@@ -889,6 +1071,12 @@ function recordConfiguredStageResults(registry, registryPath, config, context, w
|
|
|
889
1071
|
summary: 'Formula, doctor, sample and CDN config offline checks verified',
|
|
890
1072
|
resources: [],
|
|
891
1073
|
},
|
|
1074
|
+
process: {
|
|
1075
|
+
commands: ['create-process', 'configure-process'],
|
|
1076
|
+
summary: `Process form configured and republished: ${context.processCode || 'n/a'}`,
|
|
1077
|
+
resources: ['process'],
|
|
1078
|
+
artifacts: ['process-definition', 'process-rule-definition', 'process-official-node-fixture'],
|
|
1079
|
+
},
|
|
892
1080
|
'connector-local': {
|
|
893
1081
|
commands: ['connector-gen-template', 'connector-parse-api'],
|
|
894
1082
|
summary: 'Connector template generation and cURL parsing verified locally',
|
|
@@ -948,6 +1136,9 @@ function run(options = {}) {
|
|
|
948
1136
|
businessDashboardFormUuid: null,
|
|
949
1137
|
businessDashboardSharePath: null,
|
|
950
1138
|
importAppType: null,
|
|
1139
|
+
processCode: null,
|
|
1140
|
+
processId: null,
|
|
1141
|
+
processVersion: null,
|
|
951
1142
|
fields: [],
|
|
952
1143
|
};
|
|
953
1144
|
|
|
@@ -1200,6 +1391,61 @@ function run(options = {}) {
|
|
|
1200
1391
|
runStep('flash-to-prd', ['flash-to-prd', '--file', flashNotePath, '--name', `${config.prefix} PRD`], { allowNoJson: true });
|
|
1201
1392
|
}
|
|
1202
1393
|
|
|
1394
|
+
if (hasStage(config.stages, 'process')) {
|
|
1395
|
+
if (!context.appType || !context.formUuid) {
|
|
1396
|
+
throw new Error('Process stage requires app and form stages');
|
|
1397
|
+
}
|
|
1398
|
+
const processCreateDefinitionPath = writeJsonFile(
|
|
1399
|
+
path.join(workDir, 'process-create-definition.json'),
|
|
1400
|
+
buildProcessCreateDefinition(context.fields),
|
|
1401
|
+
);
|
|
1402
|
+
const processRuleDefinitionPath = writeJsonFile(
|
|
1403
|
+
path.join(workDir, 'process-rule-definition.json'),
|
|
1404
|
+
buildProcessRuleDefinition(context.fields),
|
|
1405
|
+
);
|
|
1406
|
+
const officialNodeFixturePath = writeJsonFile(
|
|
1407
|
+
path.join(workDir, 'process-official-node-fixture.json'),
|
|
1408
|
+
buildOfficialProcessNodeFixture(context),
|
|
1409
|
+
);
|
|
1410
|
+
registry.artifacts = registry.artifacts || [];
|
|
1411
|
+
registry.artifacts.push(
|
|
1412
|
+
{ type: 'process-definition', path: processCreateDefinitionPath },
|
|
1413
|
+
{ type: 'process-rule-definition', path: processRuleDefinitionPath },
|
|
1414
|
+
{ type: 'process-official-node-fixture', path: officialNodeFixturePath },
|
|
1415
|
+
);
|
|
1416
|
+
persistRegistry(registryPath, registry);
|
|
1417
|
+
|
|
1418
|
+
const processCreate = runStep('create-process', [
|
|
1419
|
+
'create-process',
|
|
1420
|
+
context.appType,
|
|
1421
|
+
'--formUuid',
|
|
1422
|
+
context.formUuid,
|
|
1423
|
+
processCreateDefinitionPath,
|
|
1424
|
+
]).json;
|
|
1425
|
+
context.processCode = processCreate.processCode;
|
|
1426
|
+
if (!context.processCode) {
|
|
1427
|
+
throw new Error(`create-process did not return processCode: ${JSON.stringify(processCreate)}`);
|
|
1428
|
+
}
|
|
1429
|
+
trackResource(registry, registryPath, {
|
|
1430
|
+
type: 'process',
|
|
1431
|
+
appType: context.appType,
|
|
1432
|
+
formUuid: context.formUuid,
|
|
1433
|
+
processCode: context.processCode,
|
|
1434
|
+
name: `${config.prefix}_Process`,
|
|
1435
|
+
url: processCreate.url,
|
|
1436
|
+
});
|
|
1437
|
+
|
|
1438
|
+
const processRule = runStep('configure-process', [
|
|
1439
|
+
'configure-process',
|
|
1440
|
+
context.appType,
|
|
1441
|
+
context.formUuid,
|
|
1442
|
+
processRuleDefinitionPath,
|
|
1443
|
+
context.processCode,
|
|
1444
|
+
]).json;
|
|
1445
|
+
context.processId = processRule.processId || null;
|
|
1446
|
+
context.processVersion = processRule.processVersion || null;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1203
1449
|
if (hasStage(config.stages, 'connector-local')) {
|
|
1204
1450
|
const templatePath = path.join(workDir, 'api-template.md');
|
|
1205
1451
|
runStep('connector-gen-template', ['connector', 'gen-template', templatePath], { allowNoJson: true });
|
|
@@ -1305,6 +1551,9 @@ module.exports = {
|
|
|
1305
1551
|
buildDashboardSource,
|
|
1306
1552
|
buildDashboardSkillSource,
|
|
1307
1553
|
buildBusinessDashboardSource,
|
|
1554
|
+
buildOfficialProcessNodeFixture,
|
|
1555
|
+
buildProcessCreateDefinition,
|
|
1556
|
+
buildProcessRuleDefinition,
|
|
1308
1557
|
collectFields,
|
|
1309
1558
|
fieldByLabel,
|
|
1310
1559
|
findValueByKeys,
|
|
@@ -22,7 +22,7 @@ const SKILL_COVERAGE = {
|
|
|
22
22
|
'yida-create-app': { level: 'real-e2e', stages: ['app'], commands: ['create-app'] },
|
|
23
23
|
'yida-create-form-page': { level: 'real-e2e', stages: ['form'], commands: ['create-form create', 'create-form update', 'create-form add-option'] },
|
|
24
24
|
'yida-create-page': { level: 'real-e2e', stages: ['page', 'dashboard'], commands: ['create-page --mode dashboard'] },
|
|
25
|
-
'yida-create-process': { level: 'opt-in', reason: '
|
|
25
|
+
'yida-create-process': { level: 'opt-in-real-e2e', stages: ['process'], commands: ['create-process --formUuid'], reason: 'process stage mutates workflow definitions and is excluded from default full E2E unless explicitly requested' },
|
|
26
26
|
'yida-custom-page': { level: 'real-e2e', stages: ['page'], commands: ['check-page', 'build-page', 'compile', 'publish'] },
|
|
27
27
|
'yida-dashboard': { level: 'real-e2e', stages: ['dashboard'], commands: ['create-page --mode dashboard', 'publish dashboard skill page'] },
|
|
28
28
|
'yida-data-management': { level: 'real-e2e', stages: ['data', 'task'], commands: ['data create/query/update form', 'data query tasks'] },
|
|
@@ -44,7 +44,7 @@ const SKILL_COVERAGE = {
|
|
|
44
44
|
'yida-page-config': { level: 'real-e2e', stages: ['share'], commands: ['get-page-config', 'verify-short-url', 'save-share-config'] },
|
|
45
45
|
'yida-ppt': { level: 'deprecated', reason: 'skill is deprecated in favor of yida-ppt-slider' },
|
|
46
46
|
'yida-ppt-slider': { level: 'offline-unit', reason: 'presentation-style custom page skill should be validated by page generation/check-page fixtures' },
|
|
47
|
-
'yida-process-rule': { level: 'opt-in', reason: 'publishes workflow rules
|
|
47
|
+
'yida-process-rule': { level: 'opt-in-real-e2e', stages: ['process'], commands: ['configure-process'], reason: 'process stage publishes workflow rules on the disposable E2E form and is excluded from default full E2E unless explicitly requested' },
|
|
48
48
|
'yida-publish-page': { level: 'real-e2e', stages: ['page', 'dashboard'], commands: ['publish --health-check'] },
|
|
49
49
|
'yida-report': { level: 'real-e2e', stages: ['report'], commands: ['create-report', 'append-chart'] },
|
|
50
50
|
'yida-table-form': { level: 'offline-unit', reason: 'table-form custom page template should be validated with check-page fixture before real publish stage is added' },
|
package/yida-skills/SKILL.md
CHANGED
|
@@ -182,7 +182,7 @@ openyida copy
|
|
|
182
182
|
| `yida-data-management` | `skills/yida-data-management/SKILL.md` | 表单/流程/任务数据查询与变更 | `openyida data query form <appType> <formUuid>` |
|
|
183
183
|
| `yida-corp-efficiency` | `skills/yida-corp-efficiency/SKILL.md` | 平台管理企业效能概览、查看明细报表、报表接口模板、学习成果和通知群动作 | `openyida corp-efficiency` |
|
|
184
184
|
| `yida-table-form` | `skills/yida-table-form/SKILL.md` | 表格形态批量录入页面 | 详见 SKILL.md |
|
|
185
|
-
| `yida-process-rule` | `skills/yida-process-rule/SKILL.md` |
|
|
185
|
+
| `yida-process-rule` | `skills/yida-process-rule/SKILL.md` | 配置流程规则、审批/办理/抄送、条件/并行分支、字段权限、跳转规则和官方组件节点配置适配 | `openyida configure-process <appType> <formUuid> <流程JSON>` |
|
|
186
186
|
| `yida-integration` | `skills/yida-integration/SKILL.md` | 集成自动化逻辑流(创建/列表/启停) | `openyida integration <create\|list\|enable\|disable> ...` |
|
|
187
187
|
| `yida-business-rule` | `skills/yida-business-rule/SKILL.md` | 表单业务关联规则高级函数(INSERT/UPDATE/DELETE/UPSERT) | 详见 SKILL.md |
|
|
188
188
|
| `yida-connector` | `skills/yida-connector/SKILL.md` | HTTP 连接器创建、测试与动作管理 | `openyida connector smart-create <配置>` |
|
|
@@ -494,7 +494,7 @@ export function didMount() {
|
|
|
494
494
|
- [ ] 聚合指标(KPI、饼图、柱状图)通过 `getDataAsync.json` 报表接口获取
|
|
495
495
|
- [ ] 明细表格通过 `searchFormDatas` 获取(返回 `formInstId`,支持详情跳转)
|
|
496
496
|
- [ ] 包含 `didUnmount` 函数,清理 ECharts 实例和 resize 监听
|
|
497
|
-
- [ ]
|
|
497
|
+
- [ ] `renderJsx` 顶部定义 `var self = this`,事件绑定使用箭头函数包裹:`onClick={(e) => { self.xxx(e); }}`
|
|
498
498
|
|
|
499
499
|
---
|
|
500
500
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yida-create-process
|
|
3
|
-
description: 宜搭流程表单一体化创建。整合创建表单 → 转流程表单 → 获取 processCode →
|
|
3
|
+
description: 宜搭流程表单一体化创建。整合创建表单 → 转流程表单 → 获取 processCode → 配置流程四步为一步,流程定义格式与 yida-process-rule 完全一致,支持审批/办理/抄送、条件/并行分支、跳转规则,以及官方组件节点配置透传和 processJson 适配。不适用于:已有流程表单只需修改审批规则(应使用 yida-process-rule),或只需创建普通表单无审批(应使用 yida-create-form-page)。
|
|
4
4
|
---
|
|
5
5
|
# 流程表单一体化创建
|
|
6
6
|
|
|
@@ -78,7 +78,7 @@ openyida create-form create "APP_XXX" "订单处理表" .cache/openyida/order/or
|
|
|
78
78
|
openyida create-process "APP_XXX" --formUuid "FORM-YYY" .cache/openyida/order/process-definition.json
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
> 流程定义中的 `fieldId`
|
|
81
|
+
> 流程定义中的 `fieldId` 需在表单创建后确定。如流程不含条件分支、字段权限或数据节点字段映射,可用用法 1 一步到位。
|
|
82
82
|
|
|
83
83
|
## AI 自动生成流程特性
|
|
84
84
|
|
|
@@ -86,6 +86,7 @@ openyida create-process "APP_XXX" --formUuid "FORM-YYY" .cache/openyida/order/pr
|
|
|
86
86
|
|
|
87
87
|
1. **🔐 字段权限**:当字段 ≥ 3 且审批节点 ≥ 2 时,每个节点只允许编辑相关字段
|
|
88
88
|
2. **🔄 跳转规则**:存在回退/循环语义时,自动配置 `routeRules`
|
|
89
|
+
3. **🔀 并行/办理/高级组件**:需要并行会审、办理节点或连接器/数据/消息等官方组件节点时,流程定义格式直接参考 `yida-process-rule`
|
|
89
90
|
|
|
90
91
|
详见 `yida-process-rule` 的 SKILL.md。
|
|
91
92
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yida-custom-page
|
|
3
|
-
description: 宜搭自定义页面 JSX 开发规范。React 16
|
|
3
|
+
description: 宜搭自定义页面 JSX 开发规范。React 16 宜搭原生 export function 页面模式,宜搭 JS API 调用,状态管理与编码约束。不适用于:原生表单页面开发(无需 JSX),或发布页面(编写完成后需使用 yida-publish-page 发布)。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 自定义页面开发
|
|
@@ -21,6 +21,8 @@ description: 宜搭自定义页面 JSX 开发规范。React 16 类组件模式
|
|
|
21
21
|
8. **所有 API 调用必须 .catch()**:异常通过 `this.utils.toast({ title: message, type: 'error' })` 提示用户
|
|
22
22
|
9. **renderJsx 每个 return 分支必须渲染 timestamp**:`<div style={{ display: 'none' }}>{this.state && this.state.timestamp}</div>`;`.oyd.jsx` 构建会自动补齐,但生成原生写法时仍必须显式写出
|
|
23
23
|
10. **禁止 ES6 计算属性名**:不要写 `{ [key]: value }`、`{ [FIELDS.xxx]: value }` 或 `setCustomState({ [key]: value })`;宜搭运行时可能静默白屏,`check-page` 会以 `computed-property` error 阻塞。改用 `var obj = {}; obj[key] = value;`
|
|
24
|
+
11. **生命周期名称大小写固定**:只允许 `export function didMount()` 与 `export function didUnmount()`;`didmount`、`componentDidMount`、`componentWillUnmount` 会被 `check-page` 阻塞
|
|
25
|
+
12. **按钮必须真的绑定事件**:禁止 `onclick` 小写属性、`onClick={self.save()}`、`onClick={(e) => self.save}`、`<button>静态标签</button>` 等看起来有按钮但不会正确绑定的写法;统一使用 `onClick={(e) => { self.save(e); }}`。如果只是状态标签/截图标记,用 `span`/`div`,不要用 `button`
|
|
24
26
|
|
|
25
27
|
### 重要规则(IMPORTANT)
|
|
26
28
|
|
|
@@ -62,9 +64,11 @@ description: 宜搭自定义页面 JSX 开发规范。React 16 类组件模式
|
|
|
62
64
|
|
|
63
65
|
| 异常场景 | 处理方式 |
|
|
64
66
|
|---------|----------|
|
|
65
|
-
| 在原生 `renderJsx` 页面里使用了 React Hooks |
|
|
67
|
+
| 在原生 `renderJsx` 页面里使用了 React Hooks | 改为宜搭原生 `export function` + `_customState` 模式;或改用 `.oyd.jsx` 的 `export default function Page()` authoring 模式,并确认只使用受支持的 `useState` / `useEffect(..., [])` |
|
|
66
68
|
| 字段 ID 不确定 | 执行 `openyida get-schema` 获取真实 fieldId |
|
|
67
69
|
| `forceUpdate is not a function` | 检查 `this` 绑定,确认方法用 `export function` 定义 |
|
|
70
|
+
| didMount / didUnmount 报错或没有执行 | 检查是否写成了 `didmount`、`componentDidMount` 等错误名称;运行 `openyida check-page <file> --json` 查看 `lifecycle-case` / `react-lifecycle-method` |
|
|
71
|
+
| 按钮点不了 | 检查是否用了小写 `onclick`、渲染期调用 `onClick={self.xxx()}`、只引用不调用 `onClick={(e) => self.xxx}`、或 `<button>` 根本没有事件;运行 `openyida check-page <file>` 会阻塞这些写法 |
|
|
68
72
|
| API 调用无响应 | 确认 `.catch()` 错误处理,检查登录态 |
|
|
69
73
|
| 发布后页面空白 | 检查 `renderJsx` 是否正确导出,查看浏览器控制台 |
|
|
70
74
|
|
|
@@ -186,6 +190,7 @@ openyida publish project/pages/src/employee-query.oyd.jsx APP_XXX FORM-QUERY001
|
|
|
186
190
|
```
|
|
187
191
|
|
|
188
192
|
> **生成代码时的自检清单**:检查 `renderJsx` 中所有 `onClick`、`onChange`、`onSubmit` 等事件属性,确保每一个都是 `(e) => { self.xxx(e) }` 形式,不存在任何 `onClick={this.xxx}` 或 `.bind(this)` 的写法。
|
|
193
|
+
> `check-page` 会阻塞四类“按钮看得到但点不了”的 IDE 常见误写:小写 `onclick`、渲染时直接执行 `onClick={self.xxx()}`、箭头函数只返回方法引用 `onClick={(e) => self.xxx}`、可见 `<button>` 没有任何事件。静态徽标、状态胶囊、截图排除标记一律用 `span`/`div`。
|
|
189
194
|
|
|
190
195
|
```javascript
|
|
191
196
|
// ❌ 错误③:在 .map(function(){}) 普通函数回调中使用箭头函数事件处理器,this 已在 function 回调里丢失,箭头函数捕获的 this 是 undefined!
|