@befly-addon/admin 1.0.37 → 1.0.38

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 (57) hide show
  1. package/apis/admin/del.ts +1 -5
  2. package/apis/admin/ins.ts +2 -6
  3. package/apis/admin/list.ts +5 -0
  4. package/apis/admin/roleDetail.ts +1 -5
  5. package/apis/admin/roleSave.ts +1 -5
  6. package/apis/admin/upd.ts +1 -6
  7. package/apis/api/all.ts +1 -6
  8. package/apis/auth/login.ts +1 -5
  9. package/apis/auth/logout.ts +1 -5
  10. package/apis/auth/register.ts +1 -5
  11. package/apis/auth/sendSmsCode.ts +1 -5
  12. package/apis/dashboard/changelog.ts +1 -5
  13. package/apis/dashboard/configStatus.ts +1 -5
  14. package/apis/dashboard/environmentInfo.ts +1 -5
  15. package/apis/dashboard/performanceMetrics.ts +1 -5
  16. package/apis/dashboard/permissionStats.ts +1 -5
  17. package/apis/dashboard/serviceStatus.ts +1 -5
  18. package/apis/dashboard/systemInfo.ts +1 -5
  19. package/apis/dashboard/systemOverview.ts +1 -5
  20. package/apis/dashboard/systemResources.ts +1 -5
  21. package/apis/dict/all.ts +0 -3
  22. package/apis/menu/del.ts +1 -5
  23. package/apis/role/all.ts +18 -0
  24. package/apis/role/apiDetail.ts +1 -5
  25. package/apis/role/apiSave.ts +1 -5
  26. package/apis/role/del.ts +1 -5
  27. package/apis/role/detail.ts +1 -5
  28. package/apis/role/ins.ts +0 -3
  29. package/apis/role/list.ts +5 -0
  30. package/apis/role/menuDetail.ts +1 -5
  31. package/apis/role/menuSave.ts +1 -5
  32. package/apis/role/save.ts +1 -5
  33. package/package.json +5 -3
  34. package/styles/variables.scss +87 -0
  35. package/tables/admin.json +2 -8
  36. package/views/403/index.vue +20 -30
  37. package/views/admin/components/edit.vue +73 -48
  38. package/views/admin/index.vue +128 -48
  39. package/views/dict/index.vue +0 -2
  40. package/views/index/components/addonList.vue +20 -14
  41. package/views/index/components/environmentInfo.vue +6 -6
  42. package/views/index/components/operationLogs.vue +9 -9
  43. package/views/index/components/performanceMetrics.vue +22 -32
  44. package/views/index/components/serviceStatus.vue +14 -14
  45. package/views/index/components/systemNotifications.vue +21 -21
  46. package/views/index/components/systemOverview.vue +24 -24
  47. package/views/index/components/systemResources.vue +4 -4
  48. package/views/index/components/userInfo.vue +7 -7
  49. package/views/index/index.vue +0 -2
  50. package/views/login/components/emailLoginForm.vue +46 -46
  51. package/views/login/index_1.vue +158 -121
  52. package/views/role/components/api.vue +11 -9
  53. package/views/role/components/edit.vue +13 -2
  54. package/views/role/index.vue +0 -2
  55. package/utils/scanBeflyAddonViews.js +0 -43
  56. package/views/admin/components/role.vue +0 -138
  57. /package/apis/admin/{info.ts → detail.ts} +0 -0
@@ -1,189 +1,226 @@
1
1
  <template>
2
- <div class="auth-container" :class="{ 'sign-up-mode': $Data.isSignUp }">
3
- <!-- 左侧欢迎区域 -->
4
- <div class="left-panel">
5
- <WelcomePanel :is-sign-up="$Data.isSignUp" @toggle="$Method.toggleMode" />
2
+ <div class="login-container">
3
+ <!-- 左侧装饰区域 -->
4
+ <div class="left-section">
5
+ <div class="bg-decoration">
6
+ <div class="circle circle-1"></div>
7
+ <div class="circle circle-2"></div>
8
+ <div class="circle circle-3"></div>
9
+ </div>
10
+ <div class="welcome-content">
11
+ <h1 class="brand-title">Befly</h1>
12
+ <p class="brand-subtitle">轻量级业务快速开发框架</p>
13
+ </div>
6
14
  </div>
