Files
Web_BLV_OA_Exam_Prod/api/database/index.ts
XuJiacheng 57101fac37 feat: 更新考试相关页面,添加刷新功能,修改考试状态显示
- 注:当前代码还存在bug:查看结果暂出现错误。
- 在 SubjectSelectionPage 页面中添加刷新按钮,允许用户手动刷新考试任务列表。
- 修改 UserTaskPage 页面,重构考试任务为答题记录,更新数据结构和状态显示。
- 在 AdminDashboardPage、UserManagePage、UserRecordsPage 等管理页面中添加考试状态显示,使用不同颜色区分状态(不及格、合格、优秀)。
- 在 ResultPage 中显示考试状态,确保用户能够清晰了解考试结果。
- 添加约束,确保单次考试试卷中题目不可重复出现,并记录相关规范。
- 添加评分状态约束,根据得分占比自动计算考试状态,并在结果页面显示。
2025-12-29 20:28:33 +08:00

188 lines
5.4 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 path from 'path';
import fs from 'fs';
import { v4 as uuidv4 } from 'uuid';
import { createRequire } from 'module';
// 在ES模块中创建require函数用于兼容CommonJS模块
const require = createRequire(import.meta.url);
const DEFAULT_DB_DIR = path.join(process.cwd(), 'data');
const DEFAULT_DB_PATH = path.join(DEFAULT_DB_DIR, 'survey.db');
const DB_PATH = process.env.DB_PATH || DEFAULT_DB_PATH;
const DB_DIR = path.dirname(DB_PATH);
// 确保数据目录存在
if (!fs.existsSync(DB_DIR)) {
fs.mkdirSync(DB_DIR, { recursive: true });
}
// 延迟初始化数据库连接
let db: any = null;
let isInitialized = false;
// 初始化数据库连接的函数
export const initDbConnection = async () => {
if (!isInitialized) {
try {
// 使用require加载sqlite3因为它是CommonJS模块
const sqlite3 = require('sqlite3');
db = new sqlite3.Database(DB_PATH, (err: Error) => {
if (err) {
console.error('数据库连接失败:', err);
} else {
console.log('数据库连接成功');
// 启用外键约束
db.run('PRAGMA foreign_keys = ON');
}
});
isInitialized = true;
} catch (error) {
console.error('初始化数据库失败:', error);
// 初始化失败不设置isInitialized为true允许后续调用再次尝试
return null;
}
}
return db;
};
// 导出一个函数,用于获取数据库连接
export const getDb = async () => {
if (!db) {
return await initDbConnection();
}
return db;
};
const exec = async (sql: string): Promise<void> => {
return new Promise(async (resolve, reject) => {
const db = await getDb();
if (!db) {
reject(new Error('数据库连接未初始化'));
return;
}
db.exec(sql, (err: Error) => {
if (err) reject(err);
else resolve();
});
});
};
const tableExists = async (tableName: string): Promise<boolean> => {
const row = await get(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?",
[tableName]
);
return Boolean(row);
};
const columnExists = async (tableName: string, columnName: string): Promise<boolean> => {
const columns = await query(`PRAGMA table_info(${tableName})`);
return columns.some((col: any) => col.name === columnName);
};
const ensureColumn = async (tableName: string, columnDefSql: string, columnName: string) => {
if (!(await columnExists(tableName, columnName))) {
console.log(`添加列 ${tableName}.${columnName}`);
await exec(`ALTER TABLE ${tableName} ADD COLUMN ${columnDefSql}`);
} else {
console.log(`${tableName}.${columnName} 已存在`);
}
};
const ensureTable = async (createTableSql: string) => {
await exec(createTableSql);
};
const ensureIndex = async (createIndexSql: string) => {
await exec(createIndexSql);
};
const migrateDatabase = async () => {
// 跳过迁移,因为数据库连接可能未初始化
console.log('跳过数据库迁移');
};
// 数据库初始化函数
export const initDatabase = async () => {
try {
// 确保数据库连接已初始化
await initDbConnection();
// 检查是否需要初始化如果users表不存在则执行初始化
const usersTableExists = await tableExists('users');
if (!usersTableExists) {
// 读取并执行初始化SQL文件
const initSqlPath = path.join(path.dirname(import.meta.url.replace('file:///', '')), 'init.sql');
const initSql = fs.readFileSync(initSqlPath, 'utf8');
await exec(initSql);
console.log('数据库初始化成功');
} else {
console.log('数据库表已存在,跳过初始化');
await ensureColumn('questions', "analysis TEXT NOT NULL DEFAULT ''", 'analysis');
await ensureColumn('quiz_records', "score_percentage REAL", 'score_percentage');
await ensureColumn('quiz_records', "status TEXT", 'status');
}
} catch (error) {
console.error('数据库初始化失败:', error);
// 即使初始化失败,服务器也应该继续运行
}
};
// 数据库查询工具函数
export const query = async (sql: string, params: any[] = []): Promise<any[]> => {
return new Promise(async (resolve, reject) => {
const db = await getDb();
if (!db) {
reject(new Error('数据库连接未初始化'));
return;
}
db.all(sql, params, (err: Error, rows: any[]) => {
if (err) {
reject(err);
} else {
resolve(rows);
}
});
});
};
// all函数是query函数的别名用于向后兼容
export const all = query;
export const run = async (sql: string, params: any[] = []): Promise<{ id: string }> => {
return new Promise(async (resolve, reject) => {
const db = await getDb();
if (!db) {
reject(new Error('数据库连接未初始化'));
return;
}
db.run(sql, params, function(this: any, err: Error | null) {
if (err) {
reject(err);
} else {
resolve({ id: this.lastID ? this.lastID.toString() : '' });
}
});
});
};
export const get = async (sql: string, params: any[] = []): Promise<any> => {
return new Promise(async (resolve, reject) => {
const db = await getDb();
if (!db) {
reject(new Error('数据库连接未初始化'));
return;
}
db.get(sql, params, (err: Error, row: any) => {
if (err) {
reject(err);
} else {
resolve(row);
}
});
});
};