/*
* @name: 文件
* @Author: Action
* @Date: 2021-01-18 15:41:30
* @LastEditors:
* @LastEditTime: 2023-07-05 11:08:04
*/
import Vue from 'vue'
import Router from 'vue-router'
import { getToken } from '@/utils/auth.js'
Vue.use(Router)
// const tokenStr = getToken()
const bigproUrl = window._CONFIG['proUrlNew']
const bigproUrlOld = window._CONFIG['proUrl']
// const url = bigproUrl + '?' + tokenStr // 新大屏地址
// const urlOld = bigproUrlOld + '?' + tokenStr // 老大屏地址
export const constantRoutes = [
{
path: '/login',
alias: '/',
component: () => import('@/views/login/index'),
hidden: true
},
// 老版本大屏
{
path: '/bigpro',
alias: '/',
component: () => {
// window.open(urlOld) // 使用 window.open 打开新页面
toOtherUrlJointToken(bigproUrlOld)
return null // 返回空组件,避免渲染当前路由组件
},
hidden: true
},
// 新版本大屏
{
path: '/bigproNew',
alias: '/',
component: () => {
// window.open(url) // 使用 window.open 打开新页面
// 初次token获取不到问题处理
toOtherUrlJointToken(bigproUrl)
return null // 返回空组件,避免渲染当前路由组件
},
hidden: true
},
// 新版本数据看板
{
path: '/bigDataBoard',
alias: '/',
name: 'BigDataBoard',
component: () => import('@/views/bigDataBoard/index'),
hidden: true
},
{
path: '/bigDataBoard2',
alias: '/',
name: 'BigDataBoard2',
component: () => import('@/views/bigDataBoard/index2'),
hidden: true
},
{
path: '/redirectIndex',
component: () => import('@/views/login/redirectIndex'),
hidden: true
},
{
path: '/transferPage',
name: 'TransferPage',
component: () => import('@/views/login/transferPage'),
hidden: true
},
{
path: '/kdRedirectIndex',
component: () => import('@/views/login/kdRedirectIndex'),
hidden: true
},
{
path: '/kdReturnIndex',
component: () => import('@/views/login/kdReturnIndex'),
hidden: true
},
{
path: '/401',
component: () => import('@/views/error-page/401'),
hidden: true
}
]
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
]
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
// 正式开发 异步路由动态加入
routes: constantRoutes
})
const router = createRouter()
const toOtherUrlJointToken = (gotoUrl) => {
window.open(gotoUrl + '?' + getToken())
}
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
/**
* 用户状态管理模块
* 负责用户认证、权限管理和动态路由生成
*/
import { login, getByToken } from '@/api/user'
import { getToken, setToken, removeToken, setSession, removeSession } from '@/utils/auth'
import router, { resetRouter } from '@/router'
import Layout from '@/layout'
import { ParentView } from '@/layout/components'
import { Message } from 'element-ui'
// 用户状态数据结构
const myState = {
token: getToken(),
communityName: '',
currentCommunityId: '',
name: '',
avatar: '',
introduction: '',
roles: [],
permissionRoutes: [],
roleTypeId: '',
allInfo: {},
currentDistrictId: '',
neighborhoodName: '',
userId: ''
}
// 状态变更方法
const mutations = {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_INTRODUCTION: (state, introduction) => {
state.introduction = introduction
},
SET_NAME: (state, name) => {
state.name = name
},
SET_COMMUNITY_NAME: (state, name) => {
state.communityName = name
},
SET_CURRENT_COMMUNITY_ID: (state, currentCommunityId) => {
state.currentCommunityId = currentCommunityId
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
},
SET_PERMISSIONROUTES: (state, permissionRoutes) => {
state.permissionRoutes = permissionRoutes
},
SET_ALL_INFO: (state, allInfo) => {
// 存储完整的用户信息对象
state.allInfo = allInfo
},
SET_ROLE_TYPE_ID: (state, roleTypeId) => {
state.roleTypeId = roleTypeId
},
SET_CURRENT_DISTRICT_ID: (state, currentDistrictId) => {
state.currentDistrictId = currentDistrictId
},
SET_NEIGHBORHOODNAME: (state, neighborhoodName) => {
state.neighborhoodName = neighborhoodName
},
SET_USER_ID: (state, userId) => {
state.userId = userId
}
}
// 异步操作方法
const actions = {
// 用户登录
login({ commit }, userInfo) {
const { username, password } = userInfo
return new Promise((resolve, reject) => {
login({ username: username.trim(), password: password }).then(response => {
const { data } = response
commit('SET_TOKEN', data.token)
setToken(data.token)
setSession(data.token)
resolve(response)
}).catch(error => {
reject(error)
})
})
},
// get user info
// 获取用户信息和菜单权限
getInfo({ commit }) {
return new Promise((resolve, reject) => {
getByToken().then(res => {
const { data } = res
let mainMenus = []
// 设置用户角色权限
commit('SET_ROLES', data.children)
// 生成动态菜单路由
mainMenus = generaMenu(mainMenus, data.children)
if (!data) {
reject('Verification failed, please Login again.')
}
// 检查用户是否有页面访问权限
if (res.data.children.length === 0) {
Message({
message: '无页面权限,请联系管理员',
type: 'error'
})
router.push('/login')
return
}
// roles must be a non-empty array
resolve({ mainMenus })
})
})
},
// 系统切换时获取新系统的菜单信息
getTransferInfo({ commit }, data) {
return new Promise((resolve, reject) => {
// 验证新系统是否有可访问的菜单
if (!data?.children || data.children.length === 0) {
Message({
message: '无页面权限,请联系管理员',
type: 'error'
})
return
}
let mainMenus = []
// 生成新系统的菜单路由(不更新角色信息,仅切换菜单)
mainMenus = generaMenu(mainMenus, data.children)
if (!data) {
reject('Verification failed, please Login again.')
}
// roles must be a non-empty array
resolve({ mainMenus })
})
},
// 用户退出登录
logout({ commit, dispatch }) {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
removeSession()
resetRouter()
sessionStorage.clear();
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true })
},
// 重置用户令牌
resetToken({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
removeSession()
resolve()
})
},
// 动态修改用户权限(用于角色切换)
async changeRoles({ commit, dispatch }, role) {
const token = role + '-token'
commit('SET_TOKEN', token)
setToken(token)
setSession(token)
const { roles } = await dispatch('getInfo')
resetRouter()
// generate accessible routes map based on roles
const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
// dynamically add accessible routes
router.addRoutes(accessRoutes)
// reset visited views and cached views
dispatch('tagsView/delAllViews', null, { root: true })
}
}
/**
* 生成动态菜单路由配置
* @param {Array} routes - 用于存储生成路由的数组
* @param {Array} data - 原始菜单数据
* @returns {Array} 生成的路由配置数组
*/
export function generaMenu(routes, data) {
// 预处理:智能去重,解决同一路径多个菜单项的冲突问题
const filteredData = []
const pathGroups = {}
// 按路径分组,识别重复路径
data.forEach(item => {
if (!pathGroups[item.resourceUri]) {
pathGroups[item.resourceUri] = []
}
pathGroups[item.resourceUri].push(item)
})
// 对每个路径组选择最佳菜单项
Object.keys(pathGroups).forEach(path => {
const group = pathGroups[path]
if (group.length === 1) {
// 单个菜单项,直接使用
filteredData.push(group[0])
} else {
// 多个菜单项冲突,应用选择策略
// 优先级:homePageFlag=='1' > 包含"首页" > 第一个
const bestItem = group.find(item => item.homePageFlag == '1') ||
group.find(item => item.resourceName.indexOf('首页') !== -1) ||
group[0]
filteredData.push(bestItem)
}
})
// 处理去重后的菜单数据
filteredData.forEach((item, index) => {
if (item.resourceUri === null) {
item.resourceUri = ''
}
let menu = {}
// 首页类型菜单:包含"首页"字样或homePageFlag为'1'的菜单
// 这类菜单使用 Layout + 单个子路由的结构,符合首页展示需求
if (item.resourceName.indexOf('首页') !== -1 || item.homePageFlag == '1') {
menu = {
path: item.resourceUri,
component: Layout,
// 注意:父级路由不设置name,遵循Vue Router最佳实践
// 当父级有默认子路由时,应该使用子路由的name进行导航
children: [
{
path: '', // 子路由使用空路径,表示默认子路由
name: item.resourceName, // 路由名称设置在子路由上
component: (resolve) => require([`@/views${item.resourceUri}`], resolve),
meta: {
title: item.resourceName,
icon: item.iconClass,
id: item.parentId,
roles: ['admin']
}
}
]
}
} else {
// 普通菜单:既不是首页类型,也没有特殊标识的常规菜单
// 根据层级和子菜单情况采用不同的组件配置策略
menu = {
path: item.resourceUri,
children: [],
name: item.resourceName,
meta: {
title: item.resourceName,
icon: item.iconClass,
id: item.parentId,
roles: ['admin']
}
}
if (item.resourceUri !== '*' && item.resourceUri !== '') {
// 根据菜单层级设置适当的组件类型
if (item.parentId === 0 || item.parentId === 1) {
// 根级路由:使用Layout组件作为页面容器
menu.component = Layout
// 处理单页面根级路由的特殊情况
if (!item.children || item.children.length === 0) {
// 单页面根级路由需要特殊处理以符合Vue Router最佳实践
// 移除父级name,避免"Named Route has a default child route"警告
delete menu.name
menu.children = [
{
path: '', // 默认子路由使用空路径
name: item.resourceName, // 将路由名称设置在子路由上
component: (resolve) => require([`@/views${item.resourceUri}`], resolve),
meta: {
title: item.resourceName,
icon: item.iconClass,
id: item.parentId,
roles: ['admin']
}
}
]
}
// 如果有子菜单,保留空children数组,后续递归填充
} else if (item.children && item.children.length > 0) {
// 中间目录节点:有子菜单但不是根级的菜单项
// 使用ParentView避免Layout组件的嵌套问题
menu.component = ParentView
} else {
// 叶子节点:无子菜单的最终页面
// 直接加载对应的Vue组件
menu.component = (resolve) => require([`@/views${item.resourceUri}`], resolve)
}
}
// 递归处理子菜单
if (item.children && item.children?.length) {
generaMenu(menu.children, item.children)
}
// 根路径特殊处理:设置默认重定向到第一个子路由
if (item.resourceUri === '/') {
if (item.children.length !== 0) {
menu.redirect = item.children[0].resourceUri
}
}
}
// 将生成的路由配置添加到路由数组中
routes.push(menu)
})
// 可选:按菜单ID排序(当前注释掉)
// routes.sort(function(a, b) {
// return a.meta?.id - b.meta?.id
// })
return routes
}
export default {
namespaced: true,
state: myState,
mutations,
actions
}
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router
<!--
* @name: 重点车辆交通环境档案管理页面
* @Author: Clanton
* @Date: 2025-10-28 10:00:00
* @LastEditTime: 2025-10-28 13:12:12
-->
<template>
<div class="vehicle-inspection-page">
<!-- 查询条件区域 -->
<div class="query-condition">
<h3>查询条件</h3>
<div class="condition-row">
<div class="condition-item">
<label>号牌号码:</label>
<el-input v-model="queryParams.plateNumber" placeholder="请输入号牌号码" />
</div>
<div class="condition-item">
<label>巡检人员:</label>
<el-input v-model="queryParams.inspector" placeholder="请输入巡检人员" />
</div>
<div class="condition-item">
<label>单位名称:</label>
<el-input v-model="queryParams.unitName" placeholder="请输入单位名称" />
</div>
<div class="condition-item">
<label>状态:</label>
<el-checkbox v-model="queryParams.statusOnline">在线</el-checkbox>
<el-checkbox v-model="queryParams.statusOffline">离线</el-checkbox>
</div>
</div>
<div class="button-group">
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</div>
</div>
<!-- 操作按钮 -->
<div class="operation-buttons">
<el-button type="primary">新增</el-button>
</div>
<!-- 数据表格 -->
<el-table :data="tableData" border style="width: 100%">
<el-table-column prop="index" label="序号" width="50" />
<el-table-column prop="districtTeam" label="辖区中队" width="100" />
<el-table-column prop="plateNumber" label="号牌号码" width="120" />
<el-table-column prop="plateType" label="号牌种类" width="100" />
<el-table-column prop="vehicleType" label="车辆类型" width="150" />
<el-table-column prop="inspector" label="巡检人员" width="100" />
<el-table-column prop="unitName" label="单位名称" width="200" />
<el-table-column prop="route" label="行驶线路" width="250" />
<el-table-column prop="status" label="状态" width="80">
<template slot-scope="scope">
<span
:class="{
'status--online': scope.row.status === '在线',
'status--offline': scope.row.status === '离线'
}"
>
{{ scope.row.status }}
</span>
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button type="text" @click="viewRecord(scope.row)">巡检记录</el-button>
<el-button type="text" @click="enterResult(scope.row)">录入巡检结果</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页器 -->
<div class="pagination">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
/>
</div>
</div>
</template>
<script>
/**
* 重点车辆交通环境档案管理页面
*/
export default {
name: 'VehicleTrafficEnvironmentArchiveManagement', // 大驼峰组件名
data() {
return {
// 查询参数
queryParams: {
plateNumber: '',
inspector: '',
unitName: '',
statusOnline: false,
statusOffline: false
},
// 表格数据
tableData: [
{
index: 1,
districtTeam: '城厢中队',
plateNumber: '苏E98Q83',
plateType: '小型汽车',
vehicleType: '轻型车辆运输车',
inspector: '张三',
unitName: '太仓市鑫达电子电器配件厂',
route: '郑和西路-郑和中路-东仓南路-上海东路',
status: '在线'
},
],
currentPage: 1,
pageSize: 10,
total: 100
}
},
methods: {
/**
* 执行查询操作
* @name: handleQuery
* @return {void}
*/
handleQuery() {
console.log('执行查询,参数:', this.queryParams)
// TODO: 调用 API
},
/**
* 重置查询条件
* @name: handleReset
* @return {void}
*/
handleReset() {
this.queryParams = {
plateNumber: '',
inspector: '',
unitName: '',
statusOnline: false,
statusOffline: false
}
},
/**
* 查看巡检记录
* @name: viewRecord
* @param {Object} row 当前行数据
* @return {void}
*/
viewRecord(row) {
console.log('查看巡检记录:', row)
},
/**
* 录入巡检结果
* @name: enterResult
* @param {Object} row 当前行数据
* @return {void}
*/
enterResult(row) {
console.log('录入巡检结果:', row)
},
/**
* 每页条数变更
* @name: handleSizeChange
* @param {Number} val 新的每页条数
* @return {void}
*/
handleSizeChange(val) {
this.pageSize = val
this.loadTableData()
},
/**
* 当前页码变更
* @name: handleCurrentChange
* @param {Number} val 新的页码
* @return {void}
*/
handleCurrentChange(val) {
this.currentPage = val
this.loadTableData()
},
/**
* 加载表格数据(模拟)
* @name: loadTableData
* @return {void}
*/
loadTableData() {
console.log(`加载第${this.currentPage}页,每页${this.pageSize}条`)
}
},
mounted() {
this.loadTableData()
}
}
</script>
<style lang="scss" scoped>
.vehicle-inspection-page {
padding: 20px;
}
.query-condition {
background-color: #f9f9f9;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #ebeef5;
border-radius: 4px;
}
.query-condition h3 {
margin-top: 0;
margin-bottom: 15px;
font-size: 16px;
}
.condition-row {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 15px;
}
.condition-item {
display: flex;
align-items: center;
}
.condition-item label {
margin-right: 10px;
font-weight: bold;
}
.button-group {
text-align: center;
}
.operation-buttons {
margin-bottom: 20px;
}
.status--online {
color: green;
}
.status--offline {
color: red;
}
.pagination {
margin-top: 20px;
text-align: right;
}
</style>
为什么重点车辆交通环境档案管理页面不显示
最新发布