7
15
 
8
- <!-- 右侧表单区域 -->
9
- <div class="right-panel">
10
- <!-- 登录表单 -->
11
- <div class="form-container sign-in-form" :class="{ active: !$Data.isSignUp }">
12
- <h2 class="form-title">登录到 Befly</h2>
16
+ <!-- 右侧登录区域 -->
17
+ <div class="right-section">
18
+ <div class="login-box">
19
+ <div class="login-header">
20
+ <h2 class="login-title">欢迎回来</h2>
21
+ <p class="login-subtitle">请登录您的账户</p>
22
+ </div>
13
23
 
14
- <!-- 邮箱登录 -->
15
24
  <EmailLoginForm />
16
- </div>
17
-
18
- <!-- 注册表单 -->
19
- <div class="form-container sign-up-form" :class="{ active: $Data.isSignUp }">
20
- <h2 class="form-title">注册账号</h2>
21
25
 
22
- <RegisterForm @success="$Method.handleRegisterSuccess" />
26
+ <div class="login-footer">
27
+ <p class="copyright">© 2024 Befly. All rights reserved.</p>
28
+ </div>
23
29
  </div>
24
30
  </div>
25
31
  </div>
26
32
  </template>
27
33
 
28
34
  <script setup>
29
- import WelcomePanel from './components/welcomePanel.vue';
30
35
  import EmailLoginForm from './components/emailLoginForm.vue';
31
- import RegisterForm from './components/registerForm.vue';
32
-
33
- // 数据定义
34
- const $Data = $ref({
35
- isSignUp: false
36
- });
37
-
38
- // 方法定义
39
- const $Method = {
40
- // 切换登录/注册模式
41
- toggleMode() {
42
- $Data.isSignUp = !$Data.isSignUp;
43
- },
44
-
45
- // 注册成功后切换到登录模式
46
- handleRegisterSuccess() {
47
- $Data.isSignUp = false;
48
- }
49
- };
50
36
  </script>
51
37
 
52
38
  <style scoped lang="scss">
