refactor: ♻️ 字典重构,系统权限模块优化
This commit is contained in:
@@ -5,9 +5,9 @@ VITE_APP_PORT = 3000
|
|||||||
VITE_APP_BASE_API = '/dev-api'
|
VITE_APP_BASE_API = '/dev-api'
|
||||||
|
|
||||||
# 线上接口地址
|
# 线上接口地址
|
||||||
VITE_APP_API_URL = http://vapi.youlai.tech
|
# VITE_APP_API_URL = http://vapi.youlai.tech
|
||||||
# 开发接口地址
|
# 开发接口地址
|
||||||
# VITE_APP_API_URL = http://localhost:8989
|
VITE_APP_API_URL = http://localhost:8989
|
||||||
|
|
||||||
# 是否启用 Mock 服务
|
# 是否启用 Mock 服务
|
||||||
VITE_MOCK_DEV_SERVER = false
|
VITE_MOCK_DEV_SERVER = false
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export default defineMock([
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// 新增字典类型
|
// 新增字典
|
||||||
{
|
{
|
||||||
url: "dict/types",
|
url: "dict/types",
|
||||||
method: ["POST"],
|
method: ["POST"],
|
||||||
@@ -100,12 +100,12 @@ export default defineMock([
|
|||||||
return {
|
return {
|
||||||
code: "00000",
|
code: "00000",
|
||||||
data: null,
|
data: null,
|
||||||
msg: "新增字典类型" + body.name + "成功",
|
msg: "新增字典" + body.name + "成功",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取字典类型表单数据
|
// 获取字典表单数据
|
||||||
{
|
{
|
||||||
url: "dict/types/:id/form",
|
url: "dict/types/:id/form",
|
||||||
method: ["GET"],
|
method: ["GET"],
|
||||||
@@ -118,7 +118,7 @@ export default defineMock([
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// 修改字典类型
|
// 修改字典
|
||||||
{
|
{
|
||||||
url: "dict/types/:id",
|
url: "dict/types/:id",
|
||||||
method: ["PUT"],
|
method: ["PUT"],
|
||||||
@@ -126,12 +126,12 @@ export default defineMock([
|
|||||||
return {
|
return {
|
||||||
code: "00000",
|
code: "00000",
|
||||||
data: null,
|
data: null,
|
||||||
msg: "修改字典类型" + body.name + "成功",
|
msg: "修改字典" + body.name + "成功",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// 删除字典类型
|
// 删除字典
|
||||||
{
|
{
|
||||||
url: "dict/types/:id",
|
url: "dict/types/:id",
|
||||||
method: ["DELETE"],
|
method: ["DELETE"],
|
||||||
@@ -139,7 +139,7 @@ export default defineMock([
|
|||||||
return {
|
return {
|
||||||
code: "00000",
|
code: "00000",
|
||||||
data: null,
|
data: null,
|
||||||
msg: "删除字典类型" + params.id + "成功",
|
msg: "删除字典" + params.id + "成功",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -178,7 +178,7 @@ export default defineMock([
|
|||||||
return {
|
return {
|
||||||
code: "00000",
|
code: "00000",
|
||||||
data: null,
|
data: null,
|
||||||
msg: "修改字典类型" + body.name + "成功",
|
msg: "修改字典" + body.name + "成功",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -197,7 +197,7 @@ export default defineMock([
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 字典类型映射表数据
|
// 字典映射表数据
|
||||||
const dictTypeMap: Record<string, any> = {
|
const dictTypeMap: Record<string, any> = {
|
||||||
1: {
|
1: {
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|||||||
@@ -720,7 +720,7 @@ export default defineMock([
|
|||||||
{
|
{
|
||||||
id: 79,
|
id: 79,
|
||||||
parentId: 6,
|
parentId: 6,
|
||||||
name: "字典类型新增",
|
name: "字典新增",
|
||||||
type: "BUTTON",
|
type: "BUTTON",
|
||||||
path: "",
|
path: "",
|
||||||
component: null,
|
component: null,
|
||||||
@@ -734,7 +734,7 @@ export default defineMock([
|
|||||||
{
|
{
|
||||||
id: 81,
|
id: 81,
|
||||||
parentId: 6,
|
parentId: 6,
|
||||||
name: "字典类型编辑",
|
name: "字典编辑",
|
||||||
type: "BUTTON",
|
type: "BUTTON",
|
||||||
path: "",
|
path: "",
|
||||||
component: null,
|
component: null,
|
||||||
@@ -748,7 +748,7 @@ export default defineMock([
|
|||||||
{
|
{
|
||||||
id: 84,
|
id: 84,
|
||||||
parentId: 6,
|
parentId: 6,
|
||||||
name: "字典类型删除",
|
name: "字典删除",
|
||||||
type: "BUTTON",
|
type: "BUTTON",
|
||||||
path: "",
|
path: "",
|
||||||
component: null,
|
component: null,
|
||||||
@@ -1231,15 +1231,15 @@ export default defineMock([
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
value: 79,
|
value: 79,
|
||||||
label: "字典类型新增",
|
label: "字典新增",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 81,
|
value: 81,
|
||||||
label: "字典类型编辑",
|
label: "字典编辑",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 84,
|
value: 84,
|
||||||
label: "字典类型删除",
|
label: "字典删除",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 85,
|
value: 85,
|
||||||
|
|||||||
72
src/api/auth.ts
Normal file
72
src/api/auth.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import request from "@/utils/request";
|
||||||
|
|
||||||
|
const AUTH_BASE_URL = "/api/v1/auth";
|
||||||
|
|
||||||
|
class AuthAPI {
|
||||||
|
/** 登录 接口*/
|
||||||
|
static login(data: LoginData) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("username", data.username);
|
||||||
|
formData.append("password", data.password);
|
||||||
|
formData.append("captchaKey", data.captchaKey);
|
||||||
|
formData.append("captchaCode", data.captchaCode);
|
||||||
|
return request<any, LoginResult>({
|
||||||
|
url: `${AUTH_BASE_URL}/login`,
|
||||||
|
method: "post",
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 注销 接口*/
|
||||||
|
static logout() {
|
||||||
|
return request({
|
||||||
|
url: `${AUTH_BASE_URL}/logout`,
|
||||||
|
method: "delete",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取验证码 接口*/
|
||||||
|
static getCaptcha() {
|
||||||
|
return request<any, CaptchaResult>({
|
||||||
|
url: `${AUTH_BASE_URL}/captcha`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AuthAPI;
|
||||||
|
|
||||||
|
/** 登录请求参数 */
|
||||||
|
export interface LoginData {
|
||||||
|
/** 用户名 */
|
||||||
|
username: string;
|
||||||
|
/** 密码 */
|
||||||
|
password: string;
|
||||||
|
/** 验证码缓存key */
|
||||||
|
captchaKey: string;
|
||||||
|
/** 验证码 */
|
||||||
|
captchaCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 登录响应 */
|
||||||
|
export interface LoginResult {
|
||||||
|
/** 访问token */
|
||||||
|
accessToken?: string;
|
||||||
|
/** 过期时间(单位:毫秒) */
|
||||||
|
expires?: number;
|
||||||
|
/** 刷新token */
|
||||||
|
refreshToken?: string;
|
||||||
|
/** token 类型 */
|
||||||
|
tokenType?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 验证码响应 */
|
||||||
|
export interface CaptchaResult {
|
||||||
|
/** 验证码缓存key */
|
||||||
|
captchaKey: string;
|
||||||
|
/** 验证码图片Base64字符串 */
|
||||||
|
captchaBase64: string;
|
||||||
|
}
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
import request from "@/utils/request";
|
|
||||||
import { CaptchaResult, LoginData, LoginResult } from "./model";
|
|
||||||
|
|
||||||
const AUTH_BASE_URL = "/api/v1/auth";
|
|
||||||
|
|
||||||
class AuthAPI {
|
|
||||||
/**
|
|
||||||
* 登录API
|
|
||||||
*
|
|
||||||
* @param data 登录数据
|
|
||||||
* @returns 登录结果
|
|
||||||
*/
|
|
||||||
static login(data: LoginData) {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append("username", data.username);
|
|
||||||
formData.append("password", data.password);
|
|
||||||
formData.append("captchaKey", data.captchaKey || "");
|
|
||||||
formData.append("captchaCode", data.captchaCode || "");
|
|
||||||
return request<any, LoginResult>({
|
|
||||||
url: `${AUTH_BASE_URL}/login`,
|
|
||||||
method: "post",
|
|
||||||
data: formData,
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "multipart/form-data",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注销API
|
|
||||||
*
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static logout() {
|
|
||||||
return request({
|
|
||||||
url: `${AUTH_BASE_URL}/logout`,
|
|
||||||
method: "delete",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取验证码
|
|
||||||
*
|
|
||||||
* @returns 验证码结果
|
|
||||||
*/
|
|
||||||
static getCaptcha() {
|
|
||||||
return request<any, CaptchaResult>({
|
|
||||||
url: `${AUTH_BASE_URL}/captcha`,
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AuthAPI;
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/**
|
|
||||||
* 登录请求参数
|
|
||||||
*/
|
|
||||||
export interface LoginData {
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username: string;
|
|
||||||
/**
|
|
||||||
* 密码
|
|
||||||
*/
|
|
||||||
password: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证码缓存key
|
|
||||||
*/
|
|
||||||
captchaKey?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证码
|
|
||||||
*/
|
|
||||||
captchaCode?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 登录响应
|
|
||||||
*/
|
|
||||||
export interface LoginResult {
|
|
||||||
/**
|
|
||||||
* 访问token
|
|
||||||
*/
|
|
||||||
accessToken?: string;
|
|
||||||
/**
|
|
||||||
* 过期时间(单位:毫秒)
|
|
||||||
*/
|
|
||||||
expires?: number;
|
|
||||||
/**
|
|
||||||
* 刷新token
|
|
||||||
*/
|
|
||||||
refreshToken?: string;
|
|
||||||
/**
|
|
||||||
* token 类型
|
|
||||||
*/
|
|
||||||
tokenType?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证码响应
|
|
||||||
*/
|
|
||||||
export interface CaptchaResult {
|
|
||||||
/**
|
|
||||||
* 验证码缓存key
|
|
||||||
*/
|
|
||||||
captchaKey: string;
|
|
||||||
/**
|
|
||||||
* 验证码图片Base64字符串
|
|
||||||
*/
|
|
||||||
captchaBase64: string;
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
import { DeptForm, DeptQuery, DeptVO } from "./model";
|
|
||||||
|
|
||||||
const DEPT_BASE_URL = "/api/v1/dept";
|
const DEPT_BASE_URL = "/api/v1/dept";
|
||||||
|
|
||||||
class DeptAPI {
|
class DeptAPI {
|
||||||
/**
|
/**
|
||||||
* 获取部门树形表格列表
|
* 获取部门列表
|
||||||
*
|
*
|
||||||
* @param queryParams 查询参数(可选)
|
* @param queryParams 查询参数(可选)
|
||||||
* @returns 部门树形表格数据
|
* @returns 部门树形表格数据
|
||||||
@@ -18,11 +17,7 @@ class DeptAPI {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** 获取部门下拉列表 */
|
||||||
* 获取部门下拉列表选项
|
|
||||||
*
|
|
||||||
* @returns 部门下拉列表选项
|
|
||||||
*/
|
|
||||||
static getOptions() {
|
static getOptions() {
|
||||||
return request<any, OptionType[]>({
|
return request<any, OptionType[]>({
|
||||||
url: `${DEPT_BASE_URL}/options`,
|
url: `${DEPT_BASE_URL}/options`,
|
||||||
@@ -87,3 +82,47 @@ class DeptAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default DeptAPI;
|
export default DeptAPI;
|
||||||
|
|
||||||
|
/** 部门查询参数 */
|
||||||
|
export interface DeptQuery {
|
||||||
|
/** 搜索关键字 */
|
||||||
|
keywords?: string;
|
||||||
|
/** 状态 */
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 部门类型 */
|
||||||
|
export interface DeptVO {
|
||||||
|
/** 子部门 */
|
||||||
|
children?: DeptVO[];
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime?: Date;
|
||||||
|
/** 部门ID */
|
||||||
|
id?: number;
|
||||||
|
/** 部门名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 部门编号 */
|
||||||
|
code?: string;
|
||||||
|
/** 父部门ID */
|
||||||
|
parentId?: number;
|
||||||
|
/** 排序 */
|
||||||
|
sort?: number;
|
||||||
|
/** 状态(1:启用;0:禁用) */
|
||||||
|
status?: number;
|
||||||
|
/** 修改时间 */
|
||||||
|
updateTime?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 部门表单类型 */
|
||||||
|
export interface DeptForm {
|
||||||
|
/** 部门ID(新增不填) */
|
||||||
|
id?: number;
|
||||||
|
/** 部门名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 父部门ID */
|
||||||
|
parentId: number;
|
||||||
|
/** 排序 */
|
||||||
|
sort?: number;
|
||||||
|
/** 状态(1:启用;0:禁用) */
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/**
|
|
||||||
* 部门查询参数
|
|
||||||
*/
|
|
||||||
export interface DeptQuery {
|
|
||||||
keywords?: string;
|
|
||||||
status?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门类型
|
|
||||||
*/
|
|
||||||
export interface DeptVO {
|
|
||||||
/**
|
|
||||||
* 子部门
|
|
||||||
*/
|
|
||||||
children?: DeptVO[];
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
createTime?: Date;
|
|
||||||
/**
|
|
||||||
* 部门ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 部门名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 父部门ID
|
|
||||||
*/
|
|
||||||
parentId?: number;
|
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
sort?: number;
|
|
||||||
/**
|
|
||||||
* 状态(1:启用;0:禁用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 修改时间
|
|
||||||
*/
|
|
||||||
updateTime?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门表单类型
|
|
||||||
*/
|
|
||||||
export interface DeptForm {
|
|
||||||
/**
|
|
||||||
* 部门ID(新增不填)
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 部门名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 父部门ID
|
|
||||||
*/
|
|
||||||
parentId: number;
|
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
sort?: number;
|
|
||||||
/**
|
|
||||||
* 状态(1:启用;0:禁用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
}
|
|
||||||
183
src/api/dict.ts
Normal file
183
src/api/dict.ts
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import request from "@/utils/request";
|
||||||
|
|
||||||
|
const DICT_BASE_URL = "/api/v1/dict";
|
||||||
|
|
||||||
|
class DictAPI {
|
||||||
|
/**
|
||||||
|
* 获取字典分页列表
|
||||||
|
*
|
||||||
|
* @param queryParams 查询参数
|
||||||
|
* @returns 字典分页结果
|
||||||
|
*/
|
||||||
|
static getPage(queryParams: DictPageQuery) {
|
||||||
|
return request<any, PageResult<DictPageVO[]>>({
|
||||||
|
url: `${DICT_BASE_URL}/page`,
|
||||||
|
method: "get",
|
||||||
|
params: queryParams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字典表单数据
|
||||||
|
*
|
||||||
|
* @param id 字典ID
|
||||||
|
* @returns 字典表单数据
|
||||||
|
*/
|
||||||
|
static getFormData(id: number) {
|
||||||
|
return request<any, ResponseData<DictForm>>({
|
||||||
|
url: `${DICT_BASE_URL}/${id}/form`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增字典
|
||||||
|
*
|
||||||
|
* @param data 字典表单数据
|
||||||
|
* @returns 请求结果
|
||||||
|
*/
|
||||||
|
static add(data: DictForm) {
|
||||||
|
return request({
|
||||||
|
url: `${DICT_BASE_URL}`,
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改字典
|
||||||
|
*
|
||||||
|
* @param id 字典ID
|
||||||
|
* @param data 字典表单数据
|
||||||
|
* @returns 请求结果
|
||||||
|
*/
|
||||||
|
static update(id: number, data: DictForm) {
|
||||||
|
return request({
|
||||||
|
url: `${DICT_BASE_URL}/${id}`,
|
||||||
|
method: "put",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除字典
|
||||||
|
*
|
||||||
|
* @param ids 字典ID,多个以英文逗号(,)分隔
|
||||||
|
* @returns 请求结果
|
||||||
|
*/
|
||||||
|
static deleteByIds(ids: string) {
|
||||||
|
return request({
|
||||||
|
url: `${DICT_BASE_URL}/${ids}`,
|
||||||
|
method: "delete",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字典的数据项
|
||||||
|
*
|
||||||
|
* @param typeCode 字典编码
|
||||||
|
* @returns 字典数据项
|
||||||
|
*/
|
||||||
|
static getOptions(code: string) {
|
||||||
|
return request<any, OptionType[]>({
|
||||||
|
url: `${DICT_BASE_URL}/${code}/options`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DictAPI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典查询参数
|
||||||
|
*/
|
||||||
|
export interface DictPageQuery extends PageQuery {
|
||||||
|
/**
|
||||||
|
* 关键字(字典名称/编码)
|
||||||
|
*/
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典分页对象
|
||||||
|
*/
|
||||||
|
export interface DictPageVO {
|
||||||
|
/**
|
||||||
|
* 字典ID
|
||||||
|
*/
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* 字典名称
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* 字典编码
|
||||||
|
*/
|
||||||
|
code: string;
|
||||||
|
/**
|
||||||
|
* 字典状态(1-启用,0-禁用)
|
||||||
|
*/
|
||||||
|
status: number;
|
||||||
|
/**
|
||||||
|
* 字典项列表
|
||||||
|
*/
|
||||||
|
dictItems: DictItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典项
|
||||||
|
*/
|
||||||
|
export interface DictItem {
|
||||||
|
/**
|
||||||
|
* 字典项ID
|
||||||
|
*/
|
||||||
|
id?: number;
|
||||||
|
/**
|
||||||
|
* 字典项名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* 字典项值
|
||||||
|
*/
|
||||||
|
value?: string;
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*/
|
||||||
|
sort?: number;
|
||||||
|
/**
|
||||||
|
* 状态(1-启用,0-禁用)
|
||||||
|
*/
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeScript 类型声明
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典
|
||||||
|
*/
|
||||||
|
export interface DictForm {
|
||||||
|
/**
|
||||||
|
* 字典ID
|
||||||
|
*/
|
||||||
|
id?: number;
|
||||||
|
/**
|
||||||
|
* 字典名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* 字典编码
|
||||||
|
*/
|
||||||
|
code?: string;
|
||||||
|
/**
|
||||||
|
* 字典状态(1-启用,0-禁用)
|
||||||
|
*/
|
||||||
|
status?: number;
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
remark?: string;
|
||||||
|
/**
|
||||||
|
* 字典数据项列表
|
||||||
|
*/
|
||||||
|
dictItems?: DictItem[];
|
||||||
|
}
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
import request from "@/utils/request";
|
|
||||||
import {
|
|
||||||
DictTypeQuery,
|
|
||||||
DictTypePageResult,
|
|
||||||
DictTypeForm,
|
|
||||||
DictQuery,
|
|
||||||
DictForm,
|
|
||||||
DictPageResult,
|
|
||||||
} from "./model";
|
|
||||||
|
|
||||||
const DICT_BASE_URL = "/api/v1/dict";
|
|
||||||
|
|
||||||
class DictAPI {
|
|
||||||
/**
|
|
||||||
* 获取字典类型分页列表
|
|
||||||
*
|
|
||||||
* @param queryParams 查询参数
|
|
||||||
* @returns 字典类型分页结果
|
|
||||||
*/
|
|
||||||
static getDictTypePage(queryParams: DictTypeQuery) {
|
|
||||||
return request<any, DictTypePageResult>({
|
|
||||||
url: `${DICT_BASE_URL}/types/page`,
|
|
||||||
method: "get",
|
|
||||||
params: queryParams,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取字典类型表单数据
|
|
||||||
*
|
|
||||||
* @param id 字典类型ID
|
|
||||||
* @returns 字典类型表单数据
|
|
||||||
*/
|
|
||||||
static getDictTypeForm(id: number) {
|
|
||||||
return request<any, ResponseData<DictTypeForm>>({
|
|
||||||
url: `${DICT_BASE_URL}/types/${id}/form`,
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增字典类型
|
|
||||||
*
|
|
||||||
* @param data 字典类型表单数据
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static addDictType(data: DictTypeForm) {
|
|
||||||
return request({
|
|
||||||
url: `${DICT_BASE_URL}/types`,
|
|
||||||
method: "post",
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改字典类型
|
|
||||||
*
|
|
||||||
* @param id 字典类型ID
|
|
||||||
* @param data 字典类型表单数据
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static updateDictType(id: number, data: DictTypeForm) {
|
|
||||||
return request({
|
|
||||||
url: `${DICT_BASE_URL}/types/${id}`,
|
|
||||||
method: "put",
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除字典类型
|
|
||||||
*
|
|
||||||
* @param ids 字典类型ID,多个以英文逗号(,)分隔
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static deleteDictTypes(ids: string) {
|
|
||||||
return request({
|
|
||||||
url: `${DICT_BASE_URL}/types/${ids}`,
|
|
||||||
method: "delete",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取字典类型的数据项
|
|
||||||
*
|
|
||||||
* @param typeCode 字典类型编码
|
|
||||||
* @returns 字典类型的数据项
|
|
||||||
*/
|
|
||||||
static getDictOptions(typeCode: string) {
|
|
||||||
return request<any, OptionType[]>({
|
|
||||||
url: `${DICT_BASE_URL}/${typeCode}/options`,
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取字典分页列表
|
|
||||||
*
|
|
||||||
* @param queryParams 查询参数
|
|
||||||
* @returns 字典分页结果
|
|
||||||
*/
|
|
||||||
static getDictPage(queryParams: DictQuery) {
|
|
||||||
return request<any, DictPageResult>({
|
|
||||||
url: `${DICT_BASE_URL}/page`,
|
|
||||||
method: "get",
|
|
||||||
params: queryParams,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取字典表单数据
|
|
||||||
*
|
|
||||||
* @param id 字典项ID
|
|
||||||
* @returns 字典表单数据
|
|
||||||
*/
|
|
||||||
static getDictFormData(id: number) {
|
|
||||||
return request<any, DictForm>({
|
|
||||||
url: `${DICT_BASE_URL}/${id}/form`,
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增字典
|
|
||||||
*
|
|
||||||
* @param data 字典表单数据
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static addDict(data: DictForm) {
|
|
||||||
return request({
|
|
||||||
url: `${DICT_BASE_URL}`,
|
|
||||||
method: "post",
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改字典项
|
|
||||||
*
|
|
||||||
* @param id 字典项ID
|
|
||||||
* @param data 字典表单数据
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static updateDict(id: number, data: DictForm) {
|
|
||||||
return request({
|
|
||||||
url: `${DICT_BASE_URL}/${id}`,
|
|
||||||
method: "put",
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除字典
|
|
||||||
*
|
|
||||||
* @param ids 字典项ID,多个以英文逗号(,)分隔
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static deleteDictByIds(ids: string) {
|
|
||||||
return request({
|
|
||||||
url: `${DICT_BASE_URL}/${ids}`,
|
|
||||||
method: "delete",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DictAPI;
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
/**
|
|
||||||
* 字典类型查询参数
|
|
||||||
*/
|
|
||||||
export interface DictTypeQuery extends PageQuery {
|
|
||||||
/**
|
|
||||||
* 关键字(字典类型名称/编码)
|
|
||||||
*/
|
|
||||||
keywords?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字典类型分页对象
|
|
||||||
*/
|
|
||||||
export interface DictTypePageVO {
|
|
||||||
/**
|
|
||||||
* 字典类型ID
|
|
||||||
*/
|
|
||||||
id: number;
|
|
||||||
/**
|
|
||||||
* 类型编码
|
|
||||||
*/
|
|
||||||
code: string;
|
|
||||||
/**
|
|
||||||
* 类型名称
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
/**
|
|
||||||
* 状态(1:启用;0:禁用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 备注
|
|
||||||
*/
|
|
||||||
remark?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字典分页项类型声明
|
|
||||||
*/
|
|
||||||
export type DictTypePageResult = PageResult<DictTypePageVO[]>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字典表单类型声明
|
|
||||||
*/
|
|
||||||
export interface DictTypeForm {
|
|
||||||
/**
|
|
||||||
* 字典类型ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 类型名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 类型编码
|
|
||||||
*/
|
|
||||||
code?: string;
|
|
||||||
/**
|
|
||||||
* 类型状态:1:启用;0:禁用
|
|
||||||
*/
|
|
||||||
status: number;
|
|
||||||
/**
|
|
||||||
* 备注
|
|
||||||
*/
|
|
||||||
remark?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字典查询参数
|
|
||||||
*/
|
|
||||||
export interface DictQuery extends PageQuery {
|
|
||||||
/**
|
|
||||||
* 字典项名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 字典类型编码
|
|
||||||
*/
|
|
||||||
typeCode?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字典分页对象
|
|
||||||
*/
|
|
||||||
export interface DictPageVO {
|
|
||||||
/**
|
|
||||||
* 字典ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 字典名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 状态(1:启用;0:禁用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 字典值
|
|
||||||
*/
|
|
||||||
value?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字典分页
|
|
||||||
*/
|
|
||||||
export type DictPageResult = PageResult<DictPageVO[]>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字典表单
|
|
||||||
*/
|
|
||||||
export interface DictForm {
|
|
||||||
/**
|
|
||||||
* 字典ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 字典名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
sort?: number;
|
|
||||||
/**
|
|
||||||
* 状态(1:启用;0:禁用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 类型编码
|
|
||||||
*/
|
|
||||||
typeCode?: string;
|
|
||||||
/**
|
|
||||||
* 值
|
|
||||||
*/
|
|
||||||
value?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 备注
|
|
||||||
*/
|
|
||||||
remark?: string;
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
import { FileInfo } from "./model";
|
|
||||||
|
|
||||||
class FileAPI {
|
class FileAPI {
|
||||||
/**
|
/**
|
||||||
@@ -35,3 +34,13 @@ class FileAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default FileAPI;
|
export default FileAPI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件API类型声明
|
||||||
|
*/
|
||||||
|
export interface FileInfo {
|
||||||
|
/** 文件名 */
|
||||||
|
name: string;
|
||||||
|
/** 文件路径 */
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* 文件API类型声明
|
|
||||||
*/
|
|
||||||
export interface FileInfo {
|
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
209
src/api/menu.ts
Normal file
209
src/api/menu.ts
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
import request from "@/utils/request";
|
||||||
|
// 菜单基础URL
|
||||||
|
const MENU_BASE_URL = "/api/v1/menus";
|
||||||
|
|
||||||
|
class MenuAPI {
|
||||||
|
/**
|
||||||
|
* 获取路由列表
|
||||||
|
*
|
||||||
|
* @returns 路由列表
|
||||||
|
*/
|
||||||
|
static getRoutes() {
|
||||||
|
return request<any, RouteVO[]>({
|
||||||
|
url: `${MENU_BASE_URL}/routes`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取菜单树形列表
|
||||||
|
*
|
||||||
|
* @param queryParams 查询参数
|
||||||
|
* @returns 菜单树形列表
|
||||||
|
*/
|
||||||
|
static getList(queryParams: MenuQuery) {
|
||||||
|
return request<any, MenuVO[]>({
|
||||||
|
url: `${MENU_BASE_URL}`,
|
||||||
|
method: "get",
|
||||||
|
params: queryParams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取菜单下拉数据源
|
||||||
|
*
|
||||||
|
* @returns 菜单下拉数据源
|
||||||
|
*/
|
||||||
|
static getOptions() {
|
||||||
|
return request<any, OptionType[]>({
|
||||||
|
url: `${MENU_BASE_URL}/options`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取菜单表单数据
|
||||||
|
*
|
||||||
|
* @param id 菜单ID
|
||||||
|
* @returns 菜单表单数据
|
||||||
|
*/
|
||||||
|
static getFormData(id: number) {
|
||||||
|
return request<any, MenuForm>({
|
||||||
|
url: `${MENU_BASE_URL}/${id}/form`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加菜单
|
||||||
|
*
|
||||||
|
* @param data 菜单表单数据
|
||||||
|
* @returns 请求结果
|
||||||
|
*/
|
||||||
|
static add(data: MenuForm) {
|
||||||
|
return request({
|
||||||
|
url: `${MENU_BASE_URL}`,
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改菜单
|
||||||
|
*
|
||||||
|
* @param id 菜单ID
|
||||||
|
* @param data 菜单表单数据
|
||||||
|
* @returns 请求结果
|
||||||
|
*/
|
||||||
|
static update(id: string, data: MenuForm) {
|
||||||
|
return request({
|
||||||
|
url: `${MENU_BASE_URL}/${id}`,
|
||||||
|
method: "put",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除菜单
|
||||||
|
*
|
||||||
|
* @param id 菜单ID
|
||||||
|
* @returns 请求结果
|
||||||
|
*/
|
||||||
|
static deleteById(id: number) {
|
||||||
|
return request({
|
||||||
|
url: `${MENU_BASE_URL}/${id}`,
|
||||||
|
method: "delete",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MenuAPI;
|
||||||
|
|
||||||
|
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
|
||||||
|
|
||||||
|
/** 菜单查询参数 */
|
||||||
|
export interface MenuQuery {
|
||||||
|
/** 搜索关键字 */
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 菜单视图对象 */
|
||||||
|
export interface MenuVO {
|
||||||
|
/** 子菜单 */
|
||||||
|
children?: MenuVO[];
|
||||||
|
/** 组件路径 */
|
||||||
|
component?: string;
|
||||||
|
/** ICON */
|
||||||
|
icon?: string;
|
||||||
|
/** 菜单ID */
|
||||||
|
id?: number;
|
||||||
|
/** 菜单名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 父菜单ID */
|
||||||
|
parentId?: number;
|
||||||
|
/** 按钮权限标识 */
|
||||||
|
perm?: string;
|
||||||
|
/** 跳转路径 */
|
||||||
|
redirect?: string;
|
||||||
|
/** 路由名称 */
|
||||||
|
routeName?: string;
|
||||||
|
/** 路由相对路径 */
|
||||||
|
routePath?: string;
|
||||||
|
/** 菜单排序(数字越小排名越靠前) */
|
||||||
|
sort?: number;
|
||||||
|
/** 菜单 */
|
||||||
|
type?: MenuTypeEnum;
|
||||||
|
/** 菜单是否可见(1:显示;0:隐藏) */
|
||||||
|
visible?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 菜单表单对象 */
|
||||||
|
export interface MenuForm {
|
||||||
|
/** 菜单ID */
|
||||||
|
id?: string;
|
||||||
|
/** 父菜单ID */
|
||||||
|
parentId?: number;
|
||||||
|
/** 菜单名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 菜单是否可见(1-是 0-否) */
|
||||||
|
visible: number;
|
||||||
|
/** ICON */
|
||||||
|
icon?: string;
|
||||||
|
/** 排序 */
|
||||||
|
sort?: number;
|
||||||
|
/** 路由名称 */
|
||||||
|
routeName?: string;
|
||||||
|
/** 路由路径 */
|
||||||
|
routePath?: string;
|
||||||
|
/** 组件路径 */
|
||||||
|
component?: string;
|
||||||
|
/** 跳转路由路径 */
|
||||||
|
redirect?: string;
|
||||||
|
/** 菜单 */
|
||||||
|
type?: MenuTypeEnum;
|
||||||
|
/** 权限标识 */
|
||||||
|
perm?: string;
|
||||||
|
/** 【菜单】是否开启页面缓存 */
|
||||||
|
keepAlive?: number;
|
||||||
|
/** 【目录】只有一个子路由是否始终显示 */
|
||||||
|
alwaysShow?: number;
|
||||||
|
/** 参数 */
|
||||||
|
params?: KeyValue[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface KeyValue {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** RouteVO,路由对象 */
|
||||||
|
export interface RouteVO {
|
||||||
|
/** 子路由列表 */
|
||||||
|
children: RouteVO[];
|
||||||
|
/** 组件路径 */
|
||||||
|
component?: string;
|
||||||
|
/** 路由属性 */
|
||||||
|
meta?: Meta;
|
||||||
|
/** 路由名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 路由路径 */
|
||||||
|
path?: string;
|
||||||
|
/** 跳转链接 */
|
||||||
|
redirect?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Meta,路由属性 */
|
||||||
|
export interface Meta {
|
||||||
|
/** 【目录】只有一个子路由是否始终显示 */
|
||||||
|
alwaysShow?: boolean;
|
||||||
|
/** 是否隐藏(true-是 false-否) */
|
||||||
|
hidden?: boolean;
|
||||||
|
/** ICON */
|
||||||
|
icon?: string;
|
||||||
|
/** 【菜单】是否开启页面缓存 */
|
||||||
|
keepAlive?: boolean;
|
||||||
|
/** 拥有路由权限的角色编码 */
|
||||||
|
roles?: string[];
|
||||||
|
/** 路由title */
|
||||||
|
title?: string;
|
||||||
|
}
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
import request from "@/utils/request";
|
|
||||||
import { MenuQuery, MenuVO, MenuForm, RouteVO } from "./model";
|
|
||||||
|
|
||||||
const MENU_BASE_URL = "/api/v1/menus";
|
|
||||||
|
|
||||||
class MenuAPI {
|
|
||||||
/**
|
|
||||||
* 获取路由列表
|
|
||||||
*
|
|
||||||
* @returns 路由列表
|
|
||||||
*/
|
|
||||||
static getRoutes() {
|
|
||||||
return request<any, RouteVO[]>({
|
|
||||||
url: `${MENU_BASE_URL}/routes`,
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取菜单树形列表
|
|
||||||
*
|
|
||||||
* @param queryParams 查询参数
|
|
||||||
* @returns 菜单树形列表
|
|
||||||
*/
|
|
||||||
static getList(queryParams: MenuQuery) {
|
|
||||||
return request<any, MenuVO[]>({
|
|
||||||
url: `${MENU_BASE_URL}`,
|
|
||||||
method: "get",
|
|
||||||
params: queryParams,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取菜单下拉数据源
|
|
||||||
*
|
|
||||||
* @returns 菜单下拉数据源
|
|
||||||
*/
|
|
||||||
static getOptions() {
|
|
||||||
return request<any, OptionType[]>({
|
|
||||||
url: `${MENU_BASE_URL}/options`,
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取菜单表单数据
|
|
||||||
*
|
|
||||||
* @param id 菜单ID
|
|
||||||
* @returns 菜单表单数据
|
|
||||||
*/
|
|
||||||
static getFormData(id: number) {
|
|
||||||
return request<any, MenuForm>({
|
|
||||||
url: `${MENU_BASE_URL}/${id}/form`,
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加菜单
|
|
||||||
*
|
|
||||||
* @param data 菜单表单数据
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static add(data: MenuForm) {
|
|
||||||
return request({
|
|
||||||
url: `${MENU_BASE_URL}`,
|
|
||||||
method: "post",
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改菜单
|
|
||||||
*
|
|
||||||
* @param id 菜单ID
|
|
||||||
* @param data 菜单表单数据
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static update(id: string, data: MenuForm) {
|
|
||||||
return request({
|
|
||||||
url: `${MENU_BASE_URL}/${id}`,
|
|
||||||
method: "put",
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除菜单
|
|
||||||
*
|
|
||||||
* @param id 菜单ID
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static deleteById(id: number) {
|
|
||||||
return request({
|
|
||||||
url: `${MENU_BASE_URL}/${id}`,
|
|
||||||
method: "delete",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MenuAPI;
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜单查询参数类型
|
|
||||||
*/
|
|
||||||
export interface MenuQuery {
|
|
||||||
keywords?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜单视图对象类型
|
|
||||||
*/
|
|
||||||
export interface MenuVO {
|
|
||||||
/**
|
|
||||||
* 子菜单
|
|
||||||
*/
|
|
||||||
children?: MenuVO[];
|
|
||||||
/**
|
|
||||||
* 组件路径
|
|
||||||
*/
|
|
||||||
component?: string;
|
|
||||||
/**
|
|
||||||
* ICON
|
|
||||||
*/
|
|
||||||
icon?: string;
|
|
||||||
/**
|
|
||||||
* 菜单ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 菜单名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 父菜单ID
|
|
||||||
*/
|
|
||||||
parentId?: number;
|
|
||||||
/**
|
|
||||||
* 按钮权限标识
|
|
||||||
*/
|
|
||||||
perm?: string;
|
|
||||||
/**
|
|
||||||
* 跳转路径
|
|
||||||
*/
|
|
||||||
redirect?: string;
|
|
||||||
/**
|
|
||||||
* 路由名称
|
|
||||||
*/
|
|
||||||
routeName?: string;
|
|
||||||
/**
|
|
||||||
* 路由相对路径
|
|
||||||
*/
|
|
||||||
routePath?: string;
|
|
||||||
/**
|
|
||||||
* 菜单排序(数字越小排名越靠前)
|
|
||||||
*/
|
|
||||||
sort?: number;
|
|
||||||
/**
|
|
||||||
* 菜单类型
|
|
||||||
*/
|
|
||||||
type?: MenuTypeEnum;
|
|
||||||
/**
|
|
||||||
* 菜单是否可见(1:显示;0:隐藏)
|
|
||||||
*/
|
|
||||||
visible?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜单表单对象类型
|
|
||||||
*/
|
|
||||||
export interface MenuForm {
|
|
||||||
/**
|
|
||||||
* 菜单ID
|
|
||||||
*/
|
|
||||||
id?: string;
|
|
||||||
/**
|
|
||||||
* 父菜单ID
|
|
||||||
*/
|
|
||||||
parentId?: number;
|
|
||||||
/**
|
|
||||||
* 菜单名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 菜单是否可见(1:是;0:否;)
|
|
||||||
*/
|
|
||||||
visible: number;
|
|
||||||
icon?: string;
|
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
sort?: number;
|
|
||||||
/**
|
|
||||||
* 组件路径
|
|
||||||
*/
|
|
||||||
component?: string;
|
|
||||||
/**
|
|
||||||
* 路由路径
|
|
||||||
*/
|
|
||||||
path?: string;
|
|
||||||
/**
|
|
||||||
* 跳转路由路径
|
|
||||||
*/
|
|
||||||
redirect?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜单类型
|
|
||||||
*/
|
|
||||||
type?: MenuTypeEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 权限标识
|
|
||||||
*/
|
|
||||||
perm?: string;
|
|
||||||
/**
|
|
||||||
* 【菜单】是否开启页面缓存
|
|
||||||
*/
|
|
||||||
keepAlive?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 【目录】只有一个子路由是否始终显示
|
|
||||||
*/
|
|
||||||
alwaysShow?: number;
|
|
||||||
|
|
||||||
params?: KeyValue[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface KeyValue {
|
|
||||||
key: string;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RouteVO,路由对象
|
|
||||||
*/
|
|
||||||
export interface RouteVO {
|
|
||||||
/**
|
|
||||||
* 子路由列表
|
|
||||||
*/
|
|
||||||
children: RouteVO[];
|
|
||||||
/**
|
|
||||||
* 组件路径
|
|
||||||
*/
|
|
||||||
component?: string;
|
|
||||||
meta?: Meta;
|
|
||||||
/**
|
|
||||||
* 路由名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 路由路径
|
|
||||||
*/
|
|
||||||
path?: string;
|
|
||||||
/**
|
|
||||||
* 跳转链接
|
|
||||||
*/
|
|
||||||
redirect?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Meta,路由属性类型
|
|
||||||
*/
|
|
||||||
export interface Meta {
|
|
||||||
/**
|
|
||||||
* 【目录】只有一个子路由是否始终显示
|
|
||||||
*/
|
|
||||||
alwaysShow?: boolean;
|
|
||||||
/**
|
|
||||||
* 是否隐藏(true-是 false-否)
|
|
||||||
*/
|
|
||||||
hidden?: boolean;
|
|
||||||
/**
|
|
||||||
* ICON
|
|
||||||
*/
|
|
||||||
icon?: string;
|
|
||||||
/**
|
|
||||||
* 【菜单】是否开启页面缓存
|
|
||||||
*/
|
|
||||||
keepAlive?: boolean;
|
|
||||||
/**
|
|
||||||
* 拥有路由权限的角色编码
|
|
||||||
*/
|
|
||||||
roles?: string[];
|
|
||||||
/**
|
|
||||||
* 路由title
|
|
||||||
*/
|
|
||||||
title?: string;
|
|
||||||
}
|
|
||||||
@@ -1,34 +1,22 @@
|
|||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
import { RoleQuery, RolePageResult, RoleForm } from "./model";
|
|
||||||
|
|
||||||
const ROLE_BASE_URL = "/api/v1/roles";
|
const ROLE_BASE_URL = "/api/v1/roles";
|
||||||
|
|
||||||
class RoleAPI {
|
class RoleAPI {
|
||||||
/**
|
/** 获取角色分页数据 */
|
||||||
* 获取角色分页数据
|
static getPage(queryParams?: RolePageQuery) {
|
||||||
*
|
return request<any, PageResult<RolePageVO[]>>({
|
||||||
* @param queryParams 查询参数
|
|
||||||
* @returns 角色分页数据
|
|
||||||
*/
|
|
||||||
static getPage(queryParams?: RoleQuery) {
|
|
||||||
return request<any, RolePageResult>({
|
|
||||||
url: `${ROLE_BASE_URL}/page`,
|
url: `${ROLE_BASE_URL}/page`,
|
||||||
method: "get",
|
method: "get",
|
||||||
params: queryParams,
|
params: queryParams,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** 获取角色下拉数据源 */
|
||||||
* 获取角色下拉数据源
|
static getOptions() {
|
||||||
*
|
|
||||||
* @param queryParams 查询参数(可选)
|
|
||||||
* @returns 角色下拉数据源
|
|
||||||
*/
|
|
||||||
static getOptions(queryParams?: RoleQuery) {
|
|
||||||
return request<any, OptionType[]>({
|
return request<any, OptionType[]>({
|
||||||
url: `${ROLE_BASE_URL}/options`,
|
url: `${ROLE_BASE_URL}/options`,
|
||||||
method: "get",
|
method: "get",
|
||||||
params: queryParams,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +34,7 @@ class RoleAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分配菜单权限给角色
|
* 分配菜单权限
|
||||||
*
|
*
|
||||||
* @param roleId 角色ID
|
* @param roleId 角色ID
|
||||||
* @param data 菜单ID集合
|
* @param data 菜单ID集合
|
||||||
@@ -73,12 +61,7 @@ class RoleAPI {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** 添加角色 */
|
||||||
* 添加角色
|
|
||||||
*
|
|
||||||
* @param data 角色表单数据
|
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
|
||||||
static add(data: RoleForm) {
|
static add(data: RoleForm) {
|
||||||
return request({
|
return request({
|
||||||
url: `${ROLE_BASE_URL}`,
|
url: `${ROLE_BASE_URL}`,
|
||||||
@@ -92,7 +75,6 @@ class RoleAPI {
|
|||||||
*
|
*
|
||||||
* @param id 角色ID
|
* @param id 角色ID
|
||||||
* @param data 角色表单数据
|
* @param data 角色表单数据
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
*/
|
||||||
static update(id: number, data: RoleForm) {
|
static update(id: number, data: RoleForm) {
|
||||||
return request({
|
return request({
|
||||||
@@ -106,7 +88,6 @@ class RoleAPI {
|
|||||||
* 批量删除角色,多个以英文逗号(,)分割
|
* 批量删除角色,多个以英文逗号(,)分割
|
||||||
*
|
*
|
||||||
* @param ids 角色ID字符串,多个以英文逗号(,)分割
|
* @param ids 角色ID字符串,多个以英文逗号(,)分割
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
*/
|
||||||
static deleteByIds(ids: string) {
|
static deleteByIds(ids: string) {
|
||||||
return request({
|
return request({
|
||||||
@@ -117,3 +98,43 @@ class RoleAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default RoleAPI;
|
export default RoleAPI;
|
||||||
|
|
||||||
|
/** 角色分页查询参数 */
|
||||||
|
export interface RolePageQuery extends PageQuery {
|
||||||
|
/** 搜索关键字 */
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 角色分页对象 */
|
||||||
|
export interface RolePageVO {
|
||||||
|
/** 角色编码 */
|
||||||
|
code?: string;
|
||||||
|
/** 角色ID */
|
||||||
|
id?: number;
|
||||||
|
/** 角色名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 排序 */
|
||||||
|
sort?: number;
|
||||||
|
/** 角色状态 */
|
||||||
|
status?: number;
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime?: Date;
|
||||||
|
/** 修改时间 */
|
||||||
|
updateTime?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 角色表单对象 */
|
||||||
|
export interface RoleForm {
|
||||||
|
/** 角色ID */
|
||||||
|
id?: number;
|
||||||
|
/** 角色编码 */
|
||||||
|
code: string;
|
||||||
|
/** 数据权限 */
|
||||||
|
dataScope?: number;
|
||||||
|
/** 角色名称 */
|
||||||
|
name: string;
|
||||||
|
/** 排序 */
|
||||||
|
sort?: number;
|
||||||
|
/** 角色状态(1-正常;0-停用) */
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/**
|
|
||||||
* 角色查询参数
|
|
||||||
*/
|
|
||||||
export interface RoleQuery extends PageQuery {
|
|
||||||
keywords?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 角色分页对象
|
|
||||||
*/
|
|
||||||
export interface RolePageVO {
|
|
||||||
/**
|
|
||||||
* 角色编码
|
|
||||||
*/
|
|
||||||
code?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 角色ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 角色名称
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
sort?: number;
|
|
||||||
/**
|
|
||||||
* 角色状态
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
createTime?: Date;
|
|
||||||
/**
|
|
||||||
* 修改时间
|
|
||||||
*/
|
|
||||||
updateTime?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 角色分页
|
|
||||||
*/
|
|
||||||
export type RolePageResult = PageResult<RolePageVO[]>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 角色表单对象
|
|
||||||
*/
|
|
||||||
export interface RoleForm {
|
|
||||||
/**
|
|
||||||
* 角色ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 角色编码
|
|
||||||
*/
|
|
||||||
code: string;
|
|
||||||
/**
|
|
||||||
* 数据权限
|
|
||||||
*/
|
|
||||||
dataScope?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 角色名称
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
sort?: number;
|
|
||||||
/**
|
|
||||||
* 角色状态(1-正常;0-停用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
import { UserForm, UserInfo, UserPageVO, UserQuery } from "./model";
|
|
||||||
|
|
||||||
const USER_BASE_URL = "/api/v1/users";
|
const USER_BASE_URL = "/api/v1/users";
|
||||||
|
|
||||||
class UserAPI {
|
class UserAPI {
|
||||||
/**
|
/**
|
||||||
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
|
* 获取当前登录用户信息
|
||||||
*
|
*
|
||||||
* @returns 用户信息
|
* @returns 登录用户昵称、头像信息,包括角色和权限
|
||||||
*/
|
*/
|
||||||
static getInfo() {
|
static getInfo() {
|
||||||
return request<any, UserInfo>({
|
return request<any, UserInfo>({
|
||||||
@@ -20,9 +19,8 @@ class UserAPI {
|
|||||||
* 获取用户分页列表
|
* 获取用户分页列表
|
||||||
*
|
*
|
||||||
* @param queryParams 查询参数
|
* @param queryParams 查询参数
|
||||||
* @returns 用户分页列表
|
|
||||||
*/
|
*/
|
||||||
static getPage(queryParams: UserQuery) {
|
static getPage(queryParams: UserPageQuery) {
|
||||||
return request<any, PageResult<UserPageVO[]>>({
|
return request<any, PageResult<UserPageVO[]>>({
|
||||||
url: `${USER_BASE_URL}/page`,
|
url: `${USER_BASE_URL}/page`,
|
||||||
method: "get",
|
method: "get",
|
||||||
@@ -47,7 +45,6 @@ class UserAPI {
|
|||||||
* 添加用户
|
* 添加用户
|
||||||
*
|
*
|
||||||
* @param data 用户表单数据
|
* @param data 用户表单数据
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
*/
|
||||||
static add(data: UserForm) {
|
static add(data: UserForm) {
|
||||||
return request({
|
return request({
|
||||||
@@ -62,7 +59,6 @@ class UserAPI {
|
|||||||
*
|
*
|
||||||
* @param id 用户ID
|
* @param id 用户ID
|
||||||
* @param data 用户表单数据
|
* @param data 用户表单数据
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
*/
|
||||||
static update(id: number, data: UserForm) {
|
static update(id: number, data: UserForm) {
|
||||||
return request({
|
return request({
|
||||||
@@ -77,7 +73,6 @@ class UserAPI {
|
|||||||
*
|
*
|
||||||
* @param id 用户ID
|
* @param id 用户ID
|
||||||
* @param password 新密码
|
* @param password 新密码
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
*/
|
||||||
static updatePassword(id: number, password: string) {
|
static updatePassword(id: number, password: string) {
|
||||||
return request({
|
return request({
|
||||||
@@ -91,7 +86,6 @@ class UserAPI {
|
|||||||
* 批量删除用户,多个以英文逗号(,)分割
|
* 批量删除用户,多个以英文逗号(,)分割
|
||||||
*
|
*
|
||||||
* @param ids 用户ID字符串,多个以英文逗号(,)分割
|
* @param ids 用户ID字符串,多个以英文逗号(,)分割
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
*/
|
||||||
static deleteByIds(ids: string) {
|
static deleteByIds(ids: string) {
|
||||||
return request({
|
return request({
|
||||||
@@ -100,11 +94,7 @@ class UserAPI {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** 下载用户导入模板 */
|
||||||
* 下载用户导入模板
|
|
||||||
*
|
|
||||||
* @returns 用户导入模板文件
|
|
||||||
*/
|
|
||||||
static downloadTemplate() {
|
static downloadTemplate() {
|
||||||
return request({
|
return request({
|
||||||
url: `${USER_BASE_URL}/template`,
|
url: `${USER_BASE_URL}/template`,
|
||||||
@@ -117,9 +107,8 @@ class UserAPI {
|
|||||||
* 导出用户
|
* 导出用户
|
||||||
*
|
*
|
||||||
* @param queryParams 查询参数
|
* @param queryParams 查询参数
|
||||||
* @returns 导出文件
|
|
||||||
*/
|
*/
|
||||||
static export(queryParams: UserQuery) {
|
static export(queryParams: UserPageQuery) {
|
||||||
return request({
|
return request({
|
||||||
url: `${USER_BASE_URL}/export`,
|
url: `${USER_BASE_URL}/export`,
|
||||||
method: "get",
|
method: "get",
|
||||||
@@ -133,7 +122,6 @@ class UserAPI {
|
|||||||
*
|
*
|
||||||
* @param deptId 部门ID
|
* @param deptId 部门ID
|
||||||
* @param file 导入文件
|
* @param file 导入文件
|
||||||
* @returns 请求结果
|
|
||||||
*/
|
*/
|
||||||
static import(deptId: number, file: File) {
|
static import(deptId: number, file: File) {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
@@ -151,3 +139,94 @@ class UserAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default UserAPI;
|
export default UserAPI;
|
||||||
|
|
||||||
|
/** 登录用户信息 */
|
||||||
|
export interface UserInfo {
|
||||||
|
/** 用户ID */
|
||||||
|
userId?: number;
|
||||||
|
|
||||||
|
/** 用户名 */
|
||||||
|
username?: string;
|
||||||
|
|
||||||
|
/** 昵称 */
|
||||||
|
nickname?: string;
|
||||||
|
|
||||||
|
/** 头像URL */
|
||||||
|
avatar?: string;
|
||||||
|
|
||||||
|
/** 角色 */
|
||||||
|
roles: string[];
|
||||||
|
|
||||||
|
/** 权限 */
|
||||||
|
perms: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户分页查询对象
|
||||||
|
*/
|
||||||
|
export interface UserPageQuery extends PageQuery {
|
||||||
|
/** 搜索关键字 */
|
||||||
|
keywords?: string;
|
||||||
|
|
||||||
|
/** 用户状态 */
|
||||||
|
status?: number;
|
||||||
|
|
||||||
|
/** 部门ID */
|
||||||
|
deptId?: number;
|
||||||
|
|
||||||
|
/** 开始时间 */
|
||||||
|
startTime?: string;
|
||||||
|
|
||||||
|
/** 结束时间 */
|
||||||
|
endTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用户分页对象 */
|
||||||
|
export interface UserPageVO {
|
||||||
|
/** 用户头像URL */
|
||||||
|
avatar?: string;
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime?: Date;
|
||||||
|
/** 部门名称 */
|
||||||
|
deptName?: string;
|
||||||
|
/** 用户邮箱 */
|
||||||
|
email?: string;
|
||||||
|
/** 性别 */
|
||||||
|
genderLabel?: string;
|
||||||
|
/** 用户ID */
|
||||||
|
id?: number;
|
||||||
|
/** 手机号 */
|
||||||
|
mobile?: string;
|
||||||
|
/** 用户昵称 */
|
||||||
|
nickname?: string;
|
||||||
|
/** 角色名称,多个使用英文逗号(,)分割 */
|
||||||
|
roleNames?: string;
|
||||||
|
/** 用户状态(1:启用;0:禁用) */
|
||||||
|
status?: number;
|
||||||
|
/** 用户名 */
|
||||||
|
username?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用户表单类型 */
|
||||||
|
export interface UserForm {
|
||||||
|
/** 用户头像 */
|
||||||
|
avatar?: string;
|
||||||
|
/** 部门ID */
|
||||||
|
deptId?: number;
|
||||||
|
/** 邮箱 */
|
||||||
|
email?: string;
|
||||||
|
/** 性别 */
|
||||||
|
gender?: number;
|
||||||
|
/** 用户ID */
|
||||||
|
id?: number;
|
||||||
|
/** 手机号 */
|
||||||
|
mobile?: string;
|
||||||
|
/** 昵称 */
|
||||||
|
nickname?: string;
|
||||||
|
/** 角色ID集合 */
|
||||||
|
roleIds?: number[];
|
||||||
|
/** 用户状态(1:正常;0:禁用) */
|
||||||
|
status?: number;
|
||||||
|
/** 用户名 */
|
||||||
|
username?: string;
|
||||||
|
}
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
/**
|
|
||||||
* 登录用户信息
|
|
||||||
*/
|
|
||||||
export interface UserInfo {
|
|
||||||
userId?: number;
|
|
||||||
username?: string;
|
|
||||||
nickname?: string;
|
|
||||||
avatar?: string;
|
|
||||||
roles: string[];
|
|
||||||
perms: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户查询对象类型
|
|
||||||
*/
|
|
||||||
export interface UserQuery extends PageQuery {
|
|
||||||
keywords?: string;
|
|
||||||
status?: number;
|
|
||||||
deptId?: number;
|
|
||||||
startTime?: string;
|
|
||||||
endTime?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户分页对象
|
|
||||||
*/
|
|
||||||
export interface UserPageVO {
|
|
||||||
/**
|
|
||||||
* 用户头像地址
|
|
||||||
*/
|
|
||||||
avatar?: string;
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
createTime?: Date;
|
|
||||||
/**
|
|
||||||
* 部门名称
|
|
||||||
*/
|
|
||||||
deptName?: string;
|
|
||||||
/**
|
|
||||||
* 用户邮箱
|
|
||||||
*/
|
|
||||||
email?: string;
|
|
||||||
/**
|
|
||||||
* 性别
|
|
||||||
*/
|
|
||||||
genderLabel?: string;
|
|
||||||
/**
|
|
||||||
* 用户ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 手机号
|
|
||||||
*/
|
|
||||||
mobile?: string;
|
|
||||||
/**
|
|
||||||
* 用户昵称
|
|
||||||
*/
|
|
||||||
nickname?: string;
|
|
||||||
/**
|
|
||||||
* 角色名称,多个使用英文逗号(,)分割
|
|
||||||
*/
|
|
||||||
roleNames?: string;
|
|
||||||
/**
|
|
||||||
* 用户状态(1:启用;0:禁用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户表单类型
|
|
||||||
*/
|
|
||||||
export interface UserForm {
|
|
||||||
/**
|
|
||||||
* 用户头像
|
|
||||||
*/
|
|
||||||
avatar?: string;
|
|
||||||
/**
|
|
||||||
* 部门ID
|
|
||||||
*/
|
|
||||||
deptId?: number;
|
|
||||||
/**
|
|
||||||
* 邮箱
|
|
||||||
*/
|
|
||||||
email?: string;
|
|
||||||
/**
|
|
||||||
* 性别
|
|
||||||
*/
|
|
||||||
gender?: number;
|
|
||||||
/**
|
|
||||||
* 用户ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
mobile?: string;
|
|
||||||
/**
|
|
||||||
* 昵称
|
|
||||||
*/
|
|
||||||
nickname?: string;
|
|
||||||
/**
|
|
||||||
* 角色ID集合
|
|
||||||
*/
|
|
||||||
roleIds?: number[];
|
|
||||||
/**
|
|
||||||
* 用户状态(1:正常;0:禁用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username?: string;
|
|
||||||
}
|
|
||||||
@@ -20,9 +20,9 @@ import DictAPI from "@/api/dict";
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
/**
|
/**
|
||||||
* 字典类型编码(eg: 性别-gender)
|
* 字典编码(eg: 性别-gender)
|
||||||
*/
|
*/
|
||||||
typeCode: {
|
code: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
@@ -39,14 +39,17 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits(["update:modelValue"]); // 父组件监听事件,同步子组件值的变化给父组件
|
const emits = defineEmits(["update:modelValue"]);
|
||||||
|
|
||||||
const options: Ref<OptionType[]> = ref([]); // 字典下拉数据源
|
const options: Ref<OptionType[]> = ref([]);
|
||||||
|
|
||||||
const selectedValue = ref<string | number | undefined>();
|
const selectedValue = ref<string | number | undefined>();
|
||||||
|
|
||||||
watch([options, () => props.modelValue], ([newOptions, newModelValue]) => {
|
watch([options, () => props.modelValue], ([newOptions, newModelValue]) => {
|
||||||
if (newOptions.length === 0) return; // 下拉数据源加载未完成不回显
|
if (newOptions.length === 0) {
|
||||||
|
// 下拉数据源加载未完成不回显
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (newModelValue == undefined) {
|
if (newModelValue == undefined) {
|
||||||
selectedValue.value = undefined;
|
selectedValue.value = undefined;
|
||||||
return;
|
return;
|
||||||
@@ -65,8 +68,8 @@ function handleChange(val?: string | number | undefined) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
// 根据字典类型编码(typeCode)获取字典选项
|
// 根据字典编码获取字典项
|
||||||
DictAPI.getDictOptions(props.typeCode).then((data) => {
|
DictAPI.getOptions(props.code).then((data) => {
|
||||||
options.value = data;
|
options.value = data;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { RouteRecordRaw } from "vue-router";
|
|||||||
import { constantRoutes } from "@/router";
|
import { constantRoutes } from "@/router";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import MenuAPI from "@/api/menu";
|
import MenuAPI from "@/api/menu";
|
||||||
import { RouteVO } from "@/api/menu/model";
|
import { RouteVO } from "@/api/menu/types";
|
||||||
|
|
||||||
const modules = import.meta.glob("../../views/**/**.vue");
|
const modules = import.meta.glob("../../views/**/**.vue");
|
||||||
const Layout = () => import("@/layout/index.vue");
|
const Layout = () => import("@/layout/index.vue");
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import UserAPI from "@/api/user";
|
|||||||
import { resetRouter } from "@/router";
|
import { resetRouter } from "@/router";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
|
|
||||||
import { LoginData } from "@/api/auth/model";
|
import { LoginData } from "@/api/auth";
|
||||||
import { UserInfo } from "@/api/user/model";
|
import { UserInfo } from "@/api/user";
|
||||||
import { TOKEN_KEY } from "@/enums/CacheEnum";
|
import { TOKEN_KEY } from "@/enums/CacheEnum";
|
||||||
|
|
||||||
export const useUserStore = defineStore("user", () => {
|
export const useUserStore = defineStore("user", () => {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ declare module "vue" {
|
|||||||
Breadcrumb: (typeof import("./../components/Breadcrumb/index.vue"))["default"];
|
Breadcrumb: (typeof import("./../components/Breadcrumb/index.vue"))["default"];
|
||||||
CURD: (typeof import("./../components/CURD/index.vue"))["default"];
|
CURD: (typeof import("./../components/CURD/index.vue"))["default"];
|
||||||
DeptTree: (typeof import("./../views/system/user/components/dept-tree.vue"))["default"];
|
DeptTree: (typeof import("./../views/system/user/components/dept-tree.vue"))["default"];
|
||||||
|
UserImport: (typeof import("./../views/system/user/components/user-import.vue"))["default"];
|
||||||
Dictionary: (typeof import("./../components/Dictionary/index.vue"))["default"];
|
Dictionary: (typeof import("./../components/Dictionary/index.vue"))["default"];
|
||||||
DictItem: (typeof import("./../views/system/dict/components/dict-item.vue"))["default"];
|
DictItem: (typeof import("./../views/system/dict/components/dict-item.vue"))["default"];
|
||||||
ElBacktop: (typeof import("element-plus/es"))["ElBacktop"];
|
ElBacktop: (typeof import("element-plus/es"))["ElBacktop"];
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import DeptAPI from "@/api/dept";
|
import DeptAPI from "@/api/dept";
|
||||||
import RoleAPI from "@/api/role";
|
import RoleAPI from "@/api/role";
|
||||||
import UserAPI from "@/api/user";
|
import UserAPI, { UserForm } from "@/api/user";
|
||||||
import type { UserForm } from "@/api/user/model";
|
|
||||||
import type { IModalConfig } from "@/components/CURD/types";
|
import type { IModalConfig } from "@/components/CURD/types";
|
||||||
|
|
||||||
const modalConfig: IModalConfig<UserForm> = {
|
const modalConfig: IModalConfig<UserForm> = {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import UserAPI from "@/api/user";
|
import UserAPI from "@/api/user";
|
||||||
import RoleAPI from "@/api/role";
|
import RoleAPI from "@/api/role";
|
||||||
import type { UserQuery } from "@/api/user/model";
|
import type { UserPageQuery } from "@/api/user";
|
||||||
import type { IContentConfig } from "@/components/CURD/types";
|
import type { IContentConfig } from "@/components/CURD/types";
|
||||||
|
|
||||||
const contentConfig: IContentConfig<UserQuery> = {
|
const contentConfig: IContentConfig<UserPageQuery> = {
|
||||||
pageName: "sys:user",
|
pageName: "sys:user",
|
||||||
table: {
|
table: {
|
||||||
border: true,
|
border: true,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import DeptAPI from "@/api/dept";
|
import DeptAPI from "@/api/dept";
|
||||||
import RoleAPI from "@/api/role";
|
import RoleAPI from "@/api/role";
|
||||||
import UserAPI from "@/api/user";
|
import UserAPI from "@/api/user";
|
||||||
import type { UserForm } from "@/api/user/model";
|
import type { UserForm } from "@/api/user";
|
||||||
import type { IModalConfig } from "@/components/CURD/types";
|
import type { IModalConfig } from "@/components/CURD/types";
|
||||||
import { DeviceEnum } from "@/enums/DeviceEnum";
|
import { DeviceEnum } from "@/enums/DeviceEnum";
|
||||||
import { useAppStore } from "@/store";
|
import { useAppStore } from "@/store";
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
@submit-click="handleSubmitClick"
|
@submit-click="handleSubmitClick"
|
||||||
>
|
>
|
||||||
<template #gender="scope">
|
<template #gender="scope">
|
||||||
<dictionary v-model="scope.formData[scope.prop]" type-code="gender" />
|
<dictionary v-model="scope.formData[scope.prop]" code="gender" />
|
||||||
</template>
|
</template>
|
||||||
</page-modal>
|
</page-modal>
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
@submit-click="handleSubmitClick"
|
@submit-click="handleSubmitClick"
|
||||||
>
|
>
|
||||||
<template #gender="scope">
|
<template #gender="scope">
|
||||||
<dictionary v-model="scope.formData[scope.prop]" type-code="gender" />
|
<dictionary v-model="scope.formData[scope.prop]" code="gender" />
|
||||||
</template>
|
</template>
|
||||||
</page-modal>
|
</page-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ const numberValue = ref(1); // 性别(值为Number)
|
|||||||
>
|
>
|
||||||
<el-form>
|
<el-form>
|
||||||
<el-form-item label="性别">
|
<el-form-item label="性别">
|
||||||
<dictionary v-model="stringValue" type-code="gender" />
|
<dictionary v-model="stringValue" code="gender" />
|
||||||
<el-link :underline="false" type="primary" class="ml-5"
|
<el-link :underline="false" type="primary" class="ml-5"
|
||||||
>值为String: const value = ref("1");
|
>值为String: const value = ref("1");
|
||||||
</el-link>
|
</el-link>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="性别">
|
<el-form-item label="性别">
|
||||||
<dictionary v-model="numberValue" type-code="gender" />
|
<dictionary v-model="numberValue" code="gender" />
|
||||||
<el-link :underline="false" type="success" class="ml-5"
|
<el-link :underline="false" type="success" class="ml-5"
|
||||||
>值为Number: const value = ref(1);
|
>值为Number: const value = ref(1);
|
||||||
</el-link>
|
</el-link>
|
||||||
|
|||||||
@@ -116,7 +116,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useSettingsStore, useUserStore } from "@/store";
|
import { useSettingsStore, useUserStore } from "@/store";
|
||||||
import AuthAPI from "@/api/auth";
|
import AuthAPI from "@/api/auth";
|
||||||
import { LoginData } from "@/api/auth/model";
|
import { LoginData } from "@/api/auth/types";
|
||||||
import type { FormInstance } from "element-plus";
|
import type { FormInstance } from "element-plus";
|
||||||
import { LocationQuery, useRoute } from "vue-router";
|
import { LocationQuery, useRoute } from "vue-router";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:dept:add']"
|
v-hasPerm="['sys:dept:add']"
|
||||||
type="success"
|
type="success"
|
||||||
@click="openDialog(0, undefined)"
|
@click="handleOpenDialog(0, undefined)"
|
||||||
><i-ep-plus />新增</el-button
|
><i-ep-plus />新增</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
>
|
>
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
<el-table-column prop="name" label="部门名称" min-width="200" />
|
<el-table-column prop="name" label="部门名称" min-width="200" />
|
||||||
|
<el-table-column prop="code" label="部门编号" width="200" />
|
||||||
<el-table-column prop="status" label="状态" width="100">
|
<el-table-column prop="status" label="状态" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.status == 1" type="success">正常</el-tag>
|
<el-tag v-if="scope.row.status == 1" type="success">正常</el-tag>
|
||||||
@@ -76,7 +77,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click.stop="openDialog(scope.row.id, undefined)"
|
@click.stop="handleOpenDialog(scope.row.id, undefined)"
|
||||||
><i-ep-plus />新增
|
><i-ep-plus />新增
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -84,7 +85,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click.stop="openDialog(scope.row.parentId, scope.row.id)"
|
@click.stop="handleOpenDialog(scope.row.parentId, scope.row.id)"
|
||||||
><i-ep-edit />编辑
|
><i-ep-edit />编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -105,7 +106,7 @@
|
|||||||
v-model="dialog.visible"
|
v-model="dialog.visible"
|
||||||
:title="dialog.title"
|
:title="dialog.title"
|
||||||
width="600px"
|
width="600px"
|
||||||
@closed="closeDialog"
|
@closed="handleCloseDialog"
|
||||||
>
|
>
|
||||||
<el-form
|
<el-form
|
||||||
ref="deptFormRef"
|
ref="deptFormRef"
|
||||||
@@ -126,6 +127,9 @@
|
|||||||
<el-form-item label="部门名称" prop="name">
|
<el-form-item label="部门名称" prop="name">
|
||||||
<el-input v-model="formData.name" placeholder="请输入部门名称" />
|
<el-input v-model="formData.name" placeholder="请输入部门名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="部门编号" prop="code">
|
||||||
|
<el-input v-model="formData.code" placeholder="请输入部门编号" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="显示排序" prop="sort">
|
<el-form-item label="显示排序" prop="sort">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="formData.sort"
|
v-model="formData.sort"
|
||||||
@@ -145,7 +149,7 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button type="primary" @click="handleSubmit"> 确 定 </el-button>
|
<el-button type="primary" @click="handleSubmit"> 确 定 </el-button>
|
||||||
<el-button @click="closeDialog"> 取 消 </el-button>
|
<el-button @click="handleCloseDialog"> 取 消 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -158,8 +162,7 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import DeptAPI from "@/api/dept";
|
import DeptAPI, { DeptVO, DeptForm, DeptQuery } from "@/api/dept";
|
||||||
import { DeptVO, DeptForm, DeptQuery } from "@/api/dept/model";
|
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
const deptFormRef = ref(ElForm);
|
const deptFormRef = ref(ElForm);
|
||||||
@@ -183,12 +186,15 @@ const formData = reactive<DeptForm>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
parentId: [{ required: true, message: "上级部门不能为空", trigger: "blur" }],
|
parentId: [
|
||||||
|
{ required: true, message: "上级部门不能为空", trigger: "change" },
|
||||||
|
],
|
||||||
name: [{ required: true, message: "部门名称不能为空", trigger: "blur" }],
|
name: [{ required: true, message: "部门名称不能为空", trigger: "blur" }],
|
||||||
|
code: [{ required: true, message: "部门编号不能为空", trigger: "blur" }],
|
||||||
sort: [{ required: true, message: "显示排序不能为空", trigger: "blur" }],
|
sort: [{ required: true, message: "显示排序不能为空", trigger: "blur" }],
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 查询 */
|
/** 查询部门 */
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
DeptAPI.getList(queryParams).then((data) => {
|
DeptAPI.getList(queryParams).then((data) => {
|
||||||
@@ -208,9 +214,15 @@ function handleSelectionChange(selection: any) {
|
|||||||
ids.value = selection.map((item: any) => item.id);
|
ids.value = selection.map((item: any) => item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取部门下拉数据 */
|
/**
|
||||||
async function loadDeptOptions() {
|
* 打开部门弹窗
|
||||||
DeptAPI.getOptions().then((data) => {
|
*
|
||||||
|
* @param parentId 父部门ID
|
||||||
|
* @param deptId 部门ID
|
||||||
|
*/
|
||||||
|
async function handleOpenDialog(parentId?: number, deptId?: number) {
|
||||||
|
// 加载部门下拉数据
|
||||||
|
const data = await DeptAPI.getOptions();
|
||||||
deptOptions.value = [
|
deptOptions.value = [
|
||||||
{
|
{
|
||||||
value: 0,
|
value: 0,
|
||||||
@@ -218,17 +230,7 @@ async function loadDeptOptions() {
|
|||||||
children: data,
|
children: data,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开弹窗
|
|
||||||
*
|
|
||||||
* @param parentId 父部门ID
|
|
||||||
* @param deptId 部门ID
|
|
||||||
*/
|
|
||||||
async function openDialog(parentId?: number, deptId?: number) {
|
|
||||||
await loadDeptOptions();
|
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
if (deptId) {
|
if (deptId) {
|
||||||
dialog.title = "修改部门";
|
dialog.title = "修改部门";
|
||||||
@@ -241,17 +243,17 @@ async function openDialog(parentId?: number, deptId?: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表单提交 */
|
/** 提交部门表单 */
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
deptFormRef.value.validate((valid: any) => {
|
deptFormRef.value.validate((valid: any) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const deptId = formData.id;
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
const deptId = formData.id;
|
||||||
if (deptId) {
|
if (deptId) {
|
||||||
DeptAPI.update(deptId, formData)
|
DeptAPI.update(deptId, formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success("修改成功");
|
ElMessage.success("修改成功");
|
||||||
closeDialog();
|
handleCloseDialog();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
})
|
})
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
@@ -259,7 +261,7 @@ function handleSubmit() {
|
|||||||
DeptAPI.add(formData)
|
DeptAPI.add(formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success("新增成功");
|
ElMessage.success("新增成功");
|
||||||
closeDialog();
|
handleCloseDialog();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
})
|
})
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
@@ -290,13 +292,9 @@ function handleDelete(deptId?: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 关闭弹窗 */
|
/** 关闭弹窗 */
|
||||||
function closeDialog() {
|
function handleCloseDialog() {
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
resetForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置表单 */
|
|
||||||
function resetForm() {
|
|
||||||
deptFormRef.value.resetFields();
|
deptFormRef.value.resetFields();
|
||||||
deptFormRef.value.clearValidate();
|
deptFormRef.value.clearValidate();
|
||||||
|
|
||||||
|
|||||||
@@ -1,308 +0,0 @@
|
|||||||
<!-- 字典数据 -->
|
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<div class="search-container">
|
|
||||||
<!-- 搜索表单 -->
|
|
||||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
|
||||||
<el-form-item label="关键字" prop="name">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.name"
|
|
||||||
placeholder="字典名称"
|
|
||||||
clearable
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="handleQuery"
|
|
||||||
><i-ep-search />搜索</el-button
|
|
||||||
>
|
|
||||||
<el-button @click="handleResetQuery"> <i-ep-refresh />重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
<el-card shadow="never">
|
|
||||||
<template #header>
|
|
||||||
<el-button
|
|
||||||
v-hasPerm="['sys:dict:add']"
|
|
||||||
type="success"
|
|
||||||
@click="openDialog()"
|
|
||||||
><i-ep-plus />新增</el-button
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
v-hasPerm="['sys:dict:delete']"
|
|
||||||
type="danger"
|
|
||||||
:disabled="ids.length === 0"
|
|
||||||
@click="handleDelete()"
|
|
||||||
><i-ep-delete />删除</el-button
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<el-table
|
|
||||||
v-loading="loading"
|
|
||||||
:data="dictList"
|
|
||||||
border
|
|
||||||
@selection-change="handleSelectionChange"
|
|
||||||
>
|
|
||||||
<el-table-column type="selection" width="50" />
|
|
||||||
<el-table-column label="字典名称" prop="name" />
|
|
||||||
<el-table-column label="字典值" prop="value" />
|
|
||||||
<el-table-column label="状态" align="center">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-tag v-if="scope.row.status === 1" type="success">启用</el-tag>
|
|
||||||
<el-tag v-else type="info">禁用</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column fixed="right" label="操作" align="center">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-button
|
|
||||||
v-hasPerm="['sys:dict:edit']"
|
|
||||||
type="primary"
|
|
||||||
link
|
|
||||||
@click="openDialog(scope.row.id)"
|
|
||||||
><i-ep-edit />编辑</el-button
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
v-hasPerm="['sys:dict:delete']"
|
|
||||||
type="primary"
|
|
||||||
link
|
|
||||||
@click.stop="handleDelete(scope.row.id)"
|
|
||||||
><i-ep-delete />删除</el-button
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination
|
|
||||||
v-if="total > 0"
|
|
||||||
v-model:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
|
||||||
@pagination="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- 表单弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
v-model="dialog.visible"
|
|
||||||
:title="dialog.title"
|
|
||||||
width="500px"
|
|
||||||
@close="closeDialog"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
ref="dataFormRef"
|
|
||||||
:model="formData"
|
|
||||||
:rules="rules"
|
|
||||||
label-width="100px"
|
|
||||||
>
|
|
||||||
<el-form-item label="字典名称">{{ typeName }}</el-form-item>
|
|
||||||
<el-form-item label="字典名称" prop="name">
|
|
||||||
<el-input v-model="formData.name" placeholder="请输入字典名称" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="字典值" prop="value">
|
|
||||||
<el-input v-model="formData.value" placeholder="字典值" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="排序" prop="sort">
|
|
||||||
<el-input-number
|
|
||||||
v-model="formData.sort"
|
|
||||||
controls-position="right"
|
|
||||||
:min="0"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="状态" prop="status">
|
|
||||||
<el-radio-group v-model="formData.status">
|
|
||||||
<el-radio :label="1">正常</el-radio>
|
|
||||||
<el-radio :label="0">停用</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="备注" prop="remark">
|
|
||||||
<el-input v-model="formData.remark" type="textarea" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
|
||||||
<el-button @click="closeDialog">取 消</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
defineOptions({
|
|
||||||
name: "DictData",
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
import DictAPI from "@/api/dict";
|
|
||||||
import { DictPageVO, DictForm, DictQuery } from "@/api/dict/model";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
typeCode: {
|
|
||||||
type: String,
|
|
||||||
default: () => {
|
|
||||||
return "";
|
|
||||||
},
|
|
||||||
},
|
|
||||||
typeName: {
|
|
||||||
type: String,
|
|
||||||
default: () => {
|
|
||||||
return "";
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.typeCode,
|
|
||||||
(newVal: string) => {
|
|
||||||
queryParams.typeCode = newVal;
|
|
||||||
formData.typeCode = newVal;
|
|
||||||
handleResetQuery();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
|
||||||
const dataFormRef = ref(ElForm);
|
|
||||||
|
|
||||||
const loading = ref(false);
|
|
||||||
const ids = ref<number[]>([]);
|
|
||||||
const total = ref(0);
|
|
||||||
|
|
||||||
const queryParams = reactive<DictQuery>({
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
typeCode: props.typeCode,
|
|
||||||
});
|
|
||||||
|
|
||||||
const dictList = ref<DictPageVO[]>();
|
|
||||||
|
|
||||||
const dialog = reactive({
|
|
||||||
title: "",
|
|
||||||
visible: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const formData = reactive<DictForm>({
|
|
||||||
status: 1,
|
|
||||||
typeCode: props.typeCode,
|
|
||||||
sort: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
const rules = reactive({
|
|
||||||
name: [{ required: true, message: "请输入字典名称", trigger: "blur" }],
|
|
||||||
value: [{ required: true, message: "请输入字典值", trigger: "blur" }],
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 查询 */
|
|
||||||
function handleQuery() {
|
|
||||||
if (queryParams.typeCode) {
|
|
||||||
loading.value = true;
|
|
||||||
DictAPI.getDictPage(queryParams)
|
|
||||||
.then((data) => {
|
|
||||||
dictList.value = data.list;
|
|
||||||
total.value = data.total;
|
|
||||||
})
|
|
||||||
.finally(() => (loading.value = false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置查询 */
|
|
||||||
function handleResetQuery() {
|
|
||||||
queryFormRef.value.resetFields();
|
|
||||||
queryParams.pageNum = 1;
|
|
||||||
handleQuery();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 行checkbox change事件
|
|
||||||
*
|
|
||||||
* @param selection
|
|
||||||
*/
|
|
||||||
function handleSelectionChange(selection: any) {
|
|
||||||
ids.value = selection.map((item: any) => item.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开字典表单弹窗
|
|
||||||
*
|
|
||||||
* @param dictId 字典ID
|
|
||||||
*/
|
|
||||||
function openDialog(dictId?: number) {
|
|
||||||
dialog.visible = true;
|
|
||||||
if (dictId) {
|
|
||||||
dialog.title = "修改字典";
|
|
||||||
DictAPI.getDictFormData(dictId).then((data) => {
|
|
||||||
Object.assign(formData, data);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dialog.title = "新增字典";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 字典表单提交 */
|
|
||||||
function handleSubmit() {
|
|
||||||
dataFormRef.value.validate((isValid: boolean) => {
|
|
||||||
if (isValid) {
|
|
||||||
loading.value = false;
|
|
||||||
const dictId = formData.id;
|
|
||||||
if (dictId) {
|
|
||||||
DictAPI.updateDict(dictId, formData)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success("修改成功");
|
|
||||||
closeDialog();
|
|
||||||
handleResetQuery();
|
|
||||||
})
|
|
||||||
.finally(() => (loading.value = false));
|
|
||||||
} else {
|
|
||||||
DictAPI.addDict(formData)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success("新增成功");
|
|
||||||
closeDialog();
|
|
||||||
handleResetQuery();
|
|
||||||
})
|
|
||||||
.finally(() => (loading.value = false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 关闭弹窗 */
|
|
||||||
function closeDialog() {
|
|
||||||
dialog.visible = false;
|
|
||||||
resetForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置表单 */
|
|
||||||
function resetForm() {
|
|
||||||
dataFormRef.value.resetFields();
|
|
||||||
dataFormRef.value.clearValidate();
|
|
||||||
|
|
||||||
formData.id = undefined;
|
|
||||||
formData.status = 1;
|
|
||||||
formData.sort = 1;
|
|
||||||
formData.typeCode = props.typeCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除字典 */
|
|
||||||
function handleDelete(dictId?: number) {
|
|
||||||
const dictIds = [dictId || ids.value].join(",");
|
|
||||||
if (!dictIds) {
|
|
||||||
ElMessage.warning("请勾选删除项");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
|
|
||||||
confirmButtonText: "确定",
|
|
||||||
cancelButtonText: "取消",
|
|
||||||
type: "warning",
|
|
||||||
}).then(() => {
|
|
||||||
DictAPI.deleteDictByIds(dictIds).then(() => {
|
|
||||||
ElMessage.success("删除成功");
|
|
||||||
handleResetQuery();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
handleQuery();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
<!--字典类型-->
|
<!-- 分类字典 -->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
@@ -7,7 +6,7 @@
|
|||||||
<el-form-item label="关键字" prop="name">
|
<el-form-item label="关键字" prop="name">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.keywords"
|
v-model="queryParams.keywords"
|
||||||
placeholder="字典类型名称/编码"
|
placeholder="字典名称"
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter="handleQuery"
|
@keyup.enter="handleQuery"
|
||||||
/>
|
/>
|
||||||
@@ -16,68 +15,67 @@
|
|||||||
<el-button type="primary" @click="handleQuery()"
|
<el-button type="primary" @click="handleQuery()"
|
||||||
><i-ep-search />搜索</el-button
|
><i-ep-search />搜索</el-button
|
||||||
>
|
>
|
||||||
<el-button @click="handleResetQuery()"
|
<el-button @click="handleResetClick()"
|
||||||
><i-ep-refresh />重置</el-button
|
><i-ep-refresh />重置</el-button
|
||||||
>
|
>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-card shadow="never" class="table-container">
|
<el-card shadow="never">
|
||||||
<template #header>
|
<div class="mb-[10px]">
|
||||||
<el-button
|
<el-button type="success" @click="handleAddClick()"
|
||||||
v-hasPerm="['sys:dict_type:add']"
|
|
||||||
type="success"
|
|
||||||
@click="openDialog()"
|
|
||||||
><i-ep-plus />新增</el-button
|
><i-ep-plus />新增</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
type="danger"
|
type="danger"
|
||||||
:disabled="ids.length === 0"
|
:disabled="ids.length === 0"
|
||||||
@click="handleDelete()"
|
@click="handleDeleteClick()"
|
||||||
><i-ep-delete />删除</el-button
|
><i-ep-delete />删除</el-button
|
||||||
>
|
>
|
||||||
</template>
|
</div>
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
highlight-current-row
|
highlight-current-row
|
||||||
:data="dictTypeList"
|
:data="tableData"
|
||||||
border
|
border
|
||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
<el-table-column label="字典类型名称" prop="name" width="200" />
|
|
||||||
<el-table-column label="字典类型编码" prop="code" width="200" />
|
<el-table-column type="expand" label="字典项列表" width="100">
|
||||||
<el-table-column label="状态" align="center" width="100">
|
<template #default="props">
|
||||||
<template #default="scope">
|
<el-table :data="props.row.dictItems">
|
||||||
<el-tag v-if="scope.row.status === 1" type="success">启用</el-tag>
|
<el-table-column label="字典项键" prop="name" width="200" />
|
||||||
<el-tag v-else type="info">禁用</el-tag>
|
<el-table-column label="字典项值" prop="value" align="center" />
|
||||||
|
<el-table-column label="排序" prop="sort" align="center" />
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="字典名称" prop="name" />
|
||||||
|
<el-table-column label="字典编码" prop="code" />
|
||||||
|
<el-table-column label="状态" prop="status">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="scope.row.status === 1 ? 'success' : 'info'">
|
||||||
|
{{ scope.row.status === 1 ? "启用" : "禁用" }}
|
||||||
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="备注" prop="remark" align="center" />
|
|
||||||
<el-table-column fixed="right" label="操作" align="center" width="220">
|
<el-table-column fixed="right" label="操作" align="center" width="220">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click.stop="openDictDialog(scope.row)"
|
@click.stop="handleEditClick(scope.row.id, scope.row.name)"
|
||||||
><i-ep-Collection />字典数据</el-button
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
v-hasPerm="['sys:dict_type:edit']"
|
|
||||||
type="primary"
|
|
||||||
link
|
|
||||||
size="small"
|
|
||||||
@click.stop="openDialog(scope.row.id)"
|
|
||||||
><i-ep-edit />编辑</el-button
|
><i-ep-edit />编辑</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:dict_type:delete']"
|
type="danger"
|
||||||
type="primary"
|
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click.stop="handleDelete(scope.row.id)"
|
@click.stop="handleDeleteClick(scope.row.id)"
|
||||||
><i-ep-delete />删除</el-button
|
><i-ep-delete />删除</el-button
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
@@ -93,71 +91,128 @@
|
|||||||
/>
|
/>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog
|
<!--字典弹窗-->
|
||||||
|
<el-drawer
|
||||||
v-model="dialog.visible"
|
v-model="dialog.visible"
|
||||||
:title="dialog.title"
|
:title="dialog.title"
|
||||||
width="500px"
|
size="70%"
|
||||||
@close="closeDialog"
|
@close="handleCloseDialog"
|
||||||
>
|
>
|
||||||
<el-form
|
<el-form
|
||||||
ref="dataFormRef"
|
ref="dataFormRef"
|
||||||
:model="formData"
|
:model="formData"
|
||||||
:rules="rules"
|
:rules="computedRules"
|
||||||
label-width="80px"
|
label-width="100px"
|
||||||
|
:inline="true"
|
||||||
>
|
>
|
||||||
|
<el-card shadow="never">
|
||||||
<el-form-item label="字典名称" prop="name">
|
<el-form-item label="字典名称" prop="name">
|
||||||
<el-input v-model="formData.name" placeholder="请输入字典名称" />
|
<el-input v-model="formData.name" placeholder="请输入字典名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="字典编码" prop="code">
|
<el-form-item label="字典编码" prop="code">
|
||||||
<el-input v-model="formData.code" placeholder="请输入字典编码" />
|
<el-input v-model="formData.code" placeholder="请输入字典编码" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态" prop="status">
|
|
||||||
|
<el-form-item label="状态">
|
||||||
<el-radio-group v-model="formData.status">
|
<el-radio-group v-model="formData.status">
|
||||||
<el-radio :label="1">正常</el-radio>
|
<el-radio :value="1">启用</el-radio>
|
||||||
<el-radio :label="0">停用</el-radio>
|
<el-radio :value="0">禁用</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
|
||||||
<el-input
|
<el-form-item label="备注">
|
||||||
v-model="formData.remark"
|
<el-input v-model="formData.remark" />
|
||||||
type="textarea"
|
|
||||||
placeholder="字典类型备注"
|
|
||||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-card>
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
<el-card shadow="never" class="mt-5">
|
||||||
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
<template #header>
|
||||||
<el-button @click="closeDialog">取 消</el-button>
|
<div class="flex-x-between">
|
||||||
|
<span>字典项</span>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleAddAttrClick"
|
||||||
|
><i-ep-plus />新增字典</el-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
<el-table
|
||||||
|
v-loading="loading"
|
||||||
<!--字典数据弹窗-->
|
highlight--currentrow
|
||||||
<el-dialog
|
:data="formData.dictItems"
|
||||||
v-model="dictDataDialog.visible"
|
@selection-change="handleSelectionChange"
|
||||||
:title="dictDataDialog.title"
|
|
||||||
width="1000px"
|
|
||||||
@close="closeDictDialog"
|
|
||||||
>
|
>
|
||||||
<dict-item
|
<el-table-column label="字典项名称" width="200">
|
||||||
v-model:typeCode="selectedDictType.typeCode"
|
<template #default="scope">
|
||||||
v-model:typeName="selectedDictType.typeName"
|
<el-form-item :prop="'dictItems.' + scope.$index + '.name'">
|
||||||
|
<el-input v-model="scope.row.name" />
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="字典项值" width="200">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-form-item :prop="'dictItems.' + scope.$index + '.value'">
|
||||||
|
<el-input v-model="scope.row.value" />
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="排序">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-form-item :prop="'dictItems.' + scope.$index + '.sort'">
|
||||||
|
<el-input v-model="scope.row.sort" />
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="状态" prop="status">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-form-item :prop="'dictItems.' + scope.$index + '.status'">
|
||||||
|
<el-switch
|
||||||
|
v-model="scope.row.status"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
/>
|
/>
|
||||||
</el-dialog>
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
fixed="right"
|
||||||
|
label="操作"
|
||||||
|
align="center"
|
||||||
|
width="120"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
link
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleDeleteAttrClick(scope.$index)"
|
||||||
|
><i-ep-delete />删除</el-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="handleSubmitClick">确 定</el-button>
|
||||||
|
<el-button @click="handleCloseDialog">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "DictType",
|
name: "Dict",
|
||||||
inheritAttrs: false,
|
inherititems: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import DictAPI from "@/api/dict";
|
import DictAPI, { DictPageQuery, DictPageVO, DictForm } from "@/api/dict";
|
||||||
|
|
||||||
import { DictTypePageVO, DictTypeQuery, DictTypeForm } from "@/api/dict/model";
|
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
const dataFormRef = ref(ElForm);
|
const dataFormRef = ref(ElForm);
|
||||||
@@ -166,33 +221,42 @@ const loading = ref(false);
|
|||||||
const ids = ref<number[]>([]);
|
const ids = ref<number[]>([]);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryParams = reactive<DictTypeQuery>({
|
const queryParams = reactive<DictPageQuery>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
});
|
});
|
||||||
|
|
||||||
const dictTypeList = ref<DictTypePageVO[]>();
|
const tableData = ref<DictPageVO[]>();
|
||||||
|
|
||||||
|
// 字典弹窗
|
||||||
const dialog = reactive({
|
const dialog = reactive({
|
||||||
title: "",
|
title: "",
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const formData = reactive<DictTypeForm>({
|
const formData = reactive<DictForm>({});
|
||||||
status: 1,
|
|
||||||
|
const computedRules = computed(() => {
|
||||||
|
const rules: Partial<Record<string, any>> = {
|
||||||
|
name: [{ required: true, message: "请输入字典名称", trigger: "blur" }],
|
||||||
|
code: [{ required: true, message: "请输入字典编码", trigger: "blur" }],
|
||||||
|
};
|
||||||
|
if (formData.dictItems) {
|
||||||
|
formData.dictItems.forEach((attr, index) => {
|
||||||
|
rules[`dictItems.${index}.name`] = [
|
||||||
|
{ required: true, message: "请输入字典项名称", trigger: "blur" },
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return rules;
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive({
|
// 查询
|
||||||
name: [{ required: true, message: "请输入字典类型名称", trigger: "blur" }],
|
|
||||||
code: [{ required: true, message: "请输入字典类型编码", trigger: "blur" }],
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 查询 */
|
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
DictAPI.getDictTypePage(queryParams)
|
DictAPI.getPage(queryParams)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
dictTypeList.value = data.list;
|
tableData.value = data.list;
|
||||||
total.value = data.total;
|
total.value = data.total;
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -200,56 +264,57 @@ function handleQuery() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 重置查询
|
||||||
* 重置查询
|
function handleResetClick() {
|
||||||
*/
|
|
||||||
function handleResetQuery() {
|
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value.resetFields();
|
||||||
queryParams.pageNum = 1;
|
queryParams.pageNum = 1;
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 行复选框选中 */
|
// 行选择
|
||||||
function handleSelectionChange(selection: any) {
|
function handleSelectionChange(selection: any) {
|
||||||
ids.value = selection.map((item: any) => item.id);
|
ids.value = selection.map((item: any) => item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 新增字典
|
||||||
* 打开字典类型表单弹窗
|
function handleAddClick() {
|
||||||
*
|
|
||||||
* @param dicTypeId 字典类型ID
|
|
||||||
*/
|
|
||||||
function openDialog(dicTypeId?: number) {
|
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
if (dicTypeId) {
|
dialog.title = "新增字典";
|
||||||
dialog.title = "修改字典类型";
|
}
|
||||||
DictAPI.getDictTypeForm(dicTypeId).then((data) => {
|
|
||||||
|
/**
|
||||||
|
* 编辑字典
|
||||||
|
*
|
||||||
|
* @param id 字典ID
|
||||||
|
*/
|
||||||
|
function handleEditClick(id: number, name: string) {
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "【" + name + "】字典修改";
|
||||||
|
DictAPI.getFormData(id).then((data) => {
|
||||||
Object.assign(formData, data);
|
Object.assign(formData, data);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
dialog.title = "新增字典类型";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 字典类型表单提交 */
|
// 提交字典表单
|
||||||
function handleSubmit() {
|
function handleSubmitClick() {
|
||||||
dataFormRef.value.validate((isValid: boolean) => {
|
dataFormRef.value.validate((isValid: boolean) => {
|
||||||
|
console.log("isValid", isValid);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
loading.value = false;
|
loading.value = true;
|
||||||
const dictTypeId = formData.id;
|
const id = formData.id;
|
||||||
if (dictTypeId) {
|
if (id) {
|
||||||
DictAPI.updateDictType(dictTypeId, formData)
|
DictAPI.update(id, formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success("修改成功");
|
ElMessage.success("修改成功");
|
||||||
closeDialog();
|
handleCloseDialog();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
})
|
})
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
} else {
|
} else {
|
||||||
DictAPI.addDictType(formData)
|
DictAPI.add(formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success("新增成功");
|
ElMessage.success("新增成功");
|
||||||
closeDialog();
|
handleCloseDialog();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
})
|
})
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
@@ -258,63 +323,57 @@ function handleSubmit() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 关闭字典类型弹窗 */
|
/** 关闭字典弹窗 */
|
||||||
function closeDialog() {
|
function handleCloseDialog() {
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
resetForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置字典类型表单 */
|
|
||||||
function resetForm() {
|
|
||||||
dataFormRef.value.resetFields();
|
dataFormRef.value.resetFields();
|
||||||
dataFormRef.value.clearValidate();
|
dataFormRef.value.clearValidate();
|
||||||
|
|
||||||
formData.id = undefined;
|
formData.id = undefined;
|
||||||
formData.status = 1;
|
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
/** 删除字典类型 */
|
* 删除字典
|
||||||
function handleDelete(dictTypeId?: number) {
|
*
|
||||||
const dictTypeIds = [dictTypeId || ids.value].join(",");
|
* @param id 字典ID
|
||||||
if (!dictTypeIds) {
|
*/
|
||||||
|
function handleDeleteClick(id?: number) {
|
||||||
|
const attrGroupIds = [id || ids.value].join(",");
|
||||||
|
if (!attrGroupIds) {
|
||||||
ElMessage.warning("请勾选删除项");
|
ElMessage.warning("请勾选删除项");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
|
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
|
||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
DictAPI.deleteDictTypes(dictTypeIds).then(() => {
|
DictAPI.deleteByIds(attrGroupIds).then(() => {
|
||||||
ElMessage.success("删除成功");
|
ElMessage.success("删除成功");
|
||||||
handleResetQuery();
|
handleResetClick();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const dictDataDialog = reactive({
|
// 新增字典
|
||||||
title: "",
|
function handleAddAttrClick() {
|
||||||
visible: false,
|
formData.dictItems = formData.dictItems ?? [];
|
||||||
});
|
formData.dictItems.push({ sort: 1, status: 1 });
|
||||||
|
}
|
||||||
const selectedDictType = reactive({ typeCode: "", typeName: "" }); // 当前选中的字典类型
|
// 删除字典
|
||||||
|
function handleDeleteAttrClick(index: number) {
|
||||||
/** 打开字典数据弹窗 */
|
if (formData.dictItems && formData.dictItems.length > 0) {
|
||||||
function openDictDialog(row: DictTypePageVO) {
|
formData.dictItems.splice(index, 1);
|
||||||
dictDataDialog.visible = true;
|
|
||||||
dictDataDialog.title = "【" + row.name + "】字典数据";
|
|
||||||
|
|
||||||
selectedDictType.typeCode = row.code;
|
|
||||||
selectedDictType.typeName = row.name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 关闭字典数据弹窗 */
|
|
||||||
function closeDictDialog() {
|
|
||||||
dictDataDialog.visible = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
handleQuery();
|
handleQuery();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.el-form--inline .el-form-item {
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:menu:add']"
|
v-hasPerm="['sys:menu:add']"
|
||||||
type="success"
|
type="success"
|
||||||
@click="handleDialogOpen(0)"
|
@click="handleOpenDialog(0)"
|
||||||
>
|
>
|
||||||
<template #icon><i-ep-plus /></template>
|
<template #icon><i-ep-plus /></template>
|
||||||
新增</el-button
|
新增</el-button
|
||||||
@@ -84,11 +84,18 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
label="路由名称"
|
||||||
|
align="left"
|
||||||
|
width="150"
|
||||||
|
prop="routeName"
|
||||||
|
/>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="路由路径"
|
label="路由路径"
|
||||||
align="left"
|
align="left"
|
||||||
width="150"
|
width="150"
|
||||||
prop="path"
|
prop="routePath"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
@@ -122,7 +129,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click.stop="handleDialogOpen(scope.row.id)"
|
@click.stop="handleOpenDialog(scope.row.id)"
|
||||||
>
|
>
|
||||||
<i-ep-plus />新增
|
<i-ep-plus />新增
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -132,7 +139,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click.stop="handleDialogOpen(undefined, scope.row.id)"
|
@click.stop="handleOpenDialog(undefined, scope.row.id)"
|
||||||
>
|
>
|
||||||
<i-ep-edit />编辑
|
<i-ep-edit />编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -150,19 +157,17 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog
|
<el-drawer
|
||||||
v-model="dialog.visible"
|
v-model="dialog.visible"
|
||||||
:title="dialog.title"
|
:title="dialog.title"
|
||||||
destroy-on-close
|
@close="handleCloseDialog"
|
||||||
append-to-body
|
size="50%"
|
||||||
width="1000px"
|
|
||||||
@close="closeDialog"
|
|
||||||
>
|
>
|
||||||
<el-form
|
<el-form
|
||||||
ref="menuFormRef"
|
ref="menuFormRef"
|
||||||
:model="formData"
|
:model="formData"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
label-width="160px"
|
label-width="100px"
|
||||||
>
|
>
|
||||||
<el-form-item label="父级菜单" prop="parentId">
|
<el-form-item label="父级菜单" prop="parentId">
|
||||||
<el-tree-select
|
<el-tree-select
|
||||||
@@ -196,7 +201,10 @@
|
|||||||
label="外链地址"
|
label="外链地址"
|
||||||
prop="path"
|
prop="path"
|
||||||
>
|
>
|
||||||
<el-input v-model="formData.path" placeholder="请输入外链完整路径" />
|
<el-input
|
||||||
|
v-model="formData.routePath"
|
||||||
|
placeholder="请输入外链完整路径"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item
|
||||||
@@ -204,8 +212,29 @@
|
|||||||
formData.type == MenuTypeEnum.CATALOG ||
|
formData.type == MenuTypeEnum.CATALOG ||
|
||||||
formData.type == MenuTypeEnum.MENU
|
formData.type == MenuTypeEnum.MENU
|
||||||
"
|
"
|
||||||
label=""
|
prop="routeName"
|
||||||
prop="path"
|
>
|
||||||
|
<template #label>
|
||||||
|
<div>
|
||||||
|
路由名称
|
||||||
|
<el-tooltip placement="bottom" effect="light">
|
||||||
|
<template #content>
|
||||||
|
如果需要开启缓存,需保证页面 defineOptions 中的 name
|
||||||
|
与此处一致,建议使用驼峰。
|
||||||
|
</template>
|
||||||
|
<i-ep-QuestionFilled class="inline-block" />
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-input v-model="formData.routeName" placeholder="User" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item
|
||||||
|
v-if="
|
||||||
|
formData.type == MenuTypeEnum.CATALOG ||
|
||||||
|
formData.type == MenuTypeEnum.MENU
|
||||||
|
"
|
||||||
|
prop="routePath"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div>
|
<div>
|
||||||
@@ -222,10 +251,10 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-input
|
<el-input
|
||||||
v-if="formData.type == MenuTypeEnum.CATALOG"
|
v-if="formData.type == MenuTypeEnum.CATALOG"
|
||||||
v-model="formData.path"
|
v-model="formData.routePath"
|
||||||
placeholder="system"
|
placeholder="system"
|
||||||
/>
|
/>
|
||||||
<el-input v-else v-model="formData.path" placeholder="user" />
|
<el-input v-else v-model="formData.routePath" placeholder="user" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item
|
||||||
@@ -405,10 +434,10 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
<el-button @click="closeDialog">取 消</el-button>
|
<el-button @click="handleCloseDialog">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -418,8 +447,7 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import MenuAPI from "@/api/menu";
|
import MenuAPI, { MenuQuery, MenuForm, MenuVO } from "@/api/menu";
|
||||||
import { MenuQuery, MenuForm, MenuVO } from "@/api/menu/model";
|
|
||||||
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
|
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
@@ -458,7 +486,7 @@ const rules = reactive({
|
|||||||
parentId: [{ required: true, message: "请选择顶级菜单", trigger: "blur" }],
|
parentId: [{ required: true, message: "请选择顶级菜单", trigger: "blur" }],
|
||||||
name: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
|
name: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
|
||||||
type: [{ required: true, message: "请选择菜单类型", trigger: "blur" }],
|
type: [{ required: true, message: "请选择菜单类型", trigger: "blur" }],
|
||||||
path: [{ required: true, message: "请输入路由路径", trigger: "blur" }],
|
routePath: [{ required: true, message: "请输入路由路径", trigger: "blur" }],
|
||||||
component: [{ required: true, message: "请输入组件路径", trigger: "blur" }],
|
component: [{ required: true, message: "请输入组件路径", trigger: "blur" }],
|
||||||
visible: [{ required: true, message: "请输入路由路径", trigger: "blur" }],
|
visible: [{ required: true, message: "请输入路由路径", trigger: "blur" }],
|
||||||
});
|
});
|
||||||
@@ -496,7 +524,7 @@ function handleRowClick(row: MenuVO) {
|
|||||||
* @param parentId 父菜单ID
|
* @param parentId 父菜单ID
|
||||||
* @param menuId 菜单ID
|
* @param menuId 菜单ID
|
||||||
*/
|
*/
|
||||||
function handleDialogOpen(parentId?: number, menuId?: number) {
|
function handleOpenDialog(parentId?: number, menuId?: number) {
|
||||||
MenuAPI.getOptions()
|
MenuAPI.getOptions()
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
menuOptions.value = [{ value: 0, label: "顶级菜单", children: data }];
|
menuOptions.value = [{ value: 0, label: "顶级菜单", children: data }];
|
||||||
@@ -541,13 +569,13 @@ function submitForm() {
|
|||||||
if (menuId) {
|
if (menuId) {
|
||||||
MenuAPI.update(menuId, formData.value).then(() => {
|
MenuAPI.update(menuId, formData.value).then(() => {
|
||||||
ElMessage.success("修改成功");
|
ElMessage.success("修改成功");
|
||||||
closeDialog();
|
handleCloseDialog();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
MenuAPI.add(formData.value).then(() => {
|
MenuAPI.add(formData.value).then(() => {
|
||||||
ElMessage.success("新增成功");
|
ElMessage.success("新增成功");
|
||||||
closeDialog();
|
handleCloseDialog();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -577,7 +605,7 @@ function handleDelete(menuId: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
function closeDialog() {
|
function handleCloseDialog() {
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
menuFormRef.value.resetFields();
|
menuFormRef.value.resetFields();
|
||||||
menuFormRef.value.clearValidate();
|
menuFormRef.value.clearValidate();
|
||||||
|
|||||||
@@ -195,7 +195,6 @@
|
|||||||
:data="menuPermOptions"
|
:data="menuPermOptions"
|
||||||
:filter-node-method="handlePermFilter"
|
:filter-node-method="handlePermFilter"
|
||||||
:default-expand-all="true"
|
:default-expand-all="true"
|
||||||
:check-on-click-node="true"
|
|
||||||
:check-strictly="!parentChildLinked"
|
:check-strictly="!parentChildLinked"
|
||||||
class="mt-5"
|
class="mt-5"
|
||||||
>
|
>
|
||||||
@@ -222,11 +221,9 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import RoleAPI from "@/api/role";
|
import RoleAPI, { RolePageVO, RoleForm, RolePageQuery } from "@/api/role";
|
||||||
import MenuAPI from "@/api/menu";
|
import MenuAPI from "@/api/menu";
|
||||||
|
|
||||||
import { RolePageVO, RoleForm, RoleQuery } from "@/api/role/model";
|
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
const roleFormRef = ref(ElForm);
|
const roleFormRef = ref(ElForm);
|
||||||
const permTreeRef = ref<InstanceType<typeof ElTree>>();
|
const permTreeRef = ref<InstanceType<typeof ElTree>>();
|
||||||
@@ -235,7 +232,7 @@ const loading = ref(false);
|
|||||||
const ids = ref<number[]>([]);
|
const ids = ref<number[]>([]);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryParams = reactive<RoleQuery>({
|
const queryParams = reactive<RolePageQuery>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
});
|
});
|
||||||
@@ -315,7 +312,7 @@ function handleOpenDialog(roleId?: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 角色保存提交
|
/** 提交角色表单 */
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
roleFormRef.value.validate((valid: any) => {
|
roleFormRef.value.validate((valid: any) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
@@ -342,7 +339,7 @@ function handleSubmit() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭表单弹窗
|
/** 关闭表单弹窗 */
|
||||||
function handleCloseDialog() {
|
function handleCloseDialog() {
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
|
|
||||||
@@ -354,7 +351,7 @@ function handleCloseDialog() {
|
|||||||
formData.status = 1;
|
formData.status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除角色
|
/** 删除角色 */
|
||||||
function handleDelete(roleId?: number) {
|
function handleDelete(roleId?: number) {
|
||||||
const roleIds = [roleId || ids.value].join(",");
|
const roleIds = [roleId || ids.value].join(",");
|
||||||
if (!roleIds) {
|
if (!roleIds) {
|
||||||
@@ -377,7 +374,7 @@ function handleDelete(roleId?: number) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打开分配权限
|
/** 打开分配菜单权限弹窗 */
|
||||||
async function handleOpenAssignPermDialog(row: RolePageVO) {
|
async function handleOpenAssignPermDialog(row: RolePageVO) {
|
||||||
const roleId = row.id;
|
const roleId = row.id;
|
||||||
if (roleId) {
|
if (roleId) {
|
||||||
@@ -404,7 +401,7 @@ async function handleOpenAssignPermDialog(row: RolePageVO) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分配权限提交
|
/** 分配菜单权限提交 */
|
||||||
function handleAssignPermSubmit() {
|
function handleAssignPermSubmit() {
|
||||||
const roleId = checkedRole.value.id;
|
const roleId = checkedRole.value.id;
|
||||||
if (roleId) {
|
if (roleId) {
|
||||||
@@ -425,7 +422,7 @@ function handleAssignPermSubmit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换菜单树展开状态
|
/** 展开/收缩 菜单权限树 */
|
||||||
function togglePermTree() {
|
function togglePermTree() {
|
||||||
isExpanded.value = !isExpanded.value;
|
isExpanded.value = !isExpanded.value;
|
||||||
if (permTreeRef.value) {
|
if (permTreeRef.value) {
|
||||||
@@ -438,11 +435,12 @@ function togglePermTree() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 菜单权限筛选
|
||||||
watch(permKeywords, (val) => {
|
watch(permKeywords, (val) => {
|
||||||
permTreeRef.value!.filter(val);
|
permTreeRef.value!.filter(val);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 权限筛选
|
/** 权限筛选 */
|
||||||
function handlePermFilter(
|
function handlePermFilter(
|
||||||
value: string,
|
value: string,
|
||||||
data: {
|
data: {
|
||||||
@@ -453,6 +451,7 @@ function handlePermFilter(
|
|||||||
return data.label.includes(value);
|
return data.label.includes(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 父子菜单节点是否联动 change*/
|
||||||
function handleparentChildLinkedChange(val: any) {
|
function handleparentChildLinkedChange(val: any) {
|
||||||
parentChildLinked.value = val;
|
parentChildLinked.value = val;
|
||||||
}
|
}
|
||||||
|
|||||||
145
src/views/system/user/components/user-import.vue
Normal file
145
src/views/system/user/components/user-import.vue
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:align-center="true"
|
||||||
|
title="导入数据"
|
||||||
|
width="600px"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<el-scrollbar max-height="60vh">
|
||||||
|
<el-form
|
||||||
|
ref="importFormRef"
|
||||||
|
label-width="auto"
|
||||||
|
style="padding-right: var(--el-dialog-padding-primary)"
|
||||||
|
:model="importFormData"
|
||||||
|
:rules="importFormRules"
|
||||||
|
>
|
||||||
|
<el-form-item label="文件名" prop="files">
|
||||||
|
<el-upload
|
||||||
|
class="w-full"
|
||||||
|
ref="uploadRef"
|
||||||
|
v-model:file-list="importFormData.files"
|
||||||
|
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
|
||||||
|
:drag="true"
|
||||||
|
:limit="1"
|
||||||
|
:auto-upload="false"
|
||||||
|
:on-exceed="handleFileExceed"
|
||||||
|
>
|
||||||
|
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||||
|
<div class="el-upload__text">
|
||||||
|
将文件拖到此处,或<em>点击上传</em>
|
||||||
|
</div>
|
||||||
|
<template #tip>
|
||||||
|
<div class="el-upload__tip">
|
||||||
|
*.xlsx / *.xls
|
||||||
|
<el-link
|
||||||
|
type="primary"
|
||||||
|
icon="download"
|
||||||
|
:underline="false"
|
||||||
|
@click="handleDownloadTemplate"
|
||||||
|
>
|
||||||
|
下载模板
|
||||||
|
</el-link>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div style="padding-right: var(--el-dialog-padding-primary)">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="importFormData.files.length === 0"
|
||||||
|
@click="handleSubmit"
|
||||||
|
>
|
||||||
|
确 定
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="handleClose">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { type UploadUserFile } from "element-plus";
|
||||||
|
|
||||||
|
import UserAPI from "@/api/user";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "import-success"]);
|
||||||
|
|
||||||
|
const dialogVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: (val) => {
|
||||||
|
emit("update:visible", val);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const importFormRef = ref(null);
|
||||||
|
const uploadRef = ref(null);
|
||||||
|
|
||||||
|
const importFormData = reactive<{
|
||||||
|
files: UploadUserFile[];
|
||||||
|
}>({
|
||||||
|
files: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const importFormRules = {
|
||||||
|
files: [{ required: true, message: "文件不能为空", trigger: "blur" }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
dialogVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
if (!importFormData.files.length) {
|
||||||
|
ElMessage.warning("请选择文件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await UserAPI.import(1, importFormData.files[0].raw as File);
|
||||||
|
ElMessage.success("上传成功");
|
||||||
|
emit("import-success");
|
||||||
|
handleClose();
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error("上传失败");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileExceed = () => {
|
||||||
|
ElMessage.warning("只能上传一个文件");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDownloadTemplate = () => {
|
||||||
|
UserAPI.downloadTemplate().then((response: any) => {
|
||||||
|
const fileData = response.data;
|
||||||
|
const fileName = decodeURI(
|
||||||
|
response.headers["content-disposition"].split(";")[1].split("=")[1]
|
||||||
|
);
|
||||||
|
const fileType =
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
||||||
|
|
||||||
|
const blob = new Blob([fileData], { type: fileType });
|
||||||
|
const downloadUrl = window.URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
const downloadLink = document.createElement("a");
|
||||||
|
downloadLink.href = downloadUrl;
|
||||||
|
downloadLink.download = fileName;
|
||||||
|
|
||||||
|
document.body.appendChild(downloadLink);
|
||||||
|
downloadLink.click();
|
||||||
|
|
||||||
|
document.body.removeChild(downloadLink);
|
||||||
|
window.URL.revokeObjectURL(downloadUrl);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -59,12 +59,12 @@
|
|||||||
|
|
||||||
<el-card shadow="never" class="table-container">
|
<el-card shadow="never" class="table-container">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex justify-between">
|
<div class="flex-x-between">
|
||||||
<div>
|
<div>
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:user:add']"
|
v-hasPerm="['sys:user:add']"
|
||||||
type="success"
|
type="success"
|
||||||
@click="openDialog('user-form')"
|
@click="handleOpenDialog()"
|
||||||
><i-ep-plus />新增</el-button
|
><i-ep-plus />新增</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -76,19 +76,10 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-dropdown split-button>
|
<el-button class="ml-3" @click="handleOpenImportDialog"
|
||||||
导入
|
><template #icon><i-ep-upload /></template>导入</el-button
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item @click="downloadTemplate">
|
|
||||||
<i-ep-download />下载模板</el-dropdown-item
|
|
||||||
>
|
>
|
||||||
<el-dropdown-item @click="openDialog('user-import')">
|
|
||||||
<i-ep-top />导入数据</el-dropdown-item
|
|
||||||
>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
<el-button class="ml-3" @click="handleExport"
|
<el-button class="ml-3" @click="handleExport"
|
||||||
><template #icon><i-ep-download /></template>导出</el-button
|
><template #icon><i-ep-download /></template>导出</el-button
|
||||||
>
|
>
|
||||||
@@ -162,7 +153,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
link
|
link
|
||||||
@click="resetPassword(scope.row)"
|
@click="hancleResetPassword(scope.row)"
|
||||||
><i-ep-refresh-left />重置密码</el-button
|
><i-ep-refresh-left />重置密码</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -170,12 +161,12 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click="openDialog('user-form', scope.row.id)"
|
@click="handleOpenDialog(scope.row.id)"
|
||||||
><i-ep-edit />编辑</el-button
|
><i-ep-edit />编辑</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:user:delete']"
|
v-hasPerm="['sys:user:delete']"
|
||||||
type="primary"
|
type="danger"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click="handleDelete(scope.row.id)"
|
@click="handleDelete(scope.row.id)"
|
||||||
@@ -196,17 +187,15 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 弹窗 -->
|
<!-- 用户表单弹窗 -->
|
||||||
<el-dialog
|
<el-drawer
|
||||||
v-model="dialog.visible"
|
v-model="dialog.visible"
|
||||||
:title="dialog.title"
|
:title="dialog.title"
|
||||||
:width="dialog.width"
|
|
||||||
append-to-body
|
append-to-body
|
||||||
@close="closeDialog"
|
@close="handleCloseDialog"
|
||||||
>
|
>
|
||||||
<!-- 用户新增/编辑表单 -->
|
<!-- 用户新增/编辑表单 -->
|
||||||
<el-form
|
<el-form
|
||||||
v-if="dialog.type === 'user-form'"
|
|
||||||
ref="userFormRef"
|
ref="userFormRef"
|
||||||
:model="formData"
|
:model="formData"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
@@ -228,7 +217,7 @@
|
|||||||
<el-tree-select
|
<el-tree-select
|
||||||
v-model="formData.deptId"
|
v-model="formData.deptId"
|
||||||
placeholder="请选择所属部门"
|
placeholder="请选择所属部门"
|
||||||
:data="deptList"
|
:data="deptOptions"
|
||||||
filterable
|
filterable
|
||||||
check-strictly
|
check-strictly
|
||||||
:render-after-expand="false"
|
:render-after-expand="false"
|
||||||
@@ -236,13 +225,13 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="性别" prop="gender">
|
<el-form-item label="性别" prop="gender">
|
||||||
<dictionary v-model="formData.gender" type-code="gender" />
|
<dictionary v-model="formData.gender" code="gender" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="角色" prop="roleIds">
|
<el-form-item label="角色" prop="roleIds">
|
||||||
<el-select v-model="formData.roleIds" multiple placeholder="请选择">
|
<el-select v-model="formData.roleIds" multiple placeholder="请选择">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in roleList"
|
v-for="item in roleOptions"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
@@ -274,55 +263,19 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<!-- 用户导入表单 -->
|
|
||||||
<el-form
|
|
||||||
v-else-if="dialog.type === 'user-import'"
|
|
||||||
:model="importData"
|
|
||||||
label-width="100px"
|
|
||||||
>
|
|
||||||
<el-form-item label="部门">
|
|
||||||
<el-tree-select
|
|
||||||
v-model="importData.deptId"
|
|
||||||
placeholder="请选择部门"
|
|
||||||
:data="deptList"
|
|
||||||
filterable
|
|
||||||
check-strictly
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="Excel文件">
|
|
||||||
<el-upload
|
|
||||||
ref="uploadRef"
|
|
||||||
action=""
|
|
||||||
drag
|
|
||||||
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
|
|
||||||
:limit="1"
|
|
||||||
:auto-upload="false"
|
|
||||||
:file-list="importData.fileList"
|
|
||||||
:on-change="handleFileChange"
|
|
||||||
:on-exceed="handleFileExceed"
|
|
||||||
>
|
|
||||||
<el-icon class="el-icon--upload">
|
|
||||||
<i-ep-upload-filled />
|
|
||||||
</el-icon>
|
|
||||||
<div class="el-upload__text">
|
|
||||||
将文件拖到此处,或
|
|
||||||
<em>点击上传</em>
|
|
||||||
</div>
|
|
||||||
<template #tip>
|
|
||||||
<div>xls/xlsx files</div>
|
|
||||||
</template>
|
|
||||||
</el-upload>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<!-- 弹窗底部操作按钮 -->
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
||||||
<el-button @click="closeDialog">取 消</el-button>
|
<el-button @click="handleCloseDialog">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
|
|
||||||
|
<!-- 用户导入弹窗 -->
|
||||||
|
<user-import
|
||||||
|
v-model:visible="importDialogVisible"
|
||||||
|
@import-success="handleOpenImportDialogSuccess"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -332,30 +285,28 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import UserAPI from "@/api/user";
|
import UserAPI, { UserForm, UserPageQuery, UserPageVO } from "@/api/user";
|
||||||
import DeptAPI from "@/api/dept";
|
import DeptAPI from "@/api/dept";
|
||||||
import RoleAPI from "@/api/role";
|
import RoleAPI from "@/api/role";
|
||||||
|
|
||||||
import { UserForm, UserQuery, UserPageVO } from "@/api/user/model";
|
const queryFormRef = ref(ElForm);
|
||||||
import type { UploadInstance } from "element-plus";
|
const userFormRef = ref(ElForm);
|
||||||
import { genFileId } from "element-plus";
|
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm); // 查询表单
|
const loading = ref(false);
|
||||||
const userFormRef = ref(ElForm); // 用户表单
|
const removeIds = ref([]);
|
||||||
const uploadRef = ref<UploadInstance>(); // 上传组件
|
const total = ref(0);
|
||||||
|
const pageData = ref<UserPageVO[]>();
|
||||||
const loading = ref(false); // 加载状态
|
/** 部门下拉选项 */
|
||||||
const removeIds = ref([]); // 删除用户ID集合 用于批量删除
|
const deptOptions = ref<OptionType[]>();
|
||||||
const queryParams = reactive<UserQuery>({
|
/** 角色下拉选项 */
|
||||||
|
const roleOptions = ref<OptionType[]>();
|
||||||
|
/** 用户查询参数 */
|
||||||
|
const queryParams = reactive<UserPageQuery>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
});
|
});
|
||||||
const dateTimeRange = ref("");
|
|
||||||
const total = ref(0); // 数据总数
|
|
||||||
const pageData = ref<UserPageVO[]>(); // 用户分页数据
|
|
||||||
const deptList = ref<OptionType[]>(); // 部门下拉数据源
|
|
||||||
const roleList = ref<OptionType[]>(); // 角色下拉数据源
|
|
||||||
|
|
||||||
|
const dateTimeRange = ref("");
|
||||||
watch(dateTimeRange, (newVal) => {
|
watch(dateTimeRange, (newVal) => {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
queryParams.startTime = newVal[0];
|
queryParams.startTime = newVal[0];
|
||||||
@@ -363,27 +314,21 @@ watch(dateTimeRange, (newVal) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 弹窗对象
|
/** 用户弹窗对象 */
|
||||||
const dialog = reactive({
|
const dialog = reactive({
|
||||||
visible: false,
|
visible: false,
|
||||||
type: "user-form",
|
|
||||||
width: 800,
|
|
||||||
title: "",
|
title: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** 导入弹窗显示状态 */
|
||||||
|
const importDialogVisible = ref(false);
|
||||||
|
|
||||||
// 用户表单数据
|
// 用户表单数据
|
||||||
const formData = reactive<UserForm>({
|
const formData = reactive<UserForm>({
|
||||||
status: 1,
|
status: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 用户导入数据
|
/** 用户表单校验规则 */
|
||||||
const importData = reactive({
|
|
||||||
deptId: undefined,
|
|
||||||
file: undefined,
|
|
||||||
fileList: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
// 校验规则
|
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
username: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
|
username: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
|
||||||
nickname: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
|
nickname: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
|
||||||
@@ -436,7 +381,7 @@ function handleSelectionChange(selection: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 重置密码 */
|
/** 重置密码 */
|
||||||
function resetPassword(row: { [key: string]: any }) {
|
function hancleResetPassword(row: { [key: string]: any }) {
|
||||||
ElMessageBox.prompt(
|
ElMessageBox.prompt(
|
||||||
"请输入用户「" + row.username + "」的新密码",
|
"请输入用户「" + row.username + "」的新密码",
|
||||||
"重置密码",
|
"重置密码",
|
||||||
@@ -456,34 +401,18 @@ function resetPassword(row: { [key: string]: any }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 加载角色下拉数据源 */
|
|
||||||
async function loadRoleOptions() {
|
|
||||||
RoleAPI.getOptions().then((data) => {
|
|
||||||
roleList.value = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 加载部门下拉数据源 */
|
|
||||||
async function loadDeptOptions() {
|
|
||||||
DeptAPI.getOptions().then((data) => {
|
|
||||||
deptList.value = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开弹窗
|
* 打开弹窗
|
||||||
*
|
*
|
||||||
* @param type 弹窗类型 用户表单:user-form | 用户导入:user-import
|
|
||||||
* @param id 用户ID
|
* @param id 用户ID
|
||||||
*/
|
*/
|
||||||
async function openDialog(type: string, id?: number) {
|
async function handleOpenDialog(id?: number) {
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.type = type;
|
// 加载角色下拉数据源
|
||||||
|
roleOptions.value = await RoleAPI.getOptions();
|
||||||
|
// 加载部门下拉数据源
|
||||||
|
deptOptions.value = await DeptAPI.getOptions();
|
||||||
|
|
||||||
if (dialog.type === "user-form") {
|
|
||||||
// 用户表单弹窗
|
|
||||||
await loadDeptOptions();
|
|
||||||
await loadRoleOptions();
|
|
||||||
if (id) {
|
if (id) {
|
||||||
dialog.title = "修改用户";
|
dialog.title = "修改用户";
|
||||||
UserAPI.getFormData(id).then((data) => {
|
UserAPI.getFormData(id).then((data) => {
|
||||||
@@ -492,36 +421,20 @@ async function openDialog(type: string, id?: number) {
|
|||||||
} else {
|
} else {
|
||||||
dialog.title = "新增用户";
|
dialog.title = "新增用户";
|
||||||
}
|
}
|
||||||
} else if (dialog.type === "user-import") {
|
|
||||||
// 用户导入弹窗
|
|
||||||
dialog.title = "导入用户";
|
|
||||||
dialog.width = 600;
|
|
||||||
loadDeptOptions();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** 关闭弹窗 */
|
||||||
* 关闭弹窗
|
function handleCloseDialog() {
|
||||||
*
|
|
||||||
* @param type 弹窗类型 用户表单:user-form | 用户导入:user-import
|
|
||||||
*/
|
|
||||||
function closeDialog() {
|
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
if (dialog.type === "user-form") {
|
|
||||||
userFormRef.value.resetFields();
|
userFormRef.value.resetFields();
|
||||||
userFormRef.value.clearValidate();
|
userFormRef.value.clearValidate();
|
||||||
|
|
||||||
formData.id = undefined;
|
formData.id = undefined;
|
||||||
formData.status = 1;
|
formData.status = 1;
|
||||||
} else if (dialog.type === "user-import") {
|
|
||||||
importData.file = undefined;
|
|
||||||
importData.fileList = [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表单提交 */
|
/** 表单提交 */
|
||||||
const handleSubmit = useThrottleFn(() => {
|
const handleSubmit = useThrottleFn(() => {
|
||||||
if (dialog.type === "user-form") {
|
|
||||||
userFormRef.value.validate((valid: any) => {
|
userFormRef.value.validate((valid: any) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const userId = formData.id;
|
const userId = formData.id;
|
||||||
@@ -530,7 +443,7 @@ const handleSubmit = useThrottleFn(() => {
|
|||||||
UserAPI.update(userId, formData)
|
UserAPI.update(userId, formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success("修改用户成功");
|
ElMessage.success("修改用户成功");
|
||||||
closeDialog();
|
handleCloseDialog();
|
||||||
handleResetQuery();
|
handleResetQuery();
|
||||||
})
|
})
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
@@ -538,28 +451,13 @@ const handleSubmit = useThrottleFn(() => {
|
|||||||
UserAPI.add(formData)
|
UserAPI.add(formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success("新增用户成功");
|
ElMessage.success("新增用户成功");
|
||||||
closeDialog();
|
handleCloseDialog();
|
||||||
handleResetQuery();
|
handleResetQuery();
|
||||||
})
|
})
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (dialog.type === "user-import") {
|
|
||||||
if (!importData?.deptId) {
|
|
||||||
ElMessage.warning("请选择部门");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!importData?.file) {
|
|
||||||
ElMessage.warning("上传Excel文件不能为空");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
UserAPI.import(importData?.deptId, importData?.file).then((data) => {
|
|
||||||
ElMessage.success("导入用户成功");
|
|
||||||
closeDialog();
|
|
||||||
handleResetQuery();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
/** 删除用户 */
|
/** 删除用户 */
|
||||||
@@ -581,44 +479,14 @@ function handleDelete(id?: number) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/** 打开导入弹窗 */
|
||||||
/** 下载导入模板 */
|
function handleOpenImportDialog() {
|
||||||
function downloadTemplate() {
|
importDialogVisible.value = true;
|
||||||
UserAPI.downloadTemplate().then((response: any) => {
|
|
||||||
const fileData = response.data;
|
|
||||||
const fileName = decodeURI(
|
|
||||||
response.headers["content-disposition"].split(";")[1].split("=")[1]
|
|
||||||
);
|
|
||||||
const fileType =
|
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
|
||||||
|
|
||||||
const blob = new Blob([fileData], { type: fileType });
|
|
||||||
const downloadUrl = window.URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
const downloadLink = document.createElement("a");
|
|
||||||
downloadLink.href = downloadUrl;
|
|
||||||
downloadLink.download = fileName;
|
|
||||||
|
|
||||||
document.body.appendChild(downloadLink);
|
|
||||||
downloadLink.click();
|
|
||||||
|
|
||||||
document.body.removeChild(downloadLink);
|
|
||||||
window.URL.revokeObjectURL(downloadUrl);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Excel文件 Change */
|
/** 导入用户成功 */
|
||||||
function handleFileChange(file: any) {
|
function handleOpenImportDialogSuccess() {
|
||||||
importData.file = file.raw;
|
handleQuery();
|
||||||
}
|
|
||||||
|
|
||||||
/** Excel文件 Exceed */
|
|
||||||
function handleFileExceed(files: any) {
|
|
||||||
uploadRef.value!.clearFiles();
|
|
||||||
const file = files[0];
|
|
||||||
file.uid = genFileId();
|
|
||||||
uploadRef.value!.handleStart(file);
|
|
||||||
importData.file = file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出用户 */
|
/** 导出用户 */
|
||||||
|
|||||||
@@ -25,9 +25,8 @@
|
|||||||
"jsxFragmentFactory": "Fragment"
|
"jsxFragmentFactory": "Fragment"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
|
||||||
"src/**/*.vue",
|
"src/**/*.vue",
|
||||||
"src/typings/**/*.d.ts",
|
"src/types/**/*.d.ts",
|
||||||
"mock/**/*.ts",
|
"mock/**/*.ts",
|
||||||
"vite.config.ts"
|
"vite.config.ts"
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user