feat(codegen): 代码生成支持本地写入和代码优化

This commit is contained in:
Ray.Hao
2025-08-21 18:28:38 +08:00
parent 72b89e2894
commit 07206576a8
61 changed files with 1045 additions and 1087 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "vue3-element-admin",
"description": "Vue3 + Vite + TypeScript + Element-Plus 的后台管理模板vue-element-admin 的 Vue3 版本",
"version": "3.2.2",
"version": "3.3.0",
"private": true,
"type": "module",
"scripts": {

View File

@@ -30,10 +30,11 @@ const GeneratorAPI = {
},
/** 获取代码生成预览数据 */
getPreviewData(tableName: string) {
getPreviewData(tableName: string, pageType?: "classic" | "curd") {
return request<any, GeneratorPreviewVO[]>({
url: `${GENERATOR_BASE_URL}/${tableName}/preview`,
method: "get",
params: pageType ? { pageType } : undefined,
});
},
@@ -50,10 +51,11 @@ const GeneratorAPI = {
* @param url
* @param fileName
*/
download(tableName: string) {
download(tableName: string, pageType?: "classic" | "curd") {
return request({
url: `${GENERATOR_BASE_URL}/${tableName}/download`,
method: "get",
params: pageType ? { pageType } : undefined,
responseType: "blob",
}).then((response) => {
const fileName = decodeURI(
@@ -140,6 +142,12 @@ export interface GenConfigForm {
/** 字段配置列表 */
fieldConfigs?: FieldConfig[];
/** 页面类型 classic|curd */
pageType?: "classic" | "curd";
/** 要移除的表前缀,如 sys_ */
removeTablePrefix?: string;
}
/** 字段配置 */

View File

@@ -1,25 +1,17 @@
import request from "@/utils/request";
const FileAPI = {
/**
*
*
* @param formData
*/
/** 上传文件 */
upload(formData: FormData) {
return request<any, FileInfo>({
url: "/api/v1/files",
method: "post",
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
headers: { "Content-Type": "multipart/form-data" },
});
},
/**
*
*/
/** 上传文件(传入 File */
uploadFile(file: File) {
const formData = new FormData();
formData.append("file", file);
@@ -27,17 +19,11 @@ const FileAPI = {
url: "/api/v1/files",
method: "post",
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
headers: { "Content-Type": "multipart/form-data" },
});
},
/**
*
*
* @param filePath
*/
/** 删除文件 */
delete(filePath?: string) {
return request({
url: "/api/v1/files",
@@ -46,11 +32,7 @@ const FileAPI = {
});
},
/**
*
* @param url
* @param fileName
*/
/** 下载文件 */
download(url: string, fileName?: string) {
return request({
url,
@@ -59,23 +41,18 @@ const FileAPI = {
}).then((res) => {
const blob = new Blob([res.data]);
const a = document.createElement("a");
const url = window.URL.createObjectURL(blob);
a.href = url;
const urlObject = window.URL.createObjectURL(blob);
a.href = urlObject;
a.download = fileName || "下载文件";
a.click();
window.URL.revokeObjectURL(url);
window.URL.revokeObjectURL(urlObject);
});
},
};
export default FileAPI;
/**
* API类型声明
*/
export interface FileInfo {
/** 文件名 */
name: string;
/** 文件路径 */
url: string;
}

View File

@@ -3,7 +3,7 @@ import request from "@/utils/request";
const CONFIG_BASE_URL = "/api/v1/config";
const ConfigAPI = {
/** 系统配置分页 */
/** 获取配置分页数据 */
getPage(queryParams?: ConfigPageQuery) {
return request<any, PageResult<ConfigPageVO[]>>({
url: `${CONFIG_BASE_URL}/page`,
@@ -11,62 +11,38 @@ const ConfigAPI = {
params: queryParams,
});
},
/** 系统配置表单数据 */
/** 获取配置表单数据 */
getFormData(id: string) {
return request<any, ConfigForm>({
url: `${CONFIG_BASE_URL}/${id}/form`,
method: "get",
});
},
/** 新增系统配置 */
/** 新增配置 */
create(data: ConfigForm) {
return request({
url: `${CONFIG_BASE_URL}`,
method: "post",
data,
});
return request({ url: `${CONFIG_BASE_URL}`, method: "post", data });
},
/** 更新系统配置 */
/** 修改配置 */
update(id: string, data: ConfigForm) {
return request({
url: `${CONFIG_BASE_URL}/${id}`,
method: "put",
data,
});
return request({ url: `${CONFIG_BASE_URL}/${id}`, method: "put", data });
},
/**
*
*
* @param ids ID
*/
/** 删除配置 */
deleteById(id: string) {
return request({
url: `${CONFIG_BASE_URL}/${id}`,
method: "delete",
});
return request({ url: `${CONFIG_BASE_URL}/${id}`, method: "delete" });
},
/** 刷新系统配置缓存 */
/** 刷新配置缓存 */
refreshCache() {
return request({
url: `${CONFIG_BASE_URL}/refresh`,
method: "PUT",
});
return request({ url: `${CONFIG_BASE_URL}/refresh`, method: "PUT" });
},
};
export default ConfigAPI;
/** $系统配置分页查询参数 */
export interface ConfigPageQuery extends PageQuery {
/** 搜索关键字 */
keywords?: string;
}
/** 系统配置表单对象 */
export interface ConfigForm {
/** 主键 */
id?: string;
@@ -80,7 +56,6 @@ export interface ConfigForm {
remark?: string;
}
/** 系统配置分页对象 */
export interface ConfigPageVO {
/** 主键 */
id?: string;

View File

@@ -0,0 +1,75 @@
import request from "@/utils/request";
const DEPT_BASE_URL = "/api/v1/dept";
const DeptAPI = {
/** 获取部门树形列表 */
getList(queryParams?: DeptQuery) {
return request<any, DeptVO[]>({ url: `${DEPT_BASE_URL}`, method: "get", params: queryParams });
},
/** 获取部门下拉数据源 */
getOptions() {
return request<any, OptionType[]>({ url: `${DEPT_BASE_URL}/options`, method: "get" });
},
/** 获取部门表单数据 */
getFormData(id: string) {
return request<any, DeptForm>({ url: `${DEPT_BASE_URL}/${id}/form`, method: "get" });
},
/** 新增部门 */
create(data: DeptForm) {
return request({ url: `${DEPT_BASE_URL}`, method: "post", data });
},
/** 修改部门 */
update(id: string, data: DeptForm) {
return request({ url: `${DEPT_BASE_URL}/${id}`, method: "put", data });
},
/** 批量删除部门,多个以英文逗号(,)分割 */
deleteByIds(ids: string) {
return request({ url: `${DEPT_BASE_URL}/${ids}`, method: "delete" });
},
};
export default DeptAPI;
export interface DeptQuery {
/** 搜索关键字 */
keywords?: string;
/** 状态 */
status?: number;
}
export interface DeptVO {
/** 子部门 */
children?: DeptVO[];
/** 创建时间 */
createTime?: Date;
/** 部门ID */
id?: string;
/** 部门名称 */
name?: string;
/** 部门编号 */
code?: string;
/** 父部门ID */
parentid?: string;
/** 排序 */
sort?: number;
/** 状态(1:启用0:禁用) */
status?: number;
/** 修改时间 */
updateTime?: Date;
}
export interface DeptForm {
/** 部门ID(新增不填) */
id?: string;
/** 部门名称 */
name?: string;
/** 部门编号 */
code?: string;
/** 父部门ID */
parentId: string;
/** 排序 */
sort?: number;
/** 状态(1:启用0禁用) */
status?: number;
}

View File

@@ -1,130 +0,0 @@
import request from "@/utils/request";
const DEPT_BASE_URL = "/api/v1/dept";
const DeptAPI = {
/**
* 获取部门列表
*
* @param queryParams 查询参数(可选)
* @returns 部门树形表格数据
*/
getList(queryParams?: DeptQuery) {
return request<any, DeptVO[]>({
url: `${DEPT_BASE_URL}`,
method: "get",
params: queryParams,
});
},
/** 获取部门下拉列表 */
getOptions() {
return request<any, OptionType[]>({
url: `${DEPT_BASE_URL}/options`,
method: "get",
});
},
/**
* 获取部门表单数据
*
* @param id 部门ID
* @returns 部门表单数据
*/
getFormData(id: string) {
return request<any, DeptForm>({
url: `${DEPT_BASE_URL}/${id}/form`,
method: "get",
});
},
/**
* 新增部门
*
* @param data 部门表单数据
* @returns 请求结果
*/
create(data: DeptForm) {
return request({
url: `${DEPT_BASE_URL}`,
method: "post",
data,
});
},
/**
* 修改部门
*
* @param id 部门ID
* @param data 部门表单数据
* @returns 请求结果
*/
update(id: string, data: DeptForm) {
return request({
url: `${DEPT_BASE_URL}/${id}`,
method: "put",
data,
});
},
/**
* 删除部门
*
* @param ids 部门ID多个以英文逗号(,)分隔
* @returns 请求结果
*/
deleteByIds(ids: string) {
return request({
url: `${DEPT_BASE_URL}/${ids}`,
method: "delete",
});
},
};
export default DeptAPI;
/** 部门查询参数 */
export interface DeptQuery {
/** 搜索关键字 */
keywords?: string;
/** 状态 */
status?: number;
}
/** 部门类型 */
export interface DeptVO {
/** 子部门 */
children?: DeptVO[];
/** 创建时间 */
createTime?: Date;
/** 部门ID */
id?: string;
/** 部门名称 */
name?: string;
/** 部门编号 */
code?: string;
/** 父部门ID */
parentid?: string;
/** 排序 */
sort?: number;
/** 状态(1:启用0:禁用) */
status?: number;
/** 修改时间 */
updateTime?: Date;
}
/** 部门表单类型 */
export interface DeptForm {
/** 部门ID(新增不填) */
id?: string;
/** 部门名称 */
name?: string;
/** 部门编号 */
code?: string;
/** 父部门ID */
parentId: string;
/** 排序 */
sort?: number;
/** 状态(1:启用0禁用) */
status?: number;
}

145
src/api/system/dict-api.ts Normal file
View File

@@ -0,0 +1,145 @@
import request from "@/utils/request";
const DICT_BASE_URL = "/api/v1/dicts";
const DictAPI = {
/** 字典分页列表 */
getPage(queryParams: DictPageQuery) {
return request<any, PageResult<DictPageVO[]>>({
url: `${DICT_BASE_URL}/page`,
method: "get",
params: queryParams,
});
},
/** 字典列表 */
getList() {
return request<any, OptionType[]>({ url: `${DICT_BASE_URL}`, method: "get" });
},
/** 字典表单数据 */
getFormData(id: string) {
return request<any, DictForm>({ url: `${DICT_BASE_URL}/${id}/form`, method: "get" });
},
/** 新增字典 */
create(data: DictForm) {
return request({ url: `${DICT_BASE_URL}`, method: "post", data });
},
/** 修改字典 */
update(id: string, data: DictForm) {
return request({ url: `${DICT_BASE_URL}/${id}`, method: "put", data });
},
/** 删除字典 */
deleteByIds(ids: string) {
return request({ url: `${DICT_BASE_URL}/${ids}`, method: "delete" });
},
/** 获取字典项分页列表 */
getDictItemPage(dictCode: string, queryParams: DictItemPageQuery) {
return request<any, PageResult<DictItemPageVO[]>>({
url: `${DICT_BASE_URL}/${dictCode}/items/page`,
method: "get",
params: queryParams,
});
},
/** 获取字典项列表 */
getDictItems(dictCode: string) {
return request<any, DictItemOption[]>({
url: `${DICT_BASE_URL}/${dictCode}/items`,
method: "get",
});
},
/** 新增字典项 */
createDictItem(dictCode: string, data: DictItemForm) {
return request({ url: `${DICT_BASE_URL}/${dictCode}/items`, method: "post", data });
},
/** 获取字典项表单数据 */
getDictItemFormData(dictCode: string, id: string) {
return request<any, DictItemForm>({
url: `${DICT_BASE_URL}/${dictCode}/items/${id}/form`,
method: "get",
});
},
/** 修改字典项 */
updateDictItem(dictCode: string, id: string, data: DictItemForm) {
return request({ url: `${DICT_BASE_URL}/${dictCode}/items/${id}`, method: "put", data });
},
/** 删除字典项 */
deleteDictItems(dictCode: string, ids: string) {
return request({ url: `${DICT_BASE_URL}/${dictCode}/items/${ids}`, method: "delete" });
},
};
export default DictAPI;
export interface DictPageQuery extends PageQuery {
/** 搜索关键字 */
keywords?: string;
/** 状态(1:启用;0:禁用) */
status?: number;
}
export interface DictPageVO {
/** 字典ID */
id: string;
/** 字典名称 */
name: string;
/** 字典编码 */
dictCode: string;
/** 状态(1:启用;0:禁用) */
status: number;
}
export interface DictForm {
/** 字典ID(新增不填) */
id?: string;
/** 字典名称 */
name?: string;
/** 字典编码 */
dictCode?: string;
/** 状态(1:启用;0:禁用) */
status?: number;
/** 备注 */
remark?: string;
}
export interface DictItemPageQuery extends PageQuery {
/** 搜索关键字 */
keywords?: string;
/** 字典编码 */
dictCode?: string;
}
export interface DictItemPageVO {
/** 字典项ID */
id: string;
/** 字典编码 */
dictCode: string;
/** 字典项值 */
value: string;
/** 字典项标签 */
label: string;
/** 状态(1:启用;0:禁用) */
status: number;
/** 排序 */
sort?: number;
}
export interface DictItemForm {
/** 字典项ID(新增不填) */
id?: string;
/** 字典编码 */
dictCode?: string;
/** 字典项值 */
value?: string;
/** 字典项标签 */
label?: string;
/** 状态(1:启用;0:禁用) */
status?: number;
/** 排序 */
sort?: number;
/** 标签类型 */
tagType?: "success" | "warning" | "info" | "primary" | "danger" | "";
}
export interface DictItemOption {
/** 值 */
value: number | string;
/** 标签 */
label: string;
/** 标签类型 */
tagType?: "" | "success" | "info" | "warning" | "danger";
[key: string]: any;
}

View File

@@ -1,310 +0,0 @@
import request from "@/utils/request";
const DICT_BASE_URL = "/api/v1/dicts";
const DictAPI = {
//---------------------------------------------------
// 字典相关接口
//---------------------------------------------------
/**
* 字典分页列表
*
* @param queryParams 查询参数
* @returns 字典分页结果
*/
getPage(queryParams: DictPageQuery) {
return request<any, PageResult<DictPageVO[]>>({
url: `${DICT_BASE_URL}/page`,
method: "get",
params: queryParams,
});
},
/**
* 字典列表
*
* @returns 字典列表
*/
getList() {
return request<any, OptionType[]>({
url: `${DICT_BASE_URL}`,
method: "get",
});
},
/**
* 字典表单数据
*
* @param id 字典ID
* @returns 字典表单数据
*/
getFormData(id: string) {
return request<any, DictForm>({
url: `${DICT_BASE_URL}/${id}/form`,
method: "get",
});
},
/**
* 新增字典
*
* @param data 字典表单数据
*/
create(data: DictForm) {
return request({
url: `${DICT_BASE_URL}`,
method: "post",
data,
});
},
/**
* 修改字典
*
* @param id 字典ID
* @param data 字典表单数据
*/
update(id: string, data: DictForm) {
return request({
url: `${DICT_BASE_URL}/${id}`,
method: "put",
data,
});
},
/**
* 删除字典
*
* @param ids 字典ID多个以英文逗号(,)分隔
*/
deleteByIds(ids: string) {
return request({
url: `${DICT_BASE_URL}/${ids}`,
method: "delete",
});
},
//---------------------------------------------------
// 字典项相关接口
//---------------------------------------------------
/**
* 获取字典分页列表
*
* @param queryParams 查询参数
* @returns 字典分页结果
*/
getDictItemPage(dictCode: string, queryParams: DictItemPageQuery) {
return request<any, PageResult<DictItemPageVO[]>>({
url: `${DICT_BASE_URL}/${dictCode}/items/page`,
method: "get",
params: queryParams,
});
},
/**
* 获取字典项列表
*/
getDictItems(dictCode: string) {
return request<any, DictItemOption[]>({
url: `${DICT_BASE_URL}/${dictCode}/items`,
method: "get",
});
},
/**
* 新增字典项
*/
createDictItem(dictCode: string, data: DictItemForm) {
return request({
url: `${DICT_BASE_URL}/${dictCode}/items`,
method: "post",
data,
});
},
/**
* 获取字典项表单数据
*
* @param id 字典项ID
* @returns 字典项表单数据
*/
getDictItemFormData(dictCode: string, id: string) {
return request<any, DictItemForm>({
url: `${DICT_BASE_URL}/${dictCode}/items/${id}/form`,
method: "get",
});
},
/**
* 修改字典项
*/
updateDictItem(dictCode: string, id: string, data: DictItemForm) {
return request({
url: `${DICT_BASE_URL}/${dictCode}/items/${id}`,
method: "put",
data,
});
},
/**
* 删除字典项
*/
deleteDictItems(dictCode: string, ids: string) {
return request({
url: `${DICT_BASE_URL}/${dictCode}/items/${ids}`,
method: "delete",
});
},
};
export default DictAPI;
/**
* 字典查询参数
*/
export interface DictPageQuery extends PageQuery {
/**
* 关键字(字典名称/编码)
*/
keywords?: string;
/**
* 字典状态1:启用0:禁用)
*/
status?: number;
}
/**
* 字典分页对象
*/
export interface DictPageVO {
/**
* 字典ID
*/
id: string;
/**
* 字典名称
*/
name: string;
/**
* 字典编码
*/
dictCode: string;
/**
* 字典状态1:启用0:禁用)
*/
status: number;
}
/**
* 字典
*/
export interface DictForm {
/**
* 字典ID
*/
id?: string;
/**
* 字典名称
*/
name?: string;
/**
* 字典编码
*/
dictCode?: string;
/**
* 字典状态1-启用0-禁用)
*/
status?: number;
/**
* 备注
*/
remark?: string;
}
/**
* 字典查询参数
*/
export interface DictItemPageQuery extends PageQuery {
/** 关键字(字典数据值/标签) */
keywords?: string;
/** 字典编码 */
dictCode?: string;
}
/**
* 字典分页对象
*/
export interface DictItemPageVO {
/**
* 字典ID
*/
id: string;
/**
* 字典编码
*/
dictCode: string;
/**
* 字典数据值
*/
value: string;
/**
* 字典数据标签
*/
label: string;
/**
* 状态1:启用0:禁用)
*/
status: number;
/**
* 字典排序
*/
sort?: number;
}
/**
* 字典
*/
export interface DictItemForm {
/**
* 字典ID
*/
id?: string;
/**
* 字典编码
*/
dictCode?: string;
/**
* 字典数据值
*/
value?: string;
/**
* 字典数据标签
*/
label?: string;
/**
* 状态1:启用0:禁用)
*/
status?: number;
/**
* 字典排序
*/
sort?: number;
/**
* 标签类型
*/
tagType?: "success" | "warning" | "info" | "primary" | "danger" | "";
}
/**
* 字典项下拉选项
*/
export interface DictItemOption {
value: number | string;
label: string;
tagType?: "" | "success" | "info" | "warning" | "danger";
[key: string]: any;
}

View File

@@ -3,11 +3,7 @@ import request from "@/utils/request";
const LOG_BASE_URL = "/api/v1/logs";
const LogAPI = {
/**
*
*
* @param queryParams
*/
/** 获取日志分页列表 */
getPage(queryParams: LogPageQuery) {
return request<any, PageResult<LogPageVO[]>>({
url: `${LOG_BASE_URL}/page`,
@@ -15,13 +11,7 @@ const LogAPI = {
params: queryParams,
});
},
/**
* 访
*
* @param queryParams
* @returns
*/
/** 获取访问趋势 */
getVisitTrend(queryParams: VisitTrendQuery) {
return request<any, VisitTrendVO>({
url: `${LOG_BASE_URL}/visit-trend`,
@@ -29,36 +19,20 @@ const LogAPI = {
params: queryParams,
});
},
/**
* 访
*
* @param queryParams
* @returns
*/
/** 获取访问统计 */
getVisitStats() {
return request<any, VisitStatsVO>({
url: `${LOG_BASE_URL}/visit-stats`,
method: "get",
});
return request<any, VisitStatsVO>({ url: `${LOG_BASE_URL}/visit-stats`, method: "get" });
},
};
export default LogAPI;
/**
*
*/
export interface LogPageQuery extends PageQuery {
/** 搜索关键字 */
keywords?: string;
/** 操作时间 */
createTime?: [string, string];
}
/**
* VO
*/
export interface LogPageVO {
/** 主键 */
id: string;
@@ -83,8 +57,6 @@ export interface LogPageVO {
/** 操作人 */
operator: string;
}
/** 访问趋势视图对象 */
export interface VisitTrendVO {
/** 日期列表 */
dates: string[];
@@ -95,16 +67,12 @@ export interface VisitTrendVO {
/** IP数 */
ipList: number[];
}
/** 访问趋势查询参数 */
export interface VisitTrendQuery {
/** 开始日期 */
startDate: string;
/** 结束日期 */
endDate: string;
}
/** 访问统计 */
export interface VisitStatsVO {
/** 今日访客数(UV) */
todayUvCount: number;

View File

@@ -1,41 +1,16 @@
import request from "@/utils/request";
// 菜单基础URL
const MENU_BASE_URL = "/api/v1/menus";
const MenuAPI = {
/**
*
* <p/>
* token获取角色自行判断是否拥有路由的权限
*
* @returns
*/
/** 获取当前用户的路由列表 */
getRoutes() {
return request<any, RouteVO[]>({
url: `${MENU_BASE_URL}/routes`,
method: "get",
});
return request<any, RouteVO[]>({ url: `${MENU_BASE_URL}/routes`, method: "get" });
},
/**
*
*
* @param queryParams
* @returns
*/
/** 获取菜单树形列表 */
getList(queryParams: MenuQuery) {
return request<any, MenuVO[]>({
url: `${MENU_BASE_URL}`,
method: "get",
params: queryParams,
});
return request<any, MenuVO[]>({ url: `${MENU_BASE_URL}`, method: "get", params: queryParams });
},
/**
*
*
* @returns
*/
/** 获取菜单下拉数据源 */
getOptions(onlyParent?: boolean) {
return request<any, OptionType[]>({
url: `${MENU_BASE_URL}/options`,
@@ -43,73 +18,31 @@ const MenuAPI = {
params: { onlyParent },
});
},
/**
*
*
* @param id ID
*/
/** 获取菜单表单数据 */
getFormData(id: string) {
return request<any, MenuForm>({
url: `${MENU_BASE_URL}/${id}/form`,
method: "get",
});
return request<any, MenuForm>({ url: `${MENU_BASE_URL}/${id}/form`, method: "get" });
},
/**
*
*
* @param data
* @returns
*/
/** 新增菜单 */
create(data: MenuForm) {
return request({
url: `${MENU_BASE_URL}`,
method: "post",
data,
});
return request({ url: `${MENU_BASE_URL}`, method: "post", data });
},
/**
*
*
* @param id ID
* @param data
* @returns
*/
/** 修改菜单 */
update(id: string, data: MenuForm) {
return request({
url: `${MENU_BASE_URL}/${id}`,
method: "put",
data,
});
return request({ url: `${MENU_BASE_URL}/${id}`, method: "put", data });
},
/**
*
*
* @param id ID
* @returns
*/
/** 删除菜单 */
deleteById(id: string) {
return request({
url: `${MENU_BASE_URL}/${id}`,
method: "delete",
});
return request({ url: `${MENU_BASE_URL}/${id}`, method: "delete" });
},
};
export default MenuAPI;
import type { MenuTypeEnum } from "@/enums/system/menu.enum";
/** 菜单查询参数 */
export interface MenuQuery {
/** 搜索关键字 */
keywords?: string;
}
/** 菜单视图对象 */
export type MenuTypeEnum = 0 | 1 | 2;
export interface MenuVO {
/** 子菜单 */
children?: MenuVO[];
@@ -133,13 +66,11 @@ export interface MenuVO {
routePath?: string;
/** 菜单排序(数字越小排名越靠前) */
sort?: number;
/** 菜单 */
/** 菜单类型 */
type?: MenuTypeEnum;
/** 菜单是否可见(1:显示;0:隐藏) */
/** 是否可见(1:显示;0:隐藏) */
visible?: number;
}
/** 菜单表单对象 */
export interface MenuForm {
/** 菜单ID */
id?: string;
@@ -147,7 +78,7 @@ export interface MenuForm {
parentId?: string;
/** 菜单名称 */
name?: string;
/** 菜单是否可见(1-是 0-否) */
/** 是否可见(1-是 0-否) */
visible: number;
/** ICON */
icon?: string;
@@ -161,7 +92,7 @@ export interface MenuForm {
component?: string;
/** 跳转路由路径 */
redirect?: string;
/** 菜单 */
/** 菜单类型 */
type?: MenuTypeEnum;
/** 权限标识 */
perm?: string;
@@ -169,16 +100,13 @@ export interface MenuForm {
keepAlive?: number;
/** 【目录】只有一个子路由是否始终显示 */
alwaysShow?: number;
/** 参数 */
/** 其他参数 */
params?: KeyValue[];
}
interface KeyValue {
key: string;
value: string;
}
/** RouteVO路由对象 */
export interface RouteVO {
/** 子路由列表 */
children: RouteVO[];
@@ -193,8 +121,6 @@ export interface RouteVO {
/** 跳转链接 */
redirect?: string;
}
/** Meta路由属性 */
export interface Meta {
/** 【目录】只有一个子路由是否始终显示 */
alwaysShow?: boolean;

View File

@@ -0,0 +1,121 @@
import request from "@/utils/request";
const NOTICE_BASE_URL = "/api/v1/notices";
const NoticeAPI = {
/** 获取通知公告分页数据 */
getPage(queryParams?: NoticePageQuery) {
return request<any, PageResult<NoticePageVO[]>>({
url: `${NOTICE_BASE_URL}/page`,
method: "get",
params: queryParams,
});
},
/** 获取通知公告表单数据 */
getFormData(id: string) {
return request<any, NoticeForm>({ url: `${NOTICE_BASE_URL}/${id}/form`, method: "get" });
},
/** 添加通知公告 */
create(data: NoticeForm) {
return request({ url: `${NOTICE_BASE_URL}`, method: "post", data });
},
/** 更新通知公告 */
update(id: string, data: NoticeForm) {
return request({ url: `${NOTICE_BASE_URL}/${id}`, method: "put", data });
},
/** 批量删除通知公告,多个以英文逗号(,)分割 */
deleteByIds(ids: string) {
return request({ url: `${NOTICE_BASE_URL}/${ids}`, method: "delete" });
},
/** 发布通知 */
publish(id: string) {
return request({ url: `${NOTICE_BASE_URL}/${id}/publish`, method: "put" });
},
/** 撤回通知 */
revoke(id: string) {
return request({ url: `${NOTICE_BASE_URL}/${id}/revoke`, method: "put" });
},
/** 查看通知 */
getDetail(id: string) {
return request<any, NoticeDetailVO>({ url: `${NOTICE_BASE_URL}/${id}/detail`, method: "get" });
},
/** 全部已读 */
readAll() {
return request({ url: `${NOTICE_BASE_URL}/read-all`, method: "put" });
},
/** 获取我的通知分页列表 */
getMyNoticePage(queryParams?: NoticePageQuery) {
return request<any, PageResult<NoticePageVO[]>>({
url: `${NOTICE_BASE_URL}/my-page`,
method: "get",
params: queryParams,
});
},
};
export default NoticeAPI;
export interface NoticePageQuery extends PageQuery {
/** 标题 */
title?: string;
/** 发布状态(0:草稿;1:已发布;2:已撤回) */
publishStatus?: number;
/** 是否已读(1:是;0:否) */
isRead?: number;
}
export interface NoticeForm {
/** 通知ID(新增不填) */
id?: string;
/** 标题 */
title?: string;
/** 内容 */
content?: string;
/** 类型 */
type?: number;
/** 优先级/级别 */
level?: string;
/** 目标类型 */
targetType?: number;
/** 目标用户ID(多个以英文逗号(,)分割) */
targetUserIds?: string;
}
export interface NoticePageVO {
/** 通知ID */
id: string;
/** 标题 */
title?: string;
/** 内容 */
content?: string;
/** 类型 */
type?: number;
/** 发布人ID */
publisherId?: bigint;
/** 优先级 */
priority?: number;
/** 目标类型 */
targetType?: number;
/** 发布状态 */
publishStatus?: number;
/** 发布时间 */
publishTime?: Date;
/** 撤回时间 */
revokeTime?: Date;
}
export interface NoticeDetailVO {
/** 通知ID */
id?: string;
/** 标题 */
title?: string;
/** 内容 */
content?: string;
/** 类型 */
type?: number;
/** 发布人名称 */
publisherName?: string;
/** 优先级/级别 */
level?: string;
/** 发布时间 */
publishTime?: Date;
/** 发布状态 */
publishStatus?: number;
}

View File

@@ -1,199 +0,0 @@
import request from "@/utils/request";
const NOTICE_BASE_URL = "/api/v1/notices";
const NoticeAPI = {
/** 获取通知公告分页数据 */
getPage(queryParams?: NoticePageQuery) {
return request<any, PageResult<NoticePageVO[]>>({
url: `${NOTICE_BASE_URL}/page`,
method: "get",
params: queryParams,
});
},
/**
* 获取通知公告表单数据
*
* @param id 通知
* @returns 通知表单数据
*/
getFormData(id: string) {
return request<any, NoticeForm>({
url: `${NOTICE_BASE_URL}/${id}/form`,
method: "get",
});
},
/**
* 添加通知公告
*
* @param data 通知表单数据
* @returns
*/
create(data: NoticeForm) {
return request({
url: `${NOTICE_BASE_URL}`,
method: "post",
data,
});
},
/**
* 更新通知公告
*
* @param id 通知ID
* @param data 通知表单数据
*/
update(id: string, data: NoticeForm) {
return request({
url: `${NOTICE_BASE_URL}/${id}`,
method: "put",
data,
});
},
/**
* 批量删除通知公告,多个以英文逗号(,)分割
*
* @param ids 通知公告ID字符串多个以英文逗号(,)分割
*/
deleteByIds(ids: string) {
return request({
url: `${NOTICE_BASE_URL}/${ids}`,
method: "delete",
});
},
/**
* 发布通知
*
* @param id 被发布的通知公告id
* @returns
*/
publish(id: string) {
return request({
url: `${NOTICE_BASE_URL}/${id}/publish`,
method: "put",
});
},
/**
* 撤回通知
*
* @param id 撤回的通知id
* @returns
*/
revoke(id: string) {
return request({
url: `${NOTICE_BASE_URL}/${id}/revoke`,
method: "put",
});
},
/**
* 查看通知
*
* @param id
*/
getDetail(id: string) {
return request<any, NoticeDetailVO>({
url: `${NOTICE_BASE_URL}/${id}/detail`,
method: "get",
});
},
/* 全部已读 */
readAll() {
return request({
url: `${NOTICE_BASE_URL}/read-all`,
method: "put",
});
},
/** 获取我的通知分页列表 */
getMyNoticePage(queryParams?: NoticePageQuery) {
return request<any, PageResult<NoticePageVO[]>>({
url: `${NOTICE_BASE_URL}/my-page`,
method: "get",
params: queryParams,
});
},
};
export default NoticeAPI;
/** 通知公告分页查询参数 */
export interface NoticePageQuery extends PageQuery {
/** 标题 */
title?: string;
/** 发布状态(0未发布1已发布-1已撤回) */
publishStatus?: number;
isRead?: number;
}
/** 通知公告表单对象 */
export interface NoticeForm {
id?: string;
/** 通知标题 */
title?: string;
/** 通知内容 */
content?: string;
/** 通知类型 */
type?: number;
/** 优先级(LMH高) */
level?: string;
/** 目标类型(1-全体 2-指定) */
targetType?: number;
/** 目标ID合集以,分割 */
targetUserIds?: string;
}
/** 通知公告分页对象 */
export interface NoticePageVO {
id: string;
/** 通知标题 */
title?: string;
/** 通知内容 */
content?: string;
/** 通知类型 */
type?: number;
/** 发布人 */
publisherId?: bigint;
/** 优先级(0-低 1-中 2-高) */
priority?: number;
/** 目标类型(0-全体 1-指定) */
targetType?: number;
/** 发布状态(0-未发布 1已发布 2已撤回) */
publishStatus?: number;
/** 发布时间 */
publishTime?: Date;
/** 撤回时间 */
revokeTime?: Date;
}
export interface NoticeDetailVO {
/** 通知ID */
id?: string;
/** 通知标题 */
title?: string;
/** 通知内容 */
content?: string;
/** 通知类型 */
type?: number;
/** 发布人 */
publisherName?: string;
/** 优先级(L-低 M-中 H-高) */
level?: string;
/** 发布时间 */
publishTime?: Date;
/** 发布状态 */
publishStatus?: number;
}

View File

@@ -0,0 +1,79 @@
import request from "@/utils/request";
const ROLE_BASE_URL = "/api/v1/roles";
const RoleAPI = {
/** 获取角色分页数据 */
getPage(queryParams?: RolePageQuery) {
return request<any, PageResult<RolePageVO[]>>({
url: `${ROLE_BASE_URL}/page`,
method: "get",
params: queryParams,
});
},
/** 获取角色下拉数据源 */
getOptions() {
return request<any, OptionType[]>({ url: `${ROLE_BASE_URL}/options`, method: "get" });
},
/** 获取角色的菜单ID集合 */
getRoleMenuIds(roleId: string) {
return request<any, string[]>({ url: `${ROLE_BASE_URL}/${roleId}/menuIds`, method: "get" });
},
/** 分配菜单权限 */
updateRoleMenus(roleId: string, data: number[]) {
return request({ url: `${ROLE_BASE_URL}/${roleId}/menus`, method: "put", data });
},
/** 获取角色表单数据 */
getFormData(id: string) {
return request<any, RoleForm>({ url: `${ROLE_BASE_URL}/${id}/form`, method: "get" });
},
/** 新增角色 */
create(data: RoleForm) {
return request({ url: `${ROLE_BASE_URL}`, method: "post", data });
},
/** 更新角色 */
update(id: string, data: RoleForm) {
return request({ url: `${ROLE_BASE_URL}/${id}`, method: "put", data });
},
/** 批量删除角色,多个以英文逗号(,)分割 */
deleteByIds(ids: string) {
return request({ url: `${ROLE_BASE_URL}/${ids}`, method: "delete" });
},
};
export default RoleAPI;
export interface RolePageQuery extends PageQuery {
/** 搜索关键字 */
keywords?: string;
}
export interface RolePageVO {
/** 角色ID */
id?: string;
/** 角色编码 */
code?: string;
/** 角色名称 */
name?: string;
/** 排序 */
sort?: number;
/** 角色状态 */
status?: number;
/** 创建时间 */
createTime?: Date;
/** 修改时间 */
updateTime?: Date;
}
export interface RoleForm {
/** 角色ID */
id?: string;
/** 角色编码 */
code?: string;
/** 数据权限 */
dataScope?: number;
/** 角色名称 */
name?: string;
/** 排序 */
sort?: number;
/** 角色状态(1-正常0-停用) */
status?: number;
}

View File

@@ -1,138 +0,0 @@
import request from "@/utils/request";
const ROLE_BASE_URL = "/api/v1/roles";
const RoleAPI = {
/** 获取角色分页数据 */
getPage(queryParams?: RolePageQuery) {
return request<any, PageResult<RolePageVO[]>>({
url: `${ROLE_BASE_URL}/page`,
method: "get",
params: queryParams,
});
},
/** 获取角色下拉数据源 */
getOptions() {
return request<any, OptionType[]>({
url: `${ROLE_BASE_URL}/options`,
method: "get",
});
},
/**
* 获取角色的菜单ID集合
*
* @param roleId 角色ID
* @returns 角色的菜单ID集合
*/
getRoleMenuIds(roleId: string) {
return request<any, string[]>({
url: `${ROLE_BASE_URL}/${roleId}/menuIds`,
method: "get",
});
},
/**
* 分配菜单权限
*
* @param roleId 角色ID
* @param data 菜单ID集合
*/
updateRoleMenus(roleId: string, data: number[]) {
return request({
url: `${ROLE_BASE_URL}/${roleId}/menus`,
method: "put",
data,
});
},
/**
* 获取角色表单数据
*
* @param id 角色ID
* @returns 角色表单数据
*/
getFormData(id: string) {
return request<any, RoleForm>({
url: `${ROLE_BASE_URL}/${id}/form`,
method: "get",
});
},
/** 添加角色 */
create(data: RoleForm) {
return request({
url: `${ROLE_BASE_URL}`,
method: "post",
data,
});
},
/**
* 更新角色
*
* @param id 角色ID
* @param data 角色表单数据
*/
update(id: string, data: RoleForm) {
return request({
url: `${ROLE_BASE_URL}/${id}`,
method: "put",
data,
});
},
/**
* 批量删除角色,多个以英文逗号(,)分割
*
* @param ids 角色ID字符串多个以英文逗号(,)分割
*/
deleteByIds(ids: string) {
return request({
url: `${ROLE_BASE_URL}/${ids}`,
method: "delete",
});
},
};
export default RoleAPI;
/** 角色分页查询参数 */
export interface RolePageQuery extends PageQuery {
/** 搜索关键字 */
keywords?: string;
}
/** 角色分页对象 */
export interface RolePageVO {
/** 角色ID */
id?: string;
/** 角色编码 */
code?: string;
/** 角色名称 */
name?: string;
/** 排序 */
sort?: number;
/** 角色状态 */
status?: number;
/** 创建时间 */
createTime?: Date;
/** 修改时间 */
updateTime?: Date;
}
/** 角色表单对象 */
export interface RoleForm {
/** 角色ID */
id?: string;
/** 角色编码 */
code?: string;
/** 数据权限 */
dataScope?: number;
/** 角色名称 */
name?: string;
/** 排序 */
sort?: number;
/** 角色状态(1-正常0-停用) */
status?: number;
}

View File

@@ -17,7 +17,7 @@
</template>
<script setup lang="ts">
import { useAppStore } from "@/store/modules/app.store";
import { useAppStore } from "@/store/modules/app-store";
import { LanguageEnum } from "@/enums/settings/locale.enum";
defineProps({

View File

@@ -79,7 +79,7 @@
</template>
<script setup lang="ts">
import NoticeAPI, { NoticePageVO, NoticeDetailVO } from "@/api/system/notice.api";
import NoticeAPI, { NoticePageVO, NoticeDetailVO } from "@/api/system/notice-api";
import router from "@/router";
const noticeList = ref<NoticePageVO[]>([]);

View File

@@ -21,7 +21,7 @@
<script setup lang="ts">
import { ComponentSize } from "@/enums/settings/layout.enum";
import { useAppStore } from "@/store/modules/app.store";
import { useAppStore } from "@/store/modules/app-store";
const { t } = useI18n();
const sizeOptions = computed(() => {

View File

@@ -51,7 +51,7 @@ import {
UploadRequestOptions,
} from "element-plus";
import FileAPI, { FileInfo } from "@/api/file.api";
import FileAPI, { FileInfo } from "@/api/file-api";
const props = defineProps({
/**

View File

@@ -40,7 +40,7 @@
</template>
<script setup lang="ts">
import { UploadRawFile, UploadRequestOptions, UploadUserFile } from "element-plus";
import FileAPI, { FileInfo } from "@/api/file.api";
import FileAPI, { FileInfo } from "@/api/file-api";
const props = defineProps({
/**

View File

@@ -25,7 +25,7 @@
<script setup lang="ts">
import { UploadRawFile, UploadRequestOptions } from "element-plus";
import FileAPI, { FileInfo } from "@/api/file.api";
import FileAPI, { FileInfo } from "@/api/file-api";
const props = defineProps({
/**

View File

@@ -34,7 +34,7 @@ import { Toolbar, Editor } from "@wangeditor-next/editor-for-vue";
import { IToolbarConfig, IEditorConfig } from "@wangeditor-next/editor";
// 文件上传 API
import FileAPI from "@/api/file.api";
import FileAPI from "@/api/file-api";
// 上传图片回调函数类型
type InsertFnType = (_url: string, _alt: string, _href: string) => void;

View File

@@ -1,4 +1,4 @@
import { useDictStoreHook } from "@/store/modules/dict.store";
import { useDictStoreHook } from "@/store/modules/dict-store";
import { useStomp } from "./useStomp";
import type { IMessage } from "@stomp/stompjs";
import { ref } from "vue";

View File

@@ -1,6 +1,6 @@
import type { App } from "vue";
import { createI18n } from "vue-i18n";
import { useAppStoreHook } from "@/store/modules/app.store";
import { useAppStoreHook } from "@/store/modules/app-store";
// 本地语言包
import enLocale from "./package/en";
import zhCnLocale from "./package/zh-cn";

View File

@@ -8,10 +8,10 @@ export function setupStore(app: App<Element>) {
app.use(store);
}
export * from "./modules/app.store";
export * from "./modules/permission.store";
export * from "./modules/settings.store";
export * from "./modules/tags-view.store";
export * from "./modules/user.store";
export * from "./modules/dict.store";
export * from "./modules/app-store";
export * from "./modules/permission-store";
export * from "./modules/settings-store";
export * from "./modules/tags-view-store";
export * from "./modules/user-store";
export * from "./modules/dict-store";
export { store };

View File

@@ -1,5 +1,5 @@
import { store } from "@/store";
import DictAPI, { type DictItemOption } from "@/api/system/dict.api";
import DictAPI, { type DictItemOption } from "@/api/system/dict-api";
export const useDictStore = defineStore("dict", () => {
// 字典数据缓存

View File

@@ -3,7 +3,7 @@ import { constantRoutes } from "@/router";
import { store } from "@/store";
import router from "@/router";
import MenuAPI, { type RouteVO } from "@/api/system/menu.api";
import MenuAPI, { type RouteVO } from "@/api/system/menu-api";
const modules = import.meta.glob("../../views/**/**.vue");
const Layout = () => import("@/layouts/index.vue");

View File

@@ -1,11 +1,11 @@
import { store } from "@/store";
import AuthAPI, { type LoginFormData } from "@/api/auth.api";
import UserAPI, { type UserInfo } from "@/api/system/user.api";
import AuthAPI, { type LoginFormData } from "@/api/auth-api";
import UserAPI, { type UserInfo } from "@/api/system/user-api";
import { AuthStorage } from "@/utils/auth";
import { usePermissionStoreHook } from "@/store/modules/permission.store";
import { useDictStoreHook } from "@/store/modules/dict.store";
import { usePermissionStoreHook } from "@/store/modules/permission-store";
import { useDictStoreHook } from "@/store/modules/dict-store";
import { useTagsViewStore } from "@/store";
import { cleanupWebSocket } from "@/plugins/websocket";

View File

@@ -1,6 +1,6 @@
import axios, { type InternalAxiosRequestConfig, type AxiosResponse } from "axios";
import qs from "qs";
import { useUserStoreHook } from "@/store/modules/user.store";
import { useUserStoreHook } from "@/store/modules/user-store";
import { ResultEnum } from "@/enums/api/result.enum";
import { AuthStorage } from "@/utils/auth";
import router from "@/router";

View File

@@ -144,6 +144,22 @@
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="移除表前缀">
<el-input v-model="genConfigFormData.removeTablePrefix" placeholder="如: sys_" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="页面类型">
<el-radio-group v-model="genConfigFormData.pageType">
<el-radio-button label="classic">普通</el-radio-button>
<el-radio-button label="curd">封装(CURD)</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item>
@@ -180,6 +196,38 @@
</el-form>
<div v-show="active == 1" class="elTableCustom">
<div class="mb-2 flex-y-center gap-2">
<el-tag size="small" type="info">批量设置</el-tag>
<el-space size="small">
<el-dropdown>
<el-button size="small" type="primary" plain>查询</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="bulkSet('isShowInQuery', 1)">全选</el-dropdown-item>
<el-dropdown-item @click="bulkSet('isShowInQuery', 0)">全不选</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown>
<el-button size="small" type="success" plain>列表</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="bulkSet('isShowInList', 1)">全选</el-dropdown-item>
<el-dropdown-item @click="bulkSet('isShowInList', 0)">全不选</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown>
<el-button size="small" type="warning" plain>表单</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="bulkSet('isShowInForm', 1)">全选</el-dropdown-item>
<el-dropdown-item @click="bulkSet('isShowInForm', 0)">全不选</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
</div>
<el-table
v-loading="loading"
row-key="id"
@@ -227,51 +275,19 @@
</template>
</el-table-column>
<el-table-column width="70">
<template #header>
<div class="flex-y-center">
<span>查询</span>
<el-checkbox
v-model="isCheckAllQuery"
class="ml-1"
@change="toggleCheckAll('isShowInQuery', isCheckAllQuery)"
/>
</div>
</template>
<el-table-column width="70" label="查询">
<template #default="scope">
<el-checkbox v-model="scope.row.isShowInQuery" :true-value="1" :false-value="0" />
</template>
</el-table-column>
<el-table-column width="70">
<template #header>
<div class="flex-y-center">
<span>列表</span>
<el-checkbox
v-model="isCheckAllList"
class="ml-1"
@change="toggleCheckAll('isShowInList', isCheckAllList)"
/>
</div>
</template>
<el-table-column width="70" label="列表">
<template #default="scope">
<el-checkbox v-model="scope.row.isShowInList" :true-value="1" :false-value="0" />
</template>
</el-table-column>
<el-table-column width="70">
<template #header>
<div class="flex-y-center">
<span>表单</span>
<el-checkbox
v-model="isCheckAllForm"
class="ml-1"
@change="toggleCheckAll('isShowInForm', isCheckAllForm)"
/>
</div>
</template>
<el-table-column width="70" label="表单">
<template #default="scope">
<el-checkbox v-model="scope.row.isShowInForm" :true-value="1" :false-value="0" />
</template>
@@ -347,10 +363,26 @@
</div>
<el-row v-show="active == 2">
<el-col :span="24" class="mb-2">
<div class="flex-y-center gap-3">
<span class="text-sm color-#909399">预览范围</span>
<el-radio-group v-model="previewScope" size="small">
<el-radio-button label="all">全部</el-radio-button>
<el-radio-button label="frontend">前端</el-radio-button>
<el-radio-button label="backend">后端</el-radio-button>
</el-radio-group>
<span class="ml-3 text-sm color-#909399">类型</span>
<el-checkbox-group v-model="previewTypes" size="small">
<el-checkbox-button v-for="t in previewTypeOptions" :key="t" :label="t">
{{ t }}
</el-checkbox-button>
</el-checkbox-group>
</div>
</el-col>
<el-col :span="6">
<el-scrollbar max-height="72vh">
<el-tree
:data="treeData"
:data="filteredTreeData"
default-expand-all
highlight-current
@node-click="handleFileTreeNodeClick"
@@ -403,8 +435,79 @@
<Download />
</el-icon>
</el-button>
<el-button
v-if="active === 2"
:disabled="!supportsFSAccess"
type="primary"
plain
@click="openWriteDialog"
>
<template #icon>
<el-icon><FolderOpened /></el-icon>
</template>
写入本地
</el-button>
</template>
</el-drawer>
<!-- 写入本地对话框 -->
<el-dialog v-model="writeDialog.visible" title="写入本地" width="820px">
<div class="space-y-3">
<el-alert
v-if="!supportsFSAccess"
title="当前浏览器不支持 File System Access API建议使用 Chrome/Edge 最新版"
type="warning"
show-icon
:closable="false"
/>
<el-form :label-width="110">
<el-form-item label="前端根目录">
<div class="flex-y-center gap-2">
<el-input v-model="frontendDirPath" placeholder="请选择前端根目录" readonly />
<el-button :disabled="!supportsFSAccess" @click="pickFrontendDir">选择</el-button>
</div>
</el-form-item>
<el-form-item label="后端根目录">
<div class="flex-y-center gap-2">
<el-input v-model="backendDirPath" placeholder="请选择后端根目录" readonly />
<el-button :disabled="!supportsFSAccess" @click="pickBackendDir">选择</el-button>
</div>
</el-form-item>
<el-form-item label="写入范围">
<el-radio-group v-model="writeScope">
<el-radio-button label="all">全部</el-radio-button>
<el-radio-button label="frontend">仅前端</el-radio-button>
<el-radio-button label="backend">仅后端</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="覆盖策略">
<el-radio-group v-model="overwriteMode">
<el-radio-button label="overwrite">覆盖</el-radio-button>
<el-radio-button label="skip">跳过已存在</el-radio-button>
<el-radio-button label="ifChanged">仅变更覆盖</el-radio-button>
</el-radio-group>
</el-form-item>
</el-form>
<div v-if="writeProgress.total > 0" class="mt-2">
<el-progress :text-inside="true" :stroke-width="16" :percentage="writeProgress.percent" />
<div class="mt-1 text-sm color-#909399">
{{ writeProgress.done }}/{{ writeProgress.total }} {{ writeProgress.current }}
</div>
</div>
</div>
<template #footer>
<el-button @click="writeDialog.visible = false"> </el-button>
<el-button
type="primary"
:disabled="!canWriteToLocal || writeRunning"
@click="confirmWrite"
>
</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -427,10 +530,11 @@ import GeneratorAPI, {
GenConfigForm,
TablePageQuery,
FieldConfig,
} from "@/api/codegen.api";
} from "@/api/codegen-api";
import { ElLoading } from "element-plus";
import DictAPI from "@/api/system/dict.api";
import MenuAPI from "@/api/system/menu.api";
import DictAPI from "@/api/system/dict-api";
import MenuAPI from "@/api/system/menu-api";
interface TreeNode {
label: string;
@@ -438,6 +542,41 @@ interface TreeNode {
children?: TreeNode[];
}
const treeData = ref<TreeNode[]>([]);
const previewScope = ref<"all" | "frontend" | "backend">("all");
const previewTypeOptions = ["ts", "vue", "java", "xml"];
const previewTypes = ref<string[]>([...previewTypeOptions]);
const filteredTreeData = computed<TreeNode[]>(() => {
if (!treeData.value.length) return [];
// 基于原树按 scope/types 过滤叶子节点
const match = (label: string, parentPath: string[]): boolean => {
// scope 过滤:根据路径初步判断
const pathStr = parentPath.join("/");
if (previewScope.value !== "all") {
const isBackend = /(^|\/)src\/main\//.test(pathStr) || /(^|\/)java\//.test(pathStr);
const scopeOfNode = isBackend ? "backend" : "frontend";
if (scopeOfNode !== previewScope.value) return false;
}
// 类型过滤:根据后缀
const ext = label.split(".").pop() || "";
return previewTypes.value.includes(ext);
};
const cloneFilter = (node: TreeNode, parents: string[] = []): TreeNode | null => {
if (!node.children || node.children.length === 0) {
return match(node.label, parents) ? { ...node } : null;
}
const nextParents = [...parents, node.label];
const children = (node.children || [])
.map((c) => cloneFilter(c, nextParents))
.filter(Boolean) as TreeNode[];
if (!children.length) return null;
return { label: node.label, children };
};
const filtered = treeData.value.map((n) => cloneFilter(n)).filter(Boolean) as TreeNode[];
return filtered;
});
const queryFormRef = ref();
const queryParams = reactive<TablePageQuery>({
@@ -457,6 +596,7 @@ const dictOptions = ref<OptionType[]>();
const menuOptions = ref<OptionType[]>([]);
const genConfigFormData = ref<GenConfigForm>({
fieldConfigs: [],
pageType: "classic",
});
const genConfigFormRules = {
@@ -472,6 +612,24 @@ const dialog = reactive({
title: "",
});
// 页面风格使用后端持久化字段 genConfigFormData.ui
watch(
() => genConfigFormData.value.removeTablePrefix,
(prefix) => {
const table = genConfigFormData.value.tableName;
if (!table) return;
const p = prefix || "";
const base = table.startsWith(p) ? table.slice(p.length) : table;
// 将下划线分隔的表名转为帕斯卡命名
const camel = base
.split("_")
.filter(Boolean)
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
.join("");
genConfigFormData.value.entityName = camel;
}
);
const { copy, copied } = useClipboard();
const code = ref();
const cmRef = ref<CmComponentRef>();
@@ -485,6 +643,28 @@ const active = ref(0);
const currentTableName = ref("");
const sortFlag = ref<object>();
// ================= 本地写盘(可选) =================
const supportsFSAccess = typeof (window as any).showDirectoryPicker === "function";
const outputMode = ref<"zip" | "local">("zip");
const frontendDirHandle = ref<any>(null);
const backendDirHandle = ref<any>(null);
const frontendDirName = ref("");
const backendDirName = ref("");
// 预览的原始文件列表(用于写盘)
const lastPreviewFiles = ref<{ path: string; fileName: string; content: string }[]>([]);
const needFrontend = computed(() =>
lastPreviewFiles.value.some((f) => resolveRootForPath(f.path) === "frontend")
);
const needBackend = computed(() =>
lastPreviewFiles.value.some((f) => resolveRootForPath(f.path) === "backend")
);
const canWriteToLocal = computed(() => {
if (!lastPreviewFiles.value.length) return false;
const frontOk = needFrontend.value ? !!frontendDirHandle.value : true;
const backOk = needBackend.value ? !!backendDirHandle.value : true;
return frontOk && backOk;
});
// 查询是否全选
const isCheckAllQuery = ref(false);
// 列表是否全选
@@ -623,7 +803,9 @@ function handleNextClick() {
ElMessage.error("表名不能为空");
return;
}
GeneratorAPI.download(tableName);
if (outputMode.value === "zip" || !supportsFSAccess) {
GeneratorAPI.download(tableName, (genConfigFormData.value.pageType as any) || "classic");
}
}
}
}
@@ -699,15 +881,15 @@ function handleResetConfig(tableName: string) {
type FieldConfigKey = "isShowInQuery" | "isShowInList" | "isShowInForm";
/** 全选 */
const toggleCheckAll = (key: FieldConfigKey, value: boolean) => {
const fieldConfigs = genConfigFormData.value?.fieldConfigs;
// 单列全选开关已移除,改为顶部“批量设置”入口;保留方法时会触发未使用告警,故删除。
if (fieldConfigs) {
fieldConfigs.forEach((row: FieldConfig) => {
row[key] = value ? 1 : 0;
function bulkSet(key: FieldConfigKey, value: 0 | 1) {
const list = genConfigFormData.value?.fieldConfigs || [];
list.forEach((row: any) => {
// 只改已有字段,保持响应式
row[key] = value;
});
}
};
const checkAllSelected = (key: keyof FieldConfig, isCheckAllRef: any) => {
const fieldConfigs = genConfigFormData.value?.fieldConfigs || [];
@@ -717,12 +899,15 @@ const checkAllSelected = (key: keyof FieldConfig, isCheckAllRef: any) => {
/** 获取生成预览 */
function handlePreview(tableName: string) {
treeData.value = [];
GeneratorAPI.getPreviewData(tableName)
GeneratorAPI.getPreviewData(tableName, (genConfigFormData.value.pageType as any) || "classic")
.then((data) => {
dialog.title = `代码生成 ${tableName}`;
// 组装树形结构完善代码
const tree = buildTree(data);
treeData.value = [tree];
// 缓存原始数据用于写盘
lastPreviewFiles.value = data || [];
// 去掉根节点“前后端代码”,直接展示其 children 作为一级目录
treeData.value = tree?.children ? [...tree.children] : [];
// 默认选中第一个叶子节点并设置 code 值
const firstLeafNode = findFirstLeafNode(tree);
@@ -858,6 +1043,280 @@ const handleCopyCode = () => {
}
};
// =============== 目录选择与写入 ===============
const pickFrontendDir = async () => {
try {
// @ts-ignore
frontendDirHandle.value = await (window as any).showDirectoryPicker();
frontendDirName.value = frontendDirHandle.value?.name || "";
ElMessage.success("前端目录选择成功");
} catch {
// 用户取消或浏览器不支持
}
};
const pickBackendDir = async () => {
try {
// @ts-ignore
backendDirHandle.value = await (window as any).showDirectoryPicker();
backendDirName.value = backendDirHandle.value?.name || "";
ElMessage.success("后端目录选择成功");
} catch {
// 用户取消或浏览器不支持
}
};
async function ensureDir(root: any, path: string[], force = true) {
let current = root;
for (const segment of path) {
try {
// @ts-ignore
current = await current.getDirectoryHandle(segment, { create: true });
} catch (err: any) {
// 若同名文件阻塞目录创建,尝试强制删除后重建
if (force && err?.name === "TypeMismatchError") {
try {
// @ts-ignore
await current.removeEntry(segment, { recursive: true });
// @ts-ignore
current = await current.getDirectoryHandle(segment, { create: true });
} catch {
throw err;
}
} else {
throw err;
}
}
}
return current;
}
async function writeFile(dirHandle: any, filePath: string, content: string) {
const normalized = filePath.replace(/\\/g, "/");
const parts = normalized.split("/").filter(Boolean);
const fileName = parts.pop()!;
const folderSegments = parts;
const targetDir = await ensureDir(dirHandle, folderSegments, true);
// @ts-ignore
let fileHandle;
try {
// @ts-ignore
fileHandle = await targetDir.getFileHandle(fileName, { create: true });
} catch (err: any) {
if (err?.name === "TypeMismatchError") {
// 存在同名目录,尝试删除后重建文件
try {
// @ts-ignore
await targetDir.removeEntry(fileName, { recursive: true });
// @ts-ignore
fileHandle = await targetDir.getFileHandle(fileName, { create: true });
} catch {
throw err;
}
} else {
throw err;
}
}
// @ts-ignore
const writable = await fileHandle.createWritable();
await writable.write(content ?? "");
await writable.close();
}
async function pathExists(dirHandle: any, filePath: string): Promise<boolean> {
try {
const normalized = filePath.replace(/\\/g, "/");
const parts = normalized.split("/").filter(Boolean);
const fileName = parts.pop()!;
const targetDir = await ensureDir(dirHandle, parts, false);
// @ts-ignore
await targetDir.getFileHandle(fileName, { create: false });
return true;
} catch {
return false;
}
}
async function isSameFile(dirHandle: any, filePath: string, content: string): Promise<boolean> {
try {
const normalized = filePath.replace(/\\/g, "/");
const parts = normalized.split("/").filter(Boolean);
const fileName = parts.pop()!;
const targetDir = await ensureDir(dirHandle, parts, false);
// @ts-ignore
const fileHandle = await targetDir.getFileHandle(fileName, { create: false });
// @ts-ignore
const file = await fileHandle.getFile();
const text = await file.text();
return text === (content ?? "");
} catch {
return false;
}
}
// 将模板中的 path 映射到前端/后端根目录
function resolveRootForPath(p: string) {
const normalized = p.replace(/\\/g, "/");
const frontApp = genConfigFormData.value.frontendAppName;
const backApp = genConfigFormData.value.backendAppName;
if (
(backApp && normalized.startsWith(`${backApp}/`)) ||
normalized.includes("/src/main/") ||
normalized.startsWith("src/main/") ||
normalized.startsWith("java/")
) {
return "backend" as const;
}
if ((frontApp && normalized.startsWith(`${frontApp}/`)) || normalized.startsWith("src/")) {
return "frontend" as const;
}
// 默认前端
return "frontend" as const;
}
function stripProjectRoot(p: string) {
const normalized = p.replace(/\\/g, "/");
const frontApp = genConfigFormData.value.frontendAppName;
const backApp = genConfigFormData.value.backendAppName;
let rel = normalized;
if (frontApp && normalized.startsWith(`${frontApp}/`)) {
rel = normalized.slice(frontApp.length + 1);
} else if (backApp && normalized.startsWith(`${backApp}/`)) {
rel = normalized.slice(backApp.length + 1);
} else {
const idx = normalized.indexOf("/src/");
if (idx > -1) {
rel = normalized.slice(idx + 1); // 保留 'src/...'
} else if (normalized.startsWith("src/")) {
rel = normalized;
}
}
return rel;
}
const writeGeneratedCode = async () => {
if (!supportsFSAccess) {
ElMessage.warning("当前浏览器不支持本地写入请选择下载ZIP");
return;
}
if (
(needFrontend.value && !frontendDirHandle.value) ||
(needBackend.value && !backendDirHandle.value)
) {
ElMessage.warning("请先选择所需的前端/后端目录");
return;
}
if (!lastPreviewFiles.value.length) {
ElMessage.warning("请先生成预览");
return;
}
loading.value = true;
const loadingSvc = ElLoading.service({
lock: true,
text: "正在写入代码...",
});
writeRunning.value = true;
let frontCount = 0;
let backCount = 0;
const failed: string[] = [];
const files = lastPreviewFiles.value.filter((f) => {
const root = resolveRootForPath(f.path);
return writeScope.value === "all" || root === writeScope.value;
});
writeProgress.total = files.length;
writeProgress.done = 0;
writeProgress.percent = 0;
writeProgress.current = "";
const concurrency = 4;
const queue = files.slice();
const workers: Promise<void>[] = [];
async function worker() {
while (queue.length) {
const item = queue.shift()!;
try {
const root = resolveRootForPath(item.path);
const relativePath = stripProjectRoot(`${item.path}/${item.fileName}`);
writeProgress.current = relativePath;
if (overwriteMode.value === "ifChanged") {
// 简单差异:已有文件内容与待写内容相同则跳过
// @ts-ignore
const targetRoot = root === "frontend" ? frontendDirHandle.value : backendDirHandle.value;
const existsSame = await isSameFile(targetRoot, relativePath, item.content || "");
if (existsSame) {
// 视作成功但不写
writeProgress.done++;
writeProgress.percent = Math.round((writeProgress.done / writeProgress.total) * 100);
continue;
}
}
if (overwriteMode.value === "skip") {
// @ts-ignore
const targetRoot = root === "frontend" ? frontendDirHandle.value : backendDirHandle.value;
const exists = await pathExists(targetRoot, relativePath);
if (exists) {
writeProgress.done++;
writeProgress.percent = Math.round((writeProgress.done / writeProgress.total) * 100);
continue;
}
}
if (root === "frontend") {
await writeFile(frontendDirHandle.value, relativePath, item.content || "");
frontCount++;
} else {
await writeFile(backendDirHandle.value, relativePath, item.content || "");
backCount++;
}
} catch (err) {
console.error("写入失败:", item.path, err);
failed.push(item.path);
} finally {
writeProgress.done++;
writeProgress.percent = Math.round((writeProgress.done / writeProgress.total) * 100);
}
}
}
for (let i = 0; i < concurrency; i++) {
workers.push(worker());
}
await Promise.all(workers);
loading.value = false;
loadingSvc.close();
writeRunning.value = false;
if (failed.length) {
ElMessage.warning(
`部分文件写入失败:${failed.length} 个,成功 前端 ${frontCount} 个/后端 ${backCount} 个。打开控制台查看详情`
);
} else {
ElMessage.success(`写入完成:前端 ${frontCount} 个文件,后端 ${backCount} 个文件`);
}
};
const writeDialog = reactive({ visible: false });
const frontendDirPath = ref("");
const backendDirPath = ref("");
const writeScope = ref<"all" | "frontend" | "backend">("all");
const overwriteMode = ref<"overwrite" | "skip" | "ifChanged">("overwrite");
const writeProgress = reactive({ total: 0, done: 0, percent: 0, current: "" });
const writeRunning = ref(false);
// 提示文本已取消展示,保留逻辑意义不大,移除。
function openWriteDialog() {
writeDialog.visible = true;
}
// 同步展示路径
watch(frontendDirName, (v) => (frontendDirPath.value = v));
watch(backendDirName, (v) => (backendDirPath.value = v));
async function confirmWrite() {
await writeGeneratedCode();
writeDialog.visible = false;
}
/** 组件挂载后执行 */
onMounted(() => {
handleQuery();

View File

@@ -354,8 +354,8 @@ defineOptions({
});
import { dayjs } from "element-plus";
import LogAPI, { VisitStatsVO, VisitTrendVO } from "@/api/system/log.api";
import { useUserStore } from "@/store/modules/user.store";
import LogAPI, { VisitStatsVO, VisitTrendVO } from "@/api/system/log-api";
import { useUserStore } from "@/store/modules/user-store";
import { formatGrowthRate } from "@/utils";
import { useTransition, useDateFormat } from "@vueuse/core";
import { Connection, Failed } from "@element-plus/icons-vue";

View File

@@ -1,4 +1,4 @@
import UserAPI, { type UserForm } from "@/api/system/user.api";
import UserAPI, { type UserForm } from "@/api/system/user-api";
import type { IModalConfig } from "@/components/CURD/types";
import { deptArr, roleArr } from "./options";

View File

@@ -1,6 +1,6 @@
import UserAPI from "@/api/system/user.api";
import RoleAPI from "@/api/system/role.api";
import type { UserPageQuery } from "@/api/system/user.api";
import UserAPI from "@/api/system/user-api";
import RoleAPI from "@/api/system/role-api";
import type { UserPageQuery } from "@/api/system/user-api";
import type { IContentConfig } from "@/components/CURD/types";
const contentConfig: IContentConfig<UserPageQuery> = {

View File

@@ -1,4 +1,4 @@
import UserAPI, { type UserForm } from "@/api/system/user.api";
import UserAPI, { type UserForm } from "@/api/system/user-api";
import type { IModalConfig } from "@/components/CURD/types";
import { DeviceEnum } from "@/enums/settings/device.enum";
import { useAppStore } from "@/store";

View File

@@ -1,6 +1,6 @@
/** 公共下载数据,减少重复请求次数 */
import DeptAPI from "@/api/system/dept.api";
import RoleAPI from "@/api/system/role.api";
import DeptAPI from "@/api/system/dept-api";
import RoleAPI from "@/api/system/role-api";
interface OptionType {
label: string;

View File

@@ -1,4 +1,4 @@
import type { UserForm } from "@/api/system/user.api";
import type { UserForm } from "@/api/system/user-api";
import type { IModalConfig } from "@/components/CURD/types";
import { deptArr } from "../config/options";

View File

@@ -113,7 +113,7 @@
</template>
<script setup lang="ts">
import UserAPI from "@/api/system/user.api";
import UserAPI from "@/api/system/user-api";
import type { IObject, IOperateData, PageModalInstance } from "@/components/CURD/types";
import usePage from "@/components/CURD/usePage";
import addModalConfig from "./config/add";

View File

@@ -139,9 +139,9 @@
</template>
<script setup lang="ts">
import { useDictStoreHook } from "@/store/modules/dict.store";
import { useDictStoreHook } from "@/store/modules/dict-store";
import { useDateFormat } from "@vueuse/core";
import DictAPI, { DictItemForm } from "@/api/system/dict.api";
import DictAPI, { DictItemForm } from "@/api/system/dict-api";
import { useDictSync, DictMessage } from "@/composables/useDictSync";
// 性别字典编码

View File

@@ -21,7 +21,7 @@
</div>
</template>
<script setup lang="ts">
import FileAPI from "@/api/file.api";
import FileAPI from "@/api/file-api";
const imgUrl = ref("");
const canvas = ref();

View File

@@ -1,4 +1,4 @@
import UserAPI from "@/api/system/user.api";
import UserAPI from "@/api/system/user-api";
import type { ISelectConfig } from "@/components/TableSelect/index.vue";
const selectConfig: ISelectConfig = {

View File

@@ -98,7 +98,7 @@
<script setup lang="ts">
import { useStomp } from "@/composables/useStomp";
import { useUserStoreHook } from "@/store/modules/user.store";
import { useUserStoreHook } from "@/store/modules/user-store";
const userStore = useUserStoreHook();
// 用于手动调整 WebSocket 地址

View File

@@ -111,7 +111,7 @@
</template>
<script setup lang="ts">
import type { FormInstance } from "element-plus";
import AuthAPI, { type LoginFormData } from "@/api/auth.api";
import AuthAPI, { type LoginFormData } from "@/api/auth-api";
import router from "@/router";
import { useUserStore } from "@/store";
import CommonWrapper from "@/components/CommonWrapper/index.vue";

View File

@@ -98,7 +98,7 @@
import type { FormInstance } from "element-plus";
import { Lock } from "@element-plus/icons-vue";
import { useI18n } from "vue-i18n";
import AuthAPI, { type LoginFormData } from "@/api/auth.api";
import AuthAPI, { type LoginFormData } from "@/api/auth-api";
const { t } = useI18n();

View File

@@ -230,9 +230,9 @@ import UserAPI, {
MobileUpdateForm,
EmailUpdateForm,
UserProfileForm,
} from "@/api/system/user.api";
} from "@/api/system/user-api";
import FileAPI from "@/api/file.api";
import FileAPI from "@/api/file-api";
import { useUserStoreHook } from "@/store";
import { Camera } from "@element-plus/icons-vue";

View File

@@ -141,7 +141,7 @@ defineOptions({
inheritAttrs: false,
});
import ConfigAPI, { ConfigPageVO, ConfigForm, ConfigPageQuery } from "@/api/system/config.api";
import ConfigAPI, { ConfigPageVO, ConfigForm, ConfigPageQuery } from "@/api/system/config-api";
import { ElMessage, ElMessageBox } from "element-plus";
import { useDebounceFn } from "@vueuse/core";

View File

@@ -163,7 +163,7 @@ defineOptions({
inheritAttrs: false,
});
import DeptAPI, { DeptVO, DeptForm, DeptQuery } from "@/api/system/dept.api";
import DeptAPI, { DeptVO, DeptForm, DeptQuery } from "@/api/system/dept-api";
const queryFormRef = ref();
const deptFormRef = ref();

View File

@@ -155,7 +155,7 @@
<script setup lang="ts">
import type { TagProps } from "element-plus";
import DictAPI, { DictItemPageQuery, DictItemPageVO, DictItemForm } from "@/api/system/dict.api";
import DictAPI, { DictItemPageQuery, DictItemPageVO, DictItemForm } from "@/api/system/dict-api";
const route = useRoute();

View File

@@ -137,7 +137,7 @@ defineOptions({
inherititems: false,
});
import DictAPI, { DictPageQuery, DictPageVO, DictForm } from "@/api/system/dict.api";
import DictAPI, { DictPageQuery, DictPageVO, DictForm } from "@/api/system/dict-api";
import router from "@/router";

View File

@@ -68,7 +68,7 @@ defineOptions({
inheritAttrs: false,
});
import LogAPI, { LogPageVO, LogPageQuery } from "@/api/system/log.api";
import LogAPI, { LogPageVO, LogPageQuery } from "@/api/system/log-api";
const queryFormRef = ref();

View File

@@ -340,10 +340,10 @@
</template>
<script setup lang="ts">
import { useAppStore } from "@/store/modules/app.store";
import { useAppStore } from "@/store/modules/app-store";
import { DeviceEnum } from "@/enums/settings/device.enum";
import MenuAPI, { MenuQuery, MenuForm, MenuVO } from "@/api/system/menu.api";
import MenuAPI, { MenuQuery, MenuForm, MenuVO } from "@/api/system/menu-api";
import { MenuTypeEnum } from "@/enums/system/menu.enum";
defineOptions({

View File

@@ -115,7 +115,7 @@ defineOptions({
inheritAttrs: false,
});
import NoticeAPI, { NoticePageVO, NoticePageQuery, NoticeDetailVO } from "@/api/system/notice.api";
import NoticeAPI, { NoticePageVO, NoticePageQuery, NoticeDetailVO } from "@/api/system/notice-api";
const queryFormRef = ref();
const pageData = ref<NoticePageVO[]>([]);

View File

@@ -265,8 +265,8 @@ import NoticeAPI, {
NoticeForm,
NoticePageQuery,
NoticeDetailVO,
} from "@/api/system/notice.api";
import UserAPI from "@/api/system/user.api";
} from "@/api/system/notice-api";
import UserAPI from "@/api/system/user-api";
const queryFormRef = ref();
const dataFormRef = ref();

View File

@@ -212,11 +212,11 @@
</template>
<script setup lang="ts">
import { useAppStore } from "@/store/modules/app.store";
import { useAppStore } from "@/store/modules/app-store";
import { DeviceEnum } from "@/enums/settings/device.enum";
import RoleAPI, { RolePageVO, RoleForm, RolePageQuery } from "@/api/system/role.api";
import MenuAPI from "@/api/system/menu.api";
import RoleAPI, { RolePageVO, RoleForm, RolePageQuery } from "@/api/system/role-api";
import MenuAPI from "@/api/system/menu-api";
defineOptions({
name: "Role",

View File

@@ -21,7 +21,7 @@
</template>
<script setup lang="ts">
import DeptAPI from "@/api/system/dept.api";
import DeptAPI from "@/api/system/dept-api";
const props = defineProps({
modelValue: {
type: [String, Number],

View File

@@ -89,7 +89,7 @@
<script lang="ts" setup>
import { ElMessage, type UploadUserFile } from "element-plus";
import UserAPI from "@/api/system/user.api";
import UserAPI from "@/api/system/user-api";
import { ResultEnum } from "@/enums/api/result.enum";
const emit = defineEmits(["import-success"]);

View File

@@ -244,12 +244,12 @@
</template>
<script setup lang="ts">
import { useAppStore } from "@/store/modules/app.store";
import { useAppStore } from "@/store/modules/app-store";
import { DeviceEnum } from "@/enums/settings/device.enum";
import UserAPI, { UserForm, UserPageQuery, UserPageVO } from "@/api/system/user.api";
import DeptAPI from "@/api/system/dept.api";
import RoleAPI from "@/api/system/role.api";
import UserAPI, { UserForm, UserPageQuery, UserPageVO } from "@/api/system/user-api";
import DeptAPI from "@/api/system/dept-api";
import RoleAPI from "@/api/system/role-api";
import DeptTree from "./components/DeptTree.vue";
import UserImport from "./components/UserImport.vue";

View File

@@ -185,6 +185,8 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
"element-plus/es/components/tree/style/index",
"element-plus/es/components/upload/style/index",
"element-plus/es/components/watermark/style/index",
"element-plus/es/components/checkbox-button/style/index",
"element-plus/es/components/space/style/index",
],
},
// 构建配置