mirror of
https://github.com/yangzongzhuan/RuoYi-Vue3.git
synced 2025-11-12 21:01:55 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b8d2db756 | ||
|
|
fab5c92d26 | ||
|
|
9e7d46217a | ||
|
|
78526a4bab | ||
|
|
8552850e2c | ||
|
|
4250792a2a | ||
|
|
ab98f29c3f | ||
|
|
3535b4d67f | ||
|
|
4610953b11 | ||
|
|
1d14ade6b5 | ||
|
|
a4289fa8c3 | ||
|
|
c46abc1c79 | ||
|
|
f61979f419 | ||
|
|
0fca81b350 | ||
|
|
3286323c8c | ||
|
|
16c38acb10 | ||
|
|
ee2205d4f1 | ||
|
|
612164abde | ||
|
|
e7ad4f5048 | ||
|
|
0fd409dd58 | ||
|
|
bce42bf13c | ||
|
|
10b387ff94 | ||
|
|
d70239952c | ||
|
|
6a5e441155 | ||
|
|
1f25c95c05 | ||
|
|
d32db45e36 | ||
|
|
1aba7f61d9 |
@@ -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群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) 点击按钮入群。
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) 点击按钮入群。
|
||||
@@ -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
BIN
src/assets/images/pay.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
@@ -182,12 +182,3 @@ aside {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
//refine vue-multiselect plugin
|
||||
.multiselect {
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.multiselect--active {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#app {
|
||||
|
||||
.main-container {
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
transition: margin-left .28s;
|
||||
margin-left: $base-sidebar-width;
|
||||
position: relative;
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.fade-transform-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.fade-transform-enter {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
|
||||
@@ -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>
|
||||
|
||||
163
src/components/Editor/index.vue
Normal file
163
src/components/Editor/index.vue
Normal 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>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="icon-body">
|
||||
<el-input
|
||||
v-model="iconName"
|
||||
style="position: relative;"
|
||||
class="icon-search"
|
||||
clearable
|
||||
placeholder="请输入图标名称"
|
||||
@clear="filterIcons"
|
||||
@@ -11,9 +11,13 @@
|
||||
<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;" />
|
||||
<span>{{ item }}</span>
|
||||
<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>
|
||||
@@ -22,6 +26,12 @@
|
||||
<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 {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
.icon-list {
|
||||
height: 200px;
|
||||
overflow-y: scroll;
|
||||
div {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin-bottom: -5px;
|
||||
cursor: pointer;
|
||||
width: 33%;
|
||||
float: left;
|
||||
.icon-body {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
.icon-search {
|
||||
position: relative;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
.icon-list {
|
||||
height: 200px;
|
||||
overflow: auto;
|
||||
.list-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.icon-item-wrapper {
|
||||
width: calc(100% / 3);
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
cursor: pointer;
|
||||
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>
|
||||
@@ -121,7 +121,13 @@ function handleSelect(key, keyPath) {
|
||||
window.open(key, "_blank");
|
||||
} else if (!route || !route.children) {
|
||||
// 没有子路由路径内部打开
|
||||
router.push({ path: key });
|
||||
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 {
|
||||
// 显示左侧联动菜单
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #c0c0c0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -99,7 +99,7 @@ defineExpose({
|
||||
bottom: 0px;
|
||||
}
|
||||
:deep(.el-scrollbar__wrap) {
|
||||
height: 49px;
|
||||
height: 39px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<app-main />
|
||||
<settings ref="settingRef" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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>
|
||||
|
||||
8
src/views/monitor/cache/index.vue
vendored
8
src/views/monitor/cache/index.vue
vendored
@@ -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>
|
||||
|
||||
8
src/views/monitor/cache/list.vue
vendored
8
src/views/monitor/cache/list.vue
vendored
@@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
/** 删除按钮操作 */
|
||||
|
||||
Reference in New Issue
Block a user