pda-kit-mcp-server 2.0.1
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 +107 -0
- package/bin/pda-kit-mcp.js +35 -0
- package/dist/file-reader.d.ts +83 -0
- package/dist/file-reader.d.ts.map +1 -0
- package/dist/file-reader.js +170 -0
- package/dist/file-reader.js.map +1 -0
- package/dist/http-entry.d.ts +12 -0
- package/dist/http-entry.d.ts.map +1 -0
- package/dist/http-entry.js +149 -0
- package/dist/http-entry.js.map +1 -0
- package/dist/http-server.d.ts +5 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +114 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/paths.d.ts +37 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +52 -0
- package/dist/paths.js.map +1 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +308 -0
- package/dist/server.js.map +1 -0
- package/dist/stdio-server.d.ts +8 -0
- package/dist/stdio-server.d.ts.map +1 -0
- package/dist/stdio-server.js +83 -0
- package/dist/stdio-server.js.map +1 -0
- package/dist/tools/generate-component.d.ts +54 -0
- package/dist/tools/generate-component.d.ts.map +1 -0
- package/dist/tools/generate-component.js +80 -0
- package/dist/tools/generate-component.js.map +1 -0
- package/dist/tools/get-component-spec.d.ts +70 -0
- package/dist/tools/get-component-spec.d.ts.map +1 -0
- package/dist/tools/get-component-spec.js +95 -0
- package/dist/tools/get-component-spec.js.map +1 -0
- package/dist/tools/get-global-rules.d.ts +42 -0
- package/dist/tools/get-global-rules.d.ts.map +1 -0
- package/dist/tools/get-global-rules.js +83 -0
- package/dist/tools/get-global-rules.js.map +1 -0
- package/dist/tools/list-components.d.ts +52 -0
- package/dist/tools/list-components.d.ts.map +1 -0
- package/dist/tools/list-components.js +104 -0
- package/dist/tools/list-components.js.map +1 -0
- package/dist/tools/search-components.d.ts +54 -0
- package/dist/tools/search-components.d.ts.map +1 -0
- package/dist/tools/search-components.js +124 -0
- package/dist/tools/search-components.js.map +1 -0
- package/dist/tools/validate-html.d.ts +43 -0
- package/dist/tools/validate-html.d.ts.map +1 -0
- package/dist/tools/validate-html.js +116 -0
- package/dist/tools/validate-html.js.map +1 -0
- package/package.json +59 -0
- package/spec-data/badge.md +461 -0
- package/spec-data/button.md +148 -0
- package/spec-data/camera.md +622 -0
- package/spec-data/dialog.md +419 -0
- package/spec-data/divider.md +208 -0
- package/spec-data/drawer.md +301 -0
- package/spec-data/empty-state.md +336 -0
- package/spec-data/home-page.md +352 -0
- package/spec-data/input-row.md +346 -0
- package/spec-data/layout-page.md +317 -0
- package/spec-data/list-item.md +128 -0
- package/spec-data/location-selector.md +630 -0
- package/spec-data/more-actions.md +427 -0
- package/spec-data/navbar.md +482 -0
- package/spec-data/photo-list.md +461 -0
- package/spec-data/picker-single.md +199 -0
- package/spec-data/picker.md +586 -0
- package/spec-data/scan-input.md +304 -0
- package/spec-data/section-heading.md +268 -0
- package/spec-data/selectable-list.md +331 -0
- package/spec-data/stepper.md +247 -0
- package/spec-data/tab-bar.md +254 -0
- package/spec-data/tab.md +349 -0
- package/spec-data/tag.md +363 -0
- package/spec-data/tooltip.md +202 -0
- package/spec-data/waybill-number.md +257 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: picker
|
|
3
|
+
name: 选择器
|
|
4
|
+
category: "表单/Form"
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
source: PDAKit-业务组件
|
|
7
|
+
source_url: https://mastergo.ky-tech.com.cn/goto/TZAlKGkG
|
|
8
|
+
source_doc_id: 103417331857122
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 选择器 Picker
|
|
12
|
+
|
|
13
|
+
双层选择器组件,**左侧类型切换 + 右侧单选选项**,底部操作确认。用于点部选择、分类筛选等场景。
|
|
14
|
+
|
|
15
|
+
> **核心规则**:左列控制右列内容(类型联动),右侧为单选操作,底部取消/确定确认选择结果。
|
|
16
|
+
> **颜色规则**:全部使用 Token(`--color-{色系}-{色阶}`),禁止 Hex。
|
|
17
|
+
> **字体**:PingFang SC。
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Props
|
|
22
|
+
|
|
23
|
+
### 父组件 Props(选择器面板)
|
|
24
|
+
|
|
25
|
+
| Prop | 类型 | 值 | 默认 |
|
|
26
|
+
|------|------|-----|------|
|
|
27
|
+
| 标题 | string | 头部标题文字 | `测试组件` |
|
|
28
|
+
| 显示关闭 | boolean | 是否显示右上角关闭按钮 | `true` |
|
|
29
|
+
| 显示描述 | boolean | 标题下方是否显示描述文字 | `false` |
|
|
30
|
+
| 描述文字 | string | 描述内容(`显示描述=true` 时生效) | — |
|
|
31
|
+
| 1级选项列表 | array | 左侧分类选项数据 | `[]` |
|
|
32
|
+
| 2级选项列表 | array | 右侧选项数据 | `[]` |
|
|
33
|
+
| 已选项 ID | string | 当前已选中的选项 ID | `null` |
|
|
34
|
+
|
|
35
|
+
### 底部按钮 Props
|
|
36
|
+
|
|
37
|
+
| Prop | 类型 | 值 | 默认 |
|
|
38
|
+
|------|------|-----|------|
|
|
39
|
+
| 按钮类型 | enum | `两列按钮` | `两列按钮` |
|
|
40
|
+
| 显示分割线 | boolean | 底部上方是否显示分割线 | `true` |
|
|
41
|
+
| 左按钮文字 | string | 左侧(取消)按钮文字 | `取消` |
|
|
42
|
+
| 右按钮文字 | string | 右侧(确定)按钮文字 | `确定` |
|
|
43
|
+
|
|
44
|
+
### 1级选项行 Props(左列)
|
|
45
|
+
|
|
46
|
+
| Prop | 类型 | 说明 |
|
|
47
|
+
|------|------|------|
|
|
48
|
+
| 选中状态 | enum | `选中` / `默认` |
|
|
49
|
+
| 文本 | string | 分类名称 |
|
|
50
|
+
|
|
51
|
+
### 2级选项行 Props(右列)
|
|
52
|
+
|
|
53
|
+
| Prop | 类型 | 说明 |
|
|
54
|
+
|------|------|------|
|
|
55
|
+
| 选中状态 | enum | `已选` / `未选` |
|
|
56
|
+
| 文本 | string | 选项名称 |
|
|
57
|
+
| 二级分类 | enum | `单选`(选项互斥) |
|
|
58
|
+
| 语音备注 | boolean | 是否显示语音备注功能 | `false` |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 整体容器规格
|
|
63
|
+
|
|
64
|
+
| 属性 | 值 |
|
|
65
|
+
|------|------|
|
|
66
|
+
| 宽度 | `480px` |
|
|
67
|
+
| 高度 | `477px`(min `320px` / max `740px`) |
|
|
68
|
+
| 布局 | `flex-column` |
|
|
69
|
+
| 圆角(顶部) | `16px` |
|
|
70
|
+
| 弹窗类型 | Bottom Sheet,由底部向上滑入,`300ms ease-in` |
|
|
71
|
+
| 遮罩 | `rgba(0,0,0,0.4)`,z-index: 900 |
|
|
72
|
+
| 面板 | z-index: 901 |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 1. 头部
|
|
77
|
+
|
|
78
|
+
### 规格
|
|
79
|
+
|
|
80
|
+
| 属性 | 值 |
|
|
81
|
+
|------|------|
|
|
82
|
+
| 背景 | `--color-grey-1`(`#FFFFFF`) |
|
|
83
|
+
| 上内边距 | `24px` |
|
|
84
|
+
| 下内边距 | `8px` |
|
|
85
|
+
| 左右内边距 | `16px` |
|
|
86
|
+
| 子元素间距 | `4px`(gap) |
|
|
87
|
+
| 圆角(顶部) | `16px` |
|
|
88
|
+
| 宽度 | `480px` |
|
|
89
|
+
|
|
90
|
+
### 内部布局
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
┌─ 480px ─────────────────────────────────┐
|
|
94
|
+
│ [×] 关闭图标 │ ← 绝对定位, right: 16px, top: 24px
|
|
95
|
+
│ 测试组件 (24px/600) │ ← 标题居中
|
|
96
|
+
│ 描述文字 (16px #666) ← 按需 │ ← 描述居中(可选)
|
|
97
|
+
└──────────────────────────────────────────┘
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
| 元素 | 样式 |
|
|
101
|
+
|------|------|
|
|
102
|
+
| 标题 | `24px / 36px line-height`, font-weight: `600`, color: `--color-black-6` (`#333333`), text-align: `center` |
|
|
103
|
+
| 描述文字 | `16px / 22px line-height`, color: `--color-grey-6` (`#52567B`), text-align: `center` |
|
|
104
|
+
| 关闭图标 | `common_ic_close_o.svg`, `24×24`, absolute, `right: 16px, top: 24px` |
|
|
105
|
+
|
|
106
|
+
### CSS 示例
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
.picker-header {
|
|
110
|
+
width: 480px;
|
|
111
|
+
display: flex;
|
|
112
|
+
flex-direction: column;
|
|
113
|
+
align-items: center;
|
|
114
|
+
gap: 4px;
|
|
115
|
+
padding: 24px 16px 8px;
|
|
116
|
+
background: var(--color-grey-1);
|
|
117
|
+
border-top-left-radius: 16px;
|
|
118
|
+
border-top-right-radius: 16px;
|
|
119
|
+
position: relative;
|
|
120
|
+
flex-shrink: 0;
|
|
121
|
+
}
|
|
122
|
+
.picker-header-title {
|
|
123
|
+
color: var(--color-black-6);
|
|
124
|
+
font-size: 24px;
|
|
125
|
+
line-height: 36px;
|
|
126
|
+
font-weight: 600;
|
|
127
|
+
font-family: PingFang SC;
|
|
128
|
+
text-align: center;
|
|
129
|
+
}
|
|
130
|
+
.picker-header-desc {
|
|
131
|
+
color: var(--color-grey-6);
|
|
132
|
+
font-size: 16px;
|
|
133
|
+
line-height: 22px;
|
|
134
|
+
font-family: PingFang SC;
|
|
135
|
+
text-align: center;
|
|
136
|
+
}
|
|
137
|
+
.picker-header-close {
|
|
138
|
+
position: absolute;
|
|
139
|
+
right: 16px;
|
|
140
|
+
top: 24px;
|
|
141
|
+
width: 24px;
|
|
142
|
+
height: 24px;
|
|
143
|
+
cursor: pointer;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 2. 内容区(左列 + 右列)
|
|
150
|
+
|
|
151
|
+
### 容器
|
|
152
|
+
|
|
153
|
+
| 属性 | 值 |
|
|
154
|
+
|------|------|
|
|
155
|
+
| 布局 | `flex-row` |
|
|
156
|
+
| 背景 | `--color-grey-1`(`#FFFFFF`) |
|
|
157
|
+
| 伸缩 | `flex: 1` |
|
|
158
|
+
| 溢出 | `overflow: hidden` |
|
|
159
|
+
|
|
160
|
+
### 2.1 一级选项组(左列)
|
|
161
|
+
|
|
162
|
+
| 属性 | 值 |
|
|
163
|
+
|------|------|
|
|
164
|
+
| 布局 | `flex-column`, `flex-shrink: 0`, `align-self: stretch` |
|
|
165
|
+
| 背景 | `--color-grey-2`(`#F3F4F6`) |
|
|
166
|
+
| 宽度 | `120px` |
|
|
167
|
+
|
|
168
|
+
#### 选项行
|
|
169
|
+
|
|
170
|
+
| 属性 | 值 |
|
|
171
|
+
|------|------|
|
|
172
|
+
| 高度 | `70px` |
|
|
173
|
+
| 内边距 | `0 16px` |
|
|
174
|
+
| 布局 | `flex-column`, `justify-content: center`, `align-items: flex-start` |
|
|
175
|
+
| 字体 | `18px / 25px`, `--color-black-6`(`#333333`) |
|
|
176
|
+
|
|
177
|
+
#### 状态
|
|
178
|
+
|
|
179
|
+
| 状态 | 背景 | 文字颜色 | 左侧指示线 |
|
|
180
|
+
|------|------|---------|-----------|
|
|
181
|
+
| 默认 | `--color-grey-2`(`#F3F4F6`) | `--color-black-6`(`#333333`) | 无 |
|
|
182
|
+
| 选中 | `--color-grey-1`(`#FFFFFF`) | `--color-main-6`(`#6445D1`),font-weight: `600` | `4px × 28px`, `--color-main-6`, 左侧 |
|
|
183
|
+
|
|
184
|
+
### CSS 示例(左列)
|
|
185
|
+
|
|
186
|
+
```css
|
|
187
|
+
.picker-left-panel {
|
|
188
|
+
width: 120px;
|
|
189
|
+
display: flex;
|
|
190
|
+
flex-direction: column;
|
|
191
|
+
align-self: stretch;
|
|
192
|
+
flex-shrink: 0;
|
|
193
|
+
background: var(--color-grey-2);
|
|
194
|
+
overflow-y: auto;
|
|
195
|
+
}
|
|
196
|
+
.picker-left-item {
|
|
197
|
+
width: 120px;
|
|
198
|
+
height: 70px;
|
|
199
|
+
display: flex;
|
|
200
|
+
flex-direction: column;
|
|
201
|
+
justify-content: center;
|
|
202
|
+
align-items: flex-start;
|
|
203
|
+
padding: 0 16px;
|
|
204
|
+
font-size: 18px;
|
|
205
|
+
line-height: 25px;
|
|
206
|
+
font-family: PingFang SC;
|
|
207
|
+
color: var(--color-black-6);
|
|
208
|
+
cursor: pointer;
|
|
209
|
+
position: relative;
|
|
210
|
+
flex-shrink: 0;
|
|
211
|
+
}
|
|
212
|
+
.picker-left-item.selected {
|
|
213
|
+
background: var(--color-grey-1);
|
|
214
|
+
color: var(--color-main-6);
|
|
215
|
+
font-weight: 600;
|
|
216
|
+
}
|
|
217
|
+
.picker-left-item.selected::before {
|
|
218
|
+
content: '';
|
|
219
|
+
position: absolute;
|
|
220
|
+
left: 0;
|
|
221
|
+
top: 50%;
|
|
222
|
+
transform: translateY(-50%);
|
|
223
|
+
width: 4px;
|
|
224
|
+
height: 28px;
|
|
225
|
+
background: var(--color-main-6);
|
|
226
|
+
border-radius: 2px;
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### 2.2 二级选项组(右列)
|
|
231
|
+
|
|
232
|
+
| 属性 | 值 |
|
|
233
|
+
|------|------|
|
|
234
|
+
| 布局 | `flex-column`, `flex-shrink: 0`, `align-self: stretch`, `justify-content: center`, `align-items: center` |
|
|
235
|
+
| 背景 | `--color-grey-1`(`#FFFFFF`) |
|
|
236
|
+
| 宽度 | `360px`(480 - 120) |
|
|
237
|
+
|
|
238
|
+
#### 选项行(单选)
|
|
239
|
+
|
|
240
|
+
| 属性 | 值 |
|
|
241
|
+
|------|------|
|
|
242
|
+
| 高度 | `70px` |
|
|
243
|
+
| 内边距 | `0 16px` |
|
|
244
|
+
| 布局 | `flex-row`, `align-items: center`, `justify-content: space-between` |
|
|
245
|
+
| 字体 | `18px / 25px`, `--color-black-6`(`#333333`) |
|
|
246
|
+
| 行分割线 | `border-bottom: 1px solid var(--color-black-2)`,最后一行无 |
|
|
247
|
+
|
|
248
|
+
#### 单选指示器
|
|
249
|
+
|
|
250
|
+
| 属性 | 值 |
|
|
251
|
+
|------|------|
|
|
252
|
+
| 尺寸 | `24×24px` |
|
|
253
|
+
| 间距(与文字) | 位于文字右侧 |
|
|
254
|
+
| 未选态 | 圆形描边 `1.5px --color-black-2`(`#DDDDDD`),透明背景 |
|
|
255
|
+
| 已选态 | 圆形填充 `--color-green-6`(`#03c15f`),白色 `common_ic_check_two.svg` 图标 `16×16px` |
|
|
256
|
+
| 交互 | 单选互斥:同一分类下仅一项可选中 |
|
|
257
|
+
|
|
258
|
+
### CSS 示例(右列)
|
|
259
|
+
|
|
260
|
+
```css
|
|
261
|
+
.picker-right-panel {
|
|
262
|
+
width: 360px;
|
|
263
|
+
display: flex;
|
|
264
|
+
flex-direction: column;
|
|
265
|
+
justify-content: center;
|
|
266
|
+
align-items: center;
|
|
267
|
+
align-self: stretch;
|
|
268
|
+
flex-shrink: 0;
|
|
269
|
+
background: var(--color-grey-1);
|
|
270
|
+
overflow-y: auto;
|
|
271
|
+
}
|
|
272
|
+
.picker-right-item {
|
|
273
|
+
width: 100%;
|
|
274
|
+
height: 70px;
|
|
275
|
+
display: flex;
|
|
276
|
+
align-items: center;
|
|
277
|
+
justify-content: space-between;
|
|
278
|
+
padding: 0 16px;
|
|
279
|
+
font-size: 18px;
|
|
280
|
+
line-height: 25px;
|
|
281
|
+
font-family: PingFang SC;
|
|
282
|
+
color: var(--color-black-6);
|
|
283
|
+
cursor: pointer;
|
|
284
|
+
flex-shrink: 0;
|
|
285
|
+
border-bottom: 1px solid var(--color-black-2);
|
|
286
|
+
}
|
|
287
|
+
.picker-right-item:last-child { border-bottom: none; }
|
|
288
|
+
.picker-right-item:active {
|
|
289
|
+
background: var(--color-grey-2);
|
|
290
|
+
}
|
|
291
|
+
.picker-radio {
|
|
292
|
+
width: 24px;
|
|
293
|
+
height: 24px;
|
|
294
|
+
flex-shrink: 0;
|
|
295
|
+
border: 1.5px solid var(--color-black-2);
|
|
296
|
+
border-radius: 50%;
|
|
297
|
+
background: transparent;
|
|
298
|
+
display: flex;
|
|
299
|
+
align-items: center;
|
|
300
|
+
justify-content: center;
|
|
301
|
+
cursor: pointer;
|
|
302
|
+
position: relative;
|
|
303
|
+
}
|
|
304
|
+
.picker-radio.checked {
|
|
305
|
+
background: var(--color-green-6);
|
|
306
|
+
border-color: var(--color-green-6);
|
|
307
|
+
}
|
|
308
|
+
.picker-radio svg { display: none; }
|
|
309
|
+
.picker-radio.checked svg {
|
|
310
|
+
display: block;
|
|
311
|
+
width: 16px;
|
|
312
|
+
height: 16px;
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 3. 底部操作按钮
|
|
319
|
+
|
|
320
|
+
**描述**:固定底部,取消/确定双按钮确认选择结果。
|
|
321
|
+
|
|
322
|
+
### 规格
|
|
323
|
+
|
|
324
|
+
| 属性 | 值 |
|
|
325
|
+
|------|------|
|
|
326
|
+
| 分割线 | `1px`, `--color-black-2`(`#DDDDDD`), 宽 `480px` |
|
|
327
|
+
| 容器背景 | `--color-grey-1`(`#FFFFFF`) |
|
|
328
|
+
| 垂直内边距 | `8px` |
|
|
329
|
+
| 水平内边距 | `16px` |
|
|
330
|
+
| 按钮间距 | `16px`(gap) |
|
|
331
|
+
| 布局 | `flex-row`, `justify-content: center`, `align-items: center` |
|
|
332
|
+
|
|
333
|
+
### 按钮规格
|
|
334
|
+
|
|
335
|
+
| 属性 | 取消按钮 | 确定按钮 |
|
|
336
|
+
|------|---------|---------|
|
|
337
|
+
| 背景 | `--color-grey-2`(`#F3F4F6`) | `--color-main-6`(`#6445D1`) |
|
|
338
|
+
| 文字颜色 | `--color-grey-6`(`#52567B`) | `--color-grey-1`(`#FFFFFF`) |
|
|
339
|
+
| 文字 | `取消` | `确定` |
|
|
340
|
+
| 字体 | `22px / 30px`, PingFang SC | `22px / 30px`, PingFang SC |
|
|
341
|
+
| 最小宽度 | `100px` | `100px` |
|
|
342
|
+
| 最大宽度 | `448px` | `448px` |
|
|
343
|
+
| 高度 | `64px` | `64px` |
|
|
344
|
+
| 圆角 | `8px` | `8px` |
|
|
345
|
+
| 伸缩 | `flex: 1` | `flex: 1` |
|
|
346
|
+
| 交互态 | `:active` → `--color-grey-3` | `:active` → `--color-main-7` |
|
|
347
|
+
|
|
348
|
+
### CSS 示例
|
|
349
|
+
|
|
350
|
+
```css
|
|
351
|
+
.picker-bottom {
|
|
352
|
+
display: flex;
|
|
353
|
+
flex-direction: column;
|
|
354
|
+
align-self: stretch;
|
|
355
|
+
background: var(--color-grey-1);
|
|
356
|
+
flex-shrink: 0;
|
|
357
|
+
}
|
|
358
|
+
.picker-divider {
|
|
359
|
+
width: 480px;
|
|
360
|
+
height: 1px;
|
|
361
|
+
background: var(--color-black-2);
|
|
362
|
+
}
|
|
363
|
+
.picker-bottom-row {
|
|
364
|
+
display: flex;
|
|
365
|
+
align-items: center;
|
|
366
|
+
justify-content: center;
|
|
367
|
+
gap: 16px;
|
|
368
|
+
padding: 8px 16px;
|
|
369
|
+
}
|
|
370
|
+
.picker-btn-cancel {
|
|
371
|
+
flex: 1;
|
|
372
|
+
min-width: 100px;
|
|
373
|
+
max-width: 448px;
|
|
374
|
+
height: 64px;
|
|
375
|
+
display: flex;
|
|
376
|
+
justify-content: center;
|
|
377
|
+
align-items: center;
|
|
378
|
+
background: var(--color-grey-2);
|
|
379
|
+
border: none;
|
|
380
|
+
border-radius: 8px;
|
|
381
|
+
color: var(--color-grey-6);
|
|
382
|
+
font-size: 22px;
|
|
383
|
+
line-height: 30px;
|
|
384
|
+
font-family: PingFang SC;
|
|
385
|
+
cursor: pointer;
|
|
386
|
+
}
|
|
387
|
+
.picker-btn-cancel:active { background: var(--color-grey-3); }
|
|
388
|
+
.picker-btn-confirm {
|
|
389
|
+
flex: 1;
|
|
390
|
+
min-width: 100px;
|
|
391
|
+
max-width: 448px;
|
|
392
|
+
height: 64px;
|
|
393
|
+
display: flex;
|
|
394
|
+
justify-content: center;
|
|
395
|
+
align-items: center;
|
|
396
|
+
background: var(--color-main-6);
|
|
397
|
+
border: none;
|
|
398
|
+
border-radius: 8px;
|
|
399
|
+
color: var(--color-grey-1);
|
|
400
|
+
font-size: 22px;
|
|
401
|
+
line-height: 30px;
|
|
402
|
+
font-family: PingFang SC;
|
|
403
|
+
cursor: pointer;
|
|
404
|
+
}
|
|
405
|
+
.picker-btn-confirm:active { background: var(--color-main-7); }
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## HTML 完整骨架
|
|
411
|
+
|
|
412
|
+
```html
|
|
413
|
+
<!-- 遮罩 -->
|
|
414
|
+
<div class="overlay show" id="pickerOverlay" onclick="closePicker()"></div>
|
|
415
|
+
|
|
416
|
+
<!-- 选择器面板 -->
|
|
417
|
+
<div class="picker-panel" id="pickerPanel">
|
|
418
|
+
<!-- 头部 -->
|
|
419
|
+
<div class="picker-header">
|
|
420
|
+
<p class="picker-header-title">测试组件</p>
|
|
421
|
+
<div class="picker-header-close" onclick="closePicker()">×</div>
|
|
422
|
+
</div>
|
|
423
|
+
|
|
424
|
+
<!-- 内容区 -->
|
|
425
|
+
<div class="picker-content">
|
|
426
|
+
<div class="picker-left-panel" id="pickerLeftPanel">
|
|
427
|
+
<!-- JS 动态渲染 -->
|
|
428
|
+
</div>
|
|
429
|
+
<div class="picker-right-panel" id="pickerRightPanel">
|
|
430
|
+
<!-- JS 动态渲染 -->
|
|
431
|
+
</div>
|
|
432
|
+
</div>
|
|
433
|
+
|
|
434
|
+
<!-- 底部操作 -->
|
|
435
|
+
<div class="picker-bottom">
|
|
436
|
+
<div class="picker-divider"></div>
|
|
437
|
+
<div class="picker-bottom-row">
|
|
438
|
+
<button class="picker-btn-cancel" onclick="closePicker()">取消</button>
|
|
439
|
+
<button class="picker-btn-confirm" onclick="confirmPicker()">确定</button>
|
|
440
|
+
</div>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## JS 交互逻辑
|
|
448
|
+
|
|
449
|
+
```javascript
|
|
450
|
+
// 选择器数据
|
|
451
|
+
let pickerData = {
|
|
452
|
+
leftOptions: [
|
|
453
|
+
{ id: 'dest', name: '目的', selected: true },
|
|
454
|
+
{ id: 'transit', name: '经停', selected: false }
|
|
455
|
+
],
|
|
456
|
+
rightOptions: {
|
|
457
|
+
dest: [
|
|
458
|
+
{ id: 'p1', name: '深圳坂田营业部' },
|
|
459
|
+
{ id: 'p2', name: '广州天河营业部' },
|
|
460
|
+
{ id: 'p3', name: '东莞南城营业部' },
|
|
461
|
+
{ id: 'p4', name: '佛山禅城营业部' },
|
|
462
|
+
{ id: 'p5', name: '珠海香洲营业部' }
|
|
463
|
+
],
|
|
464
|
+
transit: [
|
|
465
|
+
{ id: 't1', name: '北京朝阳中转场' },
|
|
466
|
+
{ id: 't2', name: '上海虹桥中转场' },
|
|
467
|
+
{ id: 't3', name: '成都双流中转场' }
|
|
468
|
+
]
|
|
469
|
+
},
|
|
470
|
+
currentCategory: 'dest',
|
|
471
|
+
selectedId: null // 单选:只存一个 ID
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
// 切换左列分类
|
|
475
|
+
function switchLeftCategory(categoryId) {
|
|
476
|
+
pickerData.leftOptions.forEach(item => {
|
|
477
|
+
item.selected = (item.id === categoryId);
|
|
478
|
+
});
|
|
479
|
+
pickerData.currentCategory = categoryId;
|
|
480
|
+
pickerData.selectedId = null; // 切换左列时清空右列选中
|
|
481
|
+
renderLeftPanel();
|
|
482
|
+
renderRightPanel();
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// 切换右列单选
|
|
486
|
+
function selectRightOption(optionId) {
|
|
487
|
+
// 单选互斥:点击同一项则取消,否则切换
|
|
488
|
+
pickerData.selectedId = (pickerData.selectedId === optionId) ? null : optionId;
|
|
489
|
+
renderRightPanel();
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// 确定
|
|
493
|
+
function confirmPicker() {
|
|
494
|
+
if (!pickerData.selectedId) {
|
|
495
|
+
showToast('请先选择一个选项');
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const options = pickerData.rightOptions[pickerData.currentCategory];
|
|
499
|
+
const selected = options.find(o => o.id === pickerData.selectedId);
|
|
500
|
+
if (selected) {
|
|
501
|
+
onPickerConfirm(selected);
|
|
502
|
+
}
|
|
503
|
+
closePicker();
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// 关闭
|
|
507
|
+
function closePicker() {
|
|
508
|
+
document.getElementById('pickerOverlay').classList.remove('show');
|
|
509
|
+
}
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
## ⚙️ PDA 工业场景硬性约束
|
|
515
|
+
|
|
516
|
+
| # | 约束 | 值 | 原因 |
|
|
517
|
+
|---|------|-----|------|
|
|
518
|
+
| 1 | 最小触控热区 | 左列行高 **70px** / 右列行高 **70px** / 底部按钮 **64px** | 仓储手套操作 / 手指粗 |
|
|
519
|
+
| 2 | 操作元素间距 | 按钮间距 **16px**,右列行间用 **分割线** 分隔 | 防止误触 |
|
|
520
|
+
| 3 | 背景-文字对比度 | **≥ 4.5:1**(WCAG AA) | 室外强光可读 |
|
|
521
|
+
| 4 | 面板最大高度 | **max-height: 740px**(默认 477px,可滚动至 740px) | 不超过屏幕 70% |
|
|
522
|
+
| 5 | 禁用装饰 | ❌ 渐变 / ❌ 阴影 / ❌ 半透明叠加 | PDA 极简原则 |
|
|
523
|
+
| 6 | 字体下界 | 标题 ≥ 24px,行文字 ≥ 18px | 小屏可读性底线 |
|
|
524
|
+
| 7 | 左列联动 | 左列选中 → 右列内容替换 + 清空选中,不可解绑 | 选择器核心交互 |
|
|
525
|
+
| 8 | 单选互斥 | 右侧同一分类下仅一项可选 | 单选行为定义 |
|
|
526
|
+
| 9 | 确认提交 | 未选时点击确定 → 提示"请先选择一个选项" | 防止误操作 |
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
## 使用规则(AI 必读)
|
|
531
|
+
|
|
532
|
+
### 第 1 层:绝对禁止(违反即错误)
|
|
533
|
+
|
|
534
|
+
- ❌ 左列和右列独立渲染、不联动 → ✅ 左列切换时右列必须重新加载数据并清空选中
|
|
535
|
+
- ❌ 底部按钮文本用 Hex 颜色 → ✅ `--color-grey-6` / `--color-grey-1`
|
|
536
|
+
- ❌ 面板高度超过 `740px` → ✅ `max-height: 740px`
|
|
537
|
+
- ❌ 右列选项行高小于 48px → ✅ `70px`
|
|
538
|
+
|
|
539
|
+
### 第 2 层:状态规则
|
|
540
|
+
|
|
541
|
+
- ✅ 左列必须有选中/默认两态(背景颜色 + 左侧紫色指示线 + 文字颜色)
|
|
542
|
+
- ✅ 右列单选指示器必须有未选/已选两态(空心圆 / 实心圆 + 内白点)
|
|
543
|
+
- ✅ 切换左列分类时右列选中自动清空
|
|
544
|
+
- ✅ 取消/关闭均不保存已选结果
|
|
545
|
+
|
|
546
|
+
### 第 3 层:组合规则
|
|
547
|
+
|
|
548
|
+
- ✅ 默认打开时,左列第一项自动选中,右列加载对应数据
|
|
549
|
+
- ✅ 单选互斥:点击已选中的项取消选中,点击未选中的项切换选中
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## 🔴 常见 AI 错误 & 自检清单
|
|
554
|
+
|
|
555
|
+
| # | ❌ 错误写法 | ✅ 正确写法 | 为什么 |
|
|
556
|
+
|---|-----------|-----------|--------|
|
|
557
|
+
| 1 | 左列和右列各自独立渲染,无联动 | 左列 `onClick` → `switchLeftCategory(id)` → 重新 `renderRightPanel()` | 选择器核心逻辑 |
|
|
558
|
+
| 2 | 取消按钮未绑定 `closePicker()` | `onclick="closePicker()"` | 取消必须关闭且不保存 |
|
|
559
|
+
| 3 | 单选指示器用方形复选框 | 圆形 `border-radius: 50%`,选中态绿色 `--color-green-6` + `common_ic_check_two` 图标 | 右列为单选 Radio |
|
|
560
|
+
| 4 | 切换左列未清空右列选中 | `pickerData.selectedId = null` 在 `switchLeftCategory` 中 | 避免脏数据 |
|
|
561
|
+
| 5 | 面板高度写死 740px | `height: 477px; max-height: 740px` | 默认 477px |
|
|
562
|
+
| 6 | 多选模式(`selectedIds: []`) | 单选模式(`selectedId: null`),互斥切换 | 设计稿规定右侧为单选 |
|
|
563
|
+
|
|
564
|
+
### 自检
|
|
565
|
+
|
|
566
|
+
```bash
|
|
567
|
+
# 1. 检查左列联动函数
|
|
568
|
+
grep -n 'switchLeftCategory\|renderRightPanel' demo.html
|
|
569
|
+
# ↑ 必须有这两个函数的定义
|
|
570
|
+
|
|
571
|
+
# 2. 检查单选指示器(圆形,非方形)
|
|
572
|
+
grep -n 'picker-radio\|border-radius.*50%' demo.html
|
|
573
|
+
# ↑ 必须是 radio(圆形)
|
|
574
|
+
|
|
575
|
+
# 3. 检查面板高度限制
|
|
576
|
+
grep -n 'max-height.*740' demo.html
|
|
577
|
+
# ↑ 必须有 max-height: 740px
|
|
578
|
+
|
|
579
|
+
# 4. 检查取消按钮
|
|
580
|
+
grep -n 'picker-btn-cancel' demo.html -A2 | grep 'onclick'
|
|
581
|
+
# ↑ 必须绑定 closePicker()
|
|
582
|
+
|
|
583
|
+
# 5. 检查切换左列时清空选中
|
|
584
|
+
grep -n 'selectedId = null' demo.html
|
|
585
|
+
# ↑ switchLeftCategory 中必须有此行
|
|
586
|
+
```
|