模拟数据

This commit is contained in:
renna 2025-06-23 19:00:40 +08:00
parent 7f80342da2
commit 7e7e46bd57
14 changed files with 1819 additions and 13 deletions

View File

@ -109,8 +109,4 @@ getStyle(type, item, status) {
实现功能计划:
1.我目前需要脱离后台进行页面展示,给增加完善的模拟数据;
2.找一个线上地址测试地图的平台概览页面显示
3.添加新图层、绘制路线,引入绘制线、绘制面、绘制点
# 模拟数据版本

View File

@ -18,8 +18,6 @@
"@supermap/iclient-ol": "^11.1.1",
"@vueuse/core": "9.5.0",
"axios": "0.27.2",
"ol": "6.15.1",
"proj4": "^2.17.0",
"echarts": "5.4.0",
"element-plus": "2.2.21",
"file-saver": "2.0.5",
@ -27,8 +25,11 @@
"js-cookie": "3.0.1",
"jsencrypt": "3.3.1",
"leaflet-minimap": "^3.6.1",
"mockjs": "^1.1.0",
"nprogress": "0.2.0",
"ol": "6.15.1",
"pinia": "2.0.22",
"proj4": "^2.17.0",
"vue": "3.2.45",
"vue-cropper": "1.0.3",
"vue-router": "4.1.4"

View File

@ -43,7 +43,21 @@ import TreeSelect from '@/components/TreeSelect'
import DictTag from '@/components/DictTag'
const app = createApp(App)
if (import.meta.env.DEV) {
console.log('正在初始化Mock数据...')
try {
// 动态导入mock确保只在开发环境中加载
import('./mock').then(module => {
const setupMock = module.default
setupMock()
console.log('Mock数据初始化成功!')
}).catch(error => {
console.error('加载Mock模块失败:', error)
})
} catch (error) {
console.error('Mock初始化错误:', error)
}
}
// 全局方法挂载
app.config.globalProperties.useDict = useDict
app.config.globalProperties.download = download

131
src/mock/index.js Normal file
View File

@ -0,0 +1,131 @@
import Mock from 'mockjs'
import userApi from './user'
import menuApi from './menu' // 新增
import roleApi from './system/role'
import sysUserApi from './system/user'
import operlogApi from './monitor/operlog'
import dictApi from './system/dict' // 新增
// 模拟数据初始化函数
function setupMock() {
// 设置拦截ajax请求的相应时间
Mock.setup({
timeout: '200-600'
})
// 增强xhr的send方法
Mock.XHR.prototype._proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false
if (this.responseType) {
this.custom.xhr.responseType = this.responseType
}
}
// 获取请求头并保存到自定义属性中
const headers = {}
const xhr = this
Object.keys(xhr).forEach(key => {
if (key.startsWith('_header_')) {
const headerName = key.substring(8)
headers[headerName] = xhr[key]
}
})
this.custom.headers = headers
// 打印详细请求信息
console.log(`Mock请求信息:`, {
method: this._args ? this._args[0] : undefined,
url: this._args ? this._args[1] : undefined,
body: arguments[0],
headers: this.custom.headers
})
return this._proxy_send(...arguments)
}
// 确保正确匹配前端请求
// 用户相关
// 验证码获取
Mock.mock(/\/dev-api\/captchaImage/, 'get', userApi.getCodeImg)
// 用户登录
Mock.mock(/\/dev-api\/login/, 'post', userApi.login)
// 获取用户信息
Mock.mock(/\/dev-api\/getInfo/, 'get', userApi.getInfo)
// 退出登录
Mock.mock(/\/dev-api\/logout/, 'post', userApi.logout)
// 获取路由
Mock.mock(/\/dev-api\/getRouters/, 'get', menuApi.getRouters)
// 字典数据
Mock.mock(/\/dev-api\/system\/dict\/data\/type\/.*/, 'get', dictApi.getDictDataByType)
// 角色管理相关
// 查询角色列表
Mock.mock(/\/dev-api\/system\/role\/list/, 'get', roleApi.listRole)
// 查询角色详细
Mock.mock(/\/dev-api\/system\/role\/\d+$/, 'get', roleApi.getRole)
// 新增角色
Mock.mock(/\/dev-api\/system\/role$/, 'post', roleApi.addRole)
// 修改角色
Mock.mock(/\/dev-api\/system\/role$/, 'put', roleApi.updateRole)
// 角色数据权限
Mock.mock(/\/dev-api\/system\/role\/dataScope/, 'put', roleApi.dataScope)
// 角色状态修改
Mock.mock(/\/dev-api\/system\/role\/changeStatus/, 'put', roleApi.changeRoleStatus)
// 删除角色
Mock.mock(/\/dev-api\/system\/role\/\d+$/, 'delete', roleApi.delRole)
// 查询角色菜单树
Mock.mock(/\/dev-api\/system\/menu\/roleMenuTreeselect\/\d+$/, 'get', roleApi.roleMenuTreeselect)
// 查询菜单树
Mock.mock(/\/dev-api\/system\/menu\/treeselect/, 'get', roleApi.menuTreeselect)
// 根据角色ID查询部门树结构
Mock.mock(/\/dev-api\/system\/role\/deptTree\/\d+$/, 'get', roleApi.deptTreeSelect)
// 用户管理相关
// 查询用户列表
Mock.mock(/\/dev-api\/system\/user\/list/, 'get', sysUserApi.listUser)
// 查询用户详细
Mock.mock(/\/dev-api\/system\/user\/\d+$/, 'get', sysUserApi.getUser)
// 新增用户
Mock.mock(/\/dev-api\/system\/user$/, 'post', sysUserApi.addUser)
// 修改用户
Mock.mock(/\/dev-api\/system\/user$/, 'put', sysUserApi.updateUser)
// 删除用户
Mock.mock(/\/dev-api\/system\/user\/\d+$/, 'delete', sysUserApi.delUser)
// 用户状态修改
Mock.mock(/\/dev-api\/system\/user\/changeStatus/, 'put', sysUserApi.changeUserStatus)
// 重置密码
Mock.mock(/\/dev-api\/system\/user\/resetPwd/, 'put', sysUserApi.resetUserPwd)
// 查询用户个人信息
Mock.mock(/\/dev-api\/system\/user\/profile/, 'get', sysUserApi.getUserProfile)
// 修改用户个人信息
Mock.mock(/\/dev-api\/system\/user\/profile/, 'put', sysUserApi.updateUserProfile)
// 用户密码重置
Mock.mock(/\/dev-api\/system\/user\/profile\/updatePwd/, 'put', sysUserApi.updateUserPwd)
// 用户头像上传
Mock.mock(/\/dev-api\/system\/user\/profile\/avatar/, 'post', sysUserApi.uploadAvatar)
// 查询授权角色
Mock.mock(/\/dev-api\/system\/user\/authRole\/\d+$/, 'get', sysUserApi.getAuthRole)
// 保存授权角色
Mock.mock(/\/dev-api\/system\/user\/authRole/, 'put', sysUserApi.updateAuthRole)
// 查询部门下拉树结构
Mock.mock(/\/dev-api\/system\/user\/deptTree/, 'get', sysUserApi.deptTreeSelect)
// 获取用户初始密码
Mock.mock(/\/dev-api\/system\/user\/initPassword/, 'get', sysUserApi.getInitPassword)
// 操作日志相关
// 查询操作日志列表
Mock.mock(/\/dev-api\/monitor\/operlog\/list/, 'get', operlogApi.list)
// 删除操作日志
Mock.mock(/\/dev-api\/monitor\/operlog\/\d+$/, 'delete', operlogApi.delOperlog)
// 清空操作日志
Mock.mock(/\/dev-api\/monitor\/operlog\/clean/, 'delete', operlogApi.cleanOperlog)
console.log('Mock拦截器设置完成')
return Mock
}
export default setupMock

