openxiangda 1.0.27 → 1.0.29
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/openxiangda-skills/SKILL.md +1 -1
- package/openxiangda-skills/references/component-guide.md +12 -12
- package/openxiangda-skills/references/style-system.md +222 -492
- package/openxiangda-skills/skills/openxiangda-page/SKILL.md +2 -2
- package/package.json +1 -1
- package/packages/sdk/src/build-source/scripts/build-forms.mjs +2 -0
- package/packages/sdk/src/build-source/scripts/build-pages.mjs +2 -0
- package/packages/sdk/src/build-source/scripts/utils/tailwind-config.mjs +9 -6
- package/packages/sdk/src/build-source/scripts/utils/tailwind-config.test.ts +20 -4
- package/packages/sdk/src/build-source/scripts/utils/tailwind-token-warnings.mjs +146 -0
- package/packages/sdk/src/build-source/scripts/utils/tailwind-token-warnings.test.ts +122 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/design-style.md +9 -2
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/styles.css +5 -5
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/styles.css +2 -2
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/styles.css +10 -10
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/styles.css +9 -9
- package/templates/sy-lowcode-app-workspace/src/index.css +2 -4
- package/templates/sy-lowcode-app-workspace/tailwind.config.cjs +7 -6
|
@@ -1,492 +1,222 @@
|
|
|
1
|
-
# OpenXiangda 样式体系参考
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
##
|
|
203
|
-
|
|
204
|
-
`
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
### 4.2 间距 / 布局类
|
|
225
|
-
|
|
226
|
-
| Tailwind 类 | 等价 CSS |
|
|
227
|
-
|---|---|
|
|
228
|
-
| `gap-form` | `gap: var(--sy-form-gap)` |
|
|
229
|
-
| `p-form` | `padding: var(--sy-form-padding)` |
|
|
230
|
-
| `px-form` / `py-form` | `padding-inline / padding-block: var(--sy-form-padding)` |
|
|
231
|
-
| `space-y-form > * + *` | `margin-top: var(--sy-form-gap)` |
|
|
232
|
-
| `h-field` | `height: var(--sy-form-field-height)` |
|
|
233
|
-
|
|
234
|
-
### 4.3 圆角 / 阴影 / 字号
|
|
235
|
-
|
|
236
|
-
| Tailwind 类 | 等价 CSS |
|
|
237
|
-
|---|---|
|
|
238
|
-
| `rounded-form` | `border-radius: var(--sy-radius-md)` |
|
|
239
|
-
| `rounded-card` | `border-radius: var(--sy-radius-lg)` |
|
|
240
|
-
| `rounded-pill` | `border-radius: var(--sy-radius-sm)` |
|
|
241
|
-
| `shadow-card` | `box-shadow: var(--sy-shadow-md)` |
|
|
242
|
-
| `shadow-popover` | `box-shadow: var(--sy-shadow-lg)` |
|
|
243
|
-
| `shadow-subtle` | `box-shadow: var(--sy-shadow-sm)` |
|
|
244
|
-
| `text-sm-sy` | `font-size: var(--sy-font-size-sm)` |
|
|
245
|
-
| `text-base-sy` | `font-size: var(--sy-font-size-base)` |
|
|
246
|
-
| `text-lg-sy` | `font-size: var(--sy-font-size-lg)` |
|
|
247
|
-
| `text-xl-sy` | `font-size: var(--sy-font-size-xl)` |
|
|
248
|
-
| `text-2xl-sy` | `font-size: var(--sy-font-size-2xl)` |
|
|
249
|
-
|
|
250
|
-
> 通用 Tailwind 数值类(如 `p-4`、`text-sm`)仍可使用,但**当存在语义类时优先用语义类**。
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## 5. 禁止规则(AI Agent 必须遵守)
|
|
255
|
-
|
|
256
|
-
| # | 规则 | 反例 | 正例 |
|
|
257
|
-
|---|---|---|---|
|
|
258
|
-
| 1 | **禁止硬编码颜色** | `color: #333`、`className="bg-[#1677ff]"` | `text-default`、`bg-container` 或 `var(--sy-color-primary)` |
|
|
259
|
-
| 2 | **禁止硬编码间距** | `padding: 16px`、`className="p-[24px]"` | `p-form`、`var(--sy-spacing-md)` |
|
|
260
|
-
| 3 | **禁止用数值类替代语义类** | `className="rounded-md gap-4"`(用于表单时)| `className="rounded-form gap-form"` |
|
|
261
|
-
| 4 | **禁止内联颜色/间距** | `<div style={{ color: '#1677ff', padding: 16 }}>` | `<div className="text-primary p-form">` |
|
|
262
|
-
| 5 | **禁止绕过 ConfigProvider 直接覆盖 antd 类名** | `.ant-btn { background: red }` | 通过 `theme.token.colorPrimary` 或自定义类组合 |
|
|
263
|
-
| 6 | **禁止 antd 弹层挂到 body** | 默认行为 | 通过 `getPopupContainer` 锚定到 `.sy-app-workspace` |
|
|
264
|
-
| 7 | **禁止在样式中假设白色/黑色背景** | `color: #fff`(在深色主题失效)| `text-default`,让 Token 决定 |
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## 6. 正确示例 vs 错误示例
|
|
269
|
-
|
|
270
|
-
### 示例 1:主操作按钮的容器
|
|
271
|
-
|
|
272
|
-
```tsx
|
|
273
|
-
// ❌ 错误:硬编码颜色 + 硬编码间距
|
|
274
|
-
<div style={{ background: '#fff', padding: 24, borderRadius: 6 }}>
|
|
275
|
-
<button style={{ background: '#1677ff', color: '#fff' }}>提交</button>
|
|
276
|
-
</div>
|
|
277
|
-
|
|
278
|
-
// ✅ 正确:语义类 + antd 组件
|
|
279
|
-
<div className="bg-container p-form rounded-form">
|
|
280
|
-
<Button type="primary">提交</Button>
|
|
281
|
-
</div>
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### 示例 2:表单字段布局
|
|
285
|
-
|
|
286
|
-
```tsx
|
|
287
|
-
// ❌ 错误:随意数值类
|
|
288
|
-
<div className="flex flex-col gap-[16px] p-[24px]">
|
|
289
|
-
<Input className="h-[32px]" />
|
|
290
|
-
<Input className="h-[32px]" />
|
|
291
|
-
</div>
|
|
292
|
-
|
|
293
|
-
// ✅ 正确:表单语义类
|
|
294
|
-
<div className="flex flex-col gap-form p-form">
|
|
295
|
-
<Input />
|
|
296
|
-
<Input />
|
|
297
|
-
</div>
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### 示例 3:状态文案
|
|
301
|
-
|
|
302
|
-
```tsx
|
|
303
|
-
// ❌ 错误:直接写颜色值
|
|
304
|
-
<span style={{ color: '#52c41a' }}>已通过</span>
|
|
305
|
-
<span style={{ color: '#ff4d4f' }}>已驳回</span>
|
|
306
|
-
|
|
307
|
-
// ✅ 正确:状态语义类
|
|
308
|
-
<span className="text-success">已通过</span>
|
|
309
|
-
<span className="text-error">已驳回</span>
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### 示例 4:卡片容器
|
|
313
|
-
|
|
314
|
-
```tsx
|
|
315
|
-
// ❌ 错误:阴影硬编码
|
|
316
|
-
<div style={{
|
|
317
|
-
background: '#fff',
|
|
318
|
-
boxShadow: '0 6px 16px rgba(0,0,0,0.08)',
|
|
319
|
-
borderRadius: 8
|
|
320
|
-
}}>...</div>
|
|
321
|
-
|
|
322
|
-
// ✅ 正确:语义类
|
|
323
|
-
<div className="bg-container shadow-card rounded-card">...</div>
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### 示例 5:次要文本 + 提示
|
|
327
|
-
|
|
328
|
-
```tsx
|
|
329
|
-
// ❌ 错误:rgba 硬编码
|
|
330
|
-
<p style={{ color: 'rgba(0,0,0,0.65)', fontSize: 12 }}>提示信息</p>
|
|
331
|
-
|
|
332
|
-
// ✅ 正确:层级语义
|
|
333
|
-
<p className="text-secondary text-sm-sy">提示信息</p>
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
### 示例 6:自定义代码节点的 CSS(局部样式表)
|
|
337
|
-
|
|
338
|
-
```css
|
|
339
|
-
/* ❌ 错误 */
|
|
340
|
-
.my-node-card {
|
|
341
|
-
background: #ffffff;
|
|
342
|
-
border: 1px solid #d9d9d9;
|
|
343
|
-
padding: 16px;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/* ✅ 正确 */
|
|
347
|
-
.sy-app-workspace .my-node-card {
|
|
348
|
-
background: var(--sy-color-bg-container);
|
|
349
|
-
border: 1px solid var(--sy-color-border);
|
|
350
|
-
padding: var(--sy-spacing-md);
|
|
351
|
-
border-radius: var(--sy-radius-md);
|
|
352
|
-
}
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
---
|
|
356
|
-
|
|
357
|
-
## 7. 自定义主题
|
|
358
|
-
|
|
359
|
-
### 7.1 全局主题切换
|
|
360
|
-
|
|
361
|
-
直接覆盖 `.sy-app-workspace` 上的 CSS 变量即可,**无需重新构建**:
|
|
362
|
-
|
|
363
|
-
```css
|
|
364
|
-
/* 应用 A —— 默认蓝 */
|
|
365
|
-
.sy-app-workspace.theme-default {
|
|
366
|
-
--sy-color-primary: #1677ff;
|
|
367
|
-
--sy-color-primary-hover: #4096ff;
|
|
368
|
-
--sy-color-primary-active: #0958d9;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/* 应用 B —— 品牌绿 */
|
|
372
|
-
.sy-app-workspace.theme-brand-green {
|
|
373
|
-
--sy-color-primary: #00b96b;
|
|
374
|
-
--sy-color-primary-hover: #2fd58a;
|
|
375
|
-
--sy-color-primary-active: #008a4f;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/* 应用 C —— 暗色 */
|
|
379
|
-
.sy-app-workspace.theme-dark {
|
|
380
|
-
--sy-color-text: rgba(255, 255, 255, 0.88);
|
|
381
|
-
--sy-color-text-secondary: rgba(255, 255, 255, 0.65);
|
|
382
|
-
--sy-color-bg-container: #1f1f1f;
|
|
383
|
-
--sy-color-bg-layout: #141414;
|
|
384
|
-
--sy-color-border: #424242;
|
|
385
|
-
}
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
```tsx
|
|
389
|
-
// 运行时切换
|
|
390
|
-
document.querySelector('.sy-app-workspace')?.classList.toggle('theme-dark');
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
由于 antd token 与 Tailwind 语义类都引用相同 CSS 变量,**变量一改,三层全变**。
|
|
394
|
-
|
|
395
|
-
### 7.2 单应用差异化
|
|
396
|
-
|
|
397
|
-
不同应用可在自身 workspace 入口注入差异化变量:
|
|
398
|
-
|
|
399
|
-
```tsx
|
|
400
|
-
// app-workspace.config.ts(应用级)
|
|
401
|
-
export default {
|
|
402
|
-
theme: {
|
|
403
|
-
'--sy-color-primary': '#722ed1',
|
|
404
|
-
'--sy-radius-md': '10px',
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
入口处将 `theme` 对象 inline 到根容器 `style` 上即可。
|
|
410
|
-
|
|
411
|
-
---
|
|
412
|
-
|
|
413
|
-
## 8. CSS Namespace 下的特殊注意事项
|
|
414
|
-
|
|
415
|
-
### 8.1 根容器要求
|
|
416
|
-
|
|
417
|
-
```tsx
|
|
418
|
-
// 应用入口必须包裹 .sy-app-workspace
|
|
419
|
-
<div className="sy-app-workspace">
|
|
420
|
-
<AppThemeProvider>
|
|
421
|
-
<YourApp />
|
|
422
|
-
</AppThemeProvider>
|
|
423
|
-
</div>
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
### 8.2 Tailwind 配置(关键)
|
|
427
|
-
|
|
428
|
-
`tailwind.config.cjs` 中:
|
|
429
|
-
|
|
430
|
-
```js
|
|
431
|
-
module.exports = {
|
|
432
|
-
important: '.sy-app-workspace', // 所有 Tailwind 工具类都受命名空间限定
|
|
433
|
-
corePlugins: {
|
|
434
|
-
preflight: false, // 避免污染宿主页面
|
|
435
|
-
},
|
|
436
|
-
content: ['./src/**/*.{ts,tsx}'],
|
|
437
|
-
presets: [require('./tailwind-preset')],
|
|
438
|
-
};
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
`important: '.sy-app-workspace'` 让所有原子类输出形如 `.sy-app-workspace .text-primary { ... }`,自动隔离。
|
|
442
|
-
|
|
443
|
-
### 8.3 antd 弹层挂载
|
|
444
|
-
|
|
445
|
-
任何 `Modal` / `Drawer` / `Select` / `DatePicker` / `Tooltip` 等组件,**必须**通过 `ConfigProvider.getPopupContainer` 或局部 `getPopupContainer` 锚定到命名空间容器:
|
|
446
|
-
|
|
447
|
-
```tsx
|
|
448
|
-
<ConfigProvider
|
|
449
|
-
getPopupContainer={() =>
|
|
450
|
-
(document.querySelector('.sy-app-workspace') as HTMLElement) ?? document.body
|
|
451
|
-
}
|
|
452
|
-
>
|
|
453
|
-
...
|
|
454
|
-
</ConfigProvider>
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
否则弹层会挂到 `document.body`,导致 CSS 变量无法继承、Tailwind 工具类失效。
|
|
458
|
-
|
|
459
|
-
### 8.4 第三方组件库
|
|
460
|
-
|
|
461
|
-
引入第三方组件时,若其样式依赖全局 reset,需在 `.sy-app-workspace` 内手动补齐;不要依赖 Tailwind preflight。
|
|
462
|
-
|
|
463
|
-
### 8.5 字体与基础样式
|
|
464
|
-
|
|
465
|
-
基础 `font-family` / `line-height` 应在 `.sy-app-workspace` 上设置一次,避免逐组件重复:
|
|
466
|
-
|
|
467
|
-
```css
|
|
468
|
-
.sy-app-workspace {
|
|
469
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC',
|
|
470
|
-
'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
|
471
|
-
font-size: var(--sy-font-size-base);
|
|
472
|
-
color: var(--sy-color-text);
|
|
473
|
-
line-height: 1.5715;
|
|
474
|
-
}
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
---
|
|
478
|
-
|
|
479
|
-
## 速查 Cheatsheet
|
|
480
|
-
|
|
481
|
-
| 想做什么 | 用什么 |
|
|
482
|
-
|---|---|
|
|
483
|
-
| 主色按钮 | `<Button type="primary">` |
|
|
484
|
-
| 主色文本 | `className="text-primary"` |
|
|
485
|
-
| 卡片容器 | `className="bg-container shadow-card rounded-card p-form"` |
|
|
486
|
-
| 表单纵向布局 | `className="flex flex-col gap-form"` |
|
|
487
|
-
| 错误状态文本 | `className="text-error"` |
|
|
488
|
-
| 次要说明文本 | `className="text-secondary text-sm-sy"` |
|
|
489
|
-
| 浮层背景 | `className="bg-elevated shadow-popover"` |
|
|
490
|
-
| 分隔线 | `className="border-t border-secondary"` |
|
|
491
|
-
| 切换主题 | 改 `.sy-app-workspace` 的 CSS 变量 |
|
|
492
|
-
| 弹层挂载 | `getPopupContainer` 指向 `.sy-app-workspace` |
|
|
1
|
+
# OpenXiangda 样式体系参考
|
|
2
|
+
|
|
3
|
+
> 面向 AI Agent 的代码页、表单页和自定义节点样式基线。默认直接使用 Tailwind 原生工具类和 Tailwind 任意值;平台 token 是兼容能力和平台组件内部能力,不是业务页面的强制范式。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 默认规则
|
|
8
|
+
|
|
9
|
+
1. **业务页面默认写原生 Tailwind**:优先使用 `bg-white`、`border`、`border-slate-200`、`text-slate-600`、`shadow-sm`、`rounded-lg`、`p-4`、`gap-4`、`grid-cols-[240px_1fr]` 这类 Tailwind 原生类和任意值。
|
|
10
|
+
2. **不要强制平台 token**:不要把 `bg-container`、`text-secondary`、`rounded-form`、`shadow-card` 当默认示例或默认范式。历史项目或平台组件需要时可以兼容使用,但新业务页面不推荐主动依赖。
|
|
11
|
+
3. **不要直接套 shadcn token**:`bg-card`、`text-muted-foreground`、`text-foreground`、`bg-background` 等不是 Tailwind 原生类。除非项目已经在 `tailwind.config.cjs` 明确配置这些 token,否则必须改成 Tailwind 原生类或任意值。
|
|
12
|
+
4. **保留 OpenXiangda 隔离能力**:Tailwind 仍通过 `.sy-app-workspace` namespace 输出,workspace 仍扫描 `openxiangda` 包内容,平台组件 safelist 仍保留。
|
|
13
|
+
5. **CSS 作用域要收敛**:页面级 CSS 写在 `styles.css`,选择器限定在 `.sy-app-workspace` 或页面根类下,避免污染宿主平台。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 2. 推荐写法
|
|
18
|
+
|
|
19
|
+
### 2.1 页面容器
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
export function DashboardPage() {
|
|
23
|
+
return (
|
|
24
|
+
<main className="min-h-screen bg-slate-50 px-6 py-5 text-slate-900">
|
|
25
|
+
<section className="rounded-lg border border-slate-200 bg-white p-5 shadow-sm">
|
|
26
|
+
<h1 className="text-xl font-semibold">排队预约</h1>
|
|
27
|
+
<p className="mt-1 text-sm text-slate-600">查看排队申请、安排上机时间、处理冲突。</p>
|
|
28
|
+
</section>
|
|
29
|
+
</main>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2.2 卡片和状态
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<div className="rounded-lg border border-slate-200 bg-white p-4 shadow-sm">
|
|
38
|
+
<div className="text-sm text-slate-500">待分配</div>
|
|
39
|
+
<div className="mt-2 text-2xl font-semibold text-amber-700">2</div>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<span className="inline-flex rounded-full bg-emerald-50 px-2 py-0.5 text-xs font-medium text-emerald-700">
|
|
43
|
+
已完成
|
|
44
|
+
</span>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2.3 精确布局和品牌色
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<div className="grid min-h-[calc(100vh-64px)] grid-cols-[280px_1fr] gap-5">
|
|
51
|
+
<aside className="border-r border-slate-200 bg-white" />
|
|
52
|
+
<section className="bg-[#f7fafc] p-6" />
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<button className="rounded-md bg-[#1677ff] px-4 py-2 text-sm font-medium text-white hover:bg-[#0958d9]">
|
|
56
|
+
提交
|
|
57
|
+
</button>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2.4 局部 CSS
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
.sy-app-workspace .queue-booking-page {
|
|
64
|
+
min-height: 100%;
|
|
65
|
+
background: #f8fafc;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.sy-app-workspace .queue-booking-page__calendar-grid {
|
|
69
|
+
display: grid;
|
|
70
|
+
grid-template-columns: repeat(7, minmax(120px, 1fr));
|
|
71
|
+
gap: 12px;
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 3. Tailwind 配置要求
|
|
78
|
+
|
|
79
|
+
OpenXiangda workspace 的 `tailwind.config.cjs` 必须保留:
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
const openxiangdaPath = require("node:path");
|
|
83
|
+
const openxiangdaPresetModule = require("openxiangda/tailwind-preset");
|
|
84
|
+
const openxiangdaPreset =
|
|
85
|
+
openxiangdaPresetModule.default ?? openxiangdaPresetModule;
|
|
86
|
+
|
|
87
|
+
function resolveOpenXiangdaContent() {
|
|
88
|
+
try {
|
|
89
|
+
const packagePath = require.resolve("openxiangda");
|
|
90
|
+
const distDir = openxiangdaPath.dirname(packagePath);
|
|
91
|
+
return [openxiangdaPath.join(distDir, "..", "**/*.{js,mjs,cjs}")];
|
|
92
|
+
} catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const openxiangdaContent = resolveOpenXiangdaContent();
|
|
98
|
+
|
|
99
|
+
module.exports = {
|
|
100
|
+
content: [
|
|
101
|
+
"./index.html",
|
|
102
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
103
|
+
...openxiangdaContent,
|
|
104
|
+
],
|
|
105
|
+
blocklist: ["[-:T]", "[-:TZ.]"],
|
|
106
|
+
presets: [openxiangdaPreset],
|
|
107
|
+
theme: {
|
|
108
|
+
extend: {},
|
|
109
|
+
},
|
|
110
|
+
plugins: [],
|
|
111
|
+
};
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
这个配置的作用:
|
|
115
|
+
|
|
116
|
+
- `openxiangdaPreset` 保留 `.sy-app-workspace` namespace、平台组件 safelist 和平台组件需要的工具类。
|
|
117
|
+
- `...openxiangdaContent` 确保平台组件内部 class 会被 Tailwind 扫描到。
|
|
118
|
+
- `blocklist` 避免 Tailwind 误生成日期字符串相关的异常类。
|
|
119
|
+
|
|
120
|
+
不要为了“更自由”移除这些平台构建能力;自由写 Tailwind 原生类和保留构建隔离能力并不冲突。
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 4. 入口 CSS 要求
|
|
125
|
+
|
|
126
|
+
`src/index.css` 默认只需要 Tailwind 指令和少量基础样式:
|
|
127
|
+
|
|
128
|
+
```css
|
|
129
|
+
@layer tailwind-base {
|
|
130
|
+
@tailwind base;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@tailwind components;
|
|
134
|
+
@tailwind utilities;
|
|
135
|
+
|
|
136
|
+
* {
|
|
137
|
+
box-sizing: border-box;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
body {
|
|
141
|
+
margin: 0;
|
|
142
|
+
min-width: 320px;
|
|
143
|
+
background: #f8fafc;
|
|
144
|
+
color: #0f172a;
|
|
145
|
+
font-family:
|
|
146
|
+
-apple-system,
|
|
147
|
+
BlinkMacSystemFont,
|
|
148
|
+
"Segoe UI",
|
|
149
|
+
sans-serif;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#root {
|
|
153
|
+
min-height: 100dvh;
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`openxiangda/styles/tokens.css` 不再是新业务页面的默认依赖。旧项目已经引入时可以保留,或在确实需要平台 CSS 变量统一主题时手动引入。
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 5. Ant Design 和弹层
|
|
162
|
+
|
|
163
|
+
PC 控件优先用 `antd`,移动端控件优先用 `antd-mobile`。弹层必须挂到当前页面容器或 `.sy-app-workspace` 内,避免宿主平台污染或滚动容器裁切:
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
<ConfigProvider
|
|
167
|
+
getPopupContainer={(trigger) =>
|
|
168
|
+
trigger?.closest('.sy-app-workspace') ??
|
|
169
|
+
(document.querySelector('.sy-app-workspace') as HTMLElement) ??
|
|
170
|
+
document.body
|
|
171
|
+
}
|
|
172
|
+
>
|
|
173
|
+
<App />
|
|
174
|
+
</ConfigProvider>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
局部组件也可以使用 `getPopupContainer={(trigger) => trigger.parentElement ?? document.body}`。不要无作用域覆盖 `.ant-select-selector`、`.ant-modal` 等私有 class;确实需要覆盖时限定在页面根类下。
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 6. 平台 Token 兼容说明
|
|
182
|
+
|
|
183
|
+
OpenXiangda 仍保留部分平台语义类和 CSS 变量,主要用于:
|
|
184
|
+
|
|
185
|
+
- 平台标准表单、数据管理列表、审批时间线等组件内部样式。
|
|
186
|
+
- 老项目兼容。
|
|
187
|
+
- 多应用统一主题或深度主题定制。
|
|
188
|
+
|
|
189
|
+
常见兼容类包括 `text-primary`、`text-secondary`、`bg-container`、`bg-layout`、`border-secondary`、`rounded-form`、`shadow-card` 等。AI 编写新业务页面时不要默认使用这些类;除非用户明确要求跟随平台变量主题,或当前项目已有一致的 token 体系。
|
|
190
|
+
|
|
191
|
+
如果需要统一主题,推荐把主题限制在 `.sy-app-workspace` 或应用根类下:
|
|
192
|
+
|
|
193
|
+
```css
|
|
194
|
+
.sy-app-workspace.theme-brand {
|
|
195
|
+
--sy-color-primary: #0f766e;
|
|
196
|
+
--sy-radius-md: 8px;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 7. 构建期提醒
|
|
203
|
+
|
|
204
|
+
OpenXiangda 构建会扫描源码里的 shadcn token 类。如果发现 `bg-card`、`text-muted-foreground`、`text-foreground` 等类,但项目没有显式配置对应 token,会输出 warning。
|
|
205
|
+
|
|
206
|
+
收到 warning 时优先修正为:
|
|
207
|
+
|
|
208
|
+
- Tailwind 原生类:`bg-white border border-slate-200 text-slate-600`
|
|
209
|
+
- Tailwind 任意值:`bg-[#1677ff] text-[13px] grid-cols-[240px_1fr]`
|
|
210
|
+
- 或在 `tailwind.config.cjs` 中显式配置这些 shadcn token
|
|
211
|
+
|
|
212
|
+
warning 不会阻断构建,但它通常意味着页面会出现“颜色、边框、文本层级异常”的视觉问题。
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 8. 提交前检查
|
|
217
|
+
|
|
218
|
+
- [ ] 页面样式默认使用 Tailwind 原生类和任意值,而不是平台 token 类?
|
|
219
|
+
- [ ] 没有使用未配置的 shadcn token 类,例如 `bg-card`、`text-muted-foreground`、`text-foreground`?
|
|
220
|
+
- [ ] `tailwind.config.cjs` 保留 OpenXiangda preset、content 扫描和 blocklist?
|
|
221
|
+
- [ ] 业务 CSS 限定在 `.sy-app-workspace` 或页面根类下?
|
|
222
|
+
- [ ] antd / antd-mobile 弹层设置了合适的挂载容器?
|