m8-mcp-server 1.0.6 → 1.0.7

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.
Files changed (67) hide show
  1. package/dist/cli.d.ts +1 -1
  2. package/dist/cli.js +1 -13
  3. package/dist/docs/apis.d.ts +1 -1
  4. package/dist/docs/apis.js +9 -326
  5. package/dist/docs/components.d.ts +1 -1
  6. package/dist/docs/components.js +2 -186
  7. package/dist/docs/index.d.ts +1 -1
  8. package/dist/docs/index.js +18 -177
  9. package/dist/docs/loader.d.ts +1 -1
  10. package/dist/docs/loader.js +1 -165
  11. package/dist/docs/search.d.ts +1 -1
  12. package/dist/docs/search.js +2 -196
  13. package/dist/docs/standards.d.ts +1 -1
  14. package/dist/docs/standards.js +3 -134
  15. package/dist/docs/utils.d.ts +1 -1
  16. package/dist/docs/utils.js +3 -129
  17. package/dist/generator/header.d.ts +1 -1
  18. package/dist/generator/header.js +3 -83
  19. package/dist/generator/index.d.ts +1 -1
  20. package/dist/generator/index.js +283 -648
  21. package/dist/generator/vue-template.d.ts +1 -1
  22. package/dist/generator/vue-template.js +336 -1016
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +1 -73
  25. package/dist/recommend/index.d.ts +1 -1
  26. package/dist/recommend/index.js +2 -412
  27. package/dist/tools/generate-code.d.ts +1 -1
  28. package/dist/tools/generate-code.js +39 -211
  29. package/dist/tools/get-api-info.d.ts +1 -1
  30. package/dist/tools/get-api-info.js +1 -65
  31. package/dist/tools/get-coding-standard.d.ts +1 -1
  32. package/dist/tools/get-coding-standard.js +1 -66
  33. package/dist/tools/get-component-info.d.ts +1 -1
  34. package/dist/tools/get-component-info.js +1 -60
  35. package/dist/tools/get-util-info.d.ts +1 -1
  36. package/dist/tools/get-util-info.js +1 -65
  37. package/dist/tools/index.d.ts +1 -1
  38. package/dist/tools/index.js +3 -101
  39. package/dist/tools/recommend-solution.d.ts +1 -1
  40. package/dist/tools/recommend-solution.js +1 -67
  41. package/dist/tools/search-docs.d.ts +1 -1
  42. package/dist/tools/search-docs.js +1 -71
  43. package/dist/types/index.d.ts +1 -1
  44. package/dist/types/index.js +0 -8
  45. package/package.json +4 -2
  46. package/dist/cli.js.map +0 -1
  47. package/dist/docs/apis.js.map +0 -1
  48. package/dist/docs/components.js.map +0 -1
  49. package/dist/docs/index.js.map +0 -1
  50. package/dist/docs/loader.js.map +0 -1
  51. package/dist/docs/search.js.map +0 -1
  52. package/dist/docs/standards.js.map +0 -1
  53. package/dist/docs/utils.js.map +0 -1
  54. package/dist/generator/header.js.map +0 -1
  55. package/dist/generator/index.js.map +0 -1
  56. package/dist/generator/vue-template.js.map +0 -1
  57. package/dist/index.js.map +0 -1
  58. package/dist/recommend/index.js.map +0 -1
  59. package/dist/tools/generate-code.js.map +0 -1
  60. package/dist/tools/get-api-info.js.map +0 -1
  61. package/dist/tools/get-coding-standard.js.map +0 -1
  62. package/dist/tools/get-component-info.js.map +0 -1
  63. package/dist/tools/get-util-info.js.map +0 -1
  64. package/dist/tools/index.js.map +0 -1
  65. package/dist/tools/recommend-solution.js.map +0 -1
  66. package/dist/tools/search-docs.js.map +0 -1
  67. package/dist/types/index.js.map +0 -1
