Merge branch 'ts' into future/flowable
This commit is contained in:
commit
375a21a300
@ -13,7 +13,13 @@ VITE_APP_CONTEXT_PATH = '/'
|
|||||||
# 监控地址
|
# 监控地址
|
||||||
VITE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/applications'
|
VITE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/applications'
|
||||||
|
|
||||||
# xxl-job 控制台地址
|
# powerjob 控制台地址
|
||||||
VITE_APP_XXL_JOB_ADMIN = 'http://localhost:9100/xxl-job-admin'
|
VITE_APP_POWERJOB_ADMIN = 'http://localhost:7700/'
|
||||||
|
|
||||||
VITE_APP_PORT = 80
|
VITE_APP_PORT = 80
|
||||||
|
|
||||||
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
|
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
|
|
||||||
|
# 客户端id
|
||||||
|
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
||||||
|
@ -10,8 +10,8 @@ VITE_APP_CONTEXT_PATH = '/'
|
|||||||
# 监控地址
|
# 监控地址
|
||||||
VITE_APP_MONITRO_ADMIN = '/admin/applications'
|
VITE_APP_MONITRO_ADMIN = '/admin/applications'
|
||||||
|
|
||||||
# 监控地址
|
# powerjob 控制台地址
|
||||||
VITE_APP_XXL_JOB_ADMIN = '/xxl-job-admin'
|
VITE_APP_POWERJOB_ADMIN = '/powerjob'
|
||||||
|
|
||||||
# 生产环境
|
# 生产环境
|
||||||
VITE_APP_BASE_API = '/prod-api'
|
VITE_APP_BASE_API = '/prod-api'
|
||||||
@ -20,3 +20,9 @@ VITE_APP_BASE_API = '/prod-api'
|
|||||||
VITE_BUILD_COMPRESS = gzip
|
VITE_BUILD_COMPRESS = gzip
|
||||||
|
|
||||||
VITE_APP_PORT = 80
|
VITE_APP_PORT = 80
|
||||||
|
|
||||||
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
|
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
|
|
||||||
|
# 客户端id
|
||||||
|
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
||||||
|
@ -1,5 +1,36 @@
|
|||||||
{
|
{
|
||||||
"globals": {
|
"globals": {
|
||||||
|
"ComponentInternalInstance": true,
|
||||||
|
"TransferKey": true,
|
||||||
|
"ElFormRules": true,
|
||||||
|
"CheckboxValueType": true,
|
||||||
|
"PropType": true,
|
||||||
|
"DateModelType": true,
|
||||||
|
"UploadFile": true,
|
||||||
|
"ElFormInstance": true,
|
||||||
|
"ElTableInstance": true,
|
||||||
|
"ElTreeInstance": true,
|
||||||
|
"ElTreeSelectInstance": true,
|
||||||
|
"ElSelectInstance": true,
|
||||||
|
"ElUploadInstance": true,
|
||||||
|
"ElCardInstance": true,
|
||||||
|
"ElDialogInstance": true,
|
||||||
|
"ElInputInstance": true,
|
||||||
|
"ElInputNumberInstance": true,
|
||||||
|
"ElRadioInstance": true,
|
||||||
|
"ElRadioGroupInstance": true,
|
||||||
|
"ElRadioButtonInstance": true,
|
||||||
|
"ElCheckboxInstance": true,
|
||||||
|
"ElCheckboxGroupInstance": true,
|
||||||
|
"ElSwitchInstance": true,
|
||||||
|
"ElDatePickerInstance": true,
|
||||||
|
"ElTimePickerInstance": true,
|
||||||
|
"ElTimeSelectInstance": true,
|
||||||
|
"ElScrollbarInstance": true,
|
||||||
|
"ElCascaderInstance": true,
|
||||||
|
"ElColorPickerInstance": true,
|
||||||
|
"ElRateInstance": true,
|
||||||
|
"ElSliderInstance": true,
|
||||||
"useRouter": true,
|
"useRouter": true,
|
||||||
"useRoute": true,
|
"useRoute": true,
|
||||||
"EffectScope": true,
|
"EffectScope": true,
|
||||||
|
@ -29,7 +29,8 @@ module.exports = {
|
|||||||
// 关闭空类型检查 {}
|
// 关闭空类型检查 {}
|
||||||
extendDefaults: true,
|
extendDefaults: true,
|
||||||
types: {
|
types: {
|
||||||
'{}': false
|
'{}': false,
|
||||||
|
'Function': false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
.history
|
||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ruoyi-vue-plus",
|
"name": "ruoyi-vue-plus",
|
||||||
"version": "5.0.0",
|
"version": "5.1.0",
|
||||||
"description": "RuoYi-Vue-Plus多租户管理系统",
|
"description": "RuoYi-Vue-Plus多租户管理系统",
|
||||||
"author": "LionLi",
|
"author": "LionLi",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -29,19 +29,23 @@
|
|||||||
"fuse.js": "6.6.2",
|
"fuse.js": "6.6.2",
|
||||||
"js-cookie": "3.0.1",
|
"js-cookie": "3.0.1",
|
||||||
"jsencrypt": "3.3.1",
|
"jsencrypt": "3.3.1",
|
||||||
|
"crypto-js": "^4.1.1",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"path-browserify": "1.0.1",
|
"path-browserify": "1.0.1",
|
||||||
"path-to-regexp": "6.2.0",
|
"path-to-regexp": "6.2.0",
|
||||||
"pinia": "2.0.22",
|
"pinia": "2.0.22",
|
||||||
"screenfull": "6.0.0",
|
"screenfull": "6.0.0",
|
||||||
|
"vform3-builds": "3.0.8",
|
||||||
"vue": "3.2.45",
|
"vue": "3.2.45",
|
||||||
"vue-cropper": "1.0.3",
|
"vue-cropper": "1.0.3",
|
||||||
"vue-i18n": "9.2.2",
|
"vue-i18n": "9.2.2",
|
||||||
"vue-router": "4.1.4"
|
"vue-router": "4.1.4",
|
||||||
|
"vue-types": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify/json": "^2.2.40",
|
"@iconify/json": "^2.2.40",
|
||||||
"@intlify/unplugin-vue-i18n": "0.8.2",
|
"@intlify/unplugin-vue-i18n": "0.8.2",
|
||||||
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/file-saver": "2.0.5",
|
"@types/file-saver": "2.0.5",
|
||||||
"@types/js-cookie": "3.0.3",
|
"@types/js-cookie": "3.0.3",
|
||||||
"@types/node": "18.14.2",
|
"@types/node": "18.14.2",
|
||||||
@ -69,11 +73,11 @@
|
|||||||
"unplugin-auto-import": "0.13.0",
|
"unplugin-auto-import": "0.13.0",
|
||||||
"unplugin-icons": "0.15.1",
|
"unplugin-icons": "0.15.1",
|
||||||
"unplugin-vue-components": "0.23.0",
|
"unplugin-vue-components": "0.23.0",
|
||||||
|
"vite": "4.3.1",
|
||||||
"vite-plugin-compression": "0.5.1",
|
"vite-plugin-compression": "0.5.1",
|
||||||
"vite-plugin-svg-icons": "2.0.1",
|
"vite-plugin-svg-icons": "2.0.1",
|
||||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||||
"vitest": "^0.29.7",
|
"vitest": "^0.29.7",
|
||||||
"vite": "4.3.1",
|
|
||||||
"vue-eslint-parser": "9.1.0",
|
"vue-eslint-parser": "9.1.0",
|
||||||
"vue-tsc": "0.35.0"
|
"vue-tsc": "0.35.0"
|
||||||
}
|
}
|
||||||
|
@ -3,22 +3,24 @@ import { AxiosPromise } from 'axios';
|
|||||||
import { LoginData, LoginResult, VerifyCodeResult, TenantInfo } from './types';
|
import { LoginData, LoginResult, VerifyCodeResult, TenantInfo } from './types';
|
||||||
import { UserInfo } from '@/api/system/user/types';
|
import { UserInfo } from '@/api/system/user/types';
|
||||||
|
|
||||||
|
// pc端固定客户端授权id
|
||||||
|
const clientId = import.meta.env.VITE_APP_CLIENT_ID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param data {LoginData}
|
* @param data {LoginData}
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function login(data: LoginData): AxiosPromise<LoginResult> {
|
export function login(data: LoginData): AxiosPromise<LoginResult> {
|
||||||
const params = {
|
const params = {
|
||||||
tenantId: data.tenantId,
|
...data,
|
||||||
username: data.username.trim(),
|
clientId: data.clientId || clientId,
|
||||||
password: data.password,
|
grantType: data.grantType || 'password'
|
||||||
code: data.code,
|
|
||||||
uuid: data.uuid
|
|
||||||
};
|
};
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/login',
|
url: '/auth/login',
|
||||||
headers: {
|
headers: {
|
||||||
isToken: false
|
isToken: false,
|
||||||
|
isEncrypt: true
|
||||||
},
|
},
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: params
|
data: params
|
||||||
@ -52,7 +54,7 @@ export function logout() {
|
|||||||
*/
|
*/
|
||||||
export function getCodeImg(): AxiosPromise<VerifyCodeResult> {
|
export function getCodeImg(): AxiosPromise<VerifyCodeResult> {
|
||||||
return request({
|
return request({
|
||||||
url: '/code',
|
url: '/auth/code',
|
||||||
headers: {
|
headers: {
|
||||||
isToken: false
|
isToken: false
|
||||||
},
|
},
|
||||||
@ -61,6 +63,22 @@ export function getCodeImg(): AxiosPromise<VerifyCodeResult> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录
|
||||||
|
*/
|
||||||
|
export function callback(data: LoginData): AxiosPromise<any> {
|
||||||
|
const LoginData = {
|
||||||
|
...data,
|
||||||
|
clientId: clientId,
|
||||||
|
grantType: 'social'
|
||||||
|
};
|
||||||
|
return request({
|
||||||
|
url: '/auth/social/callback',
|
||||||
|
method: 'post',
|
||||||
|
data: LoginData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 获取用户详细信息
|
// 获取用户详细信息
|
||||||
export function getInfo(): AxiosPromise<UserInfo> {
|
export function getInfo(): AxiosPromise<UserInfo> {
|
||||||
return request({
|
return request({
|
||||||
|
80
src/api/system/client/index.ts
Normal file
80
src/api/system/client/index.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { ClientVO, ClientForm, ClientQuery } from '@/api/system/client/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询客户端管理列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listClient = (query?: ClientQuery): AxiosPromise<ClientVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/system/client/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询客户端管理详细
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getClient = (id: string | number): AxiosPromise<ClientVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/system/client/' + id,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增客户端管理
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addClient = (data: ClientForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/system/client',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改客户端管理
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateClient = (data: ClientForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/system/client',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除客户端管理
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const delClient = (id: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/system/client/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态修改
|
||||||
|
* @param id ID
|
||||||
|
* @param status 状态
|
||||||
|
*/
|
||||||
|
export function changeStatus(id: number | string, status: string) {
|
||||||
|
const data = {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
};
|
||||||
|
return request({
|
||||||
|
url: '/system/client/changeStatus',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
}
|
138
src/api/system/client/types.ts
Normal file
138
src/api/system/client/types.ts
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
export interface ClientVO {
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端id
|
||||||
|
*/
|
||||||
|
clientId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端key
|
||||||
|
*/
|
||||||
|
clientKey: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端秘钥
|
||||||
|
*/
|
||||||
|
clientSecret: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权类型
|
||||||
|
*/
|
||||||
|
grantTypeList: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
*/
|
||||||
|
deviceType: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token活跃超时时间
|
||||||
|
*/
|
||||||
|
activeTimeout: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token固定超时
|
||||||
|
*/
|
||||||
|
timeout: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClientForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端id
|
||||||
|
*/
|
||||||
|
clientId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端key
|
||||||
|
*/
|
||||||
|
clientKey?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端秘钥
|
||||||
|
*/
|
||||||
|
clientSecret?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权类型
|
||||||
|
*/
|
||||||
|
grantTypeList?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
*/
|
||||||
|
deviceType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token活跃超时时间
|
||||||
|
*/
|
||||||
|
activeTimeout?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token固定超时
|
||||||
|
*/
|
||||||
|
timeout?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClientQuery extends PageQuery {
|
||||||
|
/**
|
||||||
|
* 客户端id
|
||||||
|
*/
|
||||||
|
clientId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端key
|
||||||
|
*/
|
||||||
|
clientKey?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端秘钥
|
||||||
|
*/
|
||||||
|
clientSecret?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权类型
|
||||||
|
*/
|
||||||
|
grantType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
*/
|
||||||
|
deviceType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token活跃超时时间
|
||||||
|
*/
|
||||||
|
activeTimeout?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token固定超时
|
||||||
|
*/
|
||||||
|
timeout?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
}
|
24
src/api/system/social/auth.ts
Normal file
24
src/api/system/social/auth.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
// 绑定账号
|
||||||
|
export function authBinding(source: string) {
|
||||||
|
return request({
|
||||||
|
url: '/auth/binding/' + source,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解绑账号
|
||||||
|
export function authUnlock(authId: string) {
|
||||||
|
return request({
|
||||||
|
url: '/auth/unlock/' + authId,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//获取授权列表
|
||||||
|
export function getAuthList() {
|
||||||
|
return request({
|
||||||
|
url: '/system/social/list',
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
@ -9,64 +9,64 @@ import { parseStrEmpty } from '@/utils/ruoyi';
|
|||||||
* 查询用户列表
|
* 查询用户列表
|
||||||
* @param query
|
* @param query
|
||||||
*/
|
*/
|
||||||
export function listUser(query: UserQuery): AxiosPromise<UserVO[]> {
|
export const listUser = (query: UserQuery): AxiosPromise<UserVO[]> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/list',
|
url: '/system/user/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户详情
|
* 获取用户详情
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
export function getUser(userId?: string | number): AxiosPromise<UserInfoVO> {
|
export const getUser = (userId?: string | number): AxiosPromise<UserInfoVO> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/' + parseStrEmpty(userId),
|
url: '/system/user/' + parseStrEmpty(userId),
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增用户
|
* 新增用户
|
||||||
*/
|
*/
|
||||||
export function addUser(data: UserForm) {
|
export const addUser = (data: UserForm) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user',
|
url: '/system/user',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改用户
|
* 修改用户
|
||||||
*/
|
*/
|
||||||
export function updateUser(data: UserForm) {
|
export const updateUser = (data: UserForm) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user',
|
url: '/system/user',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除用户
|
* 删除用户
|
||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
*/
|
*/
|
||||||
export function delUser(userId: Array<string | number> | string | number) {
|
export const delUser = (userId: Array<string | number> | string | number) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/' + userId,
|
url: '/system/user/' + userId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户密码重置
|
* 用户密码重置
|
||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
* @param password 密码
|
* @param password 密码
|
||||||
*/
|
*/
|
||||||
export function resetUserPwd(userId: string | number, password: string) {
|
export const resetUserPwd = (userId: string | number, password: string) => {
|
||||||
const data = {
|
const data = {
|
||||||
userId,
|
userId,
|
||||||
password
|
password
|
||||||
@ -76,14 +76,14 @@ export function resetUserPwd(userId: string | number, password: string) {
|
|||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户状态修改
|
* 用户状态修改
|
||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
* @param status 用户状态
|
* @param status 用户状态
|
||||||
*/
|
*/
|
||||||
export function changeUserStatus(userId: number | string, status: string) {
|
export const changeUserStatus = (userId: number | string, status: string) => {
|
||||||
const data = {
|
const data = {
|
||||||
userId,
|
userId,
|
||||||
status
|
status
|
||||||
@ -93,36 +93,36 @@ export function changeUserStatus(userId: number | string, status: string) {
|
|||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询用户个人信息
|
* 查询用户个人信息
|
||||||
*/
|
*/
|
||||||
export function getUserProfile(): AxiosPromise<UserInfoVO> {
|
export const getUserProfile = (): AxiosPromise<UserInfoVO> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile',
|
url: '/system/user/profile',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改用户个人信息
|
* 修改用户个人信息
|
||||||
* @param data 用户信息
|
* @param data 用户信息
|
||||||
*/
|
*/
|
||||||
export function updateUserProfile(data: UserForm) {
|
export const updateUserProfile = (data: UserForm) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile',
|
url: '/system/user/profile',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户密码重置
|
* 用户密码重置
|
||||||
* @param oldPassword 旧密码
|
* @param oldPassword 旧密码
|
||||||
* @param newPassword 新密码
|
* @param newPassword 新密码
|
||||||
*/
|
*/
|
||||||
export function updateUserPwd(oldPassword: string, newPassword: string) {
|
export const updateUserPwd = (oldPassword: string, newPassword: string) => {
|
||||||
const data = {
|
const data = {
|
||||||
oldPassword,
|
oldPassword,
|
||||||
newPassword
|
newPassword
|
||||||
@ -132,49 +132,66 @@ export function updateUserPwd(oldPassword: string, newPassword: string) {
|
|||||||
method: 'put',
|
method: 'put',
|
||||||
params: data
|
params: data
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户头像上传
|
* 用户头像上传
|
||||||
* @param data 头像文件
|
* @param data 头像文件
|
||||||
*/
|
*/
|
||||||
export function uploadAvatar(data: FormData) {
|
export const uploadAvatar = (data: FormData) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile/avatar',
|
url: '/system/user/profile/avatar',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询授权角色
|
* 查询授权角色
|
||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
*/
|
*/
|
||||||
export function getAuthRole(userId: string | number): AxiosPromise<{ user: UserVO; roles: RoleVO[] }> {
|
export const getAuthRole = (userId: string | number): AxiosPromise<{ user: UserVO; roles: RoleVO[] }> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/authRole/' + userId,
|
url: '/system/user/authRole/' + userId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存授权角色
|
* 保存授权角色
|
||||||
* @param data 用户ID
|
* @param data 用户ID
|
||||||
*/
|
*/
|
||||||
export function updateAuthRole(data: { userId: string; roleIds: string }) {
|
export const updateAuthRole = (data: { userId: string; roleIds: string }) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/authRole',
|
url: '/system/user/authRole',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
params: data
|
params: data
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询部门下拉树结构
|
* 查询部门下拉树结构
|
||||||
*/
|
*/
|
||||||
export function deptTreeSelect(): AxiosPromise<DeptVO[]> {
|
export const deptTreeSelect = (): AxiosPromise<DeptVO[]> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/deptTree',
|
url: '/system/user/deptTree',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
listUser,
|
||||||
|
getUser,
|
||||||
|
addUser,
|
||||||
|
updateUser,
|
||||||
|
delUser,
|
||||||
|
resetUserPwd,
|
||||||
|
changeUserStatus,
|
||||||
|
getUserProfile,
|
||||||
|
updateUserProfile,
|
||||||
|
updateUserPwd,
|
||||||
|
uploadAvatar,
|
||||||
|
getAuthRole,
|
||||||
|
updateAuthRole,
|
||||||
|
deptTreeSelect
|
||||||
|
};
|
||||||
|
@ -15,19 +15,24 @@ export type RegisterForm = {
|
|||||||
* 登录请求
|
* 登录请求
|
||||||
*/
|
*/
|
||||||
export interface LoginData {
|
export interface LoginData {
|
||||||
tenantId: string;
|
tenantId?: string;
|
||||||
username: string;
|
username?: string;
|
||||||
password: string;
|
password?: string;
|
||||||
rememberMe?: boolean;
|
rememberMe?: boolean;
|
||||||
|
socialCode?: string;
|
||||||
|
socialState?: string;
|
||||||
|
source?: string;
|
||||||
code?: string;
|
code?: string;
|
||||||
uuid?: string;
|
uuid?: string;
|
||||||
|
clientId: string;
|
||||||
|
grantType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录响应
|
* 登录响应
|
||||||
*/
|
*/
|
||||||
export interface LoginResult {
|
export interface LoginResult {
|
||||||
token: string;
|
access_token: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
1
src/assets/icons/svg/gitee.svg
Normal file
1
src/assets/icons/svg/gitee.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1686919908144" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2521" width="200" height="200" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 992C246.895625 992 32 777.104375 32 512S246.895625 32 512 32s480 214.895625 480 480-214.895625 480-480 480z m242.9521875-533.3278125h-272.56875a23.7121875 23.7121875 0 0 0-23.71125 23.7121875l-0.024375 59.255625c0 13.08 10.6078125 23.7121875 23.6878125 23.7121875h165.96c13.104375 0 23.7121875 10.6078125 23.7121875 23.6878125v11.855625a71.1121875 71.1121875 0 0 1-71.1121875 71.1121875h-225.215625a23.7121875 23.7121875 0 0 1-23.6878125-23.7121875V423.1278125a71.1121875 71.1121875 0 0 1 71.0878125-71.1121875h331.824375a23.7121875 23.7121875 0 0 0 23.6878125-23.71125l0.0721875-59.2565625a23.7121875 23.7121875 0 0 0-23.68875-23.7121875H423.08a177.76875 177.76875 0 0 0-177.76875 177.7921875V754.953125c0 13.1034375 10.60875 23.7121875 23.713125 23.7121875h349.63125a159.984375 159.984375 0 0 0 159.984375-159.984375V482.36a23.7121875 23.7121875 0 0 0-23.7121875-23.6878125z" fill="#515151" p-id="2522"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
3
src/assets/icons/svg/maxkey.svg
Normal file
3
src/assets/icons/svg/maxkey.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.3 KiB |
@ -26,6 +26,10 @@ html {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.dark .svg-icon, html.dark svg {
|
||||||
|
fill: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
@ -137,6 +141,7 @@ aside {
|
|||||||
border: 1px solid var(--el-border-color-light);
|
border: 1px solid var(--el-border-color-light);
|
||||||
background-color: var(--el-bg-color-overlay);
|
background-color: var(--el-bg-color-overlay);
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
|
transition: all ease 0.3s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 2px 12px #0000001a;
|
box-shadow: 0 2px 12px #0000001a;
|
||||||
|
@ -90,8 +90,8 @@ h6 {
|
|||||||
.el-table__fixed-header-wrapper {
|
.el-table__fixed-header-wrapper {
|
||||||
th {
|
th {
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
background-color: #f8f8f9 !important;
|
background-color: $table-header-bg !important;
|
||||||
color: #515a6e;
|
color: $table-header-text-color;
|
||||||
height: 40px !important;
|
height: 40px !important;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
.sub-menu-title-noDropdown,
|
.sub-menu-title-noDropdown,
|
||||||
.el-sub-menu__title {
|
.el-sub-menu__title {
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
background-color: $base-sub-menu-title-hover !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,7 @@
|
|||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
&:hover {
|
&:hover {
|
||||||
// you can use $sub-menuHover
|
// you can use $sub-menuHover
|
||||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
background-color: $base-menu-hover !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,40 @@
|
|||||||
|
// 全局SCSS变量
|
||||||
|
:root {
|
||||||
|
--menuBg: #304156;
|
||||||
|
--menuColor: #bfcbd9;
|
||||||
|
--menuActiveText: #f4f4f5;
|
||||||
|
--menuHover: #263445;
|
||||||
|
|
||||||
|
--subMenuBg: #1f2d3d;
|
||||||
|
--subMenuActiveText: #f4f4f5;
|
||||||
|
--subMenuHover: #001528;
|
||||||
|
--subMenuTitleHover: #293444;
|
||||||
|
|
||||||
|
--fixedHeaderBg: #ffffff;
|
||||||
|
--tableHeaderBg: #f8f8f9;
|
||||||
|
--tableHeaderTextColor: #515a6e;
|
||||||
|
}
|
||||||
|
html.dark {
|
||||||
|
--menuBg: #1d1e1f;
|
||||||
|
--menuColor: #bfcbd9;
|
||||||
|
--menuActiveText: #f4f4f5;
|
||||||
|
--menuHover: #171819;
|
||||||
|
|
||||||
|
--subMenuBg: #1d1e1f;
|
||||||
|
--subMenuActiveText: #1d1e1f;
|
||||||
|
--subMenuHover: #171819;
|
||||||
|
--subMenuTitleHover: #171819;
|
||||||
|
|
||||||
|
--fixedHeaderBg: #171819;
|
||||||
|
--tableHeaderBg: var(--el-bg-color);
|
||||||
|
--tableHeaderTextColor: var(--el-text-color);
|
||||||
|
|
||||||
|
// 覆盖ele 高亮当前行的标准暗色
|
||||||
|
.el-tree-node__content {
|
||||||
|
--el-color-primary-light-9: #262727;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// base color
|
// base color
|
||||||
$blue: #324157;
|
$blue: #324157;
|
||||||
$light-blue: #3a71a8;
|
$light-blue: #3a71a8;
|
||||||
@ -9,32 +46,23 @@ $yellow: #fec171;
|
|||||||
$panGreen: #30b08f;
|
$panGreen: #30b08f;
|
||||||
|
|
||||||
// 默认菜单主题风格
|
// 默认菜单主题风格
|
||||||
$base-menu-color: #bfcbd9;
|
$base-menu-color: var(--menuColor);
|
||||||
$base-menu-color-active: #f4f4f5;
|
$base-menu-hover: var(--menuHover);
|
||||||
$base-menu-background: #304156;
|
$base-menu-color-active: var(--menuActiveText);
|
||||||
|
$base-menu-background: var(--menuBg);
|
||||||
$base-logo-title-color: #ffffff;
|
$base-logo-title-color: #ffffff;
|
||||||
|
|
||||||
$base-menu-light-color: rgba(0, 0, 0, 0.7);
|
$base-menu-light-color: rgba(0, 0, 0, 0.7);
|
||||||
$base-menu-light-background: #ffffff;
|
$base-menu-light-background: #ffffff;
|
||||||
$base-logo-light-title-color: #001529;
|
$base-logo-light-title-color: #001529;
|
||||||
|
|
||||||
$base-sub-menu-background: #1f2d3d;
|
$base-sub-menu-background: var(--subMenuBg);
|
||||||
$base-sub-menu-hover: #001528;
|
$base-sub-menu-hover: var(--subMenuHover);
|
||||||
|
$base-sub-menu-title-hover: var(--subMenuTitleHover);
|
||||||
// 自定义暗色菜单风格
|
// 表单头背景色和标题颜色
|
||||||
/**
|
$fixed-header-bg: var(--fixedHeaderBg);
|
||||||
$base-menu-color:hsla(0,0%,100%,.65);
|
$table-header-bg: var(--tableHeaderBg);
|
||||||
$base-menu-color-active:#fff;
|
$table-header-text-color: var(--tableHeaderTextColor);
|
||||||
$base-menu-background:#001529;
|
|
||||||
$base-logo-title-color: #ffffff;
|
|
||||||
|
|
||||||
$base-menu-light-color:rgba(0,0,0,.70);
|
|
||||||
$base-menu-light-background:#ffffff;
|
|
||||||
$base-logo-light-title-color: #001529;
|
|
||||||
|
|
||||||
$base-sub-menu-background:#000c17;
|
|
||||||
$base-sub-menu-hover:#001528;
|
|
||||||
*/
|
|
||||||
|
|
||||||
$--color-primary: #409eff;
|
$--color-primary: #409eff;
|
||||||
$--color-success: #67c23a;
|
$--color-success: #67c23a;
|
||||||
|
64
src/components/BuildCode/index.vue
Normal file
64
src/components/BuildCode/index.vue
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<!-- 代码构建 -->
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
showBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
formJson: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
const buildRef = ref();
|
||||||
|
const emits = defineEmits(['reJson', 'saveDesign']);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//获取表单json
|
||||||
|
const getJson = () => {
|
||||||
|
const formJson = JSON.stringify(buildRef.value.getFormJson())
|
||||||
|
const fieldJson = JSON.stringify(buildRef.value.getFieldWidgets())
|
||||||
|
let data = {
|
||||||
|
formJson, fieldJson
|
||||||
|
}
|
||||||
|
emits("saveDesign", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.formJson) {
|
||||||
|
buildRef.value.setFormJson(props.formJson)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<v-form-designer
|
||||||
|
class="build"
|
||||||
|
ref="buildRef"
|
||||||
|
:designer-config="{ importJsonButton: true, exportJsonButton: true, exportCodeButton: true, generateSFCButton: true, formTemplates: true }"
|
||||||
|
>
|
||||||
|
<template #customToolButtons v-if="showBtn">
|
||||||
|
<el-button link type="primary" icon="Select" @click="getJson">保存</el-button>
|
||||||
|
</template>
|
||||||
|
</v-form-designer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.build {
|
||||||
|
margin: 0 !important;
|
||||||
|
overflow-y: auto !important;
|
||||||
|
|
||||||
|
& header.main-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .right-toolbar-con {
|
||||||
|
text-align: right !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
62
src/components/BuildCode/render.vue
Normal file
62
src/components/BuildCode/render.vue
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<!-- 动态表单渲染 -->
|
||||||
|
<script setup name="Render">
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
formJson: {
|
||||||
|
type: [String, Object],
|
||||||
|
default: {}
|
||||||
|
},
|
||||||
|
formData: {
|
||||||
|
type: [String, Object],
|
||||||
|
default: {}
|
||||||
|
},
|
||||||
|
isView: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const vFormRef = ref(null)
|
||||||
|
// 获取表单数据-异步
|
||||||
|
const getFormData = () => {
|
||||||
|
return vFormRef.value.getFormData()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置表单内容
|
||||||
|
* @param {表单配置} formConf
|
||||||
|
* formConfig:{ formTemplate:表单模板,formData:表单数据,hiddenField:需要隐藏的字段字符串集合,disabledField:需要禁用的自读字符串集合}
|
||||||
|
*/
|
||||||
|
const initForm = (formConf) => {
|
||||||
|
const { formTemplate, formData, hiddenField, disabledField } = toRaw(formConf)
|
||||||
|
if (formTemplate) {
|
||||||
|
vFormRef.value.setFormJson(formTemplate)
|
||||||
|
if (formData) {
|
||||||
|
vFormRef.value.setFormData(formData)
|
||||||
|
}
|
||||||
|
if (disabledField && disabledField.length > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
vFormRef.value.disableWidgets(disabledField)
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
if (hiddenField && hiddenField.length > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
vFormRef.value.hideWidgets(hiddenField)
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
if (props.isView) {
|
||||||
|
console.log(props.isView)
|
||||||
|
setTimeout(() => {
|
||||||
|
vFormRef.value.disableForm()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ getFormData, initForm })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="">
|
||||||
|
<v-form-render ref="vFormRef" :form-json="formJson" :form-data="formData" />
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -24,7 +24,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PropType } from 'vue';
|
import { propTypes } from '@/utils/propTypes';
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -36,10 +36,7 @@ const props = defineProps({
|
|||||||
// 当前的值
|
// 当前的值
|
||||||
value: [Number, String, Array] as PropType<number | string | Array<number | string>>,
|
value: [Number, String, Array] as PropType<number | string | Array<number | string>>,
|
||||||
// 当未找到匹配的数据时,显示value
|
// 当未找到匹配的数据时,显示value
|
||||||
showValue: {
|
showValue: propTypes.bool.def(true),
|
||||||
type: Boolean as PropType<boolean>,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const values = computed(() => {
|
const values = computed(() => {
|
||||||
|
@ -29,45 +29,28 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { QuillEditor, Quill } from '@vueup/vue-quill';
|
import { QuillEditor, Quill } from '@vueup/vue-quill';
|
||||||
import '@vueup/vue-quill/dist/vue-quill.snow.css';
|
import '@vueup/vue-quill/dist/vue-quill.snow.css';
|
||||||
import { getToken } from "@/utils/auth";
|
import { propTypes } from '@/utils/propTypes';
|
||||||
import { ComponentInternalInstance } from "vue";
|
import { globalHeaders } from "@/utils/request";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
/* 编辑器的内容 */
|
/* 编辑器的内容 */
|
||||||
modelValue: {
|
modelValue: propTypes.string,
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
/* 高度 */
|
/* 高度 */
|
||||||
height: {
|
height: propTypes.number.def(400),
|
||||||
type: Number,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
/* 最小高度 */
|
/* 最小高度 */
|
||||||
minHeight: {
|
minHeight: propTypes.number.def(400),
|
||||||
type: Number,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
/* 只读 */
|
/* 只读 */
|
||||||
readOnly: {
|
readOnly: propTypes.bool.def(false),
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
/* 上传文件大小限制(MB) */
|
/* 上传文件大小限制(MB) */
|
||||||
fileSize: {
|
fileSize: propTypes.number.def(5),
|
||||||
type: Number,
|
|
||||||
default: 5,
|
|
||||||
},
|
|
||||||
/* 类型(base64格式、url格式) */
|
/* 类型(base64格式、url格式) */
|
||||||
type: {
|
type: propTypes.string.def('url')
|
||||||
type: String,
|
|
||||||
default: "url",
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
const upload = reactive<UploadOption>({
|
const upload = reactive<UploadOption>({
|
||||||
headers: { Authorization: "Bearer " + getToken() },
|
headers: globalHeaders,
|
||||||
url: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload'
|
url: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload'
|
||||||
})
|
})
|
||||||
const myQuillEditor = ref();
|
const myQuillEditor = ref();
|
||||||
@ -82,7 +65,7 @@ const options = ref({
|
|||||||
container: [
|
container: [
|
||||||
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
||||||
["blockquote", "code-block"], // 引用 代码块
|
["blockquote", "code-block"], // 引用 代码块
|
||||||
[{ list: "ordered" }, { list: "bullet"} ], // 有序、无序列表
|
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
|
||||||
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
||||||
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
||||||
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
||||||
@ -166,16 +149,20 @@ const handleUploadError = (err: any) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.editor, .ql-toolbar {
|
.editor,
|
||||||
|
.ql-toolbar {
|
||||||
white-space: pre-wrap !important;
|
white-space: pre-wrap !important;
|
||||||
line-height: normal !important;
|
line-height: normal !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quill-img {
|
.quill-img {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
||||||
content: "请输入链接地址:";
|
content: "请输入链接地址:";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
content: "保存";
|
content: "保存";
|
||||||
@ -190,14 +177,17 @@ const handleUploadError = (err: any) => {
|
|||||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||||
content: "14px";
|
content: "14px";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
||||||
content: "10px";
|
content: "10px";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
||||||
content: "18px";
|
content: "18px";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
||||||
content: "32px";
|
content: "32px";
|
||||||
@ -207,26 +197,32 @@ const handleUploadError = (err: any) => {
|
|||||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
||||||
content: "文本";
|
content: "文本";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
||||||
content: "标题1";
|
content: "标题1";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
||||||
content: "标题2";
|
content: "标题2";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
||||||
content: "标题3";
|
content: "标题3";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
||||||
content: "标题4";
|
content: "标题4";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
||||||
content: "标题5";
|
content: "标题5";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
||||||
content: "标题6";
|
content: "标题6";
|
||||||
@ -236,10 +232,12 @@ const handleUploadError = (err: any) => {
|
|||||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||||
content: "标准字体";
|
content: "标准字体";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
||||||
content: "衬线字体";
|
content: "衬线字体";
|
||||||
}
|
}
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
||||||
content: "等宽字体";
|
content: "等宽字体";
|
||||||
|
@ -43,33 +43,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getToken } from "@/utils/auth";
|
|
||||||
import { listByIds, delOss } from "@/api/system/oss";
|
import { listByIds, delOss } from "@/api/system/oss";
|
||||||
import { ComponentInternalInstance } from "vue";
|
import { propTypes } from '@/utils/propTypes';
|
||||||
import { ElUpload, UploadFile } from "element-plus";
|
import { globalHeaders } from "@/utils/request";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: [String, Object, Array],
|
modelValue: [String, Object, Array],
|
||||||
// 数量限制
|
// 数量限制
|
||||||
limit: {
|
limit: propTypes.number.def(5),
|
||||||
type: Number,
|
|
||||||
default: 5,
|
|
||||||
},
|
|
||||||
// 大小限制(MB)
|
// 大小限制(MB)
|
||||||
fileSize: {
|
fileSize: propTypes.number.def(5),
|
||||||
type: Number,
|
|
||||||
default: 5,
|
|
||||||
},
|
|
||||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||||
fileType: {
|
fileType: propTypes.array.def(["doc", "xls", "ppt", "txt", "pdf"]),
|
||||||
type: Array,
|
|
||||||
default: () => ["doc", "xls", "ppt", "txt", "pdf"],
|
|
||||||
},
|
|
||||||
// 是否显示提示
|
// 是否显示提示
|
||||||
isShowTip: {
|
isShowTip: propTypes.bool.def(true),
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@ -79,14 +66,14 @@ const uploadList = ref<any[]>([]);
|
|||||||
|
|
||||||
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
||||||
const uploadFileUrl = ref(baseUrl + "/resource/oss/upload"); // 上传文件服务器地址
|
const uploadFileUrl = ref(baseUrl + "/resource/oss/upload"); // 上传文件服务器地址
|
||||||
const headers = ref({ Authorization: "Bearer " + getToken() });
|
const headers = ref(globalHeaders);
|
||||||
|
|
||||||
const fileList = ref<any[]>([]);
|
const fileList = ref<any[]>([]);
|
||||||
const showTip = computed(
|
const showTip = computed(
|
||||||
() => props.isShowTip && (props.fileType || props.fileSize)
|
() => props.isShowTip && (props.fileType || props.fileSize)
|
||||||
);
|
);
|
||||||
|
|
||||||
const fileUploadRef = ref(ElUpload);
|
const fileUploadRef = ref<ElUploadInstance>();
|
||||||
|
|
||||||
watch(() => props.modelValue, async val => {
|
watch(() => props.modelValue, async val => {
|
||||||
if (val) {
|
if (val) {
|
||||||
@ -104,7 +91,7 @@ watch(() => props.modelValue, async val => {
|
|||||||
}
|
}
|
||||||
// 然后将数组转为对象数组
|
// 然后将数组转为对象数组
|
||||||
fileList.value = list.map(item => {
|
fileList.value = list.map(item => {
|
||||||
item = {name: item.name, url: item.url, ossId: item.ossId};
|
item = { name: item.name, url: item.url, ossId: item.ossId };
|
||||||
item.uid = item.uid || new Date().getTime() + temp++;
|
item.uid = item.uid || new Date().getTime() + temp++;
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
@ -112,7 +99,7 @@ watch(() => props.modelValue, async val => {
|
|||||||
fileList.value = [];
|
fileList.value = [];
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},{ deep: true, immediate: true });
|
}, { deep: true, immediate: true });
|
||||||
|
|
||||||
// 上传前校检格式和大小
|
// 上传前校检格式和大小
|
||||||
const handleBeforeUpload = (file: any) => {
|
const handleBeforeUpload = (file: any) => {
|
||||||
@ -150,7 +137,7 @@ const handleUploadError = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 上传成功回调
|
// 上传成功回调
|
||||||
const handleUploadSuccess = (res:any, file: UploadFile) => {
|
const handleUploadSuccess = (res: any, file: UploadFile) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
uploadList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });
|
uploadList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });
|
||||||
uploadedSuccessfully();
|
uploadedSuccessfully();
|
||||||
@ -158,7 +145,7 @@ const handleUploadSuccess = (res:any, file: UploadFile) => {
|
|||||||
number.value--;
|
number.value--;
|
||||||
proxy?.$modal.closeLoading();
|
proxy?.$modal.closeLoading();
|
||||||
proxy?.$modal.msgError(res.msg);
|
proxy?.$modal.msgError(res.msg);
|
||||||
fileUploadRef.value.handleRemove(file);
|
fileUploadRef.value?.handleRemove(file);
|
||||||
uploadedSuccessfully();
|
uploadedSuccessfully();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,7 +159,7 @@ const handleDelete = (index: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 上传结束处理
|
// 上传结束处理
|
||||||
const uploadedSuccessfully =() => {
|
const uploadedSuccessfully = () => {
|
||||||
if (number.value > 0 && uploadList.value.length === number.value) {
|
if (number.value > 0 && uploadList.value.length === number.value) {
|
||||||
fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
|
fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
|
||||||
uploadList.value = [];
|
uploadList.value = [];
|
||||||
@ -209,18 +196,21 @@ const listToString = (list: any[], separator?: string) => {
|
|||||||
.upload-file-uploader {
|
.upload-file-uploader {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-file-list .el-upload-list__item {
|
.upload-file-list .el-upload-list__item {
|
||||||
border: 1px solid #e4e7ed;
|
border: 1px solid #e4e7ed;
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-file-list .ele-upload-list__item-content {
|
.upload-file-list .ele-upload-list__item-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ele-upload-list__item-content-action .el-link {
|
.ele-upload-list__item-content-action .el-link {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="padding: 0 15px;" @click="toggleClick">
|
<div style="padding: 0 15px;" @click="toggleClick">
|
||||||
<svg :class="{'is-active':isActive}" class="hamburger" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
|
<svg :class="{ 'is-active': isActive }" class="hamburger" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
|
||||||
<path
|
<path
|
||||||
d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"
|
d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"
|
||||||
/>
|
/>
|
||||||
@ -9,11 +9,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { propTypes } from '@/utils/propTypes';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
isActive: {
|
isActive: propTypes.bool.def(false)
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['toggleClick'])
|
const emit = defineEmits(['toggleClick'])
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts" name="HeaderSearch">
|
||||||
import Fuse from 'fuse.js'
|
import Fuse from 'fuse.js';
|
||||||
import { getNormalPath } from '@/utils/ruoyi'
|
import { getNormalPath } from '@/utils/ruoyi';
|
||||||
import { isHttp } from '@/utils/validate'
|
import { isHttp } from '@/utils/validate';
|
||||||
import usePermissionStore from '@/store/modules/permission'
|
import usePermissionStore from '@/store/modules/permission';
|
||||||
import { RouteOption } from 'vue-router'
|
import { RouteOption } from 'vue-router';
|
||||||
|
|
||||||
type Router = Array<{
|
type Router = Array<{
|
||||||
path: string;
|
path: string;
|
||||||
@ -34,7 +34,7 @@ const options = ref<any>([]);
|
|||||||
const searchPool = ref<Router>([]);
|
const searchPool = ref<Router>([]);
|
||||||
const show = ref(false);
|
const show = ref(false);
|
||||||
const fuse = ref();
|
const fuse = ref();
|
||||||
const headerSearchSelectRef = ref(ElSelect);
|
const headerSearchSelectRef = ref<ElSelectInstance>();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const routes = computed(() => usePermissionStore().routes);
|
const routes = computed(() => usePermissionStore().routes);
|
||||||
|
|
||||||
@ -123,9 +123,9 @@ onMounted(() => {
|
|||||||
searchPool.value = generateRoutes(routes.value);
|
searchPool.value = generateRoutes(routes.value);
|
||||||
})
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
// watchEffect(() => {
|
||||||
searchPool.value = generateRoutes(routes.value)
|
// searchPool.value = generateRoutes(routes.value)
|
||||||
})
|
// })
|
||||||
|
|
||||||
watch(show, (value) => {
|
watch(show, (value) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -31,17 +31,11 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import icons from '@/components/IconSelect/requireIcons';
|
import icons from '@/components/IconSelect/requireIcons';
|
||||||
|
import { propTypes } from '@/utils/propTypes';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: propTypes.string.isRequired,
|
||||||
type: String,
|
width: propTypes.string.def('400px')
|
||||||
require: true
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
require: false,
|
|
||||||
default: '400px'
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
@ -9,11 +9,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { propTypes } from '@/utils/propTypes';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
src: {
|
src: propTypes.string.def(''),
|
||||||
type: String,
|
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
width: {
|
width: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: ""
|
default: ""
|
||||||
@ -37,7 +36,7 @@ const realSrcList = computed(() => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let real_src_list = props.src.split(",");
|
let real_src_list = props.src.split(",");
|
||||||
let srcList:string[] = [];
|
let srcList: string[] = [];
|
||||||
real_src_list.forEach(item => {
|
real_src_list.forEach(item => {
|
||||||
return srcList.push(item);
|
return srcList.push(item);
|
||||||
});
|
});
|
||||||
@ -58,13 +57,16 @@ const realHeight = computed(() =>
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background-color: #ebeef5;
|
background-color: #ebeef5;
|
||||||
box-shadow: 0 0 5px 1px #ccc;
|
box-shadow: 0 0 5px 1px #ccc;
|
||||||
|
|
||||||
:deep(.el-image__inner) {
|
:deep(.el-image__inner) {
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.image-slot) {
|
:deep(.image-slot) {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
:on-preview="handlePictureCardPreview"
|
:on-preview="handlePictureCardPreview"
|
||||||
:class="{ hide: fileList.length >= limit }"
|
:class="{ hide: fileList.length >= limit }"
|
||||||
>
|
>
|
||||||
<el-icon class="avatar-uploader-icon"><plus /></el-icon>
|
<el-icon class="avatar-uploader-icon">
|
||||||
|
<plus />
|
||||||
|
</el-icon>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<!-- 上传提示 -->
|
<!-- 上传提示 -->
|
||||||
<div class="el-upload__tip" v-if="showTip">
|
<div class="el-upload__tip" v-if="showTip">
|
||||||
@ -38,29 +40,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getToken } from "@/utils/auth";
|
|
||||||
import { listByIds, delOss } from "@/api/system/oss";
|
import { listByIds, delOss } from "@/api/system/oss";
|
||||||
import { ComponentInternalInstance, PropType } from "vue";
|
import { ComponentInternalInstance } from "vue";
|
||||||
import { OssVO } from "@/api/system/oss/types";
|
import { OssVO } from "@/api/system/oss/types";
|
||||||
import { ElUpload, UploadFile } from "element-plus";
|
import { propTypes } from '@/utils/propTypes';
|
||||||
|
import {globalHeaders} from "@/utils/request";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: [String, Object, Array],
|
modelValue: [String, Object, Array],
|
||||||
// 图片数量限制
|
// 图片数量限制
|
||||||
limit: {
|
limit: propTypes.number.def(5),
|
||||||
type: Number,
|
|
||||||
default: 5,
|
|
||||||
},
|
|
||||||
// 大小限制(MB)
|
// 大小限制(MB)
|
||||||
fileSize: {
|
fileSize: propTypes.number.def(5),
|
||||||
type: Number,
|
|
||||||
default: 5,
|
|
||||||
},
|
|
||||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||||
fileType: {
|
fileType: propTypes.array.def(["png", "jpg", "jpeg"]),
|
||||||
type: Array as PropType<string[]>,
|
|
||||||
default: () => ["png", "jpg", "jpeg"],
|
|
||||||
},
|
|
||||||
// 是否显示提示
|
// 是否显示提示
|
||||||
isShowTip: {
|
isShowTip: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -77,19 +70,19 @@ const dialogVisible = ref(false);
|
|||||||
|
|
||||||
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
||||||
const uploadImgUrl = ref(baseUrl + "/resource/oss/upload"); // 上传的图片服务器地址
|
const uploadImgUrl = ref(baseUrl + "/resource/oss/upload"); // 上传的图片服务器地址
|
||||||
const headers = ref({ Authorization: "Bearer " + getToken() });
|
const headers = ref(globalHeaders);
|
||||||
|
|
||||||
const fileList = ref<any[]>([]);
|
const fileList = ref<any[]>([]);
|
||||||
const showTip = computed(
|
const showTip = computed(
|
||||||
() => props.isShowTip && (props.fileType || props.fileSize)
|
() => props.isShowTip && (props.fileType || props.fileSize)
|
||||||
);
|
);
|
||||||
|
|
||||||
const imageUploadRef = ref(ElUpload);
|
const imageUploadRef = ref<ElUploadInstance>();
|
||||||
|
|
||||||
watch(() => props.modelValue, async val => {
|
watch(() => props.modelValue, async val => {
|
||||||
if (val) {
|
if (val) {
|
||||||
// 首先将值转为数组
|
// 首先将值转为数组
|
||||||
let list:OssVO[] = [];
|
let list: OssVO[] = [];
|
||||||
if (Array.isArray(val)) {
|
if (Array.isArray(val)) {
|
||||||
list = val as OssVO[];
|
list = val as OssVO[];
|
||||||
} else {
|
} else {
|
||||||
@ -112,7 +105,7 @@ watch(() => props.modelValue, async val => {
|
|||||||
fileList.value = [];
|
fileList.value = [];
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},{ deep: true, immediate: true });
|
}, { deep: true, immediate: true });
|
||||||
|
|
||||||
/** 上传前loading加载 */
|
/** 上传前loading加载 */
|
||||||
const handleBeforeUpload = (file: any) => {
|
const handleBeforeUpload = (file: any) => {
|
||||||
@ -122,7 +115,7 @@ const handleBeforeUpload = (file: any) => {
|
|||||||
if (file.name.lastIndexOf(".") > -1) {
|
if (file.name.lastIndexOf(".") > -1) {
|
||||||
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
||||||
}
|
}
|
||||||
isImg = props.fileType.some((type) => {
|
isImg = props.fileType.some((type: any) => {
|
||||||
if (file.type.indexOf(type) > -1) return true;
|
if (file.type.indexOf(type) > -1) return true;
|
||||||
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
||||||
return false;
|
return false;
|
||||||
@ -161,7 +154,7 @@ const handleUploadSuccess = (res: any, file: UploadFile) => {
|
|||||||
number.value--;
|
number.value--;
|
||||||
proxy?.$modal.closeLoading();
|
proxy?.$modal.closeLoading();
|
||||||
proxy?.$modal.msgError(res.msg);
|
proxy?.$modal.msgError(res.msg);
|
||||||
imageUploadRef.value.handleRemove(file);
|
imageUploadRef.value?.handleRemove(file);
|
||||||
uploadedSuccessfully();
|
uploadedSuccessfully();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,7 +200,7 @@ const listToString = (list: any[], separator?: string) => {
|
|||||||
let strs = "";
|
let strs = "";
|
||||||
separator = separator || ",";
|
separator = separator || ",";
|
||||||
for (let i in list) {
|
for (let i in list) {
|
||||||
if(undefined !== list[i].ossId && list[i].url.indexOf("blob:") !== 0) {
|
if (undefined !== list[i].ossId && list[i].url.indexOf("blob:") !== 0) {
|
||||||
strs += list[i].ossId + separator;
|
strs += list[i].ossId + separator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,52 +22,23 @@ export default {
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { scrollTo } from '@/utils/scroll-to'
|
import { scrollTo } from '@/utils/scroll-to'
|
||||||
import { PropType } from "vue";
|
import { propTypes } from "@/utils/propTypes";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
total: {
|
total: propTypes.number,
|
||||||
required: true,
|
page: propTypes.number.def(1),
|
||||||
type: Number
|
limit: propTypes.number.def(20),
|
||||||
},
|
|
||||||
page: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
limit: {
|
|
||||||
type: Number,
|
|
||||||
default: 20
|
|
||||||
},
|
|
||||||
pageSizes: {
|
pageSizes: {
|
||||||
type: Array as PropType<number[]>,
|
type: Array as PropType<number[]>,
|
||||||
default() {
|
default: () => [10, 20, 30, 50]
|
||||||
return [10, 20, 30, 50]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// 移动端页码按钮的数量端默认值5
|
// 移动端页码按钮的数量端默认值5
|
||||||
pagerCount: {
|
pagerCount: propTypes.number.def(document.body.clientWidth < 992 ? 5 : 7),
|
||||||
type: Number,
|
layout: propTypes.string.def('total, sizes, prev, pager, next, jumper'),
|
||||||
default: document.body.clientWidth < 992 ? 5 : 7
|
background: propTypes.bool.def(true),
|
||||||
},
|
autoScroll: propTypes.bool.def(true),
|
||||||
layout: {
|
hidden: propTypes.bool.def(false),
|
||||||
type: String,
|
float: propTypes.string.def('right')
|
||||||
default: 'total, sizes, prev, pager, next, jumper'
|
|
||||||
},
|
|
||||||
background: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
autoScroll: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
hidden: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
float: {
|
|
||||||
type: String,
|
|
||||||
default: 'right'
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:page', 'update:limit', 'pagination']);
|
const emit = defineEmits(['update:page', 'update:limit', 'pagination']);
|
||||||
@ -106,7 +77,6 @@ function handleCurrentChange(val: number) {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.pagination-container {
|
.pagination-container {
|
||||||
background: #fff;
|
|
||||||
padding: 32px 16px;
|
padding: 32px 16px;
|
||||||
.el-pagination{
|
.el-pagination{
|
||||||
float: v-bind(float);
|
float: v-bind(float);
|
||||||
|
@ -18,25 +18,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { TransferKey } from "element-plus";
|
import { propTypes } from '@/utils/propTypes';
|
||||||
import { PropType } from "vue";
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
showSearch: {
|
showSearch: propTypes.bool.def(true),
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
columns: {
|
columns: {
|
||||||
type: Array as PropType<FieldOption[]>,
|
type: Array as PropType<FieldOption[]>,
|
||||||
},
|
},
|
||||||
search: {
|
search: propTypes.bool.def(true),
|
||||||
type: Boolean,
|
gutter: propTypes.number.def(10),
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
gutter: {
|
|
||||||
type: Number,
|
|
||||||
default: 10,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emits = defineEmits(['update:showSearch', 'queryTable']);
|
const emits = defineEmits(['update:showSearch', 'queryTable']);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
const url = ref('https://javalionli.gitee.io/plus-doc');
|
const url = ref('https://plus-doc.dromara.org/');
|
||||||
|
|
||||||
function goto() {
|
function goto() {
|
||||||
window.open(url.value)
|
window.open(url.value)
|
||||||
|
@ -5,19 +5,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { propTypes } from '@/utils/propTypes';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
iconClass: {
|
iconClass: propTypes.string.isRequired,
|
||||||
type: String,
|
className: propTypes.string.def(''),
|
||||||
required: true
|
color: propTypes.string.def(''),
|
||||||
},
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
color: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
const iconName = computed(() => `#icon-${props.iconClass}`);
|
const iconName = computed(() => `#icon-${props.iconClass}`);
|
||||||
const svgClass = computed(() => {
|
const svgClass = computed(() => {
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ElTreeSelect } from 'element-plus'
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
/* 配置项 */
|
/* 配置项 */
|
||||||
@ -68,7 +67,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const selectTree = ref(ElTreeSelect);
|
const selectTree = ref<ElTreeSelectInstance>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:value']);
|
const emit = defineEmits(['update:value']);
|
||||||
|
|
||||||
@ -81,14 +80,14 @@ const valueId = computed({
|
|||||||
const valueTitle = ref('');
|
const valueTitle = ref('');
|
||||||
const defaultExpandedKey = ref<any[]>([]);
|
const defaultExpandedKey = ref<any[]>([]);
|
||||||
|
|
||||||
function initHandle() {
|
const initHandle = () => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const selectedValue = valueId.value;
|
const selectedValue = valueId.value;
|
||||||
if(selectedValue !== null && typeof (selectedValue) !== 'undefined') {
|
if (selectedValue !== null && typeof (selectedValue) !== 'undefined') {
|
||||||
const node = selectTree.value.getNode(selectedValue)
|
const node = selectTree.value?.getNode(selectedValue)
|
||||||
if (node) {
|
if (node) {
|
||||||
valueTitle.value = node.data[props.objMap.label]
|
valueTitle.value = node.data[props.objMap.label]
|
||||||
selectTree.value.setCurrentKey(selectedValue) // 设置默认选中
|
selectTree.value?.setCurrentKey(selectedValue) // 设置默认选中
|
||||||
defaultExpandedKey.value = [selectedValue] // 设置默认展开
|
defaultExpandedKey.value = [selectedValue] // 设置默认展开
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -96,27 +95,27 @@ function initHandle() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function handleNodeClick(node: any) {
|
const handleNodeClick = (node: any) => {
|
||||||
valueTitle.value = node[props.objMap.label]
|
valueTitle.value = node[props.objMap.label]
|
||||||
valueId.value = node[props.objMap.value];
|
valueId.value = node[props.objMap.value];
|
||||||
defaultExpandedKey.value = [];
|
defaultExpandedKey.value = [];
|
||||||
selectTree.value.blur()
|
selectTree.value?.blur()
|
||||||
selectFilterData('')
|
selectFilterData('')
|
||||||
}
|
}
|
||||||
function selectFilterData(val: any) {
|
const selectFilterData = (val: any) => {
|
||||||
selectTree.value.filter(val)
|
selectTree.value?.filter(val)
|
||||||
}
|
}
|
||||||
function filterNode(value: any, data: any) {
|
const filterNode = (value: any, data: any) => {
|
||||||
if (!value) return true
|
if (!value) return true
|
||||||
return data[props.objMap['label']].indexOf(value) !== -1
|
return data[props.objMap['label']].indexOf(value) !== -1
|
||||||
}
|
}
|
||||||
function clearHandle() {
|
const clearHandle = () => {
|
||||||
valueTitle.value = ''
|
valueTitle.value = ''
|
||||||
valueId.value = ''
|
valueId.value = ''
|
||||||
defaultExpandedKey.value = [];
|
defaultExpandedKey.value = [];
|
||||||
clearSelected()
|
clearSelected()
|
||||||
}
|
}
|
||||||
function clearSelected() {
|
const clearSelected = () => {
|
||||||
const allNode = document.querySelectorAll('#tree-option .el-tree-node')
|
const allNode = document.querySelectorAll('#tree-option .el-tree-node')
|
||||||
allNode.forEach((element) => element.classList.remove('is-current'))
|
allNode.forEach((element) => element.classList.remove('is-current'))
|
||||||
}
|
}
|
||||||
@ -132,6 +131,7 @@ watch(valueId, () => {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "@/assets/styles/variables.module.scss";
|
@import "@/assets/styles/variables.module.scss";
|
||||||
|
|
||||||
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
|
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
@ -5,11 +5,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { propTypes } from '@/utils/propTypes';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
src: {
|
src: propTypes.string.isRequired
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const height = ref(document.documentElement.clientHeight - 94.5 + "px;")
|
const height = ref(document.documentElement.clientHeight - 94.5 + "px;")
|
||||||
|
@ -20,8 +20,13 @@
|
|||||||
<template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
|
<template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|
||||||
<header-search id="header-search" class="right-menu-item" />
|
<!-- <header-search id="header-search" class="right-menu-item" /> -->
|
||||||
|
<search-menu ref="searchMenuRef" />
|
||||||
|
<el-tooltip content="搜索" effect="dark" placement="bottom">
|
||||||
|
<div class="right-menu-item hover-effect" @click="openSearchMenu">
|
||||||
|
<svg-icon class-name="search-icon" icon-class="search" />
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
<el-tooltip content="Github" effect="dark" placement="bottom">
|
<el-tooltip content="Github" effect="dark" placement="bottom">
|
||||||
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@ -68,17 +73,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import useAppStore from '@/store/modules/app'
|
import SearchMenu from './topBar/search.vue';
|
||||||
import useUserStore from '@/store/modules/user'
|
import useAppStore from '@/store/modules/app';
|
||||||
import useSettingsStore from '@/store/modules/settings'
|
import useUserStore from '@/store/modules/user';
|
||||||
|
import useSettingsStore from '@/store/modules/settings';
|
||||||
import { getTenantList } from "@/api/login";
|
import { getTenantList } from "@/api/login";
|
||||||
import { dynamicClear, dynamicTenant } from "@/api/system/tenant";
|
import { dynamicClear, dynamicTenant } from "@/api/system/tenant";
|
||||||
import { ComponentInternalInstance } from "vue";
|
import { ComponentInternalInstance } from "vue";
|
||||||
import { TenantVO } from "@/api/types";
|
import { TenantVO } from "@/api/types";
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore();
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore();
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore();
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
@ -89,6 +95,12 @@ const tenantList = ref<TenantVO[]>([]);
|
|||||||
const dynamic = ref(false);
|
const dynamic = ref(false);
|
||||||
// 租户开关
|
// 租户开关
|
||||||
const tenantEnabled = ref(true);
|
const tenantEnabled = ref(true);
|
||||||
|
// 搜索菜单
|
||||||
|
const searchMenuRef = ref<InstanceType<typeof SearchMenu>>();
|
||||||
|
|
||||||
|
const openSearchMenu = () => {
|
||||||
|
searchMenuRef.value?.openSearch();
|
||||||
|
}
|
||||||
|
|
||||||
// 动态切换
|
// 动态切换
|
||||||
const dynamicTenantEvent = async (tenantId: string) => {
|
const dynamicTenantEvent = async (tenantId: string) => {
|
||||||
@ -104,7 +116,7 @@ const dynamicClearEvent = async () => {
|
|||||||
await dynamicClear();
|
await dynamicClear();
|
||||||
dynamic.value = false;
|
dynamic.value = false;
|
||||||
proxy?.$tab.closeAllPage();
|
proxy?.$tab.closeAllPage();
|
||||||
proxy?.$router.push('/')
|
proxy?.$router.push('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 租户列表 */
|
/** 租户列表 */
|
||||||
@ -121,7 +133,7 @@ defineExpose({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const toggleSideBar = () => {
|
const toggleSideBar = () => {
|
||||||
appStore.toggleSideBar(false)
|
appStore.toggleSideBar(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
@ -169,7 +181,7 @@ const handleCommand = (command: string) => {
|
|||||||
height: 50px;
|
height: 50px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #fff;
|
//background: #fff;
|
||||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||||
|
|
||||||
.hamburger-container {
|
.hamburger-container {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-drawer v-model="showSettings" :withHeader="false" direction="rtl" size="300px" close-on-click-modal>
|
<el-drawer v-model="showSettings" :withHeader="false" direction="rtl" size="300px" close-on-click-modal>
|
||||||
<div class="setting-drawer-title">
|
|
||||||
<h3 class="drawer-title">主题风格设置</h3>
|
<h3 class="drawer-title">主题风格设置</h3>
|
||||||
</div>
|
|
||||||
<div class="setting-drawer-block-checbox">
|
<div class="setting-drawer-block-checbox">
|
||||||
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
|
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
|
||||||
<img src="@/assets/images/dark.svg" alt="dark" />
|
<img src="@/assets/images/dark.svg" alt="dark" />
|
||||||
@ -35,6 +34,13 @@
|
|||||||
<el-color-picker v-model="theme" :predefine="predefineColors" @change="themeChange" />
|
<el-color-picker v-model="theme" :predefine="predefineColors" @change="themeChange" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="drawer-item">
|
||||||
|
<span>深色模式</span>
|
||||||
|
<span class="comp-style">
|
||||||
|
<el-switch v-model="isDark" @change="toggleDark" class="drawer-switch" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-divider />
|
<el-divider />
|
||||||
|
|
||||||
<h3 class="drawer-title">系统布局配置</h3>
|
<h3 class="drawer-title">系统布局配置</h3>
|
||||||
@ -102,7 +108,15 @@ const sideTheme = ref(settingsStore.sideTheme);
|
|||||||
const storeSettings = computed(() => settingsStore);
|
const storeSettings = computed(() => settingsStore);
|
||||||
const predefineColors = ref(["#409EFF", "#ff4500", "#ff8c00", "#ffd700", "#90ee90", "#00ced1", "#1e90ff", "#c71585"]);
|
const predefineColors = ref(["#409EFF", "#ff4500", "#ff8c00", "#ffd700", "#90ee90", "#00ced1", "#1e90ff", "#c71585"]);
|
||||||
|
|
||||||
/** 是否需要topnav */
|
// 是否暗黑模式
|
||||||
|
const isDark = useDark({
|
||||||
|
storageKey: 'useDarkKey',
|
||||||
|
valueDark: 'dark',
|
||||||
|
valueLight: 'light',
|
||||||
|
});
|
||||||
|
const toggleDark = () => useToggle(isDark);
|
||||||
|
|
||||||
|
/** 是否需要topNav */
|
||||||
const topNav = computed({
|
const topNav = computed({
|
||||||
get: () => storeSettings.value.topNav,
|
get: () => storeSettings.value.topNav,
|
||||||
set: (val) => {
|
set: (val) => {
|
||||||
@ -234,7 +248,6 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.drawer-item {
|
.drawer-item {
|
||||||
color: rgba(0, 0, 0, 0.65);
|
|
||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
|
89
src/layout/components/SocialCallback/index.vue
Normal file
89
src/layout/components/SocialCallback/index.vue
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<div v-loading="loading" class="social-callback"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { login, callback } from '@/api/login';
|
||||||
|
import { setToken } from '@/utils/auth';
|
||||||
|
import Cookies from 'js-cookie';
|
||||||
|
import { getToken } from '@/utils/auth';
|
||||||
|
import { LoginData } from '@/api/types';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const loading = ref(true);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收Route传递的参数
|
||||||
|
* @param {Object} route.query.
|
||||||
|
*/
|
||||||
|
const code = route.query.code as string;
|
||||||
|
const state = route.query.state as string;
|
||||||
|
const source = route.query.source as string;
|
||||||
|
const tenantId = Cookies.get("tenantId") ? Cookies.get("tenantId") as string : '000000';
|
||||||
|
|
||||||
|
|
||||||
|
const processResponse = async (res: any) => {
|
||||||
|
if (res.code !== 200) {
|
||||||
|
throw new Error(res.msg);
|
||||||
|
}
|
||||||
|
if (res.data !== null) {
|
||||||
|
setToken(res.data.access_token);
|
||||||
|
}
|
||||||
|
ElMessage.success(res.msg);
|
||||||
|
setTimeout(() => {
|
||||||
|
location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index';
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleError = (error: any) => {
|
||||||
|
ElMessage.error(error.message);
|
||||||
|
setTimeout(() => {
|
||||||
|
location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index';
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const callbackByCode = async (data: LoginData) => {
|
||||||
|
try {
|
||||||
|
const res = await callback(data);
|
||||||
|
await processResponse(res);
|
||||||
|
loading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loginByCode = async (data: LoginData) => {
|
||||||
|
console.log(2)
|
||||||
|
try {
|
||||||
|
const res = await login(data);
|
||||||
|
await processResponse(res);
|
||||||
|
loading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const init = async () => {
|
||||||
|
const data: LoginData = {
|
||||||
|
socialCode: code,
|
||||||
|
socialState: state,
|
||||||
|
tenantId: tenantId,
|
||||||
|
source: source,
|
||||||
|
clientId: 'e5cd7e4891bf95d1d19206ce24a7b32e',
|
||||||
|
grantType: 'social'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!getToken()) {
|
||||||
|
await loginByCode(data);
|
||||||
|
} else {
|
||||||
|
await callbackByCode(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
@ -6,22 +6,21 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import useTagsViewStore from '@/store/modules/tagsView'
|
import useTagsViewStore from '@/store/modules/tagsView'
|
||||||
import { ElScrollbar } from 'element-plus';
|
|
||||||
import { TagView } from 'vue-router'
|
import { TagView } from 'vue-router'
|
||||||
const tagAndTagSpacing = ref(4);
|
const tagAndTagSpacing = ref(4);
|
||||||
|
|
||||||
const scrollContainerRef = ref(ElScrollbar)
|
const scrollContainerRef = ref<ElScrollbarInstance>()
|
||||||
const scrollWrapper = computed(() => scrollContainerRef.value.$refs.wrapRef);
|
const scrollWrapper = computed(() => scrollContainerRef.value?.$refs.wrapRef as any);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
scrollWrapper.value.addEventListener('scroll', emitScroll, true)
|
scrollWrapper.value?.addEventListener('scroll', emitScroll, true)
|
||||||
})
|
})
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
scrollWrapper.value.removeEventListener('scroll', emitScroll)
|
scrollWrapper.value?.removeEventListener('scroll', emitScroll)
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleScroll = (e: WheelEvent) => {
|
const handleScroll = (e: WheelEvent) => {
|
||||||
const eventDelta = (e as any).wheelDelta || -e.deltaY * 40
|
const eventDelta = (e as any).wheelDelta || - e.deltaY * 40
|
||||||
const $scrollWrapper = scrollWrapper.value;
|
const $scrollWrapper = scrollWrapper.value;
|
||||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
||||||
}
|
}
|
||||||
@ -34,7 +33,7 @@ const tagsViewStore = useTagsViewStore()
|
|||||||
const visitedViews = computed(() => tagsViewStore.visitedViews);
|
const visitedViews = computed(() => tagsViewStore.visitedViews);
|
||||||
|
|
||||||
const moveToTarget = (currentTag: TagView) => {
|
const moveToTarget = (currentTag: TagView) => {
|
||||||
const $container = scrollContainerRef.value.$el
|
const $container = scrollContainerRef.value?.$el
|
||||||
const $containerWidth = $container.offsetWidth
|
const $containerWidth = $container.offsetWidth
|
||||||
const $scrollWrapper = scrollWrapper.value;
|
const $scrollWrapper = scrollWrapper.value;
|
||||||
|
|
||||||
@ -96,7 +95,7 @@ defineExpose({
|
|||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
}
|
}
|
||||||
:deep(.el-scrollbar__wrap) {
|
:deep(.el-scrollbar__wrap) {
|
||||||
height: 39px;
|
height: 49px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -125,6 +125,9 @@ const initTags = () => {
|
|||||||
}
|
}
|
||||||
const addTags = () => {
|
const addTags = () => {
|
||||||
const { name } = route;
|
const { name } = route;
|
||||||
|
if(route.query.title) {
|
||||||
|
route.meta.title = route.query.title;
|
||||||
|
}
|
||||||
if (name) {
|
if (name) {
|
||||||
useTagsViewStore().addView(route);
|
useTagsViewStore().addView(route);
|
||||||
if (route.meta.link) {
|
if (route.meta.link) {
|
||||||
@ -237,8 +240,8 @@ onMounted(() => {
|
|||||||
.tags-view-container {
|
.tags-view-container {
|
||||||
height: 34px;
|
height: 34px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background-color: var(--el-bg-color);
|
||||||
border-bottom: 1px solid #d8dce5;
|
border: 1px solid var(--el-border-color-light);
|
||||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
|
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
|
||||||
.tags-view-wrapper {
|
.tags-view-wrapper {
|
||||||
.tags-view-item {
|
.tags-view-item {
|
||||||
@ -247,13 +250,16 @@ onMounted(() => {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
line-height: 23px;
|
line-height: 23px;
|
||||||
border: 1px solid #d8dce5;
|
background-color: var(--el-bg-color);
|
||||||
|
border: 1px solid var(--el-border-color-light);
|
||||||
color: #495060;
|
color: #495060;
|
||||||
background: #fff;
|
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
|
&:hover {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
&:first-of-type {
|
&:first-of-type {
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
@ -279,7 +285,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
.contextmenu {
|
.contextmenu {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: #fff;
|
background: var(--el-bg-color);
|
||||||
z-index: 3000;
|
z-index: 3000;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
@ -287,7 +293,6 @@ onMounted(() => {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #333;
|
|
||||||
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
|
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
|
||||||
li {
|
li {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
158
src/layout/components/topBar/search.vue
Normal file
158
src/layout/components/topBar/search.vue
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-search-dialog">
|
||||||
|
<el-dialog v-model="state.isShowSearch" destroy-on-close :show-close="false">
|
||||||
|
<template #footer>
|
||||||
|
<el-autocomplete
|
||||||
|
v-model="state.menuQuery"
|
||||||
|
:fetch-suggestions="menuSearch"
|
||||||
|
placeholder="搜索"
|
||||||
|
ref="layoutMenuAutocompleteRef"
|
||||||
|
@select="onHandleSelect"
|
||||||
|
:fit-input-width="true"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<svg-icon class-name="search-icon" icon-class="search" />
|
||||||
|
</template>
|
||||||
|
<template #default="{ item }">
|
||||||
|
<div>
|
||||||
|
<svg-icon :icon-class="item.icon" class="mr5" />
|
||||||
|
{{ item.title }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-autocomplete>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="layoutBreadcrumbSearch">
|
||||||
|
import { getNormalPath } from '@/utils/ruoyi';
|
||||||
|
import { isHttp } from '@/utils/validate';
|
||||||
|
import usePermissionStore from '@/store/modules/permission';
|
||||||
|
import { RouteOption } from 'vue-router';
|
||||||
|
type Router = Array<{
|
||||||
|
path: string;
|
||||||
|
icon: string;
|
||||||
|
title: string[];
|
||||||
|
}>
|
||||||
|
type SearchState<T = any> = {
|
||||||
|
isShowSearch: boolean;
|
||||||
|
menuQuery: string;
|
||||||
|
menuList: T[];
|
||||||
|
};
|
||||||
|
// 定义变量内容
|
||||||
|
const layoutMenuAutocompleteRef = ref();
|
||||||
|
const router = useRouter();
|
||||||
|
const routes = computed(() => usePermissionStore().routes);
|
||||||
|
const state = reactive<SearchState>({
|
||||||
|
isShowSearch: false,
|
||||||
|
menuQuery: '',
|
||||||
|
menuList: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索弹窗打开
|
||||||
|
const openSearch = () => {
|
||||||
|
state.menuQuery = '';
|
||||||
|
state.isShowSearch = true;
|
||||||
|
state.menuList = generateRoutes(routes.value);
|
||||||
|
nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
layoutMenuAutocompleteRef.value.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 搜索弹窗关闭
|
||||||
|
const closeSearch = () => {
|
||||||
|
state.isShowSearch = false;
|
||||||
|
};
|
||||||
|
// 菜单搜索数据过滤
|
||||||
|
const menuSearch = (queryString: string, cb: Function) => {
|
||||||
|
let options = state.menuList.filter((item) => {
|
||||||
|
return item.title.indexOf(queryString) > -1;
|
||||||
|
});
|
||||||
|
cb(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Filter out the routes that can be displayed in the sidebar
|
||||||
|
// And generate the internationalized title
|
||||||
|
const generateRoutes = (routes: RouteOption[], basePath = '', prefixTitle: string[] = []) => {
|
||||||
|
let res: Router = []
|
||||||
|
routes.forEach(r => {
|
||||||
|
// skip hidden router
|
||||||
|
if (!r.hidden) {
|
||||||
|
const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path;
|
||||||
|
const data: any = {
|
||||||
|
path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path,
|
||||||
|
icon: r.meta?.icon,
|
||||||
|
title: [...prefixTitle]
|
||||||
|
}
|
||||||
|
if (r.meta && r.meta.title) {
|
||||||
|
data.title = [...data.title, r.meta.title];
|
||||||
|
if (r.redirect !== 'noRedirect') {
|
||||||
|
// only push the routes with title
|
||||||
|
// special case: need to exclude parent router without redirect
|
||||||
|
res.push(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// recursive child routes
|
||||||
|
if (r.children) {
|
||||||
|
const tempRoutes = generateRoutes(r.children, data.path, data.title);
|
||||||
|
if (tempRoutes.length >= 1) {
|
||||||
|
res = [...res, ...tempRoutes];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
res.forEach((item: any) => {
|
||||||
|
if (item.title instanceof Array) {
|
||||||
|
item.title = item.title.join('/');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
// 当前菜单选中时
|
||||||
|
const onHandleSelect = (val: any) => {
|
||||||
|
const paths = val.path;
|
||||||
|
if (isHttp(paths)) {
|
||||||
|
// http(s):// 路径新窗口打开
|
||||||
|
const pindex = paths.indexOf("http");
|
||||||
|
window.open(paths.substring(pindex, paths.length), "_blank");
|
||||||
|
} else {
|
||||||
|
router.push(paths);
|
||||||
|
}
|
||||||
|
state.menuQuery = ''
|
||||||
|
closeSearch();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 暴露变量
|
||||||
|
defineExpose({
|
||||||
|
openSearch
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.layout-search-dialog {
|
||||||
|
position: relative;
|
||||||
|
:deep(.el-dialog) {
|
||||||
|
.el-dialog__header,
|
||||||
|
.el-dialog__body {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.el-dialog__footer {
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
top: -53vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.el-autocomplete) {
|
||||||
|
width: 560px;
|
||||||
|
position: absolute;
|
||||||
|
top: 150px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -107,6 +107,7 @@ const setLayout = () => {
|
|||||||
z-index: 9;
|
z-index: 9;
|
||||||
width: calc(100% - #{$base-sidebar-width});
|
width: calc(100% - #{$base-sidebar-width});
|
||||||
transition: width 0.28s;
|
transition: width 0.28s;
|
||||||
|
background: $fixed-header-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hideSidebar .fixed-header {
|
.hideSidebar .fixed-header {
|
||||||
|
@ -10,7 +10,7 @@ import useSettingsStore from '@/store/modules/settings';
|
|||||||
import usePermissionStore from '@/store/modules/permission';
|
import usePermissionStore from '@/store/modules/permission';
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false });
|
NProgress.configure({ showSpinner: false });
|
||||||
const whiteList = ['/login', '/register'];
|
const whiteList = ['/login', '/register', '/social-callback'];
|
||||||
|
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
NProgress.start();
|
NProgress.start();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import FileSaver from 'file-saver';
|
import FileSaver from 'file-saver';
|
||||||
import { getToken } from '@/utils/auth';
|
|
||||||
import errorCode from '@/utils/errorCode';
|
import errorCode from '@/utils/errorCode';
|
||||||
import { blobValidate } from '@/utils/ruoyi';
|
import { blobValidate } from '@/utils/ruoyi';
|
||||||
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
|
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
|
||||||
|
import { globalHeaders } from "@/utils/request";
|
||||||
|
|
||||||
const baseURL = import.meta.env.VITE_APP_BASE_API;
|
const baseURL = import.meta.env.VITE_APP_BASE_API;
|
||||||
let downloadLoadingInstance: LoadingInstance;
|
let downloadLoadingInstance: LoadingInstance;
|
||||||
@ -16,7 +16,7 @@ export default {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
url: url,
|
url: url,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
headers: { Authorization: 'Bearer ' + getToken() }
|
headers: globalHeaders,
|
||||||
});
|
});
|
||||||
const isBlob = blobValidate(res.data);
|
const isBlob = blobValidate(res.data);
|
||||||
if (isBlob) {
|
if (isBlob) {
|
||||||
@ -34,14 +34,13 @@ export default {
|
|||||||
},
|
},
|
||||||
async zip(url: string, name: string) {
|
async zip(url: string, name: string) {
|
||||||
url = baseURL + url;
|
url = baseURL + url;
|
||||||
|
downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' });
|
||||||
|
try {
|
||||||
const res = await axios({
|
const res = await axios({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: url,
|
url: url,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
headers: {
|
headers: globalHeaders,
|
||||||
Authorization: 'Bearer ' + getToken(),
|
|
||||||
datasource: localStorage.getItem('dataName')
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
const isBlob = blobValidate(res.data);
|
const isBlob = blobValidate(res.data);
|
||||||
if (isBlob) {
|
if (isBlob) {
|
||||||
@ -50,6 +49,12 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.printErrMsg(res.data);
|
this.printErrMsg(res.data);
|
||||||
}
|
}
|
||||||
|
downloadLoadingInstance.close();
|
||||||
|
} catch (r) {
|
||||||
|
console.error(r);
|
||||||
|
ElMessage.error('下载文件出现错误,请联系管理员!');
|
||||||
|
downloadLoadingInstance.close();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async printErrMsg(data: any) {
|
async printErrMsg(data: any) {
|
||||||
const resText = await data.text();
|
const resText = await data.text();
|
||||||
|
@ -1,57 +1,57 @@
|
|||||||
import { ElMessage, ElMessageBox, ElNotification, ElLoading, MessageBoxData } from 'element-plus';
|
import { MessageBoxData } from 'element-plus';
|
||||||
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
|
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
|
||||||
let loadingInstance: LoadingInstance;
|
let loadingInstance: LoadingInstance;
|
||||||
export default {
|
export default {
|
||||||
// 消息提示
|
// 消息提示
|
||||||
msg(content: string) {
|
msg(content: any) {
|
||||||
ElMessage.info(content);
|
ElMessage.info(content);
|
||||||
},
|
},
|
||||||
// 错误消息
|
// 错误消息
|
||||||
msgError(content: string) {
|
msgError(content: any) {
|
||||||
ElMessage.error(content);
|
ElMessage.error(content);
|
||||||
},
|
},
|
||||||
// 成功消息
|
// 成功消息
|
||||||
msgSuccess(content: string) {
|
msgSuccess(content: any) {
|
||||||
ElMessage.success(content);
|
ElMessage.success(content);
|
||||||
},
|
},
|
||||||
// 警告消息
|
// 警告消息
|
||||||
msgWarning(content: string) {
|
msgWarning(content: any) {
|
||||||
ElMessage.warning(content);
|
ElMessage.warning(content);
|
||||||
},
|
},
|
||||||
// 弹出提示
|
// 弹出提示
|
||||||
alert(content: string) {
|
alert(content: any) {
|
||||||
ElMessageBox.alert(content, '系统提示');
|
ElMessageBox.alert(content, '系统提示');
|
||||||
},
|
},
|
||||||
// 错误提示
|
// 错误提示
|
||||||
alertError(content: string) {
|
alertError(content: any) {
|
||||||
ElMessageBox.alert(content, '系统提示', { type: 'error' });
|
ElMessageBox.alert(content, '系统提示', { type: 'error' });
|
||||||
},
|
},
|
||||||
// 成功提示
|
// 成功提示
|
||||||
alertSuccess(content: string, s: string, p: { dangerouslyUseHTMLString: boolean }) {
|
alertSuccess(content: any) {
|
||||||
ElMessageBox.alert(content, '系统提示', { type: 'success' });
|
ElMessageBox.alert(content, '系统提示', { type: 'success' });
|
||||||
},
|
},
|
||||||
// 警告提示
|
// 警告提示
|
||||||
alertWarning(content: string) {
|
alertWarning(content: any) {
|
||||||
ElMessageBox.alert(content, '系统提示', { type: 'warning' });
|
ElMessageBox.alert(content, '系统提示', { type: 'warning' });
|
||||||
},
|
},
|
||||||
// 通知提示
|
// 通知提示
|
||||||
notify(content: string) {
|
notify(content: any) {
|
||||||
ElNotification.info(content);
|
ElNotification.info(content);
|
||||||
},
|
},
|
||||||
// 错误通知
|
// 错误通知
|
||||||
notifyError(content: string) {
|
notifyError(content: any) {
|
||||||
ElNotification.error(content);
|
ElNotification.error(content);
|
||||||
},
|
},
|
||||||
// 成功通知
|
// 成功通知
|
||||||
notifySuccess(content: string) {
|
notifySuccess(content: any) {
|
||||||
ElNotification.success(content);
|
ElNotification.success(content);
|
||||||
},
|
},
|
||||||
// 警告通知
|
// 警告通知
|
||||||
notifyWarning(content: string) {
|
notifyWarning(content: any) {
|
||||||
ElNotification.warning(content);
|
ElNotification.warning(content);
|
||||||
},
|
},
|
||||||
// 确认窗体
|
// 确认窗体
|
||||||
confirm(content: string): Promise<MessageBoxData> {
|
confirm(content: any): Promise<MessageBoxData> {
|
||||||
return ElMessageBox.confirm(content, '系统提示', {
|
return ElMessageBox.confirm(content, '系统提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
@ -59,7 +59,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 提交内容
|
// 提交内容
|
||||||
prompt(content: string) {
|
prompt(content: any) {
|
||||||
return ElMessageBox.prompt(content, '系统提示', {
|
return ElMessageBox.prompt(content, '系统提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
|
@ -3,8 +3,11 @@ import router from '@/router';
|
|||||||
import { TagView, RouteLocationRaw } from 'vue-router';
|
import { TagView, RouteLocationRaw } from 'vue-router';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// 刷新当前tab页签
|
/**
|
||||||
async refreshPage(obj: TagView): Promise<void> {
|
* 刷新当前tab页签
|
||||||
|
* @param obj 标签对象
|
||||||
|
*/
|
||||||
|
async refreshPage(obj?: TagView): Promise<void> {
|
||||||
const { path, query, matched } = router.currentRoute.value;
|
const { path, query, matched } = router.currentRoute.value;
|
||||||
if (obj === undefined) {
|
if (obj === undefined) {
|
||||||
matched.forEach((m) => {
|
matched.forEach((m) => {
|
||||||
@ -15,11 +18,16 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// prettier-ignore
|
let query1: undefined | {} = {};
|
||||||
await useTagsViewStore().delCachedView(obj)
|
let path1: undefined | string = '';
|
||||||
router.replace({
|
if (obj) {
|
||||||
path: '/redirect' + obj.path,
|
query1 = obj.query;
|
||||||
query: obj.query
|
path1 = obj.path;
|
||||||
|
}
|
||||||
|
await useTagsViewStore().delCachedView(obj);
|
||||||
|
await router.replace({
|
||||||
|
path: '/redirect' + path1,
|
||||||
|
query: query1
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 关闭当前tab页签,打开新页签
|
// 关闭当前tab页签,打开新页签
|
||||||
@ -34,9 +42,9 @@ export default {
|
|||||||
if (obj === undefined) {
|
if (obj === undefined) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const { visitedViews } = await useTagsViewStore().delView(router.currentRoute.value) as any
|
const { visitedViews } = await useTagsViewStore().delView(router.currentRoute.value) as any
|
||||||
const latestView = visitedViews.slice(-1)[0]
|
const latestView = visitedViews.slice(-1)[0];
|
||||||
if (latestView) {
|
if (latestView) {
|
||||||
return router.push(latestView.fullPath)
|
return router.push(latestView.fullPath);
|
||||||
}
|
}
|
||||||
return router.push('/');
|
return router.push('/');
|
||||||
}
|
}
|
||||||
@ -47,22 +55,31 @@ export default {
|
|||||||
return useTagsViewStore().delAllViews();
|
return useTagsViewStore().delAllViews();
|
||||||
},
|
},
|
||||||
// 关闭左侧tab页签
|
// 关闭左侧tab页签
|
||||||
closeLeftPage(obj: TagView) {
|
closeLeftPage(obj?: TagView) {
|
||||||
return useTagsViewStore().delLeftTags(obj || router.currentRoute.value);
|
return useTagsViewStore().delLeftTags(obj || router.currentRoute.value);
|
||||||
},
|
},
|
||||||
// 关闭右侧tab页签
|
// 关闭右侧tab页签
|
||||||
closeRightPage(obj: TagView) {
|
closeRightPage(obj?: TagView) {
|
||||||
return useTagsViewStore().delRightTags(obj || router.currentRoute.value);
|
return useTagsViewStore().delRightTags(obj || router.currentRoute.value);
|
||||||
},
|
},
|
||||||
// 关闭其他tab页签
|
// 关闭其他tab页签
|
||||||
closeOtherPage(obj: TagView) {
|
closeOtherPage(obj?: TagView) {
|
||||||
return useTagsViewStore().delOthersViews(obj || router.currentRoute.value);
|
return useTagsViewStore().delOthersViews(obj || router.currentRoute.value);
|
||||||
},
|
},
|
||||||
// 打开tab页签
|
/**
|
||||||
openPage(url: RouteLocationRaw) {
|
* 打开tab页签
|
||||||
return router.push(url);
|
* @param url 路由地址
|
||||||
|
* @param title 标题
|
||||||
|
* @param query 参数
|
||||||
|
*/
|
||||||
|
openPage(url: string, title?: string, query?: any) {
|
||||||
|
const obj = { path: url, query: { ...query, title } };
|
||||||
|
return router.push(obj);
|
||||||
},
|
},
|
||||||
// 修改tab页签
|
/**
|
||||||
|
* 修改tab页签
|
||||||
|
* @param obj 标签对象
|
||||||
|
*/
|
||||||
updatePage(obj: TagView) {
|
updatePage(obj: TagView) {
|
||||||
return useTagsViewStore().updateVisitedView(obj);
|
return useTagsViewStore().updateVisitedView(obj);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,11 @@ export const constantRoutes: RouteOption[] = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/social-callback',
|
||||||
|
hidden: true,
|
||||||
|
component: () => import('@/layout/components/SocialCallback/index.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
component: () => import('@/views/login.vue'),
|
component: () => import('@/views/login.vue'),
|
||||||
@ -176,4 +181,5 @@ const router = createRouter({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -54,8 +54,11 @@ export const useTagsViewStore = defineStore('tagsView', () => {
|
|||||||
resolve([...visitedViews.value]);
|
resolve([...visitedViews.value]);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const delCachedView = (view: TagView): Promise<string[]> => {
|
const delCachedView = (view?: TagView): Promise<string[]> => {
|
||||||
const viewName = view.name as string;
|
let viewName = '';
|
||||||
|
if (view) {
|
||||||
|
viewName = view.name as string;
|
||||||
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const index = cachedViews.value.indexOf(viewName);
|
const index = cachedViews.value.indexOf(viewName);
|
||||||
index > -1 && cachedViews.value.splice(index, 1);
|
index > -1 && cachedViews.value.splice(index, 1);
|
||||||
@ -167,6 +170,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
|
|||||||
|
|
||||||
const addCachedView = (view: TagView): void => {
|
const addCachedView = (view: TagView): void => {
|
||||||
const viewName = view.name as string;
|
const viewName = view.name as string;
|
||||||
|
if (!viewName) return;
|
||||||
if (cachedViews.value.includes(viewName)) return;
|
if (cachedViews.value.includes(viewName)) return;
|
||||||
if (!view.meta?.noCache) {
|
if (!view.meta?.noCache) {
|
||||||
cachedViews.value.push(viewName);
|
cachedViews.value.push(viewName);
|
||||||
|
@ -23,8 +23,8 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const [err, res] = await to(loginApi(userInfo));
|
const [err, res] = await to(loginApi(userInfo));
|
||||||
if (res) {
|
if (res) {
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
setToken(data.token);
|
setToken(data.access_token);
|
||||||
token.value = data.token;
|
token.value = data.access_token;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
|
36
src/types/element.d.ts
vendored
36
src/types/element.d.ts
vendored
@ -1 +1,35 @@
|
|||||||
declare type ElTagType = '' | 'success' | 'warning' | 'info' | 'danger' | 'default' | 'primary';
|
import type * as ep from 'element-plus';
|
||||||
|
declare global {
|
||||||
|
declare type ElTagType = '' | 'success' | 'warning' | 'info' | 'danger' | 'default' | 'primary';
|
||||||
|
declare type ElFormInstance = InstanceType<typeof ep.ElForm>;
|
||||||
|
declare type ElTableInstance = InstanceType<typeof ep.ElTable>;
|
||||||
|
declare type ElTreeInstance = InstanceType<typeof ep.ElTree>;
|
||||||
|
declare type ElTreeSelectInstance = InstanceType<typeof ep.ElTreeSelect>;
|
||||||
|
declare type ElSelectInstance = InstanceType<typeof ep.ElSelect>;
|
||||||
|
declare type ElUploadInstance = InstanceType<typeof ep.ElUpload>;
|
||||||
|
declare type ElCardInstance = InstanceType<typeof ep.ElCard>;
|
||||||
|
declare type ElDialogInstance = InstanceType<typeof ep.ElDialog>;
|
||||||
|
declare type ElInputInstance = InstanceType<typeof ep.ElInput>;
|
||||||
|
declare type ElInputNumberInstance = InstanceType<typeof ep.ElInputNumber>;
|
||||||
|
declare type ElRadioInstance = InstanceType<typeof ep.ElRadio>;
|
||||||
|
declare type ElRadioGroupInstance = InstanceType<typeof ep.ElRadioGroup>;
|
||||||
|
declare type ElRadioButtonInstance = InstanceType<typeof ep.ElRadioButton>;
|
||||||
|
declare type ElCheckboxInstance = InstanceType<typeof ep.ElCheckbox>;
|
||||||
|
declare type ElCheckboxGroupInstance = InstanceType<typeof ep.ElCheckboxGroup>;
|
||||||
|
declare type ElSwitchInstance = InstanceType<typeof ep.ElSwitch>;
|
||||||
|
declare type ElDatePickerInstance = InstanceType<typeof ep.ElDatePicker>;
|
||||||
|
declare type ElTimePickerInstance = InstanceType<typeof ep.ElTimePicker>;
|
||||||
|
declare type ElTimeSelectInstance = InstanceType<typeof ep.ElTimeSelect>;
|
||||||
|
declare type ElCascaderInstance = InstanceType<typeof ep.ElCascader>;
|
||||||
|
declare type ElColorPickerInstance = InstanceType<typeof ep.ElColorPicker>;
|
||||||
|
declare type ElRateInstance = InstanceType<typeof ep.ElRate>;
|
||||||
|
declare type ElSliderInstance = InstanceType<typeof ep.ElSlider>;
|
||||||
|
declare type ElUploadInstance = InstanceType<typeof ep.ElUpload>;
|
||||||
|
declare type ElScrollbarInstance = InstanceType<typeof ep.ElScrollbar>;
|
||||||
|
|
||||||
|
declare type TransferKey = ep.TransferKey;
|
||||||
|
declare type CheckboxValueType = ep.CheckboxValueType;
|
||||||
|
declare type ElFormRules = ep.FormRules;
|
||||||
|
declare type DateModelType = ep.DateModelType;
|
||||||
|
declare type UploadFile = typeof ep.UploadFile;
|
||||||
|
}
|
||||||
|
4
src/types/env.d.ts
vendored
4
src/types/env.d.ts
vendored
@ -65,8 +65,10 @@ interface ImportMetaEnv {
|
|||||||
VITE_APP_BASE_URL: string;
|
VITE_APP_BASE_URL: string;
|
||||||
VITE_APP_CONTEXT_PATH: string;
|
VITE_APP_CONTEXT_PATH: string;
|
||||||
VITE_APP_MONITRO_ADMIN: string;
|
VITE_APP_MONITRO_ADMIN: string;
|
||||||
VITE_APP_XXL_JOB_ADMIN: string;
|
VITE_APP_POWERJOB_ADMIN: string;
|
||||||
VITE_APP_ENV: string;
|
VITE_APP_ENV: string;
|
||||||
|
VITE_APP_RSA_PUBLIC_KEY: string;
|
||||||
|
VITE_APP_CLIENT_ID: string;
|
||||||
}
|
}
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
readonly env: ImportMetaEnv;
|
readonly env: ImportMetaEnv;
|
||||||
|
26
src/types/global.d.ts
vendored
26
src/types/global.d.ts
vendored
@ -1,9 +1,15 @@
|
|||||||
import { FormRules } from 'element-plus';
|
import type { ComponentInternalInstance as ComponentInstance, PropType as VuePropType } from 'vue';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
/** vue Instance */
|
||||||
|
declare type ComponentInternalInstance = ComponentInstance;
|
||||||
|
/**vue */
|
||||||
|
declare type PropType<T> = VuePropType<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 界面字段隐藏属性
|
* 界面字段隐藏属性
|
||||||
*/
|
*/
|
||||||
interface FieldOption {
|
declare interface FieldOption {
|
||||||
key: number;
|
key: number;
|
||||||
label: string;
|
label: string;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
@ -12,7 +18,7 @@ declare global {
|
|||||||
/**
|
/**
|
||||||
* 弹窗属性
|
* 弹窗属性
|
||||||
*/
|
*/
|
||||||
interface DialogOption {
|
declare interface DialogOption {
|
||||||
/**
|
/**
|
||||||
* 弹窗标题
|
* 弹窗标题
|
||||||
*/
|
*/
|
||||||
@ -23,7 +29,7 @@ declare global {
|
|||||||
visible: boolean;
|
visible: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UploadOption {
|
declare interface UploadOption {
|
||||||
/** 设置上传的请求头部 */
|
/** 设置上传的请求头部 */
|
||||||
headers: { [key: string]: any };
|
headers: { [key: string]: any };
|
||||||
|
|
||||||
@ -34,7 +40,7 @@ declare global {
|
|||||||
/**
|
/**
|
||||||
* 导入属性
|
* 导入属性
|
||||||
*/
|
*/
|
||||||
interface ImportOption extends UploadOption {
|
declare interface ImportOption extends UploadOption {
|
||||||
/** 是否显示弹出层 */
|
/** 是否显示弹出层 */
|
||||||
open: boolean;
|
open: boolean;
|
||||||
/** 弹出层标题 */
|
/** 弹出层标题 */
|
||||||
@ -48,14 +54,14 @@ declare global {
|
|||||||
/**
|
/**
|
||||||
* 字典数据 数据配置
|
* 字典数据 数据配置
|
||||||
*/
|
*/
|
||||||
interface DictDataOption {
|
declare interface DictDataOption {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
elTagType?: ElTagType;
|
elTagType?: ElTagType;
|
||||||
elTagClass?: string;
|
elTagClass?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BaseEntity {
|
declare interface BaseEntity {
|
||||||
createBy?: any;
|
createBy?: any;
|
||||||
createDept?: any;
|
createDept?: any;
|
||||||
createTime?: string;
|
createTime?: string;
|
||||||
@ -68,15 +74,15 @@ declare global {
|
|||||||
* T : 表单数据
|
* T : 表单数据
|
||||||
* D : 查询参数
|
* D : 查询参数
|
||||||
*/
|
*/
|
||||||
interface PageData<T, D> {
|
declare interface PageData<T, D> {
|
||||||
form: T;
|
form: T;
|
||||||
queryParams: D;
|
queryParams: D;
|
||||||
rules: FormRules;
|
rules: ElFormRules;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 分页查询参数
|
* 分页查询参数
|
||||||
*/
|
*/
|
||||||
interface PageQuery {
|
declare interface PageQuery {
|
||||||
pageNum: number;
|
pageNum: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
}
|
}
|
||||||
|
26
src/types/module.d.ts
vendored
26
src/types/module.d.ts
vendored
@ -1,23 +1,27 @@
|
|||||||
import modal from '@/plugins/modal';
|
import type modal from '@/plugins/modal';
|
||||||
import tab from '@/plugins/tab';
|
import type tab from '@/plugins/tab';
|
||||||
import { useDict } from '@/utils/dict';
|
import type download from '@/plugins/download';
|
||||||
import { addDateRange, handleTree, selectDictLabel, selectDictLabels, parseTime } from '@/utils/ruoyi';
|
import type auth from '@/plugins/auth';
|
||||||
import { getConfigKey, updateConfigByKey } from '@/api/system/config';
|
import type cache from '@/plugins/cache';
|
||||||
import { download as download1 } from '@/utils/request';
|
import type animate from '@/animate';
|
||||||
import download from '@/plugins/download';
|
import type { useDict } from '@/utils/dict';
|
||||||
import animate from '@/animate';
|
import type { addDateRange, handleTree, selectDictLabel, selectDictLabels, parseTime } from '@/utils/ruoyi';
|
||||||
|
import type { getConfigKey, updateConfigByKey } from '@/api/system/config';
|
||||||
|
import type { download as rd } from '@/utils/request';
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface ComponentCustomProperties {
|
interface ComponentCustomProperties {
|
||||||
// 全局方法声明
|
// 全局方法声明
|
||||||
$modal: typeof modal;
|
$modal: typeof modal;
|
||||||
$tab: typeof tab;
|
$tab: typeof tab;
|
||||||
$download: typeof download;
|
$download: typeof download;
|
||||||
|
$auth: typeof auth;
|
||||||
|
$cache: typeof cache;
|
||||||
animate: typeof animate;
|
animate: typeof animate;
|
||||||
|
|
||||||
useDict: typeof useDict;
|
useDict: typeof useDict;
|
||||||
addDateRange: typeof addDateRange;
|
addDateRange: typeof addDateRange;
|
||||||
download: typeof download1;
|
download: typeof rd;
|
||||||
handleTree: typeof handleTree;
|
handleTree: typeof handleTree;
|
||||||
getConfigKey: typeof getConfigKey;
|
getConfigKey: typeof getConfigKey;
|
||||||
updateConfigByKey: typeof updateConfigByKey;
|
updateConfigByKey: typeof updateConfigByKey;
|
||||||
|
8
src/types/router.d.ts
vendored
8
src/types/router.d.ts
vendored
@ -1,7 +1,7 @@
|
|||||||
import { RouteRecordRaw } from 'vue-router';
|
import { RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
declare module 'vue-router' {
|
declare module 'vue-router' {
|
||||||
type RouteOption = {
|
declare type RouteOption = {
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
permissions?: string[];
|
permissions?: string[];
|
||||||
roles?: string[];
|
roles?: string[];
|
||||||
@ -16,15 +16,15 @@ declare module 'vue-router' {
|
|||||||
query?: string;
|
query?: string;
|
||||||
} & RouteRecordRaw;
|
} & RouteRecordRaw;
|
||||||
|
|
||||||
interface _RouteLocationBase {
|
declare interface _RouteLocationBase {
|
||||||
children?: RouteOption[];
|
children?: RouteOption[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RouteLocationOptions {
|
declare interface RouteLocationOptions {
|
||||||
fullPath?: string;
|
fullPath?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TagView extends Partial<_RouteLocationBase> {
|
declare interface TagView extends Partial<_RouteLocationBase> {
|
||||||
title?: string;
|
title?: string;
|
||||||
meta?: {
|
meta?: {
|
||||||
link?: string;
|
link?: string;
|
||||||
|
4
src/types/vform3-builds.d.ts
vendored
Normal file
4
src/types/vform3-builds.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
declare module 'vform3-builds' {
|
||||||
|
const content: any;
|
||||||
|
export = content;
|
||||||
|
}
|
@ -4,6 +4,6 @@ const tokenStorage = useStorage<null | string>(TokenKey, null);
|
|||||||
|
|
||||||
export const getToken = () => tokenStorage.value;
|
export const getToken = () => tokenStorage.value;
|
||||||
|
|
||||||
export const setToken = (token: string) => (tokenStorage.value = token);
|
export const setToken = (access_token: string) => (tokenStorage.value = access_token);
|
||||||
|
|
||||||
export const removeToken = () => (tokenStorage.value = null);
|
export const removeToken = () => (tokenStorage.value = null);
|
||||||
|
45
src/utils/crypto.ts
Normal file
45
src/utils/crypto.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机生成32位的字符串
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
const generateRandomString = () => {
|
||||||
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
let result = '';
|
||||||
|
const charactersLength = characters.length;
|
||||||
|
for (let i = 0; i < 32; i++) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机生成aes 密钥
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const generateAesKey = () => {
|
||||||
|
return CryptoJS.enc.Utf8.parse(generateRandomString());
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密base64
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const encryptBase64 = (str: CryptoJS.lib.WordArray) => {
|
||||||
|
return CryptoJS.enc.Base64.stringify(str);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用密钥对数据进行加密
|
||||||
|
* @param message
|
||||||
|
* @param aesKey
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const encryptWithAes = (message: string, aesKey: CryptoJS.lib.WordArray) => {
|
||||||
|
const encrypted = CryptoJS.AES.encrypt(message, aesKey, {
|
||||||
|
mode: CryptoJS.mode.ECB,
|
||||||
|
padding: CryptoJS.pad.Pkcs7
|
||||||
|
});
|
||||||
|
return encrypted.toString();
|
||||||
|
};
|
@ -1,18 +1,10 @@
|
|||||||
import JSEncrypt from 'jsencrypt';
|
import JSEncrypt from 'jsencrypt';
|
||||||
// 密钥对生成 http://web.chacuo.net/netrsakeypair
|
// 密钥对生成 http://web.chacuo.net/netrsakeypair
|
||||||
|
|
||||||
const publicKey =
|
const publicKey = import.meta.env.VITE_APP_RSA_PUBLIC_KEY;
|
||||||
'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' + 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==';
|
|
||||||
|
|
||||||
const privateKey =
|
// 前端不建议存放私钥 不建议解密数据 因为都是透明的意义不大
|
||||||
'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
|
const privateKey = '**********';
|
||||||
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
|
|
||||||
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
|
|
||||||
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
|
|
||||||
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
|
|
||||||
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
|
|
||||||
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
|
|
||||||
'UP8iWi1Qw0Y=';
|
|
||||||
|
|
||||||
// 加密
|
// 加密
|
||||||
export const encrypt = (txt: string) => {
|
export const encrypt = (txt: string) => {
|
||||||
|
25
src/utils/propTypes.ts
Normal file
25
src/utils/propTypes.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { CSSProperties } from 'vue';
|
||||||
|
import VueTypes, { createTypes, toValidableType, VueTypeValidableDef, VueTypesInterface } from 'vue-types';
|
||||||
|
|
||||||
|
type PropTypes = VueTypesInterface & {
|
||||||
|
readonly style: VueTypeValidableDef<CSSProperties>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const propTypes = createTypes({
|
||||||
|
func: undefined,
|
||||||
|
bool: undefined,
|
||||||
|
string: undefined,
|
||||||
|
number: undefined,
|
||||||
|
object: undefined,
|
||||||
|
integer: undefined
|
||||||
|
}) as PropTypes;
|
||||||
|
|
||||||
|
export default class ProjectTypes extends VueTypes {
|
||||||
|
static get style() {
|
||||||
|
return toValidableType('style', {
|
||||||
|
type: [String, Object],
|
||||||
|
default: undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export { propTypes };
|
@ -8,12 +8,19 @@ import { errorCode } from '@/utils/errorCode';
|
|||||||
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
|
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
|
||||||
import FileSaver from 'file-saver';
|
import FileSaver from 'file-saver';
|
||||||
import { getLanguage } from '@/lang';
|
import { getLanguage } from '@/lang';
|
||||||
|
import { encryptBase64, encryptWithAes, generateAesKey } from '@/utils/crypto';
|
||||||
|
import { encrypt } from '@/utils/jsencrypt';
|
||||||
|
|
||||||
let downloadLoadingInstance: LoadingInstance;
|
let downloadLoadingInstance: LoadingInstance;
|
||||||
// 是否显示重新登录
|
// 是否显示重新登录
|
||||||
export const isRelogin = { show: false };
|
export const isRelogin = { show: false };
|
||||||
|
export const globalHeaders = {
|
||||||
|
Authorization: "Bearer " + getToken(),
|
||||||
|
clientid: import.meta.env.VITE_APP_CLIENT_ID
|
||||||
|
}
|
||||||
|
|
||||||
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
|
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
|
||||||
|
axios.defaults.headers['clientid'] = import.meta.env.VITE_APP_CLIENT_ID;
|
||||||
// 创建 axios 实例
|
// 创建 axios 实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||||
@ -29,6 +36,8 @@ service.interceptors.request.use(
|
|||||||
const isToken = (config.headers || {}).isToken === false;
|
const isToken = (config.headers || {}).isToken === false;
|
||||||
// 是否需要防止数据重复提交
|
// 是否需要防止数据重复提交
|
||||||
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
|
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
|
||||||
|
// 是否需要加密
|
||||||
|
const isEncrypt = (config.headers || {}).isEncrypt === 'true';
|
||||||
if (getToken() && !isToken) {
|
if (getToken() && !isToken) {
|
||||||
config.headers['Authorization'] = 'Bearer ' + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
|
config.headers['Authorization'] = 'Bearer ' + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||||
}
|
}
|
||||||
@ -63,6 +72,13 @@ service.interceptors.request.use(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 当开启参数加密
|
||||||
|
if (isEncrypt && (config.method === 'post' || config.method === 'put')) {
|
||||||
|
// 生成一个 AES 密钥
|
||||||
|
const aesKey = generateAesKey();
|
||||||
|
config.headers['encrypt-key'] = encrypt(encryptBase64(aesKey));
|
||||||
|
config.data = typeof config.data === 'object' ? encryptWithAes(JSON.stringify(config.data), aesKey) : encryptWithAes(config.data, aesKey);
|
||||||
|
}
|
||||||
// FormData数据去请求头Content-Type
|
// FormData数据去请求头Content-Type
|
||||||
if (config.data instanceof FormData) {
|
if (config.data instanceof FormData) {
|
||||||
delete config.headers['Content-Type'];
|
delete config.headers['Content-Type'];
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="部门id" prop="deptId">
|
<el-form-item label="部门id" prop="deptId">
|
||||||
<el-input v-model="queryParams.deptId" placeholder="请输入部门id" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.deptId" placeholder="请输入部门id" clearable @keyup.enter="handleQuery" />
|
||||||
@ -23,10 +24,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -36,7 +38,9 @@
|
|||||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['demo:demo:edit']">修改</el-button>
|
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['demo:demo:edit']">修改</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['demo:demo:remove']">删除</el-button>
|
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['demo:demo:remove']"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['demo:demo:export']">导出</el-button>
|
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['demo:demo:export']">导出</el-button>
|
||||||
@ -65,13 +69,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
v-show="total>0"
|
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改测试单对话框 -->
|
<!-- 添加或修改测试单对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
@ -105,8 +103,6 @@
|
|||||||
<script setup name="Demo" lang="ts">
|
<script setup name="Demo" lang="ts">
|
||||||
import { listDemo, getDemo, delDemo, addDemo, updateDemo } from '@/api/demo/demo';
|
import { listDemo, getDemo, delDemo, addDemo, updateDemo } from '@/api/demo/demo';
|
||||||
import { DemoVO, DemoQuery, DemoForm } from '@/api/demo/demo/types';
|
import { DemoVO, DemoQuery, DemoForm } from '@/api/demo/demo/types';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { ElForm } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
@ -119,8 +115,8 @@ const single = ref(true);
|
|||||||
const multiple = ref(true);
|
const multiple = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const demoFormRef = ref(ElForm);
|
const demoFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -136,7 +132,7 @@ const initFormData: DemoForm = {
|
|||||||
value: undefined,
|
value: undefined,
|
||||||
}
|
}
|
||||||
const data = reactive<PageData<DemoForm, DemoQuery>>({
|
const data = reactive<PageData<DemoForm, DemoQuery>>({
|
||||||
form: {...initFormData},
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -187,8 +183,8 @@ const cancel = () => {
|
|||||||
|
|
||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = {...initFormData};
|
form.value = { ...initFormData };
|
||||||
demoFormRef.value.resetFields();
|
demoFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
@ -199,7 +195,7 @@ const handleQuery = () => {
|
|||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,30 +208,24 @@ const handleSelectionChange = (selection: DemoVO[]) => {
|
|||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "添加测试单";
|
dialog.title = "添加测试单";
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: DemoVO) => {
|
const handleUpdate = async (row?: DemoVO) => {
|
||||||
loading.value = true
|
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "修改测试单";
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
reset();
|
||||||
const _id = row?.id || ids.value[0]
|
const _id = row?.id || ids.value[0]
|
||||||
const res = await getDemo(_id);
|
const res = await getDemo(_id);
|
||||||
loading.value = false;
|
|
||||||
Object.assign(form.value, res.data);
|
Object.assign(form.value, res.data);
|
||||||
});
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改测试单";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
demoFormRef.value.validate(async (valid: boolean) => {
|
demoFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
if (form.value.id) {
|
if (form.value.id) {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="树节点名" prop="treeName">
|
<el-form-item label="树节点名" prop="treeName">
|
||||||
<el-input v-model="queryParams.treeName" placeholder="请输入树节点名" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.treeName" placeholder="请输入树节点名" clearable @keyup.enter="handleQuery" />
|
||||||
@ -11,10 +12,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -89,8 +91,6 @@
|
|||||||
<script setup name="Tree" lang="ts">
|
<script setup name="Tree" lang="ts">
|
||||||
import { listTree, getTree, delTree, addTree, updateTree } from "@/api/demo/tree";
|
import { listTree, getTree, delTree, addTree, updateTree } from "@/api/demo/tree";
|
||||||
import { TreeVO, TreeQuery, TreeForm } from '@/api/demo/tree/types';
|
import { TreeVO, TreeQuery, TreeForm } from '@/api/demo/tree/types';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { ElForm, ElTable } from 'element-plus';
|
|
||||||
|
|
||||||
|
|
||||||
type TreeOption = {
|
type TreeOption = {
|
||||||
@ -109,9 +109,9 @@ const showSearch = ref(true);
|
|||||||
const isExpandAll = ref(true);
|
const isExpandAll = ref(true);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const treeFormRef = ref(ElForm);
|
const treeFormRef = ref<ElFormInstance>();
|
||||||
const treeTableRef = ref(ElTable)
|
const treeTableRef = ref<ElTableInstance>()
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -185,7 +185,7 @@ const cancel = () => {
|
|||||||
// 表单重置
|
// 表单重置
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = {...initFormData}
|
form.value = {...initFormData}
|
||||||
treeFormRef.value.resetFields();
|
treeFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
@ -195,23 +195,21 @@ const handleQuery = () => {
|
|||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = (row?: TreeVO) => {
|
const handleAdd = (row?: TreeVO) => {
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "添加测试树";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
reset();
|
||||||
getTreeselect();
|
getTreeselect();
|
||||||
if (row != null && row.id) {
|
if (row && row.id) {
|
||||||
form.value.parentId = row.id;
|
form.value.parentId = row.id;
|
||||||
} else {
|
} else {
|
||||||
form.value.parentId = 0;
|
form.value.parentId = 0;
|
||||||
}
|
}
|
||||||
});
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加测试树";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 展开/折叠操作 */
|
/** 展开/折叠操作 */
|
||||||
@ -223,31 +221,27 @@ const handleToggleExpandAll = () => {
|
|||||||
/** 展开/折叠操作 */
|
/** 展开/折叠操作 */
|
||||||
const toggleExpandAll = (data: TreeVO[], status: boolean) => {
|
const toggleExpandAll = (data: TreeVO[], status: boolean) => {
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
treeTableRef.value.toggleRowExpansion(item, status)
|
treeTableRef.value?.toggleRowExpansion(item, status)
|
||||||
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
|
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row: TreeVO) => {
|
const handleUpdate = async (row: TreeVO) => {
|
||||||
loading.value = true;
|
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "修改测试树";
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
reset();
|
||||||
await getTreeselect();
|
await getTreeselect();
|
||||||
if (row != null) {
|
if (row) {
|
||||||
form.value.parentId = row.id;
|
form.value.parentId = row.id;
|
||||||
}
|
}
|
||||||
const res = await getTree(row.id);
|
const res = await getTree(row.id);
|
||||||
loading.value = false;
|
|
||||||
Object.assign(form.value, res.data);
|
Object.assign(form.value, res.data);
|
||||||
});
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改测试树";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
treeFormRef.value.validate(async (valid: boolean) => {
|
treeFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
if (form.value.id) {
|
if (form.value.id) {
|
||||||
@ -257,7 +251,7 @@ const submitForm = () => {
|
|||||||
}
|
}
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import errImage from '@/assets/401_images/401.gif';
|
import errImage from '@/assets/401_images/401.gif';
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
|
|
||||||
let { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
let { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
* 分布式锁 Lock4j 注解锁、工具锁 多种多样<br />
|
* 分布式锁 Lock4j 注解锁、工具锁 多种多样<br />
|
||||||
* 分布式幂等 Lock4j 基于分布式锁实现<br />
|
* 分布式幂等 Lock4j 基于分布式锁实现<br />
|
||||||
* 分布式链路追踪 SkyWalking 支持链路追踪、网格分析、度量聚合、可视化<br />
|
* 分布式链路追踪 SkyWalking 支持链路追踪、网格分析、度量聚合、可视化<br />
|
||||||
* 分布式任务调度 Xxl-Job 高性能 高可靠 易扩展<br />
|
* 分布式任务调度 PowerJob 高性能 高可靠 易扩展<br />
|
||||||
* 文件存储 Minio 本地存储<br />
|
* 文件存储 Minio 本地存储<br />
|
||||||
* 文件存储 七牛、阿里、腾讯 云存储<br />
|
* 文件存储 七牛、阿里、腾讯 云存储<br />
|
||||||
* 监控框架 SpringBoot-Admin 全方位服务监控<br />
|
* 监控框架 SpringBoot-Admin 全方位服务监控<br />
|
||||||
@ -33,14 +33,14 @@
|
|||||||
* 部署方式 Docker 容器编排 一键部署业务集群<br />
|
* 部署方式 Docker 容器编排 一键部署业务集群<br />
|
||||||
* 国际化 SpringMessage Spring标准国际化方案<br />
|
* 国际化 SpringMessage Spring标准国际化方案<br />
|
||||||
</p>
|
</p>
|
||||||
<p><b>当前版本:</b> <span>v5.0.0</span></p>
|
<p><b>当前版本:</b> <span>v5.1.0</span></p>
|
||||||
<p>
|
<p>
|
||||||
<el-tag type="danger">¥免费开源</el-tag>
|
<el-tag type="danger">¥免费开源</el-tag>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">访问码云</el-button>
|
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">访问码云</el-button>
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">访问GitHub</el-button>
|
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">访问GitHub</el-button>
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/changlog')"
|
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-vue-plus/changlog')"
|
||||||
>更新日志</el-button
|
>更新日志</el-button
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
@ -78,14 +78,14 @@
|
|||||||
* 分布式监控 Prometheus、Grafana 全方位性能监控<br />
|
* 分布式监控 Prometheus、Grafana 全方位性能监控<br />
|
||||||
* 其余与 Vue 版本一致<br />
|
* 其余与 Vue 版本一致<br />
|
||||||
</p>
|
</p>
|
||||||
<p><b>当前版本:</b> <span>v2.0.0</span></p>
|
<p><b>当前版本:</b> <span>v2.1.0</span></p>
|
||||||
<p>
|
<p>
|
||||||
<el-tag type="danger">¥免费开源</el-tag>
|
<el-tag type="danger">¥免费开源</el-tag>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">访问码云</el-button>
|
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">访问码云</el-button>
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">访问GitHub</el-button>
|
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">访问GitHub</el-button>
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://javalionli.gitee.io/plus-doc/#/ruoyi-cloud-plus/changlog')"
|
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-cloud-plus/changlog')"
|
||||||
>更新日志</el-button
|
>更新日志</el-button
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<h3 class="title">RuoYi-Vue-Plus多租户管理系统</h3>
|
<h3 class="title">RuoYi-Vue-Plus多租户管理系统</h3>
|
||||||
<el-form-item prop="tenantId" v-if="tenantEnabled">
|
<el-form-item prop="tenantId" v-if="tenantEnabled">
|
||||||
<el-select v-model="loginForm.tenantId" filterable placeholder="请选择/输入公司名称" style="width: 100%">
|
<el-select v-model="loginForm.tenantId" filterable placeholder="请选择/输入公司名称" style="width: 100%">
|
||||||
<el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"> </el-option>
|
<el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option>
|
||||||
<template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
|
<template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -27,6 +27,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
|
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
|
||||||
|
<el-form-item style="float: right;">
|
||||||
|
<el-button circle title="微信登录" @click="doSocialLogin('wechat')">
|
||||||
|
<svg-icon icon-class="wechat" />
|
||||||
|
</el-button>
|
||||||
|
<el-button circle title="MaxKey登录" @click="doSocialLogin('maxkey')">
|
||||||
|
<svg-icon icon-class="maxkey" />
|
||||||
|
</el-button>
|
||||||
|
<el-button circle title="Gitee登录" @click="doSocialLogin('gitee')">
|
||||||
|
<svg-icon icon-class="gitee" />
|
||||||
|
</el-button>
|
||||||
|
<el-button circle title="Github登录" @click="doSocialLogin('github')">
|
||||||
|
<svg-icon icon-class="github" />
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item style="width:100%;">
|
<el-form-item style="width:100%;">
|
||||||
<el-button :loading="loading" size="large" type="primary" style="width:100%;" @click.prevent="handleLogin">
|
<el-button :loading="loading" size="large" type="primary" style="width:100%;" @click.prevent="handleLogin">
|
||||||
<span v-if="!loading">登 录</span>
|
<span v-if="!loading">登 录</span>
|
||||||
@ -46,26 +60,26 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getCodeImg, getTenantList } from '@/api/login';
|
import { getCodeImg, getTenantList } from '@/api/login';
|
||||||
|
import { authBinding } from '@/api/system/social/auth';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import { encrypt, decrypt } from '@/utils/jsencrypt';
|
|
||||||
import { useUserStore } from '@/store/modules/user';
|
import { useUserStore } from '@/store/modules/user';
|
||||||
import { LoginData, TenantVO } from '@/api/types';
|
import { LoginData, TenantVO } from '@/api/types';
|
||||||
import { FormRules } from 'element-plus';
|
|
||||||
import { to } from 'await-to-js';
|
import { to } from 'await-to-js';
|
||||||
|
import { HttpStatus } from "@/enums/RespEnum";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const loginForm = ref<LoginData>({
|
const loginForm = ref<LoginData>({
|
||||||
tenantId: "000000",
|
tenantId: '000000',
|
||||||
username: 'admin',
|
username: 'admin',
|
||||||
password: 'admin123',
|
password: 'admin123',
|
||||||
rememberMe: false,
|
rememberMe: false,
|
||||||
code: '',
|
code: '',
|
||||||
uuid: ''
|
uuid: ''
|
||||||
});
|
} as LoginData);
|
||||||
|
|
||||||
const loginRules: FormRules = {
|
const loginRules: ElFormRules = {
|
||||||
tenantId: [{ required: true, trigger: "blur", message: "请输入您的租户编号" }],
|
tenantId: [{ required: true, trigger: "blur", message: "请输入您的租户编号" }],
|
||||||
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
|
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
|
||||||
password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
|
password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
|
||||||
@ -83,19 +97,19 @@ const tenantEnabled = ref(true);
|
|||||||
// 注册开关
|
// 注册开关
|
||||||
const register = ref(false);
|
const register = ref(false);
|
||||||
const redirect = ref(undefined);
|
const redirect = ref(undefined);
|
||||||
const loginRef = ref(ElForm);
|
const loginRef = ref<ElFormInstance>();
|
||||||
// 租户列表
|
// 租户列表
|
||||||
const tenantList = ref<TenantVO[]>([]);
|
const tenantList = ref<TenantVO[]>([]);
|
||||||
|
|
||||||
const handleLogin = () => {
|
const handleLogin = () => {
|
||||||
loginRef.value.validate(async (valid:boolean, fields: any) => {
|
loginRef.value?.validate(async (valid: boolean, fields: any) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
||||||
if (loginForm.value.rememberMe) {
|
if (loginForm.value.rememberMe) {
|
||||||
Cookies.set("tenantId", loginForm.value.tenantId, { expires: 30 });
|
Cookies.set("tenantId", String(loginForm.value.tenantId), { expires: 30 });
|
||||||
Cookies.set('username', loginForm.value.username, { expires: 30 });
|
Cookies.set('username', String(loginForm.value.username), { expires: 30 });
|
||||||
Cookies.set('password', String(encrypt(loginForm.value.password)), { expires: 30 });
|
Cookies.set('password', String(loginForm.value.password), { expires: 30 });
|
||||||
Cookies.set('rememberMe', String(loginForm.value.rememberMe), { expires: 30 });
|
Cookies.set('rememberMe', String(loginForm.value.rememberMe), { expires: 30 });
|
||||||
} else {
|
} else {
|
||||||
// 否则移除
|
// 否则移除
|
||||||
@ -105,7 +119,6 @@ const handleLogin = () => {
|
|||||||
Cookies.remove('rememberMe');
|
Cookies.remove('rememberMe');
|
||||||
}
|
}
|
||||||
// 调用action的登录方法
|
// 调用action的登录方法
|
||||||
// prittier-ignore
|
|
||||||
const [err] = await to(userStore.login(loginForm.value));
|
const [err] = await to(userStore.login(loginForm.value));
|
||||||
if (!err) {
|
if (!err) {
|
||||||
await router.push({ path: redirect.value || '/' });
|
await router.push({ path: redirect.value || '/' });
|
||||||
@ -141,11 +154,11 @@ const getCookie = () => {
|
|||||||
const password = Cookies.get('password');
|
const password = Cookies.get('password');
|
||||||
const rememberMe = Cookies.get('rememberMe');
|
const rememberMe = Cookies.get('rememberMe');
|
||||||
loginForm.value = {
|
loginForm.value = {
|
||||||
tenantId: tenantId === undefined ? loginForm.value.tenantId : tenantId,
|
tenantId: tenantId === undefined ? String(loginForm.value.tenantId) : tenantId,
|
||||||
username: username === undefined ? loginForm.value.username : username,
|
username: username === undefined ? String(loginForm.value.username) : username,
|
||||||
password: password === undefined ? loginForm.value.password : (decrypt(password) as string),
|
password: password === undefined ? String(loginForm.value.password) : String(password),
|
||||||
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
|
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
|
||||||
};
|
} as LoginData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -163,6 +176,28 @@ const initTenantList = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//检测租户选择框的变化
|
||||||
|
watch(() => loginForm.value.tenantId, () => {
|
||||||
|
Cookies.set("tenantId", String(loginForm.value.tenantId), { expires: 30 })
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
const doSocialLogin = (type: string) => {
|
||||||
|
authBinding(type).then((res: any) => {
|
||||||
|
if (res.code === HttpStatus.SUCCESS) {
|
||||||
|
// 获取授权地址跳转
|
||||||
|
window.location.href = res.data;
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getCode();
|
getCode();
|
||||||
initTenantList();
|
initTenantList();
|
||||||
@ -179,6 +214,7 @@ onMounted(() => {
|
|||||||
background-image: url("../assets/images/login-background.jpg");
|
background-image: url("../assets/images/login-background.jpg");
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin: 0px auto 30px auto;
|
margin: 0px auto 30px auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -190,32 +226,39 @@ onMounted(() => {
|
|||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
padding: 25px 25px 5px 25px;
|
padding: 25px 25px 5px 25px;
|
||||||
|
|
||||||
.el-input {
|
.el-input {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-icon {
|
.input-icon {
|
||||||
height: 39px;
|
height: 39px;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-tip {
|
.login-tip {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #bfbfbf;
|
color: #bfbfbf;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-code {
|
.login-code {
|
||||||
width: 33%;
|
width: 33%;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-login-footer {
|
.el-login-footer {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
@ -224,10 +267,11 @@ onMounted(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-family: Arial,serif;
|
font-family: Arial, serif;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-code-img {
|
.login-code-img {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
|
12
src/views/monitor/cache/index.vue
vendored
12
src/views/monitor/cache/index.vue
vendored
@ -2,7 +2,7 @@
|
|||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24" class="card-box">
|
<el-col :span="24" class="card-box">
|
||||||
<el-card>
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<Monitor style="width: 1em; height: 1em; vertical-align: middle;" />
|
<Monitor style="width: 1em; height: 1em; vertical-align: middle;" />
|
||||||
<span style="vertical-align: middle;">基本信息</span>
|
<span style="vertical-align: middle;">基本信息</span>
|
||||||
@ -98,7 +98,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="12" class="card-box">
|
<el-col :span="12" class="card-box">
|
||||||
<el-card>
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<PieChart style="width: 1em; height: 1em; vertical-align: middle;" />
|
<PieChart style="width: 1em; height: 1em; vertical-align: middle;" />
|
||||||
<span style="vertical-align: middle;">命令统计</span>
|
<span style="vertical-align: middle;">命令统计</span>
|
||||||
@ -110,7 +110,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="12" class="card-box">
|
<el-col :span="12" class="card-box">
|
||||||
<el-card>
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<Odometer style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">内存信息</span>
|
<Odometer style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">内存信息</span>
|
||||||
</template>
|
</template>
|
||||||
@ -126,7 +126,6 @@
|
|||||||
<script setup name="Cache" lang="ts">
|
<script setup name="Cache" lang="ts">
|
||||||
import { getCache } from '@/api/monitor/cache';
|
import { getCache } from '@/api/monitor/cache';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
|
|
||||||
const cache = ref<any>({});
|
const cache = ref<any>({});
|
||||||
const commandstats = ref();
|
const commandstats = ref();
|
||||||
@ -157,7 +156,6 @@ const getList = async () => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
const usedmemoryInstance = echarts.init(usedmemory.value, "macarons");
|
const usedmemoryInstance = echarts.init(usedmemory.value, "macarons");
|
||||||
usedmemoryInstance.setOption({
|
usedmemoryInstance.setOption({
|
||||||
tooltip: {
|
tooltip: {
|
||||||
@ -181,6 +179,10 @@ const getList = async () => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
window.addEventListener("resize",()=>{
|
||||||
|
commandstatsIntance.resize()
|
||||||
|
usedmemoryInstance.resize()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="登录地址" prop="ipaddr">
|
<el-form-item label="登录地址" prop="ipaddr">
|
||||||
<el-input v-model="queryParams.ipaddr" placeholder="请输入登录地址" clearable style="width: 240px;" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.ipaddr" placeholder="请输入登录地址" clearable style="width: 240px;" @keyup.enter="handleQuery" />
|
||||||
@ -30,10 +31,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -98,9 +100,7 @@
|
|||||||
|
|
||||||
<script setup name="Logininfor" lang="ts">
|
<script setup name="Logininfor" lang="ts">
|
||||||
import { list, delLoginInfo, cleanLoginInfo, unlockLoginInfo } from "@/api/monitor/loginInfo";
|
import { list, delLoginInfo, cleanLoginInfo, unlockLoginInfo } from "@/api/monitor/loginInfo";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { LoginInfoQuery, LoginInfoVO } from "@/api/monitor/loginInfo/types";
|
import { LoginInfoQuery, LoginInfoVO } from "@/api/monitor/loginInfo/types";
|
||||||
import { DateModelType } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_common_status } = toRefs<any>(proxy?.useDict("sys_common_status"));
|
const { sys_common_status } = toRefs<any>(proxy?.useDict("sys_common_status"));
|
||||||
@ -116,8 +116,8 @@ const total = ref(0);
|
|||||||
const dateRange = ref<[DateModelType,DateModelType]>(['', '']);
|
const dateRange = ref<[DateModelType,DateModelType]>(['', '']);
|
||||||
const defaultSort = ref<any>({ prop: "loginTime", order: "descending" });
|
const defaultSort = ref<any>({ prop: "loginTime", order: "descending" });
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const loginInfoTableRef = ref(ElTable);
|
const loginInfoTableRef = ref<ElTableInstance>();
|
||||||
// 查询参数
|
// 查询参数
|
||||||
const queryParams = ref<LoginInfoQuery>({
|
const queryParams = ref<LoginInfoQuery>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@ -145,9 +145,9 @@ const handleQuery = () => {
|
|||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
dateRange.value = ['', ''];
|
dateRange.value = ['', ''];
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
loginInfoTableRef.value.sort(defaultSort.value.prop, defaultSort.value.order);
|
loginInfoTableRef.value?.sort(defaultSort.value.prop, defaultSort.value.order);
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
const handleSelectionChange = (selection: LoginInfoVO[]) => {
|
const handleSelectionChange = (selection: LoginInfoVO[]) => {
|
||||||
@ -167,14 +167,14 @@ const handleDelete = async (row?: LoginInfoVO) => {
|
|||||||
const infoIds = row?.infoId || ids.value;
|
const infoIds = row?.infoId || ids.value;
|
||||||
await proxy?.$modal.confirm('是否确认删除访问编号为"' + infoIds + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除访问编号为"' + infoIds + '"的数据项?');
|
||||||
await delLoginInfo(infoIds);
|
await delLoginInfo(infoIds);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
/** 清空按钮操作 */
|
/** 清空按钮操作 */
|
||||||
const handleClean = async () => {
|
const handleClean = async () => {
|
||||||
await proxy?.$modal.confirm("是否确认清空所有登录日志数据项?");
|
await proxy?.$modal.confirm("是否确认清空所有登录日志数据项?");
|
||||||
await cleanLoginInfo();
|
await cleanLoginInfo();
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("清空成功");
|
proxy?.$modal.msgSuccess("清空成功");
|
||||||
}
|
}
|
||||||
/** 解锁按钮操作 */
|
/** 解锁按钮操作 */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<div class="search">
|
<div class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true">
|
||||||
<el-form-item label="登录地址" prop="ipaddr">
|
<el-form-item label="登录地址" prop="ipaddr">
|
||||||
<el-input v-model="queryParams.ipaddr" placeholder="请输入登录地址" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.ipaddr" placeholder="请输入登录地址" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
||||||
@ -13,8 +14,9 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel">
|
<el-card shadow="hover">
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:data="onlineList.slice((queryParams.pageNum - 1) * queryParams.pageSize, queryParams.pageNum * queryParams.pageSize)"
|
:data="onlineList.slice((queryParams.pageNum - 1) * queryParams.pageSize, queryParams.pageNum * queryParams.pageSize)"
|
||||||
@ -48,13 +50,12 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" />
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" />
|
||||||
</div>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Online" lang="ts">
|
<script setup name="Online" lang="ts">
|
||||||
import { forceLogout, list as initData } from "@/api/monitor/online";
|
import { forceLogout, list as initData } from "@/api/monitor/online";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { OnlineQuery, OnlineVO } from "@/api/monitor/online/types";
|
import { OnlineQuery, OnlineVO } from "@/api/monitor/online/types";
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@ -63,7 +64,7 @@ const onlineList = ref<OnlineVO[]>([]);
|
|||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const queryParams = ref<OnlineQuery>({
|
const queryParams = ref<OnlineQuery>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@ -87,14 +88,14 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 强退按钮操作 */
|
/** 强退按钮操作 */
|
||||||
const handleForceLogout = async (row: OnlineVO) => {
|
const handleForceLogout = async (row: OnlineVO) => {
|
||||||
await proxy?.$modal.confirm('是否确认强退名称为"' + row.userName + '"的用户?');
|
await proxy?.$modal.confirm('是否确认强退名称为"' + row.userName + '"的用户?');
|
||||||
await forceLogout(row.tokenId);
|
await forceLogout(row.tokenId);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="系统模块" prop="title">
|
<el-form-item label="系统模块" prop="title">
|
||||||
<el-input v-model="queryParams.title" placeholder="请输入系统模块" clearable style="width: 240px;" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.title" placeholder="请输入系统模块" clearable style="width: 240px;" @keyup.enter="handleQuery" />
|
||||||
@ -35,10 +36,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -132,7 +134,7 @@
|
|||||||
<el-form-item label="操作方法:">{{ form.method }}</el-form-item>
|
<el-form-item label="操作方法:">{{ form.method }}</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="请求参数:">{{form.operParam}}</el-form-item>
|
<el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
|
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
|
||||||
@ -165,12 +167,10 @@
|
|||||||
|
|
||||||
<script setup name="Operlog" lang="ts">
|
<script setup name="Operlog" lang="ts">
|
||||||
import { list, delOperlog, cleanOperlog } from '@/api/monitor/operlog';
|
import { list, delOperlog, cleanOperlog } from '@/api/monitor/operlog';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { OperLogForm, OperLogQuery, OperLogVO } from '@/api/monitor/operlog/types';
|
import { OperLogForm, OperLogQuery, OperLogVO } from '@/api/monitor/operlog/types';
|
||||||
import { DateModelType } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_oper_type, sys_common_status } = toRefs<any>(proxy?.useDict("sys_oper_type","sys_common_status"));
|
const { sys_oper_type, sys_common_status } = toRefs<any>(proxy?.useDict("sys_oper_type", "sys_common_status"));
|
||||||
|
|
||||||
const operlogList = ref<OperLogVO[]>([]);
|
const operlogList = ref<OperLogVO[]>([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@ -181,8 +181,8 @@ const total = ref(0);
|
|||||||
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
||||||
const defaultSort = ref<any>({ prop: "operTime", order: "descending" });
|
const defaultSort = ref<any>({ prop: "operTime", order: "descending" });
|
||||||
|
|
||||||
const operLogTableRef = ref(ElTable);
|
const operLogTableRef = ref<ElTableInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -247,9 +247,9 @@ const handleQuery = () => {
|
|||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
dateRange.value = ['', ''];
|
dateRange.value = ['', ''];
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
operLogTableRef.value.sort(defaultSort.value.prop, defaultSort.value.order);
|
operLogTableRef.value?.sort(defaultSort.value.prop, defaultSort.value.order);
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
const handleSelectionChange = (selection: OperLogVO[]) => {
|
const handleSelectionChange = (selection: OperLogVO[]) => {
|
||||||
@ -272,7 +272,7 @@ const handleDelete = async (row?: OperLogVO) => {
|
|||||||
const operIds = row?.operId || ids.value;
|
const operIds = row?.operId || ids.value;
|
||||||
await proxy?.$modal.confirm('是否确认删除日志编号为"' + operIds + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除日志编号为"' + operIds + '"的数据项?');
|
||||||
await delOperlog(operIds);
|
await delOperlog(operIds);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ const handleDelete = async (row?: OperLogVO) => {
|
|||||||
const handleClean = async () => {
|
const handleClean = async () => {
|
||||||
await proxy?.$modal.confirm("是否确认清空所有操作日志数据项?");
|
await proxy?.$modal.confirm("是否确认清空所有操作日志数据项?");
|
||||||
await cleanOperlog();
|
await cleanOperlog();
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("清空成功");
|
proxy?.$modal.msgSuccess("清空成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const url = ref(import.meta.env.VITE_APP_XXL_JOB_ADMIN);
|
const url = ref(import.meta.env.VITE_APP_POWERJOB_ADMIN);
|
||||||
</script>
|
</script>
|
@ -58,7 +58,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getCodeImg, register, getTenantList } from '@/api/login';
|
import { getCodeImg, register, getTenantList } from '@/api/login';
|
||||||
import { RegisterForm, TenantVO } from '@/api/types';
|
import { RegisterForm, TenantVO } from '@/api/types';
|
||||||
import { FormRules } from 'element-plus';
|
|
||||||
import { to } from 'await-to-js';
|
import { to } from 'await-to-js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -85,7 +84,7 @@ const equalToPassword = (rule: any, value: string, callback: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const registerRules: FormRules = {
|
const registerRules: ElFormRules = {
|
||||||
tenantId: [
|
tenantId: [
|
||||||
{ required: true, trigger: "blur", message: "请输入您的租户编号" }
|
{ required: true, trigger: "blur", message: "请输入您的租户编号" }
|
||||||
],
|
],
|
||||||
|
328
src/views/system/client/index.vue
Normal file
328
src/views/system/client/index.vue
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div class="search" v-show="showSearch">
|
||||||
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="100px">
|
||||||
|
<el-form-item label="客户端key" prop="clientKey">
|
||||||
|
<el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="客户端秘钥" prop="clientSecret">
|
||||||
|
<el-input v-model="queryParams.clientSecret" placeholder="请输入客户端秘钥" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-select v-model="queryParams.status" placeholder="状态" clearable>
|
||||||
|
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:client:add']">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:client:edit']">
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:client:remove']">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:client:export']">导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="clientList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="id" align="center" prop="id" v-if="true" />
|
||||||
|
<el-table-column label="客户端id" align="center" prop="clientId" />
|
||||||
|
<el-table-column label="客户端key" align="center" prop="clientKey" />
|
||||||
|
<el-table-column label="客户端秘钥" align="center" prop="clientSecret" />
|
||||||
|
<el-table-column label="授权类型" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<div>
|
||||||
|
<template v-for="(type, index) in scope.row.grantTypeList" :key="index">
|
||||||
|
<dict-tag class="el-check-tag" :options="sys_grant_type" :value="type" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="设备类型" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<dict-tag :options="sys_device_type" :value="scope.row.deviceType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="Token活跃超时时间" align="center" prop="activeTimeout" />
|
||||||
|
<el-table-column label="Token固定超时时间" align="center" prop="timeout" />
|
||||||
|
<el-table-column label="状态" align="center" key="status">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tooltip content="修改" placement="top">
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:client:edit']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="删除" placement="top">
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:client:remove']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total>0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改客户端管理对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="clientFormRef" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-form-item label="客户端key" prop="clientKey">
|
||||||
|
<el-input v-model="form.clientKey" :disabled="form.id != null" placeholder="请输入客户端key" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="客户端秘钥" prop="clientSecret">
|
||||||
|
<el-input v-model="form.clientSecret" :disabled="form.id != null" placeholder="请输入客户端秘钥" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="授权类型" prop="grantTypeList">
|
||||||
|
<el-select v-model="form.grantTypeList" multiple placeholder="请输入授权类型">
|
||||||
|
<el-option v-for="dict in sys_grant_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备类型" prop="deviceType">
|
||||||
|
<el-select v-model="form.deviceType" placeholder="请输入设备类型">
|
||||||
|
<el-option v-for="dict in sys_device_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="activeTimeout" label-width="auto">
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
<el-tooltip content="指定时间无操作则过期(单位:秒),默认30分钟(1800秒)" placement="top">
|
||||||
|
<el-icon><question-filled /></el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
Token活跃超时时间
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<el-input v-model="form.activeTimeout" placeholder="请输入Token活跃超时时间" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="timeout" label-width="auto">
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
<el-tooltip content="指定时间必定过期(单位:秒),默认七天(604800秒)" placement="top">
|
||||||
|
<el-icon><question-filled /></el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
Token固定超时时间
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<el-input v-model="form.timeout" placeholder="请输入Token固定超时时间" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">
|
||||||
|
{{ dict.label }}
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="Client" lang="ts">
|
||||||
|
import { listClient, getClient, delClient, addClient, updateClient, changeStatus } from '@/api/system/client';
|
||||||
|
import { ClientVO, ClientQuery, ClientForm } from '@/api/system/client/types';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable"));
|
||||||
|
const { sys_grant_type } = toRefs<any>(proxy?.useDict("sys_grant_type"));
|
||||||
|
const { sys_device_type } = toRefs<any>(proxy?.useDict("sys_device_type"));
|
||||||
|
|
||||||
|
const clientList = ref<ClientVO[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref<Array<string | number>>([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const clientFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const initFormData: ClientForm = {
|
||||||
|
id: undefined,
|
||||||
|
clientId: undefined,
|
||||||
|
clientKey: undefined,
|
||||||
|
clientSecret: undefined,
|
||||||
|
grantTypeList: undefined,
|
||||||
|
deviceType: undefined,
|
||||||
|
activeTimeout: undefined,
|
||||||
|
timeout: undefined,
|
||||||
|
status: undefined,
|
||||||
|
}
|
||||||
|
const data = reactive<PageData<ClientForm, ClientQuery>>({
|
||||||
|
form: {...initFormData},
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
clientId: undefined,
|
||||||
|
clientKey: undefined,
|
||||||
|
clientSecret: undefined,
|
||||||
|
grantType: undefined,
|
||||||
|
deviceType: undefined,
|
||||||
|
activeTimeout: undefined,
|
||||||
|
timeout: undefined,
|
||||||
|
status: undefined,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
id: [
|
||||||
|
{ required: true, message: "id不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
clientId: [
|
||||||
|
{ required: true, message: "客户端id不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
clientKey: [
|
||||||
|
{ required: true, message: "客户端key不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
clientSecret: [
|
||||||
|
{ required: true, message: "客户端秘钥不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
grantTypeList: [
|
||||||
|
{ required: true, message: "授权类型不能为空", trigger: "change" }
|
||||||
|
],
|
||||||
|
deviceType: [
|
||||||
|
{ required: true, message: "设备类型不能为空", trigger: "change" }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询客户端管理列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listClient(queryParams.value);
|
||||||
|
clientList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
const reset = () => {
|
||||||
|
form.value = {...initFormData};
|
||||||
|
clientFormRef.value?.resetFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
const handleSelectionChange = (selection: ClientVO[]) => {
|
||||||
|
ids.value = selection.map(item => item.id);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加客户端管理";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row?: ClientVO) => {
|
||||||
|
reset();
|
||||||
|
const _id = row?.id || ids.value[0]
|
||||||
|
const res = await getClient(_id);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改客户端管理";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
clientFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.id) {
|
||||||
|
await updateClient(form.value).finally(() => buttonLoading.value = false);
|
||||||
|
} else {
|
||||||
|
await addClient(form.value).finally(() => buttonLoading.value = false);
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess("修改成功");
|
||||||
|
dialog.visible = false;
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row?: ClientVO) => {
|
||||||
|
const _ids = row?.id || ids.value;
|
||||||
|
await proxy?.$modal.confirm('是否确认删除客户端管理编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
|
||||||
|
await delClient(_ids);
|
||||||
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download('system/client/export', {
|
||||||
|
...queryParams.value
|
||||||
|
}, `client_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 状态修改 */
|
||||||
|
const handleStatusChange = async (row: ClientVO) => {
|
||||||
|
let text = row.status === "0" ? "启用" : "停用"
|
||||||
|
try {
|
||||||
|
await proxy?.$modal.confirm('确认要"' + text + '"吗?');
|
||||||
|
await changeStatus(row.id, row.status);
|
||||||
|
proxy?.$modal.msgSuccess(text + "成功");
|
||||||
|
} catch (err) {
|
||||||
|
row.status = row.status === "0" ? "1" : "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="参数名称" prop="configName">
|
<el-form-item label="参数名称" prop="configName">
|
||||||
<el-input v-model="queryParams.configName" placeholder="请输入参数名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.configName" placeholder="请输入参数名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
||||||
@ -30,9 +31,10 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -123,8 +125,6 @@
|
|||||||
<script setup name="Config" lang="ts">
|
<script setup name="Config" lang="ts">
|
||||||
import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from "@/api/system/config";
|
import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from "@/api/system/config";
|
||||||
import { ConfigForm, ConfigQuery, ConfigVO } from "@/api/system/config/types";
|
import { ConfigForm, ConfigQuery, ConfigVO } from "@/api/system/config/types";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { DateModelType } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_yes_no } = toRefs<any>(proxy?.useDict("sys_yes_no"));
|
const { sys_yes_no } = toRefs<any>(proxy?.useDict("sys_yes_no"));
|
||||||
@ -138,8 +138,8 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const configFormRef = ref(ElForm);
|
const configFormRef = ref<ElFormInstance>();
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
title: ''
|
title: ''
|
||||||
@ -153,7 +153,7 @@ const initFormData: ConfigForm = {
|
|||||||
remark: ''
|
remark: ''
|
||||||
}
|
}
|
||||||
const data = reactive<PageData<ConfigForm, ConfigQuery>>({
|
const data = reactive<PageData<ConfigForm, ConfigQuery>>({
|
||||||
form: {...initFormData},
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -185,8 +185,8 @@ const cancel = () => {
|
|||||||
}
|
}
|
||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = {...initFormData};
|
form.value = { ...initFormData };
|
||||||
configFormRef.value.resetFields();
|
configFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
@ -196,7 +196,7 @@ const handleQuery = () => {
|
|||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
dateRange.value = ['', ''];
|
dateRange.value = ['', ''];
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
@ -207,31 +207,27 @@ const handleSelectionChange = (selection: ConfigVO[]) => {
|
|||||||
}
|
}
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "添加参数";
|
dialog.title = "添加参数";
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: ConfigVO) => {
|
const handleUpdate = async (row?: ConfigVO) => {
|
||||||
|
reset();
|
||||||
|
const configId = row?.configId || ids.value[0];
|
||||||
|
const res = await getConfig(configId);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "修改参数";
|
dialog.title = "修改参数";
|
||||||
const configId = row?.configId || ids.value[0];
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
|
||||||
const res = await getConfig(configId);
|
|
||||||
form.value = res.data;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
configFormRef.value.validate(async (valid: boolean) => {
|
configFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.configId ? await updateConfig(form.value) : await addConfig(form.value);
|
form.value.configId ? await updateConfig(form.value) : await addConfig(form.value);
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -240,7 +236,7 @@ const handleDelete = async (row?: ConfigVO) => {
|
|||||||
const configIds = row?.configId || ids.value;
|
const configIds = row?.configId || ids.value;
|
||||||
await proxy?.$modal.confirm('是否确认删除参数编号为"' + configIds + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除参数编号为"' + configIds + '"的数据项?');
|
||||||
await delConfig(configIds);
|
await delConfig(configIds);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
|
||||||
<el-form-item label="菜单名称" prop="menuName">
|
<el-form-item label="部门名称" prop="deptName">
|
||||||
<el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态" prop="status">
|
<el-form-item label="状态" prop="status">
|
||||||
@ -16,10 +17,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -130,7 +132,6 @@
|
|||||||
|
|
||||||
<script setup name="Dept" lang="ts">
|
<script setup name="Dept" lang="ts">
|
||||||
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept"
|
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept"
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { DeptForm, DeptQuery, DeptVO } from "@/api/system/dept/types";
|
import { DeptForm, DeptQuery, DeptVO } from "@/api/system/dept/types";
|
||||||
|
|
||||||
interface DeptOptionsType {
|
interface DeptOptionsType {
|
||||||
@ -155,9 +156,9 @@ const dialog = reactive<DialogOption>({
|
|||||||
title: ''
|
title: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const deptTableRef = ref(ElTable);
|
const deptTableRef = ref<ElTableInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const deptFormRef = ref(ElForm);
|
const deptFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const initFormData: DeptForm = {
|
const initFormData: DeptForm = {
|
||||||
deptId: undefined,
|
deptId: undefined,
|
||||||
@ -170,7 +171,7 @@ const initFormData: DeptForm = {
|
|||||||
status: "0"
|
status: "0"
|
||||||
}
|
}
|
||||||
const data = reactive<PageData<DeptForm, DeptQuery>>({
|
const data = reactive<PageData<DeptForm, DeptQuery>>({
|
||||||
form: {...initFormData},
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -205,8 +206,8 @@ const cancel = () => {
|
|||||||
}
|
}
|
||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = {...initFormData};
|
form.value = { ...initFormData };
|
||||||
deptFormRef.value.resetFields();
|
deptFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
@ -215,26 +216,10 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery()
|
handleQuery()
|
||||||
}
|
}
|
||||||
/** 新增按钮操作 */
|
|
||||||
const handleAdd = (row?: DeptVO) => {
|
|
||||||
listDept().then(res => {
|
|
||||||
const data = proxy?.handleTree<DeptOptionsType>(res.data, "deptId");
|
|
||||||
if (data) {
|
|
||||||
deptOptions.value = data
|
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "添加部门";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
|
||||||
if (row && row.deptId) {
|
|
||||||
form.value.parentId = row?.deptId;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/** 展开/折叠操作 */
|
/** 展开/折叠操作 */
|
||||||
const handleToggleExpandAll = () => {
|
const handleToggleExpandAll = () => {
|
||||||
isExpandAll.value = !isExpandAll.value;
|
isExpandAll.value = !isExpandAll.value;
|
||||||
@ -243,38 +228,55 @@ const handleToggleExpandAll = () => {
|
|||||||
/** 展开/折叠所有 */
|
/** 展开/折叠所有 */
|
||||||
const toggleExpandAll = (data: DeptVO[], status: boolean) => {
|
const toggleExpandAll = (data: DeptVO[], status: boolean) => {
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
deptTableRef.value.toggleRowExpansion(item, status)
|
deptTableRef.value?.toggleRowExpansion(item, status)
|
||||||
if(item.children && item.children.length > 0) toggleExpandAll(item.children, status)
|
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = async (row?: DeptVO) => {
|
||||||
|
reset();
|
||||||
|
const res = await listDept();
|
||||||
|
const data = proxy?.handleTree<DeptOptionsType>(res.data, "deptId");
|
||||||
|
if (data) {
|
||||||
|
deptOptions.value = data
|
||||||
|
if (row && row.deptId) {
|
||||||
|
form.value.parentId = row?.deptId;
|
||||||
|
}
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加部门";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = async (row: DeptVO) => {
|
const handleUpdate = async (row: DeptVO) => {
|
||||||
const res = await getDept(row.deptId);
|
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "修改部门";
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
reset();
|
||||||
|
const res = await getDept(row.deptId);
|
||||||
form.value = res.data
|
form.value = res.data
|
||||||
const response = await listDeptExcludeChild(row.deptId);
|
const response = await listDeptExcludeChild(row.deptId);
|
||||||
const data = proxy?.handleTree<DeptOptionsType>(response.data, "deptId")
|
const data = proxy?.handleTree<DeptOptionsType>(response.data, "deptId")
|
||||||
if (data) {
|
if (data) {
|
||||||
deptOptions.value = data;
|
deptOptions.value = data;
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
const noResultsOptions: DeptOptionsType = { deptId: res.data.parentId, deptName: res.data.parentName, children: [] };
|
const noResultsOptions: DeptOptionsType = {
|
||||||
|
deptId: res.data.parentId,
|
||||||
|
deptName: res.data.parentName,
|
||||||
|
children: []
|
||||||
|
};
|
||||||
deptOptions.value.push(noResultsOptions);
|
deptOptions.value.push(noResultsOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改部门";
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
deptFormRef.value.validate(async (valid: boolean) => {
|
deptFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.deptId ? await updateDept(form.value) : await addDept(form.value);
|
form.value.deptId ? await updateDept(form.value) : await addDept(form.value);
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -282,7 +284,7 @@ const submitForm = () => {
|
|||||||
const handleDelete = async (row: DeptVO) => {
|
const handleDelete = async (row: DeptVO) => {
|
||||||
await proxy?.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?');
|
||||||
await delDept(row.deptId);
|
await delDept(row.deptId);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="字典名称" prop="dictType">
|
<el-form-item label="字典名称" prop="dictType">
|
||||||
<el-select v-model="queryParams.dictType" style="width: 200px">
|
<el-select v-model="queryParams.dictType" style="width: 200px">
|
||||||
@ -21,9 +22,10 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -136,9 +138,7 @@ import useDictStore from '@/store/modules/dict'
|
|||||||
import { optionselect as getDictOptionselect, getType } from "@/api/system/dict/type";
|
import { optionselect as getDictOptionselect, getType } from "@/api/system/dict/type";
|
||||||
import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data";
|
import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data";
|
||||||
import { DictTypeVO } from '@/api/system/dict/type/types';
|
import { DictTypeVO } from '@/api/system/dict/type/types';
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { DictDataForm, DictDataQuery, DictDataVO } from "@/api/system/dict/data/types";
|
import { DictDataForm, DictDataQuery, DictDataVO } from "@/api/system/dict/data/types";
|
||||||
import { ElForm } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
||||||
const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable"));
|
const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable"));
|
||||||
@ -154,8 +154,8 @@ const total = ref(0);
|
|||||||
const defaultDictType = ref("");
|
const defaultDictType = ref("");
|
||||||
const typeOptions = ref<DictTypeVO[]>([]);
|
const typeOptions = ref<DictTypeVO[]>([]);
|
||||||
|
|
||||||
const dataFormRef = ref(ElForm);
|
const dataFormRef = ref<ElFormInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
@ -231,7 +231,7 @@ const cancel = () => {
|
|||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = { ...initFormData };
|
form.value = { ...initFormData };
|
||||||
dataFormRef.value.resetFields();
|
dataFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
@ -245,18 +245,16 @@ const handleClose = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
queryParams.value.dictType = defaultDictType.value;
|
queryParams.value.dictType = defaultDictType.value;
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "添加字典数据";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
reset();
|
||||||
form.value.dictType = queryParams.value.dictType;
|
form.value.dictType = queryParams.value.dictType;
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加字典数据";
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
const handleSelectionChange = (selection: DictDataVO[]) => {
|
const handleSelectionChange = (selection: DictDataVO[]) => {
|
||||||
@ -265,25 +263,23 @@ const handleSelectionChange = (selection: DictDataVO[]) => {
|
|||||||
multiple.value = !selection.length;
|
multiple.value = !selection.length;
|
||||||
}
|
}
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: DictDataVO) => {
|
const handleUpdate = async (row?: DictDataVO) => {
|
||||||
|
reset();
|
||||||
const dictCode = row?.dictCode || ids.value[0];
|
const dictCode = row?.dictCode || ids.value[0];
|
||||||
|
const res = await getData(dictCode);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "修改字典数据";
|
dialog.title = "修改字典数据";
|
||||||
nextTick(async () => {
|
|
||||||
const res = await getData(dictCode);
|
|
||||||
reset();
|
|
||||||
form.value = res.data;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
dataFormRef.value.validate(async (valid: boolean) => {
|
dataFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.dictCode ? await updateData(form.value) : await addData(form.value);
|
form.value.dictCode ? await updateData(form.value) : await addData(form.value);
|
||||||
useDictStore().removeDict(queryParams.value.dictType);
|
useDictStore().removeDict(queryParams.value.dictType);
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -293,7 +289,7 @@ const handleDelete = async (row?: DictDataVO) => {
|
|||||||
const dictCodes = row?.dictCode || ids.value;
|
const dictCodes = row?.dictCode || ids.value;
|
||||||
await proxy?.$modal.confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?');
|
||||||
await delData(dictCodes);
|
await delData(dictCodes);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
useDictStore().removeDict(queryParams.value.dictType);
|
useDictStore().removeDict(queryParams.value.dictType);
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="字典名称" prop="dictName">
|
<el-form-item label="字典名称" prop="dictName">
|
||||||
<el-input v-model="queryParams.dictName" placeholder="请输入字典名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.dictName" placeholder="请输入字典名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
||||||
@ -30,9 +31,10 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -123,9 +125,7 @@
|
|||||||
<script setup name="Dict" lang="ts">
|
<script setup name="Dict" lang="ts">
|
||||||
import useDictStore from '@/store/modules/dict'
|
import useDictStore from '@/store/modules/dict'
|
||||||
import { listType, getType, delType, addType, updateType, refreshCache } from "@/api/system/dict/type";
|
import { listType, getType, delType, addType, updateType, refreshCache } from "@/api/system/dict/type";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { DictTypeForm, DictTypeQuery, DictTypeVO } from "@/api/system/dict/type/types";
|
import { DictTypeForm, DictTypeQuery, DictTypeVO } from "@/api/system/dict/type/types";
|
||||||
import { DateModelType } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable"))
|
const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable"))
|
||||||
@ -139,8 +139,8 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
||||||
|
|
||||||
const dictFormRef = ref(ElForm);
|
const dictFormRef = ref<ElFormInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
@ -156,7 +156,7 @@ const initFormData: DictTypeForm = {
|
|||||||
remark: ''
|
remark: ''
|
||||||
}
|
}
|
||||||
const data = reactive<PageData<DictTypeForm, DictTypeQuery>>({
|
const data = reactive<PageData<DictTypeForm, DictTypeQuery>>({
|
||||||
form: {...initFormData},
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -188,8 +188,8 @@ const cancel = () => {
|
|||||||
}
|
}
|
||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = {...initFormData};
|
form.value = { ...initFormData };
|
||||||
dictFormRef.value.resetFields();
|
dictFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
@ -199,16 +199,14 @@ const handleQuery = () => {
|
|||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
dateRange.value = ['', ''];
|
dateRange.value = ['', ''];
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "添加字典类型";
|
dialog.title = "添加字典类型";
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
const handleSelectionChange = (selection: DictTypeVO[]) => {
|
const handleSelectionChange = (selection: DictTypeVO[]) => {
|
||||||
@ -217,20 +215,17 @@ const handleSelectionChange = (selection: DictTypeVO[]) => {
|
|||||||
multiple.value = !selection.length;
|
multiple.value = !selection.length;
|
||||||
}
|
}
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: DictTypeVO) => {
|
const handleUpdate = async (row?: DictTypeVO) => {
|
||||||
|
reset();
|
||||||
|
const dictId = row?.dictId || ids.value[0];
|
||||||
|
const res = await getType(dictId);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "修改字典类型";
|
dialog.title = "修改字典类型";
|
||||||
const dictId = row?.dictId || ids.value[0];
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
|
||||||
const res = await getType(dictId);
|
|
||||||
form.value = res.data;
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
dictFormRef.value.validate(async (valid: boolean) => {
|
dictFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.dictId ? await updateType(form.value) : await addType(form.value);
|
form.value.dictId ? await updateType(form.value) : await addType(form.value);
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
@ -260,7 +255,7 @@ const handleRefreshCache = async () => {
|
|||||||
useDictStore().cleanDict();
|
useDictStore().cleanDict();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
|
||||||
<el-form-item label="菜单名称" prop="menuName">
|
<el-form-item label="菜单名称" prop="menuName">
|
||||||
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter="handleQuery" />
|
||||||
@ -16,10 +17,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -37,7 +39,6 @@
|
|||||||
:data="menuList"
|
:data="menuList"
|
||||||
row-key="menuId"
|
row-key="menuId"
|
||||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||||
border
|
|
||||||
ref="menuTableRef"
|
ref="menuTableRef"
|
||||||
:default-expand-all="isExpandAll"
|
:default-expand-all="isExpandAll"
|
||||||
>
|
>
|
||||||
@ -180,7 +181,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12" v-if="form.menuType === 'C'">
|
<el-col :span="12" v-if="form.menuType === 'C'">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255" />
|
<el-input v-model="form.queryParam" placeholder="请输入路由参数" maxlength="255" />
|
||||||
<template #label>
|
<template #label>
|
||||||
<span>
|
<span>
|
||||||
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
|
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
|
||||||
@ -262,9 +263,7 @@
|
|||||||
<script setup name="Menu" lang="ts">
|
<script setup name="Menu" lang="ts">
|
||||||
import { addMenu, delMenu, getMenu, listMenu, updateMenu } from '@/api/system/menu';
|
import { addMenu, delMenu, getMenu, listMenu, updateMenu } from '@/api/system/menu';
|
||||||
import { MenuForm, MenuQuery, MenuVO } from '@/api/system/menu/types';
|
import { MenuForm, MenuQuery, MenuVO } from '@/api/system/menu/types';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
|
import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
|
||||||
import { ElTable, ElForm } from 'element-plus';
|
|
||||||
|
|
||||||
interface MenuOptionsType {
|
interface MenuOptionsType {
|
||||||
menuId: number;
|
menuId: number;
|
||||||
@ -286,8 +285,8 @@ const dialog = reactive<DialogOption>({
|
|||||||
title: ''
|
title: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const menuFormRef = ref(ElForm);
|
const menuFormRef = ref<ElFormInstance>();
|
||||||
const initFormData = {
|
const initFormData = {
|
||||||
path: '',
|
path: '',
|
||||||
menuId: undefined,
|
menuId: undefined,
|
||||||
@ -314,7 +313,7 @@ const data = reactive<PageData<MenuForm, MenuQuery>>({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const menuTableRef = ref(ElTable);
|
const menuTableRef = ref<ElTableInstance>();
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs<PageData<MenuForm, MenuQuery>>(data)
|
const { queryParams, form, rules } = toRefs<PageData<MenuForm, MenuQuery>>(data)
|
||||||
/** 查询菜单列表 */
|
/** 查询菜单列表 */
|
||||||
@ -343,7 +342,7 @@ const cancel = () => {
|
|||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = { ...initFormData };
|
form.value = { ...initFormData };
|
||||||
menuFormRef.value.resetFields();
|
menuFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
@ -352,19 +351,16 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = (row?: MenuVO) => {
|
const handleAdd = (row?: MenuVO) => {
|
||||||
|
reset();
|
||||||
|
getTreeselect();
|
||||||
|
row && row.menuId ? form.value.parentId = row.menuId : form.value.parentId = 0;
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "添加菜单";
|
dialog.title = "添加菜单";
|
||||||
getTreeselect();
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
|
||||||
row && row.menuId ? form.value.parentId = row.menuId : form.value.parentId = 0;
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/** 展开/折叠操作 */
|
/** 展开/折叠操作 */
|
||||||
const handleToggleExpandAll = () => {
|
const handleToggleExpandAll = () => {
|
||||||
@ -374,32 +370,29 @@ const handleToggleExpandAll = () => {
|
|||||||
/** 展开/折叠所有 */
|
/** 展开/折叠所有 */
|
||||||
const toggleExpandAll = (data: MenuVO[], status: boolean) => {
|
const toggleExpandAll = (data: MenuVO[], status: boolean) => {
|
||||||
data.forEach((item: MenuVO) => {
|
data.forEach((item: MenuVO) => {
|
||||||
menuTableRef.value.toggleRowExpansion(item, status)
|
menuTableRef.value?.toggleRowExpansion(item, status)
|
||||||
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
|
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = async (row: MenuVO) => {
|
const handleUpdate = async (row: MenuVO) => {
|
||||||
|
reset();
|
||||||
await getTreeselect();
|
await getTreeselect();
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "修改菜单";
|
|
||||||
await nextTick(async () => {
|
|
||||||
if (row.menuId) {
|
if (row.menuId) {
|
||||||
const { data } = await getMenu(row.menuId);
|
const { data } = await getMenu(row.menuId);
|
||||||
reset();
|
|
||||||
form.value = data;
|
form.value = data;
|
||||||
}
|
}
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改菜单";
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
menuFormRef.value.validate(async (valid: boolean) => {
|
menuFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.menuId ? await updateMenu(form.value) : await addMenu(form.value);
|
form.value.menuId ? await updateMenu(form.value) : await addMenu(form.value);
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -407,7 +400,7 @@ const submitForm = () => {
|
|||||||
const handleDelete = async (row: MenuVO) => {
|
const handleDelete = async (row: MenuVO) => {
|
||||||
await proxy?.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?');
|
||||||
await delMenu(row.menuId);
|
await delMenu(row.menuId);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="公告标题" prop="noticeTitle">
|
<el-form-item label="公告标题" prop="noticeTitle">
|
||||||
<el-input v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
||||||
@ -19,10 +20,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -119,9 +121,7 @@
|
|||||||
|
|
||||||
<script setup name="Notice" lang="ts">
|
<script setup name="Notice" lang="ts">
|
||||||
import { listNotice, getNotice, delNotice, addNotice, updateNotice } from "@/api/system/notice";
|
import { listNotice, getNotice, delNotice, addNotice, updateNotice } from "@/api/system/notice";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { NoticeForm, NoticeQuery, NoticeVO } from "@/api/system/notice/types";
|
import { NoticeForm, NoticeQuery, NoticeVO } from "@/api/system/notice/types";
|
||||||
import { ElForm } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_notice_status, sys_notice_type } = toRefs<any>(proxy?.useDict("sys_notice_status", "sys_notice_type"));
|
const { sys_notice_status, sys_notice_type } = toRefs<any>(proxy?.useDict("sys_notice_status", "sys_notice_type"));
|
||||||
@ -134,8 +134,8 @@ const single = ref(true);
|
|||||||
const multiple = ref(true);
|
const multiple = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const noticeFormRef = ref(ElForm);
|
const noticeFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
@ -186,7 +186,7 @@ const cancel = () => {
|
|||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = { ...initFormData };
|
form.value = { ...initFormData };
|
||||||
noticeFormRef.value.resetFields();
|
noticeFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
@ -195,7 +195,7 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
@ -206,31 +206,27 @@ const handleSelectionChange = (selection: NoticeVO[]) => {
|
|||||||
}
|
}
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "添加公告";
|
dialog.title = "添加公告";
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/**修改按钮操作 */
|
/**修改按钮操作 */
|
||||||
const handleUpdate = (row?: NoticeVO) => {
|
const handleUpdate = async (row?: NoticeVO) => {
|
||||||
|
reset();
|
||||||
|
const noticeId = row?.noticeId || ids.value[0];
|
||||||
|
const { data } = await getNotice(noticeId);
|
||||||
|
Object.assign(form.value, data);
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "修改公告";
|
dialog.title = "修改公告";
|
||||||
nextTick(async () => {
|
|
||||||
const noticeId = row?.noticeId || ids.value[0];
|
|
||||||
reset();
|
|
||||||
const { data } = await getNotice(noticeId);
|
|
||||||
form.value = data;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
noticeFormRef.value.validate(async (valid: boolean) => {
|
noticeFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.noticeId ? await updateNotice(form.value) : await addNotice(form.value);
|
form.value.noticeId ? await updateNotice(form.value) : await addNotice(form.value);
|
||||||
proxy?.$modal.msgSuccess("修改成功");
|
proxy?.$modal.msgSuccess("修改成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -239,7 +235,7 @@ const handleDelete = async (row?: NoticeVO) => {
|
|||||||
const noticeIds = row?.noticeId || ids.value
|
const noticeIds = row?.noticeId || ids.value
|
||||||
await proxy?.$modal.confirm('是否确认删除公告编号为"' + noticeIds + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除公告编号为"' + noticeIds + '"的数据项?');
|
||||||
await delNotice(noticeIds);
|
await delNotice(noticeIds);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="配置key" prop="configKey">
|
<el-form-item label="配置key" prop="configKey">
|
||||||
<el-input v-model="queryParams.configKey" placeholder="配置key" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.configKey" placeholder="配置key" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
||||||
@ -20,10 +21,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -62,7 +64,7 @@
|
|||||||
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width">
|
<el-table-column label="操作" fixed="right" align="center" width="150" class-name="small-padding">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tooltip content="修改" placement="top">
|
<el-tooltip content="修改" placement="top">
|
||||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:oss:edit']"></el-button>
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:oss:edit']"></el-button>
|
||||||
@ -138,9 +140,7 @@ import {
|
|||||||
updateOssConfig,
|
updateOssConfig,
|
||||||
changeOssConfigStatus
|
changeOssConfigStatus
|
||||||
} from "@/api/system/ossConfig";
|
} from "@/api/system/ossConfig";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { OssConfigForm, OssConfigQuery, OssConfigVO } from "@/api/system/ossConfig/types";
|
import { OssConfigForm, OssConfigQuery, OssConfigVO } from "@/api/system/ossConfig/types";
|
||||||
import { ElForm } from 'element-plus';
|
|
||||||
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
||||||
@ -155,8 +155,8 @@ const single = ref(true);
|
|||||||
const multiple = ref(true);
|
const multiple = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const ossConfigFormRef = ref(ElForm);
|
const ossConfigFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -262,7 +262,7 @@ const cancel = () => {
|
|||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = { ...initFormData };
|
form.value = { ...initFormData };
|
||||||
ossConfigFormRef.value.resetFields();
|
ossConfigFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
@ -271,7 +271,7 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 选择条数 */
|
/** 选择条数 */
|
||||||
@ -282,28 +282,22 @@ const handleSelectionChange = (selection: OssConfigVO[]) => {
|
|||||||
}
|
}
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "添加对象存储配置";
|
dialog.title = "添加对象存储配置";
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: OssConfigVO) => {
|
const handleUpdate = async (row?: OssConfigVO) => {
|
||||||
loading.value = true;
|
reset();
|
||||||
|
const ossConfigId = row?.ossConfigId || ids.value[0];
|
||||||
|
const res = await getOssConfig(ossConfigId);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "修改对象存储配置";
|
dialog.title = "修改对象存储配置";
|
||||||
const ossConfigId = row?.ossConfigId || ids.value[0];
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
|
||||||
const res = await getOssConfig(ossConfigId);
|
|
||||||
loading.value = false;
|
|
||||||
form.value = res.data;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
ossConfigFormRef.value.validate(async (valid: boolean) => {
|
ossConfigFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
if (form.value.ossConfigId) {
|
if (form.value.ossConfigId) {
|
||||||
@ -313,7 +307,7 @@ const submitForm = () => {
|
|||||||
}
|
}
|
||||||
proxy?.$modal.msgSuccess("新增成功");
|
proxy?.$modal.msgSuccess("新增成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -323,7 +317,7 @@ const handleStatusChange = async (row: OssConfigVO) => {
|
|||||||
try {
|
try {
|
||||||
await proxy?.$modal.confirm('确认要"' + text + '""' + row.configKey + '"配置吗?');
|
await proxy?.$modal.confirm('确认要"' + text + '""' + row.configKey + '"配置吗?');
|
||||||
await changeOssConfigStatus(row.ossConfigId, row.status, row.configKey);
|
await changeOssConfigStatus(row.ossConfigId, row.status, row.configKey);
|
||||||
getList()
|
await getList()
|
||||||
proxy?.$modal.msgSuccess(text + "成功");
|
proxy?.$modal.msgSuccess(text + "成功");
|
||||||
} catch { return } finally {
|
} catch { return } finally {
|
||||||
row.status = row.status === "0" ? "1" : "0";
|
row.status = row.status === "0" ? "1" : "0";
|
||||||
@ -336,7 +330,7 @@ const handleDelete = async (row?: OssConfigVO) => {
|
|||||||
await proxy?.$modal.confirm('是否确认删除OSS配置编号为"' + ossConfigIds + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除OSS配置编号为"' + ossConfigIds + '"的数据项?');
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await delOssConfig(ossConfigIds).finally(() => loading.value = false);
|
await delOssConfig(ossConfigIds).finally(() => loading.value = false);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="文件名" prop="fileName">
|
<el-form-item label="文件名" prop="fileName">
|
||||||
<el-input v-model="queryParams.fileName" placeholder="请输入文件名" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.fileName" placeholder="请输入文件名" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
||||||
@ -14,7 +15,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="创建时间">
|
<el-form-item label="创建时间">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="daterangeCreateTime"
|
v-model="dateRangeCreateTime"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
range-separator="-"
|
range-separator="-"
|
||||||
@ -31,10 +32,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -133,9 +135,7 @@
|
|||||||
<script setup name="Oss" lang="ts">
|
<script setup name="Oss" lang="ts">
|
||||||
import { listOss, delOss } from "@/api/system/oss";
|
import { listOss, delOss } from "@/api/system/oss";
|
||||||
import ImagePreview from "@/components/ImagePreview/index.vue";
|
import ImagePreview from "@/components/ImagePreview/index.vue";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { OssForm, OssQuery, OssVO } from "@/api/system/oss/types";
|
import { OssForm, OssQuery, OssVO } from "@/api/system/oss/types";
|
||||||
import { DateModelType } from 'element-plus';
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@ -151,7 +151,7 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const type = ref(0);
|
const type = ref(0);
|
||||||
const previewListResource = ref(true);
|
const previewListResource = ref(true);
|
||||||
const daterangeCreateTime = ref<[DateModelType, DateModelType]>(['', '']);
|
const dateRangeCreateTime = ref<[DateModelType, DateModelType]>(['', '']);
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -161,8 +161,8 @@ const dialog = reactive<DialogOption>({
|
|||||||
// 默认排序
|
// 默认排序
|
||||||
const defaultSort = ref({ prop: 'createTime', order: 'ascending' });
|
const defaultSort = ref({ prop: 'createTime', order: 'ascending' });
|
||||||
|
|
||||||
const ossFormRef = ref(ElForm);
|
const ossFormRef = ref<ElFormInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const initFormData = {
|
const initFormData = {
|
||||||
file: undefined,
|
file: undefined,
|
||||||
@ -195,7 +195,7 @@ const getList = async () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await proxy?.getConfigKey("sys.oss.previewListResource");
|
const res = await proxy?.getConfigKey("sys.oss.previewListResource");
|
||||||
previewListResource.value = res?.msg === undefined ? true : res.msg === 'true';
|
previewListResource.value = res?.msg === undefined ? true : res.msg === 'true';
|
||||||
const response = await listOss(proxy?.addDateRange(queryParams.value, daterangeCreateTime.value, "CreateTime"));
|
const response = await listOss(proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, "CreateTime"));
|
||||||
ossList.value = response.rows;
|
ossList.value = response.rows;
|
||||||
total.value = response.total;
|
total.value = response.total;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
@ -215,7 +215,7 @@ function cancel() {
|
|||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
function reset() {
|
function reset() {
|
||||||
form.value = { ...initFormData };
|
form.value = { ...initFormData };
|
||||||
ossFormRef.value.resetFields();
|
ossFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
@ -225,8 +225,8 @@ function handleQuery() {
|
|||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
function resetQuery() {
|
function resetQuery() {
|
||||||
showTable.value = false;
|
showTable.value = false;
|
||||||
daterangeCreateTime.value = ['', ''];
|
dateRangeCreateTime.value = ['', ''];
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
queryParams.value.orderByColumn = defaultSort.value.prop;
|
queryParams.value.orderByColumn = defaultSort.value.prop;
|
||||||
queryParams.value.isAsc = defaultSort.value.order;
|
queryParams.value.isAsc = defaultSort.value.order;
|
||||||
handleQuery();
|
handleQuery();
|
||||||
@ -288,21 +288,17 @@ const handleOssConfig = () => {
|
|||||||
}
|
}
|
||||||
/** 文件按钮操作 */
|
/** 文件按钮操作 */
|
||||||
const handleFile = () => {
|
const handleFile = () => {
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "上传文件";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
reset();
|
||||||
type.value = 0;
|
type.value = 0;
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "上传文件";
|
||||||
}
|
}
|
||||||
/** 图片按钮操作 */
|
/** 图片按钮操作 */
|
||||||
const handleImage = () => {
|
const handleImage = () => {
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "上传图片";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
reset();
|
||||||
type.value = 1;
|
type.value = 1;
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "上传图片";
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
@ -319,7 +315,7 @@ const handlePreviewListResource = async (preview: boolean) => {
|
|||||||
try {
|
try {
|
||||||
await proxy?.$modal.confirm('确认要"' + text + '""预览列表图片"配置吗?');
|
await proxy?.$modal.confirm('确认要"' + text + '""预览列表图片"配置吗?');
|
||||||
await proxy?.updateConfigByKey("sys.oss.previewListResource", preview);
|
await proxy?.updateConfigByKey("sys.oss.previewListResource", preview);
|
||||||
getList()
|
await getList()
|
||||||
proxy?.$modal.msgSuccess(text + "成功");
|
proxy?.$modal.msgSuccess(text + "成功");
|
||||||
} catch { return }
|
} catch { return }
|
||||||
}
|
}
|
||||||
@ -329,7 +325,7 @@ const handleDelete = async (row?: OssVO) => {
|
|||||||
await proxy?.$modal.confirm('是否确认删除OSS对象存储编号为"' + ossIds + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除OSS对象存储编号为"' + ossIds + '"的数据项?');
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await delOss(ossIds).finally(() => loading.value = false);
|
await delOss(ossIds).finally(() => loading.value = false);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="70">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="70">
|
||||||
<el-form-item label="岗位编码" prop="postCode">
|
<el-form-item label="岗位编码" prop="postCode">
|
||||||
<el-input v-model="queryParams.postCode" placeholder="请输入岗位编码" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.postCode" placeholder="请输入岗位编码" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
||||||
@ -19,9 +20,10 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -107,7 +109,6 @@
|
|||||||
<script setup name="Post" lang="ts">
|
<script setup name="Post" lang="ts">
|
||||||
import { listPost, addPost, delPost, getPost, updatePost } from "@/api/system/post";
|
import { listPost, addPost, delPost, getPost, updatePost } from "@/api/system/post";
|
||||||
import { PostForm, PostQuery, PostVO } from "@/api/system/post/types";
|
import { PostForm, PostQuery, PostVO } from "@/api/system/post/types";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable"));
|
const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable"));
|
||||||
@ -120,8 +121,8 @@ const single = ref(true);
|
|||||||
const multiple = ref(true);
|
const multiple = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const postFormRef = ref(ElForm);
|
const postFormRef = ref<ElFormInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -138,7 +139,7 @@ const initFormData: PostForm = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = reactive<PageData<PostForm, PostQuery>>({
|
const data = reactive<PageData<PostForm, PostQuery>>({
|
||||||
form: {...initFormData},
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -170,8 +171,8 @@ const cancel = () => {
|
|||||||
}
|
}
|
||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = {...initFormData};
|
form.value = { ...initFormData };
|
||||||
postFormRef.value.resetFields();
|
postFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
@ -180,7 +181,7 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
@ -191,31 +192,27 @@ const handleSelectionChange = (selection: PostVO[]) => {
|
|||||||
}
|
}
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "添加岗位";
|
dialog.title = "添加岗位";
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: PostVO) => {
|
const handleUpdate = async (row?: PostVO) => {
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "修改岗位";
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
reset();
|
||||||
const postId = row?.postId || ids.value[0];
|
const postId = row?.postId || ids.value[0];
|
||||||
const res = await getPost(postId);
|
const res = await getPost(postId);
|
||||||
form.value = res.data;
|
Object.assign(form.value, res.data);
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改岗位";
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
postFormRef.value.validate(async (valid: boolean) => {
|
postFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.postId ? await updatePost(form.value) : await addPost(form.value);
|
form.value.postId ? await updatePost(form.value) : await addPost(form.value);
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -224,7 +221,7 @@ const handleDelete = async (row?: PostVO) => {
|
|||||||
const postIds = row?.postId || ids.value;
|
const postIds = row?.postId || ids.value;
|
||||||
await proxy?.$modal.confirm('是否确认删除岗位编号为"' + postIds + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除岗位编号为"' + postIds + '"的数据项?');
|
||||||
await delPost(postIds);
|
await delPost(postIds);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
|
@ -58,13 +58,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
v-show="total > 0"
|
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
<select-user ref="selectRef" :roleId="queryParams.roleId" @ok="handleQuery" />
|
<select-user ref="selectRef" :roleId="queryParams.roleId" @ok="handleQuery" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
@ -73,10 +67,8 @@
|
|||||||
<script setup name="AuthUser" lang="ts">
|
<script setup name="AuthUser" lang="ts">
|
||||||
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role";
|
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role";
|
||||||
import { UserQuery } from "@/api/system/user/types";
|
import { UserQuery } from "@/api/system/user/types";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { UserVO } from "@/api/system/user/types";
|
import { UserVO } from "@/api/system/user/types";
|
||||||
import SelectUser from "./selectUser.vue";
|
import SelectUser from "./selectUser.vue";
|
||||||
// import { ElForm, ElSelect} from 'element-plus';
|
|
||||||
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -90,8 +82,8 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const userIds = ref<Array<string | number>>([]);
|
const userIds = ref<Array<string | number>>([]);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const selectRef = ref(SelectUser);
|
const selectRef = ref<InstanceType<typeof SelectUser>>();
|
||||||
|
|
||||||
const queryParams = reactive<UserQuery>({
|
const queryParams = reactive<UserQuery>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@ -115,29 +107,29 @@ const handleClose = () => {
|
|||||||
proxy?.$tab.closeOpenPage(obj);
|
proxy?.$tab.closeOpenPage(obj);
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery=() => {
|
const handleQuery = () => {
|
||||||
queryParams.pageNum = 1;
|
queryParams.pageNum = 1;
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery=() =>{
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
const handleSelectionChange = (selection: UserVO[]) =>{
|
const handleSelectionChange = (selection: UserVO[]) => {
|
||||||
userIds.value = selection.map(item => item.userId);
|
userIds.value = selection.map(item => item.userId);
|
||||||
multiple.value = !selection.length;
|
multiple.value = !selection.length;
|
||||||
}
|
}
|
||||||
/** 打开授权用户表弹窗 */
|
/** 打开授权用户表弹窗 */
|
||||||
const openSelectUser = () => {
|
const openSelectUser = () => {
|
||||||
selectRef.value.show();
|
selectRef.value?.show();
|
||||||
}
|
}
|
||||||
/** 取消授权按钮操作 */
|
/** 取消授权按钮操作 */
|
||||||
const cancelAuthUser = async (row: UserVO) => {
|
const cancelAuthUser = async (row: UserVO) => {
|
||||||
await proxy?.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?');
|
await proxy?.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?');
|
||||||
await authUserCancel({ userId: row.userId, roleId: queryParams.roleId });
|
await authUserCancel({ userId: row.userId, roleId: queryParams.roleId });
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("取消授权成功");
|
proxy?.$modal.msgSuccess("取消授权成功");
|
||||||
}
|
}
|
||||||
/** 批量取消授权按钮操作 */
|
/** 批量取消授权按钮操作 */
|
||||||
@ -146,7 +138,7 @@ const cancelAuthUserAll = async () => {
|
|||||||
const uIds = userIds.value.join(",");
|
const uIds = userIds.value.join(",");
|
||||||
await proxy?.$modal.confirm("是否取消选中用户授权数据项?");
|
await proxy?.$modal.confirm("是否取消选中用户授权数据项?");
|
||||||
await authUserCancelAll({ roleId: roleId, userIds: uIds });
|
await authUserCancelAll({ roleId: roleId, userIds: uIds });
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("取消授权成功");
|
proxy?.$modal.msgSuccess("取消授权成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
|
||||||
<el-form-item label="角色名称" prop="roleName">
|
<el-form-item label="角色名称" prop="roleName">
|
||||||
<el-input v-model="queryParams.roleName" placeholder="请输入角色名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.roleName" placeholder="请输入角色名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
||||||
@ -31,10 +32,11 @@
|
|||||||
<el-button @click="resetQuery" icon="Refresh">重置</el-button>
|
<el-button @click="resetQuery" icon="Refresh">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -196,8 +198,6 @@ import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updat
|
|||||||
import { roleMenuTreeselect, treeselect as menuTreeselect } from '@/api/system/menu/index';
|
import { roleMenuTreeselect, treeselect as menuTreeselect } from '@/api/system/menu/index';
|
||||||
import { RoleVO, RoleForm, RoleQuery, DeptTreeOption } from '@/api/system/role/types';
|
import { RoleVO, RoleForm, RoleQuery, DeptTreeOption } from '@/api/system/role/types';
|
||||||
import { MenuTreeOption, RoleMenuTree } from '@/api/system/menu/types';
|
import { MenuTreeOption, RoleMenuTree } from '@/api/system/menu/types';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { ElTree, ElForm, DateModelType } from 'element-plus';
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@ -228,11 +228,11 @@ const dataScopeOptions = ref([
|
|||||||
{ value: "5", label: "仅本人数据权限" }
|
{ value: "5", label: "仅本人数据权限" }
|
||||||
])
|
])
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const roleFormRef = ref(ElForm);
|
const roleFormRef = ref<ElFormInstance>();
|
||||||
const dataScopeRef = ref(ElForm);
|
const dataScopeRef = ref<ElFormInstance>();
|
||||||
const menuRef = ref(ElTree);
|
const menuRef = ref<ElTreeInstance>();
|
||||||
const deptRef = ref(ElTree);
|
const deptRef = ref<ElTreeInstance>();
|
||||||
|
|
||||||
const initForm: RoleForm = {
|
const initForm: RoleForm = {
|
||||||
roleId: undefined,
|
roleId: undefined,
|
||||||
@ -249,7 +249,7 @@ const initForm: RoleForm = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = reactive<PageData<RoleForm, RoleQuery>>({
|
const data = reactive<PageData<RoleForm, RoleQuery>>({
|
||||||
form: {...initForm},
|
form: { ...initForm },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -265,13 +265,11 @@ const data = reactive<PageData<RoleForm, RoleQuery>>({
|
|||||||
})
|
})
|
||||||
const { form, queryParams, rules } = toRefs(data)
|
const { form, queryParams, rules } = toRefs(data)
|
||||||
|
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
title: ''
|
title: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询角色列表
|
* 查询角色列表
|
||||||
*/
|
*/
|
||||||
@ -295,7 +293,7 @@ const handleQuery = () => {
|
|||||||
/** 重置 */
|
/** 重置 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
dateRange.value = ['', '']
|
dateRange.value = ['', '']
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/**删除按钮操作 */
|
/**删除按钮操作 */
|
||||||
@ -343,56 +341,51 @@ const getMenuTreeselect = async () => {
|
|||||||
menuOptions.value = res.data;
|
menuOptions.value = res.data;
|
||||||
}
|
}
|
||||||
/** 所有部门节点数据 */
|
/** 所有部门节点数据 */
|
||||||
const getDeptAllCheckedKeys = () => {
|
const getDeptAllCheckedKeys = (): any => {
|
||||||
// 目前被选中的部门节点
|
// 目前被选中的部门节点
|
||||||
let checkedKeys = deptRef.value.getCheckedKeys();
|
let checkedKeys = deptRef.value?.getCheckedKeys();
|
||||||
// 半选中的部门节点
|
// 半选中的部门节点
|
||||||
let halfCheckedKeys = deptRef.value.getHalfCheckedKeys();
|
let halfCheckedKeys = deptRef.value?.getHalfCheckedKeys();
|
||||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
if (halfCheckedKeys) {
|
||||||
|
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||||
|
}
|
||||||
return checkedKeys
|
return checkedKeys
|
||||||
}
|
}
|
||||||
/** 重置新增的表单以及其他数据 */
|
/** 重置新增的表单以及其他数据 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
menuRef.value.setCheckedKeys([]);
|
menuRef.value?.setCheckedKeys([]);
|
||||||
menuExpand.value = false
|
menuExpand.value = false
|
||||||
menuNodeAll.value = false
|
menuNodeAll.value = false
|
||||||
deptExpand.value = true
|
deptExpand.value = true
|
||||||
deptNodeAll.value = false
|
deptNodeAll.value = false
|
||||||
form.value = { ...initForm };
|
form.value = { ...initForm };
|
||||||
roleFormRef.value.resetFields();
|
roleFormRef.value?.resetFields();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 添加角色 */
|
/** 添加角色 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "添加角色";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
reset();
|
||||||
getMenuTreeselect();
|
getMenuTreeselect();
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加角色";
|
||||||
}
|
}
|
||||||
/** 修改角色 */
|
/** 修改角色 */
|
||||||
const handleUpdate = async (row?: RoleVO) => {
|
const handleUpdate = async (row?: RoleVO) => {
|
||||||
const roleId = row?.roleId || ids.value[0]
|
|
||||||
const roleMenu = getRoleMenuTreeselect(roleId)
|
|
||||||
const { data } = await getRole(roleId);
|
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "修改角色";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
reset();
|
||||||
|
const roleId = row?.roleId || ids.value[0]
|
||||||
|
const { data } = await getRole(roleId);
|
||||||
Object.assign(form.value, data);
|
Object.assign(form.value, data);
|
||||||
form.value.roleSort = Number(form.value.roleSort);
|
form.value.roleSort = Number(form.value.roleSort);
|
||||||
nextTick(async () => {
|
const res = await getRoleMenuTreeselect(roleId);
|
||||||
const res = await roleMenu;
|
dialog.title = "修改角色";
|
||||||
let checkedKeys = res.checkedKeys;
|
dialog.visible = true;
|
||||||
checkedKeys.forEach((v) => {
|
res.checkedKeys.forEach((v) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
menuRef.value.setChecked(v, true, false);
|
menuRef.value?.setChecked(v, true, false);
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
/** 根据角色ID查询菜单树结构 */
|
/** 根据角色ID查询菜单树结构 */
|
||||||
const getRoleMenuTreeselect = (roleId: string | number) => {
|
const getRoleMenuTreeselect = (roleId: string | number) => {
|
||||||
@ -408,25 +401,29 @@ const getRoleDeptTreeSelect = async (roleId: string | number) => {
|
|||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
/** 树权限(展开/折叠)*/
|
/** 树权限(展开/折叠)*/
|
||||||
const handleCheckedTreeExpand = (value: any, type: string) => {
|
const handleCheckedTreeExpand = (value: boolean, type: string) => {
|
||||||
if (type == "menu") {
|
if (type == "menu") {
|
||||||
let treeList = menuOptions.value;
|
let treeList = menuOptions.value;
|
||||||
for (let i = 0; i < treeList.length; i++) {
|
for (let i = 0; i < treeList.length; i++) {
|
||||||
|
if (menuRef.value) {
|
||||||
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (type == "dept") {
|
} else if (type == "dept") {
|
||||||
let treeList = deptOptions.value;
|
let treeList = deptOptions.value;
|
||||||
for (let i = 0; i < treeList.length; i++) {
|
for (let i = 0; i < treeList.length; i++) {
|
||||||
|
if (deptRef.value) {
|
||||||
deptRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
deptRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/** 树权限(全选/全不选) */
|
/** 树权限(全选/全不选) */
|
||||||
const handleCheckedTreeNodeAll = (value: any, type: string) => {
|
const handleCheckedTreeNodeAll = (value: any, type: string) => {
|
||||||
if (type == "menu") {
|
if (type == "menu") {
|
||||||
menuRef.value.setCheckedNodes(value ? menuOptions.value : []);
|
menuRef.value?.setCheckedNodes(value ? menuOptions.value as any : []);
|
||||||
} else if (type == "dept") {
|
} else if (type == "dept") {
|
||||||
deptRef.value.setCheckedNodes(value ? deptOptions.value : []);
|
deptRef.value?.setCheckedNodes(value ? deptOptions.value as any : []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 树权限(父子联动) */
|
/** 树权限(父子联动) */
|
||||||
@ -438,17 +435,19 @@ const handleCheckedTreeConnect = (value: any, type: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 所有菜单节点数据 */
|
/** 所有菜单节点数据 */
|
||||||
const getMenuAllCheckedKeys = () => {
|
const getMenuAllCheckedKeys = (): any => {
|
||||||
// 目前被选中的菜单节点
|
// 目前被选中的菜单节点
|
||||||
let checkedKeys = menuRef.value.getCheckedKeys();
|
let checkedKeys = menuRef.value?.getCheckedKeys();
|
||||||
// 半选中的菜单节点
|
// 半选中的菜单节点
|
||||||
let halfCheckedKeys = menuRef.value.getHalfCheckedKeys();
|
let halfCheckedKeys = menuRef.value?.getHalfCheckedKeys();
|
||||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
if (halfCheckedKeys) {
|
||||||
|
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||||
|
}
|
||||||
return checkedKeys;
|
return checkedKeys;
|
||||||
}
|
}
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
roleFormRef.value.validate(async (valid: boolean) => {
|
roleFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.menuIds = getMenuAllCheckedKeys()
|
form.value.menuIds = getMenuAllCheckedKeys()
|
||||||
form.value.roleId ? await updateRole(form.value) : await addRole(form.value);
|
form.value.roleId ? await updateRole(form.value) : await addRole(form.value);
|
||||||
@ -466,23 +465,18 @@ const cancel = () => {
|
|||||||
/** 选择角色权限范围触发 */
|
/** 选择角色权限范围触发 */
|
||||||
const dataScopeSelectChange = (value: string) => {
|
const dataScopeSelectChange = (value: string) => {
|
||||||
if (value !== "2") {
|
if (value !== "2") {
|
||||||
deptRef.value.setCheckedKeys([])
|
deptRef.value?.setCheckedKeys([])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 分配数据权限操作 */
|
/** 分配数据权限操作 */
|
||||||
const handleDataScope = async (row: RoleVO) => {
|
const handleDataScope = async (row: RoleVO) => {
|
||||||
const roleDeptTreeselect = getRoleDeptTreeSelect(row.roleId);
|
|
||||||
const response = await getRole(row.roleId);
|
const response = await getRole(row.roleId);
|
||||||
Object.assign(form.value, response.data);
|
Object.assign(form.value, response.data);
|
||||||
|
const res = await getRoleDeptTreeSelect(row.roleId);
|
||||||
openDataScope.value = true;
|
openDataScope.value = true;
|
||||||
dialog.title = "分配数据权限";
|
dialog.title = "分配数据权限";
|
||||||
nextTick(async () => {
|
await nextTick(() => {
|
||||||
const res = await roleDeptTreeselect;
|
deptRef.value?.setCheckedKeys(res.checkedKeys);
|
||||||
nextTick(() => {
|
|
||||||
if (deptRef.value) {
|
|
||||||
deptRef.value.setCheckedKeys(res.checkedKeys);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/** 提交按钮(数据权限) */
|
/** 提交按钮(数据权限) */
|
||||||
@ -497,8 +491,8 @@ const submitDataScope = async () => {
|
|||||||
}
|
}
|
||||||
/** 取消按钮(数据权限)*/
|
/** 取消按钮(数据权限)*/
|
||||||
const cancelDataScope = () => {
|
const cancelDataScope = () => {
|
||||||
dataScopeRef.value.resetFields();
|
dataScopeRef.value?.resetFields();
|
||||||
form.value = {...initForm};
|
form.value = { ...initForm };
|
||||||
openDataScope.value = false;
|
openDataScope.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +47,6 @@
|
|||||||
import { authUserSelectAll, unallocatedUserList } from "@/api/system/role";
|
import { authUserSelectAll, unallocatedUserList } from "@/api/system/role";
|
||||||
import { UserVO } from '@/api/system/user/types';
|
import { UserVO } from '@/api/system/user/types';
|
||||||
import { UserQuery } from '@/api/system/user/types';
|
import { UserQuery } from '@/api/system/user/types';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { ElForm, ElTable } from 'element-plus';
|
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -73,8 +71,8 @@ const queryParams = reactive<UserQuery>({
|
|||||||
phonenumber: undefined
|
phonenumber: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
const tableRef = ref(ElTable);
|
const tableRef = ref<ElTableInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const show = () => {
|
const show = () => {
|
||||||
queryParams.roleId = props.roleId;
|
queryParams.roleId = props.roleId;
|
||||||
@ -86,7 +84,8 @@ const show = () => {
|
|||||||
* 选择行
|
* 选择行
|
||||||
*/
|
*/
|
||||||
const clickRow = (row: any) => {
|
const clickRow = (row: any) => {
|
||||||
tableRef.value.toggleRowSelection(row);
|
// ele的bug
|
||||||
|
tableRef.value?.toggleRowSelection(row, false);
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
const handleSelectionChange = (selection: UserVO[]) => {
|
const handleSelectionChange = (selection: UserVO[]) => {
|
||||||
@ -106,7 +105,7 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="租户编号" prop="tenantId">
|
<el-form-item label="租户编号" prop="tenantId">
|
||||||
<el-input v-model="queryParams.tenantId" placeholder="请输入租户编号" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.tenantId" placeholder="请输入租户编号" clearable @keyup.enter="handleQuery" />
|
||||||
@ -20,10 +21,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -64,7 +66,7 @@
|
|||||||
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column width="150" label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tooltip content="修改" placement="top">
|
<el-tooltip content="修改" placement="top">
|
||||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:tenant:edit']"></el-button>
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:tenant:edit']"></el-button>
|
||||||
@ -80,7 +82,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改租户对话框 -->
|
<!-- 添加或修改租户对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
@ -143,8 +145,6 @@ import { listTenant, getTenant, delTenant, addTenant, updateTenant, changeTenant
|
|||||||
import { selectTenantPackage } from '@/api/system/tenantPackage';
|
import { selectTenantPackage } from '@/api/system/tenantPackage';
|
||||||
import { TenantForm, TenantQuery, TenantVO } from '@/api/system/tenant/types';
|
import { TenantForm, TenantQuery, TenantVO } from '@/api/system/tenant/types';
|
||||||
import { TenantPkgVO } from '@/api/system/tenantPackage/types';
|
import { TenantPkgVO } from '@/api/system/tenantPackage/types';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { ElForm } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
@ -158,8 +158,8 @@ const single = ref(true);
|
|||||||
const multiple = ref(true);
|
const multiple = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const tenantFormRef = ref(ElForm);
|
const tenantFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -185,7 +185,7 @@ const initFormData: TenantForm = {
|
|||||||
status: '0',
|
status: '0',
|
||||||
}
|
}
|
||||||
const data = reactive<PageData<TenantForm, TenantQuery>>({
|
const data = reactive<PageData<TenantForm, TenantQuery>>({
|
||||||
form: {...initFormData},
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -250,8 +250,8 @@ const cancel = () => {
|
|||||||
|
|
||||||
// 表单重置
|
// 表单重置
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = {...initFormData};
|
form.value = { ...initFormData };
|
||||||
tenantFormRef.value.resetFields();
|
tenantFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
@ -262,7 +262,7 @@ const handleQuery = () => {
|
|||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,32 +275,26 @@ const handleSelectionChange = (selection: TenantVO[]) => {
|
|||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "添加租户";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
reset();
|
||||||
getTenantPackage();
|
getTenantPackage();
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加租户";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: TenantVO) => {
|
const handleUpdate = async (row?: TenantVO) => {
|
||||||
loading.value = true;
|
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "修改租户";
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
reset();
|
||||||
getTenantPackage();
|
await getTenantPackage();
|
||||||
const _id = row?.id || ids.value[0];
|
const _id = row?.id || ids.value[0];
|
||||||
const res = await getTenant(_id);
|
const res = await getTenant(_id);
|
||||||
loading.value = false;
|
|
||||||
Object.assign(form.value, res.data)
|
Object.assign(form.value, res.data)
|
||||||
})
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改租户";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
tenantFormRef.value.validate(async (valid: boolean) => {
|
tenantFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
if (form.value.id) {
|
if (form.value.id) {
|
||||||
@ -310,7 +304,7 @@ const submitForm = () => {
|
|||||||
}
|
}
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -321,7 +315,7 @@ const handleDelete = async (row?: TenantVO) => {
|
|||||||
await proxy?.$modal.confirm('是否确认删除租户编号为"' + _ids + '"的数据项?')
|
await proxy?.$modal.confirm('是否确认删除租户编号为"' + _ids + '"的数据项?')
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await delTenant(_ids).finally(() => loading.value = false);
|
await delTenant(_ids).finally(() => loading.value = false);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
|
|
||||||
|
|
||||||
@ -333,9 +327,9 @@ const handleSyncTenantPackage = async (row: TenantVO) => {
|
|||||||
await proxy?.$modal.confirm('是否确认同步租户套餐租户编号为"' + row.tenantId + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认同步租户套餐租户编号为"' + row.tenantId + '"的数据项?');
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await syncTenantPackage(row.tenantId, row.packageId);
|
await syncTenantPackage(row.tenantId, row.packageId);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("同步成功");
|
proxy?.$modal.msgSuccess("同步成功");
|
||||||
} catch {return} finally {
|
} catch { return } finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="套餐名称" prop="packageName">
|
<el-form-item label="套餐名称" prop="packageName">
|
||||||
<el-input v-model="queryParams.packageName" placeholder="请输入套餐名称" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.packageName" placeholder="请输入套餐名称" clearable @keyup.enter="handleQuery" />
|
||||||
@ -11,27 +12,28 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:tenantPackage:add']">新增</el-button>
|
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:tenantPackage:add']"> 新增 </el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:tenantPackage:edit']"
|
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:tenantPackage:edit']">
|
||||||
>修改</el-button
|
修改
|
||||||
>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:tenantPackage:remove']"
|
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:tenantPackage:remove']">
|
||||||
>删除</el-button
|
删除
|
||||||
>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:tenantPackage:export']">导出</el-button>
|
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:tenantPackage:export']">导出 </el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -53,13 +55,13 @@
|
|||||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:tenantPackage:edit']"></el-button>
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:tenantPackage:edit']"></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="删除" placement="top">
|
<el-tooltip content="删除" placement="top">
|
||||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:tenantPackage:remove']"> </el-button>
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:tenantPackage:remove']"></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<!-- 添加或修改租户套餐对话框 -->
|
<!-- 添加或修改租户套餐对话框 -->
|
||||||
@ -70,8 +72,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="关联菜单">
|
<el-form-item label="关联菜单">
|
||||||
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
|
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
|
||||||
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
|
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选 </el-checkbox>
|
||||||
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
|
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动 </el-checkbox>
|
||||||
<el-tree
|
<el-tree
|
||||||
class="tree-border"
|
class="tree-border"
|
||||||
:data="menuOptions"
|
:data="menuOptions"
|
||||||
@ -98,12 +100,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="TenantPackage" lang="ts">
|
<script setup name="TenantPackage" lang="ts">
|
||||||
import { listTenantPackage, getTenantPackage, delTenantPackage, addTenantPackage, updateTenantPackage, changePackageStatus } from "@/api/system/tenantPackage";
|
import {
|
||||||
|
listTenantPackage,
|
||||||
|
getTenantPackage,
|
||||||
|
delTenantPackage,
|
||||||
|
addTenantPackage,
|
||||||
|
updateTenantPackage,
|
||||||
|
changePackageStatus
|
||||||
|
} from "@/api/system/tenantPackage";
|
||||||
import { treeselect as menuTreeselect, tenantPackageMenuTreeselect } from "@/api/system/menu";
|
import { treeselect as menuTreeselect, tenantPackageMenuTreeselect } from "@/api/system/menu";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from "@/api/system/tenantPackage/types";
|
import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from "@/api/system/tenantPackage/types";
|
||||||
import { MenuTreeOption } from "@/api/system/menu/types";
|
import { MenuTreeOption } from "@/api/system/menu/types";
|
||||||
import { CheckboxValueType, ElTree, ElForm } from 'element-plus';
|
|
||||||
import to from "await-to-js";
|
import to from "await-to-js";
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@ -120,29 +127,29 @@ const menuExpand = ref(false);
|
|||||||
const menuNodeAll = ref(false);
|
const menuNodeAll = ref(false);
|
||||||
const menuOptions = ref<MenuTreeOption[]>([]);
|
const menuOptions = ref<MenuTreeOption[]>([]);
|
||||||
|
|
||||||
const menuTreeRef = ref(ElTree);
|
const menuTreeRef = ref<ElTreeInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const tenantPackageFormRef = ref(ElForm);
|
const tenantPackageFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
title: ''
|
title: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const initFormData: TenantPkgForm = {
|
const initFormData: TenantPkgForm = {
|
||||||
packageId: undefined,
|
packageId: undefined,
|
||||||
packageName: '',
|
packageName: "",
|
||||||
menuIds: '',
|
menuIds: "",
|
||||||
remark: '',
|
remark: "",
|
||||||
menuCheckStrictly: true
|
menuCheckStrictly: true
|
||||||
};
|
};
|
||||||
const data = reactive<PageData<TenantPkgForm, TenantPkgQuery>>({
|
const data = reactive<PageData<TenantPkgForm, TenantPkgQuery>>({
|
||||||
form: {...initFormData},
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
packageName: ''
|
packageName: ""
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
packageId: [{ required: true, message: "租户套餐id不能为空", trigger: "blur" }],
|
packageId: [{ required: true, message: "租户套餐id不能为空", trigger: "blur" }],
|
||||||
@ -153,27 +160,29 @@ const data = reactive<PageData<TenantPkgForm, TenantPkgQuery>>({
|
|||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
/** 查询菜单树结构 */
|
/** 查询菜单树结构 */
|
||||||
const getMenuTreeselect = async() => {
|
const getMenuTreeselect = async () => {
|
||||||
const { data } = await menuTreeselect();
|
const { data } = await menuTreeselect();
|
||||||
menuOptions.value = data;
|
menuOptions.value = data;
|
||||||
}
|
};
|
||||||
|
|
||||||
// 所有菜单节点数据
|
// 所有菜单节点数据
|
||||||
const getMenuAllCheckedKeys = () => {
|
const getMenuAllCheckedKeys = (): any => {
|
||||||
// 目前被选中的菜单节点
|
// 目前被选中的菜单节点
|
||||||
let checkedKeys = menuTreeRef.value.getCheckedKeys();
|
let checkedKeys = menuTreeRef.value?.getCheckedKeys();
|
||||||
// 半选中的菜单节点
|
// 半选中的菜单节点
|
||||||
let halfCheckedKeys = menuTreeRef.value.getHalfCheckedKeys();
|
let halfCheckedKeys = menuTreeRef.value?.getHalfCheckedKeys();
|
||||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
if (halfCheckedKeys) {
|
||||||
|
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||||
|
}
|
||||||
return checkedKeys;
|
return checkedKeys;
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 根据租户套餐ID查询菜单树结构 */
|
/** 根据租户套餐ID查询菜单树结构 */
|
||||||
const getPackageMenuTreeselect = async(packageId: string | number) => {
|
const getPackageMenuTreeselect = async (packageId: string | number) => {
|
||||||
const res = await tenantPackageMenuTreeselect(packageId);
|
const res = await tenantPackageMenuTreeselect(packageId);
|
||||||
menuOptions.value = res.data.menus;
|
menuOptions.value = res.data.menus;
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 查询租户套餐列表 */
|
/** 查询租户套餐列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
@ -182,115 +191,107 @@ const getList = async () => {
|
|||||||
tenantPackageList.value = res.rows;
|
tenantPackageList.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
// 租户套餐状态修改
|
// 租户套餐状态修改
|
||||||
const handleStatusChange = async (row: TenantPkgVO) => {
|
const handleStatusChange = async (row: TenantPkgVO) => {
|
||||||
let text = row.status === "0" ? "启用" : "停用";
|
let text = row.status === "0" ? "启用" : "停用";
|
||||||
const [err] = await to(proxy?.$modal.confirm('确认要"' + text + '""' + row.packageName + '"套餐吗?') as Promise<any>)
|
const [err] = await to(proxy?.$modal.confirm("确认要\"" + text + "\"\"" + row.packageName + "\"套餐吗?") as Promise<any>);
|
||||||
if (err) {
|
if (err) {
|
||||||
row.status = row.status === "0" ? "1" : "0";
|
row.status = row.status === "0" ? "1" : "0";
|
||||||
} else {
|
} else {
|
||||||
await changePackageStatus(row.packageId, row.status);
|
await changePackageStatus(row.packageId, row.status);
|
||||||
proxy?.$modal.msgSuccess(text + "成功");
|
proxy?.$modal.msgSuccess(text + "成功");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// 取消按钮
|
// 取消按钮
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
reset();
|
reset();
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
// 表单重置
|
// 表单重置
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
menuTreeRef.value.setCheckedKeys([]);
|
menuTreeRef.value?.setCheckedKeys([]);
|
||||||
menuExpand.value = false;
|
menuExpand.value = false;
|
||||||
menuNodeAll.value = false;
|
menuNodeAll.value = false;
|
||||||
form.value = {...initFormData};
|
form.value = { ...initFormData };
|
||||||
tenantPackageFormRef.value.resetFields();
|
tenantPackageFormRef.value?.resetFields();
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
getList();
|
getList();
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
};
|
||||||
|
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
const handleSelectionChange = (selection: TenantPkgVO[]) => {
|
const handleSelectionChange = (selection: TenantPkgVO[]) => {
|
||||||
ids.value = selection.map(item => item.packageId);
|
ids.value = selection.map(item => item.packageId);
|
||||||
single.value = selection.length != 1;
|
single.value = selection.length != 1;
|
||||||
multiple.value = !selection.length;
|
multiple.value = !selection.length;
|
||||||
}
|
};
|
||||||
|
|
||||||
// 树权限(展开/折叠)
|
// 树权限(展开/折叠)
|
||||||
const handleCheckedTreeExpand = (value: CheckboxValueType, type: string) => {
|
const handleCheckedTreeExpand = (value: CheckboxValueType, type: string) => {
|
||||||
if (type == 'menu') {
|
if (type == "menu") {
|
||||||
let treeList = menuOptions.value;
|
let treeList = menuOptions.value;
|
||||||
for (let i = 0; i < treeList.length; i++) {
|
for (let i = 0; i < treeList.length; i++) {
|
||||||
menuTreeRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
if (menuTreeRef.value) {
|
||||||
|
menuTreeRef.value.store.nodesMap[treeList[i].id].expanded = value as boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 树权限(全选/全不选)
|
// 树权限(全选/全不选)
|
||||||
const handleCheckedTreeNodeAll = (value: CheckboxValueType, type: string) => {
|
const handleCheckedTreeNodeAll = (value: CheckboxValueType, type: string) => {
|
||||||
if (type == 'menu') {
|
if (type == "menu") {
|
||||||
menuTreeRef.value.setCheckedNodes(value ? menuOptions.value: []);
|
menuTreeRef.value?.setCheckedNodes(value ? menuOptions.value as any : []);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// 树权限(父子联动)
|
// 树权限(父子联动)
|
||||||
const handleCheckedTreeConnect = (value: CheckboxValueType, type: string) => {
|
const handleCheckedTreeConnect = (value: CheckboxValueType, type: string) => {
|
||||||
if (type == 'menu') {
|
if (type == "menu") {
|
||||||
form.value.menuCheckStrictly = value as boolean;
|
form.value.menuCheckStrictly = value as boolean;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "添加租户套餐";
|
|
||||||
nextTick(() => {
|
|
||||||
reset();
|
reset();
|
||||||
getMenuTreeselect();
|
getMenuTreeselect();
|
||||||
})
|
dialog.visible = true;
|
||||||
}
|
dialog.title = "添加租户套餐";
|
||||||
|
};
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: TenantPkgVO) => {
|
const handleUpdate = async (row?: TenantPkgVO) => {
|
||||||
loading.value = true
|
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = "修改租户套餐";
|
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
reset();
|
||||||
const _packageId = row?.packageId || ids.value[0];
|
const _packageId = row?.packageId || ids.value[0];
|
||||||
const packageMenu = getPackageMenuTreeselect(_packageId);
|
|
||||||
const response = await getTenantPackage(_packageId);
|
const response = await getTenantPackage(_packageId);
|
||||||
loading.value = false;
|
|
||||||
form.value = response.data;
|
form.value = response.data;
|
||||||
nextTick(async () => {
|
const res = await getPackageMenuTreeselect(_packageId);
|
||||||
const res = await packageMenu;
|
dialog.visible = true;
|
||||||
let checkedKeys = res.data.checkedKeys
|
dialog.title = "修改租户套餐";
|
||||||
checkedKeys.forEach((v) => {
|
res.data.checkedKeys.forEach((v) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
menuTreeRef.value.setChecked(v, true ,false);
|
menuTreeRef.value?.setChecked(v, true, false);
|
||||||
})
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
tenantPackageFormRef.value.validate(async (valid: boolean) => {
|
tenantPackageFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
form.value.menuIds = getMenuAllCheckedKeys();
|
form.value.menuIds = getMenuAllCheckedKeys();
|
||||||
@ -301,31 +302,31 @@ const submitForm = () => {
|
|||||||
}
|
}
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
getList();
|
await getList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
const handleDelete = async (row?: TenantPkgVO) => {
|
const handleDelete = async (row?: TenantPkgVO) => {
|
||||||
const _packageIds = row?.packageId || ids.value;
|
const _packageIds = row?.packageId || ids.value;
|
||||||
await proxy?.$modal.confirm('是否确认删除租户套餐编号为"' + _packageIds + '"的数据项?').finally(() => {
|
await proxy?.$modal.confirm("是否确认删除租户套餐编号为\"" + _packageIds + "\"的数据项?").finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
await delTenantPackage(_packageIds);
|
await delTenantPackage(_packageIds);
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
proxy?.download('system/tenantPackage/export', {
|
proxy?.download("system/tenantPackage/export", {
|
||||||
...queryParams.value
|
...queryParams.value
|
||||||
}, `tenantPackage_${new Date().getTime()}.xlsx`)
|
}, `tenantPackage_${new Date().getTime()}.xlsx`);
|
||||||
}
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -55,11 +55,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="AuthRole" lang="ts">
|
<script setup name="AuthRole" lang="ts">
|
||||||
import { RoleVO } from '@/api/system/role/types';
|
import { RoleVO } from "@/api/system/role/types";
|
||||||
import { getAuthRole, updateAuthRole } from '@/api/system/user';
|
import { getAuthRole, updateAuthRole } from "@/api/system/user";
|
||||||
import { UserForm } from '@/api/system/user/types';
|
import { UserForm } from "@/api/system/user/types";
|
||||||
import { ElTable } from "element-plus";
|
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
@ -71,15 +70,16 @@ const roleIds = ref<Array<string | number>>([]);
|
|||||||
const roles = ref<RoleVO[]>([]);
|
const roles = ref<RoleVO[]>([]);
|
||||||
const form = ref<Partial<UserForm>>({
|
const form = ref<Partial<UserForm>>({
|
||||||
nickName: undefined,
|
nickName: undefined,
|
||||||
userName: '',
|
userName: "",
|
||||||
userId: undefined
|
userId: undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
const tableRef = ref(ElTable)
|
const tableRef = ref<ElTableInstance>();
|
||||||
|
|
||||||
/** 单击选中行数据 */
|
/** 单击选中行数据 */
|
||||||
const clickRow = (row: RoleVO) => {
|
const clickRow = (row: RoleVO) => {
|
||||||
tableRef.value.toggleRowSelection(row);
|
// ele的方法有问题,selected应该为可选参数
|
||||||
|
tableRef.value?.toggleRowSelection(row, false);
|
||||||
};
|
};
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
const handleSelectionChange = (selection: RoleVO[]) => {
|
const handleSelectionChange = (selection: RoleVO[]) => {
|
||||||
@ -98,30 +98,30 @@ const close = () => {
|
|||||||
const submitForm = async () => {
|
const submitForm = async () => {
|
||||||
const userId = form.value.userId;
|
const userId = form.value.userId;
|
||||||
const rIds = roleIds.value.join(",");
|
const rIds = roleIds.value.join(",");
|
||||||
await updateAuthRole({ userId: userId as string, roleIds: rIds })
|
await updateAuthRole({ userId: userId as string, roleIds: rIds });
|
||||||
proxy?.$modal.msgSuccess("授权成功");
|
proxy?.$modal.msgSuccess("授权成功");
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getList = async() => {
|
const getList = async () => {
|
||||||
const userId = route.params && route.params.userId;
|
const userId = route.params && route.params.userId;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await getAuthRole(userId as string);
|
const res = await getAuthRole(userId as string);
|
||||||
Object.assign(form.value, res.data.user)
|
Object.assign(form.value, res.data.user);
|
||||||
Object.assign(roles.value, res.data.roles)
|
Object.assign(roles.value, res.data.roles);
|
||||||
total.value = roles.value.length;
|
total.value = roles.value.length;
|
||||||
await nextTick(() => {
|
await nextTick(() => {
|
||||||
roles.value.forEach(row => {
|
roles.value.forEach(row => {
|
||||||
if (row?.flag) {
|
if (row?.flag) {
|
||||||
tableRef.value.toggleRowSelection(row);
|
tableRef.value?.toggleRowSelection(row, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -16,18 +16,25 @@
|
|||||||
highlight-current
|
highlight-current
|
||||||
default-expand-all
|
default-expand-all
|
||||||
@node-click="handleNodeClick"
|
@node-click="handleNodeClick"
|
||||||
></el-tree>
|
/>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :lg="20" :xs="24">
|
<el-col :lg="20" :xs="24">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
|
||||||
<el-form-item label="用户名称" prop="userName">
|
<el-form-item label="用户名称" prop="userName">
|
||||||
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="手机号码" prop="phonenumber">
|
<el-form-item label="手机号码" prop="phonenumber">
|
||||||
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter="handleQuery" />
|
<el-input
|
||||||
|
v-model="queryParams.phonenumber"
|
||||||
|
placeholder="请输入手机号码"
|
||||||
|
clearable
|
||||||
|
style="width: 240px"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="状态" prop="status">
|
<el-form-item label="状态" prop="status">
|
||||||
@ -50,6 +57,7 @@
|
|||||||
<el-button @click="resetQuery" icon="Refresh">重置</el-button>
|
<el-button @click="resetQuery" icon="Refresh">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
@ -146,7 +154,7 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 添加或修改用户配置对话框 -->
|
<!-- 添加或修改用户配置对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body @close="closeDialog">
|
<el-dialog ref="formDialogRef" :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body @close="closeDialog">
|
||||||
<el-form :model="form" :rules="rules" ref="userFormRef" label-width="80px">
|
<el-form :model="form" :rules="rules" ref="userFormRef" label-width="80px">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@ -289,30 +297,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="User" lang="ts">
|
<script setup name="User" lang="ts">
|
||||||
import {
|
import api from "@/api/system/user"
|
||||||
changeUserStatus,
|
|
||||||
listUser,
|
|
||||||
resetUserPwd,
|
|
||||||
delUser,
|
|
||||||
getUser,
|
|
||||||
updateUser,
|
|
||||||
addUser,
|
|
||||||
deptTreeSelect
|
|
||||||
} from "@/api/system/user"
|
|
||||||
import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
|
import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { getToken } from "@/utils/auth";
|
import { getToken } from "@/utils/auth";
|
||||||
import { treeselect } from "@/api/system/dept";
|
import { treeselect } from "@/api/system/dept";
|
||||||
import { DeptVO } from "@/api/system/dept/types";
|
import { DeptVO } from "@/api/system/dept/types";
|
||||||
import { RoleVO } from "@/api/system/role/types";
|
import { RoleVO } from "@/api/system/role/types";
|
||||||
import { PostVO } from "@/api/system/post/types";
|
import { PostVO } from "@/api/system/post/types";
|
||||||
import { DateModelType, ElTree, ElUpload, UploadFile, ElForm } from 'element-plus';
|
|
||||||
import { to } from "await-to-js";
|
import { to } from "await-to-js";
|
||||||
|
import { globalHeaders } from "@/utils/request";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
||||||
const { sys_normal_disable, sys_user_sex } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex'));
|
const { sys_normal_disable, sys_user_sex } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex'));
|
||||||
|
|
||||||
|
|
||||||
const userList = ref<UserVO[]>();
|
const userList = ref<UserVO[]>();
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = ref(true)
|
const showSearch = ref(true)
|
||||||
@ -320,7 +318,7 @@ const ids = ref<Array<number | string>>([]);
|
|||||||
const single = ref(true);
|
const single = ref(true);
|
||||||
const multiple = ref(true);
|
const multiple = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const dateRange = ref<[DateModelType, DateModelType]>(['','']);
|
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
||||||
const deptName = ref('');
|
const deptName = ref('');
|
||||||
const deptOptions = ref<DeptVO[]>([]);
|
const deptOptions = ref<DeptVO[]>([]);
|
||||||
const initPassword = ref('123456');
|
const initPassword = ref('123456');
|
||||||
@ -337,7 +335,7 @@ const upload = reactive<ImportOption>({
|
|||||||
// 是否更新已经存在的用户数据
|
// 是否更新已经存在的用户数据
|
||||||
updateSupport: 0,
|
updateSupport: 0,
|
||||||
// 设置上传的请求头部
|
// 设置上传的请求头部
|
||||||
headers: { Authorization: "Bearer " + getToken() },
|
headers: globalHeaders,
|
||||||
// 上传的地址
|
// 上传的地址
|
||||||
url: import.meta.env.VITE_APP_BASE_API + "/system/user/importData"
|
url: import.meta.env.VITE_APP_BASE_API + "/system/user/importData"
|
||||||
})
|
})
|
||||||
@ -353,10 +351,11 @@ const columns = ref<FieldOption[]>([
|
|||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
const deptTreeRef = ref(ElTree);
|
const deptTreeRef = ref<ElTreeInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const userFormRef = ref(ElForm);
|
const userFormRef = ref<ElFormInstance>();
|
||||||
const uploadRef = ref(ElUpload);
|
const uploadRef = ref<ElUploadInstance>();
|
||||||
|
const formDialogRef = ref<ElDialogInstance>();
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -405,7 +404,7 @@ const filterNode = (value: string, data: any) => {
|
|||||||
}
|
}
|
||||||
/** 根据名称筛选部门树 */
|
/** 根据名称筛选部门树 */
|
||||||
watchEffect(
|
watchEffect(
|
||||||
() => {deptTreeRef.value.filter(deptName.value);},
|
() => { deptTreeRef.value?.filter(deptName.value); },
|
||||||
{
|
{
|
||||||
flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
|
flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
|
||||||
}
|
}
|
||||||
@ -413,14 +412,14 @@ watchEffect(
|
|||||||
|
|
||||||
/** 查询部门下拉树结构 */
|
/** 查询部门下拉树结构 */
|
||||||
const getTreeSelect = async () => {
|
const getTreeSelect = async () => {
|
||||||
const res = await deptTreeSelect();
|
const res = await api.deptTreeSelect();
|
||||||
deptOptions.value = res.data;
|
deptOptions.value = res.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 查询用户列表 */
|
/** 查询用户列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
|
const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
userList.value = res.rows;
|
userList.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
@ -440,11 +439,11 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
dateRange.value = ['','']
|
dateRange.value = ['', '']
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
queryParams.value.deptId = undefined;
|
queryParams.value.deptId = undefined;
|
||||||
deptTreeRef.value.setCurrentKey(null);
|
deptTreeRef.value?.setCurrentKey(undefined);
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,7 +452,7 @@ const handleDelete = async (row?: UserVO) => {
|
|||||||
const userIds = row?.userId || ids.value;
|
const userIds = row?.userId || ids.value;
|
||||||
const [err] = await to(proxy?.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?') as any);
|
const [err] = await to(proxy?.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?') as any);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
await delUser(userIds);
|
await api.delUser(userIds);
|
||||||
await getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess("删除成功");
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
}
|
}
|
||||||
@ -464,7 +463,7 @@ const handleStatusChange = async (row: UserVO) => {
|
|||||||
let text = row.status === "0" ? "启用" : "停用"
|
let text = row.status === "0" ? "启用" : "停用"
|
||||||
try {
|
try {
|
||||||
await proxy?.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?');
|
await proxy?.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?');
|
||||||
await changeUserStatus(row.userId, row.status);
|
await api.changeUserStatus(row.userId, row.status);
|
||||||
proxy?.$modal.msgSuccess(text + "成功");
|
proxy?.$modal.msgSuccess(text + "成功");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
row.status = row.status === "0" ? "1" : "0";
|
row.status = row.status === "0" ? "1" : "0";
|
||||||
@ -486,7 +485,7 @@ const handleResetPwd = async (row: UserVO) => {
|
|||||||
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
|
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
|
||||||
}))
|
}))
|
||||||
if (!err) {
|
if (!err) {
|
||||||
await resetUserPwd(row.userId, res.value);
|
await api.resetUserPwd(row.userId, res.value);
|
||||||
proxy?.$modal.msgSuccess("修改成功,新密码是:" + res.value);
|
proxy?.$modal.msgSuccess("修改成功,新密码是:" + res.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -523,14 +522,14 @@ const handleFileUploadProgress = () => {
|
|||||||
const handleFileSuccess = (response: any, file: UploadFile) => {
|
const handleFileSuccess = (response: any, file: UploadFile) => {
|
||||||
upload.open = false;
|
upload.open = false;
|
||||||
upload.isUploading = false;
|
upload.isUploading = false;
|
||||||
uploadRef.value.handleRemove(file);
|
uploadRef.value?.handleRemove(file);
|
||||||
ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
|
ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交上传文件 */
|
/** 提交上传文件 */
|
||||||
function submitFileForm() {
|
function submitFileForm() {
|
||||||
uploadRef.value.submit();
|
uploadRef.value?.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化部门数据 */
|
/** 初始化部门数据 */
|
||||||
@ -546,51 +545,46 @@ const initTreeData = async () => {
|
|||||||
/** 重置操作表单 */
|
/** 重置操作表单 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
form.value = { ...initFormData };
|
form.value = { ...initFormData };
|
||||||
userFormRef.value.resetFields();
|
userFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
/** 取消按钮 */
|
/** 取消按钮 */
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
reset();
|
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = async () => {
|
||||||
|
reset();
|
||||||
|
const { data } = await api.getUser();
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "新增用户";
|
dialog.title = "新增用户";
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
|
||||||
await initTreeData();
|
await initTreeData();
|
||||||
const { data } = await getUser();
|
|
||||||
postOptions.value = data.posts;
|
postOptions.value = data.posts;
|
||||||
roleOptions.value = data.roles;
|
roleOptions.value = data.roles;
|
||||||
form.value.password = initPassword.value;
|
form.value.password = initPassword.value;
|
||||||
})
|
|
||||||
}
|
}
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: UserForm) => {
|
const handleUpdate = async (row?: UserForm) => {
|
||||||
|
reset();
|
||||||
|
const userId = row?.userId || ids.value[0]
|
||||||
|
const { data } = await api.getUser(userId)
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = "修改用户";
|
dialog.title = "修改用户";
|
||||||
nextTick(async () => {
|
|
||||||
reset();
|
|
||||||
await initTreeData();
|
await initTreeData();
|
||||||
const userId = row?.userId || ids.value[0]
|
|
||||||
const { data } = await getUser(userId)
|
|
||||||
Object.assign(form.value, data.user);
|
Object.assign(form.value, data.user);
|
||||||
postOptions.value = data.posts;
|
postOptions.value = data.posts;
|
||||||
roleOptions.value = data.roles;
|
roleOptions.value = data.roles;
|
||||||
form.value.postIds = data.postIds;
|
form.value.postIds = data.postIds;
|
||||||
form.value.roleIds = data.roleIds;
|
form.value.roleIds = data.roleIds;
|
||||||
form.value.password = "";
|
form.value.password = "";
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
userFormRef.value.validate(async (valid: boolean) => {
|
userFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
form.value.userId ? await updateUser(form.value) : await addUser(form.value);
|
form.value.userId ? await api.updateUser(form.value) : await api.addUser(form.value);
|
||||||
proxy?.$modal.msgSuccess("操作成功");
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
await getList();
|
await getList();
|
||||||
@ -611,8 +605,8 @@ const closeDialog = () => {
|
|||||||
* 重置表单
|
* 重置表单
|
||||||
*/
|
*/
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
userFormRef.value.resetFields();
|
userFormRef.value?.resetFields();
|
||||||
userFormRef.value.clearValidate();
|
userFormRef.value?.clearValidate();
|
||||||
|
|
||||||
form.value.id = undefined;
|
form.value.id = undefined;
|
||||||
form.value.status = '1';
|
form.value.status = '1';
|
||||||
|
@ -55,6 +55,9 @@
|
|||||||
<el-tab-pane label="修改密码" name="resetPwd">
|
<el-tab-pane label="修改密码" name="resetPwd">
|
||||||
<resetPwd />
|
<resetPwd />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="第三方应用" name="thirdParty">
|
||||||
|
<thirdParty :auths="state.auths" />
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -66,13 +69,16 @@
|
|||||||
import userAvatar from "./userAvatar.vue";
|
import userAvatar from "./userAvatar.vue";
|
||||||
import userInfo from "./userInfo.vue";
|
import userInfo from "./userInfo.vue";
|
||||||
import resetPwd from "./resetPwd.vue";
|
import resetPwd from "./resetPwd.vue";
|
||||||
|
import thirdParty from "./thirdParty.vue";
|
||||||
|
import { getAuthList } from "@/api/system/social/auth";
|
||||||
import { getUserProfile } from "@/api/system/user";
|
import { getUserProfile } from "@/api/system/user";
|
||||||
|
|
||||||
const activeTab = ref("userinfo");
|
const activeTab = ref("userinfo");
|
||||||
const state = ref<{ user: any; roleGroup: string; postGroup: string}>({
|
const state = ref<Record<string, any>>({
|
||||||
user: {},
|
user: {},
|
||||||
roleGroup: '',
|
roleGroup: '',
|
||||||
postGroup: ''
|
postGroup: '',
|
||||||
|
auths: []
|
||||||
});
|
});
|
||||||
|
|
||||||
const userForm = ref({});
|
const userForm = ref({});
|
||||||
@ -85,7 +91,13 @@ const getUser = async () => {
|
|||||||
state.value.postGroup = res.data.postGroup;
|
state.value.postGroup = res.data.postGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAuths = async () => {
|
||||||
|
const res = await getAuthList();
|
||||||
|
state.value.auths = res.data;
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getUser();
|
getUser();
|
||||||
|
getAuths();
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -17,20 +17,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { updateUserPwd } from '@/api/system/user';
|
import { updateUserPwd } from "@/api/system/user";
|
||||||
import { ComponentInternalInstance } from 'vue';
|
import type { ResetPwdForm } from "@/api/system/user/types";
|
||||||
import { ResetPwdForm } from '@/api/system/user/types'
|
|
||||||
import { ElForm } from 'element-plus';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
const pwdRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const pwdRef = ref(ElForm);
|
|
||||||
|
|
||||||
const user = ref<ResetPwdForm>({
|
const user = ref<ResetPwdForm>({
|
||||||
oldPassword: '',
|
oldPassword: "",
|
||||||
newPassword: '',
|
newPassword: "",
|
||||||
confirmPassword: ''
|
confirmPassword: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const equalToPassword = (rule: any, value: string, callback: any) => {
|
const equalToPassword = (rule: any, value: string, callback: any) => {
|
||||||
@ -42,15 +37,24 @@ const equalToPassword = (rule: any, value: string, callback: any) => {
|
|||||||
};
|
};
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "blur" }],
|
oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "blur" }],
|
||||||
newPassword: [{ required: true, message: "新密码不能为空", trigger: "blur" }, { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }],
|
newPassword: [{ required: true, message: "新密码不能为空", trigger: "blur" }, {
|
||||||
confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "blur" }, { required: true, validator: equalToPassword, trigger: "blur" }]
|
min: 6,
|
||||||
|
max: 20,
|
||||||
|
message: "长度在 6 到 20 个字符",
|
||||||
|
trigger: "blur"
|
||||||
|
}],
|
||||||
|
confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "blur" }, {
|
||||||
|
required: true,
|
||||||
|
validator: equalToPassword,
|
||||||
|
trigger: "blur"
|
||||||
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
pwdRef.value.validate(async (valid: boolean) => {
|
pwdRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
await updateUserPwd(user.value.oldPassword, user.value.newPassword)
|
await updateUserPwd(user.value.oldPassword, user.value.newPassword);
|
||||||
proxy?.$modal.msgSuccess("修改成功");
|
proxy?.$modal.msgSuccess("修改成功");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
140
src/views/system/user/profile/thirdParty.vue
Normal file
140
src/views/system/user/profile/thirdParty.vue
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-table :data="auths" style="width: 100%; height: 100%; font-size: 10px">
|
||||||
|
<el-table-column label="序号" width="50" type="index"></el-table-column>
|
||||||
|
<el-table-column label="绑定账号平台" width="140" align="center" prop="source" show-overflow-tooltip />
|
||||||
|
<el-table-column label="头像" width="120" align="center" prop="avatar">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<img :src="scope.row.avatar" style="width: 45px; height: 45px" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="系统账号" width="180" align="center" prop="userName" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="绑定时间" width="180" align="center" prop="createTime" />
|
||||||
|
<el-table-column label="操作" width="80" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<el-button size="small" type="text" @click="unlockAuth(scope.row)">解绑</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div id="git-user-binding">
|
||||||
|
<h4 class="provider-desc">你可以绑定以下第三方帐号</h4>
|
||||||
|
<div id="authlist" class="user-bind">
|
||||||
|
<a class="third-app" href="#" @click="authUrl('wechar');" title="使用 微信 账号授权登录">
|
||||||
|
<div class="git-other-login-icon">
|
||||||
|
<svg-icon icon-class="wechat" />
|
||||||
|
</div>
|
||||||
|
<span class="app-name">WeiXin</span>
|
||||||
|
</a>
|
||||||
|
<a class="third-app" href="#" @click="authUrl('maxkey');" title="使用 MaxKey 账号授权登录">
|
||||||
|
<div class="git-other-login-icon">
|
||||||
|
<svg-icon icon-class="maxkey" />
|
||||||
|
</div>
|
||||||
|
<span class="app-name">MaxKey</span>
|
||||||
|
</a>
|
||||||
|
<a class="third-app" href="#" @click="authUrl('gitee');" title="使用 Gitee 账号授权登录">
|
||||||
|
<div class="git-other-login-icon">
|
||||||
|
<svg-icon icon-class="gitee" />
|
||||||
|
</div>
|
||||||
|
<span class="app-name">Gitee</span>
|
||||||
|
</a>
|
||||||
|
<a class="third-app" href="#" @click="authUrl('github');" title="使用 GitHub 账号授权登录">
|
||||||
|
<div class="git-other-login-icon">
|
||||||
|
<svg-icon icon-class="github" />
|
||||||
|
</div>
|
||||||
|
<span class="app-name">Github</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { authUnlock, authBinding } from "@/api/system/social/auth";
|
||||||
|
import { PropType } from "vue";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
auths: {
|
||||||
|
type: Object as PropType<any>,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const auths = computed(() => props.auths);
|
||||||
|
|
||||||
|
|
||||||
|
const unlockAuth = (row: any) => {
|
||||||
|
ElMessageBox.confirm('您确定要解除"' + row.source + '"的账号绑定吗?')
|
||||||
|
.then(() => {
|
||||||
|
return authUnlock(row.id);
|
||||||
|
}).then((res: any) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
proxy?.$modal.msgSuccess("解绑成功");
|
||||||
|
proxy?.$tab.refreshPage();
|
||||||
|
} else {
|
||||||
|
proxy?.$modal.msgError(res.msg);
|
||||||
|
}
|
||||||
|
}).catch(() => { });
|
||||||
|
};
|
||||||
|
|
||||||
|
const authUrl = (source: string) => {
|
||||||
|
authBinding(source).then((res: any) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
window.location.href = res.data;
|
||||||
|
} else {
|
||||||
|
proxy?.$modal.msgError(res.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
.user-bind .third-app {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 80px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-bind {
|
||||||
|
font-size: 1rem;
|
||||||
|
text-align: start;
|
||||||
|
height: 50px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-other-login-icon>img {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #005980;
|
||||||
|
}
|
||||||
|
|
||||||
|
.provider-desc {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
|
||||||
|
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Liberation Sans",
|
||||||
|
"PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Wenquanyi Micro Hei",
|
||||||
|
"WenQuanYi Zen Hei", "ST Heiti", SimHei, SimSun, "WenQuanYi Zen Hei Sharp",
|
||||||
|
sans-serif;
|
||||||
|
font-size: 1.071rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
td>img {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -29,7 +29,9 @@
|
|||||||
<el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
|
<el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
|
||||||
<el-button>
|
<el-button>
|
||||||
选择
|
选择
|
||||||
<el-icon class="el-icon--right"><Upload /></el-icon>
|
<el-icon class="el-icon--right">
|
||||||
|
<Upload />
|
||||||
|
</el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -58,18 +60,17 @@ import "vue-cropper/dist/index.css";
|
|||||||
import { VueCropper } from "vue-cropper";
|
import { VueCropper } from "vue-cropper";
|
||||||
import { uploadAvatar } from "@/api/system/user";
|
import { uploadAvatar } from "@/api/system/user";
|
||||||
import useUserStore from "@/store/modules/user";
|
import useUserStore from "@/store/modules/user";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
img: string | ArrayBuffer | null // 裁剪图片的地址
|
img: string | ArrayBuffer | null; // 裁剪图片的地址
|
||||||
autoCrop: boolean // 是否默认生成截图框
|
autoCrop: boolean; // 是否默认生成截图框
|
||||||
autoCropWidth: number // 默认生成截图框宽度
|
autoCropWidth: number; // 默认生成截图框宽度
|
||||||
autoCropHeight: number // 默认生成截图框高度
|
autoCropHeight: number; // 默认生成截图框高度
|
||||||
fixedBox: boolean // 固定截图框大小 不允许改变
|
fixedBox: boolean; // 固定截图框大小 不允许改变
|
||||||
fileName: string
|
fileName: string;
|
||||||
previews: any // 预览数据
|
previews: any; // 预览数据
|
||||||
outputType: string
|
outputType: string;
|
||||||
visible: boolean
|
visible: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ const options = reactive<Options>({
|
|||||||
autoCropHeight: 200,
|
autoCropHeight: 200,
|
||||||
fixedBox: true,
|
fixedBox: true,
|
||||||
outputType: "png",
|
outputType: "png",
|
||||||
fileName: '',
|
fileName: "",
|
||||||
previews: {},
|
previews: {},
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
@ -97,26 +98,27 @@ const options = reactive<Options>({
|
|||||||
/** 编辑头像 */
|
/** 编辑头像 */
|
||||||
const editCropper = () => {
|
const editCropper = () => {
|
||||||
open.value = true;
|
open.value = true;
|
||||||
}
|
};
|
||||||
/** 打开弹出层结束时的回调 */
|
/** 打开弹出层结束时的回调 */
|
||||||
const modalOpened = () => {
|
const modalOpened = () => {
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
}
|
};
|
||||||
/** 覆盖默认上传行为 */
|
/** 覆盖默认上传行为 */
|
||||||
const requestUpload = (): any => {}
|
const requestUpload = (): any => {
|
||||||
|
};
|
||||||
/** 向左旋转 */
|
/** 向左旋转 */
|
||||||
const rotateLeft = () => {
|
const rotateLeft = () => {
|
||||||
cropper.value.rotateLeft();
|
cropper.value.rotateLeft();
|
||||||
}
|
};
|
||||||
/** 向右旋转 */
|
/** 向右旋转 */
|
||||||
const rotateRight = () => {
|
const rotateRight = () => {
|
||||||
cropper.value.rotateRight();
|
cropper.value.rotateRight();
|
||||||
}
|
};
|
||||||
/** 图片缩放 */
|
/** 图片缩放 */
|
||||||
const changeScale = (num: number) => {
|
const changeScale = (num: number) => {
|
||||||
num = num || 1;
|
num = num || 1;
|
||||||
cropper.value.changeScale(num);
|
cropper.value.changeScale(num);
|
||||||
}
|
};
|
||||||
/** 上传预处理 */
|
/** 上传预处理 */
|
||||||
const beforeUpload = (file: any) => {
|
const beforeUpload = (file: any) => {
|
||||||
if (file.type.indexOf("image/") == -1) {
|
if (file.type.indexOf("image/") == -1) {
|
||||||
@ -129,7 +131,7 @@ const beforeUpload = (file: any) => {
|
|||||||
options.fileName = file.name;
|
options.fileName = file.name;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
/** 上传图片 */
|
/** 上传图片 */
|
||||||
const uploadImg = async () => {
|
const uploadImg = async () => {
|
||||||
cropper.value.getCropBlob(async (data: any) => {
|
cropper.value.getCropBlob(async (data: any) => {
|
||||||
@ -138,20 +140,20 @@ const uploadImg = async () => {
|
|||||||
const res = await uploadAvatar(formData);
|
const res = await uploadAvatar(formData);
|
||||||
open.value = false;
|
open.value = false;
|
||||||
options.img = res.data.imgUrl;
|
options.img = res.data.imgUrl;
|
||||||
userStore.avatar = options.img as string;
|
userStore.avatar = options.img as string
|
||||||
proxy?.$modal.msgSuccess("修改成功");
|
proxy?.$modal.msgSuccess("修改成功");
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
/** 实时预览 */
|
/** 实时预览 */
|
||||||
const realTime = (data: any) => {
|
const realTime = (data: any) => {
|
||||||
options.previews = data;
|
options.previews = data;
|
||||||
}
|
};
|
||||||
/** 关闭窗口 */
|
/** 关闭窗口 */
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
options.img = userStore.avatar;
|
options.img = userStore.avatar;
|
||||||
options.visible = false;
|
options.visible = false;
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -24,34 +24,36 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { updateUserProfile } from "@/api/system/user";
|
import { updateUserProfile } from "@/api/system/user";
|
||||||
import { FormRules } from "element-plus";
|
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
import { PropType } from "vue";
|
|
||||||
import { ElForm } from "element-plus";
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
user: {
|
user: {
|
||||||
type: Object as PropType<any>,
|
type: Object as PropType<any>,
|
||||||
|
required: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const userForm = computed(() => props.user);
|
const userForm = computed(() => props.user);
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
const userRef = ref<ElFormInstance>();
|
||||||
const userRef = ref(ElForm);
|
const rules = ref<ElFormRules>({
|
||||||
|
|
||||||
const rules = ref<FormRules>({
|
|
||||||
nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
|
nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
|
||||||
email: [{ required: true, message: "邮箱地址不能为空", trigger: "blur" }, { type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
|
email: [{ required: true, message: "邮箱地址不能为空", trigger: "blur" }, {
|
||||||
phonenumber: [{ required: true, message: "手机号码不能为空", trigger: "blur" }, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }],
|
type: "email",
|
||||||
|
message: "请输入正确的邮箱地址",
|
||||||
|
trigger: ["blur", "change"]
|
||||||
|
}],
|
||||||
|
phonenumber: [{
|
||||||
|
required: true,
|
||||||
|
message: "手机号码不能为空",
|
||||||
|
trigger: "blur"
|
||||||
|
}, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
userRef.value.validate(async (valid: boolean) => {
|
userRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
await updateUserProfile(props.user)
|
await updateUserProfile(props.user);
|
||||||
proxy?.$modal.msgSuccess("修改成功");
|
proxy?.$modal.msgSuccess("修改成功");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -31,15 +31,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PropType } from 'vue';
|
import { propTypes } from "@/utils/propTypes";
|
||||||
|
|
||||||
const prop = defineProps({
|
const prop = defineProps({
|
||||||
info: {
|
info: propTypes.any.def({})
|
||||||
type: Object as PropType<any>,
|
|
||||||
default: () => {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const infoForm = computed(() => prop.info)
|
const infoForm = computed(() => prop.info)
|
||||||
|
@ -117,9 +117,8 @@ import { getGenTable, updateGenTable } from '@/api/tool/gen';
|
|||||||
import { DbColumnVO, DbTableVO } from '@/api/tool/gen/types';
|
import { DbColumnVO, DbTableVO } from '@/api/tool/gen/types';
|
||||||
import { optionselect as getDictOptionselect } from '@/api/system/dict/type';
|
import { optionselect as getDictOptionselect } from '@/api/system/dict/type';
|
||||||
import { DictTypeVO } from '@/api/system/dict/type/types';
|
import { DictTypeVO } from '@/api/system/dict/type/types';
|
||||||
import basicInfoForm from './basicInfoForm.vue';
|
import BasicInfoForm from './basicInfoForm.vue';
|
||||||
import genInfoForm from "./genInfoForm.vue";
|
import GenInfoForm from "./genInfoForm.vue";
|
||||||
import { ComponentInternalInstance } from "vue";
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@ -131,13 +130,13 @@ const columns = ref<DbColumnVO[]>([]);
|
|||||||
const dictOptions = ref<DictTypeVO[]>([]);
|
const dictOptions = ref<DictTypeVO[]>([]);
|
||||||
const info = ref<Partial<DbTableVO>>({});
|
const info = ref<Partial<DbTableVO>>({});
|
||||||
|
|
||||||
const basicInfo = ref(basicInfoForm);
|
const basicInfo = ref<InstanceType<typeof BasicInfoForm>>();
|
||||||
const genInfo = ref(genInfoForm);
|
const genInfo = ref<InstanceType<typeof GenInfoForm>>();
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
const basicForm = basicInfo.value.$refs.basicInfoForm;
|
const basicForm = basicInfo.value?.$refs.basicInfoForm;
|
||||||
const genForm = genInfo.value.$refs.genInfoForm;
|
const genForm = genInfo.value?.$refs.genInfoForm;
|
||||||
|
|
||||||
Promise.all([basicForm, genForm].map(getFormPromise)).then(async res => {
|
Promise.all([basicForm, genForm].map(getFormPromise)).then(async res => {
|
||||||
const validateResult = res.every(item => !!item);
|
const validateResult = res.every(item => !!item);
|
||||||
@ -168,7 +167,7 @@ const getFormPromise = (form: any) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const close = () => {
|
const close = () => {
|
||||||
const obj = {path: "/tool/gen", query: {t: Date.now(), pageNum: route.query.pageNum}};
|
const obj = { path: "/tool/gen", query: { t: Date.now(), pageNum: route.query.pageNum } };
|
||||||
proxy?.$tab.closeOpenPage(obj);
|
proxy?.$tab.closeOpenPage(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { listMenu } from '@/api/system/menu';
|
import { listMenu } from '@/api/system/menu';
|
||||||
import { ComponentInternalInstance, PropType } from 'vue';
|
import { propTypes } from "@/utils/propTypes";
|
||||||
|
|
||||||
interface MenuOptionsType {
|
interface MenuOptionsType {
|
||||||
menuId: number | string;
|
menuId: number | string;
|
||||||
@ -236,14 +236,8 @@ const menuOptions = ref<Array<MenuOptionsType>>([]);
|
|||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
info: {
|
info: propTypes.any.def(null),
|
||||||
type: Object as PropType<any>,
|
tables: propTypes.any.def(null)
|
||||||
default: null
|
|
||||||
},
|
|
||||||
tables: {
|
|
||||||
type: Array as PropType<any[]>,
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const infoForm = computed(() => props.info);
|
const infoForm = computed(() => props.info);
|
||||||
@ -252,11 +246,11 @@ const table = computed(() => props.tables);
|
|||||||
|
|
||||||
// 表单校验
|
// 表单校验
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
tplCategory: [{required: true, message: "请选择生成模板", trigger: "blur"}],
|
tplCategory: [{ required: true, message: "请选择生成模板", trigger: "blur" }],
|
||||||
packageName: [{required: true, message: "请输入生成包路径", trigger: "blur"}],
|
packageName: [{ required: true, message: "请输入生成包路径", trigger: "blur" }],
|
||||||
moduleName: [{required: true, message: "请输入生成模块名", trigger: "blur"}],
|
moduleName: [{ required: true, message: "请输入生成模块名", trigger: "blur" }],
|
||||||
businessName: [{required: true, message: "请输入生成业务名", trigger: "blur"}],
|
businessName: [{ required: true, message: "请输入生成业务名", trigger: "blur" }],
|
||||||
functionName: [{required: true, message: "请输入生成功能名", trigger: "blur"}]
|
functionName: [{ required: true, message: "请输入生成功能名", trigger: "blur" }]
|
||||||
});
|
});
|
||||||
const subSelectChange = () => {
|
const subSelectChange = () => {
|
||||||
infoForm.value.subTableFkName = "";
|
infoForm.value.subTableFkName = "";
|
||||||
@ -268,7 +262,7 @@ const tplSelectChange = (value: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const setSubTableColumns = (value: string) => {
|
const setSubTableColumns = (value: string) => {
|
||||||
table.value.forEach(item => {
|
table.value.forEach((item: any) => {
|
||||||
const name = item.tableName;
|
const name = item.tableName;
|
||||||
if (value === name) {
|
if (value === name) {
|
||||||
subColumns.value = item.columns;
|
subColumns.value = item.columns;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<el-table-column prop="createTime" label="创建时间"></el-table-column>
|
<el-table-column prop="createTime" label="创建时间"></el-table-column>
|
||||||
<el-table-column prop="updateTime" label="更新时间"></el-table-column>
|
<el-table-column prop="updateTime" label="更新时间"></el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<pagination v-show="total>0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
</el-row>
|
</el-row>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
@ -40,8 +40,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { listDbTable, importTable, getDataNames } from '@/api/tool/gen';
|
import { listDbTable, importTable, getDataNames } from '@/api/tool/gen';
|
||||||
import { DbTableQuery, DbTableVO } from '@/api/tool/gen/types';
|
import { DbTableQuery, DbTableVO } from '@/api/tool/gen/types';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { ElTable, ElForm } from 'element-plus';
|
|
||||||
|
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
@ -49,8 +47,8 @@ const tables = ref<Array<string>>([]);
|
|||||||
const dbTableList = ref<Array<DbTableVO>>([]);
|
const dbTableList = ref<Array<DbTableVO>>([]);
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
const tableRef = ref(ElTable);
|
const tableRef = ref<ElTableInstance>();
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
const queryParams = reactive<DbTableQuery>({
|
const queryParams = reactive<DbTableQuery>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@ -66,7 +64,7 @@ const emit = defineEmits(["ok"]);
|
|||||||
/** 查询参数列表 */
|
/** 查询参数列表 */
|
||||||
const show = (dataName: string) => {
|
const show = (dataName: string) => {
|
||||||
getDataNameList();
|
getDataNameList();
|
||||||
if(dataName){
|
if (dataName) {
|
||||||
queryParams.dataName = dataName;
|
queryParams.dataName = dataName;
|
||||||
} else {
|
} else {
|
||||||
queryParams.dataName = 'master';
|
queryParams.dataName = 'master';
|
||||||
@ -76,7 +74,8 @@ const show = (dataName: string) => {
|
|||||||
}
|
}
|
||||||
/** 单击选择行 */
|
/** 单击选择行 */
|
||||||
const clickRow = (row: DbTableVO) => {
|
const clickRow = (row: DbTableVO) => {
|
||||||
tableRef.value.toggleRowSelection(row);
|
// ele bug
|
||||||
|
tableRef.value?.toggleRowSelection(row, false);
|
||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
const handleSelectionChange = (selection: DbTableVO[]) => {
|
const handleSelectionChange = (selection: DbTableVO[]) => {
|
||||||
@ -95,7 +94,7 @@ const handleQuery = () => {
|
|||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 导入按钮操作 */
|
/** 导入按钮操作 */
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div class="search" v-show="showSearch">
|
<div class="mb-[10px]" v-show="showSearch">
|
||||||
|
<el-card shadow="hover">
|
||||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||||
<el-form-item label="数据源" prop="dataName">
|
<el-form-item label="数据源" prop="dataName">
|
||||||
<el-select v-model="queryParams.dataName" filterable clearable placeholder="请选择/输入数据源名称" style="width: 200px">
|
<el-select v-model="queryParams.dataName" filterable clearable placeholder="请选择/输入数据源名称" style="width: 200px">
|
||||||
@ -30,10 +31,11 @@
|
|||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -99,9 +101,9 @@
|
|||||||
:name="(key as any).substring((key as any).lastIndexOf('/') + 1, (key as any).indexOf('.vm'))"
|
:name="(key as any).substring((key as any).lastIndexOf('/') + 1, (key as any).indexOf('.vm'))"
|
||||||
:key="value"
|
:key="value"
|
||||||
>
|
>
|
||||||
<el-link :underline="false" icon="DocumentCopy" v-copyText="value" v-copyText:callback="copyTextSuccess" style="float:right"
|
<el-link :underline="false" icon="DocumentCopy" v-copyText="value" v-copyText:callback="copyTextSuccess" style="float:right">
|
||||||
> 复制</el-link
|
复制
|
||||||
>
|
</el-link>
|
||||||
<pre>{{ value }}</pre>
|
<pre>{{ value }}</pre>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
@ -114,9 +116,7 @@
|
|||||||
import { listTable, previewTable, delTable, genCode, synchDb, getDataNames } from '@/api/tool/gen';
|
import { listTable, previewTable, delTable, genCode, synchDb, getDataNames } from '@/api/tool/gen';
|
||||||
import { TableQuery, TableVO } from '@/api/tool/gen/types';
|
import { TableQuery, TableVO } from '@/api/tool/gen/types';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
import importTable from './importTable.vue';
|
import ImportTable from './importTable.vue';
|
||||||
import { ComponentInternalInstance } from 'vue';
|
|
||||||
import { ElForm, DateModelType } from 'element-plus';
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@ -132,8 +132,8 @@ const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
|||||||
const uniqueId = ref("");
|
const uniqueId = ref("");
|
||||||
const dataNameList = ref<Array<string>>([]);
|
const dataNameList = ref<Array<string>>([]);
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const importRef = ref(importTable);
|
const importRef = ref<InstanceType<typeof ImportTable>>();
|
||||||
|
|
||||||
const queryParams = ref<TableQuery>({
|
const queryParams = ref<TableQuery>({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@ -143,7 +143,7 @@ const queryParams = ref<TableQuery>({
|
|||||||
dataName: ""
|
dataName: ""
|
||||||
})
|
})
|
||||||
|
|
||||||
const preview = ref <any>({
|
const preview = ref<any>({
|
||||||
data: {},
|
data: {},
|
||||||
activeName: 'domain.java'
|
activeName: 'domain.java'
|
||||||
})
|
})
|
||||||
@ -158,7 +158,7 @@ onActivated(() => {
|
|||||||
uniqueId.value = time as string;
|
uniqueId.value = time as string;
|
||||||
queryParams.value.pageNum = Number(route.query.pageNum);
|
queryParams.value.pageNum = Number(route.query.pageNum);
|
||||||
dateRange.value = ['', ''];
|
dateRange.value = ['', ''];
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -205,12 +205,12 @@ const handleSynchDb = async (row: TableVO) => {
|
|||||||
}
|
}
|
||||||
/** 打开导入表弹窗 */
|
/** 打开导入表弹窗 */
|
||||||
const openImportTable = () => {
|
const openImportTable = () => {
|
||||||
importRef.value.show(queryParams.value.dataName);
|
importRef.value?.show(queryParams.value.dataName);
|
||||||
}
|
}
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
dateRange.value = ['', ''];
|
dateRange.value = ['', ''];
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
/** 预览按钮 */
|
/** 预览按钮 */
|
||||||
@ -240,7 +240,7 @@ const handleDelete = async (row?: TableVO) => {
|
|||||||
const tableIds = row?.tableId || ids.value;
|
const tableIds = row?.tableId || ids.value;
|
||||||
await proxy?.$modal.confirm('是否确认删除表编号为"' + tableIds + '"的数据项?');
|
await proxy?.$modal.confirm('是否确认删除表编号为"' + tableIds + '"的数据项?');
|
||||||
await delTable(tableIds);
|
await delTable(tableIds);
|
||||||
getList();
|
await getList();
|
||||||
proxy?.$modal.msgSuccess('删除成功');
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user