Administrator 8117958bd6 feat: add user center with RBAC, OAuth2 multi-mode and collapsible sidebar
- Add user management with roles and permissions (RBAC)
- Implement OAuth2 service provider supporting 4 grant types:
  authorization_code, password, client_credentials, refresh_token
- Add JWT authentication with 7-day expiry
- Add admin API for users, roles and OAuth clients management
- Add CLI tool for user management (scripts/user-cli.js)
- Add collapsible sidebar layout with login dialog
- Add user management page and OAuth client management page
- Add server middleware for auth token verification
- Add seed script for initial data (admin/admin123)
2026-03-19 17:19:57 +08:00

98 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import db from '../db'
import bcrypt from 'bcryptjs'
const ALL_PERMISSIONS = [
'user:create', 'user:read', 'user:update', 'user:delete',
'event:create', 'event:read', 'event:update', 'event:delete',
'result:create', 'result:read', 'result:update', 'result:delete',
'team:create', 'team:read', 'team:update', 'team:delete',
'admin:access', 'role:manage',
'oauth:client:create', 'oauth:client:read', 'oauth:client:update', 'oauth:client:delete'
]
const USER_PERMISSIONS = ['event:read', 'result:read', 'team:read']
const GUEST_PERMISSIONS = ['event:read']
export default defineEventHandler(async () => {
try {
const checkTeams = db.prepare('SELECT COUNT(*) as count FROM teams').get() as any
if (checkTeams.count > 0) {
return { success: true, message: '数据已存在,跳过初始化' }
}
const insertRole = db.prepare('INSERT OR IGNORE INTO roles (name, description, permissions, is_system) VALUES (?, ?, ?, ?)')
insertRole.run('admin', '系统管理员', JSON.stringify(ALL_PERMISSIONS), 1)
insertRole.run('user', '普通用户', JSON.stringify(USER_PERMISSIONS), 1)
insertRole.run('guest', '访客', JSON.stringify(GUEST_PERMISSIONS), 1)
const adminRole = db.prepare('SELECT id FROM roles WHERE name = ?').get('admin') as any
const passwordHash = bcrypt.hashSync('admin123', 10)
db.prepare(
'INSERT INTO users (username, password_hash, role_id) VALUES (?, ?, ?)'
).run('admin', passwordHash, adminRole.id)
const insertTeam = db.prepare('INSERT INTO teams (name, team_group) VALUES (?, ?)')
const insertScore = db.prepare('INSERT INTO team_scores (team_id, total_score, gold_count, silver_count, bronze_count) VALUES (?, 0, 0, 0, 0)')
const teams = [
{ name: '高一1班', group: '文化班甲组' },
{ name: '高一2班', group: '文化班甲组' },
{ name: '高二1班', group: '文化班乙组' },
{ name: '高二2班', group: '文化班乙组' },
{ name: '体育1班', group: '体育班组' },
{ name: '体育2班', group: '体育班组' },
{ name: '航空1班', group: '航空班组' },
{ name: '航空2班', group: '航空班组' },
{ name: '教师队', group: '教师组' }
]
teams.forEach(team => {
const result = insertTeam.run(team.name, team.group)
insertScore.run(result.lastInsertRowid)
})
const insertEvent = db.prepare('INSERT INTO events (name, category, event_group, unit) VALUES (?, ?, ?, ?)')
const events = [
{ name: '跳高', category: '田赛', event_group: '文化班甲组', unit: '米' },
{ name: '跳远', category: '田赛', event_group: '文化班甲组', unit: '米' },
{ name: '掷铅球', category: '田赛', event_group: '文化班乙组', unit: '米' },
{ name: '100m', category: '径赛', event_group: '体育班组', unit: '秒' },
{ name: '200m', category: '径赛', event_group: '体育班组', unit: '秒' },
{ name: '400m', category: '径赛', event_group: '体育班组', unit: '秒' },
{ name: '4×100m', category: '团体赛', event_group: '航空班组', unit: '秒' },
{ name: '4×400m', category: '团体赛', event_group: '航空班组', unit: '秒' },
{ name: '20×50m', category: '团体赛', event_group: '航空班组', unit: '秒' },
{ name: '旱地龙舟', category: '团体赛', event_group: '教师组', unit: '秒' },
{ name: '跳长绳', category: '团体赛', event_group: '文化班甲组', unit: '次' },
{ name: '折返跑', category: '团体赛', event_group: '文化班乙组', unit: '秒' }
]
events.forEach(event => {
insertEvent.run(event.name, event.category, event.event_group, event.unit)
})
return {
success: true,
message: '初始化数据成功',
data: {
users: 1,
roles: 3,
teams: teams.length,
events: events.length,
adminAccount: {
username: 'admin',
password: 'admin123'
}
}
}
} catch (error: any) {
console.error('Seed error:', error)
throw createError({
statusCode: 500,
message: '初始化数据失败: ' + error.message
})
}
})