create-vue3-enterprise 1.0.1 → 1.0.2

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.

Potentially problematic release.


This version of create-vue3-enterprise might be problematic. Click here for more details.

package/dist/index.js CHANGED
@@ -1,34 +1,34 @@
1
1
  #!/usr/bin/env node
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import minimist from 'minimist';
6
- import prompts from 'prompts';
7
- import { red, green, cyan } from 'kolorist';
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import minimist from "minimist";
6
+ import prompts from "prompts";
7
+ import { red, green, cyan } from "kolorist";
8
8
  const argv = minimist(process.argv.slice(2), {
9
- string: ['_'],
10
- boolean: ['help', 'template', 'force'],
9
+ string: ["_"],
10
+ boolean: ["help", "template", "force"],
11
11
  alias: {
12
- h: 'help',
13
- t: 'template',
14
- f: 'force'
15
- }
12
+ h: "help",
13
+ t: "template",
14
+ f: "force",
15
+ },
16
16
  });
17
17
  const cwd = process.cwd();
18
18
  const __filename = fileURLToPath(import.meta.url);
19
19
  const __dirname = path.dirname(__filename);
20
20
  function printHelp() {
21
21
  console.log(`
22
- ${cyan('create-vue3-enterprise')}
22
+ ${cyan("create-vue3-enterprise")}
23
23
 
24
- ${green('Usage:')}
24
+ ${green("Usage:")}
25
25
  npm create vue3-enterprise <project-name> [options]
26
26
 
27
- ${green('Options:')}
27
+ ${green("Options:")}
28
28
  -h, --help Show help
29
29
  -f, --force Force overwrite
30
30
 
31
- ${green('Examples:')}
31
+ ${green("Examples:")}
32
32
  npm create vue3-enterprise my-project
33
33
  `);
34
34
  }
@@ -36,7 +36,12 @@ function isValidPackageName(projectName) {
36
36
  return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(projectName);
37
37
  }
38
38
  function toValidPackageName(projectName) {
39
- return projectName.trim().toLowerCase().replace(/\s+/g, '-').replace(/^[._]/, '').replace(/[^a-z0-9-~]+/g, '-');
39
+ return projectName
40
+ .trim()
41
+ .toLowerCase()
42
+ .replace(/\s+/g, "-")
43
+ .replace(/^[._]/, "")
44
+ .replace(/[^a-z0-9-~]+/g, "-");
40
45
  }
41
46
  function emptyDir(dir) {
42
47
  if (!fs.existsSync(dir))
@@ -58,66 +63,78 @@ function copyDir(srcDir, destDir) {
58
63
  }
59
64
  }
60
65
  function makePkg(targetDir, features, needRouter, needPinia) {
61
- const name = isValidPackageName(targetDir) ? targetDir : toValidPackageName(targetDir);
66
+ const name = isValidPackageName(targetDir)
67
+ ? targetDir
68
+ : toValidPackageName(targetDir);
62
69
  const pkg = {
63
70
  name,
64
- version: '0.0.0',
71
+ version: "0.0.0",
65
72
  private: true,
66
- type: 'module',
73
+ type: "module",
67
74
  scripts: {
68
- dev: 'vite',
69
- build: 'vue-tsc && vite build',
70
- preview: 'vite preview',
71
- test: 'vitest',
72
- 'test:e2e': 'playwright test',
73
- 'test:perf': 'playwright test --config=playwright.config.perf.ts',
74
- lint: 'eslint . --ext .vue,.ts,.tsx --fix',
75
- format: 'prettier --write .',
76
- 'type-check': 'vue-tsc --noEmit'
75
+ dev: "vite",
76
+ build: "vue-tsc && vite build",
77
+ preview: "vite preview",
78
+ test: "vitest",
79
+ "test:e2e": "playwright test",
80
+ "test:perf": "playwright test --config=playwright.config.perf.ts",
81
+ lint: "eslint . --ext .vue,.ts,.tsx --fix",
82
+ format: "prettier --write .",
83
+ "type-check": "vue-tsc --noEmit",
77
84
  },
78
- dependencies: { vue: '^3.4.0' },
85
+ dependencies: { vue: "^3.4.0" },
79
86
  devDependencies: {
80
- '@vitejs/plugin-vue': '^5.0.0',
81
- typescript: '^5.3.0',
82
- vite: '^5.0.0',
83
- 'vue-tsc': '^1.8.0'
84
- }
87
+ "@vitejs/plugin-vue": "^5.0.0",
88
+ typescript: "^5.3.0",
89
+ vite: "^5.0.0",
90
+ "vue-tsc": "^1.8.0",
91
+ },
85
92
  };
