13.10 学习
顶部菜单中的学习
使用远程前端,需要的app.py前面加上下面两行代码:
from flask_cors import CORSCORS(app, resources={r"/*": {"origins": "https://www.codessp.cn"}})
首先发起一个post请求chapters,发送的参数为courseId以及一个标记参数sub。
在统计的时候,已经有一个chapters请求,当时是查找所有章节,然后用作下拉菜单,并不需要做子章节,而这个sub就是标记,如果这个值不为空,那么按这一节的要求做子章节(有subChapters)
返回的json将填满左侧的章节导航,json结构如下:
{ "code": "200", "info": "31", "data": [ { "score": 0, "code": "010000", "parentCode": "000000", "serial": "第一章", "name": "python介绍", "subChapters": [ { "score": 0, "code": "010100", "parentCode": "010000", "serial": "1.1 ", "name": "python开发环境", "id": "771" }, { "score": 0, "code": "010200", "parentCode": "010000", "serial": "1.2 ", "name": "第一个python程序", "id": "772" }, { "score": 0, "code": "010300", "parentCode": "010000", "serial": "1.3 ", "name": "使用pycharm", "id": "783" }, { "score": 0, "code": "010400", "parentCode": "010000", "serial": "1.4 ", "name": "如何学习python", "id": "792" } ], "id": "765" }, { "score": 175, "code": "020000", "parentCode": "000000", "serial": "第二章", "name": "变量和运算符", "subChapters": [略...], } //其余部分略 ]}
这里的难点在于子章节,除了从数据库里找到章节数据外,还要从code值再去查一次数据库,看有没有子章节,有的话把数据绑定到subChapters下,下面是实现的伪代码:
# Python伪代码chapter_list = 从数据库里根据course_id取得主要章节(code值以0000结尾)arr = [] # json数组
for cha in chapter_list: obj = { "score": cha.score, "code": cha.code, # 其余属性省略 } # 处理子章节,只处理一层 sub_chapters = 使用cha的code值作为parent_code以及cha的course_id来查找,看是否有数据 if sub_chapters: # 非空检查 sub_chapter_arr = [] for c in sub_chapters: sub_obj = { "score": c.score, "code": c.code, # 其余属性省略 } sub_chapter_arr.append(sub_obj) obj["subChapters"] = sub_chapter_arr arr.append(obj)message = { "status": "200", "data": arr, "info": course_id}
至于serial这个属性,也就是现实“第一章”,“1.2 ”值,它是根据code值计算出来的,可直接调用下面的函数:
def chapter_serial_number(code): if not code: return "" first_level_code = code[:2] second_level_code = code[2:4] third_level_code = code[4:6] m1 = int(first_level_code) m2 = int(second_level_code) m3 = int(third_level_code) if m2 == 0 and m3 == 0: return str(m1) if m3 == 0: return f"{m1}.{m2} " return f"{m1}.{m2}.{m3} "def get_chapter_name(code): if not code: return "" chapter_name = chapter_serial_number(code) m1 = 0 chapter2 = "" if '.' in chapter_name: chapter1 = chapter_name[:chapter_name.index('.')] m1 = int(chapter1) f = chapter_name.index('.') s = chapter_name.find('.', f + 1) if s == -1: chapter2 = chapter_name[f+1:] else: chapter2 = chapter_name[f+1:s] else: m1 = int(chapter_name) number_map = { 1: "一", 2: "二", 3: "三", 4: "四", 5: "五", 6: "六", 7: "七", 8: "八", 9: "九", 10: "十", 11: "十一", 12: "十二", 13: "十三", 14: "十四", 15: "十五", 16: "十六", 17: "十七", 18: "十八", 19: "十九", 20: "二十" } m = number_map.get(m1, str(m1)) if chapter2: return chapter_name else: return f"第{m}章"
尝试完成学习页面的左边栏
学习页面右边的内容相对比较简单:
右边学习内容,点击或者进入学习页面,都会发起一个get请求/chapterContent,它有三个参数courseId、cd=030200和username=abc
cd就是chapter的code属性
返回的json如下:
{ "code": null, "info": null, "data": { "id": "728", "chapterSections": [ { "sectionContent": "练习题", "sectionQuiz": [], "sectionId": "", "queue": 0 } ], "chapterTitle": "3.2 登录", "courseId": "12", "content": "这里就是章节内容,内容过长略" }}
其中chapterSections涉及到学生做题,本节暂时忽略不做。而后面的chapterTitle就是章节标题,content就是章节内容,取自chapter表的content字段