@lvetechs/create-app 1.0.4 → 1.0.6

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 (58) hide show
  1. package/package.json +1 -1
  2. package/templates/react/.env +3 -3
  3. package/templates/react/.env.development +3 -3
  4. package/templates/react/.env.production +3 -3
  5. package/templates/react/package.json +1 -1
  6. package/templates/react/pnpm-lock.yaml +5 -5
  7. package/templates/react/src/App.tsx +7 -1
  8. package/templates/react/src/api/notification.ts +43 -0
  9. package/templates/react/src/components/NotificationButton/index.tsx +219 -0
  10. package/templates/react/src/components/Toast/index.tsx +150 -0
  11. package/templates/react/src/hooks/useForm.ts +77 -0
  12. package/templates/react/src/layouts/DefaultLayout.tsx +2 -0
  13. package/templates/react/src/layouts/menuConfig.ts +3 -33
  14. package/templates/react/src/router/index.tsx +0 -39
  15. package/templates/react/src/stores/app.ts +141 -3
  16. package/templates/react/src/stores/notification.ts +146 -0
  17. package/templates/react/src/stores/permission.ts +173 -0
  18. package/templates/react/src/stores/user.ts +151 -4
  19. package/templates/react/src/views/home/index.tsx +167 -6
  20. package/templates/react/src/views/system/user/index.tsx +171 -5
  21. package/templates/vue/.env +2 -2
  22. package/templates/vue/.env.development +2 -2
  23. package/templates/vue/.env.production +2 -2
  24. package/templates/vue/pnpm-lock.yaml +3307 -3307
  25. package/templates/vue/src/App.vue +2 -0
  26. package/templates/vue/src/api/notification.ts +43 -0
  27. package/templates/vue/src/auto-imports.d.ts +5 -0
  28. package/templates/vue/src/components/NotificationButton/index.vue +242 -0
  29. package/templates/vue/src/components/Toast/index.vue +126 -0
  30. package/templates/vue/src/components.d.ts +2 -0
  31. package/templates/vue/src/layouts/DefaultLayout.vue +2 -0
  32. package/templates/vue/src/layouts/menuConfig.ts +3 -33
  33. package/templates/vue/src/router/index.ts +3 -88
  34. package/templates/vue/src/stores/app.ts +133 -2
  35. package/templates/vue/src/stores/notification.ts +189 -0
  36. package/templates/vue/src/stores/permission.ts +184 -0
  37. package/templates/vue/src/stores/user.ts +109 -2
  38. package/templates/vue/src/views/home/index.vue +7 -7
  39. package/templates/react/src/views/about/index.tsx +0 -40
  40. package/templates/react/src/views/login/index.tsx +0 -138
  41. package/templates/react/src/views/register/index.tsx +0 -143
  42. package/templates/react/src/views/result/fail.tsx +0 -39
  43. package/templates/react/src/views/result/success.tsx +0 -35
  44. package/templates/react/src/views/screen/index.tsx +0 -120
  45. package/templates/react/src/views/system/log/login.tsx +0 -51
  46. package/templates/react/src/views/system/log/operation.tsx +0 -47
  47. package/templates/react/src/views/system/menu/index.tsx +0 -62
  48. package/templates/react/src/views/system/role/index.tsx +0 -63
  49. package/templates/vue/src/views/about/index.vue +0 -67
  50. package/templates/vue/src/views/login/index.vue +0 -153
  51. package/templates/vue/src/views/register/index.vue +0 -169
  52. package/templates/vue/src/views/result/fail.vue +0 -92
  53. package/templates/vue/src/views/result/success.vue +0 -92
  54. package/templates/vue/src/views/screen/index.vue +0 -150
  55. package/templates/vue/src/views/system/log/login.vue +0 -51
  56. package/templates/vue/src/views/system/log/operation.vue +0 -47
  57. package/templates/vue/src/views/system/menu/index.vue +0 -58
  58. package/templates/vue/src/views/system/role/index.vue +0 -59
