27 Commits

Author SHA1 Message Date
RuoYi
7b8d2db756 若依 3.8.6 2023-06-30 08:24:18 +08:00
RuoYi
fab5c92d26 修改侧边栏的平台标题内容与process.env.VITE_APP_TITLE保持同步 2023-06-29 10:25:10 +08:00
RuoYi
9e7d46217a 添加新群号:136919097 2023-04-23 16:43:50 +08:00
RuoYi
78526a4bab 恢复翻页/切换路由滚动功能 2023-04-23 16:43:38 +08:00
RuoYi
8552850e2c DictTag组件,当value没有匹配的值时,展示value 2023-04-23 16:43:15 +08:00
RuoYi
4250792a2a 修复没有重叠的判断 2023-04-23 16:42:33 +08:00
RuoYi
ab98f29c3f 缓存列表:多次清除操作,提示不变的问题 2023-04-23 16:42:03 +08:00
RuoYi
3535b4d67f 修复开启TopNav后一级菜单路由参数设置无效问题(I6T1DK) 2023-04-11 16:52:09 +08:00
RuoYi
4610953b11 优化已选择下拉图标高亮回显 2023-04-10 18:33:56 +08:00
RuoYi
1d14ade6b5 优化避免鼠标移出时无法隐藏滚动条的问题 2023-04-10 18:33:40 +08:00
RuoYi
a4289fa8c3 添加新群号:101046199 2023-04-05 18:30:39 +08:00
RuoYi
c46abc1c79 优化固定头部页签滚动条被隐藏的问题 2023-04-05 18:30:25 +08:00
RuoYi
f61979f419 移除vue-multiselect样式 2023-04-05 18:23:43 +08:00
RuoYi
0fca81b350 关闭页签后存在其他页签时不应该跳转首页 2023-03-17 14:31:27 +08:00
RuoYi
3286323c8c 优化弹窗后导航栏偏移的问题(I3YMWW) 2023-03-17 14:24:54 +08:00
RuoYi
16c38acb10 修复页面切换时布局错乱的问题(I6LR1D) 2023-03-17 14:24:02 +08:00
RuoYi
ee2205d4f1 新增富文本组件支持 2023-03-06 14:19:40 +08:00
RuoYi
612164abde 优化文件下载出现的异常(I6DLNU) 2023-02-28 14:42:03 +08:00
RuoYi
e7ad4f5048 日志管理使用索引提升查询性能 2023-02-23 10:55:28 +08:00
RuoYi
0fd409dd58 支持登录IP黑名单限制 2023-02-21 09:02:36 +08:00
RuoYi
bce42bf13c 新增监控页面图标显示 2023-02-17 08:54:46 +08:00
RuoYi
10b387ff94 操作日志新增消耗时间属性 2023-02-16 11:05:31 +08:00
RuoYi
d70239952c 操作日志新增消耗时间属性 2023-02-16 10:23:43 +08:00
RuoYi
6a5e441155 首页页签右键选择时不显示关闭左侧 2023-02-04 22:40:20 +08:00
RuoYi
1f25c95c05 update copyright 2023 2023-02-04 22:33:47 +08:00
RuoYi
d32db45e36 重置时取消部门选中 2023-01-19 11:08:57 +08:00
RuoYi
1aba7f61d9 添加新群号:108482800 2023-01-11 12:55:12 +08:00
33 changed files with 408 additions and 121 deletions

View File