@@ -1,672 +1,307 @@
1
+ import{generateFileHeader as m,generateScssFileHeader as b}from"./header.js";import{generateVueTemplate as j,filterValidComponents as P,suggestComponents as O}from"./vue-template.js";export*from"./header.js";export*from"./vue-template.js";function h(n){const t=[/创建(.+?)组件/,/生成(.+?)页面/,/实现(.+?)功能/,/(.+?)页面/,/(.+?)列表/,/(.+?)表单/,/(.+?)详情/];for(const o of t){const e=n.match(o);if(e&&e[1])return e[1].trim().replace(/[\s_]+/g,"-").toLowerCase()}return"my-page"}function v(n){const t=[/创建(.+?)组件/,/生成(.+?)页面/,/实现(.+?)功能/,/(.+?)页面/];for(const o of t){const e=n.match(o);if(e&&e[1])return e[1].trim()}return"\u9875\u9762\u6807\u9898"}function $(n,t,o=!0){const e=m({description:n}),a=o?`/rest/mock/${t}`:`/api/${t}`;return{code:`${e}
2
+
1
3
  /**
2
- * 代码生成器主入口
3
- * @作者 li peng
4
- * @创建时间 2024-12-29
5
- * @描述 根据需求生成符合 M8 规范的代码,包括 Vue、SCSS、Router、Mock 等
4
+ * ${n} - API \u63A5\u53E3
5
+ * \u4F7F\u7528 Util.ajax \u53D1\u9001\u8BF7\u6C42\uFF0C\u9075\u5FAA M8 \u89C4\u8303
6
6
  */
7
- import { generateFileHeader, generateScssFileHeader } from './header.js';
8
- import { generateVueTemplate, filterValidComponents, suggestComponents } from './vue-template.js';
7
+
9
8
  /**
10
- * 从需求描述中提取模块名称
11
- * @param requirement 需求描述
12
- * @returns 模块名称 (kebab-case)
9
+ * \u83B7\u53D6\u5217\u8868\u6570\u636E
10
+ * @param {Object} params - \u8BF7\u6C42\u53C2\u6570
11
+ * @returns {Promise} \u8BF7\u6C42\u7ED3\u679C
13
12
  */
14
- function extractModuleName(requirement) {
15
- // 尝试从需求中提取有意义的名称
16
- const patterns = [
17
- /创建(.+?)组件/,
18
- /生成(.+?)页面/,
19
- /实现(.+?)功能/,
20
- /(.+?)页面/,
21
- /(.+?)列表/,
22
- /(.+?)表单/,
23
- /(.+?)详情/
24
- ];
25
- for (const pattern of patterns) {
26
- const match = requirement.match(pattern);
27
- if (match && match[1]) {
28
- // 转换为 kebab-case
29
- return match[1]
30
- .trim()
31
- .replace(/[\s_]+/g, '-')
32
- .toLowerCase();
33
- }
34
- }
35
- // 默认名称
36
- return 'my-page';
37
- }
38
- /**
39
- * 从需求描述中提取页面标题
40
- * @param requirement 需求描述
41
- * @returns 页面标题
42
- */
43
- function extractPageTitle(requirement) {
44
- const patterns = [
45
- /创建(.+?)组件/,
46
- /生成(.+?)页面/,
47
- /实现(.+?)功能/,
48
- /(.+?)页面/,
49
- ];
50
- for (const pattern of patterns) {
51
- const match = requirement.match(pattern);
52
- if (match && match[1]) {
53
- return match[1].trim();
54
- }
55
- }
56
- return '页面标题';
57
- }
58
- /**
59
- * 生成 API 调用代码
60
- * @param requirement 需求描述
61
- * @param moduleName 模块名称
62
- * @param useMock 是否使用 Mock
63
- * @returns 生成的代码
64
- */
65
- function generateApiCallCode(requirement, moduleName, useMock = true) {
66
- const header = generateFileHeader({
67
- description: requirement
68
- });
69
- const apiPath = useMock ? `/rest/mock/${moduleName}` : `/api/${moduleName}`;
70
- const code = `${header}
71
-
72
- /**
73
- * ${requirement} - API 接口
74
- * 使用 Util.ajax 发送请求,遵循 M8 规范
75
- */
76
-
77
- /**
78
- * 获取列表数据
79
- * @param {Object} params - 请求参数
80
- * @returns {Promise} 请求结果
81
- */
82
- export function getList(params = {}) {
83
- return Util.ajax({
84
- url: Config.serverUrl + '${apiPath}/list',
85
- type: 'POST',
86
- data: {
87
- params: JSON.stringify(params)
88
- },
89
- dataPath: 'data'
90
- });
91
- }
92
-
93
- /**
94
- * 获取详情数据
95
- * @param {string} id - 数据 ID
96
- * @returns {Promise} 请求结果
97
- */
98
- export function getDetail(id) {
99
- return Util.ajax({
100
- url: Config.serverUrl + '${apiPath}/detail',
101
- type: 'POST',
102
- data: {
103
- params: JSON.stringify({ id })
104
- },
105
- dataPath: 'data'
106
- });
107
- }
108
-
109
- /**
110
- * 提交数据
111
- * @param {Object} data - 提交的数据
112
- * @returns {Promise} 请求结果
113
- */
114
- export function submitData(data) {
115
- return Util.ajax({
116
- url: Config.serverUrl + '${apiPath}/submit',
117
- type: 'POST',
118
- data: {
119
- params: JSON.stringify(data)
120
- }
121
- });
122
- }
123
- `;
124
- return {
125
- code,
126
- language: 'javascript',
127
- explanation: `生成了符合 M8 规范的 API 调用代码:
128
- - 使用 Util.ajax 而非 fetch 或 axios
129
- - 使用 Config.serverUrl 作为 API 基础 URL
130
- - ${useMock ? '使用 Mock 接口路径 /rest/mock/' : '使用正式接口路径 /api/'}
131
- - 包含完整的错误处理`
132
- };
13
+ export function getList(params = {}) {
14
+ return Util.ajax({
15
+ url: Config.serverUrl + '${a}/list',
16
+ type: 'POST',
17
+ data: {
18
+ params: JSON.stringify(params)
19
+ },
20
+ dataPath: 'data'
21
+ });
133
22
  }
23
+
134
24
  /**
135
- * 生成 JavaScript 代码
136
- * @param requirement 需求描述
137
- * @returns 生成的代码
25
+ * \u83B7\u53D6\u8BE6\u60C5\u6570\u636E
26
+ * @param {string} id - \u6570\u636E ID
27
+ * @returns {Promise} \u8BF7\u6C42\u7ED3\u679C
138
28
  */
139
- function generateJavaScriptCode(requirement) {
140
- const header = generateFileHeader({
141
- description: requirement
142
- });
143
- const code = `${header}
144
-
145
- /**
146
- * ${requirement}
147
- */
148
-
149
- /**
150
- * 示例函数
151
- * @param {Object} options - 配置选项
152
- * @returns {*} 处理结果
153
- */
154
- export function processData(options = {}) {
155
- // TODO: 实现数据处理逻辑
156
- return options;
157
- }
158
- `;
159
- return {
160
- code,
161
- language: 'javascript',
162
- explanation: `生成了基础的 JavaScript 代码框架,包含:
163
- - 规范的文件头注释
164
- - 函数注释模板
165
- - 基础代码结构`
166
- };
29
+ export function getDetail(id) {
30
+ return Util.ajax({
31
+ url: Config.serverUrl + '${a}/detail',
32
+ type: 'POST',
33
+ data: {
34
+ params: JSON.stringify({ id })
35
+ },
36
+ dataPath: 'data'
37
+ });
167
38
  }
39
+
168
40
  /**
169
- * 生成 SCSS 代码
170
- * @param requirement 需求描述
171
- * @param moduleName 模块名称
172
- * @returns 生成的代码
41
+ * \u63D0\u4EA4\u6570\u636E
42
+ * @param {Object} data - \u63D0\u4EA4\u7684\u6570\u636E
43
+ * @returns {Promise} \u8BF7\u6C42\u7ED3\u679C
173
44
  */
174
- function generateScssCode(requirement, moduleName) {
175
- const header = generateScssFileHeader({
176
- description: requirement
177
- });
178
- // 生成 CSS 类名 (使用下划线风格)
179
- const cssClassName = moduleName.replace(/-/g, '_');
180
- const req = requirement.toLowerCase();
181
- // 判断页面类型生成对应样式
182
- const isLoginPage = req.includes('登录') || req.includes('login');
183
- const isFormPage = req.includes('表单') || req.includes('form') || isLoginPage;
184
- const isListPage = req.includes('列表') || req.includes('list');
185
- let styleContent = '';
186
- if (isLoginPage) {
187
- styleContent = `
188
- // 登录页面样式
189
- .${cssClassName} {
190
- min-height: 100vh;
191
- padding: 40px 24px;
192
- background: #f5f7fa;
193
-
194
- &__form {
195
- padding: 24px;
196
- background: #fff;
197
- border-radius: 8px;
198
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
199
- }
200
-
201
- &__actions {
202
- margin-top: 24px;
203
- padding: 0 16px;
204
- }
205
- }`;
206
- }
207
- else if (isFormPage) {
208
- styleContent = `
209
- // 表单页面样式
210
- .${cssClassName} {
211
- min-height: 100vh;
212
- padding: 12px;
213
- background: #f5f7fa;
214
-
215
- &__actions {
216
- margin-top: 24px;
217
- padding: 0 16px;
218
- }
219
- }`;
45
+ export function submitData(data) {
46
+ return Util.ajax({
47
+ url: Config.serverUrl + '${a}/submit',
48
+ type: 'POST',
49
+ data: {
50
+ params: JSON.stringify(data)
220
51
  }
221
- else if (isListPage) {
222
- styleContent = `
223
- // 列表页面样式
224
- .${cssClassName} {
225
- min-height: 100vh;
226
- background: #f5f7fa;
227
-
228
- &__item {
229
- margin-bottom: 8px;
230
- background: #fff;
231
- }
232
- }`;
233
- }
234
- else {
235
- styleContent = `
236
- // 页面样式
237
- .${cssClassName} {
238
- min-height: 100vh;
239
- padding: 12px;
240
- background: #f5f7fa;
241
-
242
- &__content {
243
- padding: 16px;
244
- background: #fff;
245
- border-radius: 8px;
246
- }
247
- }`;
248
- }
249
- const code = `${header}
250
- /**
251
- * ${requirement}
252
- * 样式文件遵循 BEM 命名规范
253
- */
254
- ${styleContent}
255
- `;
256
- return {
257
- code,
258
- language: 'scss',
259
- explanation: `生成了符合 M8 规范的 SCSS 代码:
260
- - 使用 BEM 命名规范
261
- - 使用下划线风格的类名
262
- - 规范的文件头注释`
263
- };
52
+ });
264
53
  }
54
+ `,language:"javascript",explanation:`\u751F\u6210\u4E86\u7B26\u5408 M8 \u89C4\u8303\u7684 API \u8C03\u7528\u4EE3\u7801\uFF1A
55
+ - \u4F7F\u7528 Util.ajax \u800C\u975E fetch \u6216 axios
56
+ - \u4F7F\u7528 Config.serverUrl \u4F5C\u4E3A API \u57FA\u7840 URL
57
+ - ${o?"\u4F7F\u7528 Mock \u63A5\u53E3\u8DEF\u5F84 /rest/mock/":"\u4F7F\u7528\u6B63\u5F0F\u63A5\u53E3\u8DEF\u5F84 /api/"}
58
+ - \u5305\u542B\u5B8C\u6574\u7684\u9519\u8BEF\u5904\u7406`}}function C(n){return{code:`${m({description:n})}
59
+
265
60
  /**
266
- * 生成路由配置代码
267
- * @param moduleName 模块名称
268
- * @param pageTitle 页面标题
269
- * @returns 生成的代码
61
+ * ${n}
270
62
  */
271
- function generateRouterCode(moduleName, pageTitle) {
272
- const header = generateFileHeader({
273
- description: `${pageTitle} - 路由配置`
274
- });
275
- const code = `${header}
276
-
277
- /**
278
- * ${pageTitle} 路由配置
279
- * router.js 无需 import 组件,path 路径需与 vue 组件名称保持匹配
280
- * 构建时会自动将模块下的路由配置合并到 pages.json 内
281
- */
282
-
283
- // 定义路由规则
284
- const routes = [
285
- {
286
- path: 'pages/${moduleName}/index',
287
- style: {
288
- navigationBarTitleText: '${pageTitle}',
289
- navigationStyle: 'custom'
290
- }
291
- }
292
- ];
293
-
294
- // 路由选项
295
- const options = {
296
- autoSubPackages: true,
297
- isFirstModule: false
298
- };
299
-
300
- // 导出路由配置
301
- export default { routes, options };
302
- `;
303
- return {
304
- code,
305
- language: 'javascript',
306
- explanation: `生成了符合 M8 规范的路由配置:
307
- - 路径与 Vue 组件名称匹配
308
- - 包含导航栏标题配置
309
- - 使用 custom 导航样式`
310
- };
311
- }
63
+
312
64
  /**
313
- * 生成 Mock 数据代码
314
- * @param moduleName 模块名称
315
- * @param requirement 需求描述
316
- * @returns 生成的代码
65
+ * \u793A\u4F8B\u51FD\u6570
66
+ * @param {Object} options - \u914D\u7F6E\u9009\u9879
67
+ * @returns {*} \u5904\u7406\u7ED3\u679C
317
68
  */
318
- function generateMockCode(moduleName, requirement) {
319
- const header = generateFileHeader({
320
- description: `${requirement} - Mock 数据`
321
- });
322
- const req = requirement.toLowerCase();
323
- const isLoginPage = req.includes('登录') || req.includes('login');
324
- const isListPage = req.includes('列表') || req.includes('list');
325
- let mockContent = '';
326
- if (isLoginPage) {
327
- mockContent = `
328
- {
329
- // 登录接口
330
- methodUrl: '/rest/mock/${moduleName}/submit',
331
- input: {},
332
- output: Mock.mock({
333
- status: {
334
- code: 1,
335
- text: '登录成功'
336
- },
337
- data: {
338
- token: '@guid',
339
- userId: '@id',
340
- username: '@cname'
341
- }
342
- })
343
- }`;
344
- }
345
- else if (isListPage) {
346
- mockContent = `
347
- {
348
- // 列表接口
349
- methodUrl: '/rest/mock/${moduleName}/list',
350
- input: {},
351
- output: Mock.mock({
352
- status: {
353
- code: 1,
354
- text: '成功'
355
- },
356
- data: {
357
- 'list|10-20': [
358
- {
359
- 'id|+1': 1,
360
- title: '@ctitle(5, 15)',
361
- date: '@date("yyyy-MM-dd")',
362
- content: '@cparagraph(1, 2)'
363
- }
364
- ],
365
- total: '@integer(50, 200)'
366
- }
367
- })
368
- },
369
- {
370
- // 详情接口
371
- methodUrl: '/rest/mock/${moduleName}/detail',
372
- input: {},
373
- output: Mock.mock({
374
- status: {
375
- code: 1,
376
- text: '成功'
377
- },
378
- data: {
379
- id: '@id',
380
- title: '@ctitle(10, 20)',
381
- content: '@cparagraph(5, 10)',
382
- createTime: '@datetime("yyyy-MM-dd HH:mm:ss")',
383
- author: '@cname'
384
- }
385
- })
386
- }`;
387
- }
388
- else {
389
- mockContent = `
390
- {
391
- // 获取数据接口
392
- methodUrl: '/rest/mock/${moduleName}',
393
- input: {},
394
- output: Mock.mock({
395
- status: {
396
- code: 1,
397
- text: '成功'
398
- },
399
- data: {
400
- id: '@id',
401
- name: '@cname',
402
- createTime: '@datetime("yyyy-MM-dd HH:mm:ss")'
403
- }
404
- })
405
- },
406
- {
407
- // 提交数据接口
408
- methodUrl: '/rest/mock/${moduleName}/submit',
409
- input: {},
410
- output: Mock.mock({
411
- status: {
412
- code: 1,
413
- text: '提交成功'
414
- },
415
- data: {
416
- id: '@id'
417
- }
418
- })
419
- }`;
420
- }
421
- const code = `${header}
422
-
423
- /**
424
- * ${requirement} - Mock 数据配置
425
- * Mock 文件定义请求本地接口时响应的模拟数据
426
- */
427
- import Mock from '@mock';
428
-
429
- const mockData = [${mockContent}
430
- ];
431
-
432
- export default mockData;
433
- `;
434
- return {
435
- code,
436
- language: 'javascript',
437
- explanation: `生成了符合 M8 规范的 Mock 数据配置:
438
- - 使用 @mock 导入 Mock 库
439
- - 定义了 methodUrl 匹配的接口
440
- - 使用 Mock.mock 生成随机数据`
441
- };
69
+ export function processData(options = {}) {
70
+ // TODO: \u5B9E\u73B0\u6570\u636E\u5904\u7406\u903B\u8F91
71
+ return options;
442
72
  }
73
+ `,language:"javascript",explanation:`\u751F\u6210\u4E86\u57FA\u7840\u7684 JavaScript \u4EE3\u7801\u6846\u67B6\uFF0C\u5305\u542B\uFF1A
74
+ - \u89C4\u8303\u7684\u6587\u4EF6\u5934\u6CE8\u91CA
75
+ - \u51FD\u6570\u6CE8\u91CA\u6A21\u677F
76
+ - \u57FA\u7840\u4EE3\u7801\u7ED3\u6784`}}function M(n,t){const o=b({description:n}),e=t.replace(/-/g,"_"),a=n.toLowerCase(),p=a.includes("\u767B\u5F55")||a.includes("login"),r=a.includes("\u8868\u5355")||a.includes("form")||p,s=a.includes("\u5217\u8868")||a.includes("list");let i="";return p?i=`
77
+ // \u767B\u5F55\u9875\u9762\u6837\u5F0F
78
+ .${e} {
79
+ min-height: 100vh;
80
+ padding: 40px 24px;
81
+ background: #f5f7fa;
82
+
83
+ &__form {
84
+ padding: 24px;
85
+ background: #fff;
86
+ border-radius: 8px;
87
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
88
+ }
89
+
90
+ &__actions {
91
+ margin-top: 24px;
92
+ padding: 0 16px;
93
+ }
94
+ }`:r?i=`
95
+ // \u8868\u5355\u9875\u9762\u6837\u5F0F
96
+ .${e} {
97
+ min-height: 100vh;
98
+ padding: 12px;
99
+ background: #f5f7fa;
100
+
101
+ &__actions {
102
+ margin-top: 24px;
103
+ padding: 0 16px;
104
+ }
105
+ }`:s?i=`
106
+ // \u5217\u8868\u9875\u9762\u6837\u5F0F
107
+ .${e} {
108
+ min-height: 100vh;
109
+ background: #f5f7fa;
110
+
111
+ &__item {
112
+ margin-bottom: 8px;
113
+ background: #fff;
114
+ }
115
+ }`:i=`
116
+ // \u9875\u9762\u6837\u5F0F
117
+ .${e} {
118
+ min-height: 100vh;
119
+ padding: 12px;
120
+ background: #f5f7fa;
121
+
122
+ &__content {
123
+ padding: 16px;
124
+ background: #fff;
125
+ border-radius: 8px;
126
+ }
127
+ }`,{code:`${o}
443
128
  /**
444
- * 生成 Vue 组件代码
445
- * @param requirement 需求描述
446
- * @param vueVersion Vue 版本
447
- * @param components 使用的组件列表
448
- * @param useMock 是否使用 Mock
449
- * @returns 生成的代码
129
+ * ${n}
130
+ * \u6837\u5F0F\u6587\u4EF6\u9075\u5FAA BEM \u547D\u540D\u89C4\u8303
450
131
  */
451
- function generateVueComponentCode(requirement, vueVersion = 2, components = [], useMock = true) {
452
- // 从需求中提取组件名称
453
- const componentName = extractModuleName(requirement);
454
- const pageTitle = extractPageTitle(requirement);
455
- // 验证组件
456
- const { valid: validComponents, warnings } = filterValidComponents(components);
457
- // 如果没有指定组件,根据需求智能推荐
458
- const finalComponents = validComponents.length > 0
459
- ? validComponents
460
- : suggestComponents(requirement);
461
- const options = {
462
- name: componentName,
463
- vueVersion,
464
- description: requirement,
465
- components: finalComponents,
466
- includeStyle: true,
467
- useMock,
468
- pageTitle
469
- };
470
- const code = generateVueTemplate(options);
471
- const apiStyle = vueVersion === 3 ? 'Composition API (script setup)' : 'Options API';
472
- let explanation = `生成了 Vue${vueVersion} 组件代码:
473
- - 使用 ${apiStyle} 语法
474
- - 包含规范的文件头注释
475
- - 样式通过 @import 引入外部 SCSS 文件
476
- - 使用 ejs.ui.toast/showWaiting 等原生 API
477
- - 使用 Util.ajax + Config.serverUrl 发送请求`;
478
- if (finalComponents.length > 0) {
479
- explanation += `\n- 使用了 ${finalComponents.join(', ')} 组件`;
480
- }
481
- if (warnings.length > 0) {
482
- explanation += `\n\n⚠️ 警告:\n${warnings.map(w => `- ${w}`).join('\n')}`;
483
- }
484
- return {
485
- code,
486
- language: 'vue',
487
- explanation
488
- };
489
- }
132
+ ${i}
133
+ `,language:"scss",explanation:`\u751F\u6210\u4E86\u7B26\u5408 M8 \u89C4\u8303\u7684 SCSS \u4EE3\u7801\uFF1A
134
+ - \u4F7F\u7528 BEM \u547D\u540D\u89C4\u8303
135
+ - \u4F7F\u7528\u4E0B\u5212\u7EBF\u98CE\u683C\u7684\u7C7B\u540D
136
+ - \u89C4\u8303\u7684\u6587\u4EF6\u5934\u6CE8\u91CA`}}function S(n,t){return{code:`${m({description:`${t} - \u8DEF\u7531\u914D\u7F6E`})}
137
+
490
138
  /**
491
- * 代码生成器类
139
+ * ${t} \u8DEF\u7531\u914D\u7F6E
140
+ * router.js \u65E0\u9700 import \u7EC4\u4EF6\uFF0Cpath \u8DEF\u5F84\u9700\u4E0E vue \u7EC4\u4EF6\u540D\u79F0\u4FDD\u6301\u5339\u914D
141
+ * \u6784\u5EFA\u65F6\u4F1A\u81EA\u52A8\u5C06\u6A21\u5757\u4E0B\u7684\u8DEF\u7531\u914D\u7F6E\u5408\u5E76\u5230 pages.json \u5185
492
142
  */
493
- export class CodeGenerator {
494
- /**
495
- * 生成代码
496
- * @param options 生成选项
497
- * @returns 生成的代码
498
- */
499
- generateCode(options) {
500
- const { type, requirement, vueVersion = 2, components = [], useMock = true } = options;
501
- // 如果 type 是数组,使用 generateMultipleCode
502
- if (Array.isArray(type)) {
503
- const result = this.generateMultipleCode({
504
- types: type,
505
- requirement,
506
- vueVersion,
507
- components,
508
- useMock
509
- });
510
- // 返回第一个文件作为兼容
511
- return {
512
- code: result.files.map(f => f.code).join('\n\n'),
513
- language: 'text',
514
- explanation: result.explanation
515
- };
516
- }
517
- const moduleName = extractModuleName(requirement);
518
- switch (type) {
519
- case 'vue-component':
520
- return generateVueComponentCode(requirement, vueVersion, components, useMock);
521
- case 'javascript':
522
- return generateJavaScriptCode(requirement);
523
- case 'scss':
524
- return generateScssCode(requirement, moduleName);
525
- case 'api-call':
526
- return generateApiCallCode(requirement, moduleName, useMock);
527
- case 'full-page':
528
- // full-page 转换为完整页面生成(Vue + SCSS + Router + Mock)
529
- const result = this.generateMultipleCode({
530
- types: ['vue-component', 'scss', 'router', 'mock'],
531
- requirement,
532
- vueVersion,
533
- components,
534
- useMock
535
- });
536
- return {
537
- code: result.files.map(f => `// === ${f.relativePath || f.filename} ===\n${f.code}`).join('\n\n'),
538
- language: 'text',
539
- explanation: result.explanation
540
- };
541
- default:
542
- return {
543
- code: '',
544
- language: 'text',
545
- explanation: `不支持的代码类型: ${type}`
546
- };
547
- }
143
+
144
+ // \u5B9A\u4E49\u8DEF\u7531\u89C4\u5219
145
+ const routes = [
146
+ {
147
+ path: 'pages/${n}/index',
148
+ style: {
149
+ navigationBarTitleText: '${t}',
150
+ navigationStyle: 'custom'
548
151
  }
549
- /**
550
- * 生成多种类型的代码
551
- * @param options 多文件生成选项
552
- * @returns 多文件生成结果
553
- */
554
- generateMultipleCode(options) {
555
- const { types, requirement, vueVersion = 2, components = [], useMock = true } = options;
556
- const moduleName = extractModuleName(requirement);
557
- const pageTitle = extractPageTitle(requirement);
558
- // 默认模块路径在 src/pages 下
559
- const modulePath = options.modulePath || `src/pages/${moduleName}`;
560
- const files = [];
561
- const explanations = [];
562
- for (const type of types) {
563
- let result;
564
- let filename;
565
- let relativePath;
566
- switch (type) {
567
- case 'vue-component':
568
- result = generateVueComponentCode(requirement, vueVersion, components, useMock);
569
- filename = 'index.vue';
570
- relativePath = `${modulePath}/index.vue`;
571
- break;
572
- case 'javascript':
573
- result = generateJavaScriptCode(requirement);
574
- filename = `${moduleName}.js`;
575
- relativePath = `${modulePath}/${moduleName}.js`;
576
- break;
577
- case 'scss':
578
- result = generateScssCode(requirement, moduleName);
579
- filename = `${moduleName}.scss`;
580
- relativePath = `${modulePath}/css/${moduleName}.scss`;
581
- break;
582
- case 'api-call':
583
- result = generateApiCallCode(requirement, moduleName, useMock);
584
- filename = 'api.js';
585
- relativePath = `${modulePath}/api.js`;
586
- break;
587
- case 'router':
588
- result = generateRouterCode(moduleName, pageTitle);
589
- filename = 'router.js';
590
- relativePath = `${modulePath}/router.js`;
591
- break;
592
- case 'mock':
593
- result = generateMockCode(moduleName, requirement);
594
- filename = 'mock.js';
595
- relativePath = `${modulePath}/mock.js`;
596
- break;
597
- default:
598
- continue;
599
- }
600
- files.push({
601
- type,
602
- code: result.code,
603
- language: result.language,
604
- filename,
605
- relativePath
606
- });
607
- explanations.push(`**${relativePath}**: ${result.explanation.split('\n')[0]}`);
608
- }
609
- // 生成目录结构说明
610
- const structureExplanation = `
611
- ## 生成的文件结构
612
-
613
- \`\`\`
614
- ${modulePath}/
615
- ├── index.vue # Vue 页面组件
616
- ├── router.js # 路由配置
617
- ├── mock.js # Mock 数据
618
- └── css/
619
- └── ${moduleName}.scss # 样式文件
620
- \`\`\`
621
-
622
- ## 文件说明
623
-
624
- ${explanations.join('\n\n')}
625
-
626
- ## 使用说明
627
-
628
- 1. 将生成的文件放置到对应目录
629
- 2. Mock 数据会自动被框架加载
630
- 3. 路由配置会自动合并到 pages.json
631
- 4. 样式文件通过 @import 在 Vue 组件中引入
632
- `;
633
- return {
634
- files,
635
- explanation: structureExplanation,
636
- modulePath
637
- };
638
- }
639
- /**
640
- * 生成文件头注释
641
- * @param options 头部选项
642
- * @returns 头部注释字符串
643
- */
644
- generateFileHeader(options) {
645
- return generateFileHeader(options);
646
- }
647
- /**
648
- * 生成 Vue 模板
649
- * @param options 模板选项
650
- * @returns Vue 组件代码
651
- */
652
- generateVueTemplate(options) {
653
- return generateVueTemplate(options);
654
- }
655
- }
152
+ }
153
+ ];
154
+
155
+ // \u8DEF\u7531\u9009\u9879
156
+ const options = {
157
+ autoSubPackages: true,
158
+ isFirstModule: false
159
+ };
160
+
161
+ // \u5BFC\u51FA\u8DEF\u7531\u914D\u7F6E
162
+ export default { routes, options };
163
+ `,language:"javascript",explanation:`\u751F\u6210\u4E86\u7B26\u5408 M8 \u89C4\u8303\u7684\u8DEF\u7531\u914D\u7F6E\uFF1A
164
+ - \u8DEF\u5F84\u4E0E Vue \u7EC4\u4EF6\u540D\u79F0\u5339\u914D
165
+ - \u5305\u542B\u5BFC\u822A\u680F\u6807\u9898\u914D\u7F6E
166
+ - \u4F7F\u7528 custom \u5BFC\u822A\u6837\u5F0F`}}function U(n,t){const o=m({description:`${t} - Mock \u6570\u636E`}),e=t.toLowerCase(),a=e.includes("\u767B\u5F55")||e.includes("login"),p=e.includes("\u5217\u8868")||e.includes("list");let r="";return a?r=`
167
+ {
168
+ // \u767B\u5F55\u63A5\u53E3
169
+ methodUrl: '/rest/mock/${n}/submit',
170
+ input: {},
171
+ output: Mock.mock({
172
+ status: {
173
+ code: 1,
174
+ text: '\u767B\u5F55\u6210\u529F'
175
+ },
176
+ data: {
177
+ token: '@guid',
178
+ userId: '@id',
179
+ username: '@cname'
180
+ }
181
+ })
182
+ }`:p?r=`
183
+ {
184
+ // \u5217\u8868\u63A5\u53E3
185
+ methodUrl: '/rest/mock/${n}/list',
186
+ input: {},
187
+ output: Mock.mock({
188
+ status: {
189
+ code: 1,
190
+ text: '\u6210\u529F'
191
+ },
192
+ data: {
193
+ 'list|10-20': [
194
+ {
195
+ 'id|+1': 1,
196
+ title: '@ctitle(5, 15)',
197
+ date: '@date("yyyy-MM-dd")',
198
+ content: '@cparagraph(1, 2)'
199
+ }
200
+ ],
201
+ total: '@integer(50, 200)'
202
+ }
203
+ })
204
+ },
205
+ {
206
+ // \u8BE6\u60C5\u63A5\u53E3
207
+ methodUrl: '/rest/mock/${n}/detail',
208
+ input: {},
209
+ output: Mock.mock({
210
+ status: {
211
+ code: 1,
212
+ text: '\u6210\u529F'
213
+ },
214
+ data: {
215
+ id: '@id',
216
+ title: '@ctitle(10, 20)',
217
+ content: '@cparagraph(5, 10)',
218
+ createTime: '@datetime("yyyy-MM-dd HH:mm:ss")',
219
+ author: '@cname'
220
+ }
221
+ })
222
+ }`:r=`
223
+ {
224
+ // \u83B7\u53D6\u6570\u636E\u63A5\u53E3
225
+ methodUrl: '/rest/mock/${n}',
226
+ input: {},
227
+ output: Mock.mock({
228
+ status: {
229
+ code: 1,
230
+ text: '\u6210\u529F'
231
+ },
232
+ data: {
233
+ id: '@id',
234
+ name: '@cname',
235
+ createTime: '@datetime("yyyy-MM-dd HH:mm:ss")'
236
+ }
237
+ })
238
+ },
239
+ {
240
+ // \u63D0\u4EA4\u6570\u636E\u63A5\u53E3
241
+ methodUrl: '/rest/mock/${n}/submit',
242
+ input: {},
243
+ output: Mock.mock({
244
+ status: {
245
+ code: 1,
246
+ text: '\u63D0\u4EA4\u6210\u529F'
247
+ },
248
+ data: {
249
+ id: '@id'
250
+ }
251
+ })
252
+ }`,{code:`${o}
253
+
656
254
  /**
657
- * 转换为 PascalCase
658
- * @param str 输入字符串
659
- * @returns PascalCase 字符串
255
+ * ${t} - Mock \u6570\u636E\u914D\u7F6E
256
+ * Mock \u6587\u4EF6\u5B9A\u4E49\u8BF7\u6C42\u672C\u5730\u63A5\u53E3\u65F6\u54CD\u5E94\u7684\u6A21\u62DF\u6570\u636E
660
257
  */
