Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into dev

 Conflicts:
	pom.xml
	ruoyi-admin/pom.xml
	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
	ruoyi-admin/src/main/resources/application.yml
	ruoyi-common/pom.xml
	ruoyi-framework/pom.xml
	ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
	ruoyi-generator/pom.xml
	ruoyi-job/pom.xml
	ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java
	ruoyi-system/pom.xml
	ruoyi-ui/package.json
	ruoyi-ui/src/api/system/user.js
	ruoyi-ui/src/utils/request.js
	ruoyi-ui/src/views/index.vue
	ruoyi-ui/src/views/monitor/job/index.vue
	ruoyi-ui/src/views/system/user/index.vue
This commit is contained in:
疯狂的狮子li 2022-01-04 09:45:33 +08:00
commit 1c7d840ff6
8 changed files with 395 additions and 334 deletions

View File

@ -113,9 +113,10 @@ public class SysUserController extends BaseController {
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
ajax.put("posts", postService.selectPostAll());
if (StringUtils.isNotNull(userId)) {
ajax.put("user", userService.selectUserById(userId));
SysUser sysUser = userService.selectUserById(userId);
ajax.put("user", sysUser);
ajax.put("postIds", postService.selectPostListByUserId(userId));
ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
}
return AjaxResult.success(ajax);
}

View File