@@ -1,11 +1,11 @@
<p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.5</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.6</h1>
<h4 align="center">基于SpringBoot+Vue3前后端分离的Java快速开发框架</h4>
<p align="center">
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.5-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.6-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p>
@@ -106,4 +106,4 @@ yarn dev
## 若依前后端分离交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) 点击按钮入群。
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/已满-170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [![加入QQ群](https://img.shields.io/badge/已满-108482800-blue.svg)](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [![加入QQ群](https://img.shields.io/badge/已满-101046199-blue.svg)](https://jq.qq.com/?_wv=1027&k=SpyH2875) [![加入QQ群](https://img.shields.io/badge/136919097-blue.svg)](https://jq.qq.com/?_wv=1027&k=tKEt51dz) 点击按钮入群。

View File

@@ -1,6 +1,6 @@
{
"name": "ruoyi",
"version": "3.8.5",
"version": "3.8.6",
"description": "若依管理系统",
"author": "若依",
"license": "MIT",
@@ -16,6 +16,7 @@
},
"dependencies": {
"@element-plus/icons-vue": "2.0.10",
"@vueup/vue-quill": "1.1.0",
"@vueuse/core": "9.5.0",
"axios": "0.27.2",
"echarts": "5.4.0",

BIN
src/assets/images/pay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

View File

@@ -182,12 +182,3 @@ aside {
margin-bottom: 10px;
}
}
//refine vue-multiselect plugin
.multiselect {
line-height: 16px;
}
.multiselect--active {
z-index: 1000 !important;
}

View File

@@ -1,7 +1,7 @@
#app {
.main-container {
min-height: 100%;
height: 100%;
transition: margin-left .28s;
margin-left: $base-sidebar-width;
position: relative;

View File

@@ -18,10 +18,6 @@
transition: all .5s;
}
.fade-transform-leave-active {
position: absolute;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);

View File

@@ -7,7 +7,8 @@
:key="item.value"
:index="index"
:class="item.elTagClass"
>{{ item.label }}</span>
>{{ item.label + " " }}</span
>
<el-tag
v-else
:disable-transitions="true"
@@ -15,13 +16,20 @@
:index="index"
:type="item.elTagType === 'primary' ? '' : item.elTagType"
:class="item.elTagClass"
>{{ item.label }}</el-tag>
>{{ item.label + " " }}</el-tag
>
</template>
</template>
<template v-if="unmatch && showValue">
{{ unmatchArray | handleArray }}
</template>
</div>
</template>
<script setup>
// // 记录未匹配的项
const unmatchArray = ref([]);
const props = defineProps({
// 数据
options: {
@@ -30,16 +38,47 @@ const props = defineProps({
},
// 当前的值
value: [Number, String, Array],
})
// 当未找到匹配的数据时显示value
showValue: {
type: Boolean,
default: true,
},
});
const values = computed(() => {
if (props.value !== null && typeof props.value !== 'undefined') {
if (props.value !== null && typeof props.value !== "undefined") {
return Array.isArray(props.value) ? props.value : [String(props.value)];
} else {
return [];
}
})
});
const unmatch = computed(() => {
unmatchArray.value = [];
if (props.value !== null && typeof props.value !== "undefined") {
// 传入值为非数组
if (!Array.isArray(props.value)) {
if (props.options.some((v) => v.value == props.value)) return false;
unmatchArray.value.push(props.value);
return true;
}
// 传入值为Array
props.value.forEach((item) => {
if (!props.options.some((v) => v.value == item))
unmatchArray.value.push(item);
});
return true;
}
// 没有value不显示
return false;
});
function handleArray(array) {
if (array.length === 0) return "";
return array.reduce((pre, cur) => {
return pre + " " + cur;
});
}
</script>
<style scoped>

View File

@@ -0,0 +1,163 @@
<template>
<div class="editor">
<quill-editor
v-model:content="content"
contentType="html"
@textChange="(e) => $emit('update:modelValue', content)"
:options="options"
:style="styles"
/>
</div>
</template>
<script setup>
import { QuillEditor } from '@vueup/vue-quill';
import '@vueup/vue-quill/dist/vue-quill.snow.css';
const props = defineProps({
/* 编辑器的内容 */
modelValue: {
type: String,
},
/* 高度 */
height: {
type: Number,
default: null,
},
/* 最小高度 */
minHeight: {
type: Number,
default: null,
},
/* 只读 */
readOnly: {
type: Boolean,
default: false,
},
});
const options = ref({
theme: "snow",
bounds: document.body,
debug: "warn",
modules: {
// 工具栏配置
toolbar: [
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
["blockquote", "code-block"], // 引用 代码块
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
[{ indent: "-1" }, { indent: "+1" }], // 缩进
[{ size: ["small", false, "large", "huge"] }], // 字体大小
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
[{ align: [] }], // 对齐方式
["clean"], // 清除文本格式
["link", "image", "video"] // 链接、图片、视频
],
},
placeholder: '请输入内容',
readOnly: props.readOnly,
theme: 'snow'
});
const styles = computed(() => {
let style = {};
if (props.minHeight) {
style.minHeight = `${props.minHeight}px`;
}
if (props.height) {
style.height = `${props.height}px`;
}
return style;
})
const content = ref("");
watch(() => props.modelValue, (v) => {
if (v !== content.value) {
content.value = v === undefined ? "<p></p>" : v;
}
}, { immediate: true });
</script>
<style>
.editor, .ql-toolbar {
white-space: pre-wrap !important;
line-height: normal !important;
}
.quill-img {
display: none;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.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 {
content: "10px";
}
.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 {
content: "18px";
}
.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 {
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.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 {
content: "标题1";
}
.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 {
content: "标题2";
}
.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 {
content: "标题3";
}
.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 {
content: "标题4";
}
.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 {
content: "标题5";
}
.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 {
content: "标题6";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体";
}
.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 {
content: "衬线字体";
}
.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 {
content: "等宽字体";
}
</style>

View File

@@ -2,7 +2,7 @@
<div class="icon-body">
<el-input
v-model="iconName"
style="position: relative;"
class="icon-search"
clearable
placeholder="请输入图标名称"
@clear="filterIcons"
@@ -11,17 +11,27 @@
<template #suffix><i class="el-icon-search el-input__icon" /></template>
</el-input>
<div class="icon-list">
<div v-for="(item, index) in iconList" :key="index" @click="selectedIcon(item)">
<svg-icon :icon-class="item" style="height: 30px;width: 16px;" />
<div class="list-container">
<div v-for="(item, index) in iconList" class="icon-item-wrapper" :key="index" @click="selectedIcon(item)">
<div :class="['icon-item', { active: activeIcon === item }]">
<svg-icon :icon-class="item" class-name="icon" style="height: 25px;width: 16px;"/>
<span>{{ item }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import icons from './requireIcons'
const props = defineProps({
activeIcon: {
type: String
}
});
const iconName = ref('');
const iconList = ref(icons);
const emit = defineEmits(['selected']);
@@ -49,26 +59,53 @@ defineExpose({
</script>
<style lang='scss' scoped>
.icon-body {
.icon-body {
width: 100%;
padding: 10px;
.icon-search {
position: relative;
margin-bottom: 5px;
}
.icon-list {
height: 200px;
overflow-y: scroll;
div {
height: 30px;
line-height: 30px;
margin-bottom: -5px;
overflow: auto;
.list-container {
display: flex;
flex-wrap: wrap;
.icon-item-wrapper {
width: calc(100% / 3);
height: 25px;
line-height: 25px;
cursor: pointer;
width: 33%;
float: left;
display: flex;
.icon-item {
display: flex;
max-width: 100%;
height: 100%;
padding: 0 5px;
&:hover {
background: #ececec;
border-radius: 5px;
}
.icon {
flex-shrink: 0;
}
span {
display: inline-block;
vertical-align: -0.15em;
fill: currentColor;
padding-left: 2px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.icon-item.active {
background: #ececec;
border-radius: 5px;
}
}
}
}
}
}
</style>

View File

@@ -121,7 +121,13 @@ function handleSelect(key, keyPath) {
window.open(key, "_blank");
} else if (!route || !route.children) {
// 没有子路由路径内部打开
const routeMenu = childrenMenus.value.find(item => item.path === key);
if (routeMenu && routeMenu.query) {
let query = JSON.parse(routeMenu.query);
router.push({ path: key, query: query });
} else {
router.push({ path: key });
}
appStore.toggleSideBarHide(true);
} else {
// 显示左侧联动菜单

View File

@@ -47,7 +47,22 @@ const tagsViewStore = useTagsViewStore()
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 17px;
padding-right: 6px;
}
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background-color: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background-color: #c0c0c0;
border-radius: 3px;
}
</style>

View File

@@ -25,7 +25,7 @@ defineProps({
}
})
const title = ref('若依管理系统');
const title = import.meta.env.VITE_APP_TITLE;
const settingsStore = useSettingsStore();
const sideTheme = computed(() => settingsStore.sideTheme);
</script>

View File

@@ -99,7 +99,7 @@ defineExpose({
bottom: 0px;
}
:deep(.el-scrollbar__wrap) {
height: 49px;
height: 39px;
}
}
</style>

View File

@@ -94,7 +94,7 @@ function isAffix(tag) {
}
function isFirstView() {
try {
return selectedTag.value.fullPath === visitedViews.value[1].fullPath || selectedTag.value.fullPath === '/index'
return selectedTag.value.fullPath === '/index' || selectedTag.value.fullPath === visitedViews.value[1].fullPath
} catch (err) {
return false
}

View File

@@ -12,7 +12,6 @@ import store from './store'
import router from './router'
import directive from './directive' // directive
// 注册指令
import plugins from './plugins' // plugins
import { download } from '@/utils/request'
@@ -31,6 +30,8 @@ import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, select
import Pagination from '@/components/Pagination'
// 自定义表格工具组件
import RightToolbar from '@/components/RightToolbar'
// 富文本组件
import Editor from "@/components/Editor"
// 文件上传组件
import FileUpload from "@/components/FileUpload"
// 图片上传组件
@@ -62,6 +63,7 @@ app.component('FileUpload', FileUpload)
app.component('ImageUpload', ImageUpload)
app.component('ImagePreview', ImagePreview)
app.component('RightToolbar', RightToolbar)
app.component('Editor', Editor)
app.use(router)
app.use(store)

View File

@@ -11,7 +11,7 @@ import usePermissionStore from '@/store/modules/permission'
NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/auth-redirect', '/bind', '/register'];
const whiteList = ['/login', '/register'];
router.beforeEach((to, from, next) => {
NProgress.start()

View File

@@ -15,9 +15,9 @@ export default {
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then(async (res) => {
const isLogin = await blobValidate(res.data);
if (isLogin) {
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data])
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
} else {
@@ -32,9 +32,9 @@ export default {
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then(async (res) => {
const isLogin = await blobValidate(res.data);
if (isLogin) {
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data])
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
} else {
@@ -49,9 +49,9 @@ export default {
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then(async (res) => {
const isLogin = await blobValidate(res.data);
if (isLogin) {
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data], { type: 'application/zip' })
this.saveAs(blob, name)
} else {

View File

@@ -32,8 +32,12 @@ export default {
// 关闭指定tab页签
closePage(obj) {
if (obj === undefined) {
return useTagsViewStore().delView(router.currentRoute.value).then(({ lastPath }) => {
return router.push(lastPath || '/index');
return useTagsViewStore().delView(router.currentRoute.value).then(({ visitedViews }) => {
const latestView = visitedViews.slice(-1)[0]
if (latestView) {
return router.push(latestView.fullPath)
}
return router.push('/');
});
}
return useTagsViewStore().delView(obj);

View File

@@ -72,7 +72,7 @@ service.interceptors.response.use(res => {
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
@@ -125,8 +125,8 @@ export function download(url, params, filename, config) {
responseType: 'blob',
...config
}).then(async (data) => {
const isLogin = await blobValidate(data);
if (isLogin) {
const isBlob = blobValidate(data);
if (isBlob) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {

View File

@@ -241,12 +241,6 @@ export function getNormalPath(p) {
}
// 验证是否为blob格式
export async function blobValidate(data) {
try {
const text = await data.text();
JSON.parse(text);
return false;
} catch (error) {
return true;
}
export function blobValidate(data) {
return data.type !== 'application/json'
}

View File

@@ -118,12 +118,11 @@
>
</p>
<p>
<i class="el-icon-user-solid"></i> QQ群<s>满937441</s> <s>满887144332</s>
<s>满180251782</s> <s>满104180207</s> <s>满186866453</s> <s>满201396349</s>
<s>满101456076</s> <s>满101539465</s> <s>满264312783</s> <s>满167385320</s>
<s>满104748341</s> <s>满160110482</s> <a href="https://jq.qq.com/?_wv=1027&k=Xnbinl0U" target="_blank">
170801498</a
>
<i class="el-icon-user-solid"></i> QQ群<s> 满937441 </s> <s> 满887144332 </s>
<s> 满180251782 </s> <s> 满104180207 </s> <s> 满186866453 </s> <s> 满201396349 </s>
<s> 满101456076 </s> <s> 满101539465 </s> <s> 满264312783 </s> <s> 满167385320 </s>
<s> 满104748341 </s> <s> 满160110482 </s> <s> 满170801498 </s> <s> 满108482800 </s>
<s> 满101046199 </s> <a href="https://jq.qq.com/?_wv=1027&k=tKEt51dz" target="_blank">136919097</a>
</p>
<p>
<i class="el-icon-chat-dot-round"></i> 微信<a
@@ -149,6 +148,44 @@
</div>
</template>
<el-collapse accordion>
<el-collapse-item title="v3.8.6 - 2023-06-30">
<ol>
<li>支持登录IP黑名单限制</li>
<li>新增监控页面图标显示</li>
<li>操作日志新增消耗时间属性</li>
<li>屏蔽定时任务bean违规的字符</li>
<li>日志管理使用索引提升查询性能</li>
<li>日志注解支持排除指定的请求参数</li>
<li>支持自定义隐藏属性列过滤子对象</li>
<li>升级oshi到最新版本6.4.3</li>
<li>升级druid到最新版本1.2.16</li>
<li>升级fastjson到最新版2.0.34</li>
<li>升级spring-boot到最新版本2.5.15</li>
<li>升级element-ui到最新版本2.15.13</li>
<li>移除apache/commons-fileupload依赖</li>
<li>修复页面切换时布局错乱的问题</li>
<li>修复匿名注解Anonymous空指针问题</li>
<li>修复路由跳转被阻止时内部产生报错信息问题</li>
<li>修复isMatchedIp的参数判断产生空指针的问题</li>
<li>修复用户多角色数据权限可能出现权限抬升的情况</li>
<li>修复开启TopNav后一级菜单路由参数设置无效问题</li>
<li>修复DictTag组件value没有匹配的值时则展示value</li>
<li>优化文件下载出现的异常</li>
<li>优化选择图标组件高亮回显</li>
<li>优化弹窗后导航栏偏移的问题</li>
<li>优化修改密码日志存储明文问题</li>
<li>优化页签栏关闭其他出现的异常问题</li>
<li>优化页签关闭左侧选项排除首页选项</li>
<li>优化关闭当前tab页跳转最右侧tab页</li>
<li>优化缓存列表清除操作提示不变的问题</li>
<li>优化字符未使用下划线不进行驼峰式处理</li>
<li>优化用户导入更新时需获取用户编号问题</li>
<li>优化侧边栏的平台标题与VUE_APP_TITLE保持同步</li>
<li>优化导出Excel时设置dictType属性重复查缓存问题</li>
<li>连接池Druid支持新的配置connectTimeout和socketTimeout</li>
<li>其他细节优化</li>
</ol>
</el-collapse-item>
<el-collapse-item title="v3.8.5 - 2023-01-01">
<ol>
<li>定时任务违规的字符</li>
@@ -893,7 +930,7 @@
</template>
<div class="body">
<img
src="https://oscimg.oschina.net/oscnet/up-d6695f82666e5018f715c41cb7ee60d3b73.png"
src="@/assets/images/pay.png"
alt="donate"
style="width:100%"
/>
@@ -908,7 +945,7 @@
</template>
<script setup name="Index">
const version = ref('3.8.5')
const version = ref('3.8.6')
function goTarget(url) {
window.open(url, '__blank')

View File

@@ -59,7 +59,7 @@
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span>
</div>
</div>
</template>

View File

@@ -3,7 +3,7 @@
<el-row>
<el-col :span="24" class="card-box">
<el-card>
<template #header><span>基本信息</span></template>
<template #header><Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">基本信息</span></template>
<div class="el-table el-table--enable-row-hover el-table--medium">
<table cellspacing="0" style="width: 100%">
<tbody>
@@ -45,7 +45,7 @@
<el-col :span="12" class="card-box">
<el-card>
<template #header><span>命令统计</span></template>
<template #header><PieChart style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">命令统计</span></template>
<div class="el-table el-table--enable-row-hover el-table--medium">
<div ref="commandstats" style="height: 420px" />
</div>
@@ -54,9 +54,7 @@
<el-col :span="12" class="card-box">
<el-card>
<template #header>
<span>内存信息</span>
</template>
<template #header><Odometer style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">内存信息</span></template>
<div class="el-table el-table--enable-row-hover el-table--medium">
<div ref="usedmemory" style="height: 420px" />
</div>

View File

@@ -4,7 +4,7 @@
<el-col :span="8">
<el-card style="height: calc(100vh - 125px)">
<template #header>
<span>缓存列表</span>
<Collection style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">缓存列表</span>
<el-button
style="float: right; padding: 3px 0"
link
@@ -63,7 +63,7 @@
<el-col :span="8">
<el-card style="height: calc(100vh - 125px)">
<template #header>
<span>键名列表</span>
<Key style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">键名列表</span>
<el-button
style="float: right; padding: 3px 0"
link
@@ -114,7 +114,7 @@
<el-col :span="8">
<el-card :bordered="false" style="height: calc(100vh - 125px)">
<template #header>
<span>缓存内容</span>
<Document style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">缓存内容</span>
<el-button
style="float: right; padding: 3px 0"
link
@@ -185,7 +185,7 @@ function refreshCacheNames() {
/** 清理指定名称缓存 */
function handleClearCacheName(row) {
clearCacheName(row.cacheName).then(response => {
proxy.$modal.msgSuccess("清理缓存名称[" + nowCacheName.value + "]成功");
proxy.$modal.msgSuccess("清理缓存名称[" + row.cacheName + "]成功");
getCacheKeys();
});
}

View File

@@ -37,11 +37,12 @@
<el-form-item label="登录时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
></el-date-picker>
</el-form-item>
<el-form-item>
@@ -105,7 +106,7 @@
<dict-tag :options="sys_common_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="描述" align="center" prop="msg" />
<el-table-column label="描述" align="center" prop="msg" :show-overflow-tooltip="true" />
<el-table-column label="访问时间" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.loginTime) }}</span>

View File

@@ -52,11 +52,12 @@
<el-form-item label="操作时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
></el-date-picker>
</el-form-item>
<el-form-item>
@@ -98,27 +99,31 @@
</el-row>
<el-table ref="operlogRef" v-loading="loading" :data="operlogList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="日志编号" align="center" prop="operId" />
<el-table-column label="系统模块" align="center" prop="title" />
<el-table-column label="系统模块" align="center" prop="title" :show-overflow-tooltip="true" />
<el-table-column label="操作类型" align="center" prop="businessType">
<template #default="scope">
<dict-tag :options="sys_oper_type" :value="scope.row.businessType" />
</template>
</el-table-column>
<el-table-column label="请求方式" align="center" prop="requestMethod" />
<el-table-column label="操作人员" align="center" prop="operName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" width="100" />
<el-table-column label="操作人员" align="center" width="110" prop="operName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
<el-table-column label="主机" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
<el-table-column label="操作状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_common_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作日期" align="center" prop="operTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
<el-table-column label="操作日期" align="center" prop="operTime" width="180" sortable="custom" :sort-orders="['descending', 'ascending']">
<template #default="scope">
<span>{{ parseTime(scope.row.operTime) }}</span>
</template>
</el-table-column>
<el-table-column label="消耗时间" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']">
<template #default="scope">
<span>{{ scope.row.costTime }}毫秒</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="View" @click="handleView(scope.row, scope.index)" v-hasPermi="['monitor:operlog:query']">详细</el-button>
@@ -157,13 +162,16 @@
<el-col :span="24">
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="6">
<el-form-item label="操作状态:">
<div v-if="form.status === 0">正常</div>
<div v-else-if="form.status === 1">失败</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="8">
<el-form-item label="消耗时间:">{{ form.costTime }}毫秒</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
</el-col>
<el-col :span="24">

View File

@@ -3,7 +3,7 @@
<el-row>
<el-col :span="12" class="card-box">
<el-card>
<template #header><span>CPU</span></template>
<template #header><Cpu style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">CPU</span></template>
<div class="el-table el-table--enable-row-hover el-table--medium">
<table cellspacing="0" style="width: 100%;">
<thead>
@@ -37,7 +37,7 @@
<el-col :span="12" class="card-box">
<el-card>
<template #header><span>内存</span></template>
<template #header><Tickets style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">内存</span></template>
<div class="el-table el-table--enable-row-hover el-table--medium">
<table cellspacing="0" style="width: 100%;">
<thead>
@@ -76,7 +76,7 @@
<el-col :span="24" class="card-box">
<el-card>
<template #header><span>服务器信息</span></template>
<template #header><Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">服务器信息</span></template>
<div class="el-table el-table--enable-row-hover el-table--medium">
<table cellspacing="0" style="width: 100%;">
<tbody>
@@ -100,7 +100,7 @@
<el-col :span="24" class="card-box">
<el-card>
<template #header><span>Java虚拟机信息</span></template>
<template #header><CoffeeCup style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">Java虚拟机信息</span></template>
<div class="el-table el-table--enable-row-hover el-table--medium">
<table cellspacing="0" style="width: 100%;table-layout:fixed;">
<tbody>
@@ -136,7 +136,7 @@
<el-col :span="24" class="card-box">
<el-card>
<template #header><span>磁盘状态</span></template>
<template #header><MessageBox style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">磁盘状态</span></template>
<div class="el-table el-table--enable-row-hover el-table--medium">
<table cellspacing="0" style="width: 100%;">
<thead>

View File

@@ -70,7 +70,7 @@
</el-form>
<!-- 底部 -->
<div class="el-register-footer">
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span>
</div>
</div>
</template>

View File

@@ -101,7 +101,7 @@
<el-table-column label="参数主键" align="center" prop="configId" />
<el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" />
<el-table-column label="参数键名" align="center" prop="configKey" :show-overflow-tooltip="true" />
<el-table-column label="参数键值" align="center" prop="configValue" />
<el-table-column label="参数键值" align="center" prop="configValue" :show-overflow-tooltip="true" />
<el-table-column label="系统内置" align="center" prop="configType">
<template #default="scope">
<dict-tag :options="sys_yes_no" :value="scope.row.configType" />

View File

@@ -130,7 +130,7 @@
</template>
</el-input>
</template>
<icon-select ref="iconSelectRef" @selected="selected" />
<icon-select ref="iconSelectRef" @selected="selected" :active-icon="form.icon" />
</el-popover>
</el-form-item>
</el-col>

View File

@@ -143,12 +143,7 @@
</el-col>
<el-col :span="24">
<el-form-item label="内容">
<el-input
:rows="6"
type="textarea"
placeholder="请输入内容"
v-model="form.noticeContent"
/>
<editor v-model="form.noticeContent" :min-height="192"/>
</el-form-item>
</el-col>
</el-row>

View File

@@ -438,7 +438,7 @@ function resetQuery() {
dateRange.value = [];
proxy.resetForm("queryRef");
queryParams.value.deptId = undefined;
proxy.$refs.tree.setCurrentKey(null);
proxy.$refs.deptTreeRef.setCurrentKey(null);
handleQuery();
};
/** 删除按钮操作 */