@lvetechs/create-app 1.0.4 → 1.0.5

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 (47) 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/hooks/useForm.ts +77 -0
  8. package/templates/react/src/layouts/menuConfig.ts +3 -33
  9. package/templates/react/src/router/index.tsx +0 -39
  10. package/templates/react/src/stores/app.ts +141 -3
  11. package/templates/react/src/stores/notification.ts +128 -0
  12. package/templates/react/src/stores/permission.ts +183 -0
  13. package/templates/react/src/stores/user.ts +151 -4
  14. package/templates/react/src/views/home/index.tsx +167 -6
  15. package/templates/react/src/views/system/user/index.tsx +171 -5
  16. package/templates/vue/.env +2 -2
  17. package/templates/vue/.env.development +2 -2
  18. package/templates/vue/.env.production +2 -2
  19. package/templates/vue/pnpm-lock.yaml +3307 -3307
  20. package/templates/vue/src/auto-imports.d.ts +5 -0
  21. package/templates/vue/src/layouts/menuConfig.ts +3 -33
  22. package/templates/vue/src/router/index.ts +3 -88
  23. package/templates/vue/src/stores/app.ts +133 -2
  24. package/templates/vue/src/stores/notification.ts +172 -0
  25. package/templates/vue/src/stores/permission.ts +184 -0
  26. package/templates/vue/src/stores/user.ts +109 -2
  27. package/templates/vue/src/views/home/index.vue +7 -7
  28. package/templates/react/src/views/about/index.tsx +0 -40
  29. package/templates/react/src/views/login/index.tsx +0 -138
  30. package/templates/react/src/views/register/index.tsx +0 -143
  31. package/templates/react/src/views/result/fail.tsx +0 -39
  32. package/templates/react/src/views/result/success.tsx +0 -35
  33. package/templates/react/src/views/screen/index.tsx +0 -120
  34. package/templates/react/src/views/system/log/login.tsx +0 -51
  35. package/templates/react/src/views/system/log/operation.tsx +0 -47
  36. package/templates/react/src/views/system/menu/index.tsx +0 -62
  37. package/templates/react/src/views/system/role/index.tsx +0 -63
  38. package/templates/vue/src/views/about/index.vue +0 -67
  39. package/templates/vue/src/views/login/index.vue +0 -153
  40. package/templates/vue/src/views/register/index.vue +0 -169
  41. package/templates/vue/src/views/result/fail.vue +0 -92
  42. package/templates/vue/src/views/result/success.vue +0 -92
  43. package/templates/vue/src/views/screen/index.vue +0 -150
  44. package/templates/vue/src/views/system/log/login.vue +0 -51
  45. package/templates/vue/src/views/system/log/operation.vue +0 -47
  46. package/templates/vue/src/views/system/menu/index.vue +0 -58
  47. package/templates/vue/src/views/system/role/index.vue +0 -59