53
- .auth-container {
39
+ .login-container {
54
40
  display: flex;
55
41
  width: 100%;
56
42
  min-height: 100vh;
57
- overflow: hidden;
58
- position: relative;
59
- background: #fff;
43
+ background: var(--login-bg);
60
44
  }
61
45
 
62
- // 青色滑动背景块
63
- .left-panel {
64
- position: absolute;
65
- top: 0;
66
- left: 0;
67
- width: 50%;
68
- height: 100%;
46
+ // 左侧装饰区域
47
+ .left-section {
48
+ flex: 1;
49
+ position: relative;
69
50
  display: flex;
70
51
  align-items: center;
71
52
  justify-content: center;
72
- background: linear-gradient(135deg, #48b19f 0%, #3a9d8f 100%);
73
- color: #fff;
74
- z-index: 5;
75
- transition: transform 0.5s ease-in-out;
53
+ background: linear-gradient(135deg, var(--login-left-gradient-start) 0%, var(--login-left-gradient-end) 100%);
54
+ overflow: hidden;
76
55
  }
77
56
 
78
- // 表单区域容器(全屏背景)
79
- .right-panel {
57
+ .bg-decoration {
80
58
  position: absolute;
81
59
  width: 100%;
82
60
  height: 100%;
83
- top: 0;
84
- left: 0;
85
- z-index: 1;
61
+ overflow: hidden;
62
+
63
+ .circle {
64
+ position: absolute;
65
+ border-radius: 50%;
66
+ background: var(--login-circle-bg);
67
+ animation: float 20s infinite ease-in-out;
68
+
69
+ &.circle-1 {
70
+ width: 400px;
71
+ height: 400px;
72
+ top: -100px;
73
+ left: -100px;
74
+ animation-delay: 0s;
75
+ }
76
+
77
+ &.circle-2 {
78
+ width: 300px;
79
+ height: 300px;
80
+ bottom: -50px;
81
+ right: -50px;
82
+ animation-delay: 7s;
83
+ }
84
+
85
+ &.circle-3 {
86
+ width: 200px;
87
+ height: 200px;
88
+ top: 50%;
89
+ right: 10%;
90
+ animation-delay: 14s;
91
+ }
92
+ }
86
93
  }
87
94
 
88
- // 注册模式下青色块移动到右侧
89
- .auth-container.sign-up-mode {
90
- .left-panel {
91
- transform: translateX(100%);
95
+ @keyframes float {
96
+ 0%,
97
+ 100% {
98
+ transform: translateY(0) scale(1);
99
+ }
100
+ 50% {
101
+ transform: translateY(-20px) scale(1.05);
92
102
  }
93
103
  }
94
104
 
95
- // 表单容器(跟随颜色区域滑动)
96
- .form-container {
97
- position: absolute;
98
- width: 50%;
99
- height: 100%;
100
- top: 0;
105
+ .welcome-content {
106
+ position: relative;
107
+ z-index: 1;
108
+ color: #fff;
109
+ text-align: center;
110
+ padding: 2rem;
111
+ }
112
+
113
+ .brand-title {
114
+ font-size: 4rem;
115
+ font-weight: 700;
116
+ margin-bottom: 1rem;
117
+ letter-spacing: 2px;
118
+ color: var(--login-brand-title);
119
+ }
120
+
121
+ .brand-subtitle {
122
+ font-size: 1.25rem;
123
+ margin-bottom: 3rem;
124
+ color: var(--login-brand-subtitle);
125
+ }
126
+
127
+ // 右侧登录区域
128
+ .right-section {
129
+ flex: 1;
101
130
  display: flex;
102
- flex-direction: column;
103
131
  align-items: center;
104
132
  justify-content: center;
105
- padding: 3rem 2rem;
106
- opacity: 0;
107
- pointer-events: none;
108
- transition: all 0.5s ease-in-out;
109
-
110
- &.active {
111
- opacity: 1;
112
- pointer-events: all;
113
- }
133
+ padding: 2rem;
114
134
  }
115
135
 
116
- // 登录模式:登录表单在右侧
117
- .auth-container:not(.sign-up-mode) {
118
- .sign-in-form {
119
- right: 0;
120
- }
136
+ .login-box {
137
+ width: 100%;
138
+ max-width: 440px;
139
+ background: var(--login-card-bg);
140
+ border: 1px solid var(--login-card-border);
141
+ border-radius: 16px;
142
+ box-shadow: 0 10px 40px var(--login-card-shadow);
143
+ padding: 3rem 2.5rem;
144
+ }
121
145
 
122
- .sign-up-form {
123
- left: 0;
124
- }
146
+ .login-header {
147
+ text-align: center;
148
+ margin-bottom: 2.5rem;
125
149
  }
126
150
 
127
- // 注册模式:注册表单在左侧,登录表单在右侧
128
- .auth-container.sign-up-mode {
129
- .sign-in-form {
130
- right: -50%;
131
- }
151
+ .login-title {
152
+ font-size: 2rem;
153
+ font-weight: 600;
154
+ color: var(--login-title);
155
+ margin-bottom: 0.5rem;
156
+ }
132
157
 
133
- .sign-up-form {
134
- left: 0;
135
- }
158
+ .login-subtitle {
159
+ font-size: 1rem;
160
+ color: var(--login-subtitle);
136
161
  }
137
162
 
138
- .form-title {
139
- font-size: 1.8rem;
140
- color: #333;
141
- margin-bottom: 1.5rem;
142
- font-weight: 600;
163
+ .login-footer {
164
+ margin-top: 2rem;
143
165
  text-align: center;
144
- width: 100%;
166
+ }
167
+
168
+ .copyright {
169
+ font-size: 0.875rem;
170
+ color: var(--login-subtitle);
145
171
  }
146
172
 
147
173
  // 响应式设计
148
- @media (max-width: 968px) {
149
- .auth-container {
174
+ @media (max-width: 1024px) {
175
+ .login-container {
150
176
  flex-direction: column;
151
177
  }
152
178
 
153
- .left-panel,
154
- .right-panel {
179
+ .left-section {
180
+ min-height: 300px;
155
181
  flex: none;
156
- width: 100%;
157
182
  }
158
183
 
159
- .left-panel {
160
- order: 1 !important;
161
- position: relative;
184
+ .brand-title {
185
+ font-size: 3rem;
186
+ }
187
+
188
+ .right-section {
189
+ flex: 1;
190
+ }
191
+ }
192
+
193
+ @media (max-width: 768px) {
194
+ .left-section {
162
195
  min-height: 200px;
163
196
  }
164
197
 
165
- .right-panel {
166
- order: 2 !important;
167
- min-height: 500px;
198
+ .brand-title {
199
+ font-size: 2.5rem;
168
200
  }
169
201
 
170
- .form-container {
171
- width: 100%;
172
- padding: 2rem 1rem;
173
- position: static;
202
+ .brand-subtitle {
203
+ font-size: 1rem;
204
+ margin-bottom: 2rem;
174
205
  }
175
206
 
176
- .auth-container.sign-up-mode {
177
- .left-panel {
178
- transform: none;
179
- }
207
+ .login-box {
208
+ padding: 2rem 1.5rem;
209
+ }
210
+
211
+ .login-title {
212
+ font-size: 1.75rem;
180
213
  }
181
214
  }
182
215
 
183
- @media (max-width: 576px) {
184
- .form-title {
185
- font-size: 1.5rem;
186
- margin-bottom: 1.5rem;
216
+ @media (max-width: 480px) {
217
+ .right-section {
218
+ padding: 1rem;
219
+ }
220
+
221
+ .login-box {
222
+ padding: 1.5rem 1rem;
223
+ border-radius: 12px;
187
224
  }
188
225
  }
189
226
  </style>
@@ -214,8 +214,8 @@ $Method.initData();
214
214
 
215
215
  .api-group {
216
216
  margin-bottom: 16px;
217
- border: 1px solid $border-color;
218
- border-radius: $border-radius-small;
217
+ border: 1px solid var(--border-color);
218
+ border-radius: var(--border-radius-small);
219
219
  overflow: hidden;
220
220
 
221
221
  &:last-child {
@@ -224,10 +224,10 @@ $Method.initData();
224
224
 
225
225
  .group-header {
226
226
  padding: 12px 16px;
227
- background-color: $bg-color-hover;
227
+ background-color: var(--bg-color-hover);
228
228
  font-weight: 500;
229
- font-size: $font-size-sm;
230
- color: $text-primary;
229
+ font-size: var(--font-size-sm);
230
+ color: var(--text-primary);
231
231
  display: flex;
232
232
  align-items: center;
233
233
  gap: 8px;
@@ -237,15 +237,17 @@ $Method.initData();
237
237
  width: 8px;
238
238
  height: 8px;
239
239
  border-radius: 50%;
240
- background-color: $primary-color;
240
+ background-color: var(--primary-color);
241
241
  opacity: 0.3;
242
242
  flex-shrink: 0;
243
243
  }
244
244
  }
245
245
 
246
- .api-checkbox-list {
247
- padding: 16px;
248
- background-color: $bg-color-container;
246
+ .api-item {
247
+ padding: 8px 16px;
248
+ cursor: pointer;
249
+ transition: background-color 0.2s;
250
+ background-color: var(--bg-color-container);
249
251
 
250
252
  :deep(.t-checkbox-group) {
251
253
  display: flex;
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <TDialog v-model:visible="$Data.visible" :title="$Prop.actionType === 'upd' ? '更新角色' : '添加角色'" width="600px" :append-to-body="true" :show-footer="true" :esc-closable="false" top="10vh" @close="$Method.onClose">
2
+ <TDialog v-model:visible="$Data.visible" :header="$Prop.actionType === 'upd' ? '更新角色' : '添加角色'" width="600px" :append-to-body="true" :show-footer="true" :esc-closable="false" top="10vh" @close="$Method.onClose">
3
3
  <div class="comp-role-edit">
4
4
  <TForm :model="$Data.formData" label-width="120px" label-position="left" :rules="$Data2.formRules" :ref="(el) => ($From.form = el)">
5
5
  <TFormItem label="角色名称" prop="name">
@@ -30,7 +30,18 @@
30
30
  </template>
31
31
 
32
32
  <script setup>
33
- import { Dialog as TDialog, Form as TForm, FormItem as TFormItem, Input as TInput, InputNumber as TInputNumber, RadioGroup as TRadioGroup, Radio as TRadio, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
33
+ import {
34
+ //
35
+ Dialog as TDialog,
36
+ Form as TForm,
37
+ FormItem as TFormItem,
38
+ Input as TInput,
39
+ InputNumber as TInputNumber,
40
+ RadioGroup as TRadioGroup,
41
+ Radio as TRadio,
42
+ Button as TButton,
43
+ MessagePlugin
44
+ } from 'tdesign-vue-next';
34
45
  import { $Http } from '@/plugins/http';
35
46
 
36
47
  const $Prop = defineProps({
@@ -6,7 +6,6 @@
6
6
  <template #icon>
7
7
  <ILucidePlus />
8
8
  </template>
9
- 添加角色
10
9
  </TButton>
11
10
  </div>
12
11
  <div class="right">
@@ -14,7 +13,6 @@
14
13
  <template #icon>
15
14
  <ILucideRotateCw />
16
15
  </template>
17
- 刷新
18
16
  </TButton>
19
17
  </div>
20
18
  </div>
@@ -1,43 +0,0 @@
1
- import { readdirSync, existsSync } from 'node:fs';
2
- import { join } from 'node:path';
3
-
4
- /**
5
- * 扫描所有 @befly-addon 包的 views 目录
6
- * 用于 unplugin-vue-router 的 routesFolder 配置
7
- * 注意:此函数只能在 vite.config.ts 中使用(Node.js 环境),不能在浏览器中使用
8
- * @returns 路由文件夹配置数组
9
- */
10
- export function scanBeflyAddonViews() {
11
- // 使用绝对路径:基于项目根目录(process.cwd())
12
- const projectRoot = process.cwd();
13
- const addonBasePath = join(projectRoot, 'node_modules', '@befly-addon');
14
- const routesFolders = [];
15
-
16
- if (!existsSync(addonBasePath)) {
17
- return routesFolders;
18
- }
19
-
20
- try {
21
- const addonDirs = readdirSync(addonBasePath);
22
-
23
- for (const addonName of addonDirs) {
24
- const addonPath = join(addonBasePath, addonName);
25
-
26
- // 检查是否为目录(包括符号链接)
27
- if (!existsSync(addonPath)) continue;
28
-
29
- const viewsPath = join(addonPath, 'views');
30
-
31
- if (existsSync(viewsPath)) {
32
- routesFolders.push({
33
- src: viewsPath,
34
- path: `addon/${addonName}/`
35
- });
36
- }
37
- }
38
- } catch (error) {
39
- console.error('扫描 @befly-addon 目录失败:', error);
40
- }
41
-
42
- return routesFolders;
43
- }
@@ -1,138 +0,0 @@
1
- <template>
2
- <TDialog v-model:visible="$Data.visible" title="分配角色" width="600px" :append-to-body="true" :show-footer="true" :esc-closable="false" top="20vh" @close="$Method.onClose">
3
- <div class="role-dialog">
4
- <div class="user-info">
5
- <TTag type="info">{{ $Prop.rowData.username }}</TTag>
6
- <span class="user-email">{{ $Prop.rowData.email }}</span>
7
- </div>
8
- <TDivider />
9
- <TSelect v-model="$Data.checkedRoleCode" :options="$Data.roleOptions" placeholder="请选择角色" />
10
- </div>
11
- <template #footer>
12
- <TButton @click="$Method.onClose">取消</TButton>
13
- <TButton theme="primary" @click="$Method.onSubmit">确定</TButton>
14
- </template>
15
- </TDialog>
16
- </template>
17
-
18
- <script setup>
19
- import { Dialog as TDialog, Tag as TTag, Divider as TDivider, Select as TSelect, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
20
- import { $Http } from '@/plugins/http';
21
-
22
- const $Prop = defineProps({
23
- modelValue: {
24
- type: Boolean,
25
- default: false
26
- },
27
- rowData: {
28
- type: Object,
29
- default: {}
30
- }
31
- });
32
-
33
- const $Emit = defineEmits(['update:modelValue', 'success']);
34
-
35
- const $Data = $ref({
36
- visible: false,
37
- roleOptions: [],
38
- checkedRoleCode: ''
39
- });
40
-
41
- // 方法集合
42
- const $Method = {
43
- async initData() {
44
- $Method.onShow();
45
- await Promise.all([$Method.apiRoleList(), $Method.apiAdminRoleDetail()]);
46
- },
47
-
48
- onShow() {
49
- setTimeout(() => {
50
- $Data.visible = $Prop.modelValue;
51
- }, 100);
52
- },
53
-
54
- onClose() {
55
- $Data.visible = false;
56
- setTimeout(() => {
57
- $Emit('update:modelValue', false);
58
- }, 300);
59
- },
60
-
61
- // 加载角色列表
62
- async apiRoleList() {
63
- try {
64
- const res = await $Http('/addon/admin/role/list', {
65
- page: 1,
66
- limit: 1000
67
- });
68
- const roleList = res.data.lists || [];
69
- $Data.roleOptions = roleList
70
- .filter((role) => role.state === 1)
71
- .map((role) => ({
72
- label: role.name,
73
- value: role.code
74
- }));
75
- } catch (error) {
76
- console.error('加载角色列表失败:', error);
77
- MessagePlugin.info({ message: '加载角色列表失败', status: 'error' });
78
- }
79
- },
80
-
81
- // 加载管理员角色
82
- async apiAdminRoleDetail() {
83
- if (!$Prop.rowData.id) return;
84
-
85
- try {
86
- const res = await $Http('/addon/admin/admin/roleDetail', {
87
- adminId: $Prop.rowData.id
88
- });
89
- $Data.checkedRoleCode = res.data.roleCode || '';
90
- } catch (error) {
91
- console.error('加载用户角色失败:', error);
92
- }
93
- },
94
-
95
- // 提交角色分配
96
- async onSubmit() {
97
- if (!$Data.checkedRoleCode) {
98
- MessagePlugin.info({ message: '请选择角色', status: 'warning' });
99
- return;
100
- }
101
-
102
- try {
103
- const res = await $Http('/addon/admin/admin/roleSave', {
104
- adminId: $Prop.rowData.id,
105
- roleCode: $Data.checkedRoleCode
106
- });
107
-
108
- if (res.code === 0) {
109
- MessagePlugin.info({ message: '角色分配成功', status: 'success' });
110
- $Method.onClose();
111
- $Emit('success');
112
- } else {
113
- MessagePlugin.info({ message: res.msg || '分配失败', status: 'error' });
114
- }
115
- } catch (error) {
116
- console.error('分配失败:', error);
117
- MessagePlugin.info({ message: '分配失败', status: 'error' });
118
- }
119
- }
120
- };
121
-
122
- $Method.initData();
123
- </script>
124
-
125
- <style scoped lang="scss">
126
- .role-dialog {
127
- .user-info {
128
- display: flex;
129
- align-items: center;
130
- gap: 12px;
131
- margin-bottom: 16px;
132
-
133
- .user-email {
134
- color: $text-secondary;
135
- }
136
- }
137
- }
138
- </style>
File without changes