diff --git a/ruoyi-ui/.env.development b/ruoyi-ui/.env.development index 07da1aa..9da3bd2 100644 --- a/ruoyi-ui/.env.development +++ b/ruoyi-ui/.env.development @@ -5,7 +5,7 @@ VUE_APP_TITLE = 广州市城市建设职业学校 ENV = 'development' # 若依管理系统/开发环境 -VUE_APP_BASE_API = '/dev-api' +# VUE_APP_BASE_API = '/dev-api' # 应用访问路径 例如使用前缀 /admin/ VUE_APP_CONTEXT_PATH = '/' @@ -16,5 +16,8 @@ VUE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/login' # xxl-job 控制台地址 VUE_APP_XXL_JOB_ADMIN = 'http://localhost:9100/xxl-job-admin' +# VUE_APP_BASE_API = 'https://bxserver.mhito.net:8090' +VUE_APP_BASE_API = 'http://192.168.1.55:8080' + # 路由懒加载 VUE_CLI_BABEL_TRANSPILE_MODULES = true diff --git a/ruoyi-ui/dist.zip b/ruoyi-ui/dist.rar similarity index 63% rename from ruoyi-ui/dist.zip rename to ruoyi-ui/dist.rar index ad013f4..acf26a5 100644 Binary files a/ruoyi-ui/dist.zip and b/ruoyi-ui/dist.rar differ diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js index fec974b..0f6d60a 100644 --- a/ruoyi-ui/src/router/index.js +++ b/ruoyi-ui/src/router/index.js @@ -1,12 +1,20 @@ -import Vue from 'vue' -import Router from 'vue-router' -import store from '@/store' +import Vue from "vue"; +import Router from "vue-router"; +import store from "@/store"; -Vue.use(Router) +Vue.use(Router); /* Layout */ -import Layout from '@/layout' -import { getToken } from '@/utils/auth' +import Layout from "@/layout"; +import { getToken } from "@/utils/auth"; + +const originalPush = Router.prototype.push; +Router.prototype.push = function push(location, onResolve, onReject) { + if (onResolve || onReject) + return originalPush.call(this, location, onResolve, onReject); + return originalPush.call(this, location).catch((err) => err); +}; +Vue.use(Router); /** * Note: 路由配置项 @@ -34,234 +42,243 @@ import { getToken } from '@/utils/auth' export const constantRoutes = [ // 手机端发起报修 { - path: '/bx/start/:deployId([\\w|\\-]+)', - component: () => import('@/views/workflow/work/start_cellphone'), - hidden: true + path: "/bx/start/:deployId([\\w|\\-]+)", + component: () => import("@/views/workflow/work/start_cellphone"), + hidden: true, }, // 手机端查询报修列表 { - path: '/bx/list', - component: () => import('@/views/workflow/work/own_cellphone'), - hidden: true + path: "/bx/list", + component: () => import("@/views/workflow/work/own_cellphone"), + hidden: true, }, // 手机端查询报修详情 { - path: '/bx/detail/:procInsId([\\w|\\-]+)', - component: () => import('@/views/workflow/work/detail_cellphone'), - hidden: true + path: "/bx/detail/:procInsId([\\w|\\-]+)", + component: () => import("@/views/workflow/work/detail_cellphone"), + hidden: true, }, { - path: '/redirect', + path: "/redirect", component: Layout, hidden: true, children: [ { - path: '/redirect/:path(.*)', - component: () => import('@/views/redirect') - } - ] + path: "/redirect/:path(.*)", + component: () => import("@/views/redirect"), + }, + ], }, { - path: '/login', - component: () => import('@/views/login'), - hidden: true + path: "/login", + name: "login", + component: () => import("@/views/login"), + hidden: true, }, { - path: '/register', - component: () => import('@/views/register'), - hidden: true + path: "/register", + component: () => import("@/views/register"), + hidden: true, }, { - path: '/404', - component: () => import('@/views/error/404'), - hidden: true + path: "/404", + component: () => import("@/views/error/404"), + hidden: true, }, { - path: '/401', - component: () => import('@/views/error/401'), - hidden: true + path: "/401", + component: () => import("@/views/error/401"), + hidden: true, }, { - path: '', + path: "", component: Layout, - redirect: 'index', + redirect: "index", children: [ { - path: 'index', - component: () => import('@/views/index'), - name: 'Index', - meta: { title: '首页', icon: 'dashboard', affix: true } - } - ] + path: "index", + component: () => import("@/views/index"), + name: "Index", + meta: { title: "首页", icon: "dashboard", affix: true }, + }, + ], }, { - path: '/tool', + path: "/tool", component: Layout, hidden: true, children: [ { - path: 'build/index', - component: () => import('@/views/tool/build/index'), - name: 'FormBuild', - meta: { title: '表单设计', icon: '' } - } - ] + path: "build/index", + component: () => import("@/views/tool/build/index"), + name: "FormBuild", + meta: { title: "表单设计", icon: "" }, + }, + ], }, { - path: '/user', + path: "/user", component: Layout, hidden: true, - redirect: 'noredirect', + redirect: "noredirect", children: [ { - path: 'profile', - component: () => import('@/views/system/user/profile/index'), - name: 'Profile', - meta: { title: '个人中心', icon: 'user' } - } - ] - } -] + path: "profile", + component: () => import("@/views/system/user/profile/index"), + name: "Profile", + meta: { title: "个人中心", icon: "user" }, + }, + ], + }, +]; // 动态路由,基于用户权限动态去加载 export const dynamicRoutes = [ { - path: '/system/user-auth', + path: "/system/user-auth", component: Layout, hidden: true, - permissions: ['system:user:edit'], + permissions: ["system:user:edit"], children: [ { - path: 'role/:userId(\\d+)', - component: () => import('@/views/system/user/authRole'), - name: 'AuthRole', - meta: { title: '分配角色', activeMenu: '/system/user' } - } - ] + path: "role/:userId(\\d+)", + component: () => import("@/views/system/user/authRole"), + name: "AuthRole", + meta: { title: "分配角色", activeMenu: "/system/user" }, + }, + ], }, { - path: '/system/role-auth', + path: "/system/role-auth", component: Layout, hidden: true, - permissions: ['system:role:edit'], + permissions: ["system:role:edit"], children: [ { - path: 'user/:roleId(\\d+)', - component: () => import('@/views/system/role/authUser'), - name: 'AuthUser', - meta: { title: '分配用户', activeMenu: '/system/role' } - } - ] + path: "user/:roleId(\\d+)", + component: () => import("@/views/system/role/authUser"), + name: "AuthUser", + meta: { title: "分配用户", activeMenu: "/system/role" }, + }, + ], }, { - path: '/system/dict-data', + path: "/system/dict-data", component: Layout, hidden: true, - permissions: ['system:dict:list'], + permissions: ["system:dict:list"], children: [ { - path: 'index/:dictId(\\d+)', - component: () => import('@/views/system/dict/data'), - name: 'Data', - meta: { title: '字典数据', activeMenu: '/system/dict' } - } - ] + path: "index/:dictId(\\d+)", + component: () => import("@/views/system/dict/data"), + name: "Data", + meta: { title: "字典数据", activeMenu: "/system/dict" }, + }, + ], }, { - path: '/system/oss-config', + path: "/system/oss-config", component: Layout, hidden: true, - permissions: ['system:oss:list'], + permissions: ["system:oss:list"], children: [ { - path: 'index', - component: () => import('@/views/system/oss/config'), - name: 'OssConfig', - meta: { title: '配置管理', activeMenu: '/system/oss' } - } - ] + path: "index", + component: () => import("@/views/system/oss/config"), + name: "OssConfig", + meta: { title: "配置管理", activeMenu: "/system/oss" }, + }, + ], }, { - path: '/tool/gen-edit', + path: "/tool/gen-edit", component: Layout, hidden: true, - permissions: ['tool:gen:edit'], + permissions: ["tool:gen:edit"], children: [ { - path: 'index/:tableId(\\d+)', - component: () => import('@/views/tool/gen/editTable'), - name: 'GenEdit', - meta: { title: '修改生成配置', activeMenu: '/tool/gen' } - } - ] + path: "index/:tableId(\\d+)", + component: () => import("@/views/tool/gen/editTable"), + name: "GenEdit", + meta: { title: "修改生成配置", activeMenu: "/tool/gen" }, + }, + ], }, { - path: '/workflow/process', + path: "/workflow/process", component: Layout, hidden: true, - permissions: ['workflow:process:query'], + permissions: ["workflow:process:query"], children: [ { - path: 'start/:deployId([\\w|\\-]+)', - component: () => import('@/views/workflow/work/start'), - name: 'WorkStart', - meta: { title: '发起流程', icon: '' } + path: "start/:deployId([\\w|\\-]+)", + component: () => import("@/views/workflow/work/start"), + name: "WorkStart", + meta: { title: "发起流程", icon: "" }, }, { - path: 'detail/:procInsId([\\w|\\-]+)', - component: () => import('@/views/workflow/work/detail'), - name: 'WorkDetail', - meta: { title: '流程详情', activeMenu: '/work/own' } - } - ] + path: "detail/:procInsId([\\w|\\-]+)", + component: () => import("@/views/workflow/work/detail"), + name: "WorkDetail", + meta: { title: "流程详情", activeMenu: "/work/own" }, + }, + ], }, { - path: '/workflow/process/bx', + path: "/workflow/process/bx", children: [ { - path: 'start/:deployId([\\w|\\-]+)', - component: () => import('@/views/workflow/work/start_cellphone'), + path: "start/:deployId([\\w|\\-]+)", + component: () => import("@/views/workflow/work/start_cellphone"), }, { - path: 'list', - component: () => import('@/views/workflow/work/own_cellphone'), + path: "list", + component: () => import("@/views/workflow/work/own_cellphone"), }, { - path: 'detail/:procInsId([\\w|\\-]+)', - component: () => import('@/views/workflow/work/detail_cellphone'), - } - ] + path: "detail/:procInsId([\\w|\\-]+)", + component: () => import("@/views/workflow/work/detail_cellphone"), + }, + ], }, -] +]; // 防止连续点击多次路由报错 let routerPush = Router.prototype.push; let routerReplace = Router.prototype.replace; // push Router.prototype.push = function push(location) { - return routerPush.call(this, location).catch(err => err) -} + return routerPush.call(this, location).catch((err) => err); +}; // replace Router.prototype.replace = function push(location) { - return routerReplace.call(this, location).catch(err => err) -} + return routerReplace.call(this, location).catch((err) => err); +}; -export default new Router({ +const router = new Router({ base: process.env.VUE_APP_CONTEXT_PATH, - mode: 'history', // 去掉url中的# + mode: "history", // 去掉url中的# scrollBehavior: () => ({ y: 0 }), - routes: constantRoutes -}) + routes: constantRoutes, +}); -new Router().beforeEach((to, from, next) => { - const token = store.state.token // 假设你有一个名为token的Vuex状态 +router.beforeEach((to, from, next) => { + let token = getToken(); + debugger; if (token) { - // 如果token存在,继续路由导航 - next() + // 如果有token + next(); } else { - // 如果token不存在,跳转到登录页面 - // 在登录页面,保存当前页面的路径以便登录后返回 - localStorage.setItem('intendedRoute', to.fullPath) - next({ path: '/' }) + if (to.path == "/login") { + next(); + } else { + if (to.path.includes("bx/start")) { + next(); + } else { + next("/login"); + } + } } -}) \ No newline at end of file +}); + +export default router; diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js index 02bac9d..26cd3c4 100644 --- a/ruoyi-ui/src/utils/request.js +++ b/ruoyi-ui/src/utils/request.js @@ -1,115 +1,147 @@ -import axios from 'axios' -import { Notification, MessageBox, Message, Loading } from 'element-ui' -import store from '@/store' -import { getToken } from '@/utils/auth' -import errorCode from '@/utils/errorCode' +import axios from "axios"; +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 cache from '@/plugins/cache' -import { saveAs } from 'file-saver' +import cache from "@/plugins/cache"; +import { saveAs } from "file-saver"; let downloadLoadingInstance; // 是否显示重新登录 export let isRelogin = { show: false }; -axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' +axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8"; // 对应国际化资源文件后缀 -axios.defaults.headers['Content-Language'] = 'zh_CN' +axios.defaults.headers["Content-Language"] = "zh_CN"; // 创建axios实例 const service = axios.create({ // axios中请求配置有baseURL选项,表示请求URL公共部分 baseURL: process.env.VUE_APP_BASE_API, // 超时 - timeout: 10000 -}) + timeout: 10000, +}); // request拦截器 -service.interceptors.request.use(config => { - // 是否需要设置 token - const isToken = (config.headers || {}).isToken === false - // 是否需要防止数据重复提交 - const isRepeatSubmit = (config.headers || {}).repeatSubmit === false - if (getToken() && !isToken) { - config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 - } - // get请求映射params参数 - if (config.method === 'get' && config.params) { - let url = config.url + '?' + tansParams(config.params); - url = url.slice(0, -1); - config.params = {}; - config.url = url; - } - if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { - const requestObj = { - url: config.url, - data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, - time: new Date().getTime() +service.interceptors.request.use( + (config) => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false; + // 是否需要防止数据重复提交 + const isRepeatSubmit = (config.headers || {}).repeatSubmit === false; + if (getToken() && !isToken) { + config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改 } - const sessionObj = cache.session.getJSON('sessionObj') - if (sessionObj === undefined || sessionObj === null || sessionObj === '') { - cache.session.setJSON('sessionObj', requestObj) - } else { - const s_url = sessionObj.url; // 请求地址 - const s_data = sessionObj.data; // 请求数据 - const s_time = sessionObj.time; // 请求时间 - const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 - if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { - const message = '数据正在处理,请勿重复提交'; - console.warn(`[${s_url}]: ` + message) - return Promise.reject(new Error(message)) + // get请求映射params参数 + if (config.method === "get" && config.params) { + let url = config.url + "?" + tansParams(config.params); + url = url.slice(0, -1); + config.params = {}; + config.url = url; + } + if ( + !isRepeatSubmit && + (config.method === "post" || config.method === "put") + ) { + const requestObj = { + url: config.url, + data: + typeof config.data === "object" + ? JSON.stringify(config.data) + : config.data, + time: new Date().getTime(), + }; + const sessionObj = cache.session.getJSON("sessionObj"); + if ( + sessionObj === undefined || + sessionObj === null || + sessionObj === "" + ) { + cache.session.setJSON("sessionObj", requestObj); } else { - cache.session.setJSON('sessionObj', requestObj) + const s_url = sessionObj.url; // 请求地址 + const s_data = sessionObj.data; // 请求数据 + const s_time = sessionObj.time; // 请求时间 + const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 + if ( + s_data === requestObj.data && + requestObj.time - s_time < interval && + s_url === requestObj.url + ) { + const message = "数据正在处理,请勿重复提交"; + console.warn(`[${s_url}]: ` + message); + return Promise.reject(new Error(message)); + } else { + cache.session.setJSON("sessionObj", requestObj); + } } } + return config; + }, + (error) => { + console.log(error); + Promise.reject(error); } - return config -}, error => { - console.log(error) - Promise.reject(error) -}) +); // 响应拦截器 -service.interceptors.response.use(res => { - // 未设置状态码则默认成功状态 - 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) { - if (!isRelogin.show) { - isRelogin.show = true; - MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { - isRelogin.show = false; - store.dispatch('LogOut').then(() => { - location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; - }) - }).catch(() => { - isRelogin.show = false; - }); +service.interceptors.response.use( + (res) => { + // 未设置状态码则默认成功状态 + 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; } - // 保存当前页面的路径,以便登录后重定向 - localStorage.setItem('intendedRoute', router.currentRoute.fullPath); - // Token过期,清除token和用户信息 - store.commit('clearToken'); - store.commit('clearUser'); - return Promise.reject('无效的会话,或者会话已过期,请重新登录。') - } else if (code === 500) { - Message({ message: msg, type: 'error' }) - return Promise.reject(new Error(msg)) - } else if (code === 601) { - Message({ message: msg, type: 'warning' }) - return Promise.reject('error') - } else if (code !== 200) { - Notification.error({ title: msg }) - return Promise.reject('error') - } else { - return res.data - } -}, - error => { - console.log('err' + error) + if (code === 401) { + if (!isRelogin.show) { + isRelogin.show = true; + MessageBox.confirm( + "登录状态已过期,您可以继续留在该页面,或者重新登录", + "系统提示", + { + confirmButtonText: "重新登录", + cancelButtonText: "取消", + type: "warning", + } + ) + .then(() => { + isRelogin.show = false; + store.dispatch("LogOut").then(() => { + location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; + }); + }) + .catch(() => { + isRelogin.show = false; + }); + } + // // 保存当前页面的路径,以便登录后重定向 + // localStorage.setItem("intendedRoute", router.currentRoute.fullPath); + // console.log("需要重定向的路径", router.currentRoute.fullPath); + // // Token过期,清除token和用户信息 + // store.commit("clearToken"); + // store.commit("clearUser"); + return Promise.reject("无效的会话,或者会话已过期,请重新登录。"); + } else if (code === 500) { + Message({ message: msg, type: "error" }); + return Promise.reject(new Error(msg)); + } else if (code === 601) { + Message({ message: msg, type: "warning" }); + return Promise.reject("error"); + } else if (code !== 200) { + Notification.error({ title: msg }); + return Promise.reject("error"); + } else { + return res.data; + } + }, + (error) => { + console.log("err" + error); let { message } = error; if (message == "Network Error") { message = "后端接口连接异常"; @@ -118,42 +150,54 @@ service.interceptors.response.use(res => { } else if (message.includes("Request failed with status code")) { message = "系统接口" + message.substr(message.length - 3) + "异常"; } - Message({ message: message, type: 'error', duration: 5 * 1000 }) - return Promise.reject(error) + Message({ message: message, type: "error", duration: 5 * 1000 }); + return Promise.reject(error); } -) +); // 通用下载方法 export function download(url, params, filename, config) { - 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', - ...config - }).then(async (data) => { - const isBlob = blobValidate(data); - if (isBlob) { - const blob = new Blob([data]) - saveAs(blob, filename) - } else { - const resText = await data.text(); - const rspObj = JSON.parse(resText); - const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] - Message.error(errMsg); - } - downloadLoadingInstance.close(); - }).catch((r) => { - console.error(r) - Message.error('下载文件出现错误,请联系管理员!') - downloadLoadingInstance.close(); - }) + 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", + ...config, + }) + .then(async (data) => { + const isBlob = blobValidate(data); + if (isBlob) { + const blob = new Blob([data]); + saveAs(blob, filename); + } else { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = + errorCode[rspObj.code] || rspObj.msg || errorCode["default"]; + Message.error(errMsg); + } + downloadLoadingInstance.close(); + }) + .catch((r) => { + console.error(r); + Message.error("下载文件出现错误,请联系管理员!"); + downloadLoadingInstance.close(); + }); } //存放全局 if (getToken()) { - window.axios = service - window.axios.defaults.headers['Authorization'] = 'Bearer ' + getToken() + window.axios = service; + window.axios.defaults.headers["Authorization"] = "Bearer " + getToken(); } -export default service +export default service;