@@ -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
-
@@ -1,150 +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="screen-page">
9
- <!-- 顶部标题栏 -->
10
- <header class="screen-header">
11
- <button class="back-btn" @click="router.push('/')">← 返回</button>
12
- <h1>数据大屏</h1>
13
- <span class="screen-time">{{ new Date().toLocaleString() }}</span>
14
- </header>
15
-
16
- <!-- 数据面板 -->
17
- <div class="screen-body">
18
- <div class="panel">
19
- <h3>总用户数</h3>
20
- <div class="panel-value">12,580</div>
21
- <p class="panel-desc">较昨日 +128</p>
22
- </div>
23
- <div class="panel">
24
- <h3>今日活跃</h3>
25
- <div class="panel-value">3,426</div>
26
- <p class="panel-desc">活跃率 27.2%</p>
27
- </div>
28
- <div class="panel">
29
- <h3>今日订单</h3>
30
- <div class="panel-value">856</div>
31
- <p class="panel-desc">较昨日 +52</p>
32
- </div>
33
- <div class="panel">
34
- <h3>今日营收</h3>
35
- <div class="panel-value">¥98,320</div>
36
- <p class="panel-desc">较昨日 +12.3%</p>
37
- </div>
38
- <div class="panel wide">
39
- <h3>📊 数据图表区域</h3>
40
- <div class="chart-placeholder">
41
- <p>此处可集成 ECharts / Chart.js 等图表库</p>
42
- </div>
43
- </div>
44
- <div class="panel wide">
45
- <h3>🗺️ 地图区域</h3>
46
- <div class="chart-placeholder">
47
- <p>此处可集成地图或其他可视化组件</p>
48
- </div>
49
- </div>
50
- </div>
51
- </div>
52
- </template>
53
-
54
- <style scoped lang="scss">
55
- .screen-page {
56
- height: 100vh;
57
- background: #0d1b2a;
58
- color: #e0e6ed;
59
- display: flex;
60
- flex-direction: column;
61
- overflow: hidden;
62
- }
63
-
64
- .screen-header {
65
- display: flex;
66
- align-items: center;
67
- justify-content: space-between;
68
- padding: 12px 24px;
69
- background: rgba(255, 255, 255, 0.05);
70
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
71
-
72
- h1 {
73
- font-size: 22px;
74
- background: linear-gradient(90deg, #00d2ff, #928dff);
75
- -webkit-background-clip: text;
76
- -webkit-text-fill-color: transparent;
77
- }
78
-
79
- .screen-time {
80
- font-size: 13px;
81
- color: #8892a4;
82
- }
83
- }
84
-
85
- .back-btn {
86
- background: rgba(255, 255, 255, 0.1);
87
- border: 1px solid rgba(255, 255, 255, 0.2);
88
- color: #e0e6ed;
89
- padding: 6px 16px;
90
- border-radius: 4px;
91
- cursor: pointer;
92
- font-size: 13px;
93
-
94
- &:hover {
95
- background: rgba(255, 255, 255, 0.2);
96
- }
97
- }
98
-
99
- .screen-body {
100
- flex: 1;
101
- display: grid;
102
- grid-template-columns: repeat(4, 1fr);
103
- gap: 16px;
104
- padding: 20px 24px;
105
- overflow-y: auto;
106
- }
107
-
108
- .panel {
109
- background: rgba(255, 255, 255, 0.05);
110
- border: 1px solid rgba(255, 255, 255, 0.08);
111
- border-radius: 8px;
112
- padding: 20px;
113
-
114
- h3 {
115
- font-size: 14px;
116
- color: #8892a4;
117
- margin-bottom: 12px;
118
- }
119
-
120
- &.wide {
121
- grid-column: span 2;
122
- }
123
- }
124
-
125
- .panel-value {
126
- font-size: 32px;
127
- font-weight: 700;
128
- background: linear-gradient(90deg, #00d2ff, #928dff);
129
- -webkit-background-clip: text;
130
- -webkit-text-fill-color: transparent;
131
- margin-bottom: 8px;
132
- }
133
-
134
- .panel-desc {
135
- font-size: 13px;
136
- color: #67c23a;
137
- }
138
-
139
- .chart-placeholder {
140
- height: 200px;
141
- display: flex;
142
- align-items: center;
143
- justify-content: center;
144
- border: 1px dashed rgba(255, 255, 255, 0.15);
145
- border-radius: 6px;
146
- color: #8892a4;
147
- font-size: 14px;
148
- }
149
- </style>
150
-
@@ -1,51 +0,0 @@
1
- <script setup lang="ts">
2
- const logs = [
3
- { id: 1, user: 'admin', ip: '192.168.1.1', location: '本地', browser: 'Chrome 122', os: 'Windows 10', time: '2024-03-20 09:00:00', status: '成功' },
4
- { id: 2, user: 'editor', ip: '192.168.1.2', location: '本地', browser: 'Firefox 123', os: 'macOS', time: '2024-03-20 09:30:00', status: '成功' },
5
- { id: 3, user: 'hacker', ip: '10.0.0.1', location: '未知', browser: 'Unknown', os: 'Linux', time: '2024-03-20 12:00:00', status: '失败' }
6
- ]
7
- </script>
8
-
9
- <template>
10
- <div class="page-container">
11
- <div class="page-header">
12
- <h2>登录日志</h2>
13
- <button class="btn-primary">导出日志</button>
14
- </div>
15
- <table class="data-table">
16
- <thead>
17
- <tr>
18
- <th>ID</th>
19
- <th>用户名</th>
20
- <th>IP 地址</th>
21
- <th>登录地点</th>
22
- <th>浏览器</th>
23
- <th>操作系统</th>
24
- <th>登录时间</th>
25
- <th>状态</th>
26
- </tr>
27
- </thead>
28
- <tbody>
29
- <tr v-for="log in logs" :key="log.id">
30
- <td>{{ log.id }}</td>
31
- <td>{{ log.user }}</td>
32
- <td>{{ log.ip }}</td>
33
- <td>{{ log.location }}</td>
34
- <td>{{ log.browser }}</td>
35
- <td>{{ log.os }}</td>
36
- <td>{{ log.time }}</td>
37
- <td>
38
- <span :class="log.status === '成功' ? 'status-active' : 'status-disabled'">
39
- {{ log.status }}
40
- </span>
41
- </td>
42
- </tr>
43
- </tbody>
44
- </table>
45
- </div>
46
- </template>
47
-
48
- <style scoped lang="scss">
49
- @import '@/styles/page-common.scss';
50
- </style>
51
-
@@ -1,47 +0,0 @@
1
- <script setup lang="ts">
2
- const logs = [
3
- { id: 1, user: 'admin', action: '新增用户', ip: '192.168.1.1', time: '2024-03-20 10:30:00', status: '成功' },
4
- { id: 2, user: 'admin', action: '修改角色', ip: '192.168.1.1', time: '2024-03-20 11:15:00', status: '成功' },
5
- { id: 3, user: 'editor', action: '删除文章', ip: '192.168.1.2', time: '2024-03-20 14:22:00', status: '失败' }
6
- ]
7
- </script>
8
-
9
- <template>
10
- <div class="page-container">
11
- <div class="page-header">
12
- <h2>操作日志</h2>
13
- <button class="btn-primary">导出日志</button>
14
- </div>
15
- <table class="data-table">
16
- <thead>
17
- <tr>
18
- <th>ID</th>
19
- <th>操作人</th>
20
- <th>操作内容</th>
21
- <th>IP 地址</th>
22
- <th>操作时间</th>
23
- <th>状态</th>
24
- </tr>
25
- </thead>
26
- <tbody>
27
- <tr v-for="log in logs" :key="log.id">
28
- <td>{{ log.id }}</td>
29
- <td>{{ log.user }}</td>
30
- <td>{{ log.action }}</td>
31
- <td>{{ log.ip }}</td>
32
- <td>{{ log.time }}</td>
33
- <td>
34
- <span :class="log.status === '成功' ? 'status-active' : 'status-disabled'">
35
- {{ log.status }}
36
- </span>
37
- </td>
38
- </tr>
39
- </tbody>
40
- </table>
41
- </div>
42
- </template>
43
-
44
- <style scoped lang="scss">
45
- @import '@/styles/page-common.scss';
46
- </style>
47
-
@@ -1,58 +0,0 @@
1
- <script setup lang="ts">
2
- const menus = [
3
- { id: 1, title: '首页', path: '/home', icon: '🏠', type: '菜单', sort: 1 },
4
- { id: 2, title: '系统管理', path: '/system', icon: '⚙️', type: '目录', sort: 2 },
5
- { id: 3, title: '用户管理', path: '/system/user', icon: '👤', type: '菜单', sort: 1, parentId: 2 },
6
- { id: 4, title: '角色管理', path: '/system/role', icon: '🔑', type: '菜单', sort: 2, parentId: 2 },
7
- { id: 5, title: '菜单管理', path: '/system/menu', icon: '📋', type: '菜单', sort: 3, parentId: 2 }
8
- ]
9
- </script>
10
-
11
- <template>
12
- <div class="page-container">
13
- <div class="page-header">
14
- <h2>菜单管理</h2>
15
- <button class="btn-primary">+ 新增菜单</button>
16
- </div>
17
- <table class="data-table">
18
- <thead>
19
- <tr>
20
- <th>ID</th>
21
- <th>标题</th>
22
- <th>路径</th>
23
- <th>图标</th>
24
- <th>类型</th>
25
- <th>排序</th>
26
- <th>操作</th>
27
- </tr>
28
- </thead>
29
- <tbody>
30
- <tr v-for="menu in menus" :key="menu.id">
31
- <td>{{ menu.id }}</td>
32
- <td>{{ menu.title }}</td>
33
- <td><code>{{ menu.path }}</code></td>
34
- <td>{{ menu.icon }}</td>
35
- <td>{{ menu.type }}</td>
36
- <td>{{ menu.sort }}</td>
37
- <td>
38
- <button class="btn-link">编辑</button>
39
- <button class="btn-link danger">删除</button>
40
- </td>
41
- </tr>
42
- </tbody>
43
- </table>
44
- </div>
45
- </template>
46
-
47
- <style scoped lang="scss">
48
- @import '@/styles/page-common.scss';
49
-
50
- code {
51
- background: var(--bg-color-page);
52
- padding: 2px 8px;
53
- border-radius: 3px;
54
- font-size: 13px;
55
- color: var(--primary-color);
56
- }
57
- </style>
58
-