befly-admin 3.4.6 → 3.4.8

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 (65) hide show
  1. package/.gitignore +2 -0
  2. package/index.html +2 -2
  3. package/package.json +8 -8
  4. package/src/config/{internal/index.ts → index.ts} +1 -1
  5. package/src/layouts/{internal/0.vue → default.vue} +49 -20
  6. package/src/main.ts +3 -5
  7. package/src/plugins/{internal/global.ts → global.ts} +1 -11
  8. package/src/plugins/{internal/http.ts → http.ts} +1 -1
  9. package/src/{plugins/internal/router.ts → router/index.ts} +22 -15
  10. package/src/styles/{internal/index.scss → global.scss} +29 -29
  11. package/src/types/auto-imports.d.ts +90 -645
  12. package/src/types/components.d.ts +8 -12
  13. package/src/types/typed-router.d.ts +32 -0
  14. package/src/utils/index.ts +21 -9
  15. package/src/views/index.vue +27 -0
  16. package/src/views/internal/login.vue +73 -0
  17. package/src/views/test.vue +60 -0
  18. package/tsconfig.json +4 -4
  19. package/vite.config.ts +131 -44
  20. package/src/components/internal/README.md +0 -27
  21. package/src/layouts/4.vue +0 -17
  22. package/src/layouts/internal/1.vue +0 -22
  23. package/src/layouts/internal/2.vue +0 -169
  24. package/src/layouts/internal/README.md +0 -27
  25. package/src/plugins/internal/README.md +0 -36
  26. package/src/styles/internal/README.md +0 -27
  27. package/src/styles/internal/mixins.scss +0 -98
  28. package/src/types/env.d.ts +0 -23
  29. package/src/utils/README.md +0 -37
  30. package/src/utils/internal/README.md +0 -21
  31. package/src/utils/internal/index.ts +0 -30
  32. package/src/views/internal/403/403.vue +0 -66
  33. package/src/views/internal/README.md +0 -27
  34. package/src/views/internal/admin/components/edit.vue +0 -147
  35. package/src/views/internal/admin/components/role.vue +0 -135
  36. package/src/views/internal/admin/index.vue +0 -176
  37. package/src/views/internal/dict/components/edit.vue +0 -156
  38. package/src/views/internal/dict/index.vue +0 -159
  39. package/src/views/internal/index/components/addonList.vue +0 -125
  40. package/src/views/internal/index/components/environmentInfo.vue +0 -97
  41. package/src/views/internal/index/components/operationLogs.vue +0 -112
  42. package/src/views/internal/index/components/performanceMetrics.vue +0 -148
  43. package/src/views/internal/index/components/quickActions.vue +0 -27
  44. package/src/views/internal/index/components/serviceStatus.vue +0 -181
  45. package/src/views/internal/index/components/systemNotifications.vue +0 -130
  46. package/src/views/internal/index/components/systemOverview.vue +0 -188
  47. package/src/views/internal/index/components/systemResources.vue +0 -104
  48. package/src/views/internal/index/components/userInfo.vue +0 -202
  49. package/src/views/internal/index/index.vue +0 -62
  50. package/src/views/internal/login/components/emailLoginForm.vue +0 -163
  51. package/src/views/internal/login/components/registerForm.vue +0 -168
  52. package/src/views/internal/login/components/welcomePanel.vue +0 -61
  53. package/src/views/internal/login/index_1.vue +0 -189
  54. package/src/views/internal/menu/components/edit.vue +0 -150
  55. package/src/views/internal/menu/index.vue +0 -168
  56. package/src/views/internal/news/detail/detail_2.vue +0 -26
  57. package/src/views/internal/news/detail/index.vue +0 -26
  58. package/src/views/internal/news/news.vue +0 -26
  59. package/src/views/internal/role/components/api.vue +0 -280
  60. package/src/views/internal/role/components/edit.vue +0 -129
  61. package/src/views/internal/role/components/menu.vue +0 -143
  62. package/src/views/internal/role/index.vue +0 -179
  63. package/src/views/internal/user/user.vue +0 -320
  64. /package/src/plugins/{internal/storage.ts → storage.ts} +0 -0
  65. /package/src/styles/{internal/variables.scss → variables.scss} +0 -0
package/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
+ types
2
+
1
3
  # Logs
2
4
  logs
3
5
  *.log