@ -1,5 +1,5 @@
import request from '@/utils/request'
import { praseStrEmpty } from "@/utils/ruoyi";
import { parseStrEmpty } from "@/utils/ruoyi";
// 查询用户列表
export function listUser(query) {
@ -13,7 +13,7 @@ export function listUser(query) {
// 查询用户详细
export function getUser(userId) {
return request({
url: '/system/user/' + praseStrEmpty(userId),
url: '/system/user/' + parseStrEmpty(userId),
method: 'get'
})
}

View File

@ -26,7 +26,7 @@
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
<el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option>
</el-select>
</el-radio>
</el-form-item>

View File

@ -1,67 +1,84 @@
<template>
<el-image :src="`${realSrc}`" fit="cover" :style="`width:${realWidth};height:${realHeight};`" :preview-src-list="[`${realSrc}`]">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<el-image
:src="`${realSrc}`"
fit="cover"
:style="`width:${realWidth};height:${realHeight};`"
:preview-src-list="realSrcList"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
</template>
<script>
import { isExternal } from '@/utils/validate'
import { isExternal } from "@/utils/validate";
export default {
name: 'ImagePreview',
props: {
src: {
type: String,
required: true
},
width: {
type: [Number, String],
default: ''
},
height: {
type: [Number, String],
default: ''
}
name: "ImagePreview",
props: {
src: {
type: String,
required: true
},
computed: {
realSrc() {
if (isExternal(this.src)) {
return this.src
}
return process.env.VUE_APP_BASE_API + this.src
},
realWidth() {
return typeof this.width == 'string' ? this.width : `${this.width}px`
},
realHeight() {
return typeof this.height == 'string' ? this.height : `${this.height}px`
}
width: {
type: [Number, String],
default: ""
},
height: {
type: [Number, String],
default: ""
}
}
},
computed: {
realSrc() {
let real_src = this.src.split(",")[0];
if (isExternal(real_src)) {
return real_src;
}
return process.env.VUE_APP_BASE_API + real_src;
},
realSrcList() {
let real_src_list = this.src.split(",");
let srcList = [];
real_src_list.forEach(item => {
if (isExternal(item)) {
return srcList.push(item);
}
return srcList.push(process.env.VUE_APP_BASE_API + item);
});
return srcList;
},
realWidth() {
return typeof this.width == "string" ? this.width : `${this.width}px`;
},
realHeight() {
return typeof this.height == "string" ? this.height : `${this.height}px`;
}
},
};
</script>
<style lang="scss" scoped>
.el-image {
border-radius: 5px;
background-color: #ebeef5;
box-shadow: 0 0 5px 1px #ccc;
::v-deep .el-image__inner {
transition: all 0.3s;
cursor: pointer;
&:hover {
transform: scale(1.2);
}
}
::v-deep .image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
color: #909399;
font-size: 30px;
border-radius: 5px;
background-color: #ebeef5;
box-shadow: 0 0 5px 1px #ccc;
::v-deep .el-image__inner {
transition: all 0.3s;
cursor: pointer;
&:hover {
transform: scale(1.2);
}
}
::v-deep .image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
color: #909399;
font-size: 30px;
}
}
</style>

View File

@ -4,9 +4,12 @@ import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
let downloadLoadingInstance;
// 是否显示重新登录
let isReloginShow;
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 对应国际化资源文件后缀
@ -23,6 +26,8 @@ const service = axios.create({
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
@ -33,6 +38,29 @@ service.interceptors.request.use(config => {
config.params = {};
config.url = url;
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交';
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
return config
}, error => {
console.log(error)
@ -50,16 +78,25 @@ service.interceptors.response.use(res => {
return res.data
}
if (code === 401) {
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
if (!isReloginShow) {
isReloginShow = true;
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
isReloginShow = false;
store.dispatch('LogOut').then(() => {
location.href = process.env.VUE_APP_CONTEXT_PATH + "index";
// 如果是登录页面不需要重新加载
if (window.location.hash.indexOf("#/login") != 0) {
location.href = process.env.VUE_APP_CONTEXT_PATH + "index";
}
})
}).catch(() => {});
}).catch(() => {
isReloginShow = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
Message({

View File

@ -1,3 +1,5 @@
/**
* 通用js方法封装处理
* Copyright (c) 2019 ruoyi
@ -5,130 +7,133 @@
// 日期格式化
export function parseTime(time, pattern) {
if (arguments.length === 0 || !time) {
return null
}
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm),'');
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
if (arguments.length === 0 || !time) {
return null
}
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
// 表单重置
export function resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
}
// 添加日期范围
export function addDateRange(params, dateRange, propName) {
let search = params;
search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
dateRange = Array.isArray(dateRange) ? dateRange : [];
if (typeof (propName) === 'undefined') {
search.params['beginTime'] = dateRange[0];
search.params['endTime'] = dateRange[1];
} else {
search.params['begin' + propName] = dateRange[0];
search.params['end' + propName] = dateRange[1];
}
return search;
let search = params;
search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
dateRange = Array.isArray(dateRange) ? dateRange : [];
if (typeof (propName) === 'undefined') {
search.params['beginTime'] = dateRange[0];
search.params['endTime'] = dateRange[1];
} else {
search.params['begin' + propName] = dateRange[0];
search.params['end' + propName] = dateRange[1];
}
return search;
}
// 回显数据字典
export function selectDictLabel(datas, value) {
var actions = [];
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + value)) {
actions.push(datas[key].label);
return true;
}
})
return actions.join('');
var actions = [];
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + value)) {
actions.push(datas[key].label);
return true;
}
})
return actions.join('');
}
// 回显数据字典(字符串数组)
export function selectDictLabels(datas, value, separator) {
var actions = [];
var currentSeparator = undefined === separator ? "," : separator;
var temp = value.split(currentSeparator);
Object.keys(value.split(currentSeparator)).some((val) => {
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + temp[val])) {
actions.push(datas[key].label + currentSeparator);
}
})
})
return actions.join('').substring(0, actions.join('').length - 1);
if(value === undefined) {
return "";
}
var actions = [];
var currentSeparator = undefined === separator ? "," : separator;
var temp = value.split(currentSeparator);
Object.keys(value.split(currentSeparator)).some((val) => {
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + temp[val])) {
actions.push(datas[key].label + currentSeparator);
}
})
})
return actions.join('').substring(0, actions.join('').length - 1);
}
// 字符串格式化(%s )
export function sprintf(str) {
var args = arguments, flag = true, i = 1;
str = str.replace(/%s/g, function () {
var arg = args[i++];
if (typeof arg === 'undefined') {
flag = false;
return '';
}
return arg;
});
return flag ? str : '';
var args = arguments, flag = true, i = 1;
str = str.replace(/%s/g, function () {
var arg = args[i++];
if (typeof arg === 'undefined') {
flag = false;
return '';
}
return arg;
});
return flag ? str : '';
}
// 转换字符串undefined,null等转化为""
export function praseStrEmpty(str) {
if (!str || str == "undefined" || str == "null") {
return "";
}
return str;
export function parseStrEmpty(str) {
if (!str || str == "undefined" || str == "null") {
return "";
}
return str;
}
// 数据合并
export function mergeRecursive(source, target) {
for (var p in target) {
try {
if (target[p].constructor == Object) {
source[p] = mergeRecursive(source[p], target[p]);
} else {
source[p] = target[p];
}
} catch(e) {
source[p] = target[p];
}
for (var p in target) {
try {
if (target[p].constructor == Object) {
source[p] = mergeRecursive(source[p], target[p]);
} else {
source[p] = target[p];
}
} catch (e) {
source[p] = target[p];
}
return source;
}
return source;
};
/**
@ -139,47 +144,47 @@ export function mergeRecursive(source, target) {
* @param {*} children 孩子节点字段 默认 'children'
*/
export function handleTree(data, id, parentId, children) {
let config = {
id: id || 'id',
parentId: parentId || 'parentId',
childrenList: children || 'children'
};
let config = {
id: id || 'id',
parentId: parentId || 'parentId',
childrenList: children || 'children'
};
var childrenListMap = {};
var nodeIds = {};
var tree = [];
var childrenListMap = {};
var nodeIds = {};
var tree = [];
for (let d of data) {
let parentId = d[config.parentId];
if (childrenListMap[parentId] == null) {
childrenListMap[parentId] = [];
}
nodeIds[d[config.id]] = d;
childrenListMap[parentId].push(d);
}
for (let d of data) {
let parentId = d[config.parentId];
if (childrenListMap[parentId] == null) {
childrenListMap[parentId] = [];
}
nodeIds[d[config.id]] = d;
childrenListMap[parentId].push(d);
}
for (let d of data) {
let parentId = d[config.parentId];
if (nodeIds[parentId] == null) {
tree.push(d);
}
}
for (let d of data) {
let parentId = d[config.parentId];
if (nodeIds[parentId] == null) {
tree.push(d);
}
}
for (let t of tree) {
adaptToChildrenList(t);
}
for (let t of tree) {
adaptToChildrenList(t);
}
function adaptToChildrenList(o) {
if (childrenListMap[o[config.id]] !== null) {
o[config.childrenList] = childrenListMap[o[config.id]];
}
if (o[config.childrenList]) {
for (let c of o[config.childrenList]) {
adaptToChildrenList(c);
}
}
}
return tree;
function adaptToChildrenList(o) {
if (childrenListMap[o[config.id]] !== null) {
o[config.childrenList] = childrenListMap[o[config.id]];
}
if (o[config.childrenList]) {
for (let c of o[config.childrenList]) {
adaptToChildrenList(c);
}
}
}
return tree;
}
/**
@ -187,34 +192,34 @@ export function handleTree(data, id, parentId, children) {
* @param {*} params 参数
*/
export function tansParams(params) {
let result = ''
for (const propName of Object.keys(params)) {
const value = params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof (value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && typeof (value[key]) !== 'undefined') {
let params = propName + '[' + key + ']';
var subPart = encodeURIComponent(params) + "=";
result += subPart + encodeURIComponent(value[key]) + "&";
}
}
} else {
result += part + encodeURIComponent(value) + "&";
}
}
}
return result
let result = ''
for (const propName of Object.keys(params)) {
const value = params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof (value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && typeof (value[key]) !== 'undefined') {
let params = propName + '[' + key + ']';
var subPart = encodeURIComponent(params) + "=";
result += subPart + encodeURIComponent(value[key]) + "&";
}
}
} else {
result += part + encodeURIComponent(value) + "&";
}
}
}
return result
}
// 验证是否为blob格式
export async function blobValidate(data) {
try {
const text = await data.text();
JSON.parse(text);
return false;
} catch (error) {
return true;
}
try {
const text = await data.text();
JSON.parse(text);
return false;
} catch (error) {
return true;
}
}

View File

@ -495,7 +495,7 @@ export default {
//
handleNodeClick(data) {
this.queryParams.deptId = data.id;
this.getList();
this.handleQuery();
},
//
handleStatusChange(row) {

View File

@ -33,6 +33,7 @@
<el-option label="Double" value="Double" />
<el-option label="BigDecimal" value="BigDecimal" />
<el-option label="Date" value="Date" />
<el-option label="Boolean" value="Boolean" />
</el-select>
</template>
</el-table-column>