Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into dev
Conflicts:
pom.xml
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
ruoyi-ui/.env.development
ruoyi-ui/.env.production
ruoyi-ui/.env.staging
ruoyi-ui/package.json
ruoyi-ui/src/App.vue
ruoyi-ui/src/assets/styles/ruoyi.scss
ruoyi-ui/src/components/Pagination/index.vue
ruoyi-ui/src/layout/components/Settings/index.vue
ruoyi-ui/src/layout/components/Sidebar/Logo.vue
ruoyi-ui/src/main.js
ruoyi-ui/src/permission.js
ruoyi-ui/src/settings.js
ruoyi-ui/src/store/modules/settings.js
ruoyi-ui/src/views/monitor/logininfor/index.vue
ruoyi-ui/src/views/monitor/operlog/index.vue
ruoyi-ui/src/views/system/user/index.vue
ruoyi-ui/vue.config.js
| | |
| | | <spring-boot.version>2.3.11.RELEASE</spring-boot.version> |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
| | | <java.version>11</java.version> |
| | | <java.version>1.8</java.version> |
| | | <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> |
| | | <druid.version>1.2.6</druid.version> |
| | | <knife4j.version>3.0.2</knife4j.version> |
| | |
| | | public static final String RESOURCE_PREFIX = "/profile"; |
| | | |
| | | /** |
| | | * RMI 远程方法调用 |
| | | */ |
| | | public static final String LOOKUP_RMI = "rmi://"; |
| | | |
| | | /** |
| | | * 资源映射路径 前缀 |
| | | */ |
| | | public static final String REDIS_LOCK_KEY = "redis_lock:"; |
| | |
| | | /** |
| | | * 获取代码生成地址 |
| | | * |
| | | * @param table 业务表信息 |
| | | * @param table 业务表信息 |
| | | * @param template 模板文件路径 |
| | | * @return 生成地址 |
| | | */ |
| | |
| | | package com.ruoyi.quartz.controller;
|
| | |
|
| | | import com.ruoyi.common.annotation.Log;
|
| | | import com.ruoyi.common.constant.Constants;
|
| | | import com.ruoyi.common.core.controller.BaseController;
|
| | | import com.ruoyi.common.core.domain.AjaxResult;
|
| | | import com.ruoyi.common.core.page.TableDataInfo;
|
| | | import com.ruoyi.common.enums.BusinessType;
|
| | | import com.ruoyi.common.exception.job.TaskException;
|
| | | import com.ruoyi.common.utils.SecurityUtils;
|
| | | import com.ruoyi.common.utils.StringUtils;
|
| | | import com.ruoyi.common.utils.poi.ExcelUtil;
|
| | | import com.ruoyi.quartz.domain.SysJob;
|
| | | import com.ruoyi.quartz.service.ISysJobService;
|
| | |
| | | {
|
| | | if (!CronUtils.isValid(sysJob.getCronExpression()))
|
| | | {
|
| | | return AjaxResult.error("cron表达式不正确");
|
| | | return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败,Cron表达式不正确");
|
| | | }
|
| | | else if (StringUtils.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
|
| | | {
|
| | | return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
|
| | | }
|
| | | sysJob.setCreateBy(SecurityUtils.getUsername());
|
| | | return toAjax(jobService.insertJob(sysJob));
|
| | |
| | | {
|
| | | if (!CronUtils.isValid(sysJob.getCronExpression()))
|
| | | {
|
| | | return AjaxResult.error("cron表达式不正确");
|
| | | return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败,Cron表达式不正确");
|
| | | }
|
| | | else if (StringUtils.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
|
| | | {
|
| | | return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
|
| | | }
|
| | | sysJob.setUpdateBy(SecurityUtils.getUsername());
|
| | | return toAjax(jobService.updateJob(sysJob));
|
| | |
| | | /** |
| | | * 根据角色ID查询部门树信息 |
| | | * |
| | | * @param roleId 角色ID |
| | | * @param roleId 角色ID |
| | | * @param deptCheckStrictly 部门树选择项是否关联显示 |
| | | * @return 选中部门列表 |
| | | */ |
| | |
| | | int result = baseMapper.updateById(dept); |
| | | if (UserConstants.DEPT_NORMAL.equals(dept.getStatus())) { |
| | | // 如果该部门是启用状态,则启用该部门的所有上级部门 |
| | | updateParentDeptStatus(dept); |
| | | updateParentDeptStatusNormal(dept); |
| | | } |
| | | return result; |
| | | } |
| | |
| | | /** |
| | | * 修改子元素关系 |
| | | * |
| | | * @param deptId 被修改的部门ID |
| | | * @param deptId 被修改的部门ID |
| | | * @param newAncestors 新的父ID集合 |
| | | * @param oldAncestors 旧的父ID集合 |
| | | */ |
| | |
| | | # 页面标题 |
| | | VUE_APP_TITLE = 若依管理系统 |
| | | |
| | | # 开发环境配置 |
| | | ENV = 'development' |
| | | |
| | |
| | | # 页面标题 |
| | | VUE_APP_TITLE = 若依管理系统 |
| | | |
| | | # 生产环境配置 |
| | | ENV = 'production' |
| | | |
| | |
| | | # 页面标题 |
| | | VUE_APP_TITLE = 若依管理系统 |
| | | |
| | | NODE_ENV = production |
| | | |
| | | # 测试环境配置 |
| | |
| | | "clipboard": "2.0.6", |
| | | "core-js": "3.8.1", |
| | | "echarts": "4.9.0", |
| | | "element-ui": "2.15.0", |
| | | "element-ui": "2.15.2", |
| | | "file-saver": "2.0.4", |
| | | "fuse.js": "6.4.3", |
| | | "highlight.js": "9.18.5", |
| | |
| | | "vue": "2.6.12", |
| | | "vue-count-to": "1.0.13", |
| | | "vue-cropper": "0.5.5", |
| | | "vue-meta": "^2.4.0", |
| | | "vue-router": "3.4.9", |
| | | "vuedraggable": "2.24.3", |
| | | "vuex": "3.6.0" |
| | |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'App' |
| | | name: 'App', |
| | | metaInfo() { |
| | | return { |
| | | title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title, |
| | | titleTemplate: title => { |
| | | return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | |
| | | position: absolute; |
| | | } |
| | | |
| | | @media ( max-width : 768px) { |
| | | .pagination-container .el-pagination > .el-pagination__jump { |
| | | display: none !important; |
| | | } |
| | | .pagination-container .el-pagination > .el-pagination__sizes { |
| | | display: none !important; |
| | | } |
| | | } |
| | | |
| | | .el-table .fixed-width .el-button--mini { |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | |
| | | :page-size.sync="pageSize" |
| | | :layout="layout" |
| | | :page-sizes="pageSizes" |
| | | :pager-count="pagerCount" |
| | | :total="total" |
| | | v-bind="$attrs" |
| | | @size-change="handleSizeChange" |
| | |
| | | return [10, 20, 30, 50] |
| | | } |
| | | }, |
| | | // 移动端页码按钮的数量端默认值5 |
| | | pagerCount: { |
| | | type: Number, |
| | | default: document.body.clientWidth < 992 ? 5 : 7 |
| | | }, |
| | | layout: { |
| | | type: String, |
| | | default: 'total, sizes, prev, pager, next, jumper' |
| | |
| | | <el-divider/> |
| | | |
| | | <h3 class="drawer-title">系统布局配置</h3> |
| | | |
| | | |
| | | <div class="drawer-item"> |
| | | <span>开启 TopNav</span> |
| | | <el-switch v-model="topNav" class="drawer-switch" /> |
| | |
| | | <div class="drawer-item"> |
| | | <span>显示 Logo</span> |
| | | <el-switch v-model="sidebarLogo" class="drawer-switch" /> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>动态标题</span> |
| | | <el-switch v-model="dynamicTitle" class="drawer-switch" /> |
| | | </div> |
| | | |
| | | <el-divider/> |
| | |
| | | }) |
| | | } |
| | | }, |
| | | dynamicTitle: { |
| | | get() { |
| | | return this.$store.state.settings.dynamicTitle |
| | | }, |
| | | set(val) { |
| | | this.$store.dispatch('settings/changeSetting', { |
| | | key: 'dynamicTitle', |
| | | value: val |
| | | }) |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | themeChange(val) { |
| | |
| | | "tagsView":${this.tagsView}, |
| | | "fixedHeader":${this.fixedHeader}, |
| | | "sidebarLogo":${this.sidebarLogo}, |
| | | "dynamicTitle":${this.dynamicTitle}, |
| | | "sideTheme":"${this.sideTheme}", |
| | | "theme":"${this.theme}" |
| | | }` |
| | |
| | | <div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }"> |
| | | <transition name="sidebarLogoFade"> |
| | | <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> |
| | | <img v-if="logo" :src="logo" class="sidebar-logo"> |
| | | <img v-if="logo" :src="logo" class="sidebar-logo" /> |
| | | <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1> |
| | | </router-link> |
| | | <router-link v-else key="expand" class="sidebar-logo-link" to="/"> |
| | | <img v-if="logo" :src="logo" class="sidebar-logo"> |
| | | <img v-if="logo" :src="logo" class="sidebar-logo" /> |
| | | <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1> |
| | | </router-link> |
| | | </transition> |
| | |
| | | import Pagination from "@/components/Pagination"; |
| | | // 自定义表格工具扩展 |
| | | import RightToolbar from "@/components/RightToolbar" |
| | | // 头部标签插件 |
| | | import VueMeta from 'vue-meta' |
| | | |
| | | // 全局方法挂载 |
| | | Vue.prototype.getDicts = getDicts |
| | |
| | | Vue.component('RightToolbar', RightToolbar) |
| | | |
| | | Vue.use(permission) |
| | | Vue.use(VueMeta) |
| | | |
| | | /** |
| | | * If you don't want to use mock-server |
| | |
| | | router.beforeEach((to, from, next) => { |
| | | NProgress.start() |
| | | if (getToken()) { |
| | | to.meta.title && store.dispatch('settings/setTitle', to.meta.title) |
| | | /* has token*/ |
| | | if (to.path === '/login') { |
| | | next({ path: '/' }) |
| | |
| | | module.exports = { |
| | | title: 'RuoYi-Vue-Plus后台管理系统', |
| | | |
| | | /** |
| | | * 侧边栏主题 深色主题theme-dark,浅色主题theme-light |
| | | */ |
| | |
| | | sidebarLogo: true, |
| | | |
| | | /** |
| | | * 是否显示动态标题 |
| | | */ |
| | | dynamicTitle: false, |
| | | |
| | | /** |
| | | * @type {string | array} 'production' | ['production', 'development'] |
| | | * @description Need show err logs component. |
| | | * The default is only used in the production env |
| | |
| | | import variables from '@/assets/styles/element-variables.scss' |
| | | import defaultSettings from '@/settings' |
| | | |
| | | const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo } = defaultSettings |
| | | const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings |
| | | |
| | | const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' |
| | | const state = { |
| | | title: '', |
| | | theme: storageSetting.theme || variables.theme, |
| | | sideTheme: storageSetting.sideTheme || sideTheme, |
| | | showSettings: showSettings, |
| | | topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, |
| | | tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, |
| | | fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, |
| | | sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo |
| | | sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, |
| | | dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle |
| | | } |
| | | const mutations = { |
| | | CHANGE_SETTING: (state, { key, value }) => { |
| | |
| | | } |
| | | |
| | | const actions = { |
| | | // 修改布局设置 |
| | | changeSetting({ commit }, data) { |
| | | commit('CHANGE_SETTING', data) |
| | | }, |
| | | // 设置网页标题 |
| | | setTitle({ commit }, title) { |
| | | state.title = title |
| | | } |
| | | } |
| | | |
| | |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | | </el-row> |
| | | |
| | | <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="访问编号" align="center" prop="infoId" /> |
| | | <el-table-column label="用户名称" align="center" prop="userName" /> |
| | | <el-table-column label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" /> |
| | | <el-table-column label="登录地址" align="center" prop="ipaddr" width="130" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="浏览器" align="center" prop="browser" /> |
| | | <el-table-column label="浏览器" align="center" prop="browser" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="操作系统" align="center" prop="os" /> |
| | | <el-table-column label="登录状态" align="center" prop="status" :formatter="statusFormat" /> |
| | | <el-table-column label="操作信息" align="center" prop="msg" /> |
| | | <el-table-column label="登录日期" align="center" prop="loginTime" width="180"> |
| | | <el-table-column label="登录日期" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.loginTime) }}</span> |
| | | </template> |
| | |
| | | statusOptions: [], |
| | | // 日期范围 |
| | | dateRange: [], |
| | | // 默认排序 |
| | | defaultSort: {prop: 'loginTime', order: 'descending'}, |
| | | // 查询参数 |
| | | queryParams: { |
| | | pageNum: 1, |
| | |
| | | resetQuery() { |
| | | this.dateRange = []; |
| | | this.resetForm("queryForm"); |
| | | this.$refs.tables.sort(this.defaultSort.prop, this.defaultSort.order) |
| | | this.handleQuery(); |
| | | }, |
| | | // 多选框选中数据 |
| | | /** 多选框选中数据 */ |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map(item => item.infoId) |
| | | this.multiple = !selection.length |
| | | }, |
| | | /** 排序触发事件 */ |
| | | handleSortChange(column, prop, order) { |
| | | this.queryParams.orderByColumn = column.prop; |
| | | this.queryParams.isAsc = column.order; |
| | | this.getList(); |
| | | }, |
| | | /** 删除按钮操作 */ |
| | | handleDelete(row) { |
| | | const infoIds = row.infoId || this.ids; |
| | |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | | </el-row> |
| | | |
| | | <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange"> |
| | | <el-table-column type="selection" width="55" 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="businessType" :formatter="typeFormat" /> |
| | | <el-table-column label="请求方式" align="center" prop="requestMethod" /> |
| | | <el-table-column label="操作人员" align="center" prop="operName" /> |
| | | <el-table-column label="主机" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="操作人员" align="center" prop="operName" width="100" :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="operLocation" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="操作状态" align="center" prop="status" :formatter="statusFormat" /> |
| | | <el-table-column label="操作日期" align="center" prop="operTime" width="180"> |
| | | <el-table-column label="操作日期" align="center" prop="operTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.operTime) }}</span> |
| | | </template> |
| | |
| | | statusOptions: [], |
| | | // 日期范围 |
| | | dateRange: [], |
| | | // 默认排序 |
| | | defaultSort: {prop: 'operTime', order: 'descending'}, |
| | | // 表单参数 |
| | | form: {}, |
| | | // 查询参数 |
| | |
| | | resetQuery() { |
| | | this.dateRange = []; |
| | | this.resetForm("queryForm"); |
| | | this.$refs.tables.sort(this.defaultSort.prop, this.defaultSort.order) |
| | | this.handleQuery(); |
| | | }, |
| | | // 多选框选中数据 |
| | | /** 多选框选中数据 */ |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map(item => item.operId) |
| | | this.multiple = !selection.length |
| | | }, |
| | | /** 排序触发事件 */ |
| | | handleSortChange(column, prop, order) { |
| | | this.queryParams.orderByColumn = column.prop; |
| | | this.queryParams.isAsc = column.order; |
| | | this.getList(); |
| | | }, |
| | | /** 详细按钮操作 */ |
| | | handleView(row) { |
| | | this.open = true; |
| | |
| | | }, |
| | | /** 搜索按钮操作 */ |
| | | handleQuery() { |
| | | this.queryParams.page = 1; |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | /** 重置按钮操作 */ |
| | |
| | | 'use strict' |
| | | const path = require('path') |
| | | const defaultSettings = require('./src/settings.js') |
| | | |
| | | function resolve(dir) { |
| | | return path.join(__dirname, dir) |
| | | } |
| | | |
| | | const name = defaultSettings.title || 'RuoYi-Vue-Plus后台管理系统' // 标题 |
| | | const name = defaultSettings.title || 'RuoYi-Vue-Plus后台管理系统' // 网页标题 |
| | | |
| | | const port = process.env.port || process.env.npm_config_port || 80 // 端口 |
| | | |