调整部分配置,菜单为前端固定路由,无接口无权限配置仅展示用
This commit is contained in:
parent
8207f7b4cd
commit
5ebb858e83
@ -1,8 +1,9 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 后台管理系统
|
||||
VITE_APP_TITLE = 政务云后台管理系统
|
||||
|
||||
# 开发环境配置
|
||||
VITE_APP_ENV = 'development'
|
||||
|
||||
# 开发环境
|
||||
VITE_APP_BASE_API = 'http://192.168.18.9:8080/'
|
||||
VITE_APP_PLATFORM = 'http://192.168.18.99/platform'
|
@ -1,11 +1,12 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 后台管理系统
|
||||
VITE_APP_TITLE = 政务云后台管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'production'
|
||||
|
||||
# 生产环境
|
||||
VITE_APP_BASE_API = 'http://47.109.205.240:8080/'
|
||||
VITE_APP_PLATFORM = 'http://47.109.205.240/platform'
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
VITE_BUILD_COMPRESS = gzip
|
@ -1,5 +1,5 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 后台管理系统
|
||||
VITE_APP_TITLE = 政务云后台管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'staging'
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -19,6 +19,8 @@ selenium-debug.log
|
||||
*.sln
|
||||
*.local
|
||||
*.history
|
||||
*.zip
|
||||
*.rar
|
||||
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
@ -43,7 +43,7 @@ export function getInfo() {
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/auth/logout',
|
||||
method: 'post'
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
|
BIN
src/assets/logo/yunying.png
Normal file
BIN
src/assets/logo/yunying.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
BIN
src/assets/logo/zhengwu.png
Normal file
BIN
src/assets/logo/zhengwu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
12
src/components/icons.vue
Normal file
12
src/components/icons.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="icon in icons" :key="icon" style="display: inline-block; margin: 10px; text-align: center; width: 100px">
|
||||
<component :is="icon" />
|
||||
<div>{{ icon }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as icons from '@element-plus/icons-vue'
|
||||
</script>
|
@ -6,6 +6,8 @@
|
||||
|
||||
<div class="right-menu">
|
||||
<template v-if="appStore.device !== 'mobile'">
|
||||
<div class="right-menu-back" @click="goHome()">门户首页</div>
|
||||
|
||||
<header-search id="header-search" class="right-menu-item" />
|
||||
|
||||
<!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||
@ -33,7 +35,7 @@
|
||||
<el-dropdown @command="handleCommand" class="avatar-container right-menu-item hover-effect" trigger="hover">
|
||||
<div class="avatar-wrapper">
|
||||
<!-- <img :src="userStore.avatar" class="user-avatar" /> -->
|
||||
<span class="user-avatar user-icon">{{ userStore.nickName.slice(0, 1) }}</span>
|
||||
<span class="user-avatar user-icon">{{ userStore.nickName?.slice(0, 1) ?? '管' }}</span>
|
||||
<span class="user-nickname"> {{ userStore.nickName }} </span>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
@ -67,6 +69,7 @@ import RuoYiDoc from '@/components/RuoYi/Doc'
|
||||
import useAppStore from '@/store/modules/app'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
const { VITE_APP_PLATFORM } = import.meta.env;
|
||||
|
||||
const appStore = useAppStore()
|
||||
const userStore = useUserStore()
|
||||
@ -89,6 +92,10 @@ function handleCommand(command) {
|
||||
}
|
||||
}
|
||||
|
||||
function goHome() {
|
||||
window.location.href = VITE_APP_PLATFORM;
|
||||
}
|
||||
|
||||
function logout() {
|
||||
ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
@ -156,6 +163,16 @@ function toggleTheme() {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.right-menu-back {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding-right: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.right-menu-back:hover {
|
||||
color: var(--el-menu-active-color);
|
||||
}
|
||||
|
||||
.right-menu-item {
|
||||
display: inline-block;
|
||||
padding: 0 8px;
|
||||
|
@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<div class="sidebar-logo-container" :class="{ 'collapse': collapse }">
|
||||
<div class="sidebar-logo-container" :class="{ collapse: collapse }">
|
||||
<transition name="sidebarLogoFade">
|
||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
||||
<router-link
|
||||
v-if="collapse"
|
||||
key="collapse"
|
||||
class="sidebar-logo-link"
|
||||
to="/"
|
||||
>
|
||||
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
||||
<h1 v-else class="sidebar-title">{{ title }}</h1>
|
||||
</router-link>
|
||||
@ -14,40 +19,61 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import logo from '@/assets/logo/logo.png'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
import variables from '@/assets/styles/variables.module.scss'
|
||||
import { computed, reactive, onMounted } from "vue";
|
||||
import logo from "@/assets/logo/zhengwu.png";
|
||||
import logoY from "@/assets/logo/yunying.png";
|
||||
import useSettingsStore from "@/store/modules/settings";
|
||||
import variables from "@/assets/styles/variables.module.scss";
|
||||
|
||||
defineProps({
|
||||
collapse: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const title = import.meta.env.VITE_APP_TITLE
|
||||
const settingsStore = useSettingsStore()
|
||||
const sideTheme = computed(() => settingsStore.sideTheme)
|
||||
const title = import.meta.env.VITE_APP_TITLE;
|
||||
const settingsStore = useSettingsStore();
|
||||
const sideTheme = computed(() => settingsStore.sideTheme);
|
||||
|
||||
// 获取Logo背景色
|
||||
const getLogoBackground = computed(() => {
|
||||
if (settingsStore.isDark) {
|
||||
return 'var(--sidebar-bg)'
|
||||
return "var(--sidebar-bg)";
|
||||
}
|
||||
return sideTheme.value === 'theme-dark' ? variables.menuBg : variables.menuLightBg
|
||||
})
|
||||
return sideTheme.value === "theme-dark"
|
||||
? variables.menuBg
|
||||
: variables.menuLightBg;
|
||||
});
|
||||
|
||||
// 获取Logo文字颜色
|
||||
const getLogoTextColor = computed(() => {
|
||||
if (settingsStore.isDark) {
|
||||
return 'var(--sidebar-text)'
|
||||
return "var(--sidebar-text)";
|
||||
}
|
||||
return sideTheme.value === 'theme-dark' ? '#fff' : variables.menuLightText
|
||||
})
|
||||
return sideTheme.value === "theme-dark" ? "#fff" : variables.menuLightText;
|
||||
});
|
||||
|
||||
// 获取用户这里用于临时根据账户判断角色,显示不同logo图片【没其他用途】
|
||||
import { getUserProfile } from "@/api/system/user";
|
||||
const state = reactive({
|
||||
user: {},
|
||||
roleGroup: {},
|
||||
postGroup: {},
|
||||
});
|
||||
function getUser() {
|
||||
getUserProfile().then((response) => {
|
||||
state.user = response.data;
|
||||
state.roleGroup = response.roleGroup;
|
||||
state.postGroup = response.postGroup;
|
||||
console.log(state.user); // 获取用户信息
|
||||
});
|
||||
}
|
||||
getUser();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/styles/variables.module.scss';
|
||||
@import "@/assets/styles/variables.module.scss";
|
||||
|
||||
.sidebarLogoFade-enter-active {
|
||||
transition: opacity 1.5s;
|
||||
@ -96,4 +122,4 @@ const getLogoTextColor = computed(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
@ -14,7 +14,7 @@
|
||||
:class="sideTheme"
|
||||
>
|
||||
<sidebar-item
|
||||
v-for="(route, index) in sidebarRouters"
|
||||
v-for="(route, index) in baseRoutes"
|
||||
:key="route.path + index"
|
||||
:item="route"
|
||||
:base-path="route.path"
|
||||
@ -25,53 +25,276 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Logo from './Logo'
|
||||
import SidebarItem from './SidebarItem'
|
||||
import variables from '@/assets/styles/variables.module.scss'
|
||||
import useAppStore from '@/store/modules/app'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
import usePermissionStore from '@/store/modules/permission'
|
||||
import { onMounted, nextTick } from "vue";
|
||||
import Logo from "./Logo";
|
||||
import SidebarItem from "./SidebarItem";
|
||||
import variables from "@/assets/styles/variables.module.scss";
|
||||
import useAppStore from "@/store/modules/app";
|
||||
import useSettingsStore from "@/store/modules/settings";
|
||||
import usePermissionStore from "@/store/modules/permission";
|
||||
|
||||
const route = useRoute()
|
||||
const appStore = useAppStore()
|
||||
const settingsStore = useSettingsStore()
|
||||
const permissionStore = usePermissionStore()
|
||||
const route = useRoute();
|
||||
const appStore = useAppStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const permissionStore = usePermissionStore();
|
||||
|
||||
const sidebarRouters = computed(() => permissionStore.sidebarRouters)
|
||||
const showLogo = computed(() => settingsStore.sidebarLogo)
|
||||
const sideTheme = computed(() => settingsStore.sideTheme)
|
||||
const theme = computed(() => settingsStore.theme)
|
||||
const isCollapse = computed(() => !appStore.sidebar.opened)
|
||||
const baseRoutes = ref([]);
|
||||
const sidebarRouters = computed(() => permissionStore.sidebarRouters);
|
||||
const showLogo = computed(() => settingsStore.sidebarLogo);
|
||||
const sideTheme = computed(() => settingsStore.sideTheme);
|
||||
const theme = computed(() => settingsStore.theme);
|
||||
const isCollapse = computed(() => !appStore.sidebar.opened);
|
||||
|
||||
import { ref } from "vue";
|
||||
import { reactive } from "vue";
|
||||
// 下面测试用
|
||||
const yunying = reactive([
|
||||
{
|
||||
component: "Layout",
|
||||
hidden: false,
|
||||
path: "/plant",
|
||||
alwaysShow: true,
|
||||
name: "Plant",
|
||||
redirect: "noRedirect",
|
||||
meta: {
|
||||
icon: "trace",
|
||||
link: null,
|
||||
noCache: false,
|
||||
title: "智慧种植",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
component: "plant/ambient",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "农业环境监测",
|
||||
icon: "",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Ambient",
|
||||
path: "ambient",
|
||||
},
|
||||
{
|
||||
component: "plant/control",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "生产管理控制",
|
||||
icon: "",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Control",
|
||||
path: "control",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: "Layout",
|
||||
hidden: false,
|
||||
path: "/trade",
|
||||
alwaysShow: true,
|
||||
name: "Trade",
|
||||
redirect: "noRedirect",
|
||||
meta: {
|
||||
icon: "trace",
|
||||
link: null,
|
||||
noCache: false,
|
||||
title: "电商交易",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
component: "trade/agriculturalinputstrading",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "农资交易",
|
||||
icon: "",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Agriculturalinputstrading",
|
||||
path: "agriculturalinputstrading",
|
||||
},
|
||||
{
|
||||
component: "trade/supplierServices",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "供应商服务",
|
||||
icon: "",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "SupplierServices",
|
||||
path: "supplierServices",
|
||||
},
|
||||
{
|
||||
component: "trade/procurementServices",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "采购商服务",
|
||||
icon: "",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "ProcurementServices",
|
||||
path: "procurementServices",
|
||||
},
|
||||
{
|
||||
component: "trade/landTransaction",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "土地交易",
|
||||
icon: "",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "LandTransaction",
|
||||
path: "landTransaction",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: "Layout",
|
||||
hidden: false,
|
||||
path: "/",
|
||||
children: [
|
||||
{
|
||||
component: "brand/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "投入品监管平台",
|
||||
icon: "",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Brand",
|
||||
path: "brand",
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
// 下面测试用
|
||||
const zhengwu = reactive([
|
||||
{
|
||||
component: "Layout",
|
||||
hidden: false,
|
||||
path: "/",
|
||||
name: "mainbody",
|
||||
children: [
|
||||
{
|
||||
component: "mainbody/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "生产经营主体",
|
||||
icon: "icon-entities",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Mainbody",
|
||||
path: "mainbody",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: "Layout",
|
||||
hidden: false,
|
||||
path: "/",
|
||||
children: [
|
||||
{
|
||||
component: "inputs/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "投入品监管平台",
|
||||
icon: "icon-input",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Inputs",
|
||||
path: "inputs",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: "Layout",
|
||||
hidden: false,
|
||||
path: "/",
|
||||
alwaysShow: true,
|
||||
name: "Trace",
|
||||
redirect: "noRedirect",
|
||||
meta: {
|
||||
icon: "trace",
|
||||
link: null,
|
||||
noCache: false,
|
||||
title: "溯源管理",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
component: "traceability/query",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "溯源查询",
|
||||
icon: "icon-search",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Query",
|
||||
path: "query",
|
||||
},
|
||||
{
|
||||
component: "traceability/statistics",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "溯源统计",
|
||||
icon: "icon-data",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Statistics",
|
||||
path: "statistics",
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
// 获取菜单背景色
|
||||
const getMenuBackground = computed(() => {
|
||||
if (settingsStore.isDark) {
|
||||
return 'var(--sidebar-bg)'
|
||||
return "var(--sidebar-bg)";
|
||||
}
|
||||
return sideTheme.value === 'theme-dark' ? variables.menuBg : variables.menuLightBg
|
||||
})
|
||||
return sideTheme.value === "theme-dark"
|
||||
? variables.menuBg
|
||||
: variables.menuLightBg;
|
||||
});
|
||||
|
||||
// 获取菜单文字颜色
|
||||
const getMenuTextColor = computed(() => {
|
||||
if (settingsStore.isDark) {
|
||||
return 'var(--sidebar-text)'
|
||||
return "var(--sidebar-text)";
|
||||
}
|
||||
return sideTheme.value === 'theme-dark' ? variables.menuText : variables.menuLightText
|
||||
})
|
||||
return sideTheme.value === "theme-dark"
|
||||
? variables.menuText
|
||||
: variables.menuLightText;
|
||||
});
|
||||
|
||||
const activeMenu = computed(() => {
|
||||
const { meta, path } = route
|
||||
const { meta, path } = route;
|
||||
if (meta.activeMenu) {
|
||||
return meta.activeMenu
|
||||
return meta.activeMenu;
|
||||
}
|
||||
return path
|
||||
})
|
||||
return path;
|
||||
});
|
||||
onMounted(async () => {
|
||||
baseRoutes.value = [...sidebarRouters.value];
|
||||
await nextTick();
|
||||
console.log("政务云菜单");
|
||||
console.log(baseRoutes.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.sidebar-container {
|
||||
background-color: v-bind(getMenuBackground);
|
||||
|
||||
|
||||
.scrollbar-wrapper {
|
||||
background-color: v-bind(getMenuBackground);
|
||||
}
|
||||
@ -80,8 +303,9 @@ const activeMenu = computed(() => {
|
||||
border: none;
|
||||
height: 100%;
|
||||
width: 100% !important;
|
||||
|
||||
.el-menu-item, .el-sub-menu__title {
|
||||
|
||||
.el-menu-item,
|
||||
.el-sub-menu__title {
|
||||
&:hover {
|
||||
background-color: var(--menu-hover, rgba(0, 0, 0, 0.06)) !important;
|
||||
}
|
||||
@ -89,7 +313,7 @@ const activeMenu = computed(() => {
|
||||
|
||||
.el-menu-item {
|
||||
color: v-bind(getMenuTextColor);
|
||||
|
||||
|
||||
&.is-active {
|
||||
color: var(--menu-active-text, #409eff);
|
||||
background-color: var(--menu-hover, rgba(0, 0, 0, 0.06)) !important;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createWebHistory, createRouter } from 'vue-router'
|
||||
import { createWebHistory, createRouter } from "vue-router";
|
||||
/* Layout */
|
||||
import Layout from '@/layout'
|
||||
import Layout from "@/layout";
|
||||
|
||||
/**
|
||||
* Note: 路由配置项
|
||||
@ -27,148 +27,233 @@ import Layout from '@/layout'
|
||||
// 公共路由
|
||||
export const constantRoutes = [
|
||||
{
|
||||
path: '/redirect',
|
||||
path: "/redirect",
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path(.*)',
|
||||
component: () => import('@/views/redirect/index.vue')
|
||||
}
|
||||
]
|
||||
path: "/redirect/:path(.*)",
|
||||
component: () => import("@/views/redirect/index.vue"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import('@/views/login'),
|
||||
hidden: true
|
||||
path: "/login",
|
||||
component: () => import("@/views/login"),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
component: () => import('@/views/register'),
|
||||
hidden: true
|
||||
path: "/register",
|
||||
component: () => import("@/views/register"),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: "/:pathMatch(.*)*",
|
||||
component: () => import('@/views/error/404'),
|
||||
hidden: true
|
||||
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: "/icons",
|
||||
component: () => import("@/components/icons"),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
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: '/user',
|
||||
path: "/user",
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
redirect: 'noredirect',
|
||||
redirect: "noredirect",
|
||||
children: [
|
||||
{
|
||||
path: 'profile/:activeTab?',
|
||||
component: () => import('@/views/system/user/profile/index'),
|
||||
name: 'Profile',
|
||||
meta: { title: '个人中心', icon: 'user' }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
path: "profile/:activeTab?",
|
||||
component: () => import("@/views/system/user/profile/index"),
|
||||
name: "Profile",
|
||||
meta: { title: "个人中心", icon: "user" },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/mainbody",
|
||||
name: "mainbody",
|
||||
component: Layout,
|
||||
hidden: false,
|
||||
children: [
|
||||
{
|
||||
path: "mainbody/index",
|
||||
component: () => import("@/views/mainbody/index"),
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "生产经营主体",
|
||||
icon: "user",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "mainbody",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/inputs",
|
||||
name: "inputs",
|
||||
component: Layout,
|
||||
hidden: false,
|
||||
children: [
|
||||
{
|
||||
path: "inputs/index",
|
||||
component: () => import("@/views/inputs/index"),
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "投入品监管平台",
|
||||
icon: "tree",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "index",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/traceability",
|
||||
name: "traceability",
|
||||
component: Layout,
|
||||
hidden: false,
|
||||
alwaysShow: true,
|
||||
redirect: "noredirect",
|
||||
meta: {
|
||||
icon: "tree-table",
|
||||
link: null,
|
||||
noCache: false,
|
||||
title: "溯源管理",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "traceability/query",
|
||||
component: () => import("@/views/traceability/query"),
|
||||
name: "query",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "溯源查询",
|
||||
icon: "",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "traceability/statistics",
|
||||
component: () => import("@/views/traceability/statistics"),
|
||||
name: "溯源统计",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "生产管理控制",
|
||||
icon: "icon-data",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// 动态路由,基于用户权限动态去加载
|
||||
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: '/monitor/job-log',
|
||||
path: "/monitor/job-log",
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['monitor:job:list'],
|
||||
permissions: ["monitor:job:list"],
|
||||
children: [
|
||||
{
|
||||
path: 'index/:jobId(\\d+)',
|
||||
component: () => import('@/views/monitor/job/log'),
|
||||
name: 'JobLog',
|
||||
meta: { title: '调度日志', activeMenu: '/monitor/job' }
|
||||
}
|
||||
]
|
||||
path: "index/:jobId(\\d+)",
|
||||
component: () => import("@/views/monitor/job/log"),
|
||||
name: "JobLog",
|
||||
meta: { title: "调度日志", activeMenu: "/monitor/job" },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
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" },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: constantRoutes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
return savedPosition;
|
||||
}
|
||||
return { top: 0 }
|
||||
return { top: 0 };
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
export default router
|
||||
export default router;
|
||||
|
@ -1,127 +1,263 @@
|
||||
import auth from '@/plugins/auth'
|
||||
import router, { constantRoutes, dynamicRoutes } from '@/router'
|
||||
import { getRouters } from '@/api/menu'
|
||||
import Layout from '@/layout/index'
|
||||
import ParentView from '@/components/ParentView'
|
||||
import InnerLink from '@/layout/components/InnerLink'
|
||||
import auth from "@/plugins/auth";
|
||||
import router, { constantRoutes, dynamicRoutes } from "@/router";
|
||||
import { getRouters } from "@/api/menu";
|
||||
import Layout from "@/layout/index";
|
||||
import ParentView from "@/components/ParentView";
|
||||
import InnerLink from "@/layout/components/InnerLink";
|
||||
|
||||
// 匹配views里面所有的.vue文件
|
||||
const modules = import.meta.glob('./../../views/**/*.vue')
|
||||
const modules = import.meta.glob("./../../views/**/*.vue");
|
||||
|
||||
const usePermissionStore = defineStore(
|
||||
'permission',
|
||||
{
|
||||
state: () => ({
|
||||
routes: [],
|
||||
addRoutes: [],
|
||||
defaultRoutes: [],
|
||||
topbarRouters: [],
|
||||
sidebarRouters: []
|
||||
}),
|
||||
actions: {
|
||||
setRoutes(routes) {
|
||||
this.addRoutes = routes
|
||||
this.routes = constantRoutes.concat(routes)
|
||||
},
|
||||
setDefaultRoutes(routes) {
|
||||
this.defaultRoutes = constantRoutes.concat(routes)
|
||||
},
|
||||
setTopbarRoutes(routes) {
|
||||
this.topbarRouters = routes
|
||||
},
|
||||
setSidebarRouters(routes) {
|
||||
this.sidebarRouters = routes
|
||||
},
|
||||
generateRoutes(roles) {
|
||||
return new Promise(resolve => {
|
||||
// 向后端请求路由数据
|
||||
getRouters().then(res => {
|
||||
const sdata = JSON.parse(JSON.stringify(res.data))
|
||||
const rdata = JSON.parse(JSON.stringify(res.data))
|
||||
const defaultData = JSON.parse(JSON.stringify(res.data))
|
||||
const sidebarRoutes = filterAsyncRouter(sdata)
|
||||
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
|
||||
const defaultRoutes = filterAsyncRouter(defaultData)
|
||||
const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
|
||||
asyncRoutes.forEach(route => { router.addRoute(route) })
|
||||
this.setRoutes(rewriteRoutes)
|
||||
this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
|
||||
this.setDefaultRoutes(sidebarRoutes)
|
||||
this.setTopbarRoutes(defaultRoutes)
|
||||
resolve(rewriteRoutes)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
const usePermissionStore = defineStore("permission", {
|
||||
state: () => ({
|
||||
routes: [],
|
||||
addRoutes: [],
|
||||
defaultRoutes: [],
|
||||
topbarRouters: [],
|
||||
sidebarRouters: [],
|
||||
}),
|
||||
actions: {
|
||||
setRoutes(routes) {
|
||||
this.addRoutes = routes;
|
||||
this.routes = constantRoutes.concat(routes);
|
||||
},
|
||||
setDefaultRoutes(routes) {
|
||||
this.defaultRoutes = constantRoutes.concat(routes);
|
||||
},
|
||||
setTopbarRoutes(routes) {
|
||||
this.topbarRouters = routes;
|
||||
},
|
||||
setSidebarRouters(routes) {
|
||||
this.sidebarRouters = routes;
|
||||
},
|
||||
generateRoutes(roles) {
|
||||
return new Promise((resolve) => {
|
||||
// 向后端请求路由数据
|
||||
// getRouters().then(res => {
|
||||
// const sdata = JSON.parse(JSON.stringify(res.data))
|
||||
// const rdata = JSON.parse(JSON.stringify(res.data))
|
||||
// const defaultData = JSON.parse(JSON.stringify(res.data))
|
||||
// const sidebarRoutes = filterAsyncRouter(sdata)
|
||||
// const rewriteRoutes = filterAsyncRouter(rdata, false, true)
|
||||
// const defaultRoutes = filterAsyncRouter(defaultData)
|
||||
// const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
|
||||
// asyncRoutes.forEach(route => { router.addRoute(route) })
|
||||
// this.setRoutes(rewriteRoutes)
|
||||
// this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
|
||||
// this.setDefaultRoutes(sidebarRoutes)
|
||||
// this.setTopbarRoutes(defaultRoutes)
|
||||
// resolve(rewriteRoutes)
|
||||
// })
|
||||
|
||||
// 改为固定菜单数据演示用
|
||||
const res = {
|
||||
code: 200,
|
||||
msg: "success",
|
||||
data: [
|
||||
{
|
||||
alwaysShow: true,
|
||||
path: "/system",
|
||||
component: "Layout",
|
||||
redirect: "noRedirect",
|
||||
name: "System",
|
||||
hidden: false,
|
||||
meta: {
|
||||
icon: "system",
|
||||
link: null,
|
||||
noCache: false,
|
||||
title: "系统管理",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
component: "system/user/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "用户管理",
|
||||
icon: "user",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "User",
|
||||
path: "user",
|
||||
},
|
||||
{
|
||||
component: "system/role/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "角色管理",
|
||||
icon: "peoples",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Role",
|
||||
path: "role",
|
||||
},
|
||||
{
|
||||
component: "system/menu/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "菜单管理",
|
||||
icon: "tree-table",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Menu",
|
||||
path: "menu",
|
||||
},
|
||||
{
|
||||
component: "system/dept/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "部门管理",
|
||||
icon: "tree",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Dept",
|
||||
path: "dept",
|
||||
},
|
||||
{
|
||||
component: "system/notice/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "通知公告",
|
||||
icon: "message",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Notice",
|
||||
path: "notice",
|
||||
},
|
||||
{
|
||||
component: "ParentView",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "日志管理",
|
||||
icon: "log",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Log",
|
||||
path: "log",
|
||||
children: [
|
||||
{
|
||||
component: "monitor/operlog/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "操作日志",
|
||||
icon: "form",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Operlog",
|
||||
path: "operlog",
|
||||
},
|
||||
{
|
||||
component: "monitor/logininfor/index",
|
||||
hidden: false,
|
||||
meta: {
|
||||
title: "登录日志",
|
||||
icon: "logininfor",
|
||||
noCache: false,
|
||||
link: null,
|
||||
},
|
||||
name: "Logininfor",
|
||||
path: "logininfor",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const sdata = JSON.parse(JSON.stringify(res.data));
|
||||
const rdata = JSON.parse(JSON.stringify(res.data));
|
||||
const defaultData = JSON.parse(JSON.stringify(res.data));
|
||||
const sidebarRoutes = filterAsyncRouter(sdata);
|
||||
const rewriteRoutes = filterAsyncRouter(rdata, false, true);
|
||||
const defaultRoutes = filterAsyncRouter(defaultData);
|
||||
const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
|
||||
asyncRoutes.forEach((route) => {
|
||||
router.addRoute(route);
|
||||
});
|
||||
this.setRoutes(rewriteRoutes);
|
||||
this.setSidebarRouters(constantRoutes.concat(sidebarRoutes));
|
||||
this.setDefaultRoutes(sidebarRoutes);
|
||||
this.setTopbarRoutes(defaultRoutes);
|
||||
resolve(rewriteRoutes);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 遍历后台传来的路由字符串,转换为组件对象
|
||||
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
|
||||
return asyncRouterMap.filter(route => {
|
||||
return asyncRouterMap.filter((route) => {
|
||||
if (type && route.children) {
|
||||
route.children = filterChildren(route.children)
|
||||
route.children = filterChildren(route.children);
|
||||
}
|
||||
if (route.component) {
|
||||
// Layout ParentView 组件特殊处理
|
||||
if (route.component === 'Layout') {
|
||||
route.component = Layout
|
||||
} else if (route.component === 'ParentView') {
|
||||
route.component = ParentView
|
||||
} else if (route.component === 'InnerLink') {
|
||||
route.component = InnerLink
|
||||
if (route.component === "Layout") {
|
||||
route.component = Layout;
|
||||
} else if (route.component === "ParentView") {
|
||||
route.component = ParentView;
|
||||
} else if (route.component === "InnerLink") {
|
||||
route.component = InnerLink;
|
||||
} else {
|
||||
route.component = loadView(route.component)
|
||||
route.component = loadView(route.component);
|
||||
}
|
||||
}
|
||||
if (route.children != null && route.children && route.children.length) {
|
||||
route.children = filterAsyncRouter(route.children, route, type)
|
||||
route.children = filterAsyncRouter(route.children, route, type);
|
||||
} else {
|
||||
delete route['children']
|
||||
delete route['redirect']
|
||||
delete route["children"];
|
||||
delete route["redirect"];
|
||||
}
|
||||
return true
|
||||
})
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function filterChildren(childrenMap, lastRouter = false) {
|
||||
var children = []
|
||||
childrenMap.forEach(el => {
|
||||
el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path
|
||||
if (el.children && el.children.length && el.component === 'ParentView') {
|
||||
children = children.concat(filterChildren(el.children, el))
|
||||
var children = [];
|
||||
childrenMap.forEach((el) => {
|
||||
el.path = lastRouter ? lastRouter.path + "/" + el.path : el.path;
|
||||
if (el.children && el.children.length && el.component === "ParentView") {
|
||||
children = children.concat(filterChildren(el.children, el));
|
||||
} else {
|
||||
children.push(el)
|
||||
children.push(el);
|
||||
}
|
||||
})
|
||||
return children
|
||||
});
|
||||
return children;
|
||||
}
|
||||
|
||||
// 动态路由遍历,验证是否具备权限
|
||||
export function filterDynamicRoutes(routes) {
|
||||
const res = []
|
||||
routes.forEach(route => {
|
||||
const res = [];
|
||||
routes.forEach((route) => {
|
||||
if (route.permissions) {
|
||||
if (auth.hasPermiOr(route.permissions)) {
|
||||
res.push(route)
|
||||
res.push(route);
|
||||
}
|
||||
} else if (route.roles) {
|
||||
if (auth.hasRoleOr(route.roles)) {
|
||||
res.push(route)
|
||||
res.push(route);
|
||||
}
|
||||
}
|
||||
})
|
||||
return res
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
export const loadView = (view) => {
|
||||
let res
|
||||
let res;
|
||||
for (const path in modules) {
|
||||
const dir = path.split('views/')[1].split('.vue')[0]
|
||||
const dir = path.split("views/")[1].split(".vue")[0];
|
||||
if (dir === view) {
|
||||
res = () => modules[path]()
|
||||
res = () => modules[path]();
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default usePermissionStore
|
||||
export default usePermissionStore;
|
||||
|
@ -1,95 +1,125 @@
|
||||
import router from '@/router'
|
||||
import { ElMessageBox, } from 'element-plus'
|
||||
import { login, logout, getInfo } from '@/api/login'
|
||||
import { getToken, setToken, removeToken } from '@/utils/auth'
|
||||
import { isHttp, isEmpty } from "@/utils/validate"
|
||||
import defAva from '@/assets/images/profile.jpg'
|
||||
import router from "@/router";
|
||||
import { ElMessageBox } from "element-plus";
|
||||
import { login, logout, getInfo } from "@/api/login";
|
||||
import { getToken, setToken, removeToken } from "@/utils/auth";
|
||||
import { isHttp, isEmpty } from "@/utils/validate";
|
||||
import defAva from "@/assets/images/profile.jpg";
|
||||
|
||||
const useUserStore = defineStore(
|
||||
'user',
|
||||
{
|
||||
state: () => ({
|
||||
token: getToken(),
|
||||
id: '',
|
||||
name: '',
|
||||
nickName: '',
|
||||
avatar: '',
|
||||
roles: [],
|
||||
permissions: []
|
||||
}),
|
||||
actions: {
|
||||
// 登录
|
||||
login(userInfo) {
|
||||
const username = userInfo.username.trim()
|
||||
const password = userInfo.password
|
||||
const code = userInfo.code
|
||||
const uuid = userInfo.uuid
|
||||
return new Promise((resolve, reject) => {
|
||||
login(username, password, code, uuid).then(res => {
|
||||
console.log(res.data.access_token)
|
||||
setToken(res.data.access_token)
|
||||
this.token = res.data.access_token
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
const useUserStore = defineStore("user", {
|
||||
state: () => ({
|
||||
token: getToken(),
|
||||
id: "",
|
||||
name: "",
|
||||
nickName: "",
|
||||
avatar: "",
|
||||
roles: [],
|
||||
permissions: [],
|
||||
}),
|
||||
actions: {
|
||||
// 登录
|
||||
login(userInfo) {
|
||||
const username = userInfo.username.trim();
|
||||
const password = userInfo.password;
|
||||
const code = userInfo.code;
|
||||
const uuid = userInfo.uuid;
|
||||
return new Promise((resolve, reject) => {
|
||||
login(username, password, code, uuid)
|
||||
.then((res) => {
|
||||
console.log(res.data.access_token);
|
||||
setToken(res.data.access_token);
|
||||
this.token = res.data.access_token;
|
||||
resolve();
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取用户信息
|
||||
getInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInfo().then(res => {
|
||||
const user = res.user
|
||||
let avatar = user.avatar || ""
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
// 获取用户信息
|
||||
getInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInfo()
|
||||
.then((res) => {
|
||||
const user = res.user;
|
||||
let avatar = user.avatar || "";
|
||||
if (!isHttp(avatar)) {
|
||||
avatar = (isEmpty(avatar)) ? defAva : import.meta.env.VITE_APP_BASE_API + avatar
|
||||
avatar = isEmpty(avatar)
|
||||
? defAva
|
||||
: import.meta.env.VITE_APP_BASE_API + avatar;
|
||||
}
|
||||
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
this.roles = res.roles
|
||||
this.permissions = res.permissions
|
||||
if (res.roles && res.roles.length > 0) {
|
||||
// 验证返回的roles是否是一个非空数组
|
||||
this.roles = res.roles;
|
||||
this.permissions = res.permissions;
|
||||
} else {
|
||||
this.roles = ['ROLE_DEFAULT']
|
||||
this.roles = ["ROLE_DEFAULT"];
|
||||
}
|
||||
this.id = user.userId
|
||||
this.name = user.userName
|
||||
this.nickName = user.nickName
|
||||
this.avatar = avatar
|
||||
this.id = user.userId;
|
||||
this.name = user.userName;
|
||||
this.nickName = user.nickName;
|
||||
this.avatar = avatar;
|
||||
/* 初始密码提示 */
|
||||
if(res.isDefaultModifyPwd) {
|
||||
ElMessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||
}).catch(() => {})
|
||||
if (res.isDefaultModifyPwd) {
|
||||
ElMessageBox.confirm(
|
||||
"您的密码还是初始密码,请修改密码!",
|
||||
"安全提示",
|
||||
{
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
router.push({
|
||||
name: "Profile",
|
||||
params: { activeTab: "resetPwd" },
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
/* 过期密码提示 */
|
||||
if(!res.isDefaultModifyPwd && res.isPasswordExpired) {
|
||||
ElMessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||
}).catch(() => {})
|
||||
if (!res.isDefaultModifyPwd && res.isPasswordExpired) {
|
||||
ElMessageBox.confirm(
|
||||
"您的密码已过期,请尽快修改密码!",
|
||||
"安全提示",
|
||||
{
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
router.push({
|
||||
name: "Profile",
|
||||
params: { activeTab: "resetPwd" },
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
resolve(res)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
resolve(res);
|
||||
})
|
||||
})
|
||||
},
|
||||
// 退出系统
|
||||
logOut() {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// logout(this.token).then(() => {
|
||||
// this.token = ''
|
||||
// this.roles = []
|
||||
// this.permissions = []
|
||||
// removeToken()
|
||||
// resolve()
|
||||
// }).catch(error => {
|
||||
// reject(error)
|
||||
// })
|
||||
// })
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
// 退出系统
|
||||
logOut() {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// logout(this.token).then(() => {
|
||||
// this.token = ''
|
||||
// this.roles = []
|
||||
// this.permissions = []
|
||||
// removeToken()
|
||||
// resolve()
|
||||
// }).catch(error => {
|
||||
// reject(error)
|
||||
// })
|
||||
// })
|
||||
removeToken();
|
||||
location.href = "/index";
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
removeToken()
|
||||
location.href = '/index'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default useUserStore
|
||||
export default useUserStore;
|
||||
|
@ -2,22 +2,22 @@
|
||||
<div class="app-container home">
|
||||
<el-row :gutter="20">
|
||||
<el-col :sm="24" :lg="16" style="padding-left: 20px">
|
||||
<h2>后台管理系统</h2>
|
||||
<p>后台管理系统 是为政府机关、事业单位及公共服务机构量身打造的一体化智能管理平台,旨在提升政务办公效率、优化业务流程、保障数据安全,实现政务服务的数字化、规范化和透明化。</p>
|
||||
<b>
|
||||
核心功能
|
||||
</b>
|
||||
<h2>农业产业政务云平台 - 后台管理系统</h2>
|
||||
<p>
|
||||
✅ 权限分级管理:支持多角色(如超级管理员、部门管理员、审核员)精细化权限控制,确保数据安全与操作合规。<br>
|
||||
✅ 业务协同办理:集成公文流转、事项审批、数据填报等功能,实现跨部门高效协作。<br>
|
||||
✅ 数据可视化分析:动态展示民生服务、财政支出等关键指标,辅助科学决策。<br>
|
||||
✅ 安全审计追溯:操作日志全记录,支持敏感行为预警与责任追溯,符合等保要求。<br>
|
||||
✅ 移动端适配:支持PC端与移动端同步办公,满足紧急事务处理需求。
|
||||
是为县域监管部门打造的一体化智能管理平台,旨在提升农业政务监管效率、优化业务流程、保障数据安全,实现农业产业监管的数字化、规范化和透明化。
|
||||
</p>
|
||||
<b> 核心功能 </b>
|
||||
<p>
|
||||
✅ 权限分级管理:支持多角色(如超级管理员、部门管理员、审核员)精细化权限控制,确保数据安全与操作合规。<br />
|
||||
✅ 业务协同办理:集成工单流转、事项审批、数据填报等功能,实现跨域高效协作。<br />
|
||||
✅ 数据可视化分析:动态展示农资监管、农产品溯源等关键要素,辅助监管部门管理决策。<br />
|
||||
✅ 安全审计追溯:操作日志全记录,支持敏感行为预警与责任追溯,符合等保要求。<br />
|
||||
✅ 移动端适配:支持PC端与移动端同步操作,满足农业监管事务处理需求。
|
||||
</p>
|
||||
<b>系统价值</b>
|
||||
<p>
|
||||
🔹 提效减负:自动化流程减少人工干预,缩短办事周期。<br>
|
||||
🔹 阳光政务:全流程电子化留痕,增强公众监督与信任。<br>
|
||||
🔹 提效减负:自动化流程减少人工干预,缩短办事周期。<br />
|
||||
🔹 阳光政务:全流程电子化留痕,增强公众监督与信任。<br />
|
||||
🔹 资源整合:打破信息孤岛,实现跨系统数据互通共享。
|
||||
</p>
|
||||
<p>
|
||||
@ -76,7 +76,7 @@
|
||||
>http://192.168.18.99:88/platform</el-link
|
||||
>
|
||||
</p>
|
||||
<div style="height: 200px;"></div>
|
||||
<div style="height: 200px"></div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
@ -263,7 +263,7 @@
|
||||
<span>客户端</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="body" v-if="state.user.userName == 'super'">
|
||||
<div class="body">
|
||||
<img
|
||||
src="@/assets/images/MXd3uUrO.png"
|
||||
alt="donate"
|
||||
@ -271,14 +271,14 @@
|
||||
/>
|
||||
<p style="width: 200px; text-align: center">政务云APP客户端</p>
|
||||
</div>
|
||||
<div class="body" v-else>
|
||||
<!-- <div class="body" v-else>
|
||||
<img
|
||||
src="@/assets/images/4SVVtpob.png"
|
||||
alt="donate"
|
||||
style="width: 196px"
|
||||
/>
|
||||
<p style="width: 200px; text-align: center">运营云APP客户端</p>
|
||||
</div>
|
||||
</div> -->
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -286,22 +286,24 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Index">
|
||||
const version = ref("1.0.1");
|
||||
import { getUserProfile } from "@/api/system/user"
|
||||
const version = ref("4.0.1");
|
||||
|
||||
// 获取用户这里用于临时根据账户判断角色,显示不同客户端app下载图片【没其他用途】
|
||||
import { getUserProfile } from "@/api/system/user";
|
||||
const state = reactive({
|
||||
user: {},
|
||||
roleGroup: {},
|
||||
postGroup: {}
|
||||
})
|
||||
postGroup: {},
|
||||
});
|
||||
function getUser() {
|
||||
getUserProfile().then(response => {
|
||||
state.user = response.data
|
||||
state.roleGroup = response.roleGroup
|
||||
state.postGroup = response.postGroup
|
||||
console.log(state.user) // 获取用户信息
|
||||
})
|
||||
getUserProfile().then((response) => {
|
||||
state.user = response.data;
|
||||
state.roleGroup = response.roleGroup;
|
||||
state.postGroup = response.postGroup;
|
||||
console.log(state.user); // 获取用户信息
|
||||
});
|
||||
}
|
||||
getUser()
|
||||
getUser();
|
||||
|
||||
function goTarget(url) {
|
||||
window.open(url, "__blank");
|
||||
|
256
src/views/login copy.vue
Normal file
256
src/views/login copy.vue
Normal file
@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div class="login">
|
||||
<el-form
|
||||
ref="loginRef"
|
||||
:model="loginForm"
|
||||
:rules="loginRules"
|
||||
class="login-form"
|
||||
>
|
||||
<h3 class="title">{{ title }}</h3>
|
||||
<el-form-item prop="username">
|
||||
<el-input
|
||||
v-model="loginForm.username"
|
||||
type="text"
|
||||
size="large"
|
||||
auto-complete="off"
|
||||
placeholder="账号"
|
||||
>
|
||||
<template #prefix
|
||||
><svg-icon icon-class="user" class="el-input__icon input-icon"
|
||||
/></template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
v-model="loginForm.password"
|
||||
type="password"
|
||||
size="large"
|
||||
auto-complete="off"
|
||||
placeholder="密码"
|
||||
@keyup.enter="handleLogin"
|
||||
>
|
||||
<template #prefix
|
||||
><svg-icon icon-class="password" class="el-input__icon input-icon"
|
||||
/></template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item prop="code" v-if="captchaEnabled">
|
||||
<el-input
|
||||
v-model="loginForm.code"
|
||||
size="large"
|
||||
auto-complete="off"
|
||||
placeholder="验证码"
|
||||
style="width: 63%"
|
||||
@keyup.enter="handleLogin"
|
||||
>
|
||||
<template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
|
||||
</el-input>
|
||||
<div class="login-code">
|
||||
<img :src="codeUrl" @click="getCode" class="login-code-img"/>
|
||||
</div>
|
||||
</el-form-item> -->
|
||||
<el-checkbox
|
||||
v-model="loginForm.rememberMe"
|
||||
style="margin: 0px 0px 25px 0px"
|
||||
>记住密码</el-checkbox
|
||||
>
|
||||
<el-form-item style="width: 100%">
|
||||
<el-button
|
||||
:loading="loading"
|
||||
size="large"
|
||||
type="primary"
|
||||
style="width: 100%"
|
||||
@click.prevent="handleLogin"
|
||||
>
|
||||
<span v-if="!loading">登 录</span>
|
||||
<span v-else>登 录 中...</span>
|
||||
</el-button>
|
||||
<div style="float: right" v-if="register">
|
||||
<router-link class="link-type" :to="'/register'"
|
||||
>立即注册</router-link
|
||||
>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 底部 -->
|
||||
<div class="el-login-footer">
|
||||
<span>Copyright © 2018-2025 ruoyi.vip All Rights Reserved.</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getCodeImg } from "@/api/login";
|
||||
import Cookies from "js-cookie";
|
||||
import { encrypt, decrypt } from "@/utils/jsencrypt";
|
||||
import useUserStore from "@/store/modules/user";
|
||||
|
||||
const title = import.meta.env.VITE_APP_TITLE;
|
||||
const userStore = useUserStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const loginForm = ref({
|
||||
username: "admin",
|
||||
password: "admin123",
|
||||
rememberMe: false,
|
||||
code: "",
|
||||
uuid: "",
|
||||
});
|
||||
|
||||
const loginRules = {
|
||||
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
|
||||
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
|
||||
code: [{ required: true, trigger: "change", message: "请输入验证码" }],
|
||||
};
|
||||
|
||||
const codeUrl = ref("");
|
||||
const loading = ref(false);
|
||||
// 验证码开关
|
||||
const captchaEnabled = ref(true);
|
||||
// 注册开关
|
||||
const register = ref(false);
|
||||
const redirect = ref(undefined);
|
||||
|
||||
watch(
|
||||
route,
|
||||
(newRoute) => {
|
||||
console.log(newRoute);
|
||||
redirect.value = newRoute.query && newRoute.query.redirect;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
function handleLogin() {
|
||||
proxy.$refs.loginRef.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true;
|
||||
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
||||
if (loginForm.value.rememberMe) {
|
||||
Cookies.set("username", loginForm.value.username, { expires: 30 });
|
||||
Cookies.set("password", encrypt(loginForm.value.password), {
|
||||
expires: 30,
|
||||
});
|
||||
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
|
||||
} else {
|
||||
// 否则移除
|
||||
Cookies.remove("username");
|
||||
Cookies.remove("password");
|
||||
Cookies.remove("rememberMe");
|
||||
}
|
||||
// 调用action的登录方法
|
||||
userStore
|
||||
.login(loginForm.value)
|
||||
.then((res) => {
|
||||
const query = route.query;
|
||||
const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
|
||||
if (cur !== "redirect") {
|
||||
acc[cur] = query[cur];
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
router.push({ path: redirect.value || "/", query: otherQueryParams });
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
// 重新获取验证码
|
||||
// if (captchaEnabled.value) {
|
||||
// getCode();
|
||||
// }
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getCode() {
|
||||
getCodeImg().then((res) => {
|
||||
captchaEnabled.value =
|
||||
res.captchaEnabled === undefined ? true : res.captchaEnabled;
|
||||
if (captchaEnabled.value) {
|
||||
codeUrl.value = "data:image/gif;base64," + res.img;
|
||||
loginForm.value.uuid = res.uuid;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getCookie() {
|
||||
const username = Cookies.get("username");
|
||||
const password = Cookies.get("password");
|
||||
const rememberMe = Cookies.get("rememberMe");
|
||||
loginForm.value = {
|
||||
username: username === undefined ? loginForm.value.username : username,
|
||||
password:
|
||||
password === undefined ? loginForm.value.password : decrypt(password),
|
||||
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
|
||||
};
|
||||
}
|
||||
|
||||
// getCode();
|
||||
getCookie();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
background-image: url("../assets/images/login-background.jpg");
|
||||
background-size: cover;
|
||||
}
|
||||
.title {
|
||||
margin: 0px auto 30px auto;
|
||||
text-align: center;
|
||||
color: #707070;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
width: 400px;
|
||||
padding: 25px 25px 5px 25px;
|
||||
z-index: 1;
|
||||
.el-input {
|
||||
height: 40px;
|
||||
input {
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
.input-icon {
|
||||
height: 39px;
|
||||
width: 14px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
}
|
||||
.login-tip {
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
color: #bfbfbf;
|
||||
}
|
||||
.login-code {
|
||||
width: 33%;
|
||||
height: 40px;
|
||||
float: right;
|
||||
img {
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
.el-login-footer {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.login-code-img {
|
||||
height: 40px;
|
||||
padding-left: 12px;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,13 @@
|
||||
<template>
|
||||
<div class="login">
|
||||
<div>
|
||||
<div id="loader-wrapper" v-show="showType == 1">
|
||||
<div id="loader"></div>
|
||||
<div class="loader-section section-left"></div>
|
||||
<div class="loader-section section-right"></div>
|
||||
<div class="load_title">正在加载系统资源,请耐心等待</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login" v-show="showType == 2">
|
||||
<el-form
|
||||
ref="loginRef"
|
||||
:model="loginForm"
|
||||
@ -80,16 +88,19 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
import { getCodeImg } from "@/api/login";
|
||||
import Cookies from "js-cookie";
|
||||
import { encrypt, decrypt } from "@/utils/jsencrypt";
|
||||
import useUserStore from "@/store/modules/user";
|
||||
import { ref } from "vue";
|
||||
|
||||
const title = import.meta.env.VITE_APP_TITLE;
|
||||
const userStore = useUserStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const showType = ref(1);
|
||||
|
||||
const loginForm = ref({
|
||||
username: "admin",
|
||||
@ -113,9 +124,19 @@ const captchaEnabled = ref(true);
|
||||
const register = ref(false);
|
||||
const redirect = ref(undefined);
|
||||
|
||||
onMounted(() => {
|
||||
// const urlType = route.query.loginType
|
||||
// userStore.clearLoginType();
|
||||
// if (urlType && ['1', '2'].includes(urlType)) {
|
||||
// userStore.setLoginType(Number(urlType)) // 使用action更新
|
||||
// handleLogin()
|
||||
// }
|
||||
handleLogin()
|
||||
});
|
||||
watch(
|
||||
route,
|
||||
(newRoute) => {
|
||||
console.log(newRoute);
|
||||
redirect.value = newRoute.query && newRoute.query.redirect;
|
||||
},
|
||||
{ immediate: true }
|
||||
|
@ -97,7 +97,7 @@
|
||||
<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" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
|
||||
<el-table-column label="地址" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="地址" align="center" prop="ipaddr" :show-overflow-tooltip="true" width="180px" />
|
||||
<el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作系统" align="center" prop="os" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="浏览器" align="center" prop="browser" :show-overflow-tooltip="true" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container custom-container">
|
||||
<el-row :gutter="20">
|
||||
<splitpanes :horizontal="appStore.device === 'mobile'" class="default-theme">
|
||||
<!--部门数据-->
|
||||
@ -542,3 +542,12 @@ onMounted(() => {
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.custom-container {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
.el-row {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user