refactor: 项目架构重构 - 目录标准化 + 清理冗余

- 目录重命名: backend/wdkj-server/ → server/, frontend/ai-dimension/ → client/
- 删除 20+ 冗余文件(WDKJ 旧脚本、Windows 脚本、过时文档、设计稿)
- 更新 package.json 元数据(移除 wdkj 命名)
- 完善三级 .gitignore(根 + server + client)
- 重写 README.md 和 CHANGELOG.md
- 工具脚本移至 scripts/
This commit is contained in:
Yuzhiran Dev
2026-07-11 12:45:37 +08:00
parent 66ac576082
commit c1d6dd3b29
106 changed files with 17436 additions and 2311 deletions
+211
View File
@@ -0,0 +1,211 @@
/**
* 认证 API 集成测试
*/
const request = require('supertest')
const mongoose = require('mongoose')
const app = require('../../src/index')
const User = require('../../src/models/User')
const Admin = require('../../src/models/Admin')
describe('Auth API', () => {
beforeAll(async () => {
// 连接测试数据库
const mongoURI = process.env.MONGODB_URI || 'mongodb://localhost:27017/wdkj'
if (mongoose.connection.readyState === 0) {
await mongoose.connect(mongoURI)
}
})
afterAll(async () => {
// 清理并关闭连接
if (mongoose.connection.readyState !== 0) {
await mongoose.connection.dropDatabase()
await mongoose.connection.close()
}
})
beforeEach(async () => {
// 每个测试前清空集合
await User.deleteMany({})
await Admin.deleteMany({})
})
describe('POST /api/auth/login', () => {
test('新用户应该成功注册', async () => {
const response = await request(app)
.post('/api/auth/login')
.send({
openid: 'new_user_openid',
userInfo: {
nickName: '新用户',
avatarUrl: 'https://example.com/avatar.jpg'
}
})
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
expect(response.body.data.isNewUser).toBe(true)
expect(response.body.data.openid).toBe('new_user_openid')
expect(response.body.data.token).toBeDefined()
})
test('老用户应该成功登录', async () => {
// 先创建一个用户
await User.create({
openid: 'existing_user_openid',
nickName: '老用户',
totalScore: 100
})
const response = await request(app)
.post('/api/auth/login')
.send({
openid: 'existing_user_openid',
userInfo: {
nickName: '老用户新名字'
}
})
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
expect(response.body.data.isNewUser).toBe(false)
expect(response.body.data.openid).toBe('existing_user_openid')
})
test('缺少 openid 应该返回错误', async () => {
const response = await request(app)
.post('/api/auth/login')
.send({
userInfo: {
nickName: '测试用户'
}
})
expect(response.status).toBe(400)
expect(response.body.success).toBe(false)
})
})
describe('POST /api/auth/admin/login', () => {
beforeEach(async () => {
// 创建测试管理员
const admin = new Admin({
username: 'testadmin',
password: 'password123',
role: 'super_admin',
status: 'active'
})
await admin.save()
})
test('管理员应该成功登录', async () => {
const response = await request(app)
.post('/api/auth/admin/login')
.send({
username: 'testadmin',
password: 'password123'
})
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
expect(response.body.data.token).toBeDefined()
expect(response.body.data.username).toBe('testadmin')
expect(response.body.data.role).toBe('super_admin')
})
test('错误的密码应该返回401', async () => {
const response = await request(app)
.post('/api/auth/admin/login')
.send({
username: 'testadmin',
password: 'wrongpassword'
})
expect(response.status).toBe(401)
expect(response.body.success).toBe(false)
})
test('不存在的用户应该返回401', async () => {
const response = await request(app)
.post('/api/auth/admin/login')
.send({
username: 'nonexistent',
password: 'password123'
})
expect(response.status).toBe(401)
expect(response.body.success).toBe(false)
})
test('禁用的账户应该返回403', async () => {
// 创建禁用的管理员
const disabledAdmin = new Admin({
username: 'disabled',
password: 'password123',
role: 'viewer',
status: 'inactive'
})
await disabledAdmin.save()
const response = await request(app)
.post('/api/auth/admin/login')
.send({
username: 'disabled',
password: 'password123'
})
expect(response.status).toBe(403)
expect(response.body.success).toBe(false)
})
})
describe('GET /api/auth/me', () => {
let userToken
let testUser
beforeEach(async () => {
// 创建测试用户并获取token
testUser = await User.create({
openid: 'test_user_openid',
nickName: '测试用户',
totalScore: 500
})
// 登录获取token
const loginResponse = await request(app)
.post('/api/auth/login')
.send({ openid: 'test_user_openid' })
userToken = loginResponse.body.data.token
})
test('应该返回当前用户信息', async () => {
const response = await request(app)
.get('/api/auth/me')
.set('Authorization', `Bearer ${userToken}`)
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
expect(response.body.data.openid).toBe('test_user_openid')
expect(response.body.data.nickName).toBe('测试用户')
})
test('缺少 token 应该返回401', async () => {
const response = await request(app)
.get('/api/auth/me')
expect(response.status).toBe(401)
expect(response.body.success).toBe(false)
})
test('不存在的用户应该返回401', async () => {
const response = await request(app)
.get('/api/auth/me')
.set('Authorization', 'Bearer invalid_token')
expect(response.status).toBe(401)
expect(response.body.success).toBe(false)
})
})
})
+205
View File
@@ -0,0 +1,205 @@
/**
* 用户 API 集成测试
*/
const request = require('supertest')
const mongoose = require('mongoose')
const app = require('../../src/index')
const User = require('../../src/models/User')
const jwt = require('jsonwebtoken')
describe('User API', () => {
let testUser
let authToken
beforeAll(async () => {
const mongoURI = process.env.MONGODB_URI || 'mongodb://localhost:27017/wdkj'
if (mongoose.connection.readyState === 0) {
await mongoose.connect(mongoURI)
}
})
afterAll(async () => {
if (mongoose.connection.readyState !== 0) {
await mongoose.connection.dropDatabase()
await mongoose.connection.close()
}
})
beforeEach(async () => {
await User.deleteMany({})
// 创建测试用户
testUser = await User.create({
openid: 'test_user_openid',
nickName: '测试用户',
avatarUrl: 'https://example.com/avatar.jpg',
exploreData: {
dim1: { bestScore: 100, completed: true },
dim2: { bestArea: 200, completed: false }
},
totalScore: 300,
unlockedDims: [1, 2]
})
// 生成认证 Token
authToken = jwt.sign(
{ userId: testUser._id.toString(), openid: testUser.openid },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
)
})
describe('GET /api/user/progress', () => {
test('应该返回用户探索进度', async () => {
const response = await request(app)
.get('/api/user/progress')
.set('Authorization', `Bearer ${authToken}`)
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
expect(response.body.data.exploreData).toBeDefined()
expect(response.body.data.exploreData.dim1.bestScore).toBe(100)
expect(response.body.data.exploreData.dim2.bestArea).toBe(200)
})
test('不存在的用户应该返回404', async () => {
const response = await request(app)
.get('/api/user/progress')
.set('Authorization', 'Bearer invalid_token')
expect(response.status).toBe(401)
})
})
describe('POST /api/user/progress', () => {
test('应该成功保存探索进度', async () => {
const response = await request(app)
.post('/api/user/progress')
.set('Authorization', `Bearer ${authToken}`)
.send({
dim: 1,
score: 150,
collectedEggs: 5
})
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
// 验证数据库更新
const updatedUser = await User.findOne({ openid: 'test_user_openid' })
expect(updatedUser.exploreData.dim1.bestScore).toBe(150)
expect(updatedUser.exploreData.dim1.collectedEggs).toBe(5)
})
test('新用户应该自动解锁维度', async () => {
const response = await request(app)
.post('/api/user/progress')
.set('Authorization', `Bearer ${authToken}`)
.send({
dim: 3,
score: 100
})
expect(response.status).toBe(200)
const updatedUser = await User.findOne({ openid: 'test_user_openid' })
expect(updatedUser.unlockedDims).toContain(3)
})
})
describe('GET /api/user/leaderboard', () => {
beforeEach(async () => {
// 创建多个测试用户
await User.create([
{ openid: 'user1', nickName: '用户1', totalScore: 500, dim1Score: 200 },
{ openid: 'user2', nickName: '用户2', totalScore: 300, dim1Score: 150 },
{ openid: 'user3', nickName: '用户3', totalScore: 400, dim1Score: 100 }
])
})
test('应该返回总分排行榜', async () => {
const response = await request(app)
.get('/api/user/leaderboard')
.query({ limit: 10 })
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
expect(response.body.data).toHaveLength(4) // 包含testUser
expect(response.body.data[0].totalScore).toBeGreaterThanOrEqual(
response.body.data[1].totalScore
)
})
test('应该返回维度排行榜', async () => {
const response = await request(app)
.get('/api/user/leaderboard')
.query({ dim: 1, limit: 10 })
expect(response.status).toBe(200)
expect(response.body.data[0].dim1Score).toBe(200)
})
test('应该限制返回数量', async () => {
const response = await request(app)
.get('/api/user/leaderboard')
.query({ limit: 2 })
expect(response.body.data).toHaveLength(2)
})
})
describe('PUT /api/user/info', () => {
test('应该成功更新用户信息', async () => {
const response = await request(app)
.put('/api/user/info')
.set('Authorization', `Bearer ${authToken}`)
.send({
nickName: '新名字',
avatarUrl: 'https://example.com/new-avatar.jpg'
})
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
const updatedUser = await User.findOne({ openid: 'test_user_openid' })
expect(updatedUser.nickName).toBe('新名字')
expect(updatedUser.avatarUrl).toBe('https://example.com/new-avatar.jpg')
})
})
describe('POST /api/user/collect-knowledge', () => {
test('应该成功收藏知识', async () => {
const knowledgeId = new mongoose.Types.ObjectId()
const response = await request(app)
.post('/api/user/collect-knowledge')
.set('Authorization', `Bearer ${authToken}`)
.send({ knowledgeId: knowledgeId.toString() })
expect(response.status).toBe(200)
expect(response.body.success).toBe(true)
const updatedUser = await User.findOne({ openid: 'test_user_openid' })
expect(updatedUser.collectedKnowledge).toContainEqual(knowledgeId)
})
test('重复收藏应该返回已存在', async () => {
const knowledgeId = new mongoose.Types.ObjectId()
// 第一次收藏
await request(app)
.post('/api/user/collect-knowledge')
.set('Authorization', `Bearer ${authToken}`)
.send({ knowledgeId: knowledgeId.toString() })
// 第二次收藏
const response = await request(app)
.post('/api/user/collect-knowledge')
.set('Authorization', `Bearer ${authToken}`)
.send({ knowledgeId: knowledgeId.toString() })
expect(response.status).toBe(200)
})
})
})