package/index.html CHANGED
@@ -1,10 +1,10 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="zh-CN">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>Befly Admin - 后台管理系统</title>
7
+ <title>Befly - 后台管理系统</title>
8
8
  </head>
9
9
  <body>
10
10
  <div id="app"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "befly-admin",
3
- "version": "3.4.6",
3
+ "version": "3.4.8",
4
4
  "description": "Befly Admin - 基于 Vue3 + OpenTiny Vue 的后台管理系统",
5
5
  "type": "module",
6
6
  "private": false,
@@ -23,7 +23,7 @@
23
23
  ],
24
24
  "scripts": {
25
25
  "dev": "vite",
26
- "build": "vue-tsc && vite build",
26
+ "build": "vite build",
27
27
  "preview": "vite preview",
28
28
  "type-check": "vue-tsc --noEmit",
29
29
  "sync:admin": "bunx befly sync:admin"
@@ -36,25 +36,25 @@
36
36
  "vue-router": "^4.6.3"
37
37
  },
38
38
  "devDependencies": {
39
+ "@befly-addon/admin": "1.0.12",
39
40
  "@iconify-json/lucide": "^1.2.72",
40
- "@iconify/json": "^2.2.280",
41
41
  "@opentiny/unplugin-tiny-vue": "^1.0.0",
42
42
  "@vitejs/plugin-vue": "^6.0.1",
43
43
  "@vue-macros/reactivity-transform": "^3.1.1",
44
- "@vue/compiler-sfc": "^3.5.22",
45
- "befly-auto-routes": "1.1.0",
46
- "merge-anything": "^6.0.6",
47
44
  "sass": "^1.93.3",
48
45
  "typescript": "^5.9.3",
49
46
  "unplugin-auto-import": "^20.2.0",
50
47
  "unplugin-icons": "^0.22.0",
51
48
  "unplugin-vue-components": "^30.0.0",
52
- "vite": "^7.2.0",
49
+ "unplugin-vue-router": "^0.10.8",
50
+ "vite": "^7.2.2",
51
+ "vite-plugin-vue-devtools": "^8.0.3",
52
+ "vite-plugin-vue-layouts-next": "^1.2.0",
53
53
  "vue-tsc": "^3.1.3"
54
54
  },
55
55
  "engines": {
56
56
  "node": ">=24.0.0",
57
57
  "pnpm": ">=10.0.0"
58
58
  },
59
- "gitHead": "c0844203f8fee734d2a8742f3b77b67bf0874681"
59
+ "gitHead": "40b4c3e6591454ff060416a6275142792e7de66c"
60
60
  }
@@ -6,7 +6,7 @@
6
6
  /**
7
7
  * 内置配置对象
8
8
  */
