# 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服务