# 145教材系统技术文档 ## 一、技术语言和框架 #### 数据库和数据表 - 数据库:[PostgreSQL](https://www.postgresql.org/ "PostgreSQL") - 数据表 - _User【用户】 ```js "fields": { "avatar": { "type": "String" }, "name": { "type": "String" }, "mobile": { "type": "String" }, // Authing 提供信息 "phone": { "type": "String" }, "lastIP":{ "type":"String" }, "lastLogin": { "type": "Date" }, "userSourceType":{ "type": "String" }, "loginsCount":{ "type": "Number" } } ``` - Profile 【用户角色】 ```js "fields": { "user": { "type": "Pointer", "targetClass": "_User", "required": false }, "phone": { "type": "String" }, "email": { "type": "String" }, "telephone": { "type": "String" }, "province": { "type": "String" }, "companyType": { "type": "String" }, "postName": { "type": "String" }, "idcard": { "type": "String" }, "identity": { "type": "String" }, "identityFile": { "type": "String" }, "majorSubject": { "type": "String" } }, ``` - Department 【单位部门】 ```js "fields": { "parent": {//上级 "type": "Pointer", "targetClass": "Department", "required": false }, "name": {//单位、组织名称 "type": "String", "required": false }, "code": {//标识码 "type": "String", "required": false }, "branch": {//主管部门 "type": "String", "required": false }, "address": {//所在地 "type": "String", "required": false }, "type": { // 单位类型 "type": "String", "required": false }, "hasChildren": {//办学层次 "type": "Boolean", "required": false }, }, ``` - EduTextbook 【教材】 ```js "fields": { "status": { /*状态 101:待完善资料 102:可提交状态 103:已提交至高校管理员 200:已提交遴选中 201:公示中 300:退回 400:已报送 */ "type": "String", "required": false }, "childrens":{//指向所有分册 "type": "String", "required": false }, "user": { "type": "Pointer", "targetClass":"_User", "required": false }, "department": { //所属流程 "type": "Pointer", "targetClass":"Department", "required": false }, "render": { //是否提交 "type": "Boolean", "required": false }, "recommend": { //是否推荐 "type": "Boolean", "required": false }, "complete": { //是否填写完整 "type": "Boolean", "required": false }, "isDeleted": { "type": "Boolean", "required": false }, "discard": { //删除至回收站 "type": "Boolean", "required": false }, "title": { "type": "String", "required": false }, "ISBN": { "type": "String", "required": false }, "author": { "type": "String", "required": false }, "unit": { "type": "String", "required": false }, "type": { "type": "String", "required": false }, "typeNumber": {//全册次数 "type": "Number", "required": false }, "majorPoniter": { "type": "String", "required": false }, "lang": { "type": "String", "required": false }, "authors": { "type": "String", "required": false }, "editor": { "type": "String", "required": false }, "approval": {//是否为重点立项教材 "type": "String", "required": false }, "edition": { "type": "String", "required": false }, "editionFirst": { "type": "Date", "required": false }, "carrierShape": { "type": "String", "required": false }, "editionDate": { "type": "Date", "required": false }, "editionNumber": {//出版版次 "type": "Number", "required": false }, "printDate": { "type": "Date", "required": false }, "printNumber": { "type": "Number", "required": false }, "printSum": { "type": "Number", "required": false }, "importantProject": {//重点项目 "type": "Array", "required": false }, "importantProjectOther": {//重点项目-其他 "type": "String", "required": false }, "copyright": { "type": "Array", "required": false }, "CIP": { "type": "Array", "required": false }, 'majors':{//适用专业代码(六位)及名称 "type":'Number', "required": false }, "period": { "type": "Number", "required": false }, "lessons": { "type": "Array", "required": false }, "characteristic": { "type": "Array", "required": false }, "authorList": { "type": "Array", "required": false }, "authorDetails": { "type": "String", "required": false }, "achievementOptions": { "type": "Array", "required": false }, "courses": { "type": "Array", "required": false }, "innovateExplain": { "type": "String", "required": false }, "influence": { "type": "String", "required": false }, "textbookFiles": { "type": "Array", "required": false }, "links": { "type": "Array", "required": false }, "opinions": { "type": "Array", "required": false }, "selfResults": { "type": "Object", "required": false }, "expertOpinion": { "type": "Object", "required": false }, "evidence": { "type": "Object", "required": false }, "moreMaterial": { "type": "Array", "required": false }, "authorSign": { "type": "Array", "required": false }, "unitMaterial": { "type": "Object", "required": false }, "accept": {//填写承诺书 "type": "String", "required": false }, "approvedImgUrl":{//重点立项教材获批截图 "type":'String', "required": false }, "eduProcess": {//所属流程 "type": "Pointer", "targetClass":"EduProcess", "required": false }, "code":{//编号 "type":'String', "required": false }, 'editionUnit':{ "type":'String', "required": false }, 'copyrightImgUrl':{ "type":'String', "required": false }, 'CIPImgurl':{ "type":'String', "required": false }, 'examine':{//作者政治审核表 "type":'Array', "required": false }, 'cipProveFile':{//cip相关截图 "type":'Array', "required": false }, 'inviteUnit':{//推荐单位 "type":'Array', "required": false }, 'unitType':{//推荐单位类型 "type":'Array', "required": false }, 'score':{//平均分 "type":'Number', "required": false }, }, ``` - EduTextbookVolume 【分册】 ```js "fields": { "user": { "type": "Pointer", "targetClass":"_User", "required": false }, "isDeleted": { "type": "Boolean", "required": false }, "title": { "type": "String", "required": false }, "ISBN": { "type": "String", "required": false }, "author": { "type": "String", "required": false }, "unit": { "type": "String", "required": false }, "lang": { "type": "String", "required": false }, "authors": { "type": "String", "required": false }, "editor": { "type": "String", "required": false }, "editionFirst": { "type": "Date", "required": false }, "carrierShape": { "type": "String", "required": false }, "editionDate": { "type": "Date", "required": false }, "editionNumber": {//出版版次 "type": "Number", "required": false }, "printDate": { "type": "Date", "required": false }, "printNumber": { "type": "Number", "required": false }, "printSum": { "type": "Number", "required": false }, "importantProject": {//重点项目 "type": "Array", "required": false }, "importantProjectOther": {//重点项目-其他 "type": "String", "required": false }, "authorList": { "type": "Array", "required": false }, "authorDetails": { "type": "String", "required": false }, "achievementOptions": { "type": "Array", "required": false }, "courses": { "type": "Array", "required": false }, 'editionUnit':{ "type":'String', "required": false }, 'unitType':{//推荐单位类型 "type":'Array', "required": false }, "collectFIles": {//纸质教材文件 "type": "Object", "required": false }, "collectDigitFiles":{//纸质数字文件 "type": "Object", "required": false }, "collectCheck":{//教材文件上传类型 "type": "Object", "required": false }, "collectStatus":{//教材文件上传状态 "type": "Object", "required": false }, }, ``` - Activity 【评审活动】 ```js "fields": { "name":{//活动名称 "type": "String", "required": false }, "eduProcess": { //评审教材 "type": "Pointer", "targetClass": "EduProcess", "required": false }, "startDate": {//开始时间 "type": "Date", "required": false }, "deadline": {//截止时间 "type": "Date", "required": false }, "status":{//是否开始 "type": "Number", "required": false }, "desc":{//详情说明 "type": "String", "required": false }, }, ``` - Company 【公司】 ```js "fields": { "title": { "type": "String" }, }, ``` - EduProcess 【流程】 ```js "fields": { "eduCollection": { //指向报送合集 "type": "Pointer", "targetClass": "EduCollection", "required": false }, "branch": { //类别 "type": "Pointer", "targetClass": "Department", "required": false }, "department": { //部门/单位 "type": "Pointer", "targetClass": "Department", "required": false }, "profileSubmitted": {//流程管理员 "type": "Pointer", "targetClass":"Profile", "required": false }, "name": {//流程名称 "type": "String", "required": false }, "num": {//报送名额 "type": "Number", "required": false }, "code": {//流程唯一标识 "type": "String", "required": false }, "startDate": {//开始时间 "type": "Date", "required": false }, "deadline": {//截止时间 "type": "Date", "required": false }, /**@状态 * 100:暂停 * 200:已开始 * 201:评审中 * 300:已公示 * 400:已提交(完成) */ "status": { "type": "String", "required": false }, "releaseDate": {//公示时间 "type": "Date", "required": false }, "collectStartData": {//收集文件开始时间 "type": "Date", "required": false }, "collectEndData": {//收集文件结束时间 "type": "Date", "required": false }, }, ``` - EduReview 【评审记录】 ```js "fields": { "eduTextbook": { //评审教材 "type": "Pointer", "targetClass": "EduTextbook", "required": false }, "user": { "type": "Pointer", "targetClass": "_User", "required": false }, "profile": { //评审用户 "type": "Pointer", "targetClass": "Profile", "required": false }, "score": {//最终分数 "type": "Number" }, "num":{//预估分 "type": "Number" }, "verify":{//是否完成 "type": "Boolean" } }, ``` - ExpertGroup 【评审组】 ```js "fields": { "name":{//活动名称 "type": "String", "required": false }, "eduProcess": { //评审流程 "type": "Pointer", "targetClass": "EduProcess", "required": false }, "textbookList": {//评审教材列表 "type": "Array", "required": false }, "reviewList": {//评审教师列表 "type": "Array", "required": false }, "checkTextbook": {//选择教材类型 "type": "String", "required": false }, "checkReview": {//选择评审专家类型 "type": "String", "required": false }, }, ``` ### 后端语言及框架 - 编写语言:JavaScript - 技术框架:[Node.js](https://bcn4fkmpxbdo.feishu.cn/wiki/N10SwNRbmi2lfCktmAacehxInzf#share-W6CqdCNP7oyKTMxFjKTcxSIgnYd "Node.js")、[Parse Server](https://parseplatform.org/parse-server/api/7.3.0/ "Parse") ### 前端语言及框架 - 编写语言:TypeScript、HTML、SCSS - 技术框架:Angular18、Vite、NG-ZORRO ## 二、客户端前端 ### 用户操作逻辑介绍 graph TB Start(开始) --> User[用户登录页] User --> Register[注册] User --> Login[用户登录] Register --> Regcomplete[注册成功] Regcomplete --> User Login --> Manage[登录成功进入后台] Manage --> LogOut[退出登录] LogOut --> End(结束) ### 身份权限 - 登录成功时存储本地缓存profile; - 通过profile.identity身份判断角色验证 - 全局采用路由守卫 [auth.guard.ts](projects\textbook\src\services\auth.guard.ts "Parse") ### 页面路由 - 入口路由文件:projects\textbook\src\app\app.routes.ts - 各个身份子路由 - user/login //默认路由 - nav-admin //国家级管理员管理平台 - nav-province-contact //工作联系人:中央部门所属高校联系人、部省合建高校联系人、出版单位联系人、省属高校流程管理员 - nav-province-school-contact //高校联系人 - nav-review //教材评审组成员 - nav-author //作者 / 教师 / 主编 ### 主组件 - app-comp-manage【全局组件】:登录成功后跳转后页面显示;包括左侧menu,通过optionsMap身份对应显示身份功能栏 - 附件下载功能函数:openFile、downloadFile - app-comp-nav 【个人信息组件】:页面左下角个人信息,包括退出登录功能 - app-comp-upload 【文件上传组件】 - provider-oss-aliyun 引入阿里OSS处理函数等,含公开转私有、私有转公开、临时链接等 - 重点传入参数 - @files:回显文件 - @acl 上传类型,是否加密 - @type 可上传文件类型 ```js //映射关系处理 get accept() { let type; switch (this.type) { case 'image': type = 'image/*'; break; case 'pdf': type = 'application/pdf'; break; case 'audio': type = 'audio/*'; break; case 'video': type = 'video/*'; break; default: type = 'file'; break; } return type; } ``` - 上传成功、失败、删除文件触发回调 - 函数`change`,返回fileList - app-textbook 【教材列表组件】 - 重点传入参数 - @filterObj 相关权限配置 - @uid 对应用户 - @eduProcess 流程id,verify存在时需要 - @discard 是否删除 - @recommend 是否推荐 - 重要函数解释 - `getTextbook`:获取教材列表重要函数,利用Parse.Query.fromJSON多条件查询,通过设定参数传入接口查询获取教材,满足全平台90%以上页面教材列表管理 - `getDepartment`:获取所有单位部门 - `reject`: 退回教材 - `del`:删除教材 - `updateStatus`:加入/移除推荐 - `submit`:提交教材 - `beforSubmit`:高校联系人提交教材至工作联系人 - `restore`:恢复教材 - `exportProcess`:导出教材;功能业务:导出推荐汇总表 - `submitted`:提交报送跳转,非直接请求报送教材接口 ### 各身份模块 ##### 用户登录 - parse-authing.ts 【登录服务类】 应用authing登录回调,返回获取登录结果 - initLoginModal 初始化登录模块 - app-login 登录页 - new ParseAuthing实例化authing登录服务,通过login成功后回调调用AuthServr服务类,profileVerify处理登录成功后函数 ```js let parseAuthing = new ParseAuthing({ // 监听事件:登陆成功后,返回用户信息 login:(user,authClient)=>{ console.log(user) console.log(Parse.User.current()); Parse.User.current()?.id && this.authServr.profileVerify(this.modal) }, beforeChangeModule:(data:any)=>{ if(data=='register'){ this.router.navigate(['/user/account_info']) } } }); parseAuthing.initLoginModal(); ``` - app-account-info 工作联系人注册 - 功能说明 - 访客用户可在登录页点击“账户申请”进入工作联系人账户申请,国家级管理员可查看资料根据情况是否通过,通过条件会自动校验是否存在,如果流程存在该管理员会自动替换 - 主要函数方法 - `validateForm`:基础填写字段 - `identity`:注册身份 - `identityFile`:单位联系人认证文件 - 主要参数说明 - `getUnitTypes`:获取可选择注册单位 - `provinceChange`:根据所选单位类型获取对应单位 - `submitForm`:提交注册信息 - `profileSave`:提交角色信息 - `authUser`:注册基础字段信息校验,判断手机号、邮箱是否合规 ##### 作者/教师/主编 - 路由模块:`NavAuthorRoutingModule` - 组件(教材创建) - app-basic 【填写基本信息】 - 必填参数 - @eduTextbook 教材 - 主要函数方法 - `getEduTextbookVolumeList`:获取分册表 - `upload`:上传附件回调 - `saveEduTextbook`:保存教材信息 - 保存接口中判断是否填写完成 - 判断各分册填写及获取分册id代码 - 部分主要代码 ```js let eduTextbookVolumes = await this.saveEduTextbookVolume(this.eduTextbookId); console.log(eduTextbookVolumes?.isVrifly); console.log(eduTextbookVolumes.list); this.eduTextbook?.set('childrens', eduTextbookVolumes.list); this.eduTextbook?.set('typeNumber', eduTextbookVolumes.list.length); isComplete = isComplete && eduTextbookVolumes?.isVrifly; //如果填写未完整,仅保存,状态修改待完善101 if (this.eduTextbook.get('status') == '102' && !isComplete) { this.eduTextbook?.set('status', '101'); this.eduTextbook.set('complete', false); } else if (!this.eduTextbook.get('status')) { this.eduTextbook?.set('status', '101'); } if(isComplete){ this.eduTextbook.set('complete', true) } - `saveEduTextbookVolume`:上传分册数据 - 子组件调用 - 上传获批截图 ```html - 分册信息 ```html - app-textbook-pertain【填写教材适用情况】 - 必填参数 - @eduTextbook 教材 - 主要函数方法 - `saveEduTextbook`:保存教材信息 - `saveEduTextbookVolume`:上传分册数据 - 子组件调用 - 分册信息 ```html - app-textbook-content【填写教材内容】 - 必填参数 - @eduTextbook 教材 - 主要函数方法 - `saveEduTextbook`:保存教材信息 - `saveEduTextbookVolume`:上传分册数据 - 子组件调用 - 分册信息 ```html ``` - app-faith【填写教材内容】 - 必填参数 - @eduTextbook 教材 - 主要函数方法 - `saveEduTextbook`:保存教材信息 - `saveEduTextbookVolume`:上传分册数据 - `verify`:校验填写字段是否匹配 - app-attachment【上传附件材料】 - 必填参数 - @eduTextbook 教材 - 主要函数方法 - `saveEduTextbook`:保存教材信息 - `saveEduTextbookVolume`:上传分册数据 - `examineNull`:检查本页必填是否存在空项 - `isIgnoreFiledNull`:判断教材所有字段是否必填 - `upload`:上传附件回调 - 子组件调用 - app-comp-upload 附件上传组件 - 分册信息 ```html ``` - ###### 个人空间:app-space - 调用组件:app-textbook - 主要函数:`getEduProcess` 获取教师所属单位的流程 - 创建教材:app-apply - 组件调用 - app-basic - app-textbook-pertain - app-textbook-content - app-faith - app-attachment - 应用代码 ```html @switch (state) { @case (0) { } @case (1) { } @case (2) { }@case (3) { } @case (4) { } } ``` - ###### 回收站:app-recycle - 调用组件:app-textbook ```html ``` ##### 国家级管理员管理平台 - 路由模块:`NavAdminRoutingModule` - 组件 - app-collect-textbook 【教材文件收集列表】 - 必填参数 - @eduProcess 流程id - 主要函数方法 - `getTextbook`:获取教材 - `onEmitMsg`:短信提醒,提交状态置为100 - `onReject`:退回教材给出版社 - app-profile 【工作联系人】 - 必填参数 - depart:单位,用于查询本单位下注册联系人身份用户列表 - 主要函数方法 - `getProfile`:获取用户角色列表 - 全部教材:app-page-textbook - 功能说明 - 批量查看已提交至国家级管理员教材、教材文件上传管理 - 调用组件 - app-textbook - app-collect-textbook - 申报流程:app-process-list - 功能说明 - 进入页面通过`getDepart`方法获取所有一级节点部门 - 点击左侧流程调用`getDepart`获取对应一级节点下全部流程,右侧显示流程table - table操作栏可对流程进行操作,可操作按钮通过statusMap状态判断 - 可通过`toUrl('/nav-admin/manage/process/create')`跳转创建流程页 - 主要参数说明 - `activeDepart`:当前编辑部门 - `eduProcessList`:流程列表 - `formatStatus`:格式化流程状态 - `formatFileStatus`:教材上传状态 - 主要函数方法 - `getDepart`:获取部门单位节点 - `getEduProcess`:获取部门列表 - `formatNode`:格式化链 - `statusSelected`:操作流程,开始、暂停、结束、删除 - `onStatusChange`:暂停流程 - `openEditCollect`:保存收集文件设置 - `sendNoticeMSG`:短信通知 - 流程详情:app-page-process - 功能说明 - 默认进入报送流程tab栏,可修改流程名称、限额、工作联系人等相关配置信息 - 教材列表可查看已提交到国家级管理员的所有教材 - 教材文件功能查看上传教材的状态 - 调用组件 - app-process-create:流程管理 - app-textbook - app-collect-textbook - ###### 用户列表:app-page-user - 功能说明 - 本页权限通过`tbookSer.profile.identity`判断给与相应权限,包含国家级管理员、高校联系人管理权限区分;国家级管理员可管理平台所有身份用户,工作联系人可管理所属部门节点及下级节点的部门用户,不包含“工作联系人”身份的用户 - 统一管理平台所有用户,可创建、删除、修改用户 - 创建用户:点击`addMember`弹出创建用户弹窗,填写用户基本信息后点击确定完成请求创建用户,人员类型校验必须选择部门后才能选择 - 在操作通过认证时,如果该工作联系人对应流程未被绑定,则会自动校验绑定至该单位的流程作为流程管理员(注:每一个流程只能对应一个流程管理员),诺已绑定,则会取消本次绑定事件,但会继续通过身份认证。部分代码逻辑 ```js //更新工作联系人textbook.ts async updateProfileSubmitted( pid: string, type: string, dpid?: string, msg?: NzMessageService ): Promise { console.log(pid, type, dpid); let query = new Parse.Query('EduProcess'); if (!dpid) { query.equalTo('profileSubmitted', pid); } else { query.equalTo('department', dpid); } query.include('profileSubmitted'); query.select('objectId', 'profileSubmitted'); query.notEqualTo('isDeleted', true); let res = await query.first(); if (!res?.id) { msg?.warning('所属单位不存在'); return false; } if (type == 'del') { //删除工作联系人 res.set('profileSubmitted', null); await res.save(); return true; } else { //添加工作联系人 if (res?.get('profileSubmitted')?.get('user')) { msg?.warning('该单位已有部门联系人,请先移除后再操作'); return false; } res?.set('profileSubmitted', { __type: 'Pointer', className: 'Profile', objectId: pid, }); await res.save(); return true; } return false; } ``` - 主要参数说明 - `profiles`:用户列表 - `parentList`:部门选择 - `filters`:筛选条件,用于列表搜索或列表条件查询等 - 主要函数方法 - `getProfile`:获取用户列表 - `updateUrlPageIndex`:更新页面,路由返回功能回显作用 - `updateUser`:更新用户信息,通过认证或删除操作 - `addMember`:添加用户初始化,初始化后通过`accountIsVisible`设置弹窗弹出用户信息弹出,对其设置 - `getDepart`:获取部门信息 - `onCheckedDepart`:选择所属类别下级列表 - `accountComplete`:添加账号,需通过`authVrifly`表单信息校验 - `authVrifly`:用户信息表单校验,含邮箱格式正则、手机号正则等 - 用户管理&编辑:app-user-edit - 功能说明 - 路由须携带用户ID - 编辑、查看用户信息,含扩展字段,省份、职务等 - 修改密码:判断是否具有修改权限,如果有可直接在弹出中修改,修改后会直接通过邮箱或短信通知 - 用户教材:可查看该用户所创建的所有教材,含未提交的,组件传入参数 ```js submitTextBook = { status:['102','103','200','201','300','400'], btns:{ review:true,//查阅 } } ``` - 调用组件 - app-textbook ```html ``` - 主要参数说明 - `user`:用户信息 - `profileJson`:身份编辑数据 - `userJson`:user编辑数据,用于编辑未保存提示 - `edit`:是否可编辑权限 - `profile`:用户角色信息 - 主要函数方法 - `updateUser`:操作用户删除、变更用户状态 - `handleOk`:变更密码 - `showModalDepart`:选择部门 - `getDepart`:根据所选单位类型获取对应单位 - `onCheckedDepart`:选择部门 - `completeChange`:选择部门 - `submitForm`:修改账户所属部门单位 - `updateUserJson`:更新用户数据 - `moduleChange`:判断编辑数据变化 - `updateCanDeActivate`:保存提示 - ###### 申报单位管理:app-page-role - 功能说明 - 通过权限判断获取单位部门`getDepart`,存储nodes节点,部分代码 ```js nodes.push({ title: item.get('name'), key: item.id, children: [], branch: item.get('branch'), parent: item.get('parent')?.id, //上级 isLeaf: !item.get('hasChildren'), //是否是最下级 type: item.get('type'), }); ``` - 点击部门获取用户列表,在左侧用户显示,可对其管理 - 添加成员:`addMember`添加选中部门的用户角色,工作联系人管理状态下默认同节点 - 添加部门:国家级管理员可添加任意节点部门、工作联系人可添加当前单位下的部门 - 使用`nz-tree`组件,通过`contextmenu`函数调用鼠标左击直接操作选中单位可编辑的权限 - 主要参数说明 - `nodes`:部门节点 - `profileLength`:用户列表 - `activatedNode`:当前选中节点 - `activeDepart`:当前编辑部门 - `editObject`:编辑部门字段,单项赋值绑定 - 主要函数方法 - `getDepart`:获取部门单位 - `getProfile`:获取用户列表 - `contextMenu`:鼠标右击事件 - `onDelDepart`:删除部门 - `showModalDepart`:初始化用户 - `handleOk`:保存编辑&新增部门 - `showProfile`:变更用户部门 - `accountComplete`:添加账号 - `updateProfile`:保存更新部门 ##### 工作联系人:中央部门所属高校联系人、部省合建高校联系人、出版单位联系人、省属高校流程管理员 - 路由模块:`NavProContactRoutingModule` - 组件 - app-review-details 【评审教材列表】 - 必填参数 - @eduProcess 流程id - @filterObj 评审组条件 - 主要函数方法 - `getTextbook`:获取教材 - `export`:导出表格 - app-upload-collect 【教材上传列表】 - 必填参数 - @eduTextbookVolume 分册信息 - 主要函数方法 - `upload`:上传回调参数处理 - `submitForm`:提交教材文件 - 全部教材:app-page-textbook - 功能说明 - 批量查看已提交至国家级管理员教材、教材文件上传管理 - 通过`textbook?.export()`调用`app-textbook`组件直接下载汇总表 ```html ``` - 调用组件 - app-textbook - 主要参数说明 - `beforeFilterObj`:待审核参数 ```js beforeFilterObj: any = { showMore: true, //显示更多字段 isCheck: true, noStared: true, status: ['200'], btns: { export: true, }, }; ``` - `afterFilterObj`:已加入推荐 ```js afterFilterObj: any = { showMore: true, //显示更多字段 isCheck: true, status: ['200', '201', '400'], btns: { // remove: true, //移除推荐 export: true, }, }; ``` - 主要函数方法 - `getProcess`:获取流程 - `submitted`:报送 - 申报流程:app-process-list - 功能说明 - 查看本单位申报流程的流程,可点击教材名称进入详情查看 - 主要参数说明 - formatStatus:格式化流程状态,收集状态 - 主要函数方法 - getEduProcess:获取流程 - 流程详情:app-page-process - 功能说明 - 流程管理可以查看报送限额、开始及结束时间 - 评审活动显示评审活动时间 - 显示所有的已提交的教材列表; - 调用组件 - app-process-create - app-textbook ```html
待评审教材列表