9
- export const $ConfigInternal = {
9
+ export const $Config = {
10
10
  /** 应用标题 */
11
11
  appTitle: import.meta.env.VITE_APP_TITLE || '管理后台',
12
12
  /** API 基础地址 */
@@ -3,16 +3,16 @@
3
3
  <!-- 顶部导航栏 -->
4
4
  <div class="layout-header">
5
5
  <div class="logo">
6
- <h2>{{ global.data.appTitle }}</h2>
6
+ <h2>{{ $Config.appTitle }}</h2>
7
7
  </div>
8
8
  <div class="header-right">
9
- <tiny-dropdown title="管理员" trigger="click" border type="info" @item-click="$Method.handleUserMenu">
10
- <template #dropdown>
11
- <tiny-dropdown-menu>
12
- <tiny-dropdown-item :item-data="{ value: 'logout' }" divided>退出登录</tiny-dropdown-item>
13
- </tiny-dropdown-menu>
14
- </template>
15
- </tiny-dropdown>
9
+ <div class="user-info-bar">
10
+ <div class="user-text">
11
+ <span class="user-name">{{ $Data.userInfo.nickname || '管理员' }}</span>
12
+ <tiny-tag type="info" size="small">{{ $Data.userInfo.role || '超级管理员' }}</tiny-tag>
13
+ </div>
14
+ <tiny-button size="medium" :icon="iconClose()" @click="$Method.handleLogout" />
15
+ </div>
16
16
  </div>
17
17
  </div>
18
18
 
@@ -37,6 +37,7 @@
37
37
 
38
38
  <script setup>
39
39
  import { arrayToTree } from '@/utils';
40
+ import { iconClose } from '@opentiny/vue-icon';
40
41
 
41
42
  const router = useRouter();
42
43
  const route = useRoute();
@@ -46,7 +47,11 @@ const global = useGlobal();
46
47
  const $Data = $ref({
47
48
  userMenus: [],
48
49
  expandedKeys: [],
49
- currentNodeKey: 0
50
+ currentNodeKey: 0,
51
+ userInfo: {
52
+ nickname: '管理员',
53
+ role: '超级管理员'
54
+ }
50
55
  });
51
56
 
52
57
  // 方法
@@ -98,17 +103,17 @@ const $Method = {
98
103
  }
99
104
  },
100
105
 
101
- // 处理用户菜单点击
102
- handleUserMenu(data) {
103
- const value = data.itemData?.value || data.value;
104
- if (value === 'logout') {
105
- $Storage.local.remove('token');
106
- router.push('/login');
107
- Modal.message({ message: '退出成功', status: 'success' });
108
- } else if (value === 'clearCache') {
109
- console.log('刷新缓存');
110
- Modal.message({ message: '缓存刷新成功', status: 'success' });
111
- }
106
+ // 处理退出登录
107
+ handleLogout() {
108
+ Modal.confirm({
109
+ message: '确定要退出登录吗?',
110
+ title: '确认',
111
+ onConfirm: () => {
112
+ $Storage.local.remove('token');
113
+ router.push('/internal/login');
114
+ Message.success('退出成功');
115
+ }
116
+ });
112
117
  }
113
118
  };
114
119
 
@@ -162,6 +167,30 @@ $Method.fetchUserMenus();
162
167
  display: flex;
163
168
  align-items: center;
164
169
  gap: 16px;
170
+
171
+ .user-info-bar {
172
+ display: flex;
173
+ align-items: center;
174
+ gap: 12px;
175
+
176
+ .user-avatar {
177
+ width: 32px;
178
+ height: 32px;
179
+ flex-shrink: 0;
180
+ }
181
+
182
+ .user-text {
183
+ display: flex;
184
+ flex-direction: column;
185
+ align-items: flex-start;
186
+
187
+ .user-name {
188
+ font-size: 14px;
189
+ font-weight: 500;
190
+ color: $text-primary;
191
+ }
192
+ }
193
+ }
165
194
  }
166
195
  }
167
196
 
package/src/main.ts CHANGED
@@ -1,12 +1,10 @@
1
- import { createApp } from 'vue';
2
- import { createPinia } from 'pinia';
3
1
  import App from './App.vue';
4
2
 
5
- // 引入全局样式
6
- import './styles/internal/index.scss';
3
+ // 引入全局基础样式(reset、通用类、滚动条等)
4
+ import '@/styles/global.scss';
7
5
 
8
6
  // 引入路由实例
9
- import { router } from './plugins/internal/router';
7
+ import { router } from './router';
10
8
 
11
9
  const app = createApp(App);
12
10
 
@@ -1,5 +1,3 @@
1
- import { defineStore } from 'pinia';
2
-
3
1
  /**
4
2
  * 全局状态管理
5
3
  * 集中管理所有全局数据,避免分散到多个 store 文件
@@ -9,15 +7,7 @@ export const useGlobal = defineStore('global', () => {
9
7
  const data = $ref({});
10
8
 
11
9
  // ==================== 全局方法 ====================
12
- const method = {
13
- /**
14
- * 设置页面标题
15
- * @param title 标题文本
16
- */
17
- setPageTitle: (title?: string) => {
18
- document.title = title ? `${title} - ${$ConfigInternal.appTitle}` : $ConfigInternal.appTitle;
19
- }
20
- };
10
+ const method = {};
21
11
 
22
12
  // ==================== 返回 ====================
23
13
  return {
@@ -56,7 +56,7 @@ request.interceptors.response.use(
56
56
  return Promise.reject(res.data);
57
57
  }
58
58
 
59
- return res;
59
+ return res as any;
60
60
  },
61
61
  (error) => {
62
62
  Modal.message({ message: '网络连接失败', status: 'error' });
@@ -1,6 +1,16 @@
1
1
  import { createRouter, createWebHashHistory } from 'vue-router';
2
- import autoRoutes from 'virtual:befly-auto-routes';
3
- import { $Storage } from './storage';
2
+ import { routes, handleHotUpdate } from 'vue-router/auto-routes';
3
+ import { setupLayouts } from 'virtual:generated-layouts';
4
+ import { $Storage } from '@/plugins/storage';
5
+
6
+ // 应用布局系统
7
+ const layoutRoutes = setupLayouts(routes);
8
+
9
+ // 打印自动生成的路由信息
10
+ console.log('=== 自动生成的路由列表 ===');
11
+ console.log(`路由总数: ${layoutRoutes.length}`);
12
+ console.dir(layoutRoutes);
13
+ console.log('========================');
4
14
 
5
15
  /**
6
16
  * 创建并导出路由实例
@@ -8,26 +18,23 @@ import { $Storage } from './storage';
8
18
  */
9
19
  export const router = createRouter({
10
20
  history: createWebHashHistory(import.meta.env.BASE_URL),
11
- routes: autoRoutes
21
+ routes: layoutRoutes
12
22
  });
13
23
 
24
+ // HMR 支持
25
+ if (import.meta.hot) {
26
+ handleHotUpdate(router);
27
+ }
28
+
14
29
  // 路由守卫 - 基础验证
15
30
  router.beforeEach(async (to, from, next) => {
16
- // 设置页面标题
17
- const titlePrefix = 'Befly Admin';
18
- if (to.meta?.title) {
19
- document.title = `${titlePrefix} - ${to.meta.title}`;
20
- } else {
21
- document.title = titlePrefix;
22
- }
23
-
24
31
  const token = $Storage.local.get('token');
25
32
 
26
- // 判断是否为公开路由:使用 layout0 的需要登录,其他 layout 为公开路由
27
- const isProtectedRoute = to.matched.some((record) => record.name === 'layout0');
33
+ // 判断是否为公开路由:meta.public true 表示公开路由
34
+ const isPublicRoute = to.meta?.public === true;
28
35
 
29
- // 1. 未登录且访问受保护路由 → 跳转登录
30
- if (!token && isProtectedRoute) {
36
+ // 1. 未登录且访问非公开路由 → 跳转登录
37
+ if (!token && !isPublicRoute) {
31
38
  return next('/internal/login');
32
39
  }
33
40
 
@@ -73,35 +73,35 @@ body {
73
73
  padding-left: 0 !important;
74
74
  }
75
75
 
76
- // 首页组件通用样式
77
- .section-block {
78
- background: $dashboard-section-bg;
79
- border-radius: $dashboard-section-radius;
80
- padding: $dashboard-section-padding;
81
- border: 1px solid $dashboard-section-border;
82
- box-shadow: $shadow-small;
83
-
84
- .section-header {
85
- display: flex;
86
- align-items: center;
87
- gap: $spacing-sm;
88
- margin-bottom: $spacing-md;
89
- padding-bottom: $spacing-sm;
90
- border-bottom: 1px solid $border-color-light;
91
-
92
- h2 {
93
- font-size: $dashboard-header-font-size;
94
- font-weight: 600;
95
- color: $text-primary;
96
- margin: 0;
97
- flex: 1;
98
- }
99
- }
100
-
101
- .section-content {
102
- font-size: $dashboard-content-font-size;
103
- }
104
- }
76
+ // 首页组件通用样式 - 临时注释未定义变量
77
+ // .section-block {
78
+ // background: $dashboard-section-bg;
79
+ // border-radius: $dashboard-section-radius;
80
+ // padding: $dashboard-section-padding;
81
+ // border: 1px solid $dashboard-section-border;
82
+ // box-shadow: $shadow-small;
83
+
84
+ // .section-header {
85
+ // display: flex;
86
+ // align-items: center;
87
+ // gap: $spacing-sm;
88
+ // margin-bottom: $spacing-md;
89
+ // padding-bottom: $spacing-sm;
90
+ // border-bottom: 1px solid $border-color-light;
91
+
92
+ // h2 {
93
+ // font-size: $dashboard-header-font-size;
94
+ // font-weight: 600;
95
+ // color: $text-primary;
96
+ // margin: 0;
97
+ // flex: 1;
98
+ // }
99
+ // }
100
+
101
+ // .section-content {
102
+ // font-size: $dashboard-content-font-size;
103
+ // }
104
+ // }
105
105
 
106
106
  // 数据列表页面通用布局样式
107
107
  .page-table {