发布 v3.3.0

This commit is contained in:
疯狂的狮子li
2021-10-29 09:18:18 +08:00
parent 6def4aa84d
commit 4d12424378
426 changed files with 43788 additions and 4704 deletions

View File

@ -10,5 +10,8 @@ VUE_APP_BASE_API = '/dev-api'
# 监控地址
VUE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/login'
# xxl-job 控制台地址
VUE_APP_XXL_JOB_ADMIN = 'http://localhost:9100/xxl-job-admin'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -7,5 +7,8 @@ ENV = 'production'
# 监控地址
VUE_APP_MONITRO_ADMIN = '/admin/login'
# 监控地址
VUE_APP_XXL_JOB_ADMIN = '/xxl-job-admin'
# 若依管理系统/生产环境
VUE_APP_BASE_API = '/prod-api'

View File

@ -9,5 +9,8 @@ ENV = 'staging'
# 监控地址
VUE_APP_MONITRO_ADMIN = '/admin/login'
# 监控地址
VUE_APP_XXL_JOB_ADMIN = '/xxl-job-admin'
# 若依管理系统/测试环境
VUE_APP_BASE_API = '/stage-api'

View File

@ -1,6 +1,6 @@
{
"name": "ruoyi-vue-plus",
"version": "3.2.0",
"version": "3.3.0",
"description": "RuoYi-Vue-Plus后台管理系统",
"author": "LionLi",
"license": "MIT",
@ -41,7 +41,7 @@
"clipboard": "2.0.6",
"core-js": "3.8.1",
"echarts": "4.9.0",
"element-ui": "2.15.5",
"element-ui": "2.15.6",
"file-saver": "2.0.5",
"fuse.js": "6.4.3",
"highlight.js": "9.18.5",

View File

@ -148,7 +148,7 @@ export default {
handleUploadSuccess(res, file) {
if (res.code === 200) {
this.$message.success("上传成功");
this.fileList.push({ name: res.data.fileName, url: res.data.fileName });
this.fileList.push({ name: res.data.fileName, url: res.data.url });
this.$emit("input", this.listToString(this.fileList));
} else {
this.$message.error(res.msg);

View File

@ -56,7 +56,6 @@ import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch'
import RuoYiGit from '@/components/RuoYi/Git'
import RuoYiDoc from '@/components/RuoYi/Doc'
import config from '@/../vue.config'
export default {
components: {
@ -103,7 +102,7 @@ export default {
type: 'warning'
}).then(() => {
this.$store.dispatch('LogOut').then(() => {
location.href = config.publicPath + 'index';
location.href = this.$router.options.base + '/index';
})
}).catch(() => {});
}

View File

@ -162,7 +162,7 @@ export default {
this.sideTheme = val;
},
saveSetting() {
this.$modal.loading("正在保存到本地,请稍...");
this.$modal.loading("正在保存到本地,请稍...");
this.$cache.local.set(
"layout-setting",
`{
@ -178,7 +178,7 @@ export default {
setTimeout(this.$modal.closeLoading(), 1000)
},
resetSetting() {
this.$modal.loading("正在清除设置缓存并刷新,请稍...");
this.$modal.loading("正在清除设置缓存并刷新,请稍...");
this.$cache.local.remove("layout-setting")
setTimeout("window.location.reload()", 1000)
}

View File

@ -0,0 +1,60 @@
import store from '@/store'
function authPermission(permission) {
const all_permission = "*:*:*";
const permissions = store.getters && store.getters.permissions
if (permission && permission.length > 0) {
return permissions.some(v => {
return all_permission === v || v === permission
})
} else {
return false
}
}
function authRole(role) {
const super_admin = "admin";
const roles = store.getters && store.getters.roles
if (role && role.length > 0) {
return roles.some(v => {
return super_admin === v || v === role
})
} else {
return false
}
}
export default {
// 验证用户是否具备某权限
hasPermi(permission) {
return authPermission(permission);
},
// 验证用户是否含有指定权限,只需包含其中一个
hasPermiOr(permissions) {
return permissions.some(item => {
return authPermission(item)
})
},
// 验证用户是否含有指定权限,必须全部拥有
hasPermiAnd(permissions) {
return permissions.every(item => {
return authPermission(item)
})
},
// 验证用户是否具备某角色
hasRole(role) {
return authRole(role);
},
// 验证用户是否含有指定角色,只需包含其中一个
hasRoleOr(roles) {
return roles.some(item => {
return authRole(item)
})
},
// 验证用户是否含有指定角色,必须全部拥有
hasRoleAnd(roles) {
return roles.every(item => {
return authRole(item)
})
}
}

View File

@ -1,6 +1,7 @@
import { saveAs } from 'file-saver'
import axios from 'axios'
import { getToken } from '@/utils/auth'
import { Message } from 'element-ui'
const baseURL = process.env.VUE_APP_BASE_API
@ -35,9 +36,14 @@ export default {
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then(res => {
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
this.saveAs(blob, decodeURI(res.headers['download-filename']))
}).then(async (res) => {
const isLogin = await this.blobValidate(res.data);
if (isLogin) {
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
this.saveAs(blob, decodeURI(res.headers['download-filename']))
} else {
Message.error('无效的会话,或者会话已过期,请重新登录。');
}
})
},
oss(ossId) {
@ -47,9 +53,14 @@ export default {
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then(res => {
const blob = new Blob([res.data], { type: 'application/octet-stream' })
this.saveAs(blob, decodeURI(res.headers['download-filename']))
}).then(async (res) => {
const isLogin = await this.blobValidate(res.data);
if (isLogin) {
const blob = new Blob([res.data], { type: 'application/octet-stream' })
this.saveAs(blob, decodeURI(res.headers['download-filename']))
} else {
Message.error('无效的会话,或者会话已过期,请重新登录。');
}
})
},
zip(url, name) {
@ -59,13 +70,27 @@ export default {
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then(res => {
const blob = new Blob([res.data], { type: 'application/zip' })
this.saveAs(blob, name)
}).then(async (res) => {
const isLogin = await this.blobValidate(res.data);
if (isLogin) {
const blob = new Blob([res.data], { type: 'application/zip' })
this.saveAs(blob, name)
} else {
Message.error('无效的会话,或者会话已过期,请重新登录。');
}
})
},
saveAs(text, name, opts) {
saveAs(text, name, opts);
}
},
async blobValidate(data) {
try {
const text = await data.text();
JSON.parse(text);
return false;
} catch (error) {
return true;
}
},
}

View File

@ -1,9 +1,12 @@
import auth from './auth'
import cache from './cache'
import modal from './modal'
import download from './download'
export default {
install(Vue) {
// 认证对象
Vue.prototype.$auth = auth
// 缓存对象
Vue.prototype.$cache = cache
// 模态框对象

View File

@ -167,6 +167,7 @@ export const constantRoutes = [
]
export default new Router({
base: "", // 项目前缀 与 publicPath 同步 例如 /api
mode: 'history', // 去掉url中的#
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes

View File

@ -86,7 +86,7 @@ function filterChildren(childrenMap, lastRouter = false) {
var children = []
childrenMap.forEach((el, index) => {
if (el.children && el.children.length) {
if (el.component === 'ParentView') {
if (el.component === 'ParentView' && !lastRouter) {
el.children.forEach(c => {
c.path = el.path + '/' + c.path
if (c.children && c.children.length) {
@ -106,8 +106,13 @@ function filterChildren(childrenMap, lastRouter = false) {
return children
}
export const loadView = (view) => { // 路由懒加载
return (resolve) => require([`@/views/${view}`], resolve)
export const loadView = (view) => {
if (process.env.NODE_ENV === 'development') {
return (resolve) => require([`@/views/${view}`], resolve)
} else {
// 使用 import 实现生产环境的路由懒加载
return () => import(`@/views/${view}`)
}
}
export default permission

View File

@ -5,6 +5,8 @@ import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 对应国际化资源文件后缀
axios.defaults.headers['Content-Language'] = 'zh_CN'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
@ -63,7 +65,7 @@ service.interceptors.response.use(res => {
}
).then(() => {
store.dispatch('LogOut').then(() => {
location.href = '/index';
location.href = this.$router.options.base + '/index';
})
}).catch(() => {});
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')

View File

@ -93,6 +93,48 @@
<span>更新日志</span>
</div>
<el-collapse accordion>
<el-collapse-item title="v3.3.0 - 2021-10-29">
<ol>
<li>add [重磅更新] 增加分布式日志框架 TLog</li>
<li>add [重磅更新] 增加分布式任务调度系统 Xxl-Job</li>
<li>add [重大更新] 增加 ruoyi-job 任务调度模块(基于xxl-job)</li>
<li>update [重大更新]全业务 增加 接口文档注解 格式化代码</li>
<li>update springboot 2.5.5 => 2.5.6</li>
<li>update springboot-admin 2.5.1 => 2.5.2</li>
<li>update element-ui 2.15.5 => 2.15.6</li>
<li>update hutool 5.7.13 => 5.7.15</li>
<li>update qcloud.cos 5.6.55 => 5.6.58</li>
<li>update minio 8.3.0 => 8.3.3</li>
<li>update 更新 element 2.15.6 表格样式</li>
<li>update 优化 代码生成常量 关于 BO VO 注释</li>
<li>update 优化代码生成 导入表 列表返回 主键默认选中</li>
<li>update MybatisPlusRedisCache 标记过期 推荐使用 spring-cache</li>
<li>update Quartz 标记过期 推荐迁移至新框架 xxl-job</li>
<li>update Feign 标记过期</li>
<li>update 前端增加默认国际化参数</li>
<li>update 更新 Admin 监控 注释 避免错误使用</li>
<li>update Admin 监控增加日志文件输出</li>
<li>update 优化 xxl-job-admin 增加格式化日志输出与 docker 镜像</li>
<li>update 更新 xxl-job 执行器开关功能</li>
<li>update 代码生成 改为生成抽象实体</li>
<li>update 代码生成 搜索框 更新文本域生成 用于模糊查询</li>
<li>update 通用数据注入改为适配通用实体类</li>
<li>update 使用路由懒加载提升页面响应速度</li>
<li>update 迁移所有脚本文件至 script 目录</li>
<li>update swagger 组顺序配置</li>
<li>update sql 文件更新 xxljob 控制台菜单</li>
<li>update 前端增加 任务调度中心页面与环境及 nginx 配置</li>
<li>update 合并 oss.sql 至主 sql</li>
<li>update 补全国际化文件(英文)</li>
<li>update 更新关于全局路径设置与文档链接</li>
<li>update 删除无用 setUsername 使用自动注入</li>
<li>update RedisUtils 更新删除 hash 数据方法</li>
<li>fix 修复 多数据源 aop 语法错误</li>
<li>fix 修复 子菜单无 query 参数问题</li>
<li>fix 修复 oss 配置删除时删除缓存 bug</li>
<li>fix 修复无权限获取请求头 download-filename 导致文件名为空问题</li>
</ol>
</el-collapse-item>
<el-collapse-item title="v3.2.0 - 2021-9-28">
<ol>
<li>update [重大改动]接口文档 支持分组配置</li>
@ -478,14 +520,12 @@
</template>
<script>
import config from '@/../package.json'
export default {
name: "Index",
data() {
return {
// 版本号
version: config.version,
version: "3.3.0",
};
},
methods: {

View File

@ -8,34 +8,34 @@
<table cellspacing="0" style="width: 100%">
<tbody>
<tr>
<td><div class="cell">Redis版本</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td>
<td><div class="cell">运行模式</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.redis_mode == "standalone" ? "单机" : "集群" }}</div></td>
<td><div class="cell">端口</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td>
<td><div class="cell">客户端数</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">Redis版本</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">运行模式</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_mode == "standalone" ? "单机" : "集群" }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">端口</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">客户端数</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td>
</tr>
<tr>
<td><div class="cell">运行时间()</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td>
<td><div class="cell">使用内存</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td>
<td><div class="cell">使用CPU</div></td>
<td><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td>
<td><div class="cell">内存配置</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">运行时间()</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">使用内存</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">使用CPU</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">内存配置</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td>
</tr>
<tr>
<td><div class="cell">AOF是否开启</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled == "0" ? "否" : "是" }}</div></td>
<td><div class="cell">RDB是否成功</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td>
<td><div class="cell">Key数量</div></td>
<td><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td>
<td><div class="cell">网络入口/出口</div></td>
<td><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td>
<td class="el-table__cell is-leaf"><div class="cell">AOF是否开启</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled == "0" ? "否" : "是" }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">RDB是否成功</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td>
<td class="el-table__cell is-leaf"><div class="cell">Key数量</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td>
<td class="el-table__cell is-leaf"><div class="cell">网络入口/出口</div></td>
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td>
</tr>
</tbody>
</table>
@ -139,7 +139,7 @@ export default {
},
// 打开加载层
openLoading() {
this.$modal.loading("正在加载缓存监控数据,请稍");
this.$modal.loading("正在加载缓存监控数据,请稍");
},
},
};

View File

@ -0,0 +1,15 @@
<template>
<i-frame :src="url" />
</template>
<script>
import iFrame from "@/components/iFrame/index";
export default {
name: "XxlJob",
components: { iFrame },
data() {
return {
url: process.env.VUE_APP_XXL_JOB_ADMIN
};
},
};
</script>

View File

@ -200,7 +200,7 @@
ref="menu"
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中请稍"
empty-text="加载中请稍"
:props="defaultProps"
></el-tree>
</el-form-item>
@ -245,7 +245,7 @@
ref="dept"
node-key="id"
:check-strictly="!form.deptCheckStrictly"
empty-text="加载中请稍"
empty-text="加载中请稍"
:props="defaultProps"
></el-tree>
</el-form-item>

View File

@ -16,6 +16,7 @@ module.exports = {
// 部署生产环境和开发环境下的URL。
// 默认情况下Vue CLI 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
// 设置基路径参考文档: http://doc.ruoyi.vip/ruoyi-vue/document/qdsc.html#应用路径
publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
// 在npm run build 或 yarn build 时 生成文件的目录名称要和baseUrl的生产环境路径一致默认dist
outputDir: 'dist',