@befly-addon/admin 1.0.33 → 1.0.35

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.
@@ -1,9 +1,13 @@
1
- <template>
2
- <t-dialog v-model:visible="$Data.visible" title="接口权限" width="900px" :append-to-body="true" :show-footer="true" top="5vh" @close="$Method.onClose">
1
+ <template>
2
+ <TDialog v-model:visible="$Data.visible" title="接口权限" width="900px" :append-to-body="true" :show-footer="true" top="5vh" @close="$Method.onClose">
3
3
  <div class="comp-role-api">
4
4
  <!-- 搜索框 -->
5
5
  <div class="search-box">
6
- <TinySearch v-model="$Data.searchText" placeholder="搜索接口名称或路径" clearable @update:modelValue="$Method.onSearch" />
6
+ <TInput v-model="$Data.searchText" placeholder="搜索接口名称或路径" clearable @change="$Method.onSearch">
7
+ <template #prefix-icon>
8
+ <ILucideSearch />
9
+ </template>
10
+ </TInput>
7
11
  </div>
8
12
 
9
13
  <!-- 接口分组列表 -->
@@ -11,9 +15,9 @@
11
15
  <div v-for="group in $Data.filteredApiData" :key="group.name" class="api-group">
12
16
  <div class="group-header">{{ group.title }}</div>
13
17
  <div class="api-checkbox-list">
14
- <TinyCheckboxGroup v-model="$Data.checkedApiIds">
15
- <TinyCheckbox v-for="api in group.apis" :key="api.id" :label="api.id"> {{ api.label }} </TinyCheckbox>
16
- </TinyCheckboxGroup>
18
+ <TCheckboxGroup v-model="$Data.checkedApiIds">
19
+ <TCheckbox v-for="api in group.apis" :key="api.id" :value="api.id"> {{ api.label }} </TCheckbox>
20
+ </TCheckboxGroup>
17
21
  </div>
18
22
  </div>
19
23
  </div>
@@ -21,18 +25,20 @@
21
25
 
22
26
  <template #footer>
23
27
  <div class="footer-left">
24
- <t-button size="small" @click="$Method.onCheckAll">全选</t-button>
25
- <t-button size="small" @click="$Method.onUncheckAll">取消全选</t-button>
28
+ <TButton size="small" @click="$Method.onCheckAll">全选</TButton>
29
+ <TButton size="small" @click="$Method.onUncheckAll">取消全选</TButton>
26
30
  </div>
27
31
  <div class="footer-right">
28
- <t-button @click="$Method.onClose">取消</t-button>
29
- <t-button type="primary" @click="$Method.onSubmit">保存</t-button>
32
+ <TButton @click="$Method.onClose">取消</TButton>
33
+ <TButton theme="primary" @click="$Method.onSubmit">保存</TButton>
30
34
  </div>
31
35
  </template>
32
- </t-dialog>
36
+ </TDialog>
33
37
  </template>
34
38
 
35
39
  <script setup>
