diff --git a/src/api/gxmu/student/index.ts b/src/api/gxmu/student/index.ts new file mode 100644 index 0000000..b685f66 --- /dev/null +++ b/src/api/gxmu/student/index.ts @@ -0,0 +1,77 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { StudentRoster, StudentRosterParam } from './model'; + +/** 学生名册分页查询 */ +export async function pageStudentRoster(params: StudentRosterParam) { + const res = await request.get>>( + '/gxmu/student/page', + { params } + ); + if (res.data.code === 0 && res.data.data) { + return res.data.data; + } + return Promise.reject(new Error(res.data.message)); +} + +/** 学生名册详情 */ +export async function getStudentRoster(id: number) { + const res = await request.get>( + '/gxmu/student/' + id + ); + if (res.data.code === 0 && res.data.data) { + return res.data.data; + } + return Promise.reject(new Error(res.data.message)); +} + +/** 导出名册(返回已脱敏列表,由前端生成文件) */ +export async function exportStudentRoster(params: StudentRosterParam) { + const res = await request.post>( + '/gxmu/student/export', + null, + { params } + ); + if (res.data.code === 0 && res.data.data) { + return res.data.data; + } + return Promise.reject(new Error(res.data.message)); +} + +/** 自助认领(学号 + 姓名) */ +export async function claimStudent(data: { xh: string; xm: string }) { + const res = await request.post>( + '/gxmu/student/claim', + data + ); + if (res.data.code === 0) { + return res.data.message; + } + return Promise.reject(new Error(res.data.message)); +} + +/** 手动认领/改绑 */ +export async function bindStudent( + id: number, + data?: { userId?: number; phone?: string } +) { + const res = await request.put>( + `/gxmu/student/${id}/claim`, + data || {} + ); + if (res.data.code === 0) { + return res.data.message; + } + return Promise.reject(new Error(res.data.message)); +} + +/** 解除认领 */ +export async function unbindStudent(id: number) { + const res = await request.put>( + `/gxmu/student/${id}/unclaim` + ); + if (res.data.code === 0) { + return res.data.message; + } + return Promise.reject(new Error(res.data.message)); +} diff --git a/src/api/gxmu/student/model/index.ts b/src/api/gxmu/student/model/index.ts new file mode 100644 index 0000000..f2505f5 --- /dev/null +++ b/src/api/gxmu/student/model/index.ts @@ -0,0 +1,60 @@ +/** + * 学生名册(开放平台同步) + */ + +/** 学生名册记录 */ +export interface StudentRoster { + id: number; + /** 学号 */ + xh: string; + /** 姓名 */ + xm?: string; + /** 性别码 */ + xbm?: string; + /** 性别 */ + sex?: string; + /** 民族码 */ + mzm?: string; + /** 民族 */ + nation?: string; + /** 政治面貌码 */ + zzmmm?: string; + /** 政治面貌 */ + politics?: string; + /** 身份证件号(后端已脱敏) */ + sfzjh?: string; + /** 手机号(后端已脱敏) */ + sjh?: string; + /** 平台班级码 */ + bjm?: string; + /** 平台班号 */ + bh?: string; + classId?: number; + className?: string; + collegeId?: number; + collegeName?: string; + dwh?: string; + zyh?: string; + zymc?: string; + /** 培养层次 */ + pyccmc?: string; + /** 状态:1在校 0毕业 */ + status?: number; + /** 已认领的账号ID */ + userId?: number; + claimTime?: string; + syncTime?: string; +} + +/** 名册查询参数 */ +export interface StudentRosterParam { + page?: number; + limit?: number; + collegeId?: number; + classId?: number; + xh?: string; + xm?: string; + pyccmc?: string; + status?: number; + claimed?: boolean; +} diff --git a/src/api/gxmu/sync/index.ts b/src/api/gxmu/sync/index.ts new file mode 100644 index 0000000..bcb6b4b --- /dev/null +++ b/src/api/gxmu/sync/index.ts @@ -0,0 +1,66 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { + SyncBatchStatus, + SyncRecord, + SyncRecordParam +} from './model'; + +/** 提交类接口统一返回批次号 */ +async function submit(url: string) { + const res = await request.post>(url); + if (res.data.code === 0 && res.data.data) { + return res.data.data; + } + return Promise.reject(new Error(res.data.message)); +} + +/** 提交全部同步,返回批次号 */ +export function syncAll() { + return submit('/gxmu/sync/all'); +} + +/** 提交部门同步,返回批次号 */ +export function syncDept() { + return submit('/gxmu/sync/dept'); +} + +/** 提交教师同步,返回批次号 */ +export function syncTeacher() { + return submit('/gxmu/sync/teacher'); +} + +/** 提交班级同步,返回批次号 */ +export function syncClass() { + return submit('/gxmu/sync/class'); +} + +/** 提交学生同步,返回批次号 */ +export function syncStudent() { + return submit('/gxmu/sync/student'); +} + +/** + * 查询当前(或最近一次)批次进度。 + * + * 同步是异步的:学生全量约 9.8 万条、耗时 75~90 秒,提交后需轮询本接口看进度。 + */ +export async function syncStatus() { + const res = await request.get>('/gxmu/sync/status'); + if (res.data.code === 0 && res.data.data) { + return res.data.data; + } + return Promise.reject(new Error(res.data.message)); +} + +/** 同步记录分页查询 */ +export async function pageSyncRecord(params: SyncRecordParam) { + const res = await request.get>>( + '/gxmu/sync/record/page', + { params } + ); + if (res.data.code === 0 && res.data.data) { + return res.data.data; + } + return Promise.reject(new Error(res.data.message)); +} diff --git a/src/api/gxmu/sync/model/index.ts b/src/api/gxmu/sync/model/index.ts new file mode 100644 index 0000000..84b0470 --- /dev/null +++ b/src/api/gxmu/sync/model/index.ts @@ -0,0 +1,79 @@ +/** + * 开放平台数据同步 + */ + +/** 单段同步结果(同步返回,异步改动后仅用于记录展示) */ +export interface SyncResult { + /** 同步类型:dept/teacher/class/student */ + syncType: string; + /** 成功条数 */ + successCount: number; + /** 失败条数 */ + failCount: number; + /** 跳过/停用条数 */ + skipCount: number; + /** 是否成功 */ + success: boolean; + /** 错误信息 */ + errorMsg?: string; +} + +/** 某一段的进度 */ +export interface SyncSectionStatus { + /** 同步类型:dept/teacher/class/student */ + syncType: string; + /** pending 待执行 / running 进行中 / success 成功 / fail 失败 */ + state: 'pending' | 'running' | 'success' | 'fail'; + successCount?: number; + failCount?: number; + skipCount?: number; + startTime?: string; + endTime?: string; + errorMsg?: string; +} + +/** 批次进度 */ +export interface SyncBatchStatus { + /** 是否有同步任务在执行 */ + running: boolean; + batchId?: string; + triggerType?: string; + triggerUser?: string; + startTime?: string; + /** 正在执行的段 */ + currentSection?: string; + /** 本次批次的各段状态 */ + sections?: SyncSectionStatus[]; +} + +/** 同步记录 */ +export interface SyncRecord { + id: number; + /** 批次号 */ + batchId?: string; + /** 同步类型 */ + syncType: string; + /** 触发方式:schedule/manual */ + triggerType: string; + /** 触发人 */ + triggerUser?: string; + /** 开始时间 */ + startTime?: string; + /** 结束时间 */ + endTime?: string; + successCount: number; + failCount: number; + skipCount: number; + /** 状态:0成功 1失败 2进行中 */ + status: number; + /** 错误摘要 */ + errorMsg?: string; +} + +/** 同步记录查询参数 */ +export interface SyncRecordParam { + page?: number; + limit?: number; + syncType?: string; + batchId?: string; +} diff --git a/src/views/gxmu/dataSync/index.vue b/src/views/gxmu/dataSync/index.vue new file mode 100644 index 0000000..38545bc --- /dev/null +++ b/src/views/gxmu/dataSync/index.vue @@ -0,0 +1,370 @@ + + + + + diff --git a/src/views/gxmu/studentRoster/index.vue b/src/views/gxmu/studentRoster/index.vue new file mode 100644 index 0000000..c950496 --- /dev/null +++ b/src/views/gxmu/studentRoster/index.vue @@ -0,0 +1,362 @@ + + + + +