推荐教材列表
``` ```js //待审核 beforeFilterObj: any = { showMore: true, //显示更多字段 isCheck: true, noStared: true, status: ['200'], btns: { export: true, }, }; //已加入推荐 afterFilterObj: any = { showMore: true, //显示更多字段 isCheck: true, status: ['200', '201', '400'], btns: { export: true, }, }; ``` - 主要参数说明 - `beforeFilterObj`:待审核 - `afterFilterObj`:已加入推荐 - `activity`:评审活动 - 主要函数方法 - `getActivity`:获取评审活动 - `getExpertGroup`:获取评审组 - `startActivity`:开始活动 - `onCompute`:计算平均分 - `getEduReview`:获取评审详情列表 - 创建&编辑评委活动:app-activity - 功能说明 - 编辑评审活动,name、startDate、deadline;评审端评选打分教材以此时间为准,评审端通过条件判断是否在评审时间段内为评审条件之一 - 评审规则:平均数mean、截尾平均数truncatedMean用于计算时评审计平均分分 - 评审组:设置教材可评审的评审人员,教材与评审组关系:n:1 - 调用组件 - app-comp-upload ```html //上传教材评审文件,在评审端评审时可在弹出的打分中看到该文件 ``` - app-review-details ```html ``` - 主要参数说明 - `filterObj`:评审明细子组件介绍参数条件;showGroup:显示评审组名称,contained:指定评审组查询,bookMap:教材对应评审组结构{booid:评审组名称} - 主要函数方法 - `getActivity`:获取评审活动 - `getExpertGroup`:评审组 - `deleteGroup`:删除评审组 - 创建&编辑评委组:app-review-edit - 功能说明 - 默认评审教材为全部,可以onchangeTextbook切换手动选中教材,选中手动选中教材后,显示教材列表app-textbook组件,可勾选后确定,在app-textbook组件的回调中获取勾选的教材赋值变量在保存请求 - 默认评审专家为全部,可手动onchangeReview切换手动选择专家,选择的专家会在右侧 - 所有设置均有回显类名class="dep-right"元素显示,也会在当前类class="dep-comp"显示选中样式 - 教材评审明细显示已打分的各个评审专家分数 - 调用组件 - app-review-details ```html ``` - app-textbook ``` html //setOfCheckedTextbookAll传入已选择的id //updateCheck是组件选中后确认的回调方法,通过@ViewChild获取组件元素服务,直接调用组件方法赋值给页面 ``` - 主要参数说明 - `eduProcess`:申报流程 - `expertGroup`:评审组对象 - `checkProfileListLeng`:已选择评审专家人数 - `reviewFilterObj`:传入评审组件显示列表参数 - 主要函数方法 - `refresh`:初始化评审组,回显、赋值可编辑信息 - `getTextName`:获取展示已选择教材 - `getExpertGroup`:获取所有已被其他评审组选择过教材 - `getProfile`:获取评委专家 - `updateAllChecked`:选中专家改变事件 - `onSave`:保存评审设置,评审教材、评审专家 - 本社教材源文件:app-collect-file - 功能说明 - 本路由权限只有出版社部门节点下的联系人有权限进入,在app-comp-manage初始化组件中做逻辑menu权限判断 - comp-manage.component.ts相关代码 ```js if (this.tbookSer.profile.identity == '工作联系人' && this.tbookSer.profile.user?.department?.branch == '出版单位') { this.optionsMap['工作联系人'][0].child.push({ name: '本社教材源文件', path: '/nav-province-contact/manage/collect', id: '1-3', }); } ``` - 根据教材分册所选出版社,editionUnit字段是否等于当前出版社单位筛选条件;查询对应教材是否在上传期间条件:EduTextbook.eduProcess.status流程状态需要是已提交至国家级管理员 - 因为单本教材可能涉及到多个分册,每个分册可能不同出版单位,我们在教材获取下来后在分册中做了本次教材校验,且在上传中只能对应选中本出版单位本册可操作、查看,以下部分代码,通过判断渲染可编辑权限教材 ```html @for (panel of currentTextbook?.get('childrens'); track panel) { @if (panel?.get('editionUnit') == tbookSer.profile.user?.department?.name) { {{ "分册" + ($index + 1) + "-" + currentTextbook?.get("title") }}
{{ active }}
} } ``` - 管理员可点击列表编辑打开弹出后,进行教材上传 - 调用组件 - app-upload-collect - 主要参数说明 - `textbookList`:教材列表 - `statusMap`:任务状态,映射关系:{教材id:{状态,状态色、可操作按钮}} - 主要函数方法 - `fromatFiled`:格式化拓展表字段 - `getTextbook`:获取教材 - `getEduProcess`:获取流程 - `onEditModal`:上传教材打开上传弹窗 - `saveCollect`:保存上传教材 - `saveEduTextbookVolume`:保存事件推送上传教材 - 用户列表:app-page-user 功能同国家级管理员[用户列表](#用户列表app-page-user) - 申报单位管理: app-page-role 功能同国家级管理员[申报单位管理](#申报单位管理app-page-roler) ##### 高校联系人 - 路由模块:`NavProSchoolRoutingModule` - 全部教材:app-page-textbook - 功能说明 - 高校联系人只有省级教育行政部门、有关部门(单位)教育司(局)单位下级省局单位下高校有登录权限,当教师属于该单位下时,默认提交到高校联系人,由高校联系人审核后提交至工作联系人 - 在本页高校联系人可查看对应高校及以下单位的所有教师教材,含未提交 - 待提交教材可点击提交至工作联系人,代评审教材为未被专家评审或未提交报送的教材 - 调用组件 - app-textbook - 主要参数说明 - `draftFilterObj`:获取草稿传参子组件调教 - `beforeFilterObj`:获取待提交教材子组件调教 - `afterFilterObj`:获取待评审教材子组件调教 - 主要函数方法 - `getProcess`:获取流程 - 用户列表:app-page-user 功能同国家级管理员[用户列表](#用户列表app-page-user) - 申报单位管理: app-page-role 功能同国家级管理员[申报单位管理](#申报单位管理app-page-roler) - 个人空间:app-space 功能同教师[个人空间](#个人空间app-space) - 回收站:app-recycle 功能同教师[回收站](#回收站app-recycle) ##### 教材评审专家 - 路由模块:`NavReviewRoutingModule` - 教材打分:app-approve - 功能说明 - 根据评审组件获取该评审专家对应可打分评审的教材,首先需先确定该流程下的评审活动已开启,是否在评审期间以活动时间为准,以下为权限及获取打分教材部分代码 ```js //判断是否在获取期间 get isStart(): boolean { return ( !this.activity?.get('startDate') || this.activity?.get('startDate') > new Date() ); } ``` ```html ``` ```js //待评分 beforeFilterObj: any = { showMore: true, //显示更多字段 isCheck: true, status: ['200'], contained: [], btns: { eduReivew: true, mark: true, }, }; //已评审 afterFilterObj: any = { showMore: true, //显示更多字段 isCheck: false, status: ['200','201','300','400'], contained: [], btns: { eduReivew: true, }, }; ``` - 点击打分可在可允许打分条件下弹窗,若已过或未开始评审时间,则打分弹窗会被阻止;评审专家可在打分弹窗中打分,可先保存`saveScore('save')`或提交`saveScore('submit')` - 调用组件 - app-textbook - 主要参数说明 - `eduProcess`:流程 - `editTextbook`:评分教材 - `eduReview`:评审记录 - `scoreMap`:教材评审状态 - 主要函数方法 - `authCompute`:校验是否在评审期间 - `isStart`:校验评审是否开始 - `isEnd`:校验评审是否结束 - `getEduReview`:获取评审记录 - `getExpertGroup`:获取评审组相关教材,评审专家可对应对各评审组,需把所有评审组中教材获取后传递给渲染组件获取可评审教材 ```js //部分代码逻辑 r.forEach((item) => { item.get('textbookList')?.forEach((obj: any) => { this.beforeFilterObj.contained.push(obj.id || obj.objectId); }); }); ``` - `getActivity`:获取评审活动 - `onMarkScore`:打开评审弹窗 - `saveScore`:提交打分 ##### 其他公共模块 - 教材详情:app-textbook-details - 功能说明 - 展示教材所有基础信息,含附件 - 联系人或国家级管理员身份可查看评审分数 - 主要参数说明 - `textBook`:教材对象 - 主要函数方法 - `getExpertGroup`:获取评审组 - `getEduReview`:获取本教程评分 - 补充上传教材作者诚信承诺:app-upload-pdf - 功能说明 - 创建时未上传作者签名文件等,可链接本页面填写添加补全 - 主要参数说明 - `authorSignPDF`:上传签名页 - `unitMaterial`:申报单位承诺意见 - 主要函数方法 - `saveEduTextbook`:获取教材签名文件是否上传 - `upload`:上传文件回调 ### 项目公共服务类services - auth.guard.ts:路由守卫 - auth.service.ts:用户身份服务 - compute.ts:科学计算 - majors.map.ts:教材所属专业类map(6位) - majors4.map.ts:教材所属专业类map(4位) - shell.ts:定制化导出脚本 - textbook.ts:教材common服务