Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into dev
Conflicts:
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
ruoyi-generator/src/main/resources/vm/java/controller.java.vm
ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java
ruoyi-ui/package.json
ruoyi-ui/src/api/monitor/logininfor.js
ruoyi-ui/src/api/monitor/operlog.js
ruoyi-ui/src/api/system/config.js
ruoyi-ui/src/api/system/dict/data.js
ruoyi-ui/src/api/system/dict/type.js
ruoyi-ui/src/api/system/post.js
ruoyi-ui/src/api/system/role.js
ruoyi-ui/src/api/system/user.js
ruoyi-ui/src/main.js
ruoyi-ui/src/utils/request.js
ruoyi-ui/src/views/monitor/job/index.vue
ruoyi-ui/src/views/monitor/job/log.vue
ruoyi-ui/src/views/monitor/logininfor/index.vue
ruoyi-ui/src/views/monitor/operlog/index.vue
ruoyi-ui/src/views/system/config/index.vue
ruoyi-ui/src/views/system/dict/data.vue
ruoyi-ui/src/views/system/dict/index.vue
ruoyi-ui/src/views/system/post/index.vue
ruoyi-ui/src/views/system/role/index.vue
ruoyi-ui/src/views/system/user/index.vue
| | |
| | | package com.ruoyi.web.controller.system; |
| | | |
| | | import com.ruoyi.common.annotation.Log; |
| | | import com.ruoyi.common.annotation.RepeatSubmit; |
| | | import com.ruoyi.common.constant.UserConstants; |
| | | import com.ruoyi.common.core.controller.BaseController; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | |
| | | @PreAuthorize("@ss.hasPermi('system:config:add')") |
| | | @Log(title = "参数管理", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | @RepeatSubmit |
| | | public AjaxResult<Void> add(@Validated @RequestBody SysConfig config) { |
| | | if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { |
| | | return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['${moduleName}:${businessName}:export']" |
| | | >导出</el-button> |
| | |
| | | buttonLoading: false, |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | #if($table.sub) |
| | |
| | | #end |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.#[[$download]]#.excel('/${moduleName}/${businessName}/export', this.queryParams); |
| | | this.download('${moduleName}/${businessName}/export', { |
| | | ...this.queryParams |
| | | }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) |
| | | } |
| | | } |
| | | }; |
| | |
| | | }, |
| | | "dependencies": { |
| | | "@riophae/vue-treeselect": "0.4.0", |
| | | "axios": "0.21.0", |
| | | "axios": "0.24.0", |
| | | "clipboard": "2.0.6", |
| | | "core-js": "3.8.1", |
| | | "core-js": "3.19.1", |
| | | "echarts": "4.9.0", |
| | | "element-ui": "2.15.6", |
| | | "file-saver": "2.0.5", |
| | |
| | | }) |
| | | } |
| | | |
| | | // 导出定时任务调度 |
| | | export function exportJob(query) { |
| | | return request({ |
| | | url: '/monitor/job/export', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // 任务状态修改 |
| | | export function changeJobStatus(jobId, status) { |
| | | const data = { |
| | |
| | | method: 'delete' |
| | | }) |
| | | } |
| | | |
| | | // 导出岗位 |
| | | export function exportPost(query) { |
| | | return request({ |
| | | url: '/system/post/export', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | |
| | | import router from './router' |
| | | import directive from './directive' //directive |
| | | import plugins from './plugins' // plugins |
| | | import { download } from '@/utils/request' |
| | | |
| | | import './assets/icons' // icon |
| | | import './permission' // permission control |
| | |
| | | Vue.prototype.addDateRange = addDateRange |
| | | Vue.prototype.selectDictLabel = selectDictLabel |
| | | Vue.prototype.selectDictLabels = selectDictLabels |
| | | Vue.prototype.download = download |
| | | Vue.prototype.handleTree = handleTree |
| | | |
| | | // 全局组件挂载 |
| | |
| | | import { saveAs } from 'file-saver' |
| | | import axios from 'axios' |
| | | import { getToken } from '@/utils/auth' |
| | | import { Message } from 'element-ui' |
| | | import { saveAs } from 'file-saver' |
| | | import { getToken } from '@/utils/auth' |
| | | import { blobValidate } from "@/utils/ruoyi"; |
| | | |
| | | const baseURL = process.env.VUE_APP_BASE_API |
| | | |
| | |
| | | responseType: 'blob', |
| | | headers: { 'Authorization': 'Bearer ' + getToken() } |
| | | }).then(async (res) => { |
| | | const isLogin = await this.blobValidate(res.data); |
| | | const isLogin = await blobValidate(res.data); |
| | | if (isLogin) { |
| | | const blob = new Blob([res.data], { type: 'application/zip' }) |
| | | this.saveAs(blob, name) |
| | |
| | | }, |
| | | 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; |
| | | } |
| | | }, |
| | | } |
| | | } |
| | | |
| | |
| | | import axios from 'axios' |
| | | import { Notification, MessageBox, Message } from 'element-ui' |
| | | import { Notification, MessageBox, Message, Loading } from 'element-ui' |
| | | import store from '@/store' |
| | | import { getToken } from '@/utils/auth' |
| | | import errorCode from '@/utils/errorCode' |
| | | import { tansParams, blobValidate } from "@/utils/ruoyi"; |
| | | import { saveAs } from 'file-saver' |
| | | |
| | | let downloadLoadingInstance; |
| | | |
| | | axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' |
| | | // 对应国际化资源文件后缀 |
| | |
| | | // 超时 |
| | | timeout: 10000 |
| | | }) |
| | | |
| | | // request拦截器 |
| | | service.interceptors.request.use(config => { |
| | | // 是否需要设置 token |
| | |
| | | } |
| | | // get请求映射params参数 |
| | | if (config.method === 'get' && config.params) { |
| | | let url = config.url + '?'; |
| | | for (const propName of Object.keys(config.params)) { |
| | | const value = config.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 + ']'; |
| | | let subPart = encodeURIComponent(params) + '='; |
| | | url += subPart + encodeURIComponent(value[key]) + '&'; |
| | | } |
| | | } |
| | | } else { |
| | | url += part + encodeURIComponent(value) + "&"; |
| | | } |
| | | } |
| | | } |
| | | let url = config.url + '?' + tansParams(config.params); |
| | | url = url.slice(0, -1); |
| | | config.params = {}; |
| | | config.url = url; |
| | |
| | | const code = res.data.code || 200; |
| | | // 获取错误信息 |
| | | const msg = errorCode[code] || res.data.msg || errorCode['default'] |
| | | // 二进制数据则直接返回 |
| | | if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){ |
| | | return res.data |
| | | } |
| | | if (code === 401) { |
| | | MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { |
| | | let doms = document.getElementsByClassName('el-message-box')[0] |
| | | if(doms === undefined){ |
| | | MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { |
| | | confirmButtonText: '重新登录', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | } |
| | | ).then(() => { |
| | | store.dispatch('LogOut').then(() => { |
| | | location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; |
| | | }) |
| | | }).catch(() => {}); |
| | | ).then(() => { |
| | | store.dispatch('LogOut').then(() => { |
| | | location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; |
| | | }) |
| | | }).catch(() => {}); |
| | | } |
| | | return Promise.reject('无效的会话,或者会话已过期,请重新登录。') |
| | | } else if (code === 500) { |
| | | Message({ |
| | |
| | | } |
| | | ) |
| | | |
| | | // 通用下载方法 |
| | | export function download(url, params, filename) { |
| | | downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) |
| | | return service.post(url, params, { |
| | | transformRequest: [(params) => { return tansParams(params) }], |
| | | headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, |
| | | responseType: 'blob' |
| | | }).then(async (data) => { |
| | | const isLogin = await blobValidate(data); |
| | | if (isLogin) { |
| | | const blob = new Blob([data]) |
| | | saveAs(blob, filename) |
| | | } else { |
| | | Message.error('无效的会话,或者会话已过期,请重新登录。'); |
| | | } |
| | | downloadLoadingInstance.close(); |
| | | }).catch((r) => { |
| | | console.error(r) |
| | | Message.error('下载文件出现错误,请联系管理员!') |
| | | downloadLoadingInstance.close(); |
| | | }) |
| | | } |
| | | |
| | | export default service |
| | |
| | | } |
| | | return tree; |
| | | } |
| | | |
| | | /** |
| | | * 参数处理 |
| | | * @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 |
| | | } |
| | | |
| | | // 验证是否为blob格式 |
| | | export async function blobValidate(data) { |
| | | try { |
| | | const text = await data.text(); |
| | | JSON.parse(text); |
| | | return false; |
| | | } catch (error) { |
| | | return true; |
| | | } |
| | | } |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['monitor:job:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非单个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/monitor/job/export', this.queryParams); |
| | | this.download('monitor/job/export', { |
| | | ...this.queryParams |
| | | }, `job_${new Date().getTime()}.xlsx`) |
| | | } |
| | | } |
| | | }; |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['monitor:job:export']" |
| | | >导出</el-button> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { getJob } from "@/api/monitor/job"; |
| | | import { getJob} from "@/api/monitor/job"; |
| | | import { listJobLog, delJobLog, cleanJobLog } from "@/api/monitor/jobLog"; |
| | | |
| | | export default { |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非多个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/monitor/jobLog/export', this.queryParams); |
| | | this.download('/monitor/jobLog/export', { |
| | | ...this.queryParams |
| | | }, `log_${new Date().getTime()}.xlsx`) |
| | | } |
| | | } |
| | | }; |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['monitor:logininfor:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非多个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/monitor/logininfor/export', this.queryParams); |
| | | this.download('monitor/logininfor/export', { |
| | | ...this.queryParams |
| | | }, `logininfor_${new Date().getTime()}.xlsx`) |
| | | } |
| | | } |
| | | }; |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['monitor:operlog:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非多个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/monitor/operlog/export', this.queryParams); |
| | | this.download('monitor/operlog/export', { |
| | | ...this.queryParams |
| | | }, `operlog_${new Date().getTime()}.xlsx`) |
| | | } |
| | | } |
| | | }; |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:config:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非单个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/system/config/export', this.queryParams); |
| | | this.download('system/config/export', { |
| | | ...this.queryParams |
| | | }, `config_${new Date().getTime()}.xlsx`) |
| | | }, |
| | | /** 刷新缓存按钮操作 */ |
| | | handleRefreshCache() { |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:dict:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非单个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/system/dict/data/export', this.queryParams); |
| | | this.download('system/dict/data/export', { |
| | | ...this.queryParams |
| | | }, `data_${new Date().getTime()}.xlsx`) |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | </script> |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:dict:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非单个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/system/dict/type/export', this.queryParams); |
| | | this.download('system/dict/type/export', { |
| | | ...this.queryParams |
| | | }, `type_${new Date().getTime()}.xlsx`) |
| | | }, |
| | | /** 刷新缓存按钮操作 */ |
| | | handleRefreshCache() { |
| | |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | </script> |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:post:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非单个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/system/post/export', this.queryParams); |
| | | this.download('system/post/export', { |
| | | ...this.queryParams |
| | | }, `post_${new Date().getTime()}.xlsx`) |
| | | } |
| | | } |
| | | }; |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:role:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非单个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/system/role/export', this.queryParams); |
| | | this.download('system/role/export', { |
| | | ...this.queryParams |
| | | }, `role_${new Date().getTime()}.xlsx`) |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | </script> |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | :loading="exportLoading" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:user:export']" |
| | | >导出</el-button> |
| | |
| | | return { |
| | | // 遮罩层 |
| | | loading: true, |
| | | // 导出遮罩层 |
| | | exportLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非单个禁用 |
| | |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | this.$download.excel('/system/user/export', this.queryParams); |
| | | this.download('system/user/export', { |
| | | ...this.queryParams |
| | | }, `user_${new Date().getTime()}.xlsx`) |
| | | }, |
| | | /** 导入按钮操作 */ |
| | | handleImport() { |
| | |
| | | }, |
| | | /** 下载模板操作 */ |
| | | importTemplate() { |
| | | this.$download.excel('/system/user/importTemplate'); |
| | | this.download('system/user/importTemplate', { |
| | | ...this.queryParams |
| | | }, `user_template_${new Date().getTime()}.xlsx`) |
| | | }, |
| | | // 文件上传中处理 |
| | | handleFileUploadProgress(event, file, fileList) { |
| | |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | </script> |