86
93
  if (needRouter)
87
- pkg.dependencies['vue-router'] = '^4.2.0';
94
+ pkg.dependencies["vue-router"] = "^4.2.0";
88
95
  if (needPinia)
89
- pkg.dependencies['pinia'] = '^2.1.0';
90
- if (features.includes('lint')) {
96
+ pkg.dependencies["pinia"] = "^2.1.0";
97
+ if (features.includes("lint")) {
91
98
  Object.assign(pkg.devDependencies, {
92
- '@typescript-eslint/eslint-plugin': '^6.21.0',
93
- '@typescript-eslint/parser': '^6.21.0',
94
- '@vue/eslint-config-prettier': '^9.0.0',
95
- '@vue/eslint-config-typescript': '^12.0.0',
96
- eslint: '^8.57.0',
97
- 'eslint-plugin-vue': '^9.21.0',
98
- prettier: '^3.2.0'
99
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
100
+ "@typescript-eslint/parser": "^6.21.0",
101
+ "@vue/eslint-config-prettier": "^9.0.0",
102
+ "@vue/eslint-config-typescript": "^12.0.0",
103
+ eslint: "^8.57.0",
104
+ "eslint-plugin-vue": "^9.21.0",
105
+ prettier: "^3.2.0",
106
+ husky: "^9.0.11",
107
+ "lint-staged": "^15.2.2",
99
108
  });
109
+ pkg.scripts["prepare"] = "husky";
110
+ pkg.scripts["lint-staged"] = "lint-staged";
111
+ pkg["lint-staged"] = {
112
+ "*.{js,jsx,ts,tsx,vue}": ["eslint --fix", "prettier --write"],
113
+ "*.{json,md,css,scss,html}": ["prettier --write"],
114
+ };
100
115
  }
101
- if (features.includes('vitest')) {
116
+ if (features.includes("vitest")) {
102
117
  Object.assign(pkg.devDependencies, {
103
- '@vue/test-utils': '^2.4.0',
104
- 'happy-dom': '^13.0.0',
105
- vitest: '^1.2.0'
118
+ "@vue/test-utils": "^2.4.0",
119
+ "happy-dom": "^13.0.0",
120
+ vitest: "^1.2.0",
106
121
  });
107
122
  }
108
- if (features.includes('playwright')) {
109
- pkg.devDependencies['@playwright/test'] = '^1.41.0';
123
+ if (features.includes("playwright")) {
124
+ pkg.devDependencies["@playwright/test"] = "^1.41.0";
110
125
  }
111
- if (features.includes('mcp')) {
112
- pkg.devDependencies['vue3-enterprise-mcp'] = '^1.0.0';
126
+ if (features.includes("mcp")) {
127
+ pkg.devDependencies["vue3-enterprise-mcp"] = "^1.0.0";
113
128
  }
114
- if (features.includes('ci')) {
115
- pkg.devDependencies['vue3-enterprise-ci'] = '^1.0.0';
129
+ if (features.includes("ci")) {
130
+ pkg.devDependencies["vue3-enterprise-ci"] = "^1.0.0";
116
131
  }
117
132
  return pkg;
118
133
  }
119
134
  async function main() {
120
- console.log(`\n${cyan('Vue3 Enterprise Toolchain')}\n`);
135
+ console.log(`
136
+ ${cyan("Vue3 Enterprise Toolchain")}
137
+ `);
121
138
  if (argv.help) {
122
139
  printHelp();
123
140
  return;
@@ -125,46 +142,67 @@ async function main() {
125
142
  let targetDir = argv._[0];
126
143
  const response = await prompts([
127
144
  {
128
- type: targetDir ? null : 'text',
129
- name: 'name',
130
- message: 'Project name:',
131
- initial: 'vue3-enterprise-project',
132
- onState: (s) => { targetDir = String(s.value).trim() || 'vue3-enterprise-project'; }
145
+ type: targetDir ? null : "text",
146
+ name: "name",
147
+ message: "Project name:",
148
+ initial: "vue3-enterprise-project",
149
+ onState: (s) => {
150
+ targetDir = String(s.value).trim() || "vue3-enterprise-project";
151
+ },
133
152
  },
134
153
  {
135
- type: 'select', name: 'template', message: 'Select template:',
154
+ type: "select",
155
+ name: "template",
156
+ message: "Select template:",
136
157
  choices: [
137
- { title: 'Vue3 + TypeScript + Vite', value: 'vue3-ts' },
138
- { title: 'Vue3 + TS + Vite + Pinia', value: 'vue3-ts-pinia' },
139
- { title: 'Vue3 + TS + Vite + Pinia + Router', value: 'vue3-ts-full' }
140
- ]
158
+ { title: "Vue3 + TypeScript + Vite", value: "vue3-ts" },
159
+ { title: "Vue3 + TS + Vite + Pinia", value: "vue3-ts-pinia" },
160
+ { title: "Vue3 + TS + Vite + Pinia + Router", value: "vue3-ts-full" },
161
+ ],
141
162
  },
142
163
  {
143
- type: 'multiselect', name: 'features', message: 'Select features:',
164
+ type: "multiselect",
165
+ name: "features",
166
+ message: "Select features:",
144
167
  choices: [
145
- { title: 'ESLint + Prettier', value: 'lint', selected: true },
146
- { title: 'Vitest', value: 'vitest', selected: true },
147
- { title: 'Playwright', value: 'playwright', selected: true },
148
- { title: 'Vue3 Enterprise MCP', value: 'mcp', selected: true },
149
- { title: 'CI/CD Workflow', value: 'ci', selected: true },
150
- { title: 'Performance Benchmark', value: 'perf', selected: true }
151
- ]
168
+ { title: "ESLint + Prettier", value: "lint", selected: true },
169
+ { title: "Vitest", value: "vitest", selected: true },
170
+ { title: "Playwright", value: "playwright", selected: true },
171
+ { title: "Vue3 Enterprise MCP", value: "mcp", selected: true },
172
+ { title: "CI/CD Workflow", value: "ci", selected: true },
173
+ { title: "Performance Benchmark", value: "perf", selected: true },
174
+ ],
152
175
  },
153
176
  {
154
- type: 'confirm', name: 'router', message: 'Add Vue Router?', initial: true
177
+ type: "confirm",
178
+ name: "router",
179
+ message: "Add Vue Router?",
180
+ initial: true,
155
181
  },
156
182
  {
157
- type: 'confirm', name: 'pinia', message: 'Add Pinia?', initial: true
183
+ type: "confirm",
184
+ name: "pinia",
185
+ message: "Add Pinia?",
186
+ initial: true,
158
187
  },
159
188
  {
160
- type: 'confirm', name: 'overwrite',
161
- message: targetDir && fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0
162
- ? `Dir "${targetDir}" exists. Overwrite?` : 'Overwrite existing?',
163
- initial: false
164
- }
165
- ], { onCancel: () => { console.log(red('✖ Cancelled')); process.exit(1); } });
189
+ type: "confirm",
190
+ name: "overwrite",
191
+ message: targetDir &&
192
+ fs.existsSync(targetDir) &&
193
+ fs.readdirSync(targetDir).length > 0
194
+ ? `Dir "${targetDir}" exists. Overwrite?`
195
+ : "Overwrite existing?",
196
+ initial: false,
197
+ },
198
+ ], {
199
+ onCancel: () => {
200
+ console.log(red("✖ Cancelled"));
201
+ process.exit(1);
202
+ },
203
+ });
166
204
  if (!response.overwrite) {
167
- console.log(red('✖ Cancelled'));
205
+ console.log(red("✖ Cancelled"));
168
206
  process.exit(1);
169
207
  }
170
208
  const root = path.join(cwd, targetDir);
@@ -178,24 +216,29 @@ async function main() {
178
216
  }
179
217
  else
180
218
  fs.mkdirSync(root, { recursive: true });
181
- console.log(`\n${cyan('Creating project...')}\n`);
182
- copyDir(path.resolve(__dirname, '../template'), root);
219
+ console.log(`
220
+ ${cyan("Creating project...")}
221
+ `);
222
+ copyDir(path.resolve(__dirname, "../template"), root);
183
223
  const pkg = makePkg(targetDir, response.features || [], response.router, response.pinia);
184
- fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(pkg, null, 2));
224
+ fs.writeFileSync(path.join(root, "package.json"), JSON.stringify(pkg, null, 2));
185
225
  const desc = {
186
- lint: '- 🧹 ESLint + Prettier',
187
- vitest: '- 🧪 Vitest Unit Tests',
188
- playwright: '- 🎭 Playwright E2E',
189
- mcp: '- 🔍 Vue3 Enterprise MCP',
190
- ci: '- ⚡ CI/CD',
191
- perf: '- 📊 Performance'
226
+ lint: "- 🧹 ESLint + Prettier",
227
+ vitest: "- 🧪 Vitest Unit Tests",
228
+ playwright: "- 🎭 Playwright E2E",
229
+ mcp: "- 🔍 Vue3 Enterprise MCP",
230
+ ci: "- ⚡ CI/CD",
231
+ perf: "- 📊 Performance",
192
232
  };
193
233
  const readme = `# ${pkg.name}
194
234
 
195
235
  Created with Vue3 Enterprise Toolchain
196
236
 
197
237
  ## Features
198
- ${(response.features || []).map((f) => desc[f]).filter(Boolean).join('\n')}
238
+ ${(response.features || [])
239
+ .map((f) => desc[f])
240
+ .filter(Boolean)
241
+ .join("\n")}
199
242
 
200
243
  ## Quick Start
201
244
  \`\`\`bash
@@ -208,9 +251,19 @@ npm run dev
208
251
  - \`npm run build\` - Build
209
252
  - \`npm test\` - Run tests
210
253
  `;
211
- fs.writeFileSync(path.join(root, 'README.md'), readme);
212
- const gitignore = `node_modules\ndist\n*.local\n.vscode\ncoverage\ntest-results\nplaywright-report\n.perf-baseline.json`;
213
- fs.writeFileSync(path.join(root, '.gitignore'), gitignore);
214
- console.log(`${green('✔')} Created!\n cd ${cyan(targetDir)}\n npm install\n npm run dev\n`);
254
+ fs.writeFileSync(path.join(root, "README.md"), readme);
255
+ const gitignore = `node_modules
256
+ dist
257
+ *.local
258
+ .vscode
259
+ coverage
260
+ test-results
261
+ playwright-report
262
+ .perf-baseline.json`;
263
+ fs.writeFileSync(path.join(root, ".gitignore"), gitignore);
264
+ console.log(`${green("✔")} Created!\n cd ${cyan(targetDir)}\n npm install\n npm run dev\n`);
215
265
  }
