vue-standard-wanfu 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -0
- package/bin/cli.js +131 -0
- package/package.json +35 -0
- package/template/.prettierrc +9 -0
- package/template/README.md +133 -0
- package/template/eslint.config.js +30 -0
- package/template/index.html +13 -0
- package/template/package-lock.json +3566 -0
- package/template/package.json +35 -0
- package/template/src/app/App.vue +16 -0
- package/template/src/components/HelloWorld.vue +82 -0
- package/template/src/main.ts +12 -0
- package/template/src/pages/index.vue +136 -0
- package/template/src/router/index.ts +17 -0
- package/template/src/styles/main.css +32 -0
- package/template/src/types/index.ts +25 -0
- package/template/tsconfig.json +33 -0
- package/template/tsconfig.node.json +11 -0
- package/template/vite.config.ts +17 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hello-world-vue",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"packageManager": "pnpm@10.x",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=24"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "vite",
|
|
11
|
+
"build": "vue-tsc --noEmit && vite build",
|
|
12
|
+
"typecheck": "vue-tsc --noEmit",
|
|
13
|
+
"lint": "eslint .",
|
|
14
|
+
"format": "prettier . --write",
|
|
15
|
+
"test": "vitest",
|
|
16
|
+
"preview": "vite preview"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"vue": "^3.5.0",
|
|
20
|
+
"vue-router": "^4.5.0",
|
|
21
|
+
"pinia": "^2.3.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@vitejs/plugin-vue": "^5.2.0",
|
|
25
|
+
"typescript": "^5.7.0",
|
|
26
|
+
"vite": "^6.0.0",
|
|
27
|
+
"vue-tsc": "^2.2.0",
|
|
28
|
+
"eslint": "^9.20.0",
|
|
29
|
+
"prettier": "^3.5.0",
|
|
30
|
+
"@eslint/js": "^9.20.0",
|
|
31
|
+
"typescript-eslint": "^8.24.0",
|
|
32
|
+
"eslint-plugin-vue": "^9.32.0",
|
|
33
|
+
"vitest": "^3.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="hello-world" @click="handleClick">
|
|
3
|
+
<h1>{{ message }}</h1>
|
|
4
|
+
<p class="subtitle">这是一个符合前端开发规范的 Vue 3 项目</p>
|
|
5
|
+
<div class="features">
|
|
6
|
+
<span class="feature-tag">TypeScript</span>
|
|
7
|
+
<span class="feature-tag">Vite</span>
|
|
8
|
+
<span class="feature-tag">Pinia</span>
|
|
9
|
+
<span class="feature-tag">Vue Router</span>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
// #region Props 定义
|
|
16
|
+
type Props = {
|
|
17
|
+
message: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
21
|
+
message: 'Hello World',
|
|
22
|
+
});
|
|
23
|
+
// #endregion
|
|
24
|
+
|
|
25
|
+
// #region Emits 定义
|
|
26
|
+
const emit = defineEmits<{
|
|
27
|
+
click: [];
|
|
28
|
+
}>();
|
|
29
|
+
// #endregion
|
|
30
|
+
|
|
31
|
+
// #region 事件处理
|
|
32
|
+
/**
|
|
33
|
+
* 处理点击事件,向父组件发送 click 事件
|
|
34
|
+
*/
|
|
35
|
+
const handleClick = () => {
|
|
36
|
+
emit('click');
|
|
37
|
+
};
|
|
38
|
+
// #endregion
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<style scoped>
|
|
42
|
+
.hello-world {
|
|
43
|
+
padding: 40px;
|
|
44
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
45
|
+
border-radius: 12px;
|
|
46
|
+
color: white;
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
transition: transform 0.3s, box-shadow 0.3s;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.hello-world:hover {
|
|
52
|
+
transform: translateY(-5px);
|
|
53
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.hello-world h1 {
|
|
57
|
+
font-size: 48px;
|
|
58
|
+
margin: 0 0 20px 0;
|
|
59
|
+
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.subtitle {
|
|
63
|
+
font-size: 18px;
|
|
64
|
+
margin: 0 0 30px 0;
|
|
65
|
+
opacity: 0.9;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.features {
|
|
69
|
+
display: flex;
|
|
70
|
+
gap: 10px;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
flex-wrap: wrap;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.feature-tag {
|
|
76
|
+
padding: 8px 16px;
|
|
77
|
+
background-color: rgba(255, 255, 255, 0.2);
|
|
78
|
+
border-radius: 20px;
|
|
79
|
+
font-size: 14px;
|
|
80
|
+
backdrop-filter: blur(10px);
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createApp } from 'vue';
|
|
2
|
+
import { createPinia } from 'pinia';
|
|
3
|
+
import router from './router';
|
|
4
|
+
import App from './app/App.vue';
|
|
5
|
+
import './styles/main.css';
|
|
6
|
+
|
|
7
|
+
const app = createApp(App);
|
|
8
|
+
|
|
9
|
+
app.use(createPinia());
|
|
10
|
+
app.use(router);
|
|
11
|
+
|
|
12
|
+
app.mount('#app');
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="hello-world-container">
|
|
3
|
+
<HelloWorld :message="welcomeMessage" @click="handleClick" />
|
|
4
|
+
|
|
5
|
+
<div class="info-section">
|
|
6
|
+
<h2>项目信息</h2>
|
|
7
|
+
<ul>
|
|
8
|
+
<li>Vue 版本: {{ vueVersion }}</li>
|
|
9
|
+
<li>TypeScript: 已启用</li>
|
|
10
|
+
<li>构建工具: Vite</li>
|
|
11
|
+
<li>状态管理: Pinia</li>
|
|
12
|
+
<li>路由: Vue Router</li>
|
|
13
|
+
</ul>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div class="counter-section">
|
|
17
|
+
<p>计数器: {{ count }}</p>
|
|
18
|
+
<button @click="increment" :disabled="isLoading">增加</button>
|
|
19
|
+
<button @click="decrement" :disabled="isLoading">减少</button>
|
|
20
|
+
<button @click="reset" :disabled="isLoading">重置</button>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
import { ref, computed } from 'vue';
|
|
27
|
+
import HelloWorld from '@/components/HelloWorld.vue';
|
|
28
|
+
|
|
29
|
+
// #region 响应式状态
|
|
30
|
+
const count = ref(0);
|
|
31
|
+
const isLoading = ref(false);
|
|
32
|
+
// #endregion
|
|
33
|
+
|
|
34
|
+
// #region 计算属性
|
|
35
|
+
const welcomeMessage = computed(() => `欢迎使用 Vue 3 Hello World`);
|
|
36
|
+
const vueVersion = computed(() => '3.5+');
|
|
37
|
+
// #endregion
|
|
38
|
+
|
|
39
|
+
// #region 事件处理
|
|
40
|
+
/**
|
|
41
|
+
* 处理点击事件
|
|
42
|
+
*/
|
|
43
|
+
const handleClick = () => {
|
|
44
|
+
console.log('HelloWorld 组件被点击');
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 增加计数
|
|
49
|
+
*/
|
|
50
|
+
const increment = () => {
|
|
51
|
+
count.value++;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 减少计数
|
|
56
|
+
*/
|
|
57
|
+
const decrement = () => {
|
|
58
|
+
if (count.value > 0) {
|
|
59
|
+
count.value--;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 重置计数
|
|
65
|
+
*/
|
|
66
|
+
const reset = () => {
|
|
67
|
+
count.value = 0;
|
|
68
|
+
};
|
|
69
|
+
// #endregion
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<style scoped>
|
|
73
|
+
.hello-world-container {
|
|
74
|
+
max-width: 800px;
|
|
75
|
+
margin: 0 auto;
|
|
76
|
+
padding: 40px 20px;
|
|
77
|
+
text-align: center;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.info-section {
|
|
81
|
+
margin: 40px 0;
|
|
82
|
+
padding: 20px;
|
|
83
|
+
background-color: #f5f5f5;
|
|
84
|
+
border-radius: 8px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.info-section h2 {
|
|
88
|
+
color: #42b983;
|
|
89
|
+
margin-bottom: 20px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.info-section ul {
|
|
93
|
+
list-style: none;
|
|
94
|
+
padding: 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.info-section li {
|
|
98
|
+
padding: 8px 0;
|
|
99
|
+
font-size: 16px;
|
|
100
|
+
color: #333;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.counter-section {
|
|
104
|
+
margin-top: 40px;
|
|
105
|
+
padding: 20px;
|
|
106
|
+
border: 2px solid #42b983;
|
|
107
|
+
border-radius: 8px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.counter-section p {
|
|
111
|
+
font-size: 24px;
|
|
112
|
+
margin-bottom: 20px;
|
|
113
|
+
color: #42b983;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.counter-section button {
|
|
117
|
+
margin: 0 10px;
|
|
118
|
+
padding: 10px 20px;
|
|
119
|
+
font-size: 16px;
|
|
120
|
+
border: none;
|
|
121
|
+
border-radius: 4px;
|
|
122
|
+
background-color: #42b983;
|
|
123
|
+
color: white;
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
transition: background-color 0.3s;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.counter-section button:hover:not(:disabled) {
|
|
129
|
+
background-color: #369970;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.counter-section button:disabled {
|
|
133
|
+
background-color: #ccc;
|
|
134
|
+
cursor: not-allowed;
|
|
135
|
+
}
|
|
136
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createRouter, createWebHistory } from 'vue-router';
|
|
2
|
+
import type { RouteRecordRaw } from 'vue-router';
|
|
3
|
+
|
|
4
|
+
const routes: RouteRecordRaw[] = [
|
|
5
|
+
{
|
|
6
|
+
path: '/',
|
|
7
|
+
name: 'Home',
|
|
8
|
+
component: () => import('@/pages/index.vue'),
|
|
9
|
+
},
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
const router = createRouter({
|
|
13
|
+
history: createWebHistory(),
|
|
14
|
+
routes,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export default router;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
* {
|
|
2
|
+
margin: 0;
|
|
3
|
+
padding: 0;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
body {
|
|
8
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
|
|
9
|
+
'Open Sans', 'Helvetica Neue', sans-serif;
|
|
10
|
+
-webkit-font-smoothing: antialiased;
|
|
11
|
+
-moz-osx-font-smoothing: grayscale;
|
|
12
|
+
background-color: #f9f9f9;
|
|
13
|
+
color: #333;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#app {
|
|
17
|
+
width: 100%;
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
a {
|
|
22
|
+
color: #42b983;
|
|
23
|
+
text-decoration: none;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
a:hover {
|
|
27
|
+
text-decoration: underline;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
button {
|
|
31
|
+
font-family: inherit;
|
|
32
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// API 响应基础类型
|
|
6
|
+
export interface ApiResponse<T = any> {
|
|
7
|
+
code: number;
|
|
8
|
+
message: string;
|
|
9
|
+
data: T;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// 用户信息类型
|
|
13
|
+
export interface UserInfo {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
email?: string;
|
|
17
|
+
avatar?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// 分页参数
|
|
21
|
+
export interface PaginationParams {
|
|
22
|
+
page: number;
|
|
23
|
+
pageSize: number;
|
|
24
|
+
total?: number;
|
|
25
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
"jsx": "preserve",
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true,
|
|
22
|
+
"noUncheckedIndexedAccess": false,
|
|
23
|
+
"noImplicitOverride": true,
|
|
24
|
+
|
|
25
|
+
/* Path alias */
|
|
26
|
+
"baseUrl": ".",
|
|
27
|
+
"paths": {
|
|
28
|
+
"@/*": ["src/*"]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
|
|
32
|
+
"references": [{ "path": "./tsconfig.node.json" }]
|
|
33
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import vue from '@vitejs/plugin-vue';
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
|
|
5
|
+
// https://vite.dev/config/
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
plugins: [vue()],
|
|
8
|
+
resolve: {
|
|
9
|
+
alias: {
|
|
10
|
+
'@': resolve(__dirname, 'src'),
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
server: {
|
|
14
|
+
port: 3000,
|
|
15
|
+
open: true,
|
|
16
|
+
},
|
|
17
|
+
});
|