openxiangda 1.0.28 → 1.0.30
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/references/component-guide.md +9 -9
- package/openxiangda-skills/references/style-system.md +182 -459
- package/openxiangda-skills/skills/openxiangda-page/SKILL.md +1 -1
- package/package.json +3 -3
- 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 -6
- 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,499 +1,222 @@
|
|
|
1
1
|
# OpenXiangda 样式体系参考
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. 样式体系总览
|
|
8
|
-
|
|
9
|
-
### 1.1 三层结构
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
13
|
-
│ Layer 3: Tailwind Utilities (原子类层) │
|
|
14
|
-
│ 语义化类名 → 引用 CSS Variables │
|
|
15
|
-
│ 例: text-primary, bg-container, gap-form, rounded-form │
|
|
16
|
-
└──────────────────────────────────────────────────────────────┘
|
|
17
|
-
▲
|
|
18
|
-
│ 引用
|
|
19
|
-
│
|
|
20
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
21
|
-
│ Layer 2: AntD Theme Token (组件库层) │
|
|
22
|
-
│ ConfigProvider.theme.token → 映射到 CSS Variables │
|
|
23
|
-
│ 例: colorPrimary: var(--sy-color-primary) │
|
|
24
|
-
└──────────────────────────────────────────────────────────────┘
|
|
25
|
-
▲
|
|
26
|
-
│ 映射
|
|
27
|
-
│
|
|
28
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
29
|
-
│ Layer 1: CSS Variables (基础层 / Single Source of Truth) │
|
|
30
|
-
│ --sy-color-*, --sy-spacing-*, --sy-radius-*, --sy-shadow-* │
|
|
31
|
-
│ 定义在 :root 与 .sy-app-workspace │
|
|
32
|
-
└──────────────────────────────────────────────────────────────┘
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
**核心原则**:平台视觉基线优先来源于 Layer 1 的 CSS Variables;AntD 与 Tailwind 默认消费这套变量。业务页面可以在 `.sy-app-workspace` 命名空间内扩展页面级样式,不要求所有视觉值都必须来自内置 Token。
|
|
36
|
-
|
|
37
|
-
### 1.2 为什么不使用 Shadow DOM
|
|
38
|
-
|
|
39
|
-
| 维度 | Shadow DOM | CSS Namespace(当前方案)|
|
|
40
|
-
|---|---|---|
|
|
41
|
-
| antd 弹层(Modal/Drawer/Select 下拉/DatePicker)| **失效** —— 默认挂载到 `document.body`,逃出 Shadow 边界后丢失样式 | **正常** —— 通过 `getPopupContainer` 挂载到 `.sy-app-workspace` 内 |
|
|
42
|
-
| 全局样式继承 | 完全隔离,需重写所有基础样式 | 受控隔离,通过命名空间避免冲突 |
|
|
43
|
-
| 调试体验 | DevTools 跨边界困难 | 与普通 DOM 一致 |
|
|
44
|
-
| 主题切换 | 必须穿透 Shadow Root | 直接覆盖 `.sy-app-workspace` 上的 CSS 变量 |
|
|
45
|
-
|
|
46
|
-
**结论**:Shadow DOM 与 antd 的 Portal 弹层机制不兼容;改用 `.sy-app-workspace` 命名空间方案。
|
|
47
|
-
|
|
48
|
-
### 1.3 CSS Namespace 隔离原理
|
|
49
|
-
|
|
50
|
-
- 应用根节点统一加 `class="sy-app-workspace"`。
|
|
51
|
-
- 所有自定义样式(Tailwind、业务 CSS)通过 `.sy-app-workspace` 前缀限定作用域。
|
|
52
|
-
- AntD CSS-in-JS 通过 `ConfigProvider.theme.cssVar.prefix = 'sy-ant'` 输出独立变量名,避免与宿主页面碰撞。
|
|
53
|
-
- 弹层容器通过 `getPopupContainer={() => document.querySelector('.sy-app-workspace')}` 锚定到命名空间内部。
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## 2. Layer 1:CSS Variables 设计 Token
|
|
58
|
-
|
|
59
|
-
> 推荐基线。**所有平台变量同时挂载在 `:root` 与 `.sy-app-workspace`**,前者用于全局可用,后者保证命名空间生效时不依赖根选择器。页面可以继续定义自己的局部变量,例如 `--sales-dashboard-accent`、`--kanban-column-width`。
|
|
60
|
-
|
|
61
|
-
```css
|
|
62
|
-
:root, .sy-app-workspace {
|
|
63
|
-
/* ───── 品牌色 ───── */
|
|
64
|
-
--sy-color-primary: #1677ff;
|
|
65
|
-
--sy-color-primary-hover: #4096ff;
|
|
66
|
-
--sy-color-primary-active: #0958d9;
|
|
67
|
-
--sy-color-success: #52c41a;
|
|
68
|
-
--sy-color-warning: #faad14;
|
|
69
|
-
--sy-color-error: #ff4d4f;
|
|
70
|
-
|
|
71
|
-
/* ───── 文本 ───── */
|
|
72
|
-
--sy-color-text: rgba(0, 0, 0, 0.88);
|
|
73
|
-
--sy-color-text-secondary: rgba(0, 0, 0, 0.65);
|
|
74
|
-
--sy-color-text-tertiary: rgba(0, 0, 0, 0.45);
|
|
75
|
-
--sy-color-text-disabled: rgba(0, 0, 0, 0.25);
|
|
76
|
-
|
|
77
|
-
/* ───── 背景 ───── */
|
|
78
|
-
--sy-color-bg-container: #ffffff;
|
|
79
|
-
--sy-color-bg-layout: #f5f5f5;
|
|
80
|
-
--sy-color-bg-elevated: #ffffff;
|
|
81
|
-
|
|
82
|
-
/* ───── 边框 ───── */
|
|
83
|
-
--sy-color-border: #d9d9d9;
|
|
84
|
-
--sy-color-border-secondary: #f0f0f0;
|
|
85
|
-
|
|
86
|
-
/* ───── 间距 ───── */
|
|
87
|
-
--sy-spacing-xs: 4px;
|
|
88
|
-
--sy-spacing-sm: 8px;
|
|
89
|
-
--sy-spacing-md: 16px;
|
|
90
|
-
--sy-spacing-lg: 24px;
|
|
91
|
-
--sy-spacing-xl: 32px;
|
|
92
|
-
|
|
93
|
-
/* ───── 圆角 ───── */
|
|
94
|
-
--sy-radius-sm: 4px;
|
|
95
|
-
--sy-radius-md: 6px;
|
|
96
|
-
--sy-radius-lg: 8px;
|
|
97
|
-
|
|
98
|
-
/* ───── 字体 ───── */
|
|
99
|
-
--sy-font-size-sm: 12px;
|
|
100
|
-
--sy-font-size-base: 14px;
|
|
101
|
-
--sy-font-size-lg: 16px;
|
|
102
|
-
--sy-font-size-xl: 20px;
|
|
103
|
-
--sy-font-size-2xl: 24px;
|
|
104
|
-
|
|
105
|
-
/* ───── 阴影 ───── */
|
|
106
|
-
--sy-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.03), 0 1px 6px -1px rgba(0, 0, 0, 0.02);
|
|
107
|
-
--sy-shadow-md: 0 6px 16px rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12);
|
|
108
|
-
--sy-shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.12);
|
|
109
|
-
|
|
110
|
-
/* ───── 表单特定 ───── */
|
|
111
|
-
--sy-form-gap: 16px;
|
|
112
|
-
--sy-form-padding: 24px;
|
|
113
|
-
--sy-form-field-height: 32px;
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### 2.1 Token 速查表
|
|
118
|
-
|
|
119
|
-
| 类别 | 变量 | 默认值 | 用途 |
|
|
120
|
-
|---|---|---|---|
|
|
121
|
-
| 品牌 | `--sy-color-primary` | `#1677ff` | 主按钮、主色链接、激活态 |
|
|
122
|
-
| 品牌 | `--sy-color-primary-hover` | `#4096ff` | 主色 hover |
|
|
123
|
-
| 品牌 | `--sy-color-primary-active` | `#0958d9` | 主色 active/pressed |
|
|
124
|
-
| 状态 | `--sy-color-success` | `#52c41a` | 成功/通过 |
|
|
125
|
-
| 状态 | `--sy-color-warning` | `#faad14` | 警示 |
|
|
126
|
-
| 状态 | `--sy-color-error` | `#ff4d4f` | 错误/危险操作 |
|
|
127
|
-
| 文本 | `--sy-color-text` | `rgba(0,0,0,.88)` | 主文本 |
|
|
128
|
-
| 文本 | `--sy-color-text-secondary` | `rgba(0,0,0,.65)` | 次文本 |
|
|
129
|
-
| 文本 | `--sy-color-text-tertiary` | `rgba(0,0,0,.45)` | 提示/占位 |
|
|
130
|
-
| 文本 | `--sy-color-text-disabled` | `rgba(0,0,0,.25)` | 禁用 |
|
|
131
|
-
| 背景 | `--sy-color-bg-container` | `#ffffff` | 卡片/输入框 |
|
|
132
|
-
| 背景 | `--sy-color-bg-layout` | `#f5f5f5` | 页面底色 |
|
|
133
|
-
| 背景 | `--sy-color-bg-elevated` | `#ffffff` | 浮层/抽屉 |
|
|
134
|
-
| 边框 | `--sy-color-border` | `#d9d9d9` | 实体边框 |
|
|
135
|
-
| 边框 | `--sy-color-border-secondary` | `#f0f0f0` | 分隔线 |
|
|
136
|
-
| 间距 | `--sy-spacing-{xs\|sm\|md\|lg\|xl}` | 4/8/16/24/32 | 通用间距 |
|
|
137
|
-
| 圆角 | `--sy-radius-{sm\|md\|lg}` | 4/6/8 | 通用圆角 |
|
|
138
|
-
| 字号 | `--sy-font-size-{sm\|base\|lg\|xl\|2xl}` | 12/14/16/20/24 | 字号阶梯 |
|
|
139
|
-
| 阴影 | `--sy-shadow-{sm\|md\|lg}` | 见上 | 卡片/浮层阴影 |
|
|
140
|
-
| 表单 | `--sy-form-gap` | `16px` | 表单字段间距 |
|
|
141
|
-
| 表单 | `--sy-form-padding` | `24px` | 表单容器内边距 |
|
|
142
|
-
| 表单 | `--sy-form-field-height` | `32px` | 输入框高度 |
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## 3. Layer 2:AntD Theme Token 映射
|
|
147
|
-
|
|
148
|
-
通过 `ConfigProvider` 让 antd 组件读取 CSS 变量,实现"改变量即改主题"。
|
|
149
|
-
|
|
150
|
-
```tsx
|
|
151
|
-
import { ConfigProvider } from 'antd';
|
|
152
|
-
|
|
153
|
-
export function AppThemeProvider({ children }: { children: React.ReactNode }) {
|
|
154
|
-
return (
|
|
155
|
-
<ConfigProvider
|
|
156
|
-
// 让弹层挂载到命名空间容器内(关键:保证 CSS 变量可达)
|
|
157
|
-
getPopupContainer={() =>
|
|
158
|
-
(document.querySelector('.sy-app-workspace') as HTMLElement) ?? document.body
|
|
159
|
-
}
|
|
160
|
-
theme={{
|
|
161
|
-
cssVar: { prefix: 'sy-ant' }, // 输出 --sy-ant-* 变量,避免冲突
|
|
162
|
-
hashed: false, // 与 cssVar 配合,禁用 hash
|
|
163
|
-
token: {
|
|
164
|
-
// 颜色
|
|
165
|
-
colorPrimary: 'var(--sy-color-primary)',
|
|
166
|
-
colorSuccess: 'var(--sy-color-success)',
|
|
167
|
-
colorWarning: 'var(--sy-color-warning)',
|
|
168
|
-
colorError: 'var(--sy-color-error)',
|
|
169
|
-
colorText: 'var(--sy-color-text)',
|
|
170
|
-
colorTextSecondary: 'var(--sy-color-text-secondary)',
|
|
171
|
-
colorTextTertiary: 'var(--sy-color-text-tertiary)',
|
|
172
|
-
colorTextDisabled: 'var(--sy-color-text-disabled)',
|
|
173
|
-
colorBgContainer: 'var(--sy-color-bg-container)',
|
|
174
|
-
colorBgLayout: 'var(--sy-color-bg-layout)',
|
|
175
|
-
colorBgElevated: 'var(--sy-color-bg-elevated)',
|
|
176
|
-
colorBorder: 'var(--sy-color-border)',
|
|
177
|
-
colorBorderSecondary: 'var(--sy-color-border-secondary)',
|
|
178
|
-
|
|
179
|
-
// 度量(antd token 不支持 var(),需用数值;通过 components 精细控制时再用 var)
|
|
180
|
-
borderRadius: 6,
|
|
181
|
-
borderRadiusLG: 8,
|
|
182
|
-
borderRadiusSM: 4,
|
|
183
|
-
fontSize: 14,
|
|
184
|
-
controlHeight: 32,
|
|
185
|
-
},
|
|
186
|
-
components: {
|
|
187
|
-
Form: { itemMarginBottom: 16 },
|
|
188
|
-
Card: { paddingLG: 24 },
|
|
189
|
-
},
|
|
190
|
-
}}
|
|
191
|
-
>
|
|
192
|
-
{children}
|
|
193
|
-
</ConfigProvider>
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
> **注意**:antd token 中数值类(borderRadius/fontSize/controlHeight)需直接写数值,与 Layer 1 的 `--sy-radius-md`/`--sy-font-size-base`/`--sy-form-field-height` 保持同步即可。
|
|
199
|
-
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
## 4. Layer 3:Tailwind 语义化工具类
|
|
203
|
-
|
|
204
|
-
`tailwind-preset.ts` 基于 CSS Variables 扩展语义化类。语义类适合常规后台页面、表单、列表和状态展示;普通 Tailwind 工具类与任意值适合特殊布局、品牌视觉、图表容器、复杂动效和一次性精调。
|
|
205
|
-
|
|
206
|
-
### 4.1 颜色类
|
|
207
|
-
|
|
208
|
-
| Tailwind 类 | 等价 CSS | 场景 |
|
|
209
|
-
|---|---|---|
|
|
210
|
-
| `text-primary` | `color: var(--sy-color-primary)` | 主色文本/链接 |
|
|
211
|
-
| `text-success` | `color: var(--sy-color-success)` | 成功文本 |
|
|
212
|
-
| `text-warning` | `color: var(--sy-color-warning)` | 警示文本 |
|
|
213
|
-
| `text-error` | `color: var(--sy-color-error)` | 错误文本 |
|
|
214
|
-
| `text-default` | `color: var(--sy-color-text)` | 主文本 |
|
|
215
|
-
| `text-secondary` | `color: var(--sy-color-text-secondary)` | 次文本 |
|
|
216
|
-
| `text-tertiary` | `color: var(--sy-color-text-tertiary)` | 提示文本 |
|
|
217
|
-
| `text-disabled` | `color: var(--sy-color-text-disabled)` | 禁用文本 |
|
|
218
|
-
| `bg-container` | `background: var(--sy-color-bg-container)` | 卡片底 |
|
|
219
|
-
| `bg-layout` | `background: var(--sy-color-bg-layout)` | 页面底 |
|
|
220
|
-
| `bg-elevated` | `background: var(--sy-color-bg-elevated)` | 浮层底 |
|
|
221
|
-
| `border-default` | `border-color: var(--sy-color-border)` | 边框 |
|
|
222
|
-
| `border-secondary` | `border-color: var(--sy-color-border-secondary)` | 分隔 |
|
|
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`)和任意值(如 `grid-cols-[240px_1fr]`、`bg-[#0f766e]`)都可以使用。常规业务组件优先使用语义类,特殊页面按实际视觉需求选择更合适的 Tailwind/CSS 写法。
|
|
3
|
+
> 面向 AI Agent 的代码页、表单页和自定义节点样式基线。默认直接使用 Tailwind 原生工具类和 Tailwind 任意值;平台 token 是兼容能力和平台组件内部能力,不是业务页面的强制范式。
|
|
251
4
|
|
|
252
5
|
---
|
|
253
6
|
|
|
254
|
-
##
|
|
7
|
+
## 1. 默认规则
|
|
255
8
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
| 4 | 需要运行时动态值 | 少量 inline style 可以使用,尤其是动态尺寸、颜色、坐标、图表变量 | 避免把大段静态样式写进 inline style,静态样式优先放到 class/CSS |
|
|
262
|
-
| 5 | antd 主题 | 优先通过 `ConfigProvider.theme`、CSS 变量和 `className` 控制 | 如确实要覆盖内部 class,必须限定在页面命名空间内,并接受升级风险 |
|
|
263
|
-
| 6 | antd 弹层、Drawer、Modal、DatePicker、Select | 这是硬要求:通过 `getPopupContainer` 锚定到 `.sy-app-workspace` 或就近容器 | 否则弹层可能丢样式或被宿主页面污染 |
|
|
264
|
-
| 7 | CSS 作用域 | 这是硬要求:业务 CSS 必须在 `.sy-app-workspace` 或页面根类下收敛作用域 | 避免写全局裸选择器污染宿主平台 |
|
|
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` 或页面根类下,避免污染宿主平台。
|
|
265
14
|
|
|
266
15
|
---
|
|
267
16
|
|
|
268
|
-
##
|
|
17
|
+
## 2. 推荐写法
|
|
269
18
|
|
|
270
|
-
###
|
|
19
|
+
### 2.1 页面容器
|
|
271
20
|
|
|
272
21
|
```tsx
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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
|
+
}
|
|
282
32
|
```
|
|
283
33
|
|
|
284
|
-
###
|
|
34
|
+
### 2.2 卡片和状态
|
|
285
35
|
|
|
286
36
|
```tsx
|
|
287
|
-
|
|
288
|
-
<div className="
|
|
289
|
-
<
|
|
290
|
-
<Input />
|
|
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>
|
|
291
40
|
</div>
|
|
292
41
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
<Input className="h-[32px]" />
|
|
297
|
-
</div>
|
|
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>
|
|
298
45
|
```
|
|
299
46
|
|
|
300
|
-
###
|
|
47
|
+
### 2.3 精确布局和品牌色
|
|
301
48
|
|
|
302
49
|
```tsx
|
|
303
|
-
|
|
304
|
-
<
|
|
305
|
-
<
|
|
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>
|
|
306
54
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
55
|
+
<button className="rounded-md bg-[#1677ff] px-4 py-2 text-sm font-medium text-white hover:bg-[#0958d9]">
|
|
56
|
+
提交
|
|
57
|
+
</button>
|
|
310
58
|
```
|
|
311
59
|
|
|
312
|
-
###
|
|
60
|
+
### 2.4 局部 CSS
|
|
313
61
|
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
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
|
+
}
|
|
324
73
|
```
|
|
325
74
|
|
|
326
|
-
|
|
75
|
+
---
|
|
327
76
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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;
|
|
331
86
|
|
|
332
|
-
|
|
333
|
-
|
|
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
|
+
};
|
|
334
112
|
```
|
|
335
113
|
|
|
336
|
-
|
|
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 指令和少量基础样式:
|
|
337
127
|
|
|
338
128
|
```css
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
129
|
+
@layer tailwind-base {
|
|
130
|
+
@tailwind base;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@tailwind components;
|
|
134
|
+
@tailwind utilities;
|
|
135
|
+
|
|
136
|
+
* {
|
|
137
|
+
box-sizing: border-box;
|
|
344
138
|
}
|
|
345
139
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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;
|
|
352
150
|
}
|
|
353
151
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
background: linear-gradient(135deg, #0f766e, #0ea5e9);
|
|
357
|
-
border-radius: 14px;
|
|
358
|
-
padding: 20px;
|
|
152
|
+
#root {
|
|
153
|
+
min-height: 100dvh;
|
|
359
154
|
}
|
|
360
155
|
```
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
.
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
<YourApp />
|
|
429
|
-
</AppThemeProvider>
|
|
430
|
-
</div>
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
### 8.2 Tailwind 配置(关键)
|
|
434
|
-
|
|
435
|
-
`tailwind.config.cjs` 中:
|
|
436
|
-
|
|
437
|
-
```js
|
|
438
|
-
module.exports = {
|
|
439
|
-
important: '.sy-app-workspace', // 所有 Tailwind 工具类都受命名空间限定
|
|
440
|
-
corePlugins: {
|
|
441
|
-
preflight: false, // 避免污染宿主页面
|
|
442
|
-
},
|
|
443
|
-
content: ['./src/**/*.{ts,tsx}'],
|
|
444
|
-
presets: [require('./tailwind-preset')],
|
|
445
|
-
};
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
`important: '.sy-app-workspace'` 让所有原子类输出形如 `.sy-app-workspace .text-primary { ... }`,自动隔离。
|
|
449
|
-
|
|
450
|
-
### 8.3 antd 弹层挂载
|
|
451
|
-
|
|
452
|
-
任何 `Modal` / `Drawer` / `Select` / `DatePicker` / `Tooltip` 等组件,**必须**通过 `ConfigProvider.getPopupContainer` 或局部 `getPopupContainer` 锚定到命名空间容器:
|
|
453
|
-
|
|
454
|
-
```tsx
|
|
455
|
-
<ConfigProvider
|
|
456
|
-
getPopupContainer={() =>
|
|
457
|
-
(document.querySelector('.sy-app-workspace') as HTMLElement) ?? document.body
|
|
458
|
-
}
|
|
459
|
-
>
|
|
460
|
-
...
|
|
461
|
-
</ConfigProvider>
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
否则弹层会挂到 `document.body`,导致 CSS 变量无法继承、Tailwind 工具类失效。
|
|
465
|
-
|
|
466
|
-
### 8.4 第三方组件库
|
|
467
|
-
|
|
468
|
-
引入第三方组件时,若其样式依赖全局 reset,需在 `.sy-app-workspace` 内手动补齐;不要依赖 Tailwind preflight。
|
|
469
|
-
|
|
470
|
-
### 8.5 字体与基础样式
|
|
471
|
-
|
|
472
|
-
基础 `font-family` / `line-height` 应在 `.sy-app-workspace` 上设置一次,避免逐组件重复:
|
|
473
|
-
|
|
474
|
-
```css
|
|
475
|
-
.sy-app-workspace {
|
|
476
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC',
|
|
477
|
-
'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
|
478
|
-
font-size: var(--sy-font-size-base);
|
|
479
|
-
color: var(--sy-color-text);
|
|
480
|
-
line-height: 1.5715;
|
|
481
|
-
}
|
|
482
|
-
```
|
|
483
|
-
|
|
484
|
-
---
|
|
485
|
-
|
|
486
|
-
## 速查 Cheatsheet
|
|
487
|
-
|
|
488
|
-
| 想做什么 | 用什么 |
|
|
489
|
-
|---|---|
|
|
490
|
-
| 主色按钮 | `<Button type="primary">` |
|
|
491
|
-
| 主色文本 | `className="text-primary"` |
|
|
492
|
-
| 卡片容器 | `className="bg-container shadow-card rounded-card p-form"` |
|
|
493
|
-
| 表单纵向布局 | `className="flex flex-col gap-form"` |
|
|
494
|
-
| 错误状态文本 | `className="text-error"` |
|
|
495
|
-
| 次要说明文本 | `className="text-secondary text-sm-sy"` |
|
|
496
|
-
| 浮层背景 | `className="bg-elevated shadow-popover"` |
|
|
497
|
-
| 分隔线 | `className="border-t border-secondary"` |
|
|
498
|
-
| 切换主题 | 改 `.sy-app-workspace` 的 CSS 变量 |
|
|
499
|
-
| 弹层挂载 | `getPopupContainer` 指向 `.sy-app-workspace` |
|
|
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 弹层设置了合适的挂载容器?
|