661
- function toPascalCase(str) {
662
- return str
663
- .split('-')
664
- .map(part => part.charAt(0).toUpperCase() + part.slice(1))
665
- .join('');
666
- }
667
- // 导出单例
668
- export const codeGenerator = new CodeGenerator();
669
- // 导出子模块
670
- export * from './header.js';
671
- export * from './vue-template.js';
672
- //# sourceMappingURL=index.js.map
258
+ import Mock from '@mock';
259
+
260
+ const mockData = [${r}
261
+ ];
262
+
263
+ export default mockData;
264
+ `,language:"javascript",explanation:`\u751F\u6210\u4E86\u7B26\u5408 M8 \u89C4\u8303\u7684 Mock \u6570\u636E\u914D\u7F6E\uFF1A
265
+ - \u4F7F\u7528 @mock \u5BFC\u5165 Mock \u5E93
266
+ - \u5B9A\u4E49\u4E86 methodUrl \u5339\u914D\u7684\u63A5\u53E3
267
+ - \u4F7F\u7528 Mock.mock \u751F\u6210\u968F\u673A\u6570\u636E`}}function y(n,t=2,o=[],e=!0){const a=h(n),p=v(n),{valid:r,warnings:s}=P(o),i=r.length>0?r:O(n),f=j({name:a,vueVersion:t,description:n,components:i,includeStyle:!0,useMock:e,pageTitle:p});let g=`\u751F\u6210\u4E86 Vue${t} \u7EC4\u4EF6\u4EE3\u7801\uFF1A
268
+ - \u4F7F\u7528 ${t===3?"Composition API (script setup)":"Options API"} \u8BED\u6CD5
269
+ - \u5305\u542B\u89C4\u8303\u7684\u6587\u4EF6\u5934\u6CE8\u91CA
270
+ - \u6837\u5F0F\u901A\u8FC7 @import \u5F15\u5165\u5916\u90E8 SCSS \u6587\u4EF6
271
+ - \u4F7F\u7528 ejs.ui.toast/showWaiting \u7B49\u539F\u751F API
272
+ - \u4F7F\u7528 Util.ajax + Config.serverUrl \u53D1\u9001\u8BF7\u6C42`;return i.length>0&&(g+=`
273
+ - \u4F7F\u7528\u4E86 ${i.join(", ")} \u7EC4\u4EF6`),s.length>0&&(g+=`
274
+
275
+ \u26A0\uFE0F \u8B66\u544A:
276
+ ${s.map(x=>`- ${x}`).join(`
277
+ `)}`),{code:f,language:"vue",explanation:g}}class G{generateCode(t){const{type:o,requirement:e,vueVersion:a=2,components:p=[],useMock:r=!0}=t;if(Array.isArray(o)){const i=this.generateMultipleCode({types:o,requirement:e,vueVersion:a,components:p,useMock:r});return{code:i.files.map(c=>c.code).join(`
278
+
279
+ `),language:"text",explanation:i.explanation}}const s=h(e);switch(o){case"vue-component":return y(e,a,p,r);case"javascript":return C(e);case"scss":return M(e,s);case"api-call":return $(e,s,r);case"full-page":const i=this.generateMultipleCode({types:["vue-component","scss","router","mock"],requirement:e,vueVersion:a,components:p,useMock:r});return{code:i.files.map(c=>`// === ${c.relativePath||c.filename} ===
280
+ ${c.code}`).join(`
281
+
282
+ `),language:"text",explanation:i.explanation};default:return{code:"",language:"text",explanation:`\u4E0D\u652F\u6301\u7684\u4EE3\u7801\u7C7B\u578B: ${o}`}}}generateMultipleCode(t){const{types:o,requirement:e,vueVersion:a=2,components:p=[],useMock:r=!0}=t,s=h(e),i=v(e),c=t.modulePath||`src/pages/${s}`,f=[],k=[];for(const x of o){let d,l,u;switch(x){case"vue-component":d=y(e,a,p,r),l="index.vue",u=`${c}/index.vue`;break;case"javascript":d=C(e),l=`${s}.js`,u=`${c}/${s}.js`;break;case"scss":d=M(e,s),l=`${s}.scss`,u=`${c}/css/${s}.scss`;break;case"api-call":d=$(e,s,r),l="api.js",u=`${c}/api.js`;break;case"router":d=S(s,i),l="router.js",u=`${c}/router.js`;break;case"mock":d=U(s,e),l="mock.js",u=`${c}/mock.js`;break;default:continue}f.push({type:x,code:d.code,language:d.language,filename:l,relativePath:u}),k.push(`**${u}**: ${d.explanation.split(`
283
+ `)[0]}`)}const g=`
284
+ ## \u751F\u6210\u7684\u6587\u4EF6\u7ED3\u6784
285
+
286
+ \`\`\`
287
+ ${c}/
288
+ \u251C\u2500\u2500 index.vue # Vue \u9875\u9762\u7EC4\u4EF6
289
+ \u251C\u2500\u2500 router.js # \u8DEF\u7531\u914D\u7F6E
290
+ \u251C\u2500\u2500 mock.js # Mock \u6570\u636E
291
+ \u2514\u2500\u2500 css/
292
+ \u2514\u2500\u2500 ${s}.scss # \u6837\u5F0F\u6587\u4EF6
293
+ \`\`\`
294
+
295
+ ## \u6587\u4EF6\u8BF4\u660E
296
+
297
+ ${k.join(`
298
+
299
+ `)}
300
+
301
+ ## \u4F7F\u7528\u8BF4\u660E
302
+
303
+ 1. \u5C06\u751F\u6210\u7684\u6587\u4EF6\u653E\u7F6E\u5230\u5BF9\u5E94\u76EE\u5F55
304
+ 2. Mock \u6570\u636E\u4F1A\u81EA\u52A8\u88AB\u6846\u67B6\u52A0\u8F7D
305
+ 3. \u8DEF\u7531\u914D\u7F6E\u4F1A\u81EA\u52A8\u5408\u5E76\u5230 pages.json
306
+ 4. \u6837\u5F0F\u6587\u4EF6\u901A\u8FC7 @import \u5728 Vue \u7EC4\u4EF6\u4E2D\u5F15\u5165
307
+ `;return{files:f,explanation:g,modulePath:c}}generateFileHeader(t){return m(t)}generateVueTemplate(t){return j(t)}}const _=new G;export{G as CodeGenerator,_ as codeGenerator};