@me-framework/me-sku-editor 1.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.en.md +36 -0
- package/README.md +230 -0
- package/dist/demo/assets/iconfont.1782658269305-Bwz3sFC-.ttf +0 -0
- package/dist/demo/assets/iconfont.1782658269305-CiRZOtYp.woff +0 -0
- package/dist/demo/assets/iconfont.1782890314097-BllfKX1O.ttf +0 -0
- package/dist/demo/assets/iconfont.1782890314097-D9epzWxu.woff +0 -0
- package/dist/demo/assets/index-CLHSZeXE.css +1 -0
- package/dist/demo/assets/index-T0Giuvdt.js +157 -0
- package/dist/demo/favicon.svg +1 -0
- package/dist/demo/icons.svg +24 -0
- package/dist/demo/index.html +14 -0
- package/dist/lib/favicon.svg +1 -0
- package/dist/lib/icons.svg +24 -0
- package/dist/lib/me-sku-editor.css +2 -0
- package/dist/lib/me-sku-editor.mjs +22601 -0
- package/dist/lib/me-sku-editor.umd.js +104 -0
- package/document/prompt/sku-editor.md +268 -0
- package/document//344/275/277/347/224/250/346/226/207/346/241/243.md +1028 -0
- package/document//345/274/200/345/217/221/346/214/207/345/215/227.md +637 -0
- package/document//345/277/253/351/200/237/345/274/200/345/247/213.md +292 -0
- package/package.json +76 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
# 开发指南
|
|
2
|
+
|
|
3
|
+
本指南面向需要对 SkuEditor 进行二次开发或修改的开发者。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
- [项目结构](#项目结构)
|
|
8
|
+
- [核心模块说明](#核心模块说明)
|
|
9
|
+
- [扩展开发](#扩展开发)
|
|
10
|
+
- [样式定制](#样式定制)
|
|
11
|
+
- [常见修改场景](#常见修改场景)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 项目结构
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
src/
|
|
19
|
+
├── components/ # 组件目录
|
|
20
|
+
│ └── sku/ # SKU 相关组件
|
|
21
|
+
│ ├── SkuEditor.vue # 主编辑器组件
|
|
22
|
+
│ ├── SpecSection.vue # 规格管理区域
|
|
23
|
+
│ ├── SkuGrid.vue # SKU 表格区域
|
|
24
|
+
│ └── dialogs/ # 对话框组件
|
|
25
|
+
│ ├── SpecDialog.vue
|
|
26
|
+
│ ├── AttrDialog.vue
|
|
27
|
+
│ └── BatchEditDialog.vue
|
|
28
|
+
├── composables/ # 组合式函数
|
|
29
|
+
│ └── sku/ # SKU 相关逻辑
|
|
30
|
+
│ ├── useSkuGenerator.ts # SKU 生成逻辑
|
|
31
|
+
│ ├── useImportExport.ts # 导入导出逻辑
|
|
32
|
+
│ ├── useSortable.ts # 拖拽排序逻辑
|
|
33
|
+
│ ├── useMergeCells.ts # 单元格合并逻辑
|
|
34
|
+
│ ├── useColumnVisibility.ts # 列可见性管理
|
|
35
|
+
│ └── useValidation.ts # 数据校验逻辑
|
|
36
|
+
├── types/ # 类型定义
|
|
37
|
+
│ └── sku/ # SKU 相关类型
|
|
38
|
+
│ ├── index.ts # 类型导出入口
|
|
39
|
+
│ ├── spec.ts # 规格相关类型
|
|
40
|
+
│ └── sku-row.ts # SKU 行相关类型
|
|
41
|
+
├── constants/ # 常量定义
|
|
42
|
+
│ └── sku.ts # SKU 相关常量
|
|
43
|
+
├── App.vue # 示例应用
|
|
44
|
+
└── main.ts # 入口文件
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 核心模块说明
|
|
50
|
+
|
|
51
|
+
### 1. SkuEditor.vue - 主组件
|
|
52
|
+
|
|
53
|
+
**职责:**
|
|
54
|
+
- 协调各子组件
|
|
55
|
+
- 管理数据状态(外部模式为主)
|
|
56
|
+
- 处理规格和属性的增删改
|
|
57
|
+
- 暴露公共方法
|
|
58
|
+
- 处理内部/外部格式转换
|
|
59
|
+
|
|
60
|
+
**关键数据:**
|
|
61
|
+
```typescript
|
|
62
|
+
// 内部统一 SKU 数据源
|
|
63
|
+
const internalSkuData = ref<SkuRow[]>([])
|
|
64
|
+
|
|
65
|
+
// 同步数据到父组件
|
|
66
|
+
const syncDataToParent = () => {
|
|
67
|
+
if (isUpdatingFromInside.value) return
|
|
68
|
+
isUpdatingFromInside.value = true
|
|
69
|
+
try {
|
|
70
|
+
const external = toExternalFormat(internalSkuData.value, specsRef.value)
|
|
71
|
+
emit('update:skuData', external)
|
|
72
|
+
} finally {
|
|
73
|
+
nextTick(() => {
|
|
74
|
+
isUpdatingFromInside.value = false
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**关键方法:**
|
|
81
|
+
- `saveSpec()` - 保存规格
|
|
82
|
+
- `deleteSpec()` - 删除规格
|
|
83
|
+
- `saveAttr()` - 保存属性
|
|
84
|
+
- `deleteAttr()` - 删除属性
|
|
85
|
+
- `outputData()` - 输出数据到控制台
|
|
86
|
+
- `validateSkuData()` - 校验 SKU 数据
|
|
87
|
+
|
|
88
|
+
**暴露的方法:**
|
|
89
|
+
```typescript
|
|
90
|
+
defineExpose({
|
|
91
|
+
exportExcel,
|
|
92
|
+
exportJson,
|
|
93
|
+
confirmImport,
|
|
94
|
+
confirmImportExcel,
|
|
95
|
+
validateSkuData
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### 2. SpecSection.vue - 规格管理区域
|
|
102
|
+
|
|
103
|
+
**职责:**
|
|
104
|
+
- 展示规格列表
|
|
105
|
+
- 提供规格和属性的操作入口
|
|
106
|
+
- 处理拖拽排序的 DOM 引用
|
|
107
|
+
- 处理文件拖放
|
|
108
|
+
|
|
109
|
+
**关键 Props:**
|
|
110
|
+
```typescript
|
|
111
|
+
interface Props {
|
|
112
|
+
specs: Spec[]
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**关键 Events:**
|
|
117
|
+
```typescript
|
|
118
|
+
interface Emits {
|
|
119
|
+
addSpec: []
|
|
120
|
+
editSpec: [spec: Spec]
|
|
121
|
+
deleteSpec: [spec: Spec]
|
|
122
|
+
addAttribute: [specId: string]
|
|
123
|
+
editAttribute: [spec: Spec, attr: SpecAttribute]
|
|
124
|
+
deleteAttribute: [spec: Spec, attr: SpecAttribute]
|
|
125
|
+
// ... 更多事件
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### 3. SkuGrid.vue - SKU 表格区域
|
|
132
|
+
|
|
133
|
+
**职责:**
|
|
134
|
+
- 展示和编辑 SKU 数据
|
|
135
|
+
- 处理单元格合并
|
|
136
|
+
- 管理列可见性
|
|
137
|
+
- 提供筛选功能
|
|
138
|
+
- 支持行高亮配置
|
|
139
|
+
|
|
140
|
+
**关键技术:**
|
|
141
|
+
- 使用 VXE Table 组件
|
|
142
|
+
- 动态生成列配置
|
|
143
|
+
- 虚拟滚动支持
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### 4. useSkuGenerator.ts - SKU 生成逻辑
|
|
148
|
+
|
|
149
|
+
**核心函数:**
|
|
150
|
+
|
|
151
|
+
#### generateSkuData(specs, existingData?)
|
|
152
|
+
|
|
153
|
+
生成 SKU 组合的核心算法:
|
|
154
|
+
|
|
155
|
+
1. 过滤掉没有属性的规格
|
|
156
|
+
2. 计算笛卡尔积生成所有组合
|
|
157
|
+
3. 保留已有数据中匹配的组合
|
|
158
|
+
|
|
159
|
+
**笛卡尔积实现:**
|
|
160
|
+
```typescript
|
|
161
|
+
const cartesianProduct = (lists: any[][]): any[][] => {
|
|
162
|
+
return lists.reduce((a, b) =>
|
|
163
|
+
a.flatMap(x => b.map(y => [...x, y])),
|
|
164
|
+
[[]]
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**数据匹配逻辑:**
|
|
170
|
+
```typescript
|
|
171
|
+
// 使用规格ID和属性ID组合作为key
|
|
172
|
+
const generateSkuKey = (specsMap: { [key: string]: string }): string => {
|
|
173
|
+
const sortedSpecIds = Object.keys(specsMap).sort()
|
|
174
|
+
return sortedSpecIds.map(specId => `${specId}:${specsMap[specId]}`).join('|')
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### toInternalFormat(externalSkus, specs)
|
|
179
|
+
|
|
180
|
+
将外部格式(使用规格名称和属性名称)转换为内部格式(使用 ID)。
|
|
181
|
+
|
|
182
|
+
#### toExternalFormat(internalSkus, specs)
|
|
183
|
+
|
|
184
|
+
将内部格式转换为外部格式。
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### 5. useImportExport.ts - 导入导出逻辑
|
|
189
|
+
|
|
190
|
+
**Excel 导出格式:**
|
|
191
|
+
- Sheet 1:规格信息(规格序号、规格名称、规格类型、属性序号、属性名称、颜色、图片、内容)
|
|
192
|
+
- Sheet 2:SKU 数据(规格列 + 固定列)
|
|
193
|
+
|
|
194
|
+
**关键处理:**
|
|
195
|
+
- 保留字段名冲突检查(使用 `RESERVED_NAMES` 常量)
|
|
196
|
+
- 属性内容的 JSON 序列化/反序列化
|
|
197
|
+
- 兼容仅含 SKU 数据的 Excel 导入
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### 6. useSortable.ts - 拖拽排序逻辑
|
|
202
|
+
|
|
203
|
+
基于 Sortable.js 实现:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
const initSpecSortable = () => {
|
|
207
|
+
specSortable = new Sortable(el, {
|
|
208
|
+
animation: 150,
|
|
209
|
+
handle: '.drag-handle',
|
|
210
|
+
onEnd: (evt) => { /* 处理排序 */ }
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**注意**:拖拽排序后会自动更新 `sort` 字段。
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
### 7. useValidation.ts - 数据校验逻辑
|
|
220
|
+
|
|
221
|
+
**校验规则配置:**
|
|
222
|
+
```typescript
|
|
223
|
+
interface ValidationRules {
|
|
224
|
+
specs?: boolean // 校验规格
|
|
225
|
+
skuNoDuplication?: boolean // 校验 SKU 编号重复
|
|
226
|
+
requiredFields?: boolean // 校验必填字段
|
|
227
|
+
numericValues?: boolean // 校验数值合理性
|
|
228
|
+
custom?: (specs: any[], skuData: any[]) => ValidationItem[]
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**校验结果:**
|
|
233
|
+
```typescript
|
|
234
|
+
interface ValidationResult {
|
|
235
|
+
valid: boolean
|
|
236
|
+
items: ValidationItem[] // 包含 error 和 warning 类型
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 扩展开发
|
|
243
|
+
|
|
244
|
+
### 添加新的 SKU 字段
|
|
245
|
+
|
|
246
|
+
#### 1. 修改类型定义
|
|
247
|
+
|
|
248
|
+
在 `src/types/sku/sku-row.ts` 中添加字段:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
interface SkuRow {
|
|
252
|
+
// ... 现有字段
|
|
253
|
+
customField?: string // 添加你的自定义字段
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
#### 2. 更新 SkuGrid.vue
|
|
258
|
+
|
|
259
|
+
添加列配置:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
const skuColumns = computed(() => {
|
|
263
|
+
const columns: VxeGridProps['columns'] = []
|
|
264
|
+
|
|
265
|
+
// ... 规格列
|
|
266
|
+
|
|
267
|
+
// 添加自定义列
|
|
268
|
+
columns.push({
|
|
269
|
+
field: 'customField',
|
|
270
|
+
title: '自定义字段',
|
|
271
|
+
width: 150,
|
|
272
|
+
visible: true, // 或在 defaultColumnVisibility 中配置
|
|
273
|
+
slots: { default: 'customField' },
|
|
274
|
+
editRender: { name: 'VxeInput' } // 可编辑
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
// ... 其他列
|
|
278
|
+
return columns
|
|
279
|
+
})
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
添加模板插槽:
|
|
283
|
+
|
|
284
|
+
```vue
|
|
285
|
+
<template #customField="{ row }">
|
|
286
|
+
{{ row.customField || '-' }}
|
|
287
|
+
</template>
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### 3. 更新 useImportExport.ts
|
|
291
|
+
|
|
292
|
+
在导出和导入逻辑中添加对新字段的处理:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// 导出时
|
|
296
|
+
rowData['自定义字段'] = row.customField
|
|
297
|
+
|
|
298
|
+
// 导入时
|
|
299
|
+
tempSkuData.push({
|
|
300
|
+
// ... 其他字段
|
|
301
|
+
customField: row['自定义字段']
|
|
302
|
+
})
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### 4. 更新默认列可见性(可选)
|
|
306
|
+
|
|
307
|
+
在 `useColumnVisibility.ts` 中:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
export const defaultColumnVisibility: ColumnVisibilityState = {
|
|
311
|
+
specColumns: {},
|
|
312
|
+
fixedColumns: {
|
|
313
|
+
// ... 现有字段
|
|
314
|
+
customField: true // 添加新字段
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
#### 5. 更新批量编辑对话框(可选)
|
|
320
|
+
|
|
321
|
+
在 `BatchEditDialog.vue` 中添加批量设置选项。
|
|
322
|
+
|
|
323
|
+
#### 6. 更新数据校验(可选)
|
|
324
|
+
|
|
325
|
+
在 `useValidation.ts` 中添加对新字段的校验。
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
### 添加新的规格类型
|
|
330
|
+
|
|
331
|
+
#### 1. 修改类型定义
|
|
332
|
+
|
|
333
|
+
在 `src/types/sku/spec.ts` 中:
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
export type SpecType = 'text' | 'color' | 'image' | 'yourType'
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
#### 2. 更新 SpecSection.vue
|
|
340
|
+
|
|
341
|
+
在属性展示区域添加新类型的渲染:
|
|
342
|
+
|
|
343
|
+
```vue
|
|
344
|
+
<div class="attr-tag-wrapper attr-drag-handle">
|
|
345
|
+
<!-- 已有类型 -->
|
|
346
|
+
<el-color-picker v-if="spec.type === 'color'" ... />
|
|
347
|
+
<el-image v-else-if="spec.type === 'image'" ... />
|
|
348
|
+
|
|
349
|
+
<!-- 新增类型 -->
|
|
350
|
+
<your-custom-component v-else-if="spec.type === 'yourType'" ... />
|
|
351
|
+
|
|
352
|
+
<el-tag ...>{{ attr.name }}</el-tag>
|
|
353
|
+
</div>
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
#### 3. 更新类型标签显示
|
|
357
|
+
|
|
358
|
+
在 `getSpecTypeLabel` 函数中:
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
const getSpecTypeLabel = (type: SpecType) => {
|
|
362
|
+
const map: Record<SpecType, string> = {
|
|
363
|
+
text: '文字',
|
|
364
|
+
color: '颜色',
|
|
365
|
+
image: '图片',
|
|
366
|
+
yourType: '你的类型' // 添加
|
|
367
|
+
}
|
|
368
|
+
return map[type] || type
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
#### 4. 更新导入导出逻辑
|
|
373
|
+
|
|
374
|
+
在 `useImportExport.ts` 中处理新类型的导入导出。
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
### 添加新的校验规则
|
|
379
|
+
|
|
380
|
+
#### 1. 在 useValidation.ts 中添加校验逻辑
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
// 在 validateSkuData 函数中添加
|
|
384
|
+
if (rules.yourRule !== false) {
|
|
385
|
+
// 添加你的校验逻辑
|
|
386
|
+
const errors = validateYourRule(specs, skuData)
|
|
387
|
+
result.items.push(...errors)
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
#### 2. 更新 ValidationRules 类型
|
|
392
|
+
|
|
393
|
+
在 `src/types/sku/index.ts` 中:
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
interface ValidationRules {
|
|
397
|
+
// ... 现有规则
|
|
398
|
+
yourRule?: boolean
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
### 添加新的导出格式
|
|
405
|
+
|
|
406
|
+
#### 1. 在 useImportExport.ts 中添加函数
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
const exportCSV = () => {
|
|
410
|
+
// 实现 CSV 导出逻辑
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
#### 2. 在 SkuEditor.vue 中暴露方法
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
defineExpose({
|
|
418
|
+
exportExcel,
|
|
419
|
+
exportJson,
|
|
420
|
+
exportCSV, // 添加
|
|
421
|
+
confirmImport,
|
|
422
|
+
confirmImportExcel,
|
|
423
|
+
validateSkuData
|
|
424
|
+
})
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
#### 3. 在 SpecSection.vue 中添加入口
|
|
428
|
+
|
|
429
|
+
在工具栏的下拉菜单中添加选项。
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## 样式定制
|
|
434
|
+
|
|
435
|
+
### 使用 CSS 变量
|
|
436
|
+
|
|
437
|
+
组件使用 Element Plus 的 CSS 变量,可以通过覆盖变量来定制主题:
|
|
438
|
+
|
|
439
|
+
```css
|
|
440
|
+
:root {
|
|
441
|
+
--el-color-primary: #your-color;
|
|
442
|
+
--el-border-radius-base: 8px;
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 覆盖组件样式
|
|
447
|
+
|
|
448
|
+
各组件都有独立的 scoped 样式,可以通过深度选择器覆盖:
|
|
449
|
+
|
|
450
|
+
```css
|
|
451
|
+
.sku-editor :deep(.some-class) {
|
|
452
|
+
/* 你的样式 */
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### 主要样式类名
|
|
457
|
+
|
|
458
|
+
- `.sku-editor` - 主容器
|
|
459
|
+
- `.spec-section` - 规格区域
|
|
460
|
+
- `.sku-section` - SKU 表格区域
|
|
461
|
+
- `.spec-item` - 单个规格项
|
|
462
|
+
- `.attr-tag-wrapper` - 属性标签包装
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## 常见修改场景
|
|
467
|
+
|
|
468
|
+
### 1. 修改默认数据
|
|
469
|
+
|
|
470
|
+
现在组件不再内置默认数据,需要在父组件中传入:
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
// 在 App.vue 中
|
|
474
|
+
const specs = ref<Spec[]>([
|
|
475
|
+
// 你的默认数据
|
|
476
|
+
])
|
|
477
|
+
const skuData = ref<SkuRow[]>(generateSkuData(specs.value))
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### 2. 禁用某些功能
|
|
481
|
+
|
|
482
|
+
注释或移除模板中的对应元素:
|
|
483
|
+
|
|
484
|
+
```vue
|
|
485
|
+
<!-- 移除批量编辑按钮 -->
|
|
486
|
+
<!-- <template #toolbarTools>
|
|
487
|
+
<vxe-button ...>统一设置</vxe-button>
|
|
488
|
+
</template> -->
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### 3. 修改表格配置
|
|
492
|
+
|
|
493
|
+
在 `SkuGrid.vue` 中修改 `skuGridOptions`:
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
const skuGridOptions = reactive<VxeGridProps>({
|
|
497
|
+
border: true,
|
|
498
|
+
stripe: false, // 改斑马线样式
|
|
499
|
+
resizable: true,
|
|
500
|
+
height: 700, // 改高度
|
|
501
|
+
// ...
|
|
502
|
+
})
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### 4. 添加数据验证
|
|
506
|
+
|
|
507
|
+
在保存前添加验证逻辑,或使用新的校验系统:
|
|
508
|
+
|
|
509
|
+
```typescript
|
|
510
|
+
// 方式 1:在保存时验证
|
|
511
|
+
const saveSpec = (name: string, type: SpecType) => {
|
|
512
|
+
if (name.length > 20) {
|
|
513
|
+
ElMessage.error('规格名称不能超过20个字符')
|
|
514
|
+
return
|
|
515
|
+
}
|
|
516
|
+
// ... 原有逻辑
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// 方式 2:使用校验系统
|
|
520
|
+
const result = skuEditorRef.value?.validateSkuData({
|
|
521
|
+
custom: (specs, skuData) => {
|
|
522
|
+
// 你的自定义校验
|
|
523
|
+
}
|
|
524
|
+
})
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### 5. 修改 SKU 编号生成规则
|
|
528
|
+
|
|
529
|
+
在 `generateSkuData` 函数中修改:
|
|
530
|
+
|
|
531
|
+
```typescript
|
|
532
|
+
// 原逻辑
|
|
533
|
+
skuNo: remembered.skuNo || ''
|
|
534
|
+
|
|
535
|
+
// 修改为你的规则(在父组件中处理)
|
|
536
|
+
skuData.value.forEach((row, index) => {
|
|
537
|
+
if (!row.skuNo) {
|
|
538
|
+
row.skuNo = `PROD-${index + 1}`
|
|
539
|
+
}
|
|
540
|
+
})
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### 6. 修改保留字段名
|
|
544
|
+
|
|
545
|
+
在 `src/constants/sku.ts` 中修改:
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
export const RESERVED_NAMES: string[] = [
|
|
549
|
+
'SKU编号',
|
|
550
|
+
'销售价',
|
|
551
|
+
// ... 添加你的保留字段
|
|
552
|
+
]
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## 调试技巧
|
|
558
|
+
|
|
559
|
+
### 输出数据到控制台
|
|
560
|
+
|
|
561
|
+
点击工具栏的"输出到控制台"按钮,或调用 `handlePrintData()` 方法,可以查看当前的规格和 SKU 数据。
|
|
562
|
+
|
|
563
|
+
### 使用 Vue DevTools
|
|
564
|
+
|
|
565
|
+
1. 安装 Vue DevTools 浏览器扩展
|
|
566
|
+
2. 在组件树中选择 SkuEditor
|
|
567
|
+
3. 查看和修改组件的状态
|
|
568
|
+
|
|
569
|
+
### 监听数据变化
|
|
570
|
+
|
|
571
|
+
在 `SkuEditor.vue` 中添加临时的 watch 调试:
|
|
572
|
+
|
|
573
|
+
```typescript
|
|
574
|
+
watch(specsRef, (newVal) => {
|
|
575
|
+
console.log('Specs changed:', newVal)
|
|
576
|
+
}, { deep: true })
|
|
577
|
+
|
|
578
|
+
watch(internalSkuData, (newVal) => {
|
|
579
|
+
console.log('SKU data changed:', newVal)
|
|
580
|
+
}, { deep: true })
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
---
|
|
584
|
+
|
|
585
|
+
## 性能优化建议
|
|
586
|
+
|
|
587
|
+
### 1. 大量 SKU 数据时
|
|
588
|
+
|
|
589
|
+
- 确保 VXE Table 的虚拟滚动开启(`virtualYConfig.enabled: true`)
|
|
590
|
+
- 减少不必要的列显示
|
|
591
|
+
- 避免在 `spanMethod` 中做复杂计算
|
|
592
|
+
|
|
593
|
+
### 2. 频繁更新时
|
|
594
|
+
|
|
595
|
+
- 使用 `watch` 的 `flush: 'post'` 选项
|
|
596
|
+
- 防抖处理保存操作
|
|
597
|
+
- 避免在渲染期间修改数据
|
|
598
|
+
|
|
599
|
+
### 3. 导入大文件时
|
|
600
|
+
|
|
601
|
+
- 添加加载状态提示
|
|
602
|
+
- 考虑分片处理
|
|
603
|
+
- 使用 Web Worker(需要额外配置)
|
|
604
|
+
|
|
605
|
+
### 4. 数据校验时
|
|
606
|
+
|
|
607
|
+
- 对于大数据量,考虑只在保存时校验
|
|
608
|
+
- 可以只执行部分校验规则(如快速校验)
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
## 测试建议
|
|
613
|
+
|
|
614
|
+
### 单元测试关注点
|
|
615
|
+
|
|
616
|
+
- `useSkuGenerator.ts` - 测试 SKU 生成逻辑、数据转换
|
|
617
|
+
- `useMergeCells.ts` - 测试单元格合并计算
|
|
618
|
+
- `useValidation.ts` - 测试数据校验逻辑
|
|
619
|
+
- 各种边界情况(空数据、单规格、多规格等)
|
|
620
|
+
|
|
621
|
+
### 集成测试关注点
|
|
622
|
+
|
|
623
|
+
- 完整的增删改流程
|
|
624
|
+
- 导入导出功能
|
|
625
|
+
- 数据保留功能
|
|
626
|
+
- 拖拽排序功能
|
|
627
|
+
- 数据校验功能
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## 相关资源
|
|
632
|
+
|
|
633
|
+
- [Vue 3 Composition API](https://cn.vuejs.org/guide/extras/composition-api-faq.html)
|
|
634
|
+
- [Element Plus 组件](https://element-plus.org/)
|
|
635
|
+
- [VXE Table 文档](https://vxetable.cn/)
|
|
636
|
+
- [Sortable.js 文档](https://sortablejs.github.io/Sortable/)
|
|
637
|
+
- [SheetJS (xlsx)](https://sheetjs.com/)
|