create-component-template-cli 1.0.0 → 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/.changeset/config.json +1 -1
- package/AGENTS.md +114 -0
- package/CHANGELOG.md +6 -0
- package/CLAUDE.md +19 -7
- package/README.md +40 -20
- package/bin/cli.mjs +38 -29
- package/docs/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204-/346/200/235/350/267/257/346/226/207/346/241/243.md +167 -0
- package/docs/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204-/346/200/273/347/273/223/346/226/207/346/241/243.md +80 -0
- package/docs/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204-/350/256/276/350/256/241/346/226/271/346/241/210.md +477 -0
- package/package.json +1 -1
- package/plop-templates/general/data.ts.hbs +16 -0
- package/plop-templates/general/hook.ts.hbs +11 -0
- package/plop-templates/general/index.normal.vue.hbs +28 -0
- package/plop-templates/general/index.scss.hbs +5 -0
- package/plop-templates/general/index.setup.vue.hbs +20 -0
- package/plop-templates/{index.ts.hbs → general/index.ts.hbs} +2 -1
- package/plop-templates/general/typing.ts.hbs +13 -0
- package/plop-templates/multiple-pick/data.ts.hbs +20 -0
- package/plop-templates/multiple-pick/hook.ts.hbs +11 -0
- package/plop-templates/multiple-pick/index.normal.vue.hbs +37 -0
- package/plop-templates/multiple-pick/index.scss.hbs +5 -0
- package/plop-templates/multiple-pick/index.setup.vue.hbs +22 -0
- package/plop-templates/multiple-pick/index.ts.hbs +4 -0
- package/plop-templates/multiple-pick/typing.ts.hbs +13 -0
- package/plop-templates/single-pick/data.ts.hbs +16 -0
- package/plop-templates/single-pick/hook.ts.hbs +11 -0
- package/plop-templates/single-pick/index.normal.vue.hbs +36 -0
- package/plop-templates/single-pick/index.scss.hbs +5 -0
- package/plop-templates/single-pick/index.setup.vue.hbs +23 -0
- package/plop-templates/single-pick/index.ts.hbs +4 -0
- package/plop-templates/single-pick/typing.ts.hbs +13 -0
- package/plopfile.mjs +68 -59
- package/src/generate.mjs +101 -31
- package/tmp-output/GeneralNormalDemo/index.ts +4 -0
- package/tmp-output/GeneralNormalDemo/src/data.ts +16 -0
- package/tmp-output/GeneralNormalDemo/src/hook.ts +11 -0
- package/tmp-output/GeneralNormalDemo/src/index.scss +5 -0
- package/tmp-output/GeneralNormalDemo/src/index.vue +28 -0
- package/tmp-output/GeneralNormalDemo/src/typing.ts +13 -0
- package/tmp-output/GeneralSetupDemo/index.ts +4 -0
- package/tmp-output/GeneralSetupDemo/src/data.ts +16 -0
- package/tmp-output/GeneralSetupDemo/src/hook.ts +11 -0
- package/tmp-output/GeneralSetupDemo/src/index.scss +5 -0
- package/tmp-output/GeneralSetupDemo/src/index.vue +20 -0
- package/tmp-output/GeneralSetupDemo/src/typing.ts +13 -0
- package/tmp-output/MultiplePickNormalDemo/index.ts +4 -0
- package/tmp-output/MultiplePickNormalDemo/src/data.ts +20 -0
- package/tmp-output/MultiplePickNormalDemo/src/hook.ts +11 -0
- package/tmp-output/MultiplePickNormalDemo/src/index.scss +5 -0
- package/tmp-output/MultiplePickNormalDemo/src/index.vue +37 -0
- package/tmp-output/MultiplePickNormalDemo/src/typing.ts +13 -0
- package/tmp-output/MultiplePickSetupDemo/index.ts +4 -0
- package/tmp-output/MultiplePickSetupDemo/src/data.ts +20 -0
- package/tmp-output/MultiplePickSetupDemo/src/hook.ts +11 -0
- package/tmp-output/MultiplePickSetupDemo/src/index.scss +5 -0
- package/tmp-output/MultiplePickSetupDemo/src/index.vue +22 -0
- package/tmp-output/MultiplePickSetupDemo/src/typing.ts +13 -0
- package/tmp-output/SinglePickNormalDemo/index.ts +4 -0
- package/tmp-output/SinglePickNormalDemo/src/data.ts +16 -0
- package/tmp-output/SinglePickNormalDemo/src/hook.ts +11 -0
- package/tmp-output/SinglePickNormalDemo/src/index.scss +5 -0
- package/tmp-output/SinglePickNormalDemo/src/index.vue +36 -0
- package/tmp-output/SinglePickNormalDemo/src/typing.ts +13 -0
- package/tmp-output/SinglePickSetupDemo/index.ts +4 -0
- package/tmp-output/SinglePickSetupDemo/src/data.ts +16 -0
- package/tmp-output/SinglePickSetupDemo/src/hook.ts +11 -0
- package/tmp-output/SinglePickSetupDemo/src/index.scss +5 -0
- package/tmp-output/SinglePickSetupDemo/src/index.vue +23 -0
- package/tmp-output/SinglePickSetupDemo/src/typing.ts +13 -0
- package/plop-templates/data.ts.hbs +0 -7
- package/plop-templates/hook.ts.hbs +0 -29
- package/plop-templates/index.scss.hbs +0 -1
- package/plop-templates/index.setup.vue.hbs +0 -25
- package/plop-templates/index.vue.hbs +0 -38
- package/plop-templates/typing.ts.hbs +0 -14
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
# 三套业务模板与两套 Vue 语法风格并存设计方案
|
|
2
|
+
|
|
3
|
+
## 1. 背景
|
|
4
|
+
|
|
5
|
+
当前项目里存在两个容易混淆的概念:
|
|
6
|
+
|
|
7
|
+
1. 业务模板类型
|
|
8
|
+
表示要生成哪一类业务组件骨架。
|
|
9
|
+
|
|
10
|
+
2. Vue 语法风格
|
|
11
|
+
只表示 `index.vue` 使用哪种 Vue 写法。
|
|
12
|
+
|
|
13
|
+
这次需求已经明确:
|
|
14
|
+
|
|
15
|
+
- 业务层面的 `templateType` 一共有三种:
|
|
16
|
+
- `general`
|
|
17
|
+
- `single-pick`
|
|
18
|
+
- `multiple-pick`
|
|
19
|
+
- 当前逻辑中的 `setup` 和 `normal` 仍然保留
|
|
20
|
+
- `setup/normal` 只用于决定 `index.vue` 的 Vue 模板写法
|
|
21
|
+
|
|
22
|
+
因此,这次设计的核心是把“业务模板类型”和“Vue 语法风格”拆成两个独立维度,而不是让 `templateType` 同时承担两种含义。
|
|
23
|
+
|
|
24
|
+
## 2. 目标
|
|
25
|
+
|
|
26
|
+
### 2.1 功能目标
|
|
27
|
+
|
|
28
|
+
1. 支持三种业务模板类型
|
|
29
|
+
2. 保留两种 Vue 语法风格
|
|
30
|
+
3. 支持任意业务模板类型与任意 Vue 语法风格组合使用
|
|
31
|
+
4. 保持现有输出目录结构不变
|
|
32
|
+
5. 最终生成的组件文件名保持稳定
|
|
33
|
+
|
|
34
|
+
### 2.2 设计目标
|
|
35
|
+
|
|
36
|
+
1. 参数语义清晰
|
|
37
|
+
2. 模板目录结构清晰
|
|
38
|
+
3. 生成逻辑采用配置驱动
|
|
39
|
+
4. 交互模式与非交互模式规则一致
|
|
40
|
+
|
|
41
|
+
## 3. 需求拆解
|
|
42
|
+
|
|
43
|
+
这次需求不是“三套模板替换两套模板”,而是“两层模板选择并存”。
|
|
44
|
+
|
|
45
|
+
### 3.1 第一层:业务模板类型
|
|
46
|
+
|
|
47
|
+
这一层决定整套生成内容的业务语义:
|
|
48
|
+
|
|
49
|
+
- `general`:通用业务模板
|
|
50
|
+
- `single-pick`:产品组单选业务模板
|
|
51
|
+
- `multiple-pick`:产品组多选业务模板
|
|
52
|
+
|
|
53
|
+
这一层会影响的文件不只有 `index.vue`,还可能包括:
|
|
54
|
+
|
|
55
|
+
- `typing.ts`
|
|
56
|
+
- `hook.ts`
|
|
57
|
+
- `data.ts`
|
|
58
|
+
- `index.scss`
|
|
59
|
+
- `index.ts`
|
|
60
|
+
|
|
61
|
+
### 3.2 第二层:Vue 语法风格
|
|
62
|
+
|
|
63
|
+
这一层只决定 `index.vue` 使用哪种 Vue 写法:
|
|
64
|
+
|
|
65
|
+
- `setup`:`<script setup>`
|
|
66
|
+
- `normal`:`defineComponent`
|
|
67
|
+
|
|
68
|
+
最终允许的组合关系应为:
|
|
69
|
+
|
|
70
|
+
- `general + setup`
|
|
71
|
+
- `general + normal`
|
|
72
|
+
- `single-pick + setup`
|
|
73
|
+
- `single-pick + normal`
|
|
74
|
+
- `multiple-pick + setup`
|
|
75
|
+
- `multiple-pick + normal`
|
|
76
|
+
|
|
77
|
+
## 4. 现状分析
|
|
78
|
+
|
|
79
|
+
### 4.1 当前实现特点
|
|
80
|
+
|
|
81
|
+
当前实现里:
|
|
82
|
+
|
|
83
|
+
1. `templateType` 只有 `setup` 和 `normal`
|
|
84
|
+
2. 实际上只有 `index.vue` 会根据 `templateType` 切换模板文件
|
|
85
|
+
3. 其他文件模板都是固定的
|
|
86
|
+
|
|
87
|
+
这说明当前架构本质上只支持:
|
|
88
|
+
|
|
89
|
+
- 单一业务模板
|
|
90
|
+
- 两种 Vue 语法风格
|
|
91
|
+
|
|
92
|
+
### 4.2 当前问题
|
|
93
|
+
|
|
94
|
+
1. `templateType` 语义混乱
|
|
95
|
+
它现在承载的是 Vue 写法选择,而不是业务模板选择。
|
|
96
|
+
|
|
97
|
+
2. 缺少业务模板层
|
|
98
|
+
目前没有一个明确维度控制 `general`、`single-pick`、`multiple-pick`。
|
|
99
|
+
|
|
100
|
+
3. 模板组织方式扩展性不足
|
|
101
|
+
如果继续在平铺目录上叠加判断,后续文件差异会越来越难维护。
|
|
102
|
+
|
|
103
|
+
## 5. 重构原则
|
|
104
|
+
|
|
105
|
+
### 5.1 两个维度必须拆开
|
|
106
|
+
|
|
107
|
+
业务模板类型和 Vue 语法风格属于不同维度,不能再复用同一个参数语义。
|
|
108
|
+
|
|
109
|
+
### 5.2 业务模板决定整套模板目录
|
|
110
|
+
|
|
111
|
+
每种业务模板对应一套独立模板资源。
|
|
112
|
+
|
|
113
|
+
### 5.3 Vue 风格只决定 `index.vue`
|
|
114
|
+
|
|
115
|
+
`setup/normal` 只影响 `index.vue` 模板文件选择,不影响其他文件来源。
|
|
116
|
+
|
|
117
|
+
### 5.4 模板源文件名与最终输出文件名分离
|
|
118
|
+
|
|
119
|
+
内部可以通过不同模板源文件区分 Vue 写法,但最终输出给组件目录的文件名必须统一。
|
|
120
|
+
|
|
121
|
+
## 6. 参数设计
|
|
122
|
+
|
|
123
|
+
建议把参数拆成两个:
|
|
124
|
+
|
|
125
|
+
### 6.1 `templateType`
|
|
126
|
+
|
|
127
|
+
表示业务模板类型:
|
|
128
|
+
|
|
129
|
+
- `general`
|
|
130
|
+
- `single-pick`
|
|
131
|
+
- `multiple-pick`
|
|
132
|
+
|
|
133
|
+
### 6.2 `vueTemplateType`
|
|
134
|
+
|
|
135
|
+
表示 Vue 语法风格:
|
|
136
|
+
|
|
137
|
+
- `setup`
|
|
138
|
+
- `normal`
|
|
139
|
+
|
|
140
|
+
如果暂时不想新增参数名,也可以过渡为:
|
|
141
|
+
|
|
142
|
+
- `templateType`:业务模板类型
|
|
143
|
+
- `vueStyle`:Vue 语法风格
|
|
144
|
+
|
|
145
|
+
本方案更推荐使用语义更明确的命名,例如 `vueTemplateType`。
|
|
146
|
+
|
|
147
|
+
## 7. 目录设计
|
|
148
|
+
|
|
149
|
+
建议模板目录按业务模板类型分组,在每个业务模板目录中,仅对 `index.vue` 的模板源文件再区分两种 Vue 写法。
|
|
150
|
+
|
|
151
|
+
```txt
|
|
152
|
+
plop-templates/
|
|
153
|
+
general/
|
|
154
|
+
index.setup.vue.hbs
|
|
155
|
+
index.normal.vue.hbs
|
|
156
|
+
typing.ts.hbs
|
|
157
|
+
hook.ts.hbs
|
|
158
|
+
data.ts.hbs
|
|
159
|
+
index.scss.hbs
|
|
160
|
+
index.ts.hbs
|
|
161
|
+
single-pick/
|
|
162
|
+
index.setup.vue.hbs
|
|
163
|
+
index.normal.vue.hbs
|
|
164
|
+
typing.ts.hbs
|
|
165
|
+
hook.ts.hbs
|
|
166
|
+
data.ts.hbs
|
|
167
|
+
index.scss.hbs
|
|
168
|
+
index.ts.hbs
|
|
169
|
+
multiple-pick/
|
|
170
|
+
index.setup.vue.hbs
|
|
171
|
+
index.normal.vue.hbs
|
|
172
|
+
typing.ts.hbs
|
|
173
|
+
hook.ts.hbs
|
|
174
|
+
data.ts.hbs
|
|
175
|
+
index.scss.hbs
|
|
176
|
+
index.ts.hbs
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 7.1 输出文件命名规则
|
|
180
|
+
|
|
181
|
+
这里必须严格区分“模板源文件名”和“最终生成文件名”:
|
|
182
|
+
|
|
183
|
+
1. 模板源文件名
|
|
184
|
+
内部允许使用:
|
|
185
|
+
- `index.setup.vue.hbs`
|
|
186
|
+
- `index.normal.vue.hbs`
|
|
187
|
+
|
|
188
|
+
2. 最终生成文件名
|
|
189
|
+
无论选择哪种 Vue 风格,最终都只生成:
|
|
190
|
+
- `src/index.vue`
|
|
191
|
+
|
|
192
|
+
也就是说,`setup/normal` 只参与模板选择,不进入最终产物文件名。
|
|
193
|
+
|
|
194
|
+
### 7.2 这样设计的原因
|
|
195
|
+
|
|
196
|
+
1. 在算什么
|
|
197
|
+
这里算的是“如何让模板选择逻辑可区分,同时保持最终产物结构稳定”。
|
|
198
|
+
|
|
199
|
+
2. 为什么这么算
|
|
200
|
+
因为 `setup/normal` 只是模板来源差异,不是最终组件目录结构差异。对使用方来说,组件入口文件始终应该是统一的 `index.vue`。
|
|
201
|
+
|
|
202
|
+
3. 好处
|
|
203
|
+
后续如果新增业务模板,只需要新增一个目录;如果新增新的 Vue 风格,只需要在各业务目录下补充对应的 `index.xxx.vue.hbs`。
|
|
204
|
+
|
|
205
|
+
## 8. 配置结构设计
|
|
206
|
+
|
|
207
|
+
建议抽离两套配置。
|
|
208
|
+
|
|
209
|
+
### 8.1 业务模板注册表
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
BUSINESS_TEMPLATE_MAP = {
|
|
213
|
+
general: {
|
|
214
|
+
label: '通用模板',
|
|
215
|
+
templateDir: 'general'
|
|
216
|
+
},
|
|
217
|
+
'single-pick': {
|
|
218
|
+
label: '产品组单选模板',
|
|
219
|
+
templateDir: 'single-pick'
|
|
220
|
+
},
|
|
221
|
+
'multiple-pick': {
|
|
222
|
+
label: '产品组多选模板',
|
|
223
|
+
templateDir: 'multiple-pick'
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 8.2 Vue 风格注册表
|
|
229
|
+
|
|
230
|
+
```js
|
|
231
|
+
VUE_TEMPLATE_STYLE_MAP = {
|
|
232
|
+
setup: {
|
|
233
|
+
label: 'script setup 风格',
|
|
234
|
+
vueTemplateFile: 'index.setup.vue.hbs'
|
|
235
|
+
},
|
|
236
|
+
normal: {
|
|
237
|
+
label: 'defineComponent 风格',
|
|
238
|
+
vueTemplateFile: 'index.normal.vue.hbs'
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 8.3 固定输出文件清单
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
TEMPLATE_FILES = [
|
|
247
|
+
{ output: 'src/index.vue', type: 'vue-entry' },
|
|
248
|
+
{ output: 'src/index.scss', template: 'index.scss.hbs' },
|
|
249
|
+
{ output: 'src/typing.ts', template: 'typing.ts.hbs' },
|
|
250
|
+
{ output: 'src/hook.ts', template: 'hook.ts.hbs' },
|
|
251
|
+
{ output: 'src/data.ts', template: 'data.ts.hbs' },
|
|
252
|
+
{ output: 'index.ts', template: 'index.ts.hbs' }
|
|
253
|
+
]
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## 9. 模板选择逻辑
|
|
257
|
+
|
|
258
|
+
### 9.1 选择流程
|
|
259
|
+
|
|
260
|
+
1. 先根据 `templateType` 选择业务模板目录
|
|
261
|
+
2. 再根据 `vueTemplateType` 选择 `index.vue` 对应模板源文件
|
|
262
|
+
3. 将选中的 Vue 模板源文件渲染后统一写入 `src/index.vue`
|
|
263
|
+
4. 其他文件全部从业务模板目录读取固定模板
|
|
264
|
+
|
|
265
|
+
### 9.2 伪代码
|
|
266
|
+
|
|
267
|
+
```js
|
|
268
|
+
读取 templateType
|
|
269
|
+
读取 vueTemplateType
|
|
270
|
+
|
|
271
|
+
校验 templateType 是否合法
|
|
272
|
+
校验 vueTemplateType 是否合法
|
|
273
|
+
|
|
274
|
+
businessDir = BUSINESS_TEMPLATE_MAP[templateType].templateDir
|
|
275
|
+
vueFile = VUE_TEMPLATE_STYLE_MAP[vueTemplateType].vueTemplateFile
|
|
276
|
+
|
|
277
|
+
for 每个输出文件:
|
|
278
|
+
if 当前文件是 index.vue:
|
|
279
|
+
templatePath = businessDir + vueFile
|
|
280
|
+
outputPath = src/index.vue
|
|
281
|
+
else:
|
|
282
|
+
templatePath = businessDir + 固定模板文件名
|
|
283
|
+
outputPath = 固定输出路径
|
|
284
|
+
|
|
285
|
+
读取模板
|
|
286
|
+
渲染变量
|
|
287
|
+
写入 outputPath
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## 10. 代码改造方案
|
|
291
|
+
|
|
292
|
+
### 10.1 `src/generate.mjs`
|
|
293
|
+
|
|
294
|
+
#### 改造目标
|
|
295
|
+
|
|
296
|
+
让生成器同时接收“业务模板类型”和“Vue 风格”两个参数。
|
|
297
|
+
|
|
298
|
+
#### 改造内容
|
|
299
|
+
|
|
300
|
+
1. 新增业务模板合法值校验
|
|
301
|
+
2. 新增 Vue 风格合法值校验
|
|
302
|
+
3. 把 `index.vue` 模板选择逻辑改成二段式选择
|
|
303
|
+
4. 选中的 Vue 模板源文件最终统一输出为 `src/index.vue`
|
|
304
|
+
5. 其他模板文件按业务模板目录读取
|
|
305
|
+
|
|
306
|
+
### 10.2 `plopfile.mjs`
|
|
307
|
+
|
|
308
|
+
#### 改造目标
|
|
309
|
+
|
|
310
|
+
交互模式中要让用户先后选择两个维度。
|
|
311
|
+
|
|
312
|
+
#### 改造内容
|
|
313
|
+
|
|
314
|
+
1. 增加业务模板选择项
|
|
315
|
+
2. 保留 Vue 风格选择项
|
|
316
|
+
3. 生成动作时同时带上两个参数
|
|
317
|
+
4. 模板路径拼接逻辑改为“业务目录 + Vue 风格文件名”
|
|
318
|
+
5. 最终输出路径始终保持 `src/index.vue`
|
|
319
|
+
|
|
320
|
+
### 10.3 `bin/cli.mjs`
|
|
321
|
+
|
|
322
|
+
#### 改造目标
|
|
323
|
+
|
|
324
|
+
CLI 参数说明与帮助文案反映双维度结构。
|
|
325
|
+
|
|
326
|
+
#### 改造内容
|
|
327
|
+
|
|
328
|
+
1. `--templateType` 改为说明业务模板类型
|
|
329
|
+
2. 新增 Vue 风格参数说明
|
|
330
|
+
3. 明确说明 `setup/normal` 不会改变最终输出文件名
|
|
331
|
+
4. 示例命令补充若干典型组合
|
|
332
|
+
|
|
333
|
+
### 10.4 文档同步
|
|
334
|
+
|
|
335
|
+
需要同步更新:
|
|
336
|
+
|
|
337
|
+
- `README.md`
|
|
338
|
+
- `AGENTS.md`
|
|
339
|
+
- `CLAUDE.md`
|
|
340
|
+
|
|
341
|
+
避免后续使用者继续把 `templateType` 理解成 Vue 写法开关。
|
|
342
|
+
|
|
343
|
+
## 11. 模板内容设计
|
|
344
|
+
|
|
345
|
+
### 11.1 `general`
|
|
346
|
+
|
|
347
|
+
用途:通用业务组件骨架。
|
|
348
|
+
|
|
349
|
+
设计原则:
|
|
350
|
+
|
|
351
|
+
- 参考现有模板内容
|
|
352
|
+
- 去掉单选、多选场景的强业务耦合
|
|
353
|
+
- 保留基础 props、hook、data 占位
|
|
354
|
+
|
|
355
|
+
### 11.2 `single-pick`
|
|
356
|
+
|
|
357
|
+
用途:产品组单选业务模板。
|
|
358
|
+
|
|
359
|
+
设计原则:
|
|
360
|
+
|
|
361
|
+
- 参考现有 `SinglePickButtonGroup` 相关痕迹
|
|
362
|
+
- `typing.ts` 预置单选值结构
|
|
363
|
+
- `data.ts` 预置单选项数组结构
|
|
364
|
+
|
|
365
|
+
### 11.3 `multiple-pick`
|
|
366
|
+
|
|
367
|
+
用途:产品组多选业务模板。
|
|
368
|
+
|
|
369
|
+
设计原则:
|
|
370
|
+
|
|
371
|
+
- 在单选模板思路基础上扩展为多选语义
|
|
372
|
+
- `typing.ts` 预置多选值结构
|
|
373
|
+
- `data.ts` 预置多选项数组结构
|
|
374
|
+
|
|
375
|
+
### 11.4 关于 `index.vue`
|
|
376
|
+
|
|
377
|
+
每个业务模板都提供两份 `index.vue` 模板源文件:
|
|
378
|
+
|
|
379
|
+
- `index.setup.vue.hbs`
|
|
380
|
+
- `index.normal.vue.hbs`
|
|
381
|
+
|
|
382
|
+
它们表达的是同一业务模板下的两种 Vue 书写方式,不是两类业务模板。
|
|
383
|
+
最终落地生成时,文件名始终统一为 `index.vue`。
|
|
384
|
+
|
|
385
|
+
## 12. 兼容性策略
|
|
386
|
+
|
|
387
|
+
### 12.1 旧参数兼容问题
|
|
388
|
+
|
|
389
|
+
当前实现中 `templateType` 还承担 Vue 风格含义,因此重构后存在迁移问题。
|
|
390
|
+
|
|
391
|
+
### 12.2 建议过渡方案
|
|
392
|
+
|
|
393
|
+
建议采用过渡兼容:
|
|
394
|
+
|
|
395
|
+
1. 新版本引入双参数模型
|
|
396
|
+
2. 若用户仍传旧的 `templateType=setup|normal`
|
|
397
|
+
则提示参数语义已调整
|
|
398
|
+
3. 过渡期内可将旧值映射为:
|
|
399
|
+
- 业务模板默认 `general`
|
|
400
|
+
- Vue 风格使用旧值
|
|
401
|
+
|
|
402
|
+
### 12.3 过渡映射示意
|
|
403
|
+
|
|
404
|
+
```txt
|
|
405
|
+
旧输入:
|
|
406
|
+
--templateType=setup
|
|
407
|
+
|
|
408
|
+
过渡解释:
|
|
409
|
+
templateType = general
|
|
410
|
+
vueTemplateType = setup
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
这样做的原因是:
|
|
414
|
+
|
|
415
|
+
1. 在算什么
|
|
416
|
+
这里算的是“如何减少旧脚本失效风险”。
|
|
417
|
+
|
|
418
|
+
2. 为什么这么算
|
|
419
|
+
因为旧值本来就只表达 Vue 风格,并不表达业务模板,所以映射到默认业务模板 `general` 最符合原始语义。
|
|
420
|
+
|
|
421
|
+
## 13. 测试与验证方案
|
|
422
|
+
|
|
423
|
+
### 13.1 组合验证
|
|
424
|
+
|
|
425
|
+
至少验证以下 6 组:
|
|
426
|
+
|
|
427
|
+
1. `general + setup`
|
|
428
|
+
2. `general + normal`
|
|
429
|
+
3. `single-pick + setup`
|
|
430
|
+
4. `single-pick + normal`
|
|
431
|
+
5. `multiple-pick + setup`
|
|
432
|
+
6. `multiple-pick + normal`
|
|
433
|
+
|
|
434
|
+
### 13.2 异常验证
|
|
435
|
+
|
|
436
|
+
1. 非法 `templateType` 报错
|
|
437
|
+
2. 非法 `vueTemplateType` 报错
|
|
438
|
+
3. 未传业务模板时默认值正确
|
|
439
|
+
4. 未传 Vue 风格时默认值正确
|
|
440
|
+
5. `overwrite` / `skip` 行为保持不变
|
|
441
|
+
|
|
442
|
+
### 13.3 输出验证
|
|
443
|
+
|
|
444
|
+
重点检查:
|
|
445
|
+
|
|
446
|
+
1. 目录结构是否正确
|
|
447
|
+
2. 六个目标文件是否完整生成
|
|
448
|
+
3. `index.vue` 是否真的对应到所选 Vue 风格
|
|
449
|
+
4. 其他文件是否真的来自所选业务模板
|
|
450
|
+
5. 最终输出文件名是否始终为 `index.vue`
|
|
451
|
+
|
|
452
|
+
## 14. 实施步骤
|
|
453
|
+
|
|
454
|
+
1. 修正模板参数设计
|
|
455
|
+
2. 新建三套业务模板目录
|
|
456
|
+
3. 每套业务模板补齐两份 `index.vue` 模板源文件
|
|
457
|
+
4. 复制并改造 `typing.ts`、`hook.ts`、`data.ts` 等文件模板
|
|
458
|
+
5. 重构 `src/generate.mjs`
|
|
459
|
+
6. 重构 `plopfile.mjs`
|
|
460
|
+
7. 更新 `bin/cli.mjs` 帮助文案
|
|
461
|
+
8. 更新仓库说明文档
|
|
462
|
+
9. 执行 6 组组合命令做闭环验证
|
|
463
|
+
10. 验证最终是否始终输出统一文件名 `index.vue`
|
|
464
|
+
11. 产出实施总结文档
|
|
465
|
+
|
|
466
|
+
## 15. 结论
|
|
467
|
+
|
|
468
|
+
推荐采用“业务模板类型 + Vue 语法风格”双维度方案。
|
|
469
|
+
|
|
470
|
+
其中:
|
|
471
|
+
|
|
472
|
+
- `templateType` 只负责业务模板语义
|
|
473
|
+
- `setup/normal` 只负责 `index.vue` 的 Vue 书写风格
|
|
474
|
+
- `index.setup.vue.hbs` / `index.normal.vue.hbs` 只是模板源文件名
|
|
475
|
+
- 最终生成文件名始终统一为 `index.vue`
|
|
476
|
+
|
|
477
|
+
这样既符合你的补充定义,也能最大程度复用现有逻辑,并为后续继续扩展业务模板留下稳定结构。
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-component-template-cli",
|
|
3
3
|
"description": "create-vue-component-template,A CLI tool for creating standardized Vue 3 + TypeScript + Sass public component templates.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="{{ class }}"></div>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { defineComponent, PropType } from 'vue'
|
|
7
|
+
import { {{ componentName }}Props } from './typing'
|
|
8
|
+
import { use{{ componentName }} } from './hook'
|
|
9
|
+
|
|
10
|
+
export default defineComponent({
|
|
11
|
+
name: '{{ componentName }}',
|
|
12
|
+
props: {
|
|
13
|
+
user: {
|
|
14
|
+
type: Object as PropType<{{ componentName }}Props['user']>,
|
|
15
|
+
required: false,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
setup(props) {
|
|
19
|
+
const {} = use{{ componentName }}(props as {{ componentName }}Props)
|
|
20
|
+
|
|
21
|
+
return {}
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<style lang="scss" scoped>
|
|
27
|
+
@import './index.scss';
|
|
28
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="{{ class }}"></div>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import { {{ componentName }}Props } from './typing'
|
|
7
|
+
import { use{{ componentName }} } from './hook'
|
|
8
|
+
|
|
9
|
+
defineOptions({
|
|
10
|
+
name: '{{ componentName }}',
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const props = defineProps<{{ componentName }}Props>()
|
|
14
|
+
|
|
15
|
+
const {} = use{{ componentName }}(props)
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<style lang="scss" scoped>
|
|
19
|
+
@import './index.scss';
|
|
20
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DataType } from './typing'
|
|
2
|
+
|
|
3
|
+
const data: Array<DataType> = [
|
|
4
|
+
{
|
|
5
|
+
label: '多选项1',
|
|
6
|
+
value: 'multiple-1',
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
label: '多选项2',
|
|
10
|
+
value: 'multiple-2',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
label: '多选项3',
|
|
14
|
+
value: 'multiple-3',
|
|
15
|
+
},
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
data,
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ref } from 'vue'
|
|
2
|
+
import { data } from './data'
|
|
3
|
+
import type { {{ componentName }}Props } from './typing'
|
|
4
|
+
|
|
5
|
+
export const use{{ componentName }} = (props: {{ componentName }}Props) => {
|
|
6
|
+
const selectedValues = ref(props.modelValue ?? data.slice(0, 2).map((item) => item.value))
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
selectedValues,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="{{ class }}">
|
|
3
|
+
<div v-for="item in selectedValues" :key="item">{{ item }}</div>
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { defineComponent, PropType } from 'vue'
|
|
9
|
+
import { {{ componentName }}Props } from './typing'
|
|
10
|
+
import { use{{ componentName }} } from './hook'
|
|
11
|
+
|
|
12
|
+
export default defineComponent({
|
|
13
|
+
name: '{{ componentName }}',
|
|
14
|
+
props: {
|
|
15
|
+
user: {
|
|
16
|
+
type: Object as PropType<{{ componentName }}Props['user']>,
|
|
17
|
+
required: false,
|
|
18
|
+
},
|
|
19
|
+
modelValue: {
|
|
20
|
+
type: Array as PropType<{{ componentName }}Props['modelValue']>,
|
|
21
|
+
required: false,
|
|
22
|
+
default: () => [],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
setup(props) {
|
|
26
|
+
const { selectedValues } = use{{ componentName }}(props as {{ componentName }}Props)
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
selectedValues,
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<style lang="scss" scoped>
|
|
36
|
+
@import './index.scss';
|
|
37
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="{{ class }}">
|
|
3
|
+
<div v-for="item in selectedValues" :key="item">{{ item }}</div>
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { {{ componentName }}Props } from './typing'
|
|
9
|
+
import { use{{ componentName }} } from './hook'
|
|
10
|
+
|
|
11
|
+
defineOptions({
|
|
12
|
+
name: '{{ componentName }}',
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const props = defineProps<{{ componentName }}Props>()
|
|
16
|
+
|
|
17
|
+
const { selectedValues } = use{{ componentName }}(props)
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<style lang="scss" scoped>
|
|
21
|
+
@import './index.scss';
|
|
22
|
+
</style>
|