index.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. import type { AxiosResponse } from "axios";
  2. interface SplitConfig {
  3. /** index of sheets */
  4. i: number;
  5. /** 覆盖区域的width */
  6. w: number;
  7. /** 覆盖区域的height */
  8. h: number;
  9. /** 从哪里开始覆盖 左上角为 (0, 0) */
  10. x: number;
  11. /** 从哪里开始覆盖 左上角为 (0, 0) */
  12. y: number;
  13. }
  14. type SingleSheetConfig = SplitConfig;
  15. export type PictureSlice = SplitConfig;
  16. export interface MarkStore {
  17. setting: Setting;
  18. groups: Array<Group>;
  19. status: {
  20. /** 为false时不更新以下count字段 */
  21. valid: boolean;
  22. /** 个人评卷数量 */
  23. personCount: number;
  24. /** 总评卷数量 */
  25. markedCount: number;
  26. /** 总数量 */
  27. totalCount: number;
  28. /** 问题卷数量 */
  29. problemCount: number;
  30. /** 待仲裁卷数量 */
  31. arbitrateCount: number;
  32. /**成绩校验,批量校验时,已校验的学生id的集合 */
  33. markedCountStuIds?: any;
  34. };
  35. /** 保持数量为3(prefetchCount) */
  36. tasks: Array<Task>;
  37. /** 用来切换task,还有回看 */
  38. currentTask?: Task;
  39. currentQuestion?: Question;
  40. currentScore?: number;
  41. currentSpecialTag?: string;
  42. currentSpecialTagType?: SpecialTag.tagType;
  43. /** 是否打开回评侧边栏 */
  44. historyOpen: boolean;
  45. historyTasks: Array<Task>;
  46. /** 删除这些轨迹 */
  47. removeScoreTracks: Array<Track>;
  48. /** 聚焦这些tracks */
  49. focusTracks: Array<Track>;
  50. message: string | null;
  51. maxModalZIndex: number;
  52. /** 缩略图设置滚动到宽度的百分比 */
  53. minimapScrollToX?: number;
  54. /** 缩略图设置滚动到高度的百分比 */
  55. minimapScrollToY?: number;
  56. /** 是否显示全卷 */
  57. allPaperModal: boolean;
  58. /** 是否显示原卷 */
  59. sheetViewModal: boolean;
  60. /** 是否全局遮盖 */
  61. globalMask: boolean;
  62. }
  63. export interface Setting {
  64. /** 扫描图片或者多媒体,多媒体只允许 common mode */
  65. examType: "SCAN_IMAGE" | "MULTI_MEDIA";
  66. /** 阅卷模式 TRACK | COMMON */
  67. mode: "TRACK" | "COMMON";
  68. /** 是否允许模式切换,true为不允许 */
  69. forceMode: boolean;
  70. /** 是否显示原图功能 */
  71. sheetView: boolean;
  72. /** 是否自动跳转 */
  73. autoScroll: boolean;
  74. /** 原图遮盖规则 */
  75. sheetConfig: Array<SingleSheetConfig>;
  76. /** 是否开启全零分 */
  77. enableAllZero: boolean;
  78. /** 是否允许裁切 */
  79. enableSplit: boolean;
  80. /** 图片服务地址 */
  81. fileServer: string;
  82. /** 评卷员姓名 */
  83. userName: string;
  84. /** 科目信息(试卷和答案功能)*/
  85. subject: Subject;
  86. /** 强制标记是否开启 */
  87. forceSpecialTag: boolean;
  88. /** 评卷小工具控制字段 */
  89. uiSetting: UISetting;
  90. /** 只显示试评名称 TRIAL("试评"), FORMAL("正评"), FINISH("结束"): 结束状态不会在评卷端出现 */
  91. statusValue: "TRIAL" | "FORMAL" | null;
  92. /** 问题卷类型 */
  93. problemTypes: Array<{ id: number; name: string }>;
  94. /** 当前评卷分组号 */
  95. groupNumber: number;
  96. /** 当前评卷分组名称 */
  97. groupTitle: string;
  98. /** 推荐老师评卷的数量,到达这个数量提示老师 */
  99. topCount: number;
  100. /** 使用裁切整图时的裁切配置 [0,1]|[0,0.3,0.25,0.55], */
  101. splitConfig: Array<number>;
  102. /** 预加载任务数量 */
  103. prefetchCount: number;
  104. /** 评卷开始时间 */
  105. startTime: number;
  106. /** 评卷结束时间 */
  107. endTime: number;
  108. /** 是否是未选做类型 */
  109. selective: boolean;
  110. /** 可回评数量是否有限制数 */
  111. remarkCount?: any;
  112. /** 是否展示双评的轨迹 */
  113. doubleTrack?: boolean;
  114. /** 全卷复核页面是否要滑到页面底部才允许点击复核按钮 */
  115. inspectScroll?: boolean;
  116. /** 评卷员页头是否展示客观分 */
  117. showObjectiveScore?: boolean;
  118. }
  119. /** 科目信息(试卷和答案功能) */
  120. interface RawSubject {
  121. /** 科目名称 */
  122. name: string;
  123. /** 科目编号 */
  124. code: string;
  125. /** 学生答案json url */
  126. answerUrl: string;
  127. /** 试卷json url */
  128. paperUrl: string;
  129. }
  130. /** 科目信息(试卷和答案功能)增加前端自定义 questions字段*/
  131. interface Subject extends RawSubject {
  132. /** 前端自定义questions字段, 在多媒体阅卷模式下使用 */
  133. questions: Array<RichTextQuestion>;
  134. }
  135. // setting for admin page
  136. export interface AdminPageSetting {
  137. /** 扫描图片或者多媒体,多媒体只允许 common mode */
  138. examType: "SCAN_IMAGE" | "MULTI_MEDIA";
  139. /** 图片服务地址 */
  140. fileServer: string;
  141. /** 管理员姓名 */
  142. userName: string;
  143. /** 科目信息 */
  144. subject: Subject;
  145. /** 使用裁切整图时的裁切配置 [0,1]|[0,0.3,0.25,0.55], */
  146. splitConfig: Array<number>;
  147. enableSplit: boolean;
  148. doubleTrack?: boolean;
  149. inspectScroll?: boolean;
  150. }
  151. export interface AdminPageSettingForImport extends AdminPageSetting {
  152. studentIds: number[];
  153. tagIds: number[];
  154. inspectCount: number;
  155. message: string;
  156. }
  157. export interface Group {
  158. markerId: number;
  159. /** 分组编号 */
  160. number: number;
  161. /** 分组title */
  162. title: string;
  163. /** 总评卷数量 */
  164. markedCount: number;
  165. /** 总数量 */
  166. totalCount: number;
  167. }
  168. interface RawTask {
  169. libraryId: number;
  170. /** 学生ID */
  171. studentId: number;
  172. /** 任务编号 */
  173. secretNumber: string;
  174. /** 后端处理是否显示 */
  175. /** 学生名称 */
  176. studentName: string;
  177. /** 学生编号 */
  178. studentCode: string;
  179. /** 考试编号 */
  180. examNumber: string;
  181. /** 一般不要用此处的subject,优先用setting.subject */
  182. subject?: Subject;
  183. /** 裁切图url */
  184. sliceUrls: Array<string>;
  185. /** 最高显示优先级,有sliceConfig就用sliceConfig,否则使用sheetConfig */
  186. sliceConfig: Array<PictureSlice>;
  187. /** sliceUrls为空,则是多媒体阅卷,显示JSON */
  188. jsonUrl: string;
  189. questionList: Array<Question>;
  190. specialTagList: Array<SpecialTag>;
  191. /** 原图url */
  192. sheetUrls: Array<string>;
  193. /** 客观分 复核也用到 */
  194. objectiveScore: number;
  195. /** 评卷总分 */
  196. markerScore: number;
  197. /** 评卷时间 */
  198. markerTime: number;
  199. /** 复核有用 */
  200. inspectTime?: number;
  201. /** 是否自评,暂时用不着 */
  202. self: boolean;
  203. /** 是否回评 */
  204. previous: boolean;
  205. /** 是否是打回 */
  206. rejected: boolean;
  207. /** 打回原因 冒号拼接的 */
  208. rejectReason: string;
  209. message: string | null;
  210. rejectScoreList?: any;
  211. headerTagList?: any;
  212. }
  213. export interface Task extends RawTask {
  214. /** 评卷结果,在task第一次被访问时自动添加,watch currentTask */
  215. markResult: MarkResult;
  216. /** 前端自用,用于标记阅卷开始时间和计算spent */
  217. __markStartTime: number;
  218. }
  219. interface RawQuestion {
  220. /** 分组序号 */
  221. groupNumber: number;
  222. /** 大题号 */
  223. mainNumber: number;
  224. /** 小题号 */
  225. subNumber: string;
  226. /** 分数间隔 */
  227. intervalScore: number;
  228. /** 默认分数 */
  229. defaultScore: number;
  230. /** 限制最小分数 */
  231. minScore: number;
  232. /** 限制最大分数 */
  233. maxScore: number;
  234. /** 题目名称 */
  235. title: string;
  236. /** 轨迹列表 */
  237. trackList: Array<Track>;
  238. /** 得分;null的值时是为打回时可以被评卷修改的;null也是从未评分过的情况,要通过rejected来判断 */
  239. score: number | null;
  240. /** 未计分 */
  241. uncalculate: boolean;
  242. /** 选做题分组 */
  243. selectiveIndex: number | null;
  244. rejected?: boolean;
  245. questionName?: string;
  246. headerTrack?: any;
  247. }
  248. export interface Question extends RawQuestion {
  249. /** question 在 task 里面的 index ,用来对应 scoreList 的 score */
  250. __index: number;
  251. }
  252. export interface ColorMap {
  253. [key: string]: string;
  254. }
  255. /** 轨迹数据 */
  256. export interface Track {
  257. /** 大题号 */
  258. mainNumber: number;
  259. /** 小题号,当前api中只有number // 特殊标记中没有 */
  260. subNumber: string;
  261. /** 前端使用,暂时用不着,赋0 */
  262. number: number;
  263. /** 第几张图 */
  264. offsetIndex: number;
  265. /** 左上角为原点 */
  266. offsetX: number;
  267. offsetY: number;
  268. /** 相对slice的位置比例 */
  269. positionX: number;
  270. positionY: number;
  271. /** 评分数 */
  272. score: number;
  273. /** 是否此处未作答,未作答时,score默认是-0分 */
  274. unanswered: boolean;
  275. markerId?: number;
  276. color?: string;
  277. isByMultMark?: boolean;
  278. }
  279. /** 特殊标记数据 */
  280. export interface SpecialTag {
  281. /** 第几张图 */
  282. offsetIndex: number;
  283. /** 左上角为原点 */
  284. offsetX: number;
  285. offsetY: number;
  286. /** 相对slice的位置比例 */
  287. positionX: number;
  288. positionY: number;
  289. /** 特殊标记的字符串,勾叉 */
  290. tagName: string;
  291. tagType: "TEXT" | "CIRCLE" | "RIGHT" | "WRONG" | "HALF_RIGTH";
  292. markerId?: number;
  293. color?: string;
  294. isByMultMark?: boolean;
  295. }
  296. export interface UISetting {
  297. /** 给分面板展示形态 */
  298. "score.board.collapse": boolean;
  299. /** 0.2 gap */
  300. /** 试卷缩放比例 */
  301. "answer.paper.scale": number;
  302. /**
  303. * 给分模式
  304. * "keyboard": 键盘模式
  305. * "mouse": 鼠标模式
  306. * */
  307. "normal.mode": "keyboard" | "mouse";
  308. /** 弹窗显示试卷 */
  309. "paper.modal": boolean;
  310. /** 弹窗显示答案 */
  311. "answer.modal": boolean;
  312. /** 弹窗显示缩略图 */
  313. "minimap.modal": boolean;
  314. /** 弹窗显示特殊字符 */
  315. "specialTag.modal": boolean;
  316. /** 弹窗显示快捷键配置 */
  317. "shortCut.modal": boolean;
  318. /** 0.1 gap */
  319. /** 分数标记缩放比例 */
  320. "score.fontSize.scale": number;
  321. }
  322. export interface MarkResult {
  323. libraryId: number;
  324. studentId: number;
  325. statusValue: "TRIAL" | "FORMAL" | null;
  326. /** 毫秒单位 */
  327. spent: number;
  328. // 轨迹 or 键盘
  329. markerScore: number | null;
  330. /** 轨迹列表 */
  331. trackList: Array<Track>;
  332. /** 给分列表 */
  333. scoreList: Array<number | null>;
  334. /** 轨迹和键盘都需要 */
  335. specialTagList: Array<SpecialTag>;
  336. /** 问题卷 */
  337. problem: boolean;
  338. /** 问题卷类型ID */
  339. problemTypeId: number;
  340. /** 当前task是否为学生未选做 */
  341. unselective: boolean;
  342. }
  343. /** 前端自用,用来渲染裁切图 */
  344. export interface SliceImage {
  345. /** 当前是 ObjectURL , 因为 DataURL 性能太差 */
  346. url: string;
  347. indexInSliceUrls: number;
  348. trackList: Array<Track>;
  349. tagList: Array<SpecialTag>;
  350. // originalImageWidth: number; // 为了兼容原图还原轨迹而添加的属性,当前CommonMarkBody用不到
  351. // originalImageHeight: number; // 为了兼容原图还原轨迹而添加的属性,当前CommonMarkBody用不到
  352. sliceImageWidth: number;
  353. sliceImageHeight: number;
  354. /** 裁切图在原图中的左上角的x偏移量 */
  355. dx: number;
  356. /** 裁切图在原图中的左上角的y偏移量 */
  357. dy: number;
  358. /** 在多个图片从高至低排列中累积的高度 */
  359. accumTopHeight: number;
  360. /** 当前裁切图有效宽度,大小不一的裁切图时有用。
  361. * 为了能让多张图统一比例的缩放,所以将所有的图的宽度设为一样了。 */
  362. effectiveWidth: number;
  363. }
  364. export type MarkHistoryOrderBy =
  365. | "markerTime"
  366. | "inspectTime"
  367. | "markerScore"
  368. | "seceretNumber"
  369. | undefined;
  370. export type MarkHistorySortField = "ASC" | "DESC" | undefined;
  371. export interface HistoryQueryParams {
  372. /** 从1开始 */
  373. pageNumber?: number;
  374. pageSize?: number;
  375. order?: MarkHistoryOrderBy;
  376. sort?: MarkHistorySortField;
  377. secretNumber?: string | null;
  378. subjectCode?: string;
  379. groupNumber?: string;
  380. markerId?: string;
  381. markerScore?: string;
  382. }
  383. export interface GetHistory {
  384. (historyQuery: HistoryQueryParams): Promise<
  385. AxiosResponse<Task[]> | undefined
  386. >;
  387. }
  388. export interface CommonResponse {
  389. /** 请求是否成功 */
  390. success: boolean;
  391. /** 错误消息 */
  392. message: string;
  393. }
  394. /** 仲裁用:评卷明细 */
  395. export interface MarkDetail {
  396. markerName: string;
  397. markerTime: number;
  398. totalScore: number;
  399. scoreList: string;
  400. }
  401. //#region 多媒体评卷
  402. export interface RichTextQuestion {
  403. /** 题目的综合题号 1-2-4 */
  404. unionOrder: string;
  405. body: RichTextJSON;
  406. parentBody: RichTextJSON | null;
  407. answer: Array<RichTextJSON> | null;
  408. objective: boolean | null;
  409. options: Array<{ number: number; body: RichTextJSON }> | null;
  410. hideAnswer?: boolean;
  411. }
  412. export interface QuestionForRender extends Omit<RichTextQuestion, "answer"> {
  413. studentAnswer: RichTextQuestion["answer"];
  414. standardAnswer: RichTextQuestion["answer"];
  415. score: number | null;
  416. totalScore: number;
  417. }
  418. export interface RichTextJSON {
  419. sections: RichTextSectionJSON[];
  420. }
  421. export interface RichTextSectionJSON {
  422. blocks: RichTextBlockJSON[];
  423. }
  424. export interface RichTextBlockJSON {
  425. type: "text" | "image" | "audio" | "cloze";
  426. value: string;
  427. param: {
  428. underline: boolean;
  429. bold: boolean;
  430. italic: boolean;
  431. width: string;
  432. height: string;
  433. } | null;
  434. }
  435. export interface StudentAnswer {
  436. mainNumber: number;
  437. subNumber: string;
  438. subIndex: string;
  439. answer: Array<RichTextJSON> | null;
  440. }
  441. /** 云平台试卷格式 */
  442. export type ECSPaperJSON = {
  443. mainNumber: number;
  444. subNumber: string;
  445. body: RichTextJSON;
  446. parentBody: RichTextJSON | null;
  447. answer: RichTextJSON;
  448. }[];
  449. /** 在线考试平台试卷格式 */
  450. export type OExamPaperJSON = OExamPaperJSONQuestionList[];
  451. interface OExamPaperJSONQuestionList {
  452. /** 大题号 */
  453. number: number;
  454. questions: OExamPaperJSONQuestion[];
  455. }
  456. interface OExamPaperJSONQuestion {
  457. number: number;
  458. body: RichTextJSON;
  459. answer: RichTextJSON[] | null;
  460. objective: boolean | null;
  461. options: Array<{ number: number; body: RichTextJSON }>;
  462. subQuestions: OExamPaperJSONQuestion[] | null;
  463. /** 1-单选,2-多选,3-判断,4-填空,5-问答,6-套题,7-听力,8-配对题 */
  464. structType: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
  465. }
  466. //#endregion