141
src/mock/menu.js Normal file
View File

@ -0,0 +1,141 @@
// src/mock/menu.js
const menuApi = {
getRouters: () => {
return {
msg: "操作成功",
code: 200,
data: [
{
name: "System/role",
path: "/system/role",
hidden: false,
component: "Layout",
meta: {
title: "角色管理",
icon: "peoples",
noCache: false,
link: null
}
},
{
name: "System",
path: "/system",
hidden: false,
redirect: "noRedirect",
component: "Layout",
alwaysShow: true,
meta: {
title: "人员管理",
icon: "user",
noCache: false,
link: null
},
children: [
{
name: "User",
path: "user",
hidden: false,
component: "system/user/index",
meta: {
title: "用户管理",
icon: "peoples",
noCache: false,
link: null
}
},
{
name: "Driver",
path: "driver",
hidden: false,
component: "system/driver/index",
meta: {
title: "驾驶员管理",
icon: "component",
noCache: false,
link: null
}
},
{
name: "Menu",
path: "menu",
hidden: false,
component: "system/menu/index",
meta: {
title: "菜单管理",
icon: "clipboard",
noCache: false,
link: null
}
}
]
},
{
name: "Car/monitor",
path: "/car/monitor",
hidden: false,
component: "Layout",
meta: {
title: "车辆监控",
icon: "druid",
noCache: false,
link: null
}
},
{
name: "Car",
path: "/car",
hidden: false,
redirect: "noRedirect",
component: "Layout",
alwaysShow: true,
meta: {
title: "车辆管理",
icon: "edit",
noCache: false,
link: null
},
children: [
{
name: "Park",
path: "park",
hidden: false,
component: "car/park/index",
meta: {
title: "车辆入库",
icon: "date-range",
noCache: false,
link: null
}
},
{
name: "Type",
path: "type",
hidden: false,
component: "car/type/index",
meta: {
title: "类型管理",
icon: "monitor",
noCache: false,
link: null
}
}
]
},
{
name: "System/operlog",
path: "/system/operlog",
hidden: false,
component: "Layout",
meta: {
title: "操作日志",
icon: "dict",
noCache: false,
link: null
}
}
]
}
}
}
export default menuApi

272
src/mock/monitor/operlog.js Normal file
View File