40
+ import { Dialog as TDialog, Input as TInput, CheckboxGroup as TCheckboxGroup, Checkbox as TCheckbox, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
41
+ import ILucideSearch from '~icons/lucide/search';
36
42
  import { $Http } from '@/plugins/http';
37
43
 
38
44
  const $Prop = defineProps({
@@ -241,18 +247,18 @@ $Method.initData();
241
247
  padding: 16px;
242
248
  background-color: $bg-color-container;
243
249
 
244
- :deep(.tiny-checkbox-group) {
250
+ :deep(.t-checkbox-group) {
245
251
  display: flex;
246
252
  flex-wrap: wrap;
247
253
  gap: 12px;
248
254
  width: 100%;
249
255
  }
250
256
 
251
- :deep(.tiny-checkbox) {
257
+ :deep(.t-checkbox) {
252
258
  flex: 0 0 calc(33.333% - 8px);
253
259
  margin: 0;
254
260
 
255
- .tiny-checkbox__label {
261
+ .t-checkbox__label {
256
262
  white-space: nowrap;
257
263
  overflow: hidden;
258
264
  text-overflow: ellipsis;
@@ -264,7 +270,7 @@ $Method.initData();
264
270
  }
265
271
 
266
272
  // 底部操作栏布局
267
- :deep(.tiny-dialog-box__footer) {
273
+ :deep(.t-dialog__footer) {
268
274
  display: flex;
269
275
  justify-content: space-between;
270
276
  align-items: center;
@@ -1,35 +1,36 @@
1
- <template>
2
- <t-dialog 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">
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">
3
3
  <div class="comp-role-edit">
4
- <t-form :model="$Data.formData" label-width="120px" label-position="left" :rules="$Data2.formRules" :ref="(el) => ($From.form = el)">
5
- <t-form-item label="角色名称" prop="name">
6
- <t-input v-model="$Data.formData.name" placeholder="请输入角色名称" />
7
- </t-form-item>
8
- <t-form-item label="角色代码" prop="code">
9
- <t-input v-model="$Data.formData.code" placeholder="请输入角色代码,如:admin" />
10
- </t-form-item>
11
- <t-form-item label="角色描述" prop="description">
12
- <t-input v-model="$Data.formData.description" type="textarea" placeholder="请输入角色描述" :rows="3" />
13
- </t-form-item>
14
- <t-form-item label="排序" prop="sort">
15
- <t-input-number v-model="$Data.formData.sort" :min="0" :max="9999" />
16
- </t-form-item>
17
- <t-form-item label="状态" prop="state">
18
- <t-radio-group v-model="$Data.formData.state">
19
- <t-radio :label="1">正常</t-radio>
20
- <t-radio :label="2">禁用</t-radio>
21
- </t-radio-group>
22
- </t-form-item>
23
- </t-form>
4
+ <TForm :model="$Data.formData" label-width="120px" label-position="left" :rules="$Data2.formRules" :ref="(el) => ($From.form = el)">
5
+ <TFormItem label="角色名称" prop="name">
6
+ <TInput v-model="$Data.formData.name" placeholder="请输入角色名称" />
7
+ </TFormItem>
8
+ <TFormItem label="角色代码" prop="code">
9
+ <TInput v-model="$Data.formData.code" placeholder="请输入角色代码,如:admin" />
10
+ </TFormItem>
11
+ <TFormItem label="角色描述" prop="description">
12
+ <TInput v-model="$Data.formData.description" type="textarea" placeholder="请输入角色描述" :rows="3" />
13
+ </TFormItem>
14
+ <TFormItem label="排序" prop="sort">
15
+ <TInputNumber v-model="$Data.formData.sort" :min="0" :max="9999" />
16
+ </TFormItem>
17
+ <TFormItem label="状态" prop="state">
18
+ <TRadioGroup v-model="$Data.formData.state">
19
+ <TRadio :label="1">正常</TRadio>
20
+ <TRadio :label="2">禁用</TRadio>
21
+ </TRadioGroup>
22
+ </TFormItem>
23
+ </TForm>
24
24
  </div>
25
25
  <template #footer>
26
- <t-button @click="$Method.onClose">取消</t-button>
27
- <t-button type="primary" @click="$Method.onSubmit">确定</t-button>
26
+ <TButton @click="$Method.onClose">取消</TButton>
27
+ <TButton theme="primary" @click="$Method.onSubmit">确定</TButton>
28
28
  </template>
29
- </t-dialog>
29
+ </TDialog>
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
34
  import { $Http } from '@/plugins/http';
34
35
 
35
36
  const $Prop = defineProps({
@@ -1,17 +1,18 @@
1
- <template>
2
- <t-dialog v-model:visible="$Data.visible" title="菜单权限" width="600px" :append-to-body="true" :show-footer="true" top="10vh" @close="$Method.onClose">
1
+ <template>
2
+ <TDialog v-model:visible="$Data.visible" title="菜单权限" width="600px" :append-to-body="true" :show-footer="true" top="10vh" @close="$Method.onClose">
3
3
  <div class="comp-role-menu">
4
- <t-tree :data="$Data.menuTreeData" node-key="id" show-checkbox default-expand-all :props="{ label: 'name' }" :ref="(el) => ($From.tree = el)" />
4
+ <TTree :data="$Data.menuTreeData" node-key="id" show-checkbox default-expand-all :props="{ label: 'name' }" :ref="(el) => ($From.tree = el)" />
5
5
  </div>
6
6
  <template #footer>
7
- <t-button @click="$Method.onClose">取消</t-button>
8
- <t-button type="primary" @click="$Method.onSubmit">保存</t-button>
7
+ <TButton @click="$Method.onClose">取消</TButton>
8
+ <TButton theme="primary" @click="$Method.onSubmit">保存</TButton>
9
9
  </template>
10
- </t-dialog>
10
+ </TDialog>
11
11
  </template>
12
12
 
13
13
  <script setup>
14
14
  import { nextTick } from 'vue';
15
+ import { Dialog as TDialog, Tree as TTree, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
15
16
  import { arrayToTree } from '@/utils';
16
17
  import { $Http } from '@/plugins/http';
17
18
 
@@ -2,57 +2,57 @@
2
2
  <div class="page-role page-table">
3
3
  <div class="main-tool">
4
4
  <div class="left">
5
- <t-button type="primary" @click="$Method.onAction('add', {})">
5
+ <TButton theme="primary" @click="$Method.onAction('add', {})">
6
6
  <template #icon>
7
- <IconLucidePlus />
7
+ <ILucidePlus />
8
8
  </template>
9
9
  添加角色
10
- </t-button>
10
+ </TButton>
11
11
  </div>
12
12
  <div class="right">
13
- <t-button @click="$Method.handleRefresh">
13
+ <TButton @click="$Method.handleRefresh">
14
14
  <template #icon>
15
- <IconLucideRotateCw />
15
+ <ILucideRotateCw />
16
16
  </template>
17
17
  刷新
18
- </t-button>
18
+ </TButton>
19
19
  </div>
20
20
  </div>
21
21
  <div class="main-table">
22
- <t-table :data="$Data.tableData" :columns="$Data.columns" header-cell-class-name="custom-table-cell-class" size="small" height="100%" row-key="id" bordered>
22
+ <TTable :data="$Data.tableData" :columns="$Data.columns" header-cell-class-name="custom-table-cell-class" size="small" height="100%" row-key="id" bordered>
23
23
  <template #state="{ row }">
24
- <t-tag v-if="row.state === 1" theme="success">正常</t-tag>
25
- <t-tag v-else-if="row.state === 2" theme="warning">禁用</t-tag>
26
- <t-tag v-else theme="danger">已删除</t-tag>
24
+ <TTag v-if="row.state === 1" theme="success">正常</TTag>
25
+ <TTag v-else-if="row.state === 2" theme="warning">禁用</TTag>
26
+ <TTag v-else theme="danger">已删除</TTag>
27
27
  </template>
28
28
  <template #operation="{ row }">
29
- <t-dropdown trigger="click" min-column-width="120" @click="(data) => $Method.onAction(data.value, row)">
30
- <t-button variant="text" size="small">操作</t-button>
31
- <t-dropdown-menu slot="dropdown">
32
- <t-dropdown-item value="upd">
33
- <IconLucidePencil />
29
+ <TDropdown trigger="click" min-column-width="120" @click="(data) => $Method.onAction(data.value, row)">
30
+ <TButton variant="text" size="small">操作</TButton>
31
+ <TDropdownMenu slot="dropdown">
32
+ <TDropdownItem value="upd">
33
+ <ILucidePencil />
34
34
  编辑
35
- </t-dropdown-item>
36
- <t-dropdown-item value="menu">
37
- <IconLucideSettings />
35
+ </TDropdownItem>
36
+ <TDropdownItem value="menu">
37
+ <ILucideSettings />
38
38
  菜单权限
39
- </t-dropdown-item>
40
- <t-dropdown-item value="api">
41
- <IconLucideCode />
39
+ </TDropdownItem>
40
+ <TDropdownItem value="api">
41
+ <ILucideCode />
42
42
  接口权限
43
- </t-dropdown-item>
44
- <t-dropdown-item value="del" :divider="true">
45
- <IconLucideTrash2 style="width: 14px; height: 14px; margin-right: 6px" />
43
+ </TDropdownItem>
44
+ <TDropdownItem value="del" :divider="true">
45
+ <ILucideTrash2 style="width: 14px; height: 14px; margin-right: 6px" />
46
46
  删除
47
- </t-dropdown-item>
48
- </t-dropdown-menu>
49
- </t-dropdown>
47
+ </TDropdownItem>
48
+ </TDropdownMenu>
49
+ </TDropdown>
50
50
  </template>
51
- </t-table>
51
+ </TTable>
52
52
  </div>
53
53
 
54
54
  <div class="main-page">
55
- <t-pagination :current-page="$Data.pagerConfig.currentPage" :page-size="$Data.pagerConfig.pageSize" :total="$Data.pagerConfig.total" @current-change="$Method.onPageChange" @size-change="$Method.handleSizeChange" />
55
+ <TPagination :current-page="$Data.pagerConfig.currentPage" :page-size="$Data.pagerConfig.pageSize" :total="$Data.pagerConfig.total" @current-change="$Method.onPageChange" @size-change="$Method.handleSizeChange" />
56
56
  </div>
57
57
 
58
58
  <!-- 编辑对话框组件 -->
@@ -67,6 +67,13 @@
67
67
  </template>
68
68
 
69
69
  <script setup>
70
+ import { Button as TButton, Table as TTable, Tag as TTag, Dropdown as TDropdown, DropdownMenu as TDropdownMenu, DropdownItem as TDropdownItem, Pagination as TPagination, MessagePlugin, DialogPlugin } from 'tdesign-vue-next';
71
+ import ILucidePlus from '~icons/lucide/plus';
72
+ import ILucideRotateCw from '~icons/lucide/rotate-cw';
73
+ import ILucidePencil from '~icons/lucide/pencil';
74
+ import ILucideSettings from '~icons/lucide/settings';
75
+ import ILucideCode from '~icons/lucide/code';
76
+ import ILucideTrash2 from '~icons/lucide/trash-2';
70
77
  import EditDialog from './components/edit.vue';
71
78
  import MenuDialog from './components/menu.vue';
72
79
  import ApiDialog from './components/api.vue';
@@ -1,26 +0,0 @@
1
- <template>
2
- <div class="news-page">
3
- <h1>新闻页面 index</h1>
4
- <p>这个页面使用布局 1.vue</p>
5
- <div class="news-content">
6
- <p>这里是新闻内容...</p>
7
- </div>
8
- </div>
9
- </template>
10
-
11
- <script setup>
12
- // 新闻页面逻辑
13
- </script>
14
-
15
- <style scoped>
16
- .news-page {
17
- padding: 20px;
18
- }
19
-
20
- .news-content {
21
- margin-top: 20px;
22
- padding: 20px;
23
- background: #f5f5f5;
24
- border-radius: 8px;
25
- }
26
- </style>
@@ -1,26 +0,0 @@
1
- <template>
2
- <div class="news-page">
3
- <h1>新闻页面</h1>
4
- <p>这个页面使用布局 1.vue</p>
5
- <div class="news-content">
6
- <p>这里是新闻内容...</p>
7
- </div>
8
- </div>
9
- </template>
10
-
11
- <script setup>
12
- // 新闻页面逻辑
13
- </script>
14
-
15
- <style scoped>
16
- .news-page {
17
- padding: 20px;
18
- }
19
-
20
- .news-content {
21
- margin-top: 20px;
22
- padding: 20px;
23
- background: #f5f5f5;
24
- border-radius: 8px;
25
- }
26
- </style>
@@ -1,322 +0,0 @@
1
- <template>
2
- <div class="user-manage">
3
- <!-- 上:过滤和操作栏 -->
4
- <div class="toolbar">
5
- <div class="toolbar-left">
6
- <t-button theme="primary" @click="$Method.handleAdd">
7
- <template #icon>
8
- <IconLucidePlus />
9
- </template>
10
- 添加管理员
11
- </t-button>
12
- </div>
13
- <div class="toolbar-right">
14
- <t-space>
15
- <t-input v-model="$Data.searchKeyword" placeholder="搜索用户名/邮箱" clearable style="width: 200px" @enter="$Method.handleSearch" />
16
- <t-select v-model="$Data.searchState" placeholder="状态" clearable style="width: 120px" :options="$Data.stateOptions" @change="$Method.handleSearch" />
17
- <t-button theme="default" @click="$Method.handleSearch">
18
- <template #icon>
19
- <IconLucideSearch />
20
- </template>
21
- 搜索
22
- </t-button>
23
- <t-button theme="default" @click="$Method.handleReset">
24
- <template #icon>
25
- <IconLucideRotateCw />
26
- </template>
27
- 重置
28
- </t-button>
29
- </t-space>
30
- </div>
31
- </div>
32
-
33
- <!-- 中:数据表格 -->
34
- <div class="table-wrapper">
35
- <t-table :data="$Data.userList" :columns="$Data.columns" row-key="id" :loading="$Data.loading" bordered stripe hover max-height="100%">
36
- <template #state="{ row }">
37
- <t-tag v-if="row.state === 1" type="success">正常</t-tag>
38
- <t-tag v-else-if="row.state === 2" type="warning">禁用</t-tag>
39
- <t-tag v-else type="danger">已删除</t-tag>
40
- </template>
41
-
42
- <template #lastLoginTime="{ row }">
43
- <span v-if="row.lastLoginTime">{{ new Date(Number(row.lastLoginTime)).toLocaleString() }}</span>
44
- <span v-else>-</span>
45
- </template>
46
-
47
- <template #operation="{ row }">
48
- <t-space>
49
- <t-link theme="primary" @click="$Method.handleRole(row)">分配角色</t-link>
50
- <t-link theme="warning" @click="$Method.handleEdit(row)">编辑</t-link>
51
- <t-link theme="danger" @click="$Method.handleDelete(row)">删除</t-link>
52
- </t-space>
53
- </template>
54
- </t-table>
55
- </div>
56
-
57
- <!-- 下:分页栏 -->
58
- <div class="pagination-wrapper">
59
- <t-pagination v-model="$Data.pagination.current" v-model:page-size="$Data.pagination.pageSize" :total="$Data.pagination.total" :page-size-options="[10, 20, 50, 100]" show-jumper show-page-size @change="$Method.onPageChange" />
60
- </div>
61
-
62
- <!-- 角色分配对话框 -->
63
- <t-dialog v-model:visible="$Data.roleVisible" header="分配角色" width="600px" :on-confirm="$Method.handleRoleSubmit">
64
- <div class="role-dialog">
65
- <div class="user-info">
66
- <t-tag type="primary">{{ $Data.currentUser.username }}</t-tag>
67
- <span class="user-email">{{ $Data.currentUser.email }}</span>
68
- </div>
69
- <t-divider />
70
- <t-select v-model="$Data.checkedRoleCode" :options="$Data.roleOptions" placeholder="请选择角色" />
71
- </div>
72
- </t-dialog>
73
- </div>
74
- </template>
75
-
76
- <script setup>
77
- import { $Http } from '@/plugins/http';
78
-
79
- // 响应式数据
80
- const $Data = $ref({
81
- loading: false,
82
- userList: [],
83
- pagination: {
84
- current: 1,
85
- pageSize: 10,
86
- total: 0
87
- },
88
- searchKeyword: '',
89
- searchState: undefined,
90
- stateOptions: [
91
- { label: '正常', value: 1 },
92
- { label: '禁用', value: 2 },
93
- { label: '已删除', value: 0 }
94
- ],
95
- roleVisible: false,
96
- currentUser: {},
97
- columns: [
98
- { colKey: 'username', title: '用户名', width: 150 },
99
- { colKey: 'email', title: '邮箱', width: 200 },
100
- { colKey: 'nickname', title: '昵称', width: 150 },
101
- { colKey: 'state', title: '状态', width: 100 },
102
- { colKey: 'roleCode', title: '角色', width: 120 },
103
- { colKey: 'lastLoginTime', title: '最后登录', width: 180 },
104
- { colKey: 'operation', title: '操作', width: 200, fixed: 'right' }
105
- ],
106
- roleOptions: [],
107
- checkedRoleCode: ''
108
- });
109
-
110
- // 方法集合
111
- const $Method = {
112
- // 加载用户列表
113
- async loadUserList() {
114
- $Data.loading = true;
115
- try {
116
- const res = await $Http('/addon/admin/list', {
117
- page: $Data.pagination.current,
118
- limit: $Data.pagination.pageSize
119
- });
120
- if (res.code === 0 && res.data) {
121
- // getList 返回分页对象 { list, total, page, limit, pages }
122
- $Data.userList = res.data.list || [];
123
- $Data.pagination.total = res.data.total || 0;
124
- }
125
- } catch (error) {
126
- MessagePlugin.error('加载用户列表失败');
127
- console.error(error);
128
- } finally {
129
- $Data.loading = false;
130
- }
131
- },
132
-
133
- // 分页变化
134
- onPageChange(pageInfo) {
135
- $Data.pagination.current = pageInfo.current;
136
- $Data.pagination.pageSize = pageInfo.pageSize;
137
- $Method.loadUserList();
138
- },
139
-
140
- // 搜索
141
- handleSearch() {
142
- $Data.pagination.current = 1;
143
- $Method.loadUserList();
144
- },
145
-
146
- // 重置
147
- handleReset() {
148
- $Data.searchKeyword = '';
149
- $Data.searchState = undefined;
150
- $Data.pagination.current = 1;
151
- $Method.loadUserList();
152
- },
153
-
154
- // 添加管理员
155
- handleAdd() {
156
- MessagePlugin.info('添加管理员功能待开发');
157
- },
158
-
159
- // 编辑管理员
160
- handleEdit(row) {
161
- MessagePlugin.info(`编辑管理员:${row.username}`);
162
- },
163
-
164
- // 删除管理员
165
- handleDelete(row) {
166
- DialogPlugin.confirm({
167
- header: '确认删除',
168
- body: `确定要删除管理员 "${row.username}" 吗?`,
169
- onConfirm: async () => {
170
- try {
171
- // TODO: 调用删除接口
172
- MessagePlugin.success('删除成功');
173
- await $Method.loadUserList();
174
- } catch (error) {
175
- MessagePlugin.error('删除失败');
176
- console.error(error);
177
- }
178
- }
179
- });
180
- },
181
-
182
- // 加载角色列表
183
- async loadRoleList() {
184
- try {
185
- const res = await $Http('/addon/admin/role/list', {});
186
- if (res.code === 0 && res.data) {
187
- // getList 返回分页对象
188
- const roleList = res.data.list || res.data || [];
189
- $Data.roleOptions = roleList
190
- .filter((role) => role.state === 1)
191
- .map((role) => ({
192
- label: role.name,
193
- value: role.code
194
- }));
195
- }
196
- } catch (error) {
197
- MessagePlugin.error('加载角色列表失败');
198
- console.error(error);
199
- }
200
- },
201
-
202
- // 打开角色分配对话框
203
- async handleRole(row) {
204
- $Data.currentUser = row;
205
- $Data.roleVisible = true;
206
-
207
- // 加载角色列表
208
- await $Method.loadRoleList();
209
-
210
- // 加载该用户已有的角色
211
- try {
212
- const res = await $Http('/addon/admin/roleDetail', { adminId: row.id });
213
- if (res.code === 0 && res.data) {
214
- $Data.checkedRoleCode = res.data.roleCode || '';
215
- }
216
- } catch (error) {
217
- MessagePlugin.error('加载用户角色失败');
218
- console.error(error);
219
- }
220
- },
221
-
222
- // 提交角色分配
223
- async handleRoleSubmit() {
224
- if (!$Data.checkedRoleCode) {
225
- MessagePlugin.warning('请选择角色');
226
- return false;
227
- }
228
-
229
- try {
230
- const res = await $Http('/addon/admin/roleSave', {
231
- adminId: $Data.currentUser.id,
232
- roleCode: $Data.checkedRoleCode
233
- });
234
-
235
- if (res.code === 0) {
236
- MessagePlugin.success('角色分配成功');
237
- $Data.roleVisible = false;
238
- await $Method.loadUserList();
239
- return true;
240
- } else {
241
- MessagePlugin.error(res.msg || '分配失败');
242
- return false;
243
- }
244
- } catch (error) {
245
- MessagePlugin.error('分配失败');
246
- console.error(error);
247
- return false;
248
- }
249
- }
250
- };
251
-
252
- // 初始化加载
253
- $Method.loadUserList();
254
- </script>
255
-
256
- <style scoped lang="scss">
257
- .user-manage {
258
- height: 100%;
259
- display: flex;
260
- flex-direction: column;
261
- gap: 16px;
262
- padding: 16px;
263
- overflow: hidden; // 防止外层滚动
264
- }
265
-
266
- // 上:工具栏
267
- .toolbar {
268
- flex-shrink: 0; // 不允许收缩
269
- display: flex;
270
- justify-content: space-between;
271
- align-items: center;
272
- padding: 16px;
273
- background: $bg-color-container;
274
- border-radius: $border-radius;
275
- box-shadow: $shadow-card;
276
-
277
- .toolbar-left {
278
- display: flex;
279
- gap: 12px;
280
- }
281
-
282
- .toolbar-right {
283
- display: flex;
284
- gap: 12px;
285
- }
286
- }
287
-
288
- // 中:表格区域(撑满剩余空间并支持滚动)
289
- .table-wrapper {
290
- flex: 1; // 占据剩余空间
291
- overflow: hidden; // 隐藏超出部分
292
- display: flex;
293
- flex-direction: column;
294
- background: $bg-color-container;
295
- border-radius: $border-radius;
296
- box-shadow: $shadow-card;
297
- }
298
-
299
- // 下:分页栏
300
- .pagination-wrapper {
301
- flex-shrink: 0; // 不允许收缩
302
- display: flex;
303
- justify-content: flex-end;
304
- padding: 16px;
305
- background: $bg-color-container;
306
- border-radius: $border-radius;
307
- box-shadow: $shadow-card;
308
- }
309
-
310
- .role-dialog {
311
- .user-info {
312
- display: flex;
313
- align-items: center;
314
- gap: 12px;
315
- margin-bottom: 16px;
316
-
317
- .user-email {
318
- color: $text-secondary;
319
- }
320
- }
321
- }
322
- </style>