# 145教材系统技术文档
## 一、技术语言和框架
#### 数据库和数据表
- 数据库:[PostgreSQL](https://www.postgresql.org/ "PostgreSQL")
- 数据表
- _User【用户】
- Profile 【用户角色】
- Department 【单位部门】
- EduTextbook 【教材】
- EduTextbookVolume 【分册】
- Activity 【评审活动】
- Company 【公司】
- EduProcess 【流程】
- EduReview 【评审记录】
- ExpertGroup 【评审组】
### 后端语言及框架
- 编写语言: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 上传类型,是否加密
- 上传成功、失败、删除文件触发回调
- 函数`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处理登录成功后函数
```
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();
```
##### 作者/教师/主编
- 路由模块:`NavAuthorRoutingModule`
- 组件(教材创建)
- app-basic 【填写基本信息】
- 必填参数
- @eduTextbook 教材
- 主要函数方法
- `getEduTextbookVolumeList`:获取分册表
- `upload`:上传附件回调
- `saveEduTextbook`:保存教材信息
- 保存接口中判断是否填写完成
- 判断各分册填写及获取分册id代码
- 部分主要代码
```
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`:上传分册数据
- 子组件调用
- 上传获批截图
```
- 分册信息
```
- app-textbook-pertain【填写教材适用情况】
- 必填参数
- @eduTextbook 教材
- 主要函数方法
- `saveEduTextbook`:保存教材信息
- `saveEduTextbookVolume`:上传分册数据
- 子组件调用
- 分册信息
```
- app-textbook-content【填写教材内容】
- 必填参数
- @eduTextbook 教材
- 主要函数方法
- `saveEduTextbook`:保存教材信息
- `saveEduTextbookVolume`:上传分册数据
- 子组件调用
- 分册信息
```
```
- app-faith【填写教材内容】
- 必填参数
- @eduTextbook 教材
- 主要函数方法
- `saveEduTextbook`:保存教材信息
- `saveEduTextbookVolume`:上传分册数据
- `verify`:校验填写字段是否匹配
- app-attachment【上传附件材料】
- 必填参数
- @eduTextbook 教材
- 主要函数方法
- `saveEduTextbook`:保存教材信息
- `saveEduTextbookVolume`:上传分册数据
- `examineNull`:检查本页必填是否存在空项
- `isIgnoreFiledNull`:判断教材所有字段是否必填
- `upload`:上传附件回调
- 子组件调用
- app-comp-upload 附件上传组件
- 分册信息
```
```
- 个人空间:app-space
- 调用组件:app-textbook
- 主要函数:`getEduProcess` 获取教师所属单位的流程
- 创建教材:app-apply
- 组件调用
- app-basic
- app-textbook-pertain
- app-textbook-content
- app-faith
- app-attachment
- 应用代码
```
@switch (state) { @case (0) {
} @case (1) {
} @case (2) {
}@case (3) {
}
@case (4) {
} }
```
- 回收站:app-recycle
- 调用组件:app-textbook
```
```
##### 国家级管理员管理平台
- 路由模块:`NavAdminRoutingModule`
- 组件
- app-collect-textbook 【教材文件收集列表】
- 必填参数
- @eduProcess 流程id
- 主要函数方法
- `getTextbook`:获取教材
- `onEmitMsg`:短信提醒,提交状态置为100
- `onReject`:退回教材给出版社
- app-profile 【工作联系人】
- 必填参数
- depart:单位,用于查询本单位下注册联系人身份用户列表
- 主要函数方法
- `getProfile`:获取用户角色列表
- 全部教材:app-page-textbook
- 调用组件
- app-textbook
- app-collect-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