145 lines
3.9 KiB
TypeScript
145 lines
3.9 KiB
TypeScript
/**
|
|
* 用户相关模拟数据 - 框架版
|
|
*/
|
|
import type {
|
|
LoginParams,
|
|
LoginResult,
|
|
CaptchaResult,
|
|
UserInfo
|
|
} from '@/types'
|
|
|
|
// 模拟验证码
|
|
const captchaCodes: Map<string, string> = new Map()
|
|
|
|
// 模拟用户数据
|
|
const mockUsers: Array<{ username: string; password: string; userInfo: UserInfo }> = [
|
|
{
|
|
username: 'admin',
|
|
password: '123456',
|
|
userInfo: {
|
|
id: 1,
|
|
username: 'admin',
|
|
nickname: '超级管理员',
|
|
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=admin',
|
|
email: 'admin@example.com',
|
|
phone: '13800138000',
|
|
role: 'admin',
|
|
permissions: ['*'],
|
|
createTime: '2024-01-01 00:00:00',
|
|
lastLoginTime: new Date().toLocaleString()
|
|
}
|
|
},
|
|
{
|
|
username: 'user',
|
|
password: '123456',
|
|
userInfo: {
|
|
id: 2,
|
|
username: 'user',
|
|
nickname: '普通用户',
|
|
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=user',
|
|
email: 'user@example.com',
|
|
phone: '13900139000',
|
|
role: 'user',
|
|
permissions: ['read'],
|
|
createTime: '2024-06-01 00:00:00',
|
|
lastLoginTime: new Date().toLocaleString()
|
|
}
|
|
}
|
|
]
|
|
|
|
// 生成随机验证码
|
|
function generateCaptcha(): string {
|
|
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
|
|
let code = ''
|
|
for (let i = 0; i < 4; i++) {
|
|
code += chars.charAt(Math.floor(Math.random() * chars.length))
|
|
}
|
|
return code
|
|
}
|
|
|
|
// 生成SVG验证码图片
|
|
function generateCaptchaSvg(code: string): string {
|
|
const colors = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae', '#1890ff']
|
|
let svg = `<svg xmlns="http://www.w3.org/2000/svg" width="120" height="40" viewBox="0 0 120 40">`
|
|
svg += `<rect width="120" height="40" fill="#f0f2f5"/>`
|
|
|
|
// 添加干扰线
|
|
for (let i = 0; i < 4; i++) {
|
|
const x1 = Math.random() * 120
|
|
const y1 = Math.random() * 40
|
|
const x2 = Math.random() * 120
|
|
const y2 = Math.random() * 40
|
|
const color = colors[Math.floor(Math.random() * colors.length)]
|
|
svg += `<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="${color}" stroke-width="1"/>`
|
|
}
|
|
|
|
// 添加验证码文字
|
|
for (let i = 0; i < code.length; i++) {
|
|
const x = 15 + i * 25
|
|
const y = 28 + Math.random() * 6 - 3
|
|
const rotate = Math.random() * 30 - 15
|
|
const color = colors[Math.floor(Math.random() * colors.length)]
|
|
svg += `<text x="${x}" y="${y}" fill="${color}" font-size="22" font-weight="bold" transform="rotate(${rotate} ${x} ${y})">${code[i]}</text>`
|
|
}
|
|
|
|
svg += `</svg>`
|
|
return `data:image/svg+xml;base64,${btoa(svg)}`
|
|
}
|
|
|
|
// 模拟延迟
|
|
function delay(ms: number): Promise<void> {
|
|
return new Promise(resolve => setTimeout(resolve, ms))
|
|
}
|
|
|
|
// 获取验证码
|
|
export async function mockGetCaptcha(): Promise<CaptchaResult> {
|
|
await delay(300)
|
|
const captchaKey = 'captcha_' + Date.now()
|
|
const code = generateCaptcha()
|
|
captchaCodes.set(captchaKey, code)
|
|
|
|
// 5分钟后过期
|
|
setTimeout(() => captchaCodes.delete(captchaKey), 5 * 60 * 1000)
|
|
|
|
return {
|
|
captchaKey,
|
|
captchaImage: generateCaptchaSvg(code)
|
|
}
|
|
}
|
|
|
|
// 登录
|
|
export async function mockLogin(params: LoginParams): Promise<LoginResult> {
|
|
await delay(500)
|
|
|
|
// 验证验证码
|
|
const storedCode = captchaCodes.get(params.captchaKey)
|
|
if (!storedCode || storedCode.toUpperCase() !== params.captcha.toUpperCase()) {
|
|
throw new Error('验证码错误')
|
|
}
|
|
|
|
// 验证用户
|
|
const user = mockUsers.find(
|
|
u => u.username === params.username && u.password === params.password
|
|
)
|
|
|
|
if (!user) {
|
|
throw new Error('用户名或密码错误')
|
|
}
|
|
|
|
// 删除已使用的验证码
|
|
captchaCodes.delete(params.captchaKey)
|
|
|
|
return {
|
|
token: 'mock_token_' + Date.now(),
|
|
refreshToken: 'mock_refresh_token_' + Date.now(),
|
|
expires: Date.now() + 24 * 60 * 60 * 1000,
|
|
userInfo: user.userInfo
|
|
}
|
|
}
|
|
|
|
// 获取用户信息
|
|
export async function mockGetUserInfo(): Promise<UserInfo> {
|
|
await delay(200)
|
|
return mockUsers[0]!.userInfo
|
|
}
|