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,622 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: camera
|
|
3
|
+
name: 拍照组件
|
|
4
|
+
category: "媒体/Media"
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
source: PDAKit-业务组件
|
|
7
|
+
source_url: https://mastergo.ky-tech.com.cn/goto/U10IsUP5
|
|
8
|
+
source_doc_id: 103417331857122
|
|
9
|
+
component_count: 2
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# 拍照组件 Camera
|
|
13
|
+
|
|
14
|
+
货物拍照组件,用于 PDA 手持终端拍摄货物图片。支持多货物类型切换拍摄、闪光灯控制、已拍缩略图预览。
|
|
15
|
+
|
|
16
|
+
> **核心规则**:全屏拍照取景 + 底部工具栏。左上角示例图可点击放大,货物类型左右切换,每个类型独立计数,右上角完成按钮拍照后变绿。
|
|
17
|
+
> **颜色规则**:全部使用 Token(`--color-{色系}-{色阶}`),禁止 Hex。
|
|
18
|
+
> **字体**:PingFang SC。
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 组件总览
|
|
23
|
+
|
|
24
|
+
| 组件 | 用途 |
|
|
25
|
+
|------|------|
|
|
26
|
+
| 拍照取景区 | 全屏摄像头取景画面(z-index: 0 最底层) |
|
|
27
|
+
| 顶部栏 | 半透明黑底覆盖层,承载示例图 + 完成按钮 |
|
|
28
|
+
| 底部工具栏 | 半透明黑底固定栏,承载类型切换 + 缩略图 + 拍摄按钮 + 闪光灯 |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 1. 布局结构
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
┌── 480px ──────────────────────────┐
|
|
36
|
+
│ │
|
|
37
|
+
│ 摄像头实时画面 │ ← .camera-view(全屏,z-index: 0)
|
|
38
|
+
│ │
|
|
39
|
+
│ │
|
|
40
|
+
│ ┌────────────────────────────────┐ │ ← .camera-top-bar
|
|
41
|
+
│ │ ┌──────┐ ┌──────┐ │ │ 背景 rgba(0,0,0,0.6)
|
|
42
|
+
│ │ │示例图 │ │ 完成 │ │ │ 绝对定位 top:0, z-index: 2
|
|
43
|
+
│ │ └──────┘ └──────┘ │ │
|
|
44
|
+
│ └────────────────────────────────┘ │
|
|
45
|
+
│ │
|
|
46
|
+
├───────────────────────────────────┤
|
|
47
|
+
│ ┌────────────────────────────────┐ │ ← .camera-toolbar
|
|
48
|
+
│ │ 类型标签滑动区(居中滚动) │ │ 背景 rgba(0,0,0,0.6)
|
|
49
|
+
│ ├────────────────────────────────┤ │ 绝对定位 bottom:0, z-index: 2
|
|
50
|
+
│ │ [缩略图] [拍摄] [闪光灯] │ │ 高度 216px
|
|
51
|
+
│ └────────────────────────────────┘ │
|
|
52
|
+
└───────────────────────────────────┘
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 2. 拍照取景区(全屏背景)
|
|
56
|
+
|
|
57
|
+
| 属性 | 值 |
|
|
58
|
+
|------|------|
|
|
59
|
+
| 定位 | `position: absolute; top: 0; left: 0; width: 100%; height: 100%` |
|
|
60
|
+
| z-index | `0`(最底层) |
|
|
61
|
+
| 背景 | 摄像头实时画面 |
|
|
62
|
+
| 布局 | `display: flex; justify-content: center; align-items: center` |
|
|
63
|
+
|
|
64
|
+
## 3. 顶部栏
|
|
65
|
+
|
|
66
|
+
| 属性 | 值 |
|
|
67
|
+
|------|------|
|
|
68
|
+
| 定位 | `position: absolute; top: 0; left: 0; width: 100%` |
|
|
69
|
+
| 背景 | `rgba(0, 0, 0, 0.6)` |
|
|
70
|
+
| 内边距 | `12px` |
|
|
71
|
+
| 布局 | `display: flex; justify-content: space-between; align-items: center` |
|
|
72
|
+
| z-index | `2` |
|
|
73
|
+
|
|
74
|
+
### 示例图
|
|
75
|
+
|
|
76
|
+
| 属性 | 值 |
|
|
77
|
+
|------|------|
|
|
78
|
+
| 尺寸 | `68×68px`,圆角 `4px`,白色边框 `2px` |
|
|
79
|
+
| 交互 | 点击弹出全屏大图预览 |
|
|
80
|
+
|
|
81
|
+
### 完成按钮
|
|
82
|
+
|
|
83
|
+
| 属性 | 值 |
|
|
84
|
+
|------|------|
|
|
85
|
+
| 尺寸 | `80×48px`,圆角 `4px` |
|
|
86
|
+
| 布局 | `display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 12px` |
|
|
87
|
+
| z-index | `1` |
|
|
88
|
+
| 未拍照态 | `background: #FFFFFF`,文字 `#333333`,文字 `关闭`,点击退出相机 |
|
|
89
|
+
| 已拍照态 | `background: --color-green-6`(`#03C15F`),文字 `--color-grey-1`(白色),文字 `完成`,点击保存回传数据 |
|
|
90
|
+
| 文字 | 字号 `16px`,字重 `600` |
|
|
91
|
+
| 交互 | 未拍照点击退出相机;已拍照点击保存数据并返回列表 |
|
|
92
|
+
|
|
93
|
+
## 4. 底部工具栏
|
|
94
|
+
|
|
95
|
+
| 属性 | 值 |
|
|
96
|
+
|------|------|
|
|
97
|
+
| 定位 | `position: absolute; bottom: 0; left: 0; width: 100%` |
|
|
98
|
+
| 高度 | `216px` |
|
|
99
|
+
| 背景 | `rgba(0, 0, 0, 0.6)` |
|
|
100
|
+
| z-index | `2` |
|
|
101
|
+
| 布局 | `display: flex; flex-direction: column` |
|
|
102
|
+
|
|
103
|
+
#### 货物类型切换区
|
|
104
|
+
|
|
105
|
+
| 属性 | 值 |
|
|
106
|
+
|------|------|
|
|
107
|
+
| 布局 | `flex-shrink: 0; display: flex; align-items: center; gap: 12px` |
|
|
108
|
+
| 内边距 | `12px calc(240px - 70px) 0`(左右对称留白使首尾标签均可滚动至居中) |
|
|
109
|
+
| 排列 | 水平滚动,`overflow-x: auto`,隐藏滚动条,`scroll-behavior: smooth` |
|
|
110
|
+
| 类型标签 | 内边距 `8px 16px`,圆角 `20px`(胶囊形) |
|
|
111
|
+
| 选中态 | 背景 `--color-yellow-5`(`#ffb530`),文字 `--color-black-7`(`#000000`),字重 `600` |
|
|
112
|
+
| 未选中态 | 背景 `transparent`,文字 `--color-grey-1` |
|
|
113
|
+
| 字体 | `16px / 22px`,PingFang SC |
|
|
114
|
+
| 数量显示 | 文字后空格 + 数字徽章:`20px` 高 Black/NO.7 背景圆角胶囊,包裹 `14px` 白色文字,如 `货物类型 0` |
|
|
115
|
+
| 切换手势 | 左右滑动或点击类型标签切换,切换后已选中类型自动滚动至居中 |
|
|
116
|
+
|
|
117
|
+
#### 已拍缩略图
|
|
118
|
+
|
|
119
|
+
| 属性 | 值 |
|
|
120
|
+
|------|------|
|
|
121
|
+
| 尺寸 | `74×74px`,圆角 `6px` |
|
|
122
|
+
| 描边 | `1px solid --color-grey-1` |
|
|
123
|
+
| 位置 | 底部工具栏左侧,距左 `32px`,垂直居中 |
|
|
124
|
+
| 默认态 | 无缩略图时显示虚线边框占位 |
|
|
125
|
+
|
|
126
|
+
#### 拍摄按钮
|
|
127
|
+
|
|
128
|
+
| 属性 | 值 |
|
|
129
|
+
|------|------|
|
|
130
|
+
| 尺寸 | `100×100px`,圆形 |
|
|
131
|
+
| 外环 | `12px solid #ffffff`(白色粗圆环) |
|
|
132
|
+
| 内圆 | `60×60px`,`background: transparent`(透明镂空) |
|
|
133
|
+
| 位置 | 底部工具栏水平居中 |
|
|
134
|
+
| 交互 | 点击触发拍照 |
|
|
135
|
+
| 动效 | 点击时缩放 0.92,`150ms` |
|
|
136
|
+
|
|
137
|
+
#### 闪光灯按钮
|
|
138
|
+
|
|
139
|
+
| 属性 | 值 |
|
|
140
|
+
|------|------|
|
|
141
|
+
| 尺寸 | `72×72px` |
|
|
142
|
+
| 图标 | `拍照示例图/拍照-手电筒/OFF.svg`(关闭)/ `ON.svg`(开启),填满按钮 |
|
|
143
|
+
| 位置 | 底部工具栏右侧,距右 `32px`,垂直居中 |
|
|
144
|
+
| 交互 | 点击切换闪光灯 ON/OFF |
|
|
145
|
+
| 背景 | `rgba(51,51,51,0.8)` 黑色半透明圆形底 |
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 5. 示例图放大预览
|
|
150
|
+
|
|
151
|
+
| 属性 | 值 |
|
|
152
|
+
|------|------|
|
|
153
|
+
| 触发 | 点击左上角示例图 |
|
|
154
|
+
| 展示 | 全屏黑色遮罩(`rgba(0,0,0,0.9)`),图片居中展示,上层叠加类型名称(100px/600、50% 透明度黑色,绝对定位居中) |
|
|
155
|
+
| 关闭 | 点击遮罩任意位置关闭 |
|
|
156
|
+
| z-index | `950` |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## CSS 示例
|
|
161
|
+
|
|
162
|
+
```css
|
|
163
|
+
/* ===== 拍照取景区(全屏背景) ===== */
|
|
164
|
+
.camera-view {
|
|
165
|
+
position: absolute;
|
|
166
|
+
top: 0; left: 0;
|
|
167
|
+
width: 100%; height: 100%;
|
|
168
|
+
background: #1a1a1a;
|
|
169
|
+
overflow: hidden;
|
|
170
|
+
display: flex;
|
|
171
|
+
justify-content: center;
|
|
172
|
+
align-items: center;
|
|
173
|
+
z-index: 0;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* ===== 顶部栏 ===== */
|
|
177
|
+
.camera-top-bar {
|
|
178
|
+
position: absolute;
|
|
179
|
+
top: 0; left: 0;
|
|
180
|
+
width: 100%;
|
|
181
|
+
display: flex;
|
|
182
|
+
justify-content: space-between;
|
|
183
|
+
align-items: center;
|
|
184
|
+
padding: 12px;
|
|
185
|
+
background: rgba(0, 0, 0, 0.6);
|
|
186
|
+
z-index: 2;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.camera-sample {
|
|
190
|
+
width: 68px; height: 68px;
|
|
191
|
+
border-radius: 4px;
|
|
192
|
+
border: 2px solid var(--color-grey-1);
|
|
193
|
+
object-fit: cover;
|
|
194
|
+
cursor: pointer;
|
|
195
|
+
background: #333;
|
|
196
|
+
flex-shrink: 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.camera-done {
|
|
200
|
+
width: 80px;
|
|
201
|
+
height: 48px;
|
|
202
|
+
border-radius: 4px;
|
|
203
|
+
border: none;
|
|
204
|
+
display: flex;
|
|
205
|
+
flex-direction: column;
|
|
206
|
+
justify-content: center;
|
|
207
|
+
align-items: center;
|
|
208
|
+
padding: 12px;
|
|
209
|
+
color: var(--color-grey-1);
|
|
210
|
+
font-size: 16px; font-weight: 600;
|
|
211
|
+
font-family: PingFang SC;
|
|
212
|
+
cursor: pointer;
|
|
213
|
+
z-index: 1;
|
|
214
|
+
transition: background 0.3s, opacity 0.3s;
|
|
215
|
+
}
|
|
216
|
+
.camera-done.inactive {
|
|
217
|
+
background: #FFFFFF;
|
|
218
|
+
color: #333333;
|
|
219
|
+
pointer-events: auto;
|
|
220
|
+
}
|
|
221
|
+
.camera-done.active {
|
|
222
|
+
background: var(--color-green-6);
|
|
223
|
+
color: var(--color-grey-1);
|
|
224
|
+
pointer-events: auto;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* ===== 底部工具栏 ===== */
|
|
228
|
+
.camera-toolbar {
|
|
229
|
+
position: absolute;
|
|
230
|
+
bottom: 0; left: 0;
|
|
231
|
+
width: 100%;
|
|
232
|
+
height: 216px;
|
|
233
|
+
background: rgba(0, 0, 0, 0.6);
|
|
234
|
+
display: flex;
|
|
235
|
+
flex-direction: column;
|
|
236
|
+
z-index: 2;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* 货物类型切换区 */
|
|
240
|
+
.camera-types {
|
|
241
|
+
flex-shrink: 0;
|
|
242
|
+
display: flex;
|
|
243
|
+
align-items: center;
|
|
244
|
+
gap: 12px;
|
|
245
|
+
padding: 12px calc(240px - 70px) 0;
|
|
246
|
+
overflow-x: auto;
|
|
247
|
+
scrollbar-width: none;
|
|
248
|
+
scroll-behavior: smooth;
|
|
249
|
+
}
|
|
250
|
+
.camera-types::-webkit-scrollbar { display: none; }
|
|
251
|
+
|
|
252
|
+
.camera-type-tag {
|
|
253
|
+
padding: 8px 16px;
|
|
254
|
+
border-radius: 20px;
|
|
255
|
+
font-size: 16px;
|
|
256
|
+
line-height: 22px;
|
|
257
|
+
font-family: PingFang SC;
|
|
258
|
+
white-space: nowrap;
|
|
259
|
+
cursor: pointer;
|
|
260
|
+
flex-shrink: 0;
|
|
261
|
+
display: flex;
|
|
262
|
+
align-items: center;
|
|
263
|
+
gap: 6px;
|
|
264
|
+
transition: background 0.2s, color 0.2s;
|
|
265
|
+
user-select: none;
|
|
266
|
+
}
|
|
267
|
+
.camera-type-tag.active {
|
|
268
|
+
background: var(--color-yellow-5);
|
|
269
|
+
color: var(--color-black-7);
|
|
270
|
+
font-weight: 600;
|
|
271
|
+
}
|
|
272
|
+
.camera-type-tag:not(.active) {
|
|
273
|
+
background: transparent;
|
|
274
|
+
color: var(--color-grey-1);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.camera-type-count {
|
|
278
|
+
display: inline-flex;
|
|
279
|
+
justify-content: center;
|
|
280
|
+
align-items: center;
|
|
281
|
+
min-width: 20px;
|
|
282
|
+
height: 20px;
|
|
283
|
+
padding: 0 4px;
|
|
284
|
+
border-radius: 10px;
|
|
285
|
+
background: var(--color-black-7);
|
|
286
|
+
color: var(--color-grey-1);
|
|
287
|
+
font-size: 14px;
|
|
288
|
+
line-height: 20px;
|
|
289
|
+
font-weight: 600;
|
|
290
|
+
font-family: PingFang SC;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/* 底部操作区 */
|
|
294
|
+
.camera-actions {
|
|
295
|
+
flex: 1;
|
|
296
|
+
display: flex;
|
|
297
|
+
justify-content: space-between;
|
|
298
|
+
align-items: center;
|
|
299
|
+
padding: 0 32px;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* 已拍缩略图 */
|
|
303
|
+
.camera-thumb-wrap {
|
|
304
|
+
width: 74px; height: 74px;
|
|
305
|
+
flex-shrink: 0;
|
|
306
|
+
}
|
|
307
|
+
.camera-thumb {
|
|
308
|
+
width: 74px; height: 74px;
|
|
309
|
+
border-radius: 6px;
|
|
310
|
+
border: 1px solid var(--color-grey-1);
|
|
311
|
+
object-fit: cover;
|
|
312
|
+
display: none;
|
|
313
|
+
cursor: pointer;
|
|
314
|
+
}
|
|
315
|
+
.camera-thumb-placeholder {
|
|
316
|
+
width: 74px; height: 74px;
|
|
317
|
+
border-radius: 6px;
|
|
318
|
+
border: 1px dashed rgba(255,255,255,0.3);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* 拍摄按钮 */
|
|
322
|
+
.camera-shutter-outer {
|
|
323
|
+
width: 100px; height: 100px;
|
|
324
|
+
border-radius: 50%;
|
|
325
|
+
border: 12px solid #ffffff;
|
|
326
|
+
display: flex; justify-content: center; align-items: center;
|
|
327
|
+
flex-shrink: 0;
|
|
328
|
+
cursor: pointer;
|
|
329
|
+
transition: transform 0.15s;
|
|
330
|
+
}
|
|
331
|
+
.camera-shutter-outer:active { transform: scale(0.92); }
|
|
332
|
+
.camera-shutter-inner {
|
|
333
|
+
width: 60px; height: 60px;
|
|
334
|
+
border-radius: 50%;
|
|
335
|
+
background: transparent;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* 闪光灯按钮 */
|
|
339
|
+
.camera-flash {
|
|
340
|
+
width: 72px; height: 72px;
|
|
341
|
+
border-radius: 50%;
|
|
342
|
+
background: rgba(51,51,51,0.8);
|
|
343
|
+
display: flex; justify-content: center; align-items: center;
|
|
344
|
+
flex-shrink: 0;
|
|
345
|
+
cursor: pointer;
|
|
346
|
+
border: none;
|
|
347
|
+
padding: 0;
|
|
348
|
+
transition: background 0.2s;
|
|
349
|
+
}
|
|
350
|
+
.camera-flash img { width: 100%; height: 100%; }
|
|
351
|
+
|
|
352
|
+
/* ===== 示例图放大遮罩 ===== */
|
|
353
|
+
.camera-preview-overlay {
|
|
354
|
+
position: fixed; top: 0; left: 0;
|
|
355
|
+
width: 100vw; height: 100vh;
|
|
356
|
+
background: rgba(0,0,0,0.9);
|
|
357
|
+
z-index: 950;
|
|
358
|
+
display: none;
|
|
359
|
+
justify-content: center;
|
|
360
|
+
align-items: center;
|
|
361
|
+
cursor: pointer;
|
|
362
|
+
overflow: hidden;
|
|
363
|
+
}
|
|
364
|
+
.camera-preview-overlay.show { display: flex; }
|
|
365
|
+
.camera-preview-overlay img {
|
|
366
|
+
max-width: 90vw;
|
|
367
|
+
max-height: 80vh;
|
|
368
|
+
object-fit: contain;
|
|
369
|
+
border-radius: 4px;
|
|
370
|
+
}
|
|
371
|
+
.camera-preview-title {
|
|
372
|
+
position: absolute;
|
|
373
|
+
top: 50%;
|
|
374
|
+
left: 50%;
|
|
375
|
+
transform: translate(-50%, -50%);
|
|
376
|
+
font-size: 100px;
|
|
377
|
+
font-weight: 600;
|
|
378
|
+
line-height: 1;
|
|
379
|
+
color: rgba(0, 0, 0, 0.5);
|
|
380
|
+
text-align: center;
|
|
381
|
+
font-family: PingFang SC;
|
|
382
|
+
white-space: nowrap;
|
|
383
|
+
pointer-events: none;
|
|
384
|
+
z-index: 1;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/* 拍后闪光效果 */
|
|
388
|
+
.camera-flash-effect {
|
|
389
|
+
position: absolute;
|
|
390
|
+
top: 0; left: 0;
|
|
391
|
+
width: 100%; height: 100%;
|
|
392
|
+
background: #fff;
|
|
393
|
+
opacity: 0;
|
|
394
|
+
pointer-events: none;
|
|
395
|
+
z-index: 20;
|
|
396
|
+
transition: opacity 0.08s;
|
|
397
|
+
}
|
|
398
|
+
.camera-flash-effect.fire { opacity: 0.9; }
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## 资源引用说明
|
|
404
|
+
|
|
405
|
+
### 示例图路径
|
|
406
|
+
|
|
407
|
+
拍照组件使用的示例图统一存放在 `拍照示例图/` 目录下:
|
|
408
|
+
|
|
409
|
+
```
|
|
410
|
+
拍照示例图/
|
|
411
|
+
├── 拍照-手电筒/
|
|
412
|
+
│ ├── OFF.svg # 闪光灯关闭图标
|
|
413
|
+
│ └── ON.svg # 闪光灯开启图标
|
|
414
|
+
├── 角标.svg # 示例图角标(photo-list 使用)
|
|
415
|
+
├── 货物完整@8x.png # 货物完整拍照示例
|
|
416
|
+
├── 外包装全貌照@8x.png # 外包装全貌拍照示例
|
|
417
|
+
├── 开箱点数@8x.png # 开箱点数拍照示例
|
|
418
|
+
└── ... # 其他拍照类型示例图
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**引用方式**:
|
|
422
|
+
- 如果 HTML 文件在 `demos/` 目录:
|
|
423
|
+
- 示例图:`../拍照示例图/货物完整@8x.png`
|
|
424
|
+
- 闪光灯图标:`../拍照示例图/拍照-手电筒/OFF.svg`
|
|
425
|
+
- 如果 HTML 文件在根目录:
|
|
426
|
+
- 示例图:`./拍照示例图/货物完整@8x.png`
|
|
427
|
+
- 闪光灯图标:`./拍照示例图/拍照-手电筒/OFF.svg`
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## HTML 骨架
|
|
432
|
+
|
|
433
|
+
```html
|
|
434
|
+
<!-- 拍照组件完整结构示例 -->
|
|
435
|
+
<!-- 假设 HTML 文件位于 demos/ 目录 -->
|
|
436
|
+
|
|
437
|
+
<!-- 拍照取景区(全屏背景) -->
|
|
438
|
+
<div class="camera-view" id="cameraView">
|
|
439
|
+
<!-- 摄像头画面 -->
|
|
440
|
+
<div class="camera-flash-effect" id="flashEffect"></div>
|
|
441
|
+
</div>
|
|
442
|
+
|
|
443
|
+
<!-- 顶部栏 -->
|
|
444
|
+
<div class="camera-top-bar">
|
|
445
|
+
<img class="camera-sample" id="cameraSample"
|
|
446
|
+
src="../拍照示例图/货物完整@8x.png"
|
|
447
|
+
alt="示例图" onclick="openPreview()" />
|
|
448
|
+
<button class="camera-done inactive" id="btnDone"
|
|
449
|
+
onclick="onComplete()">关闭</button>
|
|
450
|
+
</div>
|
|
451
|
+
|
|
452
|
+
<!-- 底部工具栏 -->
|
|
453
|
+
<div class="camera-toolbar">
|
|
454
|
+
<div class="camera-types" id="cameraTypes">
|
|
455
|
+
<!-- JS 动态渲染类型标签 -->
|
|
456
|
+
</div>
|
|
457
|
+
<div class="camera-actions">
|
|
458
|
+
<div class="camera-thumb-wrap">
|
|
459
|
+
<img class="camera-thumb" id="thumbPreview" alt="已拍" />
|
|
460
|
+
<div class="camera-thumb-placeholder" id="thumbPlaceholder"></div>
|
|
461
|
+
</div>
|
|
462
|
+
<div class="camera-shutter-outer" onclick="takePhoto()">
|
|
463
|
+
<div class="camera-shutter-inner"></div>
|
|
464
|
+
</div>
|
|
465
|
+
<button class="camera-flash" onclick="toggleFlash()">
|
|
466
|
+
<img id="flashIcon" src="../拍照示例图/拍照-手电筒/OFF.svg" alt="闪光灯" />
|
|
467
|
+
</button>
|
|
468
|
+
</div>
|
|
469
|
+
</div>
|
|
470
|
+
|
|
471
|
+
<!-- 示例图放大预览 -->
|
|
472
|
+
<div class="camera-preview-overlay" id="previewOverlay"
|
|
473
|
+
onclick="closePreview()">
|
|
474
|
+
<p class="camera-preview-title" id="previewTitle"></p>
|
|
475
|
+
<img id="previewImage" src="" alt="预览" />
|
|
476
|
+
</div>
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## JS 交互示例
|
|
482
|
+
|
|
483
|
+
```javascript
|
|
484
|
+
// 货物类型数据(支持从 URL 参数接收拍照列表传入的类型)
|
|
485
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
486
|
+
const typesParam = urlParams.get('types');
|
|
487
|
+
const sourceEntryIndex = urlParams.get('entryIndex');
|
|
488
|
+
|
|
489
|
+
// 注意:路径根据 HTML 文件位置调整
|
|
490
|
+
// 如果 HTML 在 demos/ 目录,使用 ../拍照示例图/
|
|
491
|
+
// 如果 HTML 在根目录,使用 ./拍照示例图/
|
|
492
|
+
const allPhotoTypes = [
|
|
493
|
+
{ name: '货物完整', count: 0, sample: '../拍照示例图/货物完整@8x.png' },
|
|
494
|
+
{ name: '外包装全貌照', count: 0, sample: '../拍照示例图/外包装全貌照@8x.png' },
|
|
495
|
+
{ name: '开箱点数', count: 0, sample: '../拍照示例图/开箱点数@8x.png' },
|
|
496
|
+
{ name: '破损近景图', count: 0, sample: '../拍照示例图/破损近景图@8x.png' }
|
|
497
|
+
];
|
|
498
|
+
|
|
499
|
+
// 根据 URL 筛选类型(无参数默认全部)
|
|
500
|
+
let photoTypes;
|
|
501
|
+
if (typesParam) {
|
|
502
|
+
const typeNames = typesParam.split(',').map(s => s.trim());
|
|
503
|
+
photoTypes = allPhotoTypes.filter(t => typeNames.includes(t.name));
|
|
504
|
+
if (photoTypes.length === 0) photoTypes = allPhotoTypes;
|
|
505
|
+
} else {
|
|
506
|
+
photoTypes = allPhotoTypes;
|
|
507
|
+
}
|
|
508
|
+
let currentTypeIndex = 0;
|
|
509
|
+
let flashOn = false;
|
|
510
|
+
|
|
511
|
+
// 切换货物类型
|
|
512
|
+
function switchType(index) {
|
|
513
|
+
if (index === currentTypeIndex) return;
|
|
514
|
+
currentTypeIndex = index;
|
|
515
|
+
renderTypes();
|
|
516
|
+
scrollToCenter(index);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// 选中类型滚动至居中
|
|
520
|
+
function scrollToCenter(index) {
|
|
521
|
+
const container = document.getElementById('cameraTypes');
|
|
522
|
+
const tag = container.children[index];
|
|
523
|
+
if (!tag) return;
|
|
524
|
+
const offset = tag.offsetLeft - container.offsetWidth / 2 + tag.offsetWidth / 2;
|
|
525
|
+
container.scrollTo({ left: offset, behavior: 'smooth' });
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// 拍照
|
|
529
|
+
function takePhoto() {
|
|
530
|
+
photoTypes[currentTypeIndex].count++;
|
|
531
|
+
renderTypes();
|
|
532
|
+
scrollToCenter(currentTypeIndex);
|
|
533
|
+
updateDoneButton();
|
|
534
|
+
// 闪光效果
|
|
535
|
+
document.getElementById('flashEffect').classList.add('fire');
|
|
536
|
+
setTimeout(() => document.getElementById('flashEffect').classList.remove('fire'), 100);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// 闪光灯
|
|
540
|
+
function toggleFlash() {
|
|
541
|
+
flashOn = !flashOn;
|
|
542
|
+
// 注意:路径根据 HTML 文件位置调整
|
|
543
|
+
document.getElementById('flashIcon').src =
|
|
544
|
+
`../拍照示例图/拍照-手电筒/${flashOn ? 'ON' : 'OFF'}.svg`;
|
|
545
|
+
// TODO: 调用设备闪光灯 API
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// 更新按钮状态(切换「关闭」/「完成」)
|
|
549
|
+
function updateDoneButton() {
|
|
550
|
+
const total = photoTypes.reduce((sum, t) => sum + t.count, 0);
|
|
551
|
+
const btn = document.getElementById('btnDone');
|
|
552
|
+
if (total > 0) {
|
|
553
|
+
btn.textContent = '完成';
|
|
554
|
+
btn.classList.remove('inactive');
|
|
555
|
+
btn.classList.add('active');
|
|
556
|
+
} else {
|
|
557
|
+
btn.textContent = '关闭';
|
|
558
|
+
btn.classList.add('inactive');
|
|
559
|
+
btn.classList.remove('active');
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// 示例图放大预览
|
|
564
|
+
function openPreview() {
|
|
565
|
+
const type = photoTypes[currentTypeIndex];
|
|
566
|
+
document.getElementById('previewTitle').textContent = type.name;
|
|
567
|
+
document.getElementById('previewImage').src = type.sample;
|
|
568
|
+
document.getElementById('previewOverlay').classList.add('show');
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function closePreview() {
|
|
572
|
+
document.getElementById('previewOverlay').classList.remove('show');
|
|
573
|
+
document.getElementById('previewTitle').textContent = '';
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// 关闭 / 完成
|
|
577
|
+
function onComplete() {
|
|
578
|
+
const total = photoTypes.reduce((sum, t) => sum + t.count, 0);
|
|
579
|
+
if (total > 0) {
|
|
580
|
+
// 已拍照:保存数据,返回列表
|
|
581
|
+
const result = {
|
|
582
|
+
sourceEntryIndex: sourceEntryIndex,
|
|
583
|
+
types: photoTypes.map(t => ({
|
|
584
|
+
name: t.name,
|
|
585
|
+
count: t.count,
|
|
586
|
+
sample: t.sample
|
|
587
|
+
}))
|
|
588
|
+
};
|
|
589
|
+
sessionStorage.setItem('cameraResult', JSON.stringify(result));
|
|
590
|
+
setTimeout(() => { history.back(); }, 800);
|
|
591
|
+
} else {
|
|
592
|
+
// 未拍照:直接退出相机
|
|
593
|
+
history.back();
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
## 颜色 Token
|
|
601
|
+
|
|
602
|
+
| Token | 色值 | 使用场景 |
|
|
603
|
+
|-------|------|---------|
|
|
604
|
+
| `--color-grey-1` | `#FFFFFF` | 拍摄按钮、闪光灯图标、缩略图边框 |
|
|
605
|
+
| `--color-yellow-5` | `#ffb530` | 货物类型标签选中态背景 |
|
|
606
|
+
| `--color-black-7` | `#000000` | 货物类型标签选中文字、数量徽章背景 |
|
|
607
|
+
| `--color-black-4` | `#888888` | 完成按钮(未拍照态)背景 |
|
|
608
|
+
| `--color-green-6` | `#03C15F` | 完成按钮(已拍照态)背景 |
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
## 使用规则(AI 必读)
|
|
613
|
+
|
|
614
|
+
1. **全屏取景**:摄像头画面占满 phone-frame 全部高度,拍照组件不使用导航栏
|
|
615
|
+
2. **货物类型必须可滑动**:类型标签超过屏幕宽度时可左右滑动,隐藏滚动条。**点击切换后已选中标签自动滚动至居中**
|
|
616
|
+
3. **拍摄计数独立**:每个货物类型独立计数,切换类型不丢失之前的计数
|
|
617
|
+
4. **按钮两态**:未拍照时显示「关闭」,白色背景 `#FFFFFF`,黑色文字,点击退出相机;拍照后变「完成」,绿色背景 `--color-green-6`,白色文字,点击保存并返回。按钮规格 `80×48px`,`flex-direction: column`,`padding: 12px`,`z-index: 1`
|
|
618
|
+
5. **闪光灯图标**:使用 `拍照示例图/拍照-手电筒/OFF.svg`(关)和 `ON.svg`(开)
|
|
619
|
+
6. **示例图可放大**:点击左上角示例图弹出全屏预览
|
|
620
|
+
7. **拍照动效**:拍摄按钮点击时 150ms 缩放反馈
|
|
621
|
+
8. **颜色用 Token**:禁止裸 Hex,全部用 `--color-*` 引用
|
|
622
|
+
9. **与拍照列表联动**(⚠️ 强制):页面加载时从 URL 参数 `?types=货物完整,开箱点数&entryIndex=0` 读取拍照类型列表并筛选展示。完成拍摄后通过 `sessionStorage.setItem('cameraResult', JSON.stringify({ types: [{ name, count, sample }] }))` 回传数据,然后 `history.back()` 返回列表页
|