Add hierarchical region data to candidate and center records

This commit is contained in:
2026-07-20 11:50:51 +08:00 Unverified
parent 352f471ed0
commit c5446d5241
21 changed files with 387 additions and 64 deletions
+11 -6
View File
@@ -132,7 +132,7 @@ try {
assert.equal((await candidate.request('/api/candidate/dashboard')).response.status, 428, '未补全个人信息前仍不得进入考试业务');
const updateProfile = await candidate.request('/api/candidate/profile', {
method: 'PUT',
body: { name: '测试考生新名', gender: '男', idNumber: '320101200801019999', nativePlace: '江苏海州', birthDate: '2008-01-01', ethnicity: '汉族', phone: '13900009999', email: 'test@example.com', schoolId: 'school_hz1', classId: 'class_hz1_302', address: '海州市测试 1 号', postalCode: '222000', guardianName: '测试家长', guardianPhone: '13800008888', emergencyContact: '测试家长', emergencyPhone: '13800008888' }
body: { name: '测试考生新名', gender: '男', idNumber: '320101200801019999', nativePlace: '江苏海州', birthDate: '2008-01-01', ethnicity: '汉族', phone: '13900009999', email: 'test@example.com', schoolId: 'school_hz1', classId: 'class_hz1_302', provinceCode: '320000', cityCode: '320700', districtCode: '320706', address: '测试 1 号', postalCode: '222000', guardianName: '测试家长', guardianPhone: '13800008888', emergencyContact: '测试家长', emergencyPhone: '13800008888' }
});
assert.equal(updateProfile.response.status, 200, '考生应补全包含籍贯、住址、手机、邮箱和班级的完整资料');
assert.equal(updateProfile.data.profile.profileCompleted, true, '完整资料提交后应标记完成');
@@ -155,7 +155,7 @@ try {
const schoolCenters = await schoolAdmin.request('/api/admin/centers');
assert.ok(schoolCenters.data.centers.every(item => item.schoolId === 'school_hz1'), '校级管理员只能读取本校考点');
const newCenter = await schoolAdmin.request('/api/admin/centers', { method: 'POST', body: {
code: 'HZ01-EAST', name: '海州市第一中学东区考点', address: '海州市测试路 8 号', contact: '0518-12345678',
code: 'HZ01-EAST', name: '海州市第一中学东区考点', provinceCode: '320000', cityCode: '320700', districtCode: '320706', address: '测试路 8 号', contact: '0518-12345678',
managerName: '测试负责人', managerPhone: '13800001234', emergencyPhone: '0518-120', gateOpenTime: '07:00', transport: '东门入场', status: 'active', notes: '自动化测试档案',
rooms: [{ code: 'E001', name: '东区第 001 考场', building: '东教学楼', floor: '1 层', capacity: 30, seatPlan: '按现场座次表编排', roomType: 'standard', status: 'active', notes: '' }]
} });
@@ -214,13 +214,13 @@ try {
const centerHeaders = centerWorkbook.worksheets[0].getRow(2).values.map(String);
assert.ok(centerHeaders.includes('座位编排说明'), '考场 Excel 应使用座位编排说明');
assert.ok(!centerHeaders.some(item => item.includes('座位起号') || item.includes('座位止号')), '考场 Excel 不应再出现座位起止号');
assert.equal(centerWorkbook.worksheets[0].getCell('M3').value, '001', '考场代码应保留前导零');
assert.equal(centerWorkbook.worksheets[0].getCell('M3').numFmt, '@', '标识号列应固定为文本格式');
assert.equal(centerWorkbook.worksheets[0].getCell('S3').value, '001', '考场代码应保留前导零');
assert.equal(centerWorkbook.worksheets[0].getCell('S3').numFmt, '@', '标识号列应固定为文本格式');
const classAdminImportFile = Buffer.from(await buildWorkbook('class_admins', [{ schoolCode: 'HZ01', className: '高一(8)班', displayName: 'Excel 班管', username: 'excel_class_admin', initialPassword: 'ExcelClass123!', status: '启用' }]));
const classAdminImport = await schoolAdmin.request('/api/admin/excel/class_admins', { method: 'POST', headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }, body: classAdminImportFile });
assert.equal(classAdminImport.data.count, 1, '班级管理员应支持 Excel 批量导入');
const centerImportFile = Buffer.from(await buildWorkbook('centers', [{
schoolCode: 'HZ01', centerCode: 'HZ01-XLSX', centerName: 'Excel 导入考点', address: '海州市表格路 1 号', managerName: '表格负责人', managerPhone: '13800138001', contact: '0518-88000000', emergencyPhone: '0518-120', gateOpenTime: '07:10', transport: '北门入场', centerStatus: '启用', centerNotes: 'Excel 自动化测试',
schoolCode: 'HZ01', centerCode: 'HZ01-XLSX', centerName: 'Excel 导入考点', provinceCode: '320000', provinceName: '江苏省', cityCode: '320700', cityName: '连云港市', districtCode: '320706', districtName: '海州区', address: '表格路 1 号', managerName: '表格负责人', managerPhone: '13800138001', contact: '0518-88000000', emergencyPhone: '0518-120', gateOpenTime: '07:10', transport: '北门入场', centerStatus: '启用', centerNotes: 'Excel 自动化测试',
roomCode: 'X001', roomName: 'Excel 第 001 考场', building: '综合楼', floor: '2 层', capacity: 32, seatPlan: '按现场桌贴编排', roomType: '标准考场', roomStatus: '启用', roomNotes: ''
}]));
const centerImport = await schoolAdmin.request('/api/admin/excel/centers', { method: 'POST', headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }, body: centerImportFile });
@@ -327,7 +327,12 @@ try {
const candidates = await admin.request('/api/admin/candidates');
const profile = candidates.data.candidates.find(item => item.candidateNumber === candidateNumber);
assert.ok(profile, '管理员应能看到新注册考生');
assert.equal(profile.address, '海州市测试 1 号', '管理员应能审核考生自主填写的完整资料');
assert.equal(profile.address, '测试 1 号', '详细门牌地址应独立保存');
assert.deepEqual(
[profile.provinceCode, profile.cityCode, profile.districtCode, profile.provinceName, profile.cityName, profile.districtName],
['320000', '320700', '320706', '江苏省', '连云港市', '海州区'],
'管理员应能审核考生自主填写且经过服务端规范化的省市区县信息'
);
const schoolCandidates = await schoolAdmin.request('/api/admin/candidates');
assert.ok(schoolCandidates.data.candidates.some(item => item.id === profile.id), '校级管理员应看到本校考生');
const classCandidates = await classAdmin.request('/api/admin/candidates');