216
- main().catch((e) => { console.error(e); process.exit(1); });
266
+ main().catch((e) => {
267
+ console.error(e);
268
+ process.exit(1);
269
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-vue3-enterprise",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Vue3 + TypeScript + Vite 企业级项目脚手架",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,59 @@
1
+ #!/bin/sh
2
+ . "$(dirname "$0")/_/husky.sh"
3
+
4
+ # 获取提交信息
5
+ COMMIT_MSG_FILE=$1
6
+ COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
7
+
8
+ echo "🔍 正在检查提交信息规范..."
9
+
10
+ # 定义提交信息格式规范
11
+ # 支持的类型
12
+ VALID_TYPES="feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert"
13
+
14
+ # 检查提交信息格式
15
+ # 格式: type(scope): subject 或 type: subject
16
+ PATTERN="^($VALID_TYPES)(\(.+\))?: .+"
17
+
18
+ if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
19
+ echo ""
20
+ echo "❌ 提交信息格式错误!"
21
+ echo ""
22
+ echo "提交信息必须符合以下格式:"
23
+ echo " <type>: <subject>"
24
+ echo " 或"
25
+ echo " <type>(<scope>): <subject>"
26
+ echo ""
27
+ echo "支持的 type:"
28
+ echo " feat: 新功能"
29
+ echo " fix: 修复 bug"
30
+ echo " docs: 文档更新"
31
+ echo " style: 代码格式调整(不影响代码逻辑)"
32
+ echo " refactor: 重构代码"
33
+ echo " perf: 性能优化"
34
+ echo " test: 测试相关"
35
+ echo " chore: 构建/工具链相关"
36
+ echo " ci: CI/CD 相关"
37
+ echo " build: 构建相关"
38
+ echo " revert: 回滚提交"
39
+ echo ""
40
+ echo "示例:"
41
+ echo " feat: 添加用户登录功能"
42
+ echo " fix(auth): 修复登录失效问题"
43
+ echo " docs: 更新 README"
44
+ echo ""
45
+ exit 1
46
+ fi
47
+
48
+ # 检查提交信息长度
49
+ MSG_LENGTH=$(echo "$COMMIT_MSG" | wc -c)
50
+ if [ "$MSG_LENGTH" -gt 100 ]; then
51
+ echo ""
52
+ echo "⚠️ 提交信息过长 ($MSG_LENGTH 字符)"
53
+ echo "建议保持提交信息简洁,不超过 100 个字符"
54
+ echo ""
55
+ # 不阻止提交,只给出警告
56
+ fi
57
+
58
+ echo "✅ 提交信息格式正确!"
59
+ exit 0
@@ -0,0 +1,78 @@
1
+ #!/bin/sh
2
+ . "$(dirname "$0")/_/husky.sh"
3
+
4
+ echo "🔍 正在运行代码审查规范..."
5
+
6
+ # 获取当前暂存的文件列表
7
+ STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
8
+
9
+ if [ -z "$STAGED_FILES" ]; then
10
+ echo "ℹ️ 没有暂存的文件需要检查"
11
+ exit 0
12
+ fi
13
+
14
+ echo "📋 暂存文件列表:"
15
+ echo "$STAGED_FILES" | while read file; do
16
+ echo " - $file"
17
+ done
18
+
19
+ # 检查是否有需要 lint 的代码文件
20
+ CODE_FILES=$(echo "$STAGED_FILES" | grep -E '\.(js|jsx|ts|tsx|vue)$' || true)
21
+
22
+ if [ -n "$CODE_FILES" ]; then
23
+ echo ""
24
+ echo "🧹 正在运行 ESLint 检查..."
25
+ echo "$CODE_FILES" | xargs npx eslint --ext .js,.jsx,.ts,.tsx,.vue --max-warnings=0
26
+
27
+ if [ $? -ne 0 ]; then
28
+ echo ""
29
+ echo "❌ ESLint 检查失败"
30
+ echo " 请修复上述错误后重新提交"
31
+ exit 1
32
+ fi
33
+
34
+ echo " ✅ ESLint 检查通过"
35
+ fi
36
+
37
+ # 检查是否有 TypeScript 文件需要类型检查
38
+ TS_FILES=$(echo "$STAGED_FILES" | grep -E '\.(ts|tsx|vue)$' || true)
39
+
40
+ if [ -n "$TS_FILES" ]; then
41
+ echo ""
42
+ echo "🔎 正在运行 TypeScript 类型检查..."
43
+ npx vue-tsc --noEmit
44
+
45
+ if [ $? -ne 0 ]; then
46
+ echo ""
47
+ echo "❌ TypeScript 类型检查失败"
48
+ echo " 请修复类型错误后重新提交"
49
+ exit 1
50
+ fi
51
+
52
+ echo " ✅ TypeScript 类型检查通过"
53
+ fi
54
+
55
+ # 运行测试(仅运行与提交文件相关的测试)
56
+ echo ""
57
+ echo "🧪 正在运行相关单元测试..."
58
+ npx vitest run --reporter=verbose 2>&1 | head -50
59
+
60
+ if [ $? -ne 0 ]; then
61
+ echo ""
62
+ echo "❌ 单元测试失败"
63
+ echo " 请修复测试后重新提交"
64
+ exit 1
65
+ fi
66
+
67
+ echo " ✅ 单元测试通过"
68
+
69
+ echo ""
70
+ echo "🎉 所有代码审查规范检查通过!"
71
+ echo ""
72
+
73
+ # 如果有 MCP 配置,可以在这里调用 MCP 进行深度代码审查
74
+ if [ -f ".mcp-review.config.js" ] || [ -f "vue3-enterprise-mcp.config.js" ]; then
75
+ echo "💡 提示: 你可以运行 'npx vue3-enterprise-mcp review' 进行更深入的代码审查"
76
+ fi
77
+
78
+ exit 0
@@ -0,0 +1,153 @@
1
+ # 🚀 Vue3 Enterprise 脚手架项目
2
+
3
+ Vue3 + TypeScript + Vite 企业级开发脚手架
4
+
5
+ ## ✨ 功能特性
6
+
7
+ - **🎯 Vue3 + TypeScript + Vite** - 现代化的前端开发体验
8
+ - **🧹 ESLint + Prettier** - 自动化的代码规范检查
9
+ - **🧪 Vitest** - 快速的单元测试框架
10
+ - **🎭 Playwright** - 端到端测试方案
11
+ - **🔍 Vue3 Enterprise MCP** - Claude MCP Server 代码审查
12
+ - **⚡ CI/CD 工作流** - GitHub Actions 自动化
13
+
14
+ ## 🚀 快速开始
15
+
16
+ ```bash
17
+ # 创建新项目
18
+ npm create vue3-enterprise@latest my-project
19
+
20
+ # 进入项目目录
21
+ cd my-project
22
+
23
+ # 安装依赖
24
+ npm install
25
+
26
+ # 启动开发服务器
27
+ npm run dev
28
+ ```
29
+
30
+ ## 📋 可用脚本
31
+
32
+ | 脚本 | 说明 |
33
+ | -------------------- | ------------------------ |
34
+ | `npm run dev` | 启动开发服务器 |
35
+ | `npm run build` | 构建生产版本 |
36
+ | `npm run preview` | 预览生产构建 |
37
+ | `npm test` | 运行单元测试 |
38
+ | `npm run test:e2e` | 运行 E2E 测试 |
39
+ | `npm run lint` | 运行 ESLint 检查 |
40
+ | `npm run format` | 格式化代码 |
41
+ | `npm run type-check` | 运行 TypeScript 类型检查 |
42
+
43
+ ## 🏗️ 项目结构
44
+
45
+ ```
46
+ my-project/
47
+ ├── src/ # 源代码目录
48
+ │ ├── components/ # Vue 组件
49
+ │ ├── composables/ # 组合式函数
50
+ │ ├── views/ # 页面视图
51
+ │ ├── stores/ # Pinia 状态管理
52
+ │ ├── utils/ # 工具函数
53
+ │ ├── assets/ # 静态资源
54
+ │ ├── App.vue # 根组件
55
+ │ ├── main.ts # 入口文件
56
+ │ └── style.css # 全局样式
57
+ ├── tests/ # 测试目录
58
+ │ ├── unit/ # 单元测试
59
+ │ └── e2e/ # E2E 测试
60
+ ├── public/ # 静态文件
61
+ ├── .github/ # GitHub 配置
62
+ │ └── workflows/ # GitHub Actions
63
+ ├── index.html # HTML 模板
64
+ ├── package.json # 项目配置
65
+ ├── vite.config.ts # Vite 配置
66
+ ├── vitest.config.ts # Vitest 配置
67
+ ├── playwright.config.ts # Playwright 配置
68
+ ├── tsconfig.json # TypeScript 配置
69
+ ├── .eslintrc.cjs # ESLint 配置
70
+ └── .prettierrc # Prettier 配置
71
+ ```
72
+
73
+ ## 🔒 代码提交规范
74
+
75
+ 本项目使用 **Husky** + **lint-staged** 实现代码提交前自动检查。
76
+
77
+ ### 提交信息规范
78
+
79
+ 提交信息必须符合以下格式:
80
+
81
+ ```
82
+ <type>: <subject>
83
+ ```
84
+
85
+
86
+
87
+ ```
88
+ <type>(<scope>): <subject>
89
+ ```
90
+
91
+ ### 支持的 type
92
+
93
+ | 类型 | 说明 |
94
+ | ---------- | ------------------------------ |
95
+ | `feat` | 新功能 |
96
+ | `fix` | 修复 bug |
97
+ | `docs` | 文档更新 |
98
+ | `style` | 代码格式调整(不影响代码逻辑) |
99
+ | `refactor` | 重构代码 |
100
+ | `perf` | 性能优化 |
101
+ | `test` | 测试相关 |
102
+ | `chore` | 构建/工具链相关 |
103
+ | `ci` | CI/CD 相关 |
104
+ | `build` | 构建相关 |
105
+ | `revert` | 回滚提交 |
106
+
107
+ ### 示例
108
+
109
+ ```bash
110
+ git commit -m "feat: 添加用户登录功能"
111
+ git commit -m "fix(auth): 修复登录失效问题"
112
+ git commit -m "docs: 更新 README"
113
+ ```
114
+
115
+ ## 🧪 测试
116
+
117
+ ### 单元测试
118
+
119
+ ```bash
120
+ npm test
121
+ # 或
122
+ npm run test -- --coverage
123
+ ```
124
+
125
+ ### E2E 测试
126
+
127
+ ```bash
128
+ npm run test:e2e
129
+ ```
130
+
131
+ ## 📦 构建
132
+
133
+ ```bash
134
+ npm run build
135
+ ```
136
+
137
+ 构建后的文件将位于 `dist/` 目录。
138
+
139
+ ## 🚀 部署
140
+
141
+ 构建完成后,可以将 `dist/` 目录部署到任何静态文件服务器。
142
+
143
+ ## 📄 许可证
144
+
145
+ [MIT](LICENSE)
146
+
147
+ ## 🤝 贡献
148
+
149
+ 欢迎提交 Issue 和 Pull Request!
150
+
151
+ ## 📞 支持
152
+
153
+ 如有问题,请提交 GitHub Issue。
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "template",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vue-tsc && vite build",
9
+ "preview": "vite preview",
10
+ "test": "vitest",
11
+ "test:e2e": "playwright test",
12
+ "test:perf": "playwright test --config=playwright.config.perf.ts",
13
+ "lint": "eslint . --ext .vue,.ts,.tsx --fix",
14
+ "format": "prettier --write .",
15
+ "type-check": "vue-tsc --noEmit",
16
+ "prepare": "husky",
17
+ "lint-staged": "lint-staged"
18
+ },
19
+ "lint-staged": {
20
+ "*.{js,jsx,ts,tsx,vue}": [
21
+ "eslint --fix",
22
+ "prettier --write"
23
+ ],
24
+ "*.{json,md,css,scss,html}": [
25
+ "prettier --write"
26
+ ]
27
+ },
28
+ "dependencies": {
29
+ "vue": "^3.4.0"
30
+ },
31
+ "devDependencies": {
32
+ "@vitejs/plugin-vue": "^5.0.0",
33
+ "@vue/test-utils": "^2.4.0",
34
+ "happy-dom": "^13.0.0",
35
+ "husky": "^9.0.11",
36
+ "lint-staged": "^15.2.2",
37
+ "typescript": "^5.3.0",
38
+ "vite": "^5.0.0",
39
+ "vitest": "^1.2.0",
40
+ "vue-tsc": "^1.8.0"
41
+ }
42
+ }