Mock API是开发环境下的模拟接口系统,提供完整的后端API模拟功能,支持用户认证、权限管理、数据CRUD等操作。
文件位置: src/mock/api.js
- 用户登录
- 用户注册
- 获取用户信息
- 刷新Token
- 用户登出
- 用户列表查询
- 用户信息增删改查
- 用户权限管理
- 用户角色分配
- 菜单管理
- 角色管理
- 权限管理
- 系统设置
// POST /api/auth/login
{
url: '/api/auth/login',
method: 'post',
response: (config) => {
const { username, password } = JSON.parse(config.body)
// 验证用户名密码
const user = users.find(u => u.username === username && u.password === password)
if (!user) {
return {
status: false,
code: 401,
msg: '用户名或密码错误'
}
}
// 生成Token
const token = generateToken(user)
return {
status: true,
code: 200,
msg: '登录成功',
data: {
token,
userInfo: {
id: user.id,
username: user.username,
realName: user.realName,
email: user.email,
avatar: user.avatar,
roles: user.roles,
permissions: user.permissions
}
}
}
}
}// GET /api/auth/userinfo
{
url: '/api/auth/userinfo',
method: 'get',
response: (config) => {
const token = getTokenFromHeader(config.headers)
if (!token || !verifyToken(token)) {
return {
status: false,
code: 401,
msg: 'Token无效或已过期'
}
}
const userId = getUserIdFromToken(token)
const user = users.find(u => u.id === userId)
if (!user) {
return {
status: false,
code: 404,
msg: '用户不存在'
}
}
return {
status: true,
code: 200,
data: {
id: user.id,
username: user.username,
realName: user.realName,
email: user.email,
phone: user.phone,
avatar: user.avatar,
department: user.department,
roles: user.roles,
permissions: user.permissions,
lastLoginTime: user.lastLoginTime,
createTime: user.createTime
}
}
}
}// GET /api/user/list
{
url: '/api/user/list',
method: 'get',
response: (config) => {
const { page = 1, size = 20, username, realName, status, departmentId } = config.query
let filteredUsers = [...users]
// 应用过滤条件
if (username) {
filteredUsers = filteredUsers.filter(user =>
user.username.includes(username)
)
}
if (realName) {
filteredUsers = filteredUsers.filter(user =>
user.realName.includes(realName)
)
}
if (status !== undefined) {
filteredUsers = filteredUsers.filter(user =>
user.status === parseInt(status)
)
}
if (departmentId) {
filteredUsers = filteredUsers.filter(user =>
user.departmentId === parseInt(departmentId)
)
}
// 分页处理
const total = filteredUsers.length
const start = (page - 1) * size
const end = start + parseInt(size)
const list = filteredUsers.slice(start, end)
return {
status: true,
code: 200,
data: {
list,
total,
page: parseInt(page),
size: parseInt(size),
pages: Math.ceil(total / size)
}
}
}
}// POST /api/user/create
{
url: '/api/user/create',
method: 'post',
response: (config) => {
const userData = JSON.parse(config.body)
// 验证用户名是否已存在
const existingUser = users.find(u => u.username === userData.username)
if (existingUser) {
return {
status: false,
code: 400,
msg: '用户名已存在'
}
}
// 创建新用户
const newUser = {
id: generateId(),
...userData,
password: hashPassword(userData.password),
createTime: new Date().toISOString(),
updateTime: new Date().toISOString(),
status: 1
}
users.push(newUser)
return {
status: true,
code: 200,
msg: '用户创建成功',
data: {
id: newUser.id
}
}
}
}// GET /api/menu/tree
{
url: '/api/menu/tree',
method: 'get',
response: (config) => {
const token = getTokenFromHeader(config.headers)
const userId = getUserIdFromToken(token)
const user = users.find(u => u.id === userId)
if (!user) {
return {
status: false,
code: 401,
msg: '用户未登录'
}
}
// 根据用户权限过滤菜单
const userMenus = menus.filter(menu => {
if (!menu.permissions || menu.permissions.length === 0) {
return true
}
return menu.permissions.some(permission =>
user.permissions.includes(permission)
)
})
// 构建菜单树
const menuTree = buildMenuTree(userMenus)
return {
status: true,
code: 200,
data: menuTree
}
}
}// GET /api/role/list
{
url: '/api/role/list',
method: 'get',
response: (config) => {
const { page = 1, size = 20, name, code, status } = config.query
let filteredRoles = [...roles]
// 应用过滤条件
if (name) {
filteredRoles = filteredRoles.filter(role =>
role.name.includes(name)
)
}
if (code) {
filteredRoles = filteredRoles.filter(role =>
role.code.includes(code)
)
}
if (status !== undefined) {
filteredRoles = filteredRoles.filter(role =>
role.status === parseInt(status)
)
}
// 分页处理
const total = filteredRoles.length
const start = (page - 1) * size
const end = start + parseInt(size)
const list = filteredRoles.slice(start, end)
return {
status: true,
code: 200,
data: {
list,
total,
page: parseInt(page),
size: parseInt(size),
pages: Math.ceil(total / size)
}
}
}
}/**
* 生成Token
* @param {Object} user - 用户对象
* @returns {String} Token字符串
*/
function generateToken(user) {
const payload = {
userId: user.id,
username: user.username,
exp: Date.now() + 24 * 60 * 60 * 1000 // 24小时过期
}
return btoa(JSON.stringify(payload))
}
/**
* 验证Token
* @param {String} token - Token字符串
* @returns {Boolean} 是否有效
*/
function verifyToken(token) {
try {
const payload = JSON.parse(atob(token))
return payload.exp > Date.now()
} catch (error) {
return false
}
}
/**
* 从Token获取用户ID
* @param {String} token - Token字符串
* @returns {Number} 用户ID
*/
function getUserIdFromToken(token) {
try {
const payload = JSON.parse(atob(token))
return payload.userId
} catch (error) {
return null
}
}
/**
* 从请求头获取Token
* @param {Object} headers - 请求头对象
* @returns {String} Token字符串
*/
function getTokenFromHeader(headers) {
const authorization = headers.authorization || headers.Authorization
if (authorization && authorization.startsWith('Bearer ')) {
return authorization.slice(7)
}
return null
}/**
* 生成唯一ID
* @returns {Number} 唯一ID
*/
function generateId() {
return Date.now() + Math.floor(Math.random() * 1000)
}
/**
* 密码哈希
* @param {String} password - 原始密码
* @returns {String} 哈希后的密码
*/
function hashPassword(password) {
// 简单的哈希实现,实际项目中应使用更安全的方法
return btoa(password + 'salt')
}
/**
* 构建菜单树
* @param {Array} menus - 菜单数组
* @returns {Array} 菜单树
*/
function buildMenuTree(menus) {
const tree = []
const map = new Map()
// 创建映射
menus.forEach(menu => {
map.set(menu.id, { ...menu, children: [] })
})
// 构建树结构
menus.forEach(menu => {
const node = map.get(menu.id)
if (menu.parentId && map.has(menu.parentId)) {
map.get(menu.parentId).children.push(node)
} else {
tree.push(node)
}
})
return tree
}
/**
* 分页处理
* @param {Array} data - 数据数组
* @param {Number} page - 页码
* @param {Number} size - 页大小
* @returns {Object} 分页结果
*/
function paginate(data, page = 1, size = 20) {
const total = data.length
const start = (page - 1) * size
const end = start + parseInt(size)
const list = data.slice(start, end)
return {
list,
total,
page: parseInt(page),
size: parseInt(size),
pages: Math.ceil(total / size)
}
}/**
* 成功响应
* @param {Any} data - 响应数据
* @param {String} msg - 响应消息
* @returns {Object} 响应对象
*/
function successResponse(data, msg = '操作成功') {
return {
status: true,
code: 200,
msg,
data
}
}
/**
* 错误响应
* @param {String} msg - 错误消息
* @param {Number} code - 错误码
* @returns {Object} 响应对象
*/
function errorResponse(msg = '操作失败', code = 400) {
return {
status: false,
code,
msg
}
}
/**
* 延迟响应(模拟网络延迟)
* @param {Function} responseFunc - 响应函数
* @param {Number} delay - 延迟时间(毫秒)
* @returns {Promise} 响应Promise
*/
function delayResponse(responseFunc, delay = 500) {
return new Promise(resolve => {
setTimeout(() => {
resolve(responseFunc())
}, delay)
})
}const userModel = {
id: 1,
username: 'admin',
password: 'hashed_password',
realName: '管理员',
email: 'admin@example.com',
phone: '13800138000',
avatar: '/avatars/admin.jpg',
departmentId: 1,
department: {
id: 1,
name: '技术部'
},
roles: ['admin'],
permissions: ['*'],
status: 1, // 1-启用 0-禁用
lastLoginTime: '2025-01-15T10:30:00Z',
createTime: '2025-01-01T00:00:00Z',
updateTime: '2025-01-15T10:30:00Z'
}const menuModel = {
id: 1,
parentId: 0,
name: 'Dashboard',
title: '仪表盘',
path: '/dashboard',
component: 'Dashboard',
icon: 'Dashboard',
sort: 1,
type: 1, // 1-菜单 2-按钮
permissions: ['dashboard:view'],
hidden: false,
keepAlive: true,
status: 1,
createTime: '2025-01-01T00:00:00Z',
updateTime: '2025-01-01T00:00:00Z'
}const roleModel = {
id: 1,
name: '管理员',
code: 'ADMIN',
description: '系统管理员角色',
permissions: ['*'],
userCount: 1,
sort: 1,
status: 1,
isSystem: true,
createTime: '2025-01-01T00:00:00Z',
updateTime: '2025-01-01T00:00:00Z'
}const mockConfig = {
// 是否启用Mock
enabled: process.env.NODE_ENV === 'development',
// 响应延迟时间
delay: 500,
// 是否记录请求日志
logging: true,
// 数据持久化(localStorage)
persistence: true,
// 错误模拟概率
errorRate: 0.1
}/**
* 初始化Mock数据
*/
function initMockData() {
// 从localStorage恢复数据
if (mockConfig.persistence) {
const savedUsers = localStorage.getItem('mock_users')
if (savedUsers) {
users.splice(0, users.length, ...JSON.parse(savedUsers))
}
}
// 确保有默认管理员用户
if (!users.find(u => u.username === 'admin')) {
users.push({
id: 1,
username: 'admin',
password: hashPassword('admin123'),
realName: '系统管理员',
email: 'admin@example.com',
roles: ['admin'],
permissions: ['*'],
status: 1,
createTime: new Date().toISOString()
})
}
}// main.js
import { setupMock } from '@/mock'
if (process.env.NODE_ENV === 'development') {
setupMock()
}// 登录
const loginResponse = await request.post('/api/auth/login', {
username: 'admin',
password: 'admin123'
})
// 获取用户列表
const userListResponse = await request.get('/api/user/list', {
params: {
page: 1,
size: 20,
username: 'admin'
}
})// 添加自定义接口
Mock.mock('/api/custom/data', 'get', {
status: true,
code: 200,
data: {
message: 'Custom mock data'
}
})- 数据持久化: Mock数据默认存储在localStorage中
- 权限验证: 所有接口都会验证Token和权限
- 错误模拟: 可以配置错误概率来测试错误处理
- 性能考虑: 大量数据时注意分页和过滤性能
- 生产环境: 确保生产环境不会加载Mock代码
最后更新时间:2025-09-19