Skip to content

mikai233/fstar-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

1c6ad77 · Jan 2, 2022

History

44 Commits
Jul 7, 2021
Jan 20, 2021
Jan 20, 2021
Jan 2, 2022
Jan 20, 2021
Feb 23, 2021
Jan 20, 2021
Aug 21, 2021
Jan 20, 2021
Jan 20, 2021
Jan 20, 2021
Mar 31, 2021
Jan 2, 2022
Jan 2, 2022

Repository files navigation

FStar 繁星课程表

简介

繁星课程表是一款课程表软件,采用Flutter框架开发,包含通用模式和江苏科技大学专有模式

关于本项目开发环境

本项目采用flutter dev分支进行开发,由于flutter不同分支api有变动以及版本升级可能导致相关api被废弃,而项目的依赖没有同步进行升级, 项目运行有可能失败,请自行做相关的调整。文末有本项目可以运行的flutter环境信息以供参考

关于跨平台问题

本项目理论上是支持跨平台的,采用dev分支是为了开启Windows和Web平台,由于本项目主要还是在Android和iOS上运行, 所以Windows和Web平台仅供体验,iOS部分由于我现在手上并没有Mac,所以iOS的部分一些第三方依赖所需要的配置并没有做, 需要自行配置

通用模式

通用模式采用内置浏览器定位到教务系统课表页执行JavaScript解析函数的方法导入课表

JUST模式

开发者为江苏科技大学教务系统适配的专用模式,包含成绩查询、课表查询、常用工具等功能

APP预览

繁星课程表适配方法

如何导入课表

如果你是江苏科技大学的学生,可以在设置中选择JUST模式来快捷导入课表,如果你是其他学校的学生, 在本页配置学校的课表解析函数(右上角),退出本页点击课表导入 ,通过浏览器进入到学校的教务系统课表页,然后点击Appbar上的导入按钮即可完成导入

课表解析函数的编写(导入课表只看上面部分)

导入课表需要有该学校的课表解析函数(JavaScript),该函数可以由该学校的任意一名学生提供,只需要有一点编程基础和CSS选择器知识即可编写;编写之后把解析函数上传到服务器即可共享

课程数据结构规定

{
  "name": "MEMS封装技术",
  "id": "06050010b-1",
  "classroom": "12号楼-214(活动)",
  "week": [
    6,
    7,
    8
  ],
  "row": 7,
  "column": 5,
  "rowSpan": 2,
  "teacher": "刘瑞"
}

以上为标准的JSON结构

name 课程名称 字符串

id 课程号 字符串

classroom 教室 字符串

week 课程周数 整型数组

row 课程行定位,从1开始,表示第几小节 数字

column 课程列定位,从1开始,表示星期几 范围1-7 数字

rowSpan 课程跨行,2表示课程横跨两行,相当于两小节 数字

teacher 老师 字符串

以上字段均不能为null 跨行没有限制,课程可以任意重叠

发送课表解析结果

调用如下代码将解析结果发送给繁星课程表

window.flutter_inappwebview.callHandler('postCourse', JSON.stringify({'course': course, 'remark': remark}));

course是一个课程数组 remark为备注信息,可选,会显示到课表底部

注意 手动填入解析函数的时候要特别注意换行问题,如果没有换行,所有的代码会变成一行,如果代码中带有注释则会出错!

解析函数例子

以下为江苏科技大学本科生课表解析函数

(function () {
    let course = [];
    let trs = document.querySelectorAll('#kbtable tr');
    let remark = trs[trs.length - 1].textContent;//备注
    for (let i = 1; i < trs.length - 1; i++) {
        let contents = trs[i].querySelectorAll('td .kbcontent')
        contents.forEach((value, key) => {
            let c = parse(value.innerHTML, i, key + 1);
            course.push(...c)
        });
    }

    //解析课表
    function parse(content, row, column) {
        let eachContent = content.split(/-{5,}<br>/);
        let result = [];
        eachContent.forEach(value => {
            let regx = /(.*?)<br>(.*?)<br><.*?>(.*?)<\/font>.*?">(.*?)\(\)/
            let results = regx.exec(value);
            if (results != null) {
                let id = results[1];
                let name = results[2];
                let teacher = results[3];
                let week = parseWeek(results[4]);
                let roomRegx = /<font title="">(.*?)<\/font>/
                let roomResult = roomRegx.exec(value)
                let room = roomResult !== null ? roomResult[1] : '';
                let course = {
                    'name': name,
                    'id': id,
                    'classroom': room,
                    'week': week,
                    'row': row * 2 - 1,
                    'column': column,
                    'rowSpan': 2,
                    'teacher': teacher,
                };
                result.push(course);
            }
        });
        return result;
    }

    function parseWeek(rawWeek) {
        let eachPart = rawWeek.split(',');
        let result = [];
        eachPart.forEach(part => {
            if (part.indexOf('-') !== -1) {
                let [begin, end] = part.split('-');
                for (let i = Number(begin); i < Number(end) + 1; i++) {
                    result.push(i);
                }
            } else {
                result.push(Number(part));
            }
        });
        let setResult = new Set(result);
        return Array.from(setResult);
    }

    window.flutter_inappwebview.callHandler('postCourse', JSON.stringify({'course': course, 'remark': remark}));
})();

以下为江苏科技大学研究生课表解析函数

预处理函数

因为研究生系统含有多个iframe,需要用js代码跳转到课表页的iframe执行课表解析函数才能成功导入课表

window.location = 'http://yjsinfo.just.edu.cn/pyxx/pygl/kbcx_xs.aspx';

课表解析函数

(function () {
    let course = [];
    let trs = document.querySelectorAll('#DataGrid1 tr');
    for (let i = 1; i < trs.length; i++) {
        let contents = trs[i].querySelectorAll('td');
        let filterResult = [];
        contents.forEach(value => {
            if (value.innerHTML !== '上午' && value.innerHTML !== '下午' && value.innerHTML !== '晚上') {
                if (isNaN(parseInt(value.innerHTML))) {
                    filterResult.push(value);
                }
            }
        })
        filterResult.forEach((value, key) => {
            let rowSpan = value.getAttribute('rowSpan');
            let c = parse(value.innerHTML, i, key + 1, parseInt(rowSpan));
            course.push(...c);
        });
    }

    function parse(content, row, column, rowSpan) {
        let eachContent = content.split(/<br><br>/);
        let result = [];
        eachContent.forEach(value => {
            let regx = /:(.*?)<br>:(.*?)<br>\((.*?)\)<br>(.*?); <br>:(.*?)/
            let results = regx.exec(value);
            if (results != null) {
                let id = results[2].trim();
                let name = results[1].trim();
                let teacher = results[5].trim();
                let week = parseWeek(results[4]);
                let room = results[3].trim();
                let course = {
                    'name': name,
                    'id': id,
                    'classroom': room,
                    'week': week,
                    'row': row,
                    'column': column,
                    'rowSpan': rowSpan,
                    'teacher': teacher,
                };
                result.push(course);
            }
        });
        return result;
    }

    function parseWeek(rawWeek) {
        let eachPart = rawWeek.split(',');
        let result = [];
        eachPart.forEach(part => {
            if (part.indexOf('-') !== -1) {
                let [begin, end] = part.split('-');
                for (let i = Number(begin); i < Number(end) + 1; i++) {
                    result.push(i);
                }
            } else {
                result.push(Number(part));
            }
        });
        let setResult = new Set(result);
        return Array.from(setResult);
    }

    window.flutter_inappwebview.callHandler('postCourse', JSON.stringify({'course': course}));
})();

开发环境

本项目采用的是Flutter的dev分支进行开发的,并非stable分支

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel dev, 2.1.0-12.1.pre, on Microsoft Windows [Version 10.0.19042.867], locale zh-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Chrome - develop for the web
[✓] Visual Studio - develop for Windows (Visual Studio Enterprise 2019 16.8.2)
[✓] Android Studio (version 4.1.0)
[✓] IntelliJ IDEA Ultimate Edition (version 2020.3)
[✓] VS Code (version 1.45.1)
[✓] Connected device (4 available)

Flutter学习