@ -0,0 +1,272 @@
import Mock from 'mockjs'
// 操作日志列表数据
const operLogs = [
{
operId: 1,
title: '用户管理',
businessType: 1,
method: 'com.ruoyi.system.controller.UserController.add()',
requestMethod: 'POST',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/user',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"userName":"zhangsan","nickName":"张三","password":"123456","phonenumber":"15666666666","email":"zhangsan@example.com","sex":"1","status":"0","roleId":3,"remark":"张三"}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "成功",
errorMsg: '',
operTime: '2025-06-23 10:20:30'
},
{
operId: 2,
title: '角色管理',
businessType: 2,
method: 'com.ruoyi.system.controller.RoleController.edit()',
requestMethod: 'PUT',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/role',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"roleId":2,"roleName":"普通角色","roleKey":"common","roleSort":2,"status":"0","remark":"普通角色"}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "成功",
errorMsg: '',
operTime: '2025-06-23 08:30:45'
},
{
operId: 3,
title: '菜单管理',
businessType: 1,
method: 'com.ruoyi.system.controller.MenuController.add()',
requestMethod: 'POST',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/menu',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"menuName":"车辆监控","parentId":0,"orderNum":1,"path":"monitor","component":"Layout","menuType":"M","visible":"0","status":"0","icon":"monitor"}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "成功",
errorMsg: '',
operTime: '2025-06-23 10:20:30'
},
{
operId: 4,
title: '用户管理',
businessType: 3,
method: 'com.ruoyi.system.controller.UserController.remove()',
requestMethod: 'DELETE',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/user/4',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"userId":4}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "失败",
errorMsg: '',
operTime: '2025-06-23 14:35:25'
},
{
operId: 5,
title: '角色管理',
businessType: 3,
method: 'com.ruoyi.system.controller.RoleController.remove()',
requestMethod: 'DELETE',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/role/4',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"roleId":4}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "成功",
errorMsg: '',
operTime: '2025-06-23 09:45:15'
},
{
operId: 6,
title: '登录日志',
businessType: 9,
method: 'com.ruoyi.system.controller.LoginController.login()',
requestMethod: 'POST',
operatorType: 0,
operName: 'zhangsan',
deptName: '驾驶部门',
operUrl: '/login',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"username":"zhangsan","password":"****"}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "失败",
errorMsg: '',
operTime: '2025-06-23 08:00:20'
},
{
operId: 7,
title: '车辆管理',
businessType: 1,
method: 'com.ruoyi.system.controller.CarController.add()',
requestMethod: 'POST',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/car',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"carNo":"鲁B12345","carType":"1","status":"0"}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "失败",
errorMsg: '',
operTime: '2025-06-23 11:30:40'
},
{
operId: 8,
title: '车辆管理',
businessType: 2,
method: 'com.ruoyi.system.controller.CarController.edit()',
requestMethod: 'PUT',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/car',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"carId":1,"carNo":"鲁B12345","carType":"2","status":"0"}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "失败",
errorMsg: '',
operTime: '2025-06-23 16:20:10'
},
{
operId: 9,
title: '用户管理',
businessType: 1,
method: 'com.ruoyi.system.controller.UserController.add()',
requestMethod: 'POST',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/user',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"userName":"wangwu","nickName":"王五","password":"123456","phonenumber":"13777777777","email":"wangwu@example.com","sex":"1","status":"0","roleId":2}',
jsonResult: '{"code":500,"msg":"新增用户失败,登录账号已存在"}',
status: "成功",
errorMsg: '新增用户失败,登录账号已存在',
operTime: '2025-06-23 09:15:30'
},
{
operId: 10,
title: '车辆类型管理',
businessType: 1,
method: 'com.ruoyi.system.controller.CarTypeController.add()',
requestMethod: 'POST',
operatorType: 0,
operName: 'admin',
deptName: '研发部门',
operUrl: '/system/carType',
operIp: '127.0.0.1',
operLocation: '内网IP',
operParam: '{"typeName":"新能源车","typeCode":"001","status":"0"}',
jsonResult: '{"code":200,"msg":"操作成功"}',
status: "成功",
errorMsg: '',
operTime: '2025-06-23 14:25:50'
}
]
const operlogApi = {
// 查询操作日志列表
// 查询操作日志列表
list: (config) => {
// 增加参数检查处理params为undefined的情况
const params = config.params || {};
const {
title,
operName,
businessType,
status,
orderByColumn,
isAsc,
pageNum = 1,
pageSize = 10
} = params;
let mockList = operLogs.filter(item => {
if (title && !item.title.includes(title)) return false;
if (operName && !item.operName.includes(operName)) return false;
if (businessType && item.businessType !== parseInt(businessType)) return false;
if (status && item.status !== parseInt(status)) return false;
return true;
});
// 排序
if (orderByColumn && isAsc) {
const isAscending = isAsc.toLowerCase() === 'asc';
mockList.sort((a, b) => {
const valueA = a[orderByColumn];
const valueB = b[orderByColumn];
if (isAscending) {
return valueA > valueB ? 1 : -1;
} else {
return valueA < valueB ? 1 : -1;
}
});
} else {
// 默认按时间倒序
mockList.sort((a, b) => new Date(b.operTime) - new Date(a.operTime));
}
const pageList = mockList.filter((item, index) =>
index >= (pageNum - 1) * pageSize && index < pageNum * pageSize
);
return {
code: 200,
msg: "操作成功",
rows: pageList,
total: mockList.length
};
},
// 删除操作日志
delOperlog: (config) => {
const operId = parseInt(config.url.split('/').pop())
const index = operLogs.findIndex(item => item.operId === operId)
if (index !== -1) {
operLogs.splice(index, 1)
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该操作日志"
}
}
},
// 清空操作日志
cleanOperlog: () => {
operLogs.length = 0
return {
code: 200,
msg: "操作成功"
}
}
}
export default operlogApi

122
src/mock/system/dict.js Normal file
View File

@ -0,0 +1,122 @@
import Mock from 'mockjs'
// 字典数据
const dictDataMap = {
// 正常/停用状态字典
'sys_normal_disable': [
{
searchValue: null,
createBy: "admin",
createTime: "2025-06-17 09:28:45",
updateBy: null,
updateTime: null,
remark: "正常状态",
params: {},
dictCode: 6,
dictSort: 1,
dictLabel: "正常",
dictValue: "0",
dictType: "sys_normal_disable",
cssClass: "",
listClass: "primary",
isDefault: "Y",
status: "0",
default: true
},
{
searchValue: null,
createBy: "admin",
createTime: "2025-06-17 09:28:45",
updateBy: null,
updateTime: null,
remark: "停用状态",
params: {},
dictCode: 7,
dictSort: 2,
dictLabel: "停用",
dictValue: "1",
dictType: "sys_normal_disable",
cssClass: "",
listClass: "danger",
isDefault: "N",
status: "0",
default: false
}
],
// 用户性别字典
'sys_user_sex': [
{
searchValue: null,
createBy: "admin",
createTime: "2025-06-17 09:28:45",
updateBy: null,
updateTime: null,
remark: "性别男",
params: {},
dictCode: 1,
dictSort: 1,
dictLabel: "男",
dictValue: "0",
dictType: "sys_user_sex",
cssClass: "",
listClass: "",
isDefault: "Y",
status: "0",
default: true
},
{
searchValue: null,
createBy: "admin",
createTime: "2025-06-17 09:28:45",
updateBy: null,
updateTime: null,
remark: "性别女",
params: {},
dictCode: 2,
dictSort: 2,
dictLabel: "女",
dictValue: "1",
dictType: "sys_user_sex",
cssClass: "",
listClass: "",
isDefault: "N",
status: "0",
default: false
},
{
searchValue: null,
createBy: "admin",
createTime: "2025-06-17 09:28:45",
updateBy: null,
updateTime: null,
remark: "性别未知",
params: {},
dictCode: 3,
dictSort: 3,
dictLabel: "未知",
dictValue: "2",
dictType: "sys_user_sex",
cssClass: "",
listClass: "",
isDefault: "N",
status: "0",
default: false
}
]
}
const dictApi = {
// 根据字典类型查询字典数据
getDictDataByType: (config) => {
const dictType = config.url.split('/').pop()
const dictData = dictDataMap[dictType] || []
return {
code: 200,
msg: "操作成功",
data: dictData
}
}
}
export default dictApi

383
src/mock/system/role.js Normal file
View File

@ -0,0 +1,383 @@
import Mock from 'mockjs'
// 角色列表数据
const roles = [
{
searchValue: null,
createBy: null,
createTime: "2025-06-17 09:28:41",
updateBy: null,
updateTime: null,
remark: "超级管理员",
params: {},
roleId: 1,
roleName: '超级管理员',
roleKey: 'admin',
roleSort: "1",
dataScope: '1',
menuCheckStrictly: true,
deptCheckStrictly: true,
status: '0',
delFlag: '0',
flag: false,
menuIds: null,
deptIds: null,
permissions: null,
admin: true
},
{
searchValue: null,
createBy: null,
createTime: "2025-06-17 09:28:41",
updateBy: null,
updateTime: null,
remark: "普通角色",
params: {},
roleId: 2,
roleName: '普通角色',
roleKey: 'common',
roleSort: "2",
dataScope: '2',
menuCheckStrictly: true,
deptCheckStrictly: true,
status: '0',
delFlag: '0',
flag: false,
menuIds: null,
deptIds: null,
permissions: null,
admin: false
},
{
searchValue: null,
createBy: null,
createTime: "2025-06-17 09:28:41",
updateBy: null,
updateTime: null,
remark: "驾驶员角色",
params: {},
roleId: 3,
roleName: '驾驶员',
roleKey: 'driver',
roleSort: "3",
dataScope: '1',
menuCheckStrictly: true,
deptCheckStrictly: true,
status: '0',
delFlag: '0',
flag: false,
menuIds: null,
deptIds: null,
permissions: null,
admin: false
}
]
// 菜单数据,用于角色配置
const menuOptions = [
{
id: 1,
label: '系统管理',
children: [
{
id: 11,
label: '用户管理',
children: [
{ id: 111, label: '用户查询' },
{ id: 112, label: '用户新增' },
{ id: 113, label: '用户修改' },
{ id: 114, label: '用户删除' }
]
},
{
id: 12,
label: '角色管理',
children: [
{ id: 121, label: '角色查询' },
{ id: 122, label: '角色新增' },
{ id: 123, label: '角色修改' },
{ id: 124, label: '角色删除' }
]
},
{
id: 13,
label: '菜单管理',
children: [
{ id: 131, label: '菜单查询' },
{ id: 132, label: '菜单新增' },
{ id: 133, label: '菜单修改' },
{ id: 134, label: '菜单删除' }
]
}
]
},
{
id: 2,
label: '车辆管理',
children: [
{
id: 21,
label: '车辆入库',
children: [
{ id: 211, label: '车辆查询' },
{ id: 212, label: '车辆新增' },
{ id: 213, label: '车辆修改' },
{ id: 214, label: '车辆删除' }
]
},
{
id: 22,
label: '类型管理',
children: [
{ id: 221, label: '类型查询' },
{ id: 222, label: '类型新增' },
{ id: 223, label: '类型修改' },
{ id: 224, label: '类型删除' }
]
}
]
},
{
id: 3,
label: '车辆监控',
children: [
{ id: 31, label: '实时监控' },
{ id: 32, label: '历史轨迹' }
]
}
]
// 部门数据,用于角色数据权限
const deptOptions = [
{
id: 100,
label: '青岛机场',
children: [
{
id: 101,
label: '管理部门',
children: [
{ id: 103, label: '研发部门' },
{ id: 104, label: '运营部门' },
{ id: 105, label: '驾驶部门' }
]
},
{
id: 102,
label: '车辆部门',
children: [
{ id: 106, label: '维修部门' },
{ id: 107, label: '保养部门' }
]
}
]
}
]
const roleApi = {
// 查询角色列表
listRole: (config) => {
// 增加参数检查处理params为undefined的情况
const params = config.params || {};
const { roleName, pageNum = 1, pageSize = 10 } = params;
let mockList = roles.filter(item => {
if (roleName && !item.roleName.includes(roleName)) return false;
return true;
});
const pageList = mockList.filter((item, index) =>
index >= (pageNum - 1) * pageSize && index < pageNum * pageSize
);
return {
total: mockList.length,
rows: pageList,
code: 200,
msg: "查询成功"
};
},
// 查询角色详细
getRole: (config) => {
const roleId = parseInt(config.url.split('/').pop())
const role = roles.find(item => item.roleId === roleId)
if (role) {
return {
code: 200,
msg: "操作成功",
data: role
}
} else {
return {
code: 500,
msg: "未找到该角色"
}
}
},
// 新增角色
addRole: (config) => {
const body = JSON.parse(config.body)
const newRole = {
searchValue: null,
createBy: "admin",
createTime: Mock.Random.datetime(),
updateBy: null,
updateTime: null,
remark: body.remark || '',
params: {},
roleId: Mock.Random.integer(10, 100),
roleName: body.roleName,
roleKey: body.roleKey || body.roleName.toLowerCase(),
roleSort: roles.length + 1 + "",
dataScope: body.dataScope || '1',
menuCheckStrictly: body.menuCheckStrictly || false,
deptCheckStrictly: body.deptCheckStrictly || false,
status: body.status || '0',
delFlag: '0',
flag: false,
menuIds: body.menuIds || null,
deptIds: body.deptIds || null,
permissions: null,
admin: false
}
roles.push(newRole)
return {
code: 200,
msg: "操作成功"
}
},
// 修改角色
updateRole: (config) => {
const body = JSON.parse(config.body)
const index = roles.findIndex(item => item.roleId === body.roleId)
if (index !== -1) {
roles[index] = {
...roles[index],
...body,
updateBy: 'admin',
updateTime: Mock.Random.datetime()
}
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该角色"
}
}
},
// 角色数据权限
dataScope: (config) => {
const body = JSON.parse(config.body)
const index = roles.findIndex(item => item.roleId === body.roleId)
if (index !== -1) {
roles[index].dataScope = body.dataScope
roles[index].deptIds = body.deptIds
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该角色"
}
}
},
// 角色状态修改
changeRoleStatus: (config) => {
const { roleId, status } = config.body ? JSON.parse(config.body) : config.params
const index = roles.findIndex(item => item.roleId === parseInt(roleId))
if (index !== -1) {
roles[index].status = status
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该角色"
}
}
},
// 删除角色
delRole: (config) => {
const roleId = parseInt(config.url.split('/').pop())
const index = roles.findIndex(item => item.roleId === roleId)
if (index !== -1) {
roles.splice(index, 1)
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该角色"
}
}
},
// 查询角色菜单树
roleMenuTreeselect: (config) => {
const roleId = parseInt(config.url.match(/\d+$/)[0])
const role = roles.find(item => item.roleId === roleId)
// 模拟角色拥有的菜单权限这里简单返回一部分菜单ID
const checkedKeys = [1, 11, 111, 112, 12, 121, 31]
return {
code: 200,
msg: "操作成功",
menus: menuOptions,
checkedKeys: checkedKeys
}
},
// 查询菜单树
menuTreeselect: (config) => {
return {
code: 200,
msg: "操作成功",
data: menuOptions
}
},
// 根据角色ID查询部门树结构
deptTreeSelect: (config) => {
const roleId = parseInt(config.url.match(/\d+$/)[0])
const role = roles.find(item => item.roleId === roleId)
// 模拟角色拥有的部门权限这里简单返回一部分部门ID
const checkedKeys = role.roleId === 1 ? [100, 101, 102, 103, 104, 105, 106, 107] : [103, 104, 105]
return {
code: 200,
msg: "操作成功",
depts: deptOptions,
checkedKeys: checkedKeys
}
}
}
export default roleApi

472
src/mock/system/user.js Normal file
View File

@ -0,0 +1,472 @@
import Mock from 'mockjs'
// 用户列表数据
const users = [
{
searchValue: null,
createBy: "admin",
createTime: "2025-06-17 09:28:41",
updateBy: null,
updateTime: null,
remark: "管理员",
params: {},
userId: 1,
deptId: 103,
userName: "admin",
nickName: "若依",
email: "ry@163.com",
phonenumber: "15888888888",
sex: "1",
avatar: "",
password: "$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2",
status: "0",
delFlag: "0",
loginIp: "10.0.0.170",
loginDate: "2025-06-23T16:51:44.000+08:00",
dept: {
searchValue: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
remark: null,
params: {},
deptId: 103,
parentId: null,
ancestors: null,
deptName: "研发部门",
orderNum: null,
leader: "若依",
phone: null,
email: null,
status: null,
delFlag: null,
parentName: null,
children: []
},
roles: [],
roleIds: null,
postIds: null,
roleId: 1,
admin: true
},
{
searchValue: null,
createBy: "admin",
createTime: "2025-06-17 09:28:41",
updateBy: null,
updateTime: null,
remark: "测试员",
params: {},
userId: 2,
deptId: 105,
userName: "ry",
nickName: "若依",
email: "ry@qq.com",
phonenumber: "15666666666",
sex: "1",
avatar: "",
password: "$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2",
status: "0",
delFlag: "0",
loginIp: "127.0.0.1",
loginDate: "2025-06-17T09:28:41.000+08:00",
dept: {
searchValue: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
remark: null,
params: {},
deptId: 105,
parentId: null,
ancestors: null,
deptName: "测试部门",
orderNum: null,
leader: "若依",
phone: null,
email: null,
status: null,
delFlag: null,
parentName: null,
children: []
},
roles: [],
roleIds: null,
postIds: null,
roleId: 2,
admin: false
}
]
// 角色列表,用于分配角色
const roleOptions = [
{
roleId: 1,
roleName: '超级管理员',
roleKey: 'admin',
roleSort: 1,
dataScope: '1',
status: '0'
},
{
roleId: 2,
roleName: '普通角色',
roleKey: 'common',
roleSort: 2,
dataScope: '2',
status: '0'
},
{
roleId: 3,
roleName: '驾驶员',
roleKey: 'driver',
roleSort: 3,
dataScope: '1',
status: '0'
}
]
// 部门列表,用于用户选择部门
const deptTree = [
{
id: 100,
label: '青岛机场',
children: [
{
id: 101,
label: '管理部门',
children: [
{ id: 103, label: '研发部门' },
{ id: 104, label: '运营部门' },
{ id: 105, label: '驾驶部门' }
]
},
{
id: 102,
label: '车辆部门',
children: [
{ id: 106, label: '维修部门' },
{ id: 107, label: '保养部门' }
]
}
]
}
]
const sysUserApi = {
// 查询用户列表
listUser: (config) => {
// 增加参数检查处理params为undefined的情况
const params = config.params || {}
const { userName, roleId, pageNum = 1, pageSize = 10 } = params
let mockList = users.filter(item => {
if (userName && !item.userName.includes(userName)) return false
if (roleId && item.roleId !== parseInt(roleId)) return false
return true
})
const pageList = mockList.filter((item, index) =>
index >= (pageNum - 1) * pageSize && index < pageNum * pageSize
)
return {
code: 200,
msg: "查询成功",
rows: pageList,
total: mockList.length
}
},
// 查询用户详细
getUser: (config) => {
const userId = parseInt(config.url.split('/').pop())
const user = users.find(item => item.userId === userId)
if (user) {
// 获取用户的角色列表
const postIds = []
const roleIds = [user.roleId]
return {
code: 200,
msg: "操作成功",
data: {
...user,
postIds,
roleIds
}
}
} else {
return {
code: 500,
msg: "未找到该用户"
}
}
},
// 新增用户
addUser: (config) => {
const body = JSON.parse(config.body)
const newUser = {
userId: Mock.Random.integer(10, 100),
deptId: body.deptId || 103,
userName: body.userName,
nickName: body.nickName,
email: body.email || `${body.userName}@example.com`,
phonenumber: body.phonenumber || Mock.Random.string('number', 11),
sex: body.sex || '1',
avatar: '',
password: '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2',
status: body.status || '0',
delFlag: '0',
loginIp: '',
loginDate: null,
createBy: 'admin',
createTime: Mock.Random.datetime(),
updateBy: '',
updateTime: null,
remark: body.remark || '',
roleId: body.roleId || 2,
roles: [roleOptions.find(role => role.roleId === (body.roleId || 2)).roleName]
}
users.push(newUser)
return {
code: 200,
msg: "操作成功"
}
},
// 修改用户
updateUser: (config) => {
const body = JSON.parse(config.body)
const index = users.findIndex(item => item.userId === body.userId)
if (index !== -1) {
// 更新角色信息
const roleName = roleOptions.find(role => role.roleId === parseInt(body.roleId))?.roleName || users[index].roles[0]
users[index] = {
...users[index],
...body,
updateBy: 'admin',
updateTime: Mock.Random.datetime(),
roleId: parseInt(body.roleId) || users[index].roleId,
roles: [roleName]
}
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该用户"
}
}
},
// 删除用户
delUser: (config) => {
const userId = parseInt(config.url.split('/').pop())
const index = users.findIndex(item => item.userId === userId)
if (index !== -1) {
users.splice(index, 1)
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该用户"
}
}
},
// 用户状态修改
changeUserStatus: (config) => {
const body = JSON.parse(config.body)
const index = users.findIndex(item => item.userId === body.userId)
if (index !== -1) {
users[index].status = body.status
users[index].updateBy = 'admin'
users[index].updateTime = Mock.Random.datetime()
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该用户"
}
}
},
// 重置密码
resetUserPwd: (config) => {
const body = JSON.parse(config.body)
const index = users.findIndex(item => item.userId === body.userId)
if (index !== -1) {
users[index].password = body.password
users[index].updateBy = 'admin'
users[index].updateTime = Mock.Random.datetime()
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该用户"
}
}
},
// 查询用户个人信息
getUserProfile: () => {
// 默认返回管理员信息
const user = users.find(item => item.userId === 1)
return {
code: 200,
msg: "操作成功",
data: user
}
},
// 修改用户个人信息
updateUserProfile: (config) => {
const body = JSON.parse(config.body)
const index = users.findIndex(item => item.userId === body.userId)
if (index !== -1) {
users[index] = {
...users[index],
nickName: body.nickName,
phonenumber: body.phonenumber,
email: body.email,
sex: body.sex,
updateBy: 'admin',
updateTime: Mock.Random.datetime()
}
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该用户"
}
}
},
// 用户密码重置
updateUserPwd: (config) => {
return {
code: 200,
msg: "操作成功"
}
},
// 用户头像上传
uploadAvatar: (config) => {
// 模拟头像URL
const imgUrl = 'https://example.com/avatar/default.jpg'
return {
code: 200,
msg: "操作成功",
imgUrl: imgUrl
}
},
// 查询授权角色
getAuthRole: (config) => {
const userId = parseInt(config.url.split('/').pop())
const user = users.find(item => item.userId === userId)
if (user) {
// 用户拥有的角色ID
const roleId = user.roleId
return {
code: 200,
msg: "操作成功",
user: user,
roles: roleOptions.map(role => ({
...role,
flag: role.roleId === roleId
}))
}
} else {
return {
code: 500,
msg: "未找到该用户"
}
}
},
// 保存授权角色
updateAuthRole: (config) => {
const { userId, roleIds } = config.params
const index = users.findIndex(item => item.userId === parseInt(userId))
if (index !== -1) {
// 更新用户角色
const roleId = parseInt(roleIds.split(',')[0])
const roleName = roleOptions.find(role => role.roleId === roleId)?.roleName || '普通角色'
users[index].roleId = roleId
users[index].roles = [roleName]
users[index].updateBy = 'admin'
users[index].updateTime = Mock.Random.datetime()
return {
code: 200,
msg: "操作成功"
}
} else {
return {
code: 500,
msg: "未找到该用户"
}
}
},
// 查询部门下拉树结构
deptTreeSelect: () => {
return {
code: 200,
msg: "操作成功",
data: deptTree
}
},
// 获取用户初始密码
getInitPassword: () => {
return {
code: 200,
msg: "操作成功",
data: {
password: "123456"
}
}
}
}
export default sysUserApi

197
src/mock/user.js Normal file
View File

@ -0,0 +1,197 @@
import Mock from 'mockjs'
import { getRandomImage } from './utils'
// 模拟验证码
const captchaCode = {
codes: ['1234', '5678', 'abcd', 'efgh', 'ABCD']
}
const userApi = {
// 获取验证码
getCodeImg: () => {
const code = captchaCode.codes[Math.floor(Math.random() * captchaCode.codes.length)]
return {
code: 200,
msg: "操作成功",
img: getRandomImage(100, 40, code),
uuid: Mock.mock('@guid'),
captchaEnabled: true
}
},
// 登录
// login: (config) => {
// const body = typeof config.body === 'string' ? JSON.parse(config.body) : config.body
// console.log('登录请求参数:', body)
// // 默认管理员账号
// if (body.username === 'admin' && body.password === 'admin123') {
// const tokenValue = Mock.mock('@guid')
// console.log('生成的token值:', tokenValue)
// // 尝试格式1: 最简单的格式
// return {
// code: 200,
// msg: "操作成功",
// token: tokenValue
// }
// }
// },
// 更新 src/mock/user.js 中的 login 方法
// 登录
login: (config) => {
const body = typeof config.body === 'string' ? JSON.parse(config.body) : config.body
console.log('登录请求参数:', body)
// 默认管理员账号
if (body.username === 'admin' && body.password === 'admin123') {
return {
msg: "操作成功",
code: 200,
token: "eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImYzMDZlNzcyLTZhMmMtNGVjZi05NGNiLTE5ZDA1ZTZkNzVhNyJ9.69J3NMHMxbeP4_NLuo7Dw_0fJoPBwlrLdLb4p2b8poZxRoIfRMnj-F9lts3_i0MpsfrGG6HjmQQe-k8XenGTZg"
}
}
// 模拟普通用户
if (body.username === 'user' && body.password === 'user123') {
return {
msg: "操作成功",
code: 200,
token: "eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImQzYWIxMjM0LTVlNmYtN2FiYy04ZGVmLTk5MDEyMzQ1Njc4OSJ9.abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz"
}
}
// 用户名或密码错误
if ((body.username === 'admin' && body.password !== 'admin123') ||
(body.username === 'user' && body.password !== 'user123')) {
return {
code: 500,
msg: '用户名或密码错误'
}
}
// 验证码错误
if (body.code && !captchaCode.codes.includes(body.code)) {
return {
code: 500,
msg: '验证码错误'
}
}
// 未知用户
return {
code: 500,
msg: '用户不存在'
}
}
,
// 获取用户信息
// 获取用户信息
getInfo: (config) => {
console.log('获取用户信息请求:', config);
// 检查 Authorization 头
const token = config.headers?.Authorization?.replace('Bearer ', '') || '';
console.log('当前token:', token);
// 模拟验证 token (在实际项目中应该有更复杂的验证)
// 由于这是 mock 数据,我们可以简单地返回成功
return {
msg: "操作成功",
code: 200,
permissions: [
"*:*:*"
],
roles: [
"admin"
],
user: {
searchValue: null,
createBy: "admin",
createTime: "2025-06-17 09:28:41",
updateBy: null,
updateTime: null,
remark: "管理员",
params: {},
userId: 1,
deptId: 103,
userName: "admin",
nickName: "若依",
email: "ry@163.com",
phonenumber: "15888888888",
sex: "1",
avatar: "",
password: "$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2",
status: "0",
delFlag: "0",
loginIp: "10.0.0.170",
loginDate: "2025-06-23T14:11:40.000+08:00",
dept: {
searchValue: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
remark: null,
params: {},
deptId: 103,
parentId: 101,
ancestors: "0,100,101",
deptName: "研发部门",
orderNum: 1,
leader: "若依",
phone: null,
email: null,
status: "0",
delFlag: null,
parentName: null,
children: []
},
roles: [
{
searchValue: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
remark: null,
params: {},
roleId: 1,
roleName: "超级管理员",
roleKey: "admin",
roleSort: "1",
dataScope: "1",
menuCheckStrictly: false,
deptCheckStrictly: false,
status: "0",
delFlag: null,
flag: false,
menuIds: null,
deptIds: null,
permissions: null,
admin: true
}
],
roleIds: null,
postIds: null,
roleId: null,
admin: true
}
}
},
// 退出登录
logout: (config) => {
console.log('退出登录请求:', config);
// 检查 Authorization 头
const token = config.headers?.Authorization?.replace('Bearer ', '') || '';
console.log('退出登录token:', token);
// 在 mock 环境中,我们总是返回成功
return {
code: 200,
msg: "退出成功"
}
}
}
export default userApi

70
src/mock/utils.js Normal file
View File

@ -0,0 +1,70 @@
// src/mock/utils.js
/**
* 生成随机验证码图片的 base64 编码
* @param {number} width - 图片宽度
* @param {number} height - 图片高度
* @param {string} code - 验证码文本
* @returns {string} base64编码的图片
*/
export function getRandomImage(width, height, code) {
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
canvas.width = width
canvas.height = height
// 绘制背景
context.fillStyle = getRandomColor(180, 240)
context.fillRect(0, 0, width, height)
// 绘制文本
context.fillStyle = getRandomColor(50, 160)
context.font = 'bold 25px Arial'
// 在不同位置绘制每个字符,增加辨识难度
for (let i = 0; i < code.length; i++) {
const x = 10 + i * 20 + Math.random() * 8
const y = 25 + Math.random() * 8
// 随机旋转角度
const deg = (Math.random() - 0.5) * 30 * Math.PI / 180
context.translate(x, y)
context.rotate(deg)
context.fillText(code[i], 0, 0)
context.rotate(-deg)
context.translate(-x, -y)
}
// 绘制干扰线
for (let i = 0; i < 4; i++) {
context.strokeStyle = getRandomColor(40, 180)
context.beginPath()
context.moveTo(Math.random() * width, Math.random() * height)
context.lineTo(Math.random() * width, Math.random() * height)
context.stroke()
}
// 绘制干扰点
for (let i = 0; i < 30; i++) {
context.fillStyle = getRandomColor(0, 255)
context.beginPath()
context.arc(Math.random() * width, Math.random() * height, 1, 0, 2 * Math.PI)
context.fill()
}
return canvas.toDataURL('image/png').substring(22)
}
/**
* 生成随机颜色
* @param {number} min - 最小RGB值
* @param {number} max - 最大RGB值
* @returns {string} 颜色值
*/
function getRandomColor(min, max) {
const r = Math.floor(Math.random() * (max - min) + min)
const g = Math.floor(Math.random() * (max - min) + min)
const b = Math.floor(Math.random() * (max - min) + min)
return `rgb(${r},${g},${b})`
}

View File

@ -10,7 +10,7 @@ import useUserStore from '@/store/modules/user'
let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false };
export const baseURL = import.meta.env.VITE_APP_BASE_API || '/api'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
@ -111,7 +111,14 @@ service.interceptors.response.use(res => {
} else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
// 在开发环境中,不显示错误弹窗
if (!import.meta.env.DEV) {
ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
} else {
console.warn('接口错误(已禁用弹窗):', message)
}
return Promise.reject(error)
}
)
@ -143,4 +150,4 @@ export function download(url, params, filename, config) {
})
}
export default service
export default service

View File

@ -2,7 +2,7 @@
<div class="app-container">
<div class="park-container">
<!-- 车辆状态统计卡片 -->
<VehicleStats :stats="vehicleStats" />
<!-- <VehicleStats :stats="vehicleStats" /> -->
<!-- 搜索区域 -->
<div class="search-area">

View File

@ -31,7 +31,7 @@ export default defineConfig(({ mode, command }) => {
proxy: {
// https://cn.vitejs.dev/config/#server-proxy
'/dev-api': {
target: 'http://10.0.0.17:8099',
target: 'http://10.0.0.130:8099',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '')
}