@@ -1,62 +0,0 @@
1
- import '@/styles/page-common.scss'
2
-
3
- const menus = [
4
- { id: 1, title: '首页', path: '/home', icon: '🏠', type: '菜单', sort: 1 },
5
- { id: 2, title: '系统管理', path: '/system', icon: '⚙️', type: '目录', sort: 2 },
6
- { id: 3, title: '用户管理', path: '/system/user', icon: '👤', type: '菜单', sort: 1 },
7
- { id: 4, title: '角色管理', path: '/system/role', icon: '🔑', type: '菜单', sort: 2 },
8
- { id: 5, title: '菜单管理', path: '/system/menu', icon: '📋', type: '菜单', sort: 3 }
9
- ]
10
-
11
- export default function SystemMenu() {
12
- return (
13
- <div className="page-container">
14
- <div className="page-header">
15
- <h2>菜单管理</h2>
16
- <button className="btn-primary">+ 新增菜单</button>
17
- </div>
18
- <table className="data-table">
19
- <thead>
20
- <tr>
21
- <th>ID</th>
22
- <th>标题</th>
23
- <th>路径</th>
24
- <th>图标</th>
25
- <th>类型</th>
26
- <th>排序</th>
27
- <th>操作</th>
28
- </tr>
29
- </thead>
30
- <tbody>
31
- {menus.map((menu) => (
32
- <tr key={menu.id}>
33
- <td>{menu.id}</td>
34
- <td>{menu.title}</td>
35
- <td>
36
- <code
37
- style={{
38
- background: 'var(--bg-color-page)',
39
- padding: '2px 8px',
40
- borderRadius: 3,
41
- fontSize: 13,
42
- color: 'var(--primary-color)'
43
- }}
44
- >
45
- {menu.path}
46
- </code>
47
- </td>
48
- <td>{menu.icon}</td>
49
- <td>{menu.type}</td>
50
- <td>{menu.sort}</td>
51
- <td>
52
- <button className="btn-link">编辑</button>
53
- <button className="btn-link danger">删除</button>
54
- </td>
55
- </tr>
56
- ))}
57
- </tbody>
58
- </table>
59
- </div>
60
- )
61
- }
62
-
@@ -1,63 +0,0 @@
1
- import '@/styles/page-common.scss'
2
-
3
- const roles = [
4
- { id: 1, name: 'admin', label: '超级管理员', description: '拥有所有权限', status: '启用' },
5
- { id: 2, name: 'editor', label: '编辑', description: '可编辑内容', status: '启用' },
6
- { id: 3, name: 'viewer', label: '只读', description: '只能查看', status: '启用' }
7
- ]
8
-
9
- export default function SystemRole() {
10
- return (
11
- <div className="page-container">
12
- <div className="page-header">
13
- <h2>角色管理</h2>
14
- <button className="btn-primary">+ 新增角色</button>
15
- </div>
16
- <table className="data-table">
17
- <thead>
18
- <tr>
19
- <th>ID</th>
20
- <th>角色标识</th>
21
- <th>角色名称</th>
22
- <th>描述</th>
23
- <th>状态</th>
24
- <th>操作</th>
25
- </tr>
26
- </thead>
27
- <tbody>
28
- {roles.map((role) => (
29
- <tr key={role.id}>
30
- <td>{role.id}</td>
31
- <td>
32
- <code
33
- style={{
34
- background: 'var(--bg-color-page)',
35
- padding: '2px 8px',
36
- borderRadius: 3,
37
- fontSize: 13,
38
- color: 'var(--primary-color)'
39
- }}
40
- >
41
- {role.name}
42
- </code>
43
- </td>
44
- <td>{role.label}</td>
45
- <td>{role.description}</td>
46
- <td>
47
- <span className={role.status === '启用' ? 'status-active' : 'status-disabled'}>
48
- {role.status}
49
- </span>
50
- </td>
51
- <td>
52
- <button className="btn-link">编辑</button>
53
- <button className="btn-link">权限</button>
54
- <button className="btn-link danger">删除</button>
55
- </td>
56
- </tr>
57
- ))}
58
- </tbody>
59
- </table>
60
- </div>
61
- )
62
- }
63
-
@@ -1,67 +0,0 @@
1
- <script setup lang="ts">
2
- </script>
3
-
4
- <template>
5
- <div class="about-page">
6
- <div class="about-card">
7
- <h1>关于</h1>
8
- <p>这是一个基于 Vue 3 的现代化前端模板项目。</p>
9
- <ul>
10
- <li>Vue 3 Composition API</li>
11
- <li>Vite 5 构建工具</li>
12
- <li>TypeScript 5 类型支持</li>
13
- <li>Vue Router 4 路由管理</li>
14
- <li>Pinia 状态管理 (支持持久化)</li>
15
- <li>Axios 请求封装 (拦截器 + 类型)</li>
16
- <li>TailwindCSS</li>
17
- <li>unplugin-auto-import 自动导入</li>
18
- <li>ESLint + Prettier 代码规范</li>
19
- </ul>
20
- </div>
21
- </div>
22
- </template>
23
-
24
- <style scoped lang="scss">
25
- .about-page {
26
- max-width: 700px;
27
- margin: 0 auto;
28
- }
29
-
30
- .about-card {
31
- background: var(--bg-color-overlay);
32
- border-radius: var(--border-radius-lg);
33
- padding: 32px;
34
- box-shadow: var(--box-shadow-light);
35
-
36
- h1 {
37
- font-size: 24px;
38
- margin-bottom: 12px;
39
- color: var(--text-color);
40
- }
41
-
42
- p {
43
- color: var(--text-color-secondary);
44
- margin-bottom: 16px;
45
- }
46
-
47
- ul {
48
- list-style: none;
49
- padding: 0;
50
-
51
- li {
52
- padding: 8px 0;
53
- border-bottom: 1px solid var(--border-color-light);
54
- color: var(--text-color-regular);
55
-
56
- &::before {
57
- content: '✅ ';
58
- }
59
-
60
- &:last-child {
61
- border-bottom: none;
62
- }
63
- }
64
- }
65
- }
66
- </style>
67
-
@@ -1,153 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref } from 'vue'
3
- import { useRouter } from 'vue-router'
4
- import { useUserStore } from '@/stores/user'
5
-
6
- const router = useRouter()
7
- const userStore = useUserStore()
8
-
9
- const form = ref({
10
- username: '',
11
- password: ''
12
- })
13
- const loading = ref(false)
14
-
15
- async function handleLogin() {
16
- if (!form.value.username || !form.value.password) {
17
- alert('请输入用户名和密码')
18
- return
19
- }
20
-
21
- loading.value = true
22
- try {
23
- // TODO: 调用登录 API
24
- // const res = await loginApi(form.value)
25
- // userStore.setToken(res.data.token)
26
-
27
- // 模拟登录
28
- userStore.setToken('mock-token')
29
- userStore.setUserInfo({
30
- id: 1,
31
- username: form.value.username,
32
- nickname: '管理员',
33
- avatar: '',
34
- roles: ['admin']
35
- })
36
-
37
- router.push('/')
38
- } catch (error) {
39
- console.error('登录失败:', error)
40
- } finally {
41
- loading.value = false
42
- }
43
- }
44
- </script>
45
-
46
- <template>
47
- <div class="login-page">
48
- <div class="login-card">
49
- <h2>用户登录</h2>
50
- <form @submit.prevent="handleLogin">
51
- <div class="form-item">
52
- <label>用户名</label>
53
- <input
54
- v-model="form.username"
55
- type="text"
56
- placeholder="请输入用户名"
57
- autocomplete="username"
58
- />
59
- </div>
60
- <div class="form-item">
61
- <label>密码</label>
62
- <input
63
- v-model="form.password"
64
- type="password"
65
- placeholder="请输入密码"
66
- autocomplete="current-password"
67
- />
68
- </div>
69
- <button type="submit" class="login-btn" :disabled="loading">
70
- {{ loading ? '登录中...' : '登 录' }}
71
- </button>
72
- </form>
73
- </div>
74
- </div>
75
- </template>
76
-
77
- <style scoped lang="scss">
78
- .login-page {
79
- height: 100vh;
80
- display: flex;
81
- align-items: center;
82
- justify-content: center;
83
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
84
- }
85
-
86
- .login-card {
87
- width: 380px;
88
- padding: 40px;
89
- background: #fff;
90
- border-radius: 12px;
91
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
92
-
93
- h2 {
94
- text-align: center;
95
- margin-bottom: 32px;
96
- color: #333;
97
- font-size: 24px;
98
- }
99
- }
100
-
101
- .form-item {
102
- margin-bottom: 20px;
103
-
104
- label {
105
- display: block;
106
- margin-bottom: 6px;
107
- font-size: 14px;
108
- color: #606266;
109
- }
110
-
111
- input {
112
- width: 100%;
113
- padding: 10px 12px;
114
- border: 1px solid #dcdfe6;
115
- border-radius: 6px;
116
- font-size: 14px;
117
- outline: none;
118
- transition: border-color 0.2s;
119
- box-sizing: border-box;
120
-
121
- &:focus {
122
- border-color: #409eff;
123
- }
124
-
125
- &::placeholder {
126
- color: #c0c4cc;
127
- }
128
- }
129
- }
130
-
131
- .login-btn {
132
- width: 100%;
133
- padding: 12px;
134
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
135
- color: #fff;
136
- border: none;
137
- border-radius: 6px;
138
- font-size: 16px;
139
- cursor: pointer;
140
- transition: opacity 0.2s;
141
- margin-top: 8px;
142
-
143
- &:hover {
144
- opacity: 0.9;
145
- }
146
-
147
- &:disabled {
148
- opacity: 0.6;
149
- cursor: not-allowed;
150
- }
151
- }
152
- </style>
153
-
@@ -1,169 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref } from 'vue'
3
- import { useRouter } from 'vue-router'
4
-
5
- const router = useRouter()
6
-
7
- const form = ref({
8
- username: '',
9
- password: '',
10
- confirmPassword: ''
11
- })
12
- const loading = ref(false)
13
-
14
- async function handleRegister() {
15
- if (!form.value.username || !form.value.password) {
16
- alert('请填写完整信息')
17
- return
18
- }
19
- if (form.value.password !== form.value.confirmPassword) {
20
- alert('两次密码输入不一致')
21
- return
22
- }
23
-
24
- loading.value = true
25
- try {
26
- // TODO: 调用注册 API
27
- alert('注册成功!')
28
- router.push('/login')
29
- } catch (error) {
30
- console.error('注册失败:', error)
31
- } finally {
32
- loading.value = false
33
- }
34
- }
35
- </script>
36
-
37
- <template>
38
- <div class="register-page">
39
- <div class="register-card">
40
- <h2>用户注册</h2>
41
- <form @submit.prevent="handleRegister">
42
- <div class="form-item">
43
- <label>用户名</label>
44
- <input
45
- v-model="form.username"
46
- type="text"
47
- placeholder="请输入用户名"
48
- autocomplete="username"
49
- />
50
- </div>
51
- <div class="form-item">
52
- <label>密码</label>
53
- <input
54
- v-model="form.password"
55
- type="password"
56
- placeholder="请输入密码"
57
- autocomplete="new-password"
58
- />
59
- </div>
60
- <div class="form-item">
61
- <label>确认密码</label>
62
- <input
63
- v-model="form.confirmPassword"
64
- type="password"
65
- placeholder="请再次输入密码"
66
- autocomplete="new-password"
67
- />
68
- </div>
69
- <button type="submit" class="register-btn" :disabled="loading">
70
- {{ loading ? '注册中...' : '注 册' }}
71
- </button>
72
- <div class="to-login">
73
- 已有账号?
74
- <router-link to="/login">立即登录</router-link>
75
- </div>
76
- </form>
77
- </div>
78
- </div>
79
- </template>
80
-
81
- <style scoped lang="scss">
82
- .register-page {
83
- height: 100vh;
84
- display: flex;
85
- align-items: center;
86
- justify-content: center;
87
- background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
88
- }
89
-
90
- .register-card {
91
- width: 400px;
92
- padding: 40px;
93
- background: #fff;
94
- border-radius: 12px;
95
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
96
-
97
- h2 {
98
- text-align: center;
99
- margin-bottom: 32px;
100
- color: #333;
101
- font-size: 24px;
102
- }
103
- }
104
-
105
- .form-item {
106
- margin-bottom: 20px;
107
-
108
- label {
109
- display: block;
110
- margin-bottom: 6px;
111
- font-size: 14px;
112
- color: #606266;
113
- }
114
-
115
- input {
116
- width: 100%;
117
- padding: 10px 12px;
118
- border: 1px solid #dcdfe6;
119
- border-radius: 6px;
120
- font-size: 14px;
121
- outline: none;
122
- transition: border-color 0.2s;
123
- box-sizing: border-box;
124
-
125
- &:focus {
126
- border-color: #43e97b;
127
- }
128
-
129
- &::placeholder {
130
- color: #c0c4cc;
131
- }
132
- }
133
- }
134
-
135
- .register-btn {
136
- width: 100%;
137
- padding: 12px;
138
- background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
139
- color: #fff;
140
- border: none;
141
- border-radius: 6px;
142
- font-size: 16px;
143
- cursor: pointer;
144
- transition: opacity 0.2s;
145
- margin-top: 8px;
146
-
147
- &:hover {
148
- opacity: 0.9;
149
- }
150
-
151
- &:disabled {
152
- opacity: 0.6;
153
- cursor: not-allowed;
154
- }
155
- }
156
-
157
- .to-login {
158
- text-align: center;
159
- margin-top: 16px;
160
- font-size: 14px;
161
- color: #909399;
162
-
163
- a {
164
- color: #43e97b;
165
- font-weight: 500;
166
- }
167
- }
168
- </style>
169
-
@@ -1,92 +0,0 @@
1
- <script setup lang="ts">
2
- import { useRouter } from 'vue-router'
3
-
4
- const router = useRouter()
5
- </script>
6
-
7
- <template>
8
- <div class="result-page">
9
- <div class="result-card">
10
- <div class="result-icon fail">❌</div>
11
- <h1>操作失败</h1>
12
- <p>抱歉,您的操作未能完成,请检查后重试。</p>
13
- <div class="result-actions">
14
- <button class="btn-primary" @click="router.back()">返回重试</button>
15
- <button class="btn-outline" @click="router.push('/')">返回首页</button>
16
- </div>
17
- </div>
18
- </div>
19
- </template>
20
-
21
- <style scoped lang="scss">
22
- .result-page {
23
- height: 100vh;
24
- display: flex;
25
- align-items: center;
26
- justify-content: center;
27
- background-color: #f5f7fa;
28
- }
29
-
30
- .result-card {
31
- text-align: center;
32
- padding: 60px 80px;
33
- background: #fff;
34
- border-radius: 12px;
35
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
36
- }
37
-
38
- .result-icon {
39
- font-size: 64px;
40
- margin-bottom: 20px;
41
- }
42
-
43
- h1 {
44
- font-size: 24px;
45
- color: #333;
46
- margin-bottom: 12px;
47
- }
48
-
49
- p {
50
- font-size: 15px;
51
- color: #909399;
52
- margin-bottom: 32px;
53
- }
54
-
55
- .result-actions {
56
- display: flex;
57
- gap: 12px;
58
- justify-content: center;
59
- }
60
-
61
- .btn-primary {
62
- padding: 10px 28px;
63
- background-color: #f56c6c;
64
- color: #fff;
65
- border: none;
66
- border-radius: 6px;
67
- font-size: 15px;
68
- cursor: pointer;
69
- transition: opacity 0.2s;
70
-
71
- &:hover {
72
- opacity: 0.85;
73
- }
74
- }
75
-
76
- .btn-outline {
77
- padding: 10px 28px;
78
- background: #fff;
79
- color: #606266;
80
- border: 1px solid #dcdfe6;
81
- border-radius: 6px;
82
- font-size: 15px;
83
- cursor: pointer;
84
- transition: all 0.2s;
85
-
86
- &:hover {
87
- border-color: #409eff;
88
- color: #409eff;
89
- }
90
- }
91
- </style>
92
-
@@ -1,92 +0,0 @@
1
- <script setup lang="ts">
2
- import { useRouter } from 'vue-router'
3
-
4
- const router = useRouter()
5
- </script>
6
-
7
- <template>
8
- <div class="result-page">
9
- <div class="result-card">
10
- <div class="result-icon success">✅</div>
11
- <h1>操作成功</h1>
12
- <p>您的操作已成功完成,可以返回首页继续操作。</p>
13
- <div class="result-actions">
14
- <button class="btn-primary" @click="router.push('/')">返回首页</button>
15
- <button class="btn-outline" @click="router.back()">返回上一页</button>
16
- </div>
17
- </div>
18
- </div>
19
- </template>
20
-
21
- <style scoped lang="scss">
22
- .result-page {
23
- height: 100vh;
24
- display: flex;
25
- align-items: center;
26
- justify-content: center;
27
- background-color: #f5f7fa;
28
- }
29
-
30
- .result-card {
31
- text-align: center;
32
- padding: 60px 80px;
33
- background: #fff;
34
- border-radius: 12px;
35
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
36
- }
37
-
38
- .result-icon {
39
- font-size: 64px;
40
- margin-bottom: 20px;
41
- }
42
-
43
- h1 {
44
- font-size: 24px;
45
- color: #333;
46
- margin-bottom: 12px;
47
- }
48
-
49
- p {
50
- font-size: 15px;
51
- color: #909399;
52
- margin-bottom: 32px;
53
- }
54
-
55
- .result-actions {
56
- display: flex;
57
- gap: 12px;
58
- justify-content: center;
59
- }
60
-
61
- .btn-primary {
62
- padding: 10px 28px;
63
- background-color: #409eff;
64
- color: #fff;
65
- border: none;
66
- border-radius: 6px;
67
- font-size: 15px;
68
- cursor: pointer;
69
- transition: opacity 0.2s;
70
-
71
- &:hover {
72
- opacity: 0.85;
73
- }
74
- }
75
-
76
- .btn-outline {
77
- padding: 10px 28px;
78
- background: #fff;
79
- color: #606266;
80
- border: 1px solid #dcdfe6;
81
- border-radius: 6px;
82
- font-size: 15px;
83
- cursor: pointer;
84
- transition: all 0.2s;
85
-
86
- &:hover {
87
- border-color: #409eff;
88
- color: #409eff;
89
- }
90
- }
91
- </style>
92
-