13.10 学习

顶部菜单中的学习
使用远程前端,需要的app.py前面加上下面两行代码:
from flask_cors import CORS
CORS(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字段