This commit is contained in:
Ray.Hao
2025-04-02 20:50:13 +08:00
25 changed files with 104 additions and 108 deletions

View File

@@ -10,9 +10,9 @@
<img src="https://img.shields.io/badge/Author-有来开源组织-orange.svg"/>
</a>
<a href="https://gitee.com/youlaiorg/youlai-boot" target="_blank">
<a href="https://gitee.com/youlaiorg/vue3-element-admin" target="_blank">
<img alt="有来技术" src="https://gitee.com/youlaiorg/vue3-element-admin/badge/star.svg"/>
</a>
</a>
<a href="https://github.com/youlaitech/vue3-element-admin" target="_blank">
<img alt="有来技术" src="https://img.shields.io/github/stars/youlaitech/vue3-element-admin.svg?style=social&label=Stars"/>
</a>
@@ -25,7 +25,7 @@
![](https://foruda.gitee.com/images/1708618984641188532/a7cca095_716974.png "rainbow.png")
<div align="center">
<a target="_blank" href="http://vue3.youlai.tech">👀 Live Preview</a> | <a target="_blank" href="https://juejin.cn/post/7228990409909108793">📖 Read Documentation</a> | 🌐 <a href="./README.md">中文
<a target="_blank" href="http://vue3.youlai.tech">👀 Live Preview</a> | <a target="_blank" href="https://juejin.cn/post/7228990409909108793">📖 Read Documentation</a> | <a target="_blank" href="https://www.youlai.tech/vue3-element-admin">🌐 Official Website</a> | 🌐 <a href="./README.md">中文
</div>

View File

@@ -10,8 +10,8 @@
<img src="https://img.shields.io/badge/Author-有来开源组织-orange.svg"/>
</a>
<a href="https://gitee.com/youlaiorg/youlai-boot" target="_blank">
<img alt="有来技术" src="https://gitee.com/youlaiorg/vue3-element-admin/badge/star.svg"/>
<a href="https://gitee.com/youlaiorg/vue3-element-admin" target="_blank">
<img alt="有来技术" src="https://gitee.com/youlaiorg/vue3-element-admin/badge/star.svg"/>
</a>
<a href="https://github.com/youlaitech/vue3-element-admin" target="_blank">
<img alt="有来技术" src="https://img.shields.io/github/stars/youlaitech/vue3-element-admin.svg?style=social&label=Stars"/>
@@ -26,7 +26,7 @@
<div align="center">
<a target="_blank" href="https://vue.youlai.tech">🖥️ 在线预览</a> | <a target="_blank" href="https://juejin.cn/post/7228990409909108793">📑 阅读文档</a> | <a href="./README.en-US.md">💬 English
<a target="_blank" href="https://vue.youlai.tech">🖥️ 在线预览</a> | <a target="_blank" href="https://juejin.cn/post/7228990409909108793">📑 阅读文档</a>| <a target="_blank" href="https://www.youlai.tech//vue3-element-admin">🌐 官网</a> | <a href="./README.en-US.md">💬 English
</div>
@@ -57,20 +57,39 @@
| 项目 | Gitee | Github | GitCode|
| ---- | ----| ---- | ---- |
| 前端 | [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) | [vue3-element-admin](https://gitcode.com/youlai/vue3-element-admin) |
| 精简版 | [vue3-element-template](https://gitee.com/youlaiorg/vue3-element-template) | [vue3-element-template](https://github.com/youlaitech/vue3-element-template) |-|
| 后端 | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/haoxianrui/youlai-boot.git) |[youlai-boot](https://gitcode.com/youlai/youlai-boot.git)|
| vue3-element-admin 标准版| [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) | [vue3-element-admin](https://gitcode.com/youlai/vue3-element-admin) |
| vue3-element-admin 精简版 | [vue3-element-template](https://gitee.com/youlaiorg/vue3-element-template) | [vue3-element-template](https://github.com/youlaitech/vue3-element-template) |-|
| Java 后端 | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/haoxianrui/youlai-boot.git) |[youlai-boot](https://gitcode.com/youlai/youlai-boot.git)|
| Node 后端 | [youlai-nest](https://gitee.com/youlaiorg/youlai-nest) | [youlai-nest](https://github.com/haoxianrui/youlai-nest.git) |[youlai-nest](https://gitcode.com/youlai/youlai-nest.git)|
## 环境准备
| 环境 | 名称版本 | 下载地址 |
| -------------------- | :----------------------------------------------------------- | ------------------------------------------------------------ |
| **开发工具** | VSCode | [下载](https://code.visualstudio.com/Download) |
| **运行环境** | Node ≥18 (其中 20.6.0 版本不可用) | [下载](http://nodejs.cn/download) |
## 项目文档
| 文档名称 | 访问地址 |
|---------------|-------------------------------------------------------------------------------------------|
| 项目 0 到 1 | [基于 Vue3 + Vite + TypeScript + Element-Plus 从0到1搭建后台管理系统](https://blog.csdn.net/u013737132/article/details/130191394) |
| 官方文档 | [https://www.youlai.tech/vue3-element-admin/](https://www.youlai.tech/vue3-element-admin/) |
| 代码规范 | [ESLint V9 + Prettier + Stylelint + EditorConfig 约束和统一前端代码规范](https://youlai.blog.csdn.net/article/details/145608723) |
| Git 规范 | [Husky + Lint-staged + Commitlint + Commitizen + cz-git 配置 Git 提交规范](https://youlai.blog.csdn.net/article/details/145615236) |
| 在线接口文档 | [https://www.apifox.cn/apidoc](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5) |
## 项目启动
- **环境准备**
| 环境类型 | 版本要求 | 下载链接 |
|----------------|-----------------------------|-----------------------------|
| **开发工具** | Visual Studio Code (最新版) | [官方下载](https://code.visualstudio.com/Download) |
| **运行环境** | Node.js 18.x (推荐18.16.1) | [中文镜像](https://npmmirror.com/mirrors/node/v18.16.1/) |
> ⚠️ 注意Node.js 20.6.0版本存在兼容性问题,请勿使用
- **快速开始**
```bash
# 克隆代码
git clone https://gitee.com/youlaiorg/vue3-element-admin.git
@@ -92,7 +111,6 @@ pnpm run dev
```
## 项目部署
执行 `pnpm run build` 命令后,项目将被打包并生成 `dist` 目录。接下来,将 `dist` 目录下的文件上传到服务器 `/usr/share/nginx/html` 目录下,并配置 Nginx 进行反向代理。
@@ -161,14 +179,6 @@ server {
如果有其他问题或者建议,建议 [ISSUE](https://gitee.com/youlaiorg/vue3-element-admin/issues/new)
## 项目文档
- [基于 Vue3 + Vite + TypeScript + Element-Plus 从0到1搭建后台管理系统](https://blog.csdn.net/u013737132/article/details/130191394)
- [ESLint+Prettier+Stylelint+EditorConfig 约束和统一前端代码规范](https://youlai.blog.csdn.net/article/details/145608723)
- [Husky + Lint-staged + Commitlint + Commitizen + cz-git 配置 Git 提交规范](https://youlai.blog.csdn.net/article/details/145615236)
## 提交规范
执行 `pnpm run commit` 唤起 git commit 交互,根据提示完成信息的输入和选择。
@@ -191,11 +201,8 @@ Thanks to all the contributors!
## 加群交流
> **关注「有来技术」公众号,点击菜单“交流群”获取加群二维码。**
>
> 如果二维码过期,请加微信(haoxianrui)备注「前端」、「后端」或「全栈」拉你进群。
>
> 交流群仅限技术交流,为过滤广告营销暂设此门槛,感谢理解与配合
关注「有来技术」公众号,点击菜单 **交流群** 获取加群二维码(此举防止广告进群,感谢理解和支持)。
![有来技术公众号二维码](https://foruda.gitee.com/images/1737108820762592766/3390ed0d_716974.png)
② 直接添加微信 **`haoxianrui`** 备注「前端/后端/全栈」。
![有来技术公众号](https://foruda.gitee.com/images/1737108820762592766/3390ed0d_716974.png)

View File

@@ -1,6 +1,6 @@
{
"name": "vue3-element-admin",
"version": "2.25.1",
"version": "2.25.2",
"private": true,
"type": "module",
"scripts": {

View File

@@ -110,7 +110,7 @@ export interface TablePageVO {
/** 代码生成配置表单 */
export interface GenConfigForm {
/** 主键 */
id?: number;
id?: string;
/** 表名 */
tableName?: string;
@@ -131,7 +131,7 @@ export interface GenConfigForm {
author?: string;
/** 上级菜单 */
parentMenuId?: number;
parentMenuId?: string;
/** 后端应用名 */
backendAppName?: string;
@@ -145,7 +145,7 @@ export interface GenConfigForm {
/** 字段配置 */
export interface FieldConfig {
/** 主键 */
id?: number;
id?: string;
/** 列名 */
columnName?: string;

View File

@@ -13,7 +13,7 @@ const ConfigAPI = {
},
/** 系统配置表单数据 */
getFormData(id: number) {
getFormData(id: string) {
return request<any, ConfigForm>({
url: `${CONFIG_BASE_URL}/${id}/form`,
method: "get",
@@ -30,7 +30,7 @@ const ConfigAPI = {
},
/** 更新系统配置 */
update(id: number, data: ConfigForm) {
update(id: string, data: ConfigForm) {
return request({
url: `${CONFIG_BASE_URL}/${id}`,
method: "put",
@@ -43,7 +43,7 @@ const ConfigAPI = {
*
* @param ids 系统配置ID
*/
deleteById(id: number) {
deleteById(id: string) {
return request({
url: `${CONFIG_BASE_URL}/${id}`,
method: "delete",
@@ -69,7 +69,7 @@ export interface ConfigPageQuery extends PageQuery {
/** 系统配置表单对象 */
export interface ConfigForm {
/** 主键 */
id?: number;
id?: string;
/** 配置名称 */
configName?: string;
/** 配置键 */
@@ -83,7 +83,7 @@ export interface ConfigForm {
/** 系统配置分页对象 */
export interface ConfigPageVO {
/** 主键 */
id?: number;
id?: string;
/** 配置名称 */
configName?: string;
/** 配置键 */

View File

@@ -31,7 +31,7 @@ const DeptAPI = {
* @param id 部门ID
* @returns 部门表单数据
*/
getFormData(id: number) {
getFormData(id: string) {
return request<any, DeptForm>({
url: `${DEPT_BASE_URL}/${id}/form`,
method: "get",
@@ -98,13 +98,13 @@ export interface DeptVO {
/** 创建时间 */
createTime?: Date;
/** 部门ID */
id?: number;
id?: string;
/** 部门名称 */
name?: string;
/** 部门编号 */
code?: string;
/** 父部门ID */
parentId?: number;
parentid?: string;
/** 排序 */
sort?: number;
/** 状态(1:启用0:禁用) */

View File

@@ -39,7 +39,7 @@ const DictAPI = {
* @param id 字典ID
* @returns 字典表单数据
*/
getFormData(id: number) {
getFormData(id: string) {
return request<any, ResponseData<DictForm>>({
url: `${DICT_BASE_URL}/${id}/form`,
method: "get",
@@ -65,7 +65,7 @@ const DictAPI = {
* @param id 字典ID
* @param data 字典表单数据
*/
update(id: number, data: DictForm) {
update(id: string, data: DictForm) {
return request({
url: `${DICT_BASE_URL}/${id}`,
method: "put",
@@ -129,7 +129,7 @@ const DictAPI = {
* @param id 字典项ID
* @returns 字典项表单数据
*/
getDictItemFormData(dictCode: string, id: number) {
getDictItemFormData(dictCode: string, id: string) {
return request<any, ResponseData<DictItemForm>>({
url: `${DICT_BASE_URL}/${dictCode}/items/${id}/form`,
method: "get",
@@ -139,7 +139,7 @@ const DictAPI = {
/**
* 修改字典项
*/
updateDictItem(dictCode: string, id: number, data: DictItemForm) {
updateDictItem(dictCode: string, id: string, data: DictItemForm) {
return request({
url: `${DICT_BASE_URL}/${dictCode}/items/${id}`,
method: "put",
@@ -182,7 +182,7 @@ export interface DictPageVO {
/**
* 字典ID
*/
id: number;
id: string;
/**
* 字典名称
*/
@@ -204,7 +204,7 @@ export interface DictForm {
/**
* 字典ID
*/
id?: number;
id?: string;
/**
* 字典名称
*/
@@ -241,7 +241,7 @@ export interface DictItemPageVO {
/**
* 字典ID
*/
id: number;
id: string;
/**
* 字典编码
*/
@@ -271,7 +271,7 @@ export interface DictItemForm {
/**
* 字典ID
*/
id?: number;
id?: string;
/**
* 字典编码
*/

View File

@@ -61,7 +61,7 @@ export interface LogPageQuery extends PageQuery {
*/
export interface LogPageVO {
/** 主键 */
id: number;
id: string;
/** 日志模块 */
module: string;
/** 日志内容 */

View File

@@ -91,7 +91,7 @@ const MenuAPI = {
* @param id 菜单ID
* @returns 请求结果
*/
deleteById(id: number) {
deleteById(id: string) {
return request({
url: `${MENU_BASE_URL}/${id}`,
method: "delete",

View File

@@ -15,10 +15,10 @@ const NoticeAPI = {
/**
* 获取通知公告表单数据
*
* @param id NoticeID
* @returns Notice表单数据
* @param id 通知
* @returns 通知表单数据
*/
getFormData(id: number) {
getFormData(id: string) {
return request<any, NoticeForm>({
url: `${NOTICE_BASE_URL}/${id}/form`,
method: "get",
@@ -28,7 +28,7 @@ const NoticeAPI = {
/**
* 添加通知公告
*
* @param data Notice表单数据
* @param data 通知表单数据
* @returns
*/
create(data: NoticeForm) {
@@ -42,10 +42,10 @@ const NoticeAPI = {
/**
* 更新通知公告
*
* @param id NoticeID
* @param data Notice表单数据
* @param id 通知ID
* @param data 通知表单数据
*/
update(id: number, data: NoticeForm) {
update(id: string, data: NoticeForm) {
return request({
url: `${NOTICE_BASE_URL}/${id}`,
method: "put",
@@ -71,7 +71,7 @@ const NoticeAPI = {
* @param id 被发布的通知公告id
* @returns
*/
publish(id: number) {
publish(id: string) {
return request({
url: `${NOTICE_BASE_URL}/${id}/publish`,
method: "put",
@@ -84,7 +84,7 @@ const NoticeAPI = {
* @param id 撤回的通知id
* @returns
*/
revoke(id: number) {
revoke(id: string) {
return request({
url: `${NOTICE_BASE_URL}/${id}/revoke`,
method: "put",
@@ -134,7 +134,7 @@ export interface NoticePageQuery extends PageQuery {
/** 通知公告表单对象 */
export interface NoticeForm {
id?: number;
id?: string;
/** 通知标题 */
title?: string;
/** 通知内容 */

View File

@@ -25,8 +25,8 @@ const RoleAPI = {
* @param roleId 角色ID
* @returns 角色的菜单ID集合
*/
getRoleMenuIds(roleId: number) {
return request<any, number[]>({
getRoleMenuIds(roleId: string) {
return request<any, string[]>({
url: `${ROLE_BASE_URL}/${roleId}/menuIds`,
method: "get",
});
@@ -38,7 +38,7 @@ const RoleAPI = {
* @param roleId 角色ID
* @param data 菜单ID集合
*/
updateRoleMenus(roleId: number, data: number[]) {
updateRoleMenus(roleId: string, data: number[]) {
return request({
url: `${ROLE_BASE_URL}/${roleId}/menus`,
method: "put",
@@ -52,7 +52,7 @@ const RoleAPI = {
* @param id 角色ID
* @returns 角色表单数据
*/
getFormData(id: number) {
getFormData(id: string) {
return request<any, RoleForm>({
url: `${ROLE_BASE_URL}/${id}/form`,
method: "get",
@@ -74,7 +74,7 @@ const RoleAPI = {
* @param id 角色ID
* @param data 角色表单数据
*/
update(id: number, data: RoleForm) {
update(id: string, data: RoleForm) {
return request({
url: `${ROLE_BASE_URL}/${id}`,
method: "put",
@@ -105,10 +105,10 @@ export interface RolePageQuery extends PageQuery {
/** 角色分页对象 */
export interface RolePageVO {
/** 角色ID */
id?: string;
/** 角色编码 */
code?: string;
/** 角色ID */
id?: number;
/** 角色名称 */
name?: string;
/** 排序 */
@@ -124,7 +124,7 @@ export interface RolePageVO {
/** 角色表单对象 */
export interface RoleForm {
/** 角色ID */
id?: number;
id?: string;
/** 角色编码 */
code?: string;
/** 数据权限 */

View File

@@ -34,7 +34,7 @@ const UserAPI = {
* @param userId 用户ID
* @returns 用户表单详情
*/
getFormData(userId: number) {
getFormData(userId: string) {
return request<any, UserForm>({
url: `${USER_BASE_URL}/${userId}/form`,
method: "get",
@@ -60,7 +60,7 @@ const UserAPI = {
* @param id 用户ID
* @param data 用户表单数据
*/
update(id: number, data: UserForm) {
update(id: string, data: UserForm) {
return request({
url: `${USER_BASE_URL}/${id}`,
method: "put",
@@ -74,7 +74,7 @@ const UserAPI = {
* @param id 用户ID
* @param password 新密码
*/
resetPassword(id: number, password: string) {
resetPassword(id: string, password: string) {
return request({
url: `${USER_BASE_URL}/${id}/password/reset`,
method: "put",
@@ -123,7 +123,7 @@ const UserAPI = {
* @param deptId 部门ID
* @param file 导入文件
*/
import(deptId: number, file: File) {
import(deptId: string, file: File) {
const formData = new FormData();
formData.append("file", file);
return request<any, ExcelResult>({
@@ -215,7 +215,7 @@ export default UserAPI;
/** 登录用户信息 */
export interface UserInfo {
/** 用户ID */
userId?: number;
userId?: string;
/** 用户名 */
username?: string;
@@ -244,7 +244,7 @@ export interface UserPageQuery extends PageQuery {
status?: number;
/** 部门ID */
deptId?: number;
deptId?: string;
/** 开始时间 */
createTime?: [string, string];
@@ -253,7 +253,7 @@ export interface UserPageQuery extends PageQuery {
/** 用户分页对象 */
export interface UserPageVO {
/** 用户ID */
id: number;
id: string;
/** 用户头像URL */
avatar?: string;
/** 创建时间 */
@@ -278,16 +278,16 @@ export interface UserPageVO {
/** 用户表单类型 */
export interface UserForm {
/** 用户ID */
id?: string;
/** 用户头像 */
avatar?: string;
/** 部门ID */
deptId?: number;
deptId?: string;
/** 邮箱 */
email?: string;
/** 性别 */
gender?: number;
/** 用户ID */
id?: number;
/** 手机号 */
mobile?: string;
/** 昵称 */
@@ -303,7 +303,7 @@ export interface UserForm {
/** 个人中心用户信息 */
export interface UserProfileVO {
/** 用户ID */
id?: number;
id?: string;
/** 用户名 */
username?: string;
@@ -336,7 +336,7 @@ export interface UserProfileVO {
/** 个人中心用户信息表单 */
export interface UserProfileForm {
/** 用户ID */
id?: number;
id?: string;
/** 用户名 */
username?: string;

View File

@@ -20,7 +20,7 @@ const contentConfig: IContentConfig<UserPageQuery> = {
},
deleteAction: UserAPI.deleteByIds,
importAction(file) {
return UserAPI.import(1, file);
return UserAPI.import("1", file);
},
exportAction: UserAPI.export,
importTemplate: UserAPI.downloadTemplate,

View File

@@ -12,7 +12,7 @@ const modalConfig: IModalConfig<UserForm> = {
},
pk: "id",
formAction: function (data) {
return UserAPI.update(data.id as number, data);
return UserAPI.update(data.id as string, data);
},
beforeSubmit(data) {
console.log("提交之前处理", data);

View File

@@ -4,7 +4,7 @@ import selectConfig from "./config/select";
import { useDictStore } from "@/store";
const dictStore = useDictStore();
interface IUser {
id: number;
id: string;
username: string;
nickname: string;
mobile: string;

View File

@@ -198,7 +198,7 @@ function handleSelectionChange(selection: any) {
}
// 打开系统配置弹窗
function handleOpenDialog(id?: number) {
function handleOpenDialog(id?: string) {
dialog.visible = true;
if (id) {
dialog.title = "修改系统配置";
@@ -259,7 +259,7 @@ function handleCloseDialog() {
}
// 删除系统配置
function handleDelete(id: number) {
function handleDelete(id: string) {
ElMessageBox.confirm("确认删除该项配置?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",

View File

@@ -213,7 +213,7 @@ function handleSelectionChange(selection: any) {
* @param parentId 父部门ID
* @param deptId 部门ID
*/
async function handleOpenDialog(parentId?: string, deptId?: number) {
async function handleOpenDialog(parentId?: string, deptId?: string) {
// 加载部门下拉数据
const data = await DeptAPI.getOptions();
deptOptions.value = [

View File

@@ -129,11 +129,6 @@
</template>
<script setup lang="ts">
defineOptions({
name: "DictItem",
inherititems: false,
});
import DictAPI, { DictItemPageQuery, DictItemPageVO, DictItemForm } from "@/api/system/dict.api";
const route = useRoute();
@@ -276,10 +271,4 @@ function handleDelete(id?: number) {
onMounted(() => {
handleQuery();
});
// 同一路由参数变化时更新数据
onBeforeRouteUpdate((to) => {
queryParams.dictCode = to.query.dictCode as string;
handleQuery();
});
</script>

View File

@@ -198,7 +198,7 @@ function handleAddClick() {
*
* @param id 字典ID
*/
function handleEditClick(id: number) {
function handleEditClick(id: string) {
dialog.visible = true;
dialog.title = "修改字典";
DictAPI.getFormData(id).then((data) => {

View File

@@ -487,7 +487,7 @@ function handleSubmit() {
}
// 删除菜单
function handleDelete(menuId: number) {
function handleDelete(menuId: string) {
if (!menuId) {
ElMessage.warning("请勾选删除项");
return false;

View File

@@ -341,7 +341,7 @@ function handleSelectionChange(selection: any) {
}
// 打开通知公告弹窗
function handleOpenDialog(id?: number) {
function handleOpenDialog(id?: string) {
UserAPI.getOptions().then((data) => {
userOptions.value = data;
});
@@ -359,7 +359,7 @@ function handleOpenDialog(id?: number) {
}
// 发布通知公告
function handlePublish(id: number) {
function handlePublish(id: string) {
NoticeAPI.publish(id).then(() => {
ElMessage.success("发布成功");
handleQuery();
@@ -367,7 +367,7 @@ function handlePublish(id: number) {
}
// 撤回通知公告
function handleRevoke(id: number) {
function handleRevoke(id: string) {
NoticeAPI.revoke(id).then(() => {
ElMessage.success("撤回成功");
handleQuery();

View File

@@ -257,7 +257,7 @@ const rules = reactive({
// 选中的角色
interface CheckedRole {
id?: number;
id?: string;
name?: string;
}
const checkedRole = ref<CheckedRole>({});
@@ -294,7 +294,7 @@ function handleSelectionChange(selection: any) {
}
// 打开角色弹窗
function handleOpenDialog(roleId?: number) {
function handleOpenDialog(roleId?: string) {
dialog.visible = true;
if (roleId) {
dialog.title = "修改角色";

View File

@@ -24,7 +24,7 @@
import DeptAPI from "@/api/system/dept.api";
const props = defineProps({
modelValue: {
type: [Number],
type: [String, Number],
default: undefined,
},
});

View File

@@ -163,7 +163,7 @@ const handleUpload = async () => {
}
try {
const result = await UserAPI.import(1, importFormData.files[0].raw as File);
const result = await UserAPI.import("1", importFormData.files[0].raw as File);
if (result.code === ResultEnum.SUCCESS && result.invalidCount === 0) {
ElMessage.success("导入成功,导入数据:" + result.validCount + "条");
emit("import-success");

View File

@@ -360,7 +360,7 @@ function hancleResetPassword(row: UserPageVO) {
*
* @param id 用户ID
*/
async function handleOpenDialog(id?: number) {
async function handleOpenDialog(id?: string) {
dialog.visible = true;
// 加载角色下拉数据源
roleOptions.value = await RoleAPI.getOptions();