befly-admin 3.4.30 → 3.4.32

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/bunfig.toml CHANGED
@@ -1,4 +1,2 @@
1
1
  [install]
2
2
  linker = "isolated"
3
-
4
- publicHoistPattern = ["@types*", "*eslint*", "@opentiny/*"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "befly-admin",
3
- "version": "3.4.30",
3
+ "version": "3.4.32",
4
4
  "description": "Befly Admin - 基于 Vue3 + OpenTiny Vue 的后台管理系统",
5
5
  "type": "module",
6
6
  "private": false,
@@ -29,13 +29,14 @@
29
29
  "sync:admin": "bunx befly sync:admin"
30
30
  },
31
31
  "dependencies": {
32
+ "@befly-addon/admin": "1.0.34",
32
33
  "axios": "^1.13.2",
33
34
  "pinia": "^3.0.4",
35
+ "tdesign-vue-next": "^1.10.6",
34
36
  "vue": "^3.5.22",
35
37
  "vue-router": "^4.6.3"
36
38
  },
37
39
  "devDependencies": {
38
- "@befly-addon/admin": "1.0.32",
39
40
  "@iconify-json/lucide": "^1.2.72",
40
41
  "@unocss/preset-attributify": "^66.5.6",
41
42
  "@unocss/preset-uno": "^66.5.6",
@@ -56,5 +57,5 @@
56
57
  "node": ">=24.0.0",
57
58
  "pnpm": ">=10.0.0"
58
59
  },
59
- "gitHead": "7f8bd9dc5342e59953997d58e6abf6ca2469b211"
60
+ "gitHead": "3593368cbf5c34f379b3b4569a7439bce9666938"
60
61
  }
@@ -9,26 +9,43 @@
9
9
  <div class="user-info-bar">
10
10
  <div class="user-text">
11
11
  <span class="user-name">{{ $Data.userInfo.nickname || '管理员' }}</span>
12
- <tiny-tag type="info" size="small">{{ $Data.userInfo.role || '超级管理员' }}</tiny-tag>
12
+ <t-tag theme="primary" size="small" variant="light">{{ $Data.userInfo.role || '超级管理员' }}</t-tag>
13
13
  </div>
14
- <tiny-button size="medium" :icon="iconClose()" @click="$Method.handleLogout" />
14
+ <t-button variant="text" size="medium" @click="$Method.handleLogout">
15
+ <template #icon>
16
+ <i-lucide:x />
17
+ </template>
18
+ </t-button>
15
19
  </div>
16
20
  </div>
17
21
  </div>
18
22
 
19
23
  <!-- 菜单栏 -->
20
24
  <div class="layout-menu">
21
- <tiny-tree-menu :ref="(el) => ($From.treeMenuRef = el)" :data="$Data.userMenus" :props="{ label: 'name' }" node-key="id" :node-height="40" :show-filter="false" :default-expanded-keys="$Data.expandedKeys" style="height: 100%" only-check-children width-adapt @node-click="$Method.onMenuClick">
22
- <template #default="{ data }">
23
- <span class="menu-item">
24
- <!-- 根据路径和是否有子节点显示不同图标 -->
25
- <i-lucide:home v-if="data.path === '/addon/admin/'" />
26
- <i-lucide:folder v-else-if="data.children && data.children.length > 0" />
27
- <i-lucide:file-text v-else />
28
- <span>{{ data.name }}</span>
29
- </span>
25
+ <t-menu :value="$Data.currentMenuKey" :expanded="$Data.expandedKeys" style="height: 100%" @change="$Method.onMenuClick" @expand="(value) => ($Data.expandedKeys = value)">
26
+ <template v-for="menu in $Data.userMenus" :key="menu.id">
27
+ <!-- 无子菜单 -->
28
+ <t-menu-item v-if="!menu.children || menu.children.length === 0" :value="menu.path">
29
+ <template #icon>
30
+ <i-lucide:home v-if="menu.path === '/addon/admin/'" />
31
+ <i-lucide:file-text v-else />
32
+ </template>
33
+ {{ menu.name }}
34
+ </t-menu-item>
35
+ <!-- 有子菜单 -->
36
+ <t-submenu v-else :value="String(menu.id)" :title="menu.name">
37
+ <template #icon>
38
+ <i-lucide:folder />
39
+ </template>
40
+ <t-menu-item v-for="child in menu.children" :key="child.id" :value="child.path">
41
+ <template #icon>
42
+ <i-lucide:file-text />
43
+ </template>
44
+ {{ child.name }}
45
+ </t-menu-item>
46
+ </t-submenu>
30
47
  </template>
31
- </tiny-tree-menu>
48
+ </t-menu>
32
49
  </div>
33
50
 
34
51
  <!-- 内容区域 -->
@@ -40,7 +57,6 @@
40
57
 
41
58
  <script setup>
42
59
  import { arrayToTree } from '@/utils';
43
- import { iconClose } from '@opentiny/vue-icon';
44
60
 
45
61
  const router = useRouter();
46
62
  const route = useRoute();
@@ -55,7 +71,7 @@ const $Data = $ref({
55
71
  userMenus: [],
56
72
  userMenusFlat: [], // 一维菜单数据
57
73
  expandedKeys: [],
58
- currentNodeKey: 0,
74
+ currentMenuKey: '',
59
75
  userInfo: {
60
76
  nickname: '管理员',
61
77
  role: '超级管理员'
@@ -96,7 +112,7 @@ const $Method = {
96
112
  while (menu.pid) {
97
113
  const parent = $Data.userMenusFlat.find((m) => m.id === menu.pid);
98
114
  if (parent) {
99
- expandedKeys.unshift(parent.id);
115
+ expandedKeys.unshift(String(parent.id));
100
116
  menu = parent;
101
117
  } else {
102
118
  break;
@@ -106,17 +122,14 @@ const $Method = {
106
122
  // 使用 nextTick 确保 DOM 更新后再设置高亮
107
123
  nextTick(() => {
108
124
  $Data.expandedKeys = expandedKeys;
109
- // 使用 setCurrentKey 方法设置当前高亮节点
110
- if ($From.treeMenuRef) {
111
- $From.treeMenuRef.setCurrentKey(currentMenu.id);
112
- }
125
+ $Data.currentMenuKey = currentPath;
113
126
  });
114
127
  },
115
128
 
116
129
  // 处理菜单点击
117
- onMenuClick(data) {
118
- if (data.path) {
119
- router.push(data.path);
130
+ onMenuClick(path) {
131
+ if (path) {
132
+ router.push(path);
120
133
  }
121
134
  },
122
135
 
@@ -223,22 +236,6 @@ $Method.fetchUserMenus();
223
236
  padding: 16px 12px;
224
237
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
225
238
  border: 1px solid #e8eaed;
226
-
227
- .tiny-tree-menu:before {
228
- display: none;
229
- }
230
-
231
- .menu-item {
232
- display: flex;
233
- align-items: center;
234
- width: 100%;
235
- padding: 2px 0;
236
- transition: all 0.2s ease;
237
-
238
- &:hover {
239
- color: #0052d9;
240
- }
241
- }
242
239
  }
243
240
 
244
241
  .layout-main {
@@ -103,6 +103,7 @@ declare module 'vue' {
103
103
  readonly $Config: UnwrapRef<typeof import('../config/index.js')['$Config']>
104
104
  readonly $Http: UnwrapRef<typeof import('../plugins/http.js')['$Http']>
105
105
  readonly $Storage: UnwrapRef<typeof import('../plugins/storage.js')['$Storage']>
106
+ readonly DialogPlugin: UnwrapRef<typeof import('tdesign-vue-next')['DialogPlugin']>
106
107
  readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
107
108
  readonly MessagePlugin: UnwrapRef<typeof import('tdesign-vue-next')['MessagePlugin']>
108
109
  readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
@@ -11,12 +11,46 @@ export {}
11
11
  /* prettier-ignore */
12
12
  declare module 'vue' {
13
13
  export interface GlobalComponents {
14
+ 'ILucide:activity': typeof import('~icons/lucide/activity')['default']
15
+ 'ILucide:alertCircle': typeof import('~icons/lucide/alert-circle')['default']
16
+ 'ILucide:alertTriangle': typeof import('~icons/lucide/alert-triangle')['default']
17
+ 'ILucide:checkCircle': typeof import('~icons/lucide/check-circle')['default']
18
+ 'ILucide:circle': typeof import('~icons/lucide/circle')['default']
19
+ 'ILucide:clock': typeof import('~icons/lucide/clock')['default']
20
+ 'ILucide:cloud': typeof import('~icons/lucide/cloud')['default']
21
+ 'ILucide:code': typeof import('~icons/lucide/code')['default']
22
+ 'ILucide:cpu': typeof import('~icons/lucide/cpu')['default']
23
+ 'ILucide:database': typeof import('~icons/lucide/database')['default']
24
+ 'ILucide:disc': typeof import('~icons/lucide/disc')['default']
14
25
  'ILucide:fileText': typeof import('~icons/lucide/file-text')['default']
15
26
  'ILucide:folder': typeof import('~icons/lucide/folder')['default']
27
+ 'ILucide:hardDrive': typeof import('~icons/lucide/hard-drive')['default']
16
28
  'ILucide:home': typeof import('~icons/lucide/home')['default']
29
+ 'ILucide:info': typeof import('~icons/lucide/info')['default']
30
+ 'ILucide:lock': typeof import('~icons/lucide/lock')['default']
31
+ 'ILucide:mail': typeof import('~icons/lucide/mail')['default']
32
+ 'ILucide:menu': typeof import('~icons/lucide/menu')['default']
33
+ 'ILucide:pencil': typeof import('~icons/lucide/pencil')['default']
34
+ 'ILucide:plus': typeof import('~icons/lucide/plus')['default']
35
+ 'ILucide:rotateCw': typeof import('~icons/lucide/rotate-cw')['default']
36
+ 'ILucide:search': typeof import('~icons/lucide/search')['default']
37
+ 'ILucide:server': typeof import('~icons/lucide/server')['default']
38
+ 'ILucide:settings': typeof import('~icons/lucide/settings')['default']
39
+ 'ILucide:smile': typeof import('~icons/lucide/smile')['default']
40
+ 'ILucide:square': typeof import('~icons/lucide/square')['default']
41
+ 'ILucide:trash2': typeof import('~icons/lucide/trash2')['default']
42
+ 'ILucide:trendingUp': typeof import('~icons/lucide/trending-up')['default']
43
+ 'ILucide:user': typeof import('~icons/lucide/user')['default']
44
+ 'ILucide:users': typeof import('~icons/lucide/users')['default']
45
+ 'ILucide:webhook': typeof import('~icons/lucide/webhook')['default']
46
+ 'ILucide:x': typeof import('~icons/lucide/x')['default']
47
+ 'ILucide:xCircle': typeof import('~icons/lucide/x-circle')['default']
48
+ 'ILucide:zap': typeof import('~icons/lucide/zap')['default']
17
49
  RouterLink: typeof import('vue-router')['RouterLink']
18
50
  RouterView: typeof import('vue-router')['RouterView']
19
51
  TButton: typeof import('tdesign-vue-next')['Button']
52
+ TCheckbox: typeof import('tdesign-vue-next')['Checkbox']
53
+ TCheckboxGroup: typeof import('tdesign-vue-next')['CheckboxGroup']
20
54
  TDialog: typeof import('tdesign-vue-next')['Dialog']
21
55
  TDivider: typeof import('tdesign-vue-next')['Divider']
22
56
  TDropdown: typeof import('tdesign-vue-next')['Dropdown']
@@ -27,11 +61,15 @@ declare module 'vue' {
27
61
  TInput: typeof import('tdesign-vue-next')['Input']
28
62
  TInputNumber: typeof import('tdesign-vue-next')['InputNumber']
29
63
  TLink: typeof import('tdesign-vue-next')['Link']
64
+ TMenu: typeof import('tdesign-vue-next')['Menu']
65
+ TMenuItem: typeof import('tdesign-vue-next')['MenuItem']
30
66
  TPagination: typeof import('tdesign-vue-next')['Pagination']
67
+ TProgress: typeof import('tdesign-vue-next')['Progress']
31
68
  TRadio: typeof import('tdesign-vue-next')['Radio']
32
69
  TRadioGroup: typeof import('tdesign-vue-next')['RadioGroup']
33
70
  TSelect: typeof import('tdesign-vue-next')['Select']
34
71
  TSpace: typeof import('tdesign-vue-next')['Space']
72
+ TSubmenu: typeof import('tdesign-vue-next')['Submenu']
35
73
  TTable: typeof import('tdesign-vue-next')['Table']
36
74
  TTag: typeof import('tdesign-vue-next')['Tag']
37
75
  TTree: typeof import('tdesign-vue-next')['Tree']
@@ -14,14 +14,5 @@ meta:
14
14
  <style lang="scss" scoped>
15
15
  .page-home {
16
16
  padding: 20px;
17
-
18
- h1 {
19
- color: $primary-color;
20
- margin-bottom: 16px;
21
- }
22
-
23
- p {
24
- color: $text-color-secondary;
25
- }
26
17
  }
27
18
  </style>
package/vite.config.js CHANGED
@@ -44,7 +44,9 @@ export default defineConfig({
44
44
  }),
45
45
 
46
46
  // Vue Reactivity Transform 支持
47
- ReactivityTransform(),
47
+ ReactivityTransform({
48
+ exclude: []
49
+ }),
48
50
 
49
51
  // API 自动导入
50
52
  AutoImport({
@@ -122,33 +124,9 @@ export default defineConfig({
122
124
  return 'framework-pinia';
123
125
  }
124
126
 
125
- // TinyVue 细粒度拆分
126
- if (id.includes('@opentiny/vue-renderless/src/grid')) {
127
- return 'tiny-grid';
128
- }
129
- if (id.includes('@opentiny/vue-renderless/src/table')) {
130
- return 'tiny-table';
131
- }
132
- if (id.includes('@opentiny/vue-renderless/src/tree')) {
133
- return 'tiny-tree';
134
- }
135
- if (id.includes('@opentiny/vue-renderless/src/form')) {
136
- return 'tiny-form';
137
- }
138
- if (id.includes('node_modules/@opentiny/vue-renderless/')) {
139
- return 'tiny-renderless';
140
- }
141
- if (id.includes('node_modules/@opentiny/vue-theme/')) {
142
- return 'tiny-theme';
143
- }
144
- if (id.includes('node_modules/@opentiny/vue-locale/')) {
145
- return 'tiny-locale';
146
- }
147
- if (id.includes('node_modules/@opentiny/vue-common/')) {
148
- return 'tiny-common';
149
- }
150
- if (id.includes('node_modules/@opentiny/vue-icon/')) {
151
- return 'tiny-icon';
127
+ // TDesign Vue Next
128
+ if (id.includes('node_modules/tdesign-vue-next/') || id.includes('node_modules/.bun/tdesign-vue-next')) {
129
+ return 'tdesign';
152
130
  }
153
131
 
154
132
  // 工具库(独立文件)
@@ -161,7 +139,7 @@ export default defineConfig({
161
139
  return 'lib-lodash';
162
140
  }
163
141
 
164
- // echarts 及相关库(TinyVue 图表组件依赖)
142
+ // echarts 及相关库
165
143
  if (id.includes('node_modules/echarts/') || id.includes('node_modules/.bun/echarts')) {
166
144
  return 'lib-echarts';
167
145
  }
@@ -180,7 +158,7 @@ export default defineConfig({
180
158
  }
181
159
 
182
160
  // befly-addon
183
- if (id.includes('@befly-addon/')) {
161
+ if (id.includes('@befly-addon/') || id.includes('packages/addonAdmin/') || id.includes('packages\\addonAdmin\\')) {
184
162
  return 'befly-addon';
185
163
  }
186
164
 
@@ -1,73 +0,0 @@
1
- <template>
2
- <div class="page-login">
3
- <div class="login-box">
4
- <h1>登录</h1>
5
- <tiny-form ref="formRef" :model="$Data.form" label-position="top">
6
- <tiny-form-item label="用户名" prop="username">
7
- <tiny-input v-model="$Data.form.username" placeholder="请输入用户名" />
8
- </tiny-form-item>
9
- <tiny-form-item label="密码" prop="password">
10
- <tiny-input v-model="$Data.form.password" type="password" placeholder="请输入密码" />
11
- </tiny-form-item>
12
- <tiny-form-item>
13
- <tiny-button type="primary" @click="$Method.handleLogin">登录</tiny-button>
14
- </tiny-form-item>
15
- </tiny-form>
16
- </div>
17
- </div>
18
- </template>
19
-
20
- <script setup>
21
- const router = useRouter();
22
-
23
- const $Data = $ref({
24
- form: {
25
- username: '',
26
- password: ''
27
- }
28
- });
29
-
30
- const $Method = {
31
- async handleLogin() {
32
- // 模拟登录
33
- $Storage.local.set('token', 'mock-token-123');
34
- MessagePlugin.success('登录成功');
35
- router.push('/');
36
- }
37
- };
38
- </script>
39
-
40
- <route lang="yaml">
41
- meta:
42
- layout: blank
43
- public: true
44
- title: 登录
45
- </route>
46
-
47
- <style lang="scss" scoped>
48
- .page-login {
49
- width: 100%;
50
- height: 100%;
51
- display: flex;
52
- align-items: center;
53
- justify-content: center;
54
-
55
- .login-box {
56
- width: 400px;
57
- padding: 40px;
58
- background: #fff;
59
- border-radius: 8px;
60
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
61
-
62
- h1 {
63
- text-align: center;
64
- margin-bottom: 30px;
65
- color: $primary-color;
66
- }
67
-
68
- .tiny-button {
69
- width: 100%;
70
- }
71
- }
72
- }
73
- </style>
@@ -1,57 +0,0 @@
1
- <template>
2
- <div class="test-page">
3
- <h1>TinyVue 自动导入测试</h1>
4
-
5
- <div class="button-group">
6
- <tiny-button type="primary" @click="testModal">测试 Modal</tiny-button>
7
- <tiny-button type="success" @click="testMessage">测试 Message</tiny-button>
8
- <tiny-button type="warning" @click="testNotify">测试 Notify</tiny-button>
9
- <tiny-button type="info" @click="testMessageBox">测试 MessageBox</tiny-button>
10
- </div>
11
- </div>
12
- </template>
13
-
14
- <script setup>
15
- // 无需导入,已自动导入:MessagePlugin, DialogPlugin, NotificationPlugin, LoadingPlugin
16
-
17
- const testModal = () => {
18
- MessagePlugin.success('这是一个成功提示');
19
- };
20
-
21
- const testMessage = () => {
22
- Message.success('成功消息');
23
- };
24
-
25
- const testNotify = () => {
26
- Notify.success({
27
- title: '成功通知',
28
- message: '这是一个成功通知的内容'
29
- });
30
- };
31
-
32
- const testMessageBox = () => {
33
- MessageBox.alert('这是一个提示框', '提示');
34
- };
35
- </script>
36
-
37
- <route lang="yaml">
38
- meta:
39
- layout: default
40
- title: 自动导入测试
41
- </route>
42
-
43
- <style lang="scss" scoped>
44
- .test-page {
45
- padding: 20px;
46
-
47
- h1 {
48
- color: $primary-color;
49
- margin-bottom: 24px;
50
- }
51
-
52
- .button-group {
53
- display: flex;
54
- gap: 12px;
55
- }
56
- }
57
- </style>