20201124-申而论之小程序
本项目初始目录结构使用官方express-generator@4生成:
| 目录 | 说明 |
|---|---|
bin/ |
启动脚本 |
public/ |
静态文件 |
routes/ |
路由 |
views/ |
页面模板 |
额外加入的目录
| 目录 | 说明 |
|---|---|
utils/ |
通用模块 |
db/ |
数据库相关 |
额外加入的文件
| 文件 | 说明 |
|---|---|
api.yaml |
API描述文件(OpenAPI 3.0) |
config.yaml |
默认配置文件 |
const.yaml |
常量配置文件 |
通用配置
| 字段名 | 默认值 | 说明 |
|---|---|---|
SERVER_SECRET |
serversecret |
用于各种加密的密钥 |
STATIC_USERS |
admin:admin |
静态用户配置 |
MySQL配置:
| 字段名 | 默认值 | 说明 |
|---|---|---|
MYSQL_HOST |
localhost |
地址 |
MYSQL_PORT |
3306 |
端口 |
MYSQL_USER |
dev |
用户名 |
MYSQL_PASSWORD |
dev |
密码 |
MYSQL_DATABASE |
proj_shenlun |
数据库名 |
MYSQL_CHARSET |
utf8mb4 |
编码 |
MYSQL_TIMEZONE |
+08:00 |
时区 |
MYSQL_CONNECTION_LIMIT |
100 |
连接池大小 |
MYSQL_LOG_SQL |
false |
是否在日志中输出SQL语句 |
Session/Token配置
| 字段名 | 默认值 | 说明 |
|---|---|---|
COOKIE_SESSION_NAME |
sessionid |
保存Session ID 的Cookie 名 |
COOKIE_SESSION_EXPIRES |
86400 |
Session 过期时间(秒) |
JWT_EXPIRES |
86400 |
JWT 过期时间(秒) |
其他配置
| 字段名 | 默认值 | 说明 |
|---|---|---|
PAGE_SIZE |
20 |
默认分页大小 |
启动后默认访问端口为3000
# 启动服务
npm start
# 启动服务(输出DEBUG信息)
DEBUG=server-node-express:* npm start
Gitee项目地址:shen-lun-m-p/api-service
[2022-08-13]
缩减本文档部分内容
业务实体名+字段名(如:「用户」的英文名为
user,那么,用户ID在用户列表为id,而在其他列表中的关联用户ID则为userId)
is、has开头的字段都是布尔值(如:isDisabled)-表示倒序(如:
sort=name表示以name字段正序排列,sort=-name表示以name字段倒序排列)
isOK简单判断成功与否字段 = 值)_NULL表示按NULL匹配(字段 IS NULL)_NOT_NULL表示按NOT NULL匹配(字段 IS NOT NULL)[2020-12-28新增]
9. 所有列表类接口都会自动生成对应的根据ID筛选的详情接口,两接口本质上是同一个接口。但详情接口查询无数据时,默认会返回404,可指定?no404=true取消404报错
10. 自动生成的详情接口都排在每一组接口的最后,且在标题/描述中写明是一个自动生成的接口
11. 列表接口可以指定返回字段,填写字段名表示仅返回指定的字段(如:?fields=field1,field2,英文逗号分隔,中间无空格);开头增加减号表示剔除指定的字段(如:?fields=-,field1,field2或?fields=-field1,field2)
[2021-02-06新增]
12. 所有接口的请求体、响应体中出现的字段名以JSON结尾(如: extraJSON)的字段,全程认为object类型处理即可。服务器端都会自动做序列化反序列化处理(即入库自动序列化,出库自动反序列化)
POST /api/sign-in接口,复制响应体中,data.jwt字段的内容作为令牌Authorize按钮,将令牌值填入AdminBearerAuth中,点击Authorize即可POST /api/sign-in接口,保存响应体中,data.jwt字段的内容作为令牌POST /api/sign-in接口即可,令牌同时会加入到Cookies中Authorization: Bearer {令牌}即可实现认证POST /api/wx-mini/sign-in?code={调用wx.login()获取的临时登录凭证}获取令牌,后续操作与上述3.相同POST /api/me/profile,将当前用户信息保存至服务端,供后台管理使用[2021-08-24新增]
5. 对于使用第三方登录时(如:小程序登录),如果未绑定手机号,则不会直接返回令牌,而是返回临时Code。并使用此临时Code调用POST /api/mobile/bind绑定手机。绑定成功后返回令牌。
6. 对于使用第三方登录时(如:小程序登录),如果已经绑定手机号,则直接返回令牌。
7. 使用手机号登录,在测试环境中,正确输入验证码或者固定输入000000都可以验证通过,手机登录时,新用户会自动创建
媒体库用于存储业务实体的「附件」,业务实体操作接口本身并不直接提供媒体库的操作功能。
如:为主题贴thread附带图片的处理流程如下:
id="thrd-001")POST /api/media接口上传图片,并指定bizId值为主题贴ID(即bizId="thrd-001")至此,在后续查询主题贴列表/详情时,会自动附带media字段(类型为数组,无数据时为空数组),包含字段如下:
"media": [
{
"seq" : <媒体序号>,
"id" : "<媒体ID>",
"userId" : "<上传用户ID>",
"bizId" : "<业务实体ID>",
"originalname": "<原始文件名>",
"mimetype" : "<文件类型,如:image/jpeg>",
"size" : <文件大小,字节>,
"publicURL" : "<文件公网下载地址>"
}
]
上传附件支持两种模式:
append:新上传文件加入业务实体的媒体列表replace:新上传文件替换业务实体的媒体列表(相当于先清空后上传)多附件的业务实体可以使用追加模式;单附件(如封面)的业务实体可以使用替换模式
系统在调用极光推送Push接口时,会以以下方式推送:
{
"platform": "all",
"audience": "<接收者,详细见下文>",
"notification": {
"alert": "<消息文案,详细见下文>",
"android": {
"extras": {
"reason": "<推送原因,详细见下文>",
"xxxxId": "<关联业务实体ID>"
}
},
"ios": {
"badge": "+1",
"extras": {
"reason": "<推送原因,详细见下文>",
"xxxxId": "<关联业务实体ID>"
}
}
}
}
新题「2020年$广东申论真题副省级第1题」已发布,快来点击查看吧~extras如下:{
"reason" : "questionPublished",
"module" : "<writing|interview>",
"questionId": "<题目ID>",
"paperId" : "<试卷ID>",
}
userId题目「202年广东申论真题(副省级)第1题」中有您的新回复您的题目评论有新回复extras如下:{
"reason" : "questionCommentReply",
"module" : "<writing|interview>",
"questionId" : "<题目ID>",
"questionCommentId" : "<题目评论ID>",
"questionCommentReplyId" : "<回复的题目评论ID>",
"questionCommentTopReplyId": "<顶层题目评论ID>",
}
userId讨论「相关讨论」中有您的新回复extras如下:{
"reason" : "postReply",
"threadId" : "<主题ID>",
"postId" : "<发帖ID>",
"postReplyId" : "<回复的发帖ID>",
"postTopReplyId": "<顶层发帖ID>",
}
userId热点资讯「2020年广东热点:公考考情」中有您的新回复extras如下:{
"reason" : "hotspotNewsCommentReply",
"module" : "<writing|interview>",
"hotspotNewsId" : "<热点资讯ID>",
"hotspotNewsCommentId" : "<热点资讯评论ID>",
"hotspotNewsCommentReplyId" : "<回复的热点资讯评论ID>",
"hotspotNewsCommentTopReplyId": "<顶层热点资讯评论ID>",
}
满足以下条件时触发
applyTimeuserId课程「2020年第一次批改班」已经开始报名extras如下:{
"reason" : "courseApplyTimeReached",
"module" : "<writing|interview>",
"courseId" : "<课程ID>",
"courseType": "<课程类型>"
}
满足以下条件时触发
openTimeuserId课程「2020年第一次批改班」已经开班extras如下:{
"reason" : "courseOpenTimeReached",
"module" : "<writing|interview>",
"courseId" : "<课程ID>",
"courseType": "<课程类型>"
}
满足以下条件时触发
bizType="dailyEventWork"bizId对应作者的userId日常打卡「2022年山东申论时政热点打卡」2022-01-01 的作业中有您的新评论extras如下:{
"reason" : "commentReceived",
"module" : "<writing|interview>",
"bizType" : "<提交评论时传递的bizType>",
"bizId" : "<提交评论时传递的bizId>",
"commentId" : "<新创建的 评论ID>",
"dailyEventId" : "<日常打卡ID (仅在 bizType=dailyEventWork 时存在此字段)>",
"dailyEventTaskId" : "<日常打卡任务ID (仅在 bizType=dailyEventWork 时存在此字段)>",
"dailyEventTaskDate": "<日常打卡任务日期(仅在 bizType=dailyEventWork 时存在此字段)>",
}
满足以下条件时触发
replyIdreplyId对应作者的userId课程「江苏省入门学习」中有您的新回复课程「江苏省入门学习」章节「第一节课」中有您的新回复课程「江苏省入门学习」任务「第一个任务」中有您的新回复日常打卡「2022年山东申论时政热点打卡」2022-01-01 的作业中有您的新回复extras如下:{
"reason" : "commentReply",
"module" : "<writing|interview>",
"bizType" : "<提交评论时传递的bizType>",
"bizId" : "<提交评论时传递的bizId>",
"commentId" : "<新创建的 评论ID>",
"commentReplyId" : "<被评论的 评论ID>",
"commentTopReplyId" : "<所属顶层 评论ID>",
"courseType" : "<课程类型 (仅在 bizType=course|courseSection|courseTask 时存在此字段)>",
"dailyEventId" : "<日常打卡ID (仅在 bizType=dailyEventWork 时存在此字段)>",
"dailyEventTaskId" : "<日常打卡任务ID (仅在 bizType=dailyEventWork 时存在此字段)>",
"dailyEventTaskDate": "<日常打卡任务日期(仅在 bizType=dailyEventWork 时存在此字段)>",
}
满足以下条件时触发
isPublished=true时isPublished字段从false修改为true时日常打卡「2022年山东申论时政热点打卡」已经发布extras如下:{
"reason" : "dailyEventPublished",
"module" : "<writing|interview>",
"dailyEventId" : "<日常打卡ID>",
"dailyEventCategory": "<日常打卡分类>",
}
满足以下条件时触发
allowedAbsenceCountuserId由于缺卡次数过多,您在日常打卡「2022年山东申论时政热点打卡」的资格已经被取消extras如下:{
"reason" : "rejectedFromDailyEvent",
"module" : "<writing|interview>",
"dailyEventId" : "<日常打卡ID>",
"dailyEventCategory": "<日常打卡分类>",
}
2022-10-31 版本
满足以下条件时触发
applyTimeuserId日常打卡「XXXXX」已经开始报名extras如下:{
"reason" : "dailyEventApplyTimeReached",
"module" : "<writing|interview>",
"dailyEventId" : "<日常打卡ID>",
"dailyEventCategory": "<日常打卡分类>",
}
2022-10-31 版本
满足以下条件时触发
startTime - 1天userId亲爱的同学,「xxx」打卡明天就开始啦,请加油哦!extras如下:{
"reason" : "dailyEventStartTimeReached",
"module" : "<writing|interview>",
"dailyEventId" : "<日常打卡ID>",
"dailyEventCategory": "<日常打卡分类>",
}
2022-10-31 版本
满足以下条件时触发
startTime,且超过当天大的noticeHMapplieduserId小逸提醒您别忘了今天的打卡哦。放弃不难,但坚持一定很酷。extras如下:{
"reason" : "dailyEventEverydayNotice",
"module" : "<writing|interview>",
"dailyEventId" : "<日常打卡ID>",
"dailyEventCategory": "<日常打卡分类>",
}
满足以下条件时触发
isPublished=true时isPublished字段从false修改为true时写作打卡「2022年山东申论时政热点打卡」已经发布extras如下:{
"reason" : "writingEventPublished",
"writingEventId": "<写作打卡ID>",
}
复制服务器目录到本地
scp -r root@120.55.62.189:/root/project/webhook-receiver ~/Workspace/YiXue
| 字段名 | 说明 |
|---|---|
| id | 直播ID |
| title | 直播标题 |
| subTitle | 直播标题 |
| type | 直播类型:申论(shenlun)、行测(administrative)、面试(interview) |
| url | 直播间地址 |
| startTime | 开始时间 |
| endTime | 结束时间 |
| teacherId | 主讲老师 ID |
| isPublished | 是否发布 |
| 字段名 | 说明 |
|---|---|
| id | 回放ID |
| title | 回放标题 |
| subTitle | 回放标题 |
| type | 回放类型:直播类型:申论(shenlun)、行测(administrative)、面试(interview) |
| url | 回放地址 |
| 字段名 | 说明 |
|---|---|
| id | 推荐位ID |
| title | 推荐位标题 |
| type | 推荐位类型:直播(live)、打卡(event)、课程(course) |
| bizId | 推荐位对应的业务ID,类型为直播或打卡是单个 Id,类型为课程时是用逗号分割的 Id |
| isPublished | 是否发布 |
| publishTime | 发布时间 |
| priority | 优先级,用于排序,数字越小越靠前 |
1. docker 操作目录
cd ~/docker-stack/
2. 关闭 mysql
docker stack rm mysql
3. 确认 mysql 容器已经退出
docker stack ps
4. 开启 mysql
docker stack up mysql -c mysql.yaml
pm2 kill; pm2 start pm2.json
nginx -s reload
在阿里云购买证书,下载证书文件(Ngnix版本), 替换/root/ss文件夹下的证书文件,然后重启ngnix
替换目录/var/www/officialwebsite-new/
可进行退款操作的管理员账号:admin,密码:admin
账号:yx001 密码:yx666
banners 表:用于存储首页轮播图 Done
communities 表:用于存储社群信息 Done
lives 表:用于存储直播信息 Done
live_agg 表:用于存储直播聚合信息 Done
live_agg_user 表:用于存储直播聚合用户信息 Done
live_notice 表:用于存储直播开始通知信息 Done
live_replays 表:用于存储直播回放信息 Done
home_recs 表:用于首页推荐 Done
增加 media type:courseListCover、liveListCover、liveReplayListCover、dailyEventListCover
courses 表:增加字段:highlights(课程亮点)、obtain(你将获得)、instructions(购买须知)、copyright(版权申明)、taskDesc(任务描述)、sectionCount(章节数量)、isPinned('是否已置顶')、pinTime(置顶时间)、报名结束时间 applyEndTime, 是否有名额限制 hasSeatLimit, 守擂名额 defenderSeatCount, 翻盘名额 turnaroundSeatCount, 上课开始时间 classStartTime, 上课结束时间 classEndTime, 上课地点 location, 单间住宿额外收取收费价格(extraLodgingPrice) priceMax(最高价) priceMin(最低价) Done
course_sections 表:增加字段:duration(视频时长) Done
course_protocol_types 表:用于存储课程协议类型信息 Done
course_agg_user 表:增加字段 hasSigned(是否已经签约) courseUserInfoId(课程关联用户信息ID) signFlowId(签字协议流程ID)
signUrl(合同签署链接) Done
course_agg 表:增加字段 defenderPaidCount(守擂支付人数)、turnaroundPaidCount(翻盘支付人数) defenderOrderCount(守擂报名人数) turnaroundOrderCount(翻盘报名人数) Done
course_orders 表:增加字段 rankingSituation(排名情况) courseProtocolId(课程协议类型ID) positionTitle(岗位名称) lodgingConditions(住宿情况) Done
course_userinfos (课程关联用户信息,面试线下班专用); Done
discovery_recs 表:用于存储发现推荐信息 Done
landing_coin_orders 表:用于存储上岸币订单信息 Done
users 表:增加字段:landingCoin(上岸币数量)
在 dev api-service-launch 中添加 PROJ_ESIGN_SERVER_DOMAIN=smlopenapi.esign.cn \
在 prod api-service-launch 中添加 PROJ_ESIGN_SERVER_DOMAIN=openapi.esign.cn \
启动应用的 pm2.json 中的环境变量,一定要记得补充新增的内容 Done