From c424da786e554360137e17844d39fc7f1b91c6e8 Mon Sep 17 00:00:00 2001 From: idealclover Date: Sun, 17 Jul 2022 18:00:16 +0800 Subject: [PATCH 1/2] :bug: fixed bugs of new xk system --- lib/Utils/CourseParserXK.dart | 55 ++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/lib/Utils/CourseParserXK.dart b/lib/Utils/CourseParserXK.dart index 5b44faa..2d1a1fa 100644 --- a/lib/Utils/CourseParserXK.dart +++ b/lib/Utils/CourseParserXK.dart @@ -28,43 +28,76 @@ class CourseParser { Future> parseCourse(int tableId) async { List rst = []; + + Element? tableHead = document!.getElementsByClassName("course-head")[1]; + List headElements = tableHead.children[0].children; + int infoIndex = 3; + int courseNameIndex = 1; + int courseTeacherIndex = 2; + int courseInfoIndex = 6; + for (var i = 0; i < headElements.length; i++) { + print(headElements[i].innerHtml); + if (headElements[i].innerHtml.contains('时间地点')) { + infoIndex = i; + } else if (headElements[i].innerHtml.contains('课程名')) { + courseNameIndex = i; + } else if (headElements[i].innerHtml.contains('教师')) { + courseTeacherIndex = i; + } else if (headElements[i].innerHtml.contains('备注')) { + courseInfoIndex = i; + } + } + Element? table = document!.getElementsByClassName("course-body")[1]; List elements = table.children; + for (Element e in elements) { //退选课程 // String state = e.children[6].innerHtml.trim(); // if(state.contains('已退选')) continue; + if (e.className.contains('wdbm-course-tr')) continue; + // print(e.className); + // Time and Place - List infos = e.children[3].children; - String courseName = e.children[1].innerHtml; - String courseTeacher = e.children[2].innerHtml; - String courseInfo = e.children[6].attributes['title'] ?? ''; + List infos = e.children[infoIndex].children; + String courseName = e.children[courseNameIndex].innerHtml; + String courseTeacher = e.children[courseTeacherIndex].innerHtml; + String courseInfo = e.children[courseInfoIndex].attributes['title'] ?? ''; // String source = e.children[3].innerHtml.trim().replaceAll('
', '\\n'); // List infos = source.split('\\n'); - // print(source); + print(infos); for (Element i in infos) { String info = i.innerHtml; if (info == '') continue; + print(i.text); + // "自由时间 2-17周 详见主页通知" // ATTENTION:这里是新教务系统的坑! if (info == '自由地点') continue; - // Get WeekTime List strs = info.split(' '); - String weekStr = info.substring(0, 2); - int weekTime = _getIntWeek(weekStr); - if (weekTime == 0) { - throw (courseName); + //自由时间缺省值 + int weekTime = 0; + int startTime = 0; + int timeCount = 0; + + if (!info.contains('自由时间')) { + // Get WeekTime + String weekStr = info.substring(0, 2); + + weekTime = _getIntWeek(weekStr); + if (weekTime == 0) { + throw (courseName); + } } // Get Time - int startTime, timeCount; String weekSeries; try { From e4203d83804780829493408e0401af9e5b1422ac Mon Sep 17 00:00:00 2001 From: idealclover Date: Wed, 31 Aug 2022 00:19:11 +0800 Subject: [PATCH 2/2] :tada: version 3.3.3 --- android/app/build.gradle | 7 +- android/build.gradle | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- api/complete.json | 14 +- api/importVisibility.json | 7 + api/schoolList.json | 36 +- api/tools/njubksjw.js | 91 ++++ api/tools/njubksxk.js | 199 ++++--- api/tools/njuyjsxk.js | 3 + lib/Models/CourseTableModel.dart | 27 +- .../CourseTable/CourseTablePresenter.dart | 15 +- lib/Pages/CourseTable/CourseTableView.dart | 2 +- lib/Pages/Import/ImportFromBEView.dart | 80 ++- lib/Pages/Import/ImportFromCerView.dart | 101 +++- lib/Pages/Import/ImportFromJWView.dart | 62 ++- lib/Pages/Import/ImportView.dart | 152 ++++-- lib/Resources/Url.dart | 2 +- lib/Utils/CourseParser.dart | 3 + lib/generated/intl/messages_en.dart | 18 +- lib/generated/intl/messages_zh_CN.dart | 18 +- lib/generated/l10n.dart | 40 ++ lib/l10n/intl_en.arb | 4 + lib/l10n/intl_zh_CN.arb | 4 + pubspec.lock | 500 +++++++----------- pubspec.yaml | 15 +- 25 files changed, 902 insertions(+), 502 deletions(-) create mode 100644 api/importVisibility.json create mode 100644 api/tools/njubksjw.js diff --git a/android/app/build.gradle b/android/app/build.gradle index 5cb6f8a..4c919da 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -29,16 +29,19 @@ def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android { - compileSdkVersion 31 + compileSdkVersion 32 lintOptions { disable 'InvalidPackage' + disable "Instantiatable" + checkReleaseBuilds false + abortOnError false } defaultConfig { applicationId "com.lilystudio.wheretosleepinnju" minSdkVersion 23 - targetSdkVersion 31 + targetSdkVersion 32 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/build.gradle b/android/build.gradle index d652a29..78d035f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.1.1' + classpath 'com.android.tools.build:gradle:4.2.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } gradle.projectsEvaluated { diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index c69d51d..ca2bbd5 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip \ No newline at end of file +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip \ No newline at end of file diff --git a/api/complete.json b/api/complete.json index 83922e2..7dae8f3 100644 --- a/api/complete.json +++ b/api/complete.json @@ -1,9 +1,7 @@ { - "version": 1, - "title": "用户协议与隐私政策", - "content": "

版本生效日期:2021-10-01

感谢使用南哪课表!本应用由idealclover开发与发布。我们非常重视用户的隐私保护,绝不会在未经允许的情况下收集您的任何隐私内容。本文尽可能简短,强烈建议您认真阅读。

我们收集的数据
应用崩溃时产生的日志信息,以便于我们定位bug和改善应用健壮性;

我们不会收集的数据
用户在APP内进行登录操作时输入的账号与密码,如果您使用记住密码功能,我们会将这些信息存储在用户本地,不会上传至服务器;
用户的个人信息与课程信息将同样会存储在用户本地,不会上传至服务器;
特殊地,如果使用课表分享功能,课程信息将在服务器按期限进行暂存,如果添加由南哪助手(原NJU助手)提供的讲座信息,您的添加行为将被匿名记录以实现「X人已添加」功能;

集成的第三方 SDK
集成友盟+SDK,友盟+SDK需要收集您的设备Mac地址、唯一设备识别码(IMEI/android ID/IDFA/OPENUDID/GUID、SIM 卡 IMSI 信息)以提供统计分析服务,并通过地理位置校准报表数据准确性,提供基础反作弊能力。

", - "isForce": false, - "confirm_text_first_install": "同意协议,开始导入", - "confirm_text_for_upgrade": "同意协议,开始使用", - "cancel_text": "不同意并退出" -} \ No newline at end of file + "title": "欢迎使用南哪课表!", + "content": "2022.02\n恍惚之间又一年啊\n今年也为南哪课表做了不少工作,推出了讲座系统,支持了自由时间课程,也做了课表的官网和宣传视频,希望大家能喜欢鸭!\n\n2021.08\n又是新的学期啦\n21届的新同学都要来了,瞬间有种自己太老了的感觉hhhhhh\n\n2021.2\n不知不觉小作文更新这么长了~\n\n又是新的一年,新的一学期了。\n\n过去的这一年或许大家都经历了很多,疫情来了,翠翠毕业了,紫荆站关闭了。或许,哪次教务系统更新之后,南哪课表就再也用不起来了。\n\n所以,如果南哪课表还不错,可以在它还在的时候,一起安利给周围的小伙伴吗~\n\n过去的时光,我们都辛苦了,未来,一起加油。\n\n“敬自己一杯,因为值得。”\n\n2020.9\n这是翠翠离开南大的第一个秋天。不过放心,南哪课表还在维护。\n\n离开校园,其实想说的话有很多,但却又不知道从哪里说起,说些什么,却总会在被社会毒打的时候怀念起在南大的快乐时光。\n\n大概,衷心希望学弟学妹们珍惜大学生活w\n\n2020.5\n在付出了另一个¥688后,南哪课表终于上线 APP Store 啦!感谢大家一直以来的支持!\n\n2020.2\n2020年2月全部投喂收入将捐赠以支援湖北疫情\n(2020.3补充:已捐赠)\n\n2019.9\nHi!我是项目作者傻翠~\n\n看起来你已经导入我南教务处成功啦!撒花撒花!\n\n建议大家还是和自己教务系统中的课表对一下~避免出现什么bug~如果有bug的话欢迎反馈给我!设置-反馈中有交流群的群号~\n\n坦率地讲,从安卓移植到全平台是一个痛苦的过程。之前的APP多少是建立在开源项目的基础上,而这个重构项目算是自己从零开始搭起来的。其中也做了不少取舍与妥协,还有可能出现之前所没有过的bug,如果不巧遇到bug,欢迎向我反馈。\n\n写这个项目是一个吃力不讨好的事。单是苹果的开发者账号就要688/年,更不用提为了开发iOS版而单独买的MacBook。所以如果小伙伴想让这个项目持续下去的话,欢迎投喂傻翠。\n\n放心,这个弹框每次导入只会弹出一次,所以不会影响你的正常使用。\n\n希望南哪课表可以陪伴学弟学妹们走过每一学期ww\n\n傻翠", + "content_html": "

2022.02

恍惚之间又一年啊

今年也为南哪课表做了不少工作,推出了讲座系统,支持了自由时间课程,也做了课表的官网和宣传视频,希望大家能喜欢鸭!

2021.08

又是新的学期啦

21届的新同学都要来了,瞬间有种自己太老了的感觉hhhhhh

2021.2

不知不觉小作文更新这么长了~

又是新的一年,新的一学期了。

过去的这一年或许大家都经历了很多,疫情来了,翠翠毕业了,紫荆站关闭了。或许,哪次教务系统更新之后,南哪课表就再也用不起来了。

所以,如果南哪课表还不错,可以在它还在的时候,一起安利给周围的小伙伴吗~

过去的时光,我们都辛苦了,未来,一起加油。

“敬自己一杯,因为值得。”

2020.9

这是翠翠离开南大的第一个秋天。不过放心,南哪课表还在维护。

离开校园,其实想说的话有很多,但却又不知道从哪里说起,说些什么,却总会在被社会毒打的时候怀念起在南大的快乐时光。

大概,衷心希望学弟学妹们珍惜大学生活w

2020.5

在付出了另一个¥688后,南哪课表终于上线 APP Store 啦!感谢大家一直以来的支持!

2020.2

2020年2月全部投喂收入将捐赠以支援湖北疫情

(2020.3补充:已捐赠)

2019.9

Hi!我是项目作者傻翠~

看起来你已经导入我南教务处成功啦!撒花撒花!

建议大家还是和自己教务系统中的课表对一下~避免出现什么bug~如果有bug的话欢迎反馈给我!设置-反馈中有交流群的群号~

坦率地讲,从安卓移植到全平台是一个痛苦的过程。之前的APP多少是建立在开源项目的基础上,而这个重构项目算是自己从零开始搭起来的。其中也做了不少取舍与妥协,还有可能出现之前所没有过的bug,如果不巧遇到bug,欢迎向我反馈。

写这个项目是一个吃力不讨好的事。单是苹果的开发者账号就要688/年,更不用提为了开发iOS版而单独买的MacBook。所以如果小伙伴想让这个项目持续下去的话,欢迎投喂傻翠。

放心,这个弹框每次导入只会弹出一次,所以不会影响你的正常使用。

希望南哪课表可以陪伴学弟学妹们走过每一学期ww

傻翠

", + "semester_start_monday": "2022-09-05", + "delay": 10 +} diff --git a/api/importVisibility.json b/api/importVisibility.json new file mode 100644 index 0000000..e65e848 --- /dev/null +++ b/api/importVisibility.json @@ -0,0 +1,7 @@ +{ + "data": [ + true, + true, + false + ] +} \ No newline at end of file diff --git a/api/schoolList.json b/api/schoolList.json index f44e38d..b800750 100644 --- a/api/schoolList.json +++ b/api/schoolList.json @@ -1,18 +1,18 @@ { "data": [ { - "title": "南京大学本科生选课系统(beta)", + "title": "南京大学本科生统一认证", "pinyin": "nanjingdaxuebenke", - "description": "测试中,请确保APP版本>=3.1.0!", - "page_title": "选课系统登录", + "description": "内置导入不成功时可以试试这个", + "page_title": "教务系统登录", "initialUrl": "https://authserver.nju.edu.cn/authserver/login?service=http%3A%2F%2Felite.nju.edu.cn%2Fjiaowu%2Fcaslogin.jsp", "redirectUrl": "http://elite.nju.edu.cn/jiaowu/login.do", "targetUrl": "http://elite.nju.edu.cn/jiaowu/student/teachinginfo/courseList.do?method=currentTermCourse", "preExtractJS": "", "delayTime": 3, "extractJS": "", - "extractJSfileAndroid": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njubksxk_android.js", - "extractJSfileiOS": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njubksxk.js", + "extractJSfileAndroid": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njubksjw.js", + "extractJSfileiOS": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njubksjw.js", "banner_content": "注意:如加载失败,请连接南京大学VPN\n试试浏览器访问教务网,没准教务系统又抽风了\n听起来有点离谱,不过在南京大学,倒也正常", "banner_action": "下载南京大学VPN", "banner_url": "https://vpn.nju.edu.cn", @@ -20,9 +20,29 @@ "isGrey3.1.0": false }, { - "title": "南京大学研究生选课系统(alpha)", + "title": "南京大学本科生选课系统(beta)", + "pinyin": "nanjingdaxuebenke", + "description": "新选课系统,可能不太稳定", + "page_title": "选课系统登录", + "initialUrl": "https://xk.nju.edu.cn", + "redirectUrl": "", + "targetUrl": "https://xk.nju.edu.cn/xsxkapp/sys/xsxkapp/*default/grablessons.do", + "preExtractJS": "document.getElementsByClassName('yxkc-window-btn')[0].click();document.getElementsByClassName('jqx-tabs-titleContentWrapper ')[0].click();", + "delayTime": 3, + "extractJS": "", + "extractJSfileAndroid": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njubksxk.js", + "extractJSfileiOS": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njubksxk.js", + "banner_content": "注意:如加载失败,请连接南京大学VPN\n试试浏览器访问教务网,没准系统又抽风了\n听起来有点离谱,不过在南京大学,倒也正常", + "banner_action": "下载南京大学VPN", + "banner_url": "https://vpn.nju.edu.cn", + "isGrey": true, + "isGrey3.1.0": false, + "semester_start_monday": "2022-09-05" + }, + { + "title": "南京大学研究生选课系统", "pinyin": "nanjingdaxueyanjiu", - "description": "测试中,请确保APP版本>=3.1.0!", + "description": "研究生同学的课表导入方式", "page_title": "选课系统登录", "initialUrl": "https://yjsxk.nju.edu.cn/yjsxkapp/sys/xsxkapp/index_nju.html", "redirectUrl": "https://yjsxk.nju.edu.cn/yjsxkapp/sys/xsxkapp/course_nju.html", @@ -30,7 +50,7 @@ "preExtractJS": "", "delayTime": 3, "extractJS": "", - "extractJSfileAndroid": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njuyjsxk_android.js", + "extractJSfileAndroid": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njuyjsxk.js", "extractJSfileiOS": "https://cdn.idealclover.cn/Projects/wheretosleepinnju/production/tools/njuyjsxk.js", "banner_content": "导入方式:登陆后点击「我的选课」进入选课页\n注意:如加载失败,请连接南京大学VPN\n试试浏览器访问教务网,没准教务系统又抽风了\n听起来有点离谱,不过在南京大学,倒也正常", "banner_action": "下载南京大学VPN", diff --git a/api/tools/njubksjw.js b/api/tools/njubksjw.js new file mode 100644 index 0000000..db2db72 --- /dev/null +++ b/api/tools/njubksjw.js @@ -0,0 +1,91 @@ +function scheduleHtmlParser() { + let WEEK_WITH_BIAS = [ + "", + "周一", + "周二", + "周三", + "周四", + "周五", + "周六", + "周日", + ]; + let name = document.querySelector( + "body > div:nth-child(10) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(1)" + ).textContent; + let rst = { name: name, courses: [] }; + let table_1 = document.getElementsByClassName("TABLE_TR_01"); + let table_2 = document.getElementsByClassName("TABLE_TR_02"); + let table = table_1.concat(table_2); + table.forEach((e) => { + let state = e.children[6].innerText; + if (state.includes("已退选")) return; + let course_name = e.children[1].innerText; + let class_number = e.children[0].innerText; + let teacher = e.children[3].innerText; + let test_time = e.children[8].innerText; + let test_location = e.children[9].innerText; + let course_info = e.children[10].innerText; + let info_str = e.children[4].innerText; + let info_list = info_str.split("\n"); + info_list.forEach((i) => { + let week_time = 0; + let strs = i.split(" "); + let start_time = 0; + let time_count = 0; + let weeks = []; + for (let z = 0; z < WEEK_WITH_BIAS.length; z++) { + if (WEEK_WITH_BIAS[z] == strs[0]) week_time = z; + } + let pattern1 = new RegExp("第(\\d{1,2})-(\\d{1,2})节", "i"); + strs.forEach((w) => { + let r = pattern1.exec(w); + if (r) { + start_time = parseInt(r[1]); + time_count = parseInt(r[2]) - parseInt(r[1]); + } + }); + let pattern2 = new RegExp("(\\d{1,2})-(\\d{1,2})周", "i"); + strs.forEach((x) => { + let s = pattern2.exec(x); + if (s) { + if (strs.includes("单周")) { + for (let z = parseInt(s[1]); z <= parseInt(s[2]); z += 2) + weeks.push(z); + } else if (strs.includes("双周")) { + for (let z = parseInt(s[1]); z <= parseInt(s[2]); z += 2) + weeks.push(z); + } else { + for (let z = parseInt(s[1]); z <= parseInt(s[2]); z++) + weeks.push(z); + } + } + }); + let pattern3 = new RegExp("第(\\d{1,2})周", "i"); + strs.forEach((y) => { + let t = pattern3.exec(y); + if (t) { + weeks.push(parseInt(t[1])); + } + }); + let classroom = strs[strs.length - 1]; + rst["courses"].push({ + name: course_name, + classroom: classroom, + class_number: class_number, + teacher: teacher, + test_time: test_time, + test_location: test_location, + link: null, + weeks: weeks, + week_time: week_time, + start_time: start_time, + time_count: time_count, + import_type: 1, + info: course_info, + data: null, + }); + }); + }); + return encodeURIComponent(JSON.stringify(rst)); +} +scheduleHtmlParser(); diff --git a/api/tools/njubksxk.js b/api/tools/njubksxk.js index d1c23e5..a5bd116 100644 --- a/api/tools/njubksxk.js +++ b/api/tools/njubksxk.js @@ -1,3 +1,37 @@ +function getWeekSeriesString(info) { + let weekList = []; + let strs = []; + try { + info = info.split(" ")[2]; + strs = info.split(","); + } catch (e) { + return "[]"; + } + + for (let i = 0; i < strs.length; i++) { + var rst4 = strs[i].match(/^(\d{1,2})周$/); + if (rst4 != null) { + weekList.push(rst4[1]); + } + + var rst2 = strs[i].match(/(\d{1,2})-(\d{1,2})周/); + if (rst2 != null) { + let startWeek = parseInt(rst2[1]); + let endWeek = parseInt(rst2[2]); + if (strs[i].includes("单") || strs[i].includes("双")) { + for (let j = startWeek; j <= endWeek; j = j + 2) { + weekList.push(j); + } + } else { + for (let j = startWeek; j <= endWeek; j++) { + weekList.push(j); + } + } + } + } + return weekList; +} + function scheduleHtmlParser() { let WEEK_WITH_BIAS = [ "", @@ -9,83 +43,110 @@ function scheduleHtmlParser() { "周六", "周日", ]; - let name = document.querySelector( - "body > div:nth-child(10) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(1)" - ).textContent; - let rst = { name: name, courses: []}; - let table_1 = document.getElementsByClassName("TABLE_TR_01"); - let table_2 = document.getElementsByClassName("TABLE_TR_02"); - let table = table_1.concat(table_2); - table.forEach((e) => { - let state = e.children[6].innerText; - if (state.includes("已退选")) return; - let course_name = e.children[1].innerText; - let class_number = e.children[0].innerText; - let teacher = e.children[3].innerText; - let test_time = e.children[8].innerText; - let test_location = e.children[9].innerText; - let course_info = e.children[10].innerText; - let info_str = e.children[4].innerText; - let info_list = info_str.split("\n"); - info_list.forEach((i) => { - let week_time = 0; - let strs = i.split(" "); - let start_time = 0; - let time_count = 0; - let weeks = []; - for (let z = 0; z < WEEK_WITH_BIAS.length; z++) { - if (WEEK_WITH_BIAS[z] == strs[0]) week_time = z; - } - let pattern1 = new RegExp("第(\\d{1,2})-(\\d{1,2})节", "i"); - strs.forEach((w) => { - let r = pattern1.exec(w); - if (r) { - start_time = parseInt(r[1]); - time_count = parseInt(r[2]) - parseInt(r[1]); - } - }); - let pattern2 = new RegExp("(\\d{1,2})-(\\d{1,2})周", "i"); - strs.forEach((x) => { - let s = pattern2.exec(x); - if (s) { - if (strs.includes("单周")) { - for (let z = parseInt(s[1]); z <= parseInt(s[2]); z += 2) - weeks.push(z); - } else if (strs.includes("双周")) { - for (let z = parseInt(s[1]); z <= parseInt(s[2]); z += 2) - weeks.push(z); - } else { - for (let z = parseInt(s[1]); z <= parseInt(s[2]); z++) - weeks.push(z); + let WEEK_NUM = 17; + + let name = document.getElementsByClassName("currentTerm")[0].innerHTML; + let rst = { name: name, courses: [] }; + let tableHead = document.getElementsByClassName("course-head")[1]; + let headElements = tableHead.children[0].children; + let infoIndex = 3; + let courseNameIndex = 1; + let courseTeacherIndex = 2; + let courseInfoIndex = 6; + for (let i = 0; i < headElements.length; i++) { + // console.log(headElements[i].innerHTML); + if (headElements[i].innerHTML.includes("时间地点")) { + infoIndex = i; + } else if (headElements[i].innerHTML.includes("课程名")) { + courseNameIndex = i; + } else if (headElements[i].innerHTML.includes("教师")) { + courseTeacherIndex = i; + } else if (headElements[i].innerHTML.includes("备注")) { + courseInfoIndex = i; + } + } + let table = document.getElementsByClassName("course-body")[1]; + let elements = table.children; + + for (let i = 0; i < elements.length; i++) { + // console.log(elements[i]); + //退选课程 + // String state = e.children[6].innerHtml.trim(); + // if(state.contains('已退选')) continue; + + if (elements[i].className.includes("wdbm-course-tr")) continue; + // print(e.className); + + // Time and Place + let infos = elements[i].children[infoIndex].children; + let courseName = elements[i].children[courseNameIndex].innerHTML; + let courseTeacher = elements[i].children[courseTeacherIndex].innerHTML; + let courseInfo = + elements[i].children[courseInfoIndex].attributes["title"].value; + + // console.log(infos); + for (let j = 0; j < infos.length; j++) { + let info = infos[j].innerHTML; + if (info == "") continue; + // console.log(info); + + let strs = info.split(" "); + + //自由时间缺省值 + let weekTime = 0; + let startTime = 0; + let timeCount = 0; + if (!info.includes("自由时间")) { + // Get WeekTime + let weekStr = info.substring(0, 2); + for (let k = 0; k < WEEK_WITH_BIAS.length; k++) { + if (WEEK_WITH_BIAS[k] == weekStr) { + weekTime = k; } } - }); - let pattern3 = new RegExp("第(\\d{1,2})周", "i"); - strs.forEach((y) => { - let t = pattern3.exec(y); - if (t) { - weeks.push(parseInt(t[1])); + } + + let weekSeries; + // console.log(info) + + let time = info.match(/(\d{1,2})-(\d{1,2})节/); + // console.log(time); + // var time = patten1.firstMatch(info); + if (time) { + startTime = parseInt(time[1]); + timeCount = parseInt(time[2]) - startTime; + weekSeries = getWeekSeriesString(info); + } + if (weekSeries == null) { + weekSeries = []; + for (let j = 1; j <= WEEK_NUM; j++) { + weekSeries.push(j); } - }); - let classroom = strs[strs.length - 1]; + } + + // Get ClassRoom + let classRoom = strs[strs.length - 1]; + + // console.log(weekTime); rst["courses"].push({ - name: course_name, - classroom: classroom, - class_number: class_number, - teacher: teacher, - test_time: test_time, - test_location: test_location, + name: courseName, + classroom: classRoom, + // class_number: class_number, + teacher: courseTeacher, + // test_time: test_time, + // test_location: test_location, link: null, - weeks: weeks, - week_time: week_time, - start_time: start_time, - time_count: time_count, + weeks: weekSeries, + week_time: weekTime, + start_time: startTime, + time_count: timeCount, import_type: 1, - info: course_info, + info: courseInfo, data: null, }); - }); - }); + } + } + // return rst; return encodeURIComponent(JSON.stringify(rst)); } scheduleHtmlParser(); diff --git a/api/tools/njuyjsxk.js b/api/tools/njuyjsxk.js index f990890..a84413a 100644 --- a/api/tools/njuyjsxk.js +++ b/api/tools/njuyjsxk.js @@ -46,6 +46,9 @@ function scheduleHtmlParser() { } else if (strs[4] == '双') { for (let z = parseInt(strs[1]); z <= parseInt(strs[3]); z += 2) weeks.push(z); + } else if (typeof(strs[2]) == 'undefined') { + // Just a single weak ... + weeks.push(parseInt(strs[1])); } else { for (let z = parseInt(strs[1]); z <= parseInt(strs[3]); z++) weeks.push(z); diff --git a/lib/Models/CourseTableModel.dart b/lib/Models/CourseTableModel.dart index 5a59fb4..b189eca 100644 --- a/lib/Models/CourseTableModel.dart +++ b/lib/Models/CourseTableModel.dart @@ -77,7 +77,7 @@ class CourseTableProvider { return rst.toList(); } - Future> getclassTimeList(int id) async { + Future> getClassTimeList(int id) async { await open(); List defaultClassTimeList = Constant.CLASS_TIME_LIST; @@ -88,13 +88,13 @@ class CourseTableProvider { if (maps.isEmpty || maps[0]["data"] == null) { return defaultClassTimeList; } - print(maps); + // print(maps); try { Map rst = json.decode(maps[0]["data"]); if(rst["class_time_list"] == null) { return defaultClassTimeList; } - print(rst["class_time_list"]); + // print(rst["class_time_list"]); return List.from(rst["class_time_list"]); } catch (e) { // print(e); @@ -102,6 +102,27 @@ class CourseTableProvider { } } + Future getSemesterStartMonday(int id) async { + await open(); + List> maps = await db!.query(tableName, + columns: [columnId, columnName, columnData], + where: '$columnId = ?', + whereArgs: [id]); + if (maps.isEmpty || maps[0]["data"] == null || maps[0]["data"] == "") { + return ""; + } + try { + Map rst = json.decode(maps[0]["data"]); + if(rst["semester_start_monday"] == null) { + return ""; + } + return rst["semester_start_monday"]; + } catch (e) { + // print(e); + return ""; + } + } + Future delete(int id) async { await open(); CourseProvider courseProvider = CourseProvider(); diff --git a/lib/Pages/CourseTable/CourseTablePresenter.dart b/lib/Pages/CourseTable/CourseTablePresenter.dart index 5de77b6..aa7bfd5 100644 --- a/lib/Pages/CourseTable/CourseTablePresenter.dart +++ b/lib/Pages/CourseTable/CourseTablePresenter.dart @@ -2,12 +2,13 @@ import 'dart:io'; import 'dart:async'; import 'dart:convert'; import 'package:dio/dio.dart'; -import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart'; +import 'package:flutter_swiper_null_safety_flutter3/flutter_swiper_null_safety_flutter3.dart'; import 'package:umeng_common_sdk/umeng_common_sdk.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:scoped_model/scoped_model.dart'; import 'package:flutter_html/flutter_html.dart'; +import '../../Models/CourseTableModel.dart'; import '../../generated/l10n.dart'; import '../../Models/CourseModel.dart'; import '../../Models/ScheduleModel.dart'; @@ -102,10 +103,16 @@ class CourseTablePresenter { welcomeTitle = response.data['title']; welcomeContent = response.data['content_html']; delaySeconds = response.data['delay']; - bool isSameWeek = await WeekUtil.isSameWeek( - (response.data['semester_start_monday']), 1); + String semesterStartMonday = response.data['semester_start_monday']; + int index = await ScopedModel.of(context).getClassTable(); + CourseTableProvider courseTableProvider = CourseTableProvider(); + String tmpSemesterStartMonday = await courseTableProvider.getSemesterStartMonday(index); + if(tmpSemesterStartMonday != "") { + semesterStartMonday = tmpSemesterStartMonday; + } + bool isSameWeek = await WeekUtil.isSameWeek(semesterStartMonday, 1); if (!isSameWeek) { - await changeWeek(context, response.data['semester_start_monday']); + await changeWeek(context, semesterStartMonday); } } else { welcomeTitle = S.of(context).welcome_title; diff --git a/lib/Pages/CourseTable/CourseTableView.dart b/lib/Pages/CourseTable/CourseTableView.dart index 85609ad..6017a4f 100644 --- a/lib/Pages/CourseTable/CourseTableView.dart +++ b/lib/Pages/CourseTable/CourseTableView.dart @@ -96,7 +96,7 @@ class CourseTableViewState extends State { try{ CourseTableProvider courseTableProvider = CourseTableProvider(); - _classTimeList = await courseTableProvider.getclassTimeList(index); + _classTimeList = await courseTableProvider.getClassTimeList(index); _maxShowClasses = _classTimeList.length; }catch(e) { _classTimeList = Constant.CLASS_TIME_LIST; diff --git a/lib/Pages/Import/ImportFromBEView.dart b/lib/Pages/Import/ImportFromBEView.dart index 4335263..63523a0 100644 --- a/lib/Pages/Import/ImportFromBEView.dart +++ b/lib/Pages/Import/ImportFromBEView.dart @@ -3,15 +3,19 @@ import 'dart:async'; import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:umeng_common_sdk/umeng_common_sdk.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:scoped_model/scoped_model.dart'; +import '../../Components/Dialog.dart'; +import '../../Components/TransBgTextButton.dart'; import '../../Utils/States/MainState.dart'; import '../../generated/l10n.dart'; import '../../Components/Toast.dart'; import '../../Models/CourseModel.dart'; import '../../Models/CourseTableModel.dart'; +import '../../Resources/Url.dart'; class ImportFromBEView extends StatefulWidget { final String? title; @@ -129,16 +133,24 @@ class ImportFromBEViewState extends State { response = Uri.decodeComponent(response.replaceAll('"', '')); Map courseTableMap = json.decode(response); CourseTable courseTable; - if (widget.config['class_time_list'] == null) { + if (widget.config['class_time_list'] == null && + widget.config['semester_start_monday'] == null) { courseTable = await courseTableProvider .insert(CourseTable(courseTableMap['name'])); } else { - try{ - Map data = {"class_time_list": widget.config['class_time_list']}; + try { + Map data = {}; + if (widget.config['class_time_list'] != null) { + data["class_time_list"] = widget.config['class_time_list']; + } + if (widget.config['semester_start_monday'] != null) { + data["semester_start_monday"] = + widget.config['semester_start_monday']; + } String dataString = json.encode(data); courseTable = await courseTableProvider .insert(CourseTable(courseTableMap['name'], data: dataString)); - } catch(e) { + } catch (e) { courseTable = await courseTableProvider .insert(CourseTable(courseTableMap['name'])); } @@ -168,8 +180,66 @@ class ImportFromBEViewState extends State { Toast.showToast(S.of(context).class_parse_toast_success, context); Navigator.of(context).pop(true); } catch (e) { + String response = await controller.runJavascriptReturningResult( + "window.document.getElementsByTagName('html')[0].outerHTML;"); + String url = await controller.currentUrl() ?? ""; + + String now = DateTime.now().toString(); + String errorCode = now + .replaceAll("-", "") + .replaceAll(":", "") + .replaceAll(" ", "") + .replaceAll(".", ""); + Map info = { + "errorCode": errorCode, + "response": response, + "errorMsg": e.toString(), + "url": url, + "way": "be" + }; + await Dio() + .post(Url.URL_BACKEND + "/log/log", data: FormData.fromMap(info)); + UmengCommonSdk.onEvent("class_import", {"type": "be", "action": "fail"}); - Toast.showToast(S.of(context).online_parse_error_toast, context); + // Toast.showToast(S.of(context).online_parse_error_toast, context); + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return MDialog( + S.of(context).parse_error_dialog_title, + Text(S.of(context).parse_error_dialog_content(errorCode)), + overrideActions: [ + Container( + alignment: Alignment.centerRight, + child: TransBgTextButton( + color: Theme.of(context).brightness == Brightness.light + ? Theme.of(context).primaryColor + : Colors.white, + child: Text(S.of(context).parse_error_dialog_add_group), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: errorCode)); + if (Platform.isIOS) { + launch(Url.QQ_GROUP_APPLE_URL); + } else if (Platform.isAndroid) { + launch(Url.QQ_GROUP_ANDROID_URL); + } + Navigator.of(context).pop(); + })), + Container( + alignment: Alignment.centerRight, + child: TransBgTextButton( + color: Colors.grey, + child: Text(S.of(context).parse_error_dialog_other_ways, + style: const TextStyle(color: Colors.grey)), + onPressed: () async { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + })) + ], + ); + }); return; } } diff --git a/lib/Pages/Import/ImportFromCerView.dart b/lib/Pages/Import/ImportFromCerView.dart index 3dc7048..c9acb2f 100644 --- a/lib/Pages/Import/ImportFromCerView.dart +++ b/lib/Pages/Import/ImportFromCerView.dart @@ -1,12 +1,17 @@ import 'dart:io'; import 'dart:async'; +import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:umeng_common_sdk/umeng_common_sdk.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; +import '../../Components/Dialog.dart'; +import '../../Components/TransBgTextButton.dart'; import '../../generated/l10n.dart'; import '../../Utils/CourseParser.dart'; import '../../Components/Toast.dart'; +import '../../Resources/Url.dart'; class ImportFromCerView extends StatefulWidget { final Map config; @@ -52,7 +57,17 @@ class ImportFromCerViewState extends State { await cookieManager.clearCookies(); _webViewController.loadUrl(widget.config['initialUrl']); }, - ) + ), + + /// 作弊器 + // IconButton( + // icon: const Icon(Icons.gamepad), + // onPressed: () async { + // Response response = await Dio().get( + // "https://clover-1254951786.cos.ap-shanghai.myqcloud.com/Projects/wheretosleepinnju/debug/testfiles/jw.html"); + // import(_webViewController, context, res: response.data); + // }, + // ) ], ), body: Builder( @@ -103,26 +118,90 @@ class ImportFromCerViewState extends State { ); } - import(WebViewController controller, BuildContext context) async { - Toast.showToast(S.of(context).class_parse_toast_importing, context); - await controller.runJavascript(widget.config['preExtractJS'] ?? ''); - await Future.delayed(Duration(seconds: widget.config['delayTime'] ?? 0)); - String response = await controller - .runJavascriptReturningResult(widget.config['extractJS']); + import(WebViewController controller, BuildContext context, + {String? res}) async { + String response = ""; + if (res != null) { + /// 测试数据 + response = res; + } else { + Toast.showToast(S.of(context).class_parse_toast_importing, context); + await controller.runJavascript(widget.config['preExtractJS'] ?? ''); + await Future.delayed(Duration(seconds: widget.config['delayTime'] ?? 0)); + response = await controller + .runJavascriptReturningResult(widget.config['extractJS']); + } response = response.replaceAll('\\u003C', '<').replaceAll('\\"', '"'); - CourseParser cp = CourseParser(response); - String courseTableName = cp.parseCourseName(); - int rst = await cp.addCourseTable(courseTableName, context); try { + CourseParser cp = CourseParser(response); + String courseTableName = cp.parseCourseName(); + int rst = await cp.addCourseTable(courseTableName, context); await cp.parseCourse(rst); UmengCommonSdk.onEvent( "class_import", {"type": "cer", "action": "success"}); Toast.showToast(S.of(context).class_parse_toast_success, context); Navigator.of(context).pop(true); } catch (e) { + String now = DateTime.now().toString(); + String errorCode = now + .replaceAll("-", "") + .replaceAll(":", "") + .replaceAll(" ", "") + .replaceAll(".", ""); + Map info = { + "errorCode": errorCode, + "response": response, + "errorMsg": e.toString(), + "way": "cer" + }; + try{ + await Dio() + .post(Url.URL_BACKEND + "/log/log", data: FormData.fromMap(info)); + } catch(e) { + print(e); + } + UmengCommonSdk.onEvent("class_import", {"type": "cer", "action": "fail"}); - Toast.showToast(S.of(context).class_parse_error_toast, context); + // Toast.showToast(S.of(context).class_parse_error_toast, context); + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return MDialog( + S.of(context).parse_error_dialog_title, + Text(S.of(context).parse_error_dialog_content(errorCode)), + overrideActions: [ + Container( + alignment: Alignment.centerRight, + child: TransBgTextButton( + color: Theme.of(context).brightness == Brightness.light + ? Theme.of(context).primaryColor + : Colors.white, + child: Text(S.of(context).parse_error_dialog_add_group), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: errorCode)); + if (Platform.isIOS) { + launch(Url.QQ_GROUP_APPLE_URL); + } else if (Platform.isAndroid) { + launch(Url.QQ_GROUP_ANDROID_URL); + } + Navigator.of(context).pop(); + })), + Container( + alignment: Alignment.centerRight, + child: TransBgTextButton( + color: Colors.grey, + child: Text(S.of(context).parse_error_dialog_other_ways, + style: const TextStyle(color: Colors.grey)), + onPressed: () async { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + })) + ], + ); + }); } } } diff --git a/lib/Pages/Import/ImportFromJWView.dart b/lib/Pages/Import/ImportFromJWView.dart index 87be753..019ae91 100644 --- a/lib/Pages/Import/ImportFromJWView.dart +++ b/lib/Pages/Import/ImportFromJWView.dart @@ -1,3 +1,7 @@ +import 'dart:io'; +import 'package:flutter/services.dart'; +import '../../Components/Dialog.dart'; +import '../../Components/TransBgTextButton.dart'; import '../../generated/l10n.dart'; import 'package:umeng_common_sdk/umeng_common_sdk.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -243,14 +247,68 @@ class _ImportFromJWViewState extends State { Toast.showToast( S.of(context).class_parse_error_toast, context); } else { + UmengCommonSdk.onEvent("class_import", + {"type": "jw", "action": "success"}); Toast.showToast( S.of(context).class_parse_toast_success, context); } Navigator.of(context).pop(true); } else { - Toast.showToast( - S.of(context).class_parse_toast_fail, context); + UmengCommonSdk.onEvent( + "class_import", {"type": "jw", "action": "fail"}); + // Toast.showToast( + // S.of(context).class_parse_toast_fail, context); + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return MDialog( + S.of(context).parse_error_dialog_title, + Text(S + .of(context) + .parse_error_dialog_content("102")), + overrideActions: [ + Container( + alignment: Alignment.centerRight, + child: TransBgTextButton( + color: Theme.of(context) + .brightness == + Brightness.light + ? Theme.of(context).primaryColor + : Colors.white, + child: Text(S + .of(context) + .parse_error_dialog_add_group), + onPressed: () async { + await Clipboard.setData( + const ClipboardData( + text: "102")); + if (Platform.isIOS) { + launch(Url.QQ_GROUP_APPLE_URL); + } else if (Platform.isAndroid) { + launch( + Url.QQ_GROUP_ANDROID_URL); + } + Navigator.of(context).pop(); + })), + Container( + alignment: Alignment.centerRight, + child: TransBgTextButton( + color: Colors.grey, + child: Text( + S + .of(context) + .parse_error_dialog_other_ways, + style: const TextStyle( + color: Colors.grey)), + onPressed: () async { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + })) + ], + ); + }); setState(() { randomNumForCaptcha = Random().nextDouble(); }); diff --git a/lib/Pages/Import/ImportView.dart b/lib/Pages/Import/ImportView.dart index 0b2aae7..4a1a675 100644 --- a/lib/Pages/Import/ImportView.dart +++ b/lib/Pages/Import/ImportView.dart @@ -54,8 +54,11 @@ class ImportView extends StatefulWidget { } class _ImportViewState extends State { + List importVisibility = [false, false, false]; + @override void initState() { + getImportVisibility(); super.initState(); } @@ -70,57 +73,71 @@ class _ImportViewState extends State { // child: Column( children: ListTile.divideTiles(context: context, tiles: [ - Container( - child: - Text(S.of(context).import_inline, style: const TextStyle()), - padding: - const EdgeInsets.only(left: 15.0, top: 10.0, bottom: 5.0), - alignment: Alignment.centerLeft, - color: Theme.of(context).hoverColor), - ListTile( - title: Text(S.of(context).import_from_NJU_cer_title), - subtitle: FittedBox( - fit: BoxFit.scaleDown, - alignment: Alignment.centerLeft, - child: Text(S.of(context).import_from_NJU_cer_subtitle)), - onTap: () async { - UmengCommonSdk.onEvent( - "class_import", {"type": "cer", "action": "show"}); - bool? status = await Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) => - const ImportFromCerView(config: Config.jw_config))); - if (status == true) Navigator.of(context).pop(status); - }, - ), - ListTile( - title: Text(S.of(context).import_from_NJU_title), - subtitle: FittedBox( - fit: BoxFit.scaleDown, - alignment: Alignment.centerLeft, - child: Text(S.of(context).import_from_NJU_subtitle)), - onTap: () async { - UmengCommonSdk.onEvent( - "class_import", {"type": "jw", "action": "show"}); - bool? status = await Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) => const ImportFromJWView())); - if (status == true) Navigator.of(context).pop(status); - }, - ), - ListTile( - title: Text(S.of(context).import_from_NJU_xk_title), - subtitle: FittedBox( - fit: BoxFit.scaleDown, - alignment: Alignment.centerLeft, - child: Text(S.of(context).import_from_NJU_xk_subtitle)), - onTap: () async { - UmengCommonSdk.onEvent( - "class_import", {"type": "xk", "action": "show"}); - bool? status = await Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) => - const ImportFromXKView(config: Config.xk_config))); - if (status == true) Navigator.of(context).pop(status); - }, - ), + (importVisibility[0] || importVisibility[1] || importVisibility[2]) + ? Container( + child: Text(S.of(context).import_inline, + style: const TextStyle()), + padding: + const EdgeInsets.only(left: 15.0, top: 10.0, bottom: 5.0), + alignment: Alignment.centerLeft, + color: Theme.of(context).hoverColor) + : Container(), + importVisibility[0] + ? ListTile( + title: Text(S.of(context).import_from_NJU_cer_title), + subtitle: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: Text(S.of(context).import_from_NJU_cer_subtitle)), + onTap: () async { + UmengCommonSdk.onEvent( + "class_import", {"type": "cer", "action": "show"}); + bool? status = await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => + const ImportFromCerView( + config: Config.jw_config))); + if (status == true) Navigator.of(context).pop(status); + }, + ) + : Container(), + importVisibility[1] + ? ListTile( + title: Text(S.of(context).import_from_NJU_title), + subtitle: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: Text(S.of(context).import_from_NJU_subtitle)), + onTap: () async { + UmengCommonSdk.onEvent( + "class_import", {"type": "jw", "action": "show"}); + bool? status = await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => + const ImportFromJWView())); + if (status == true) Navigator.of(context).pop(status); + }, + ) + : Container(), + importVisibility[2] + ? ListTile( + title: Text(S.of(context).import_from_NJU_xk_title), + subtitle: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: Text(S.of(context).import_from_NJU_xk_subtitle)), + onTap: () async { + UmengCommonSdk.onEvent( + "class_import", {"type": "xk", "action": "show"}); + bool? status = await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => + const ImportFromXKView( + config: Config.xk_config))); + if (status == true) Navigator.of(context).pop(status); + }, + ) + : Container(), Container( child: Text(S.of(context).import_online, style: const TextStyle()), @@ -133,6 +150,18 @@ class _ImportViewState extends State { builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData) { + if (snapshot.data!.isEmpty) { + return Column( + children: [ + Container( + padding: const EdgeInsets.symmetric( + vertical: 10, horizontal: 0), + child: const Text("加载中..."), + ), + moreSchools() + ], + ); + } // List configList = snapshot.data!; List schoolList = snapshot.data! .map((data) => School( @@ -195,6 +224,22 @@ class _ImportViewState extends State { ); } + getImportVisibility() async { + try { + Dio dio = Dio(); + String url = Url.UPDATE_ROOT + '/importVisibility.json'; + Response response = await dio.get(url); + List rst = List.from(response.data['data']); + setState(() { + importVisibility = rst; + }); + } catch (e) { + setState(() { + importVisibility = [true, false, false]; + }); + } + } + Future getOnlineConfig() async { try { Dio dio = Dio(); @@ -265,7 +310,10 @@ class _ImportViewState extends State { return InkWell( child: Container( child: Text(S.of(context).import_more_schools, - style: TextStyle(color: Theme.of(context).primaryColor)), + style: TextStyle( + color: Theme.of(context).brightness == Brightness.light + ? Theme.of(context).primaryColor + : Colors.white)), alignment: Alignment.topCenter, padding: const EdgeInsets.only(top: 5.0, bottom: 5.0)), onTap: () { diff --git a/lib/Resources/Url.dart b/lib/Resources/Url.dart index c41a7ac..9c77489 100644 --- a/lib/Resources/Url.dart +++ b/lib/Resources/Url.dart @@ -27,5 +27,5 @@ class Url { // TODO: change URL to production static const String UPDATE_ROOT = 'https://cdn.idealclover.cn/Projects/wheretosleepinnju/production'; -// static final String UPDATE_ROOT = 'https://clover-1254951786.cos.ap-shanghai.myqcloud.com/Projects/wheretosleepinnju/debug'; + // static const String UPDATE_ROOT = 'https://clover-1254951786.cos.ap-shanghai.myqcloud.com/Projects/wheretosleepinnju/debug'; } diff --git a/lib/Utils/CourseParser.dart b/lib/Utils/CourseParser.dart index e39a760..39c1057 100644 --- a/lib/Utils/CourseParser.dart +++ b/lib/Utils/CourseParser.dart @@ -24,6 +24,9 @@ class CourseParser { // "body > div:nth-child(10) > table > tbody > tr:nth-child(2) > td"); final RegExp nameExp = RegExp("[0-9]+-[0-9]+学年第(一|二)学期"); String name = nameExp.stringMatch(html).toString(); + if(name == "null") { + throw Exception("Didn't find course table."); + } // print(element.innerHtml); return name; } diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index d507255..48a9d73 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -34,9 +34,12 @@ class MessageLookup extends MessageLookupByLibrary { static String m6(num) => "已结束(${num}人已添加)"; - static String m7(num) => "第 ${num} 周"; + static String m7(code) => + "看起来导入失败了,都怪傻翠!\n\n本次导入错误码:${code}\n\n点击下方按钮将复制该错误码并加入用户群,你可以报告傻翠并等待修复,当然,也可以试试其他方式是否可以正常导入"; - static String m8(start, end) => "${start}-${end} 周"; + static String m8(num) => "第 ${num} 周"; + + static String m9(start, end) => "${start}-${end} 周"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -265,6 +268,13 @@ class MessageLookup extends MessageLookupByLibrary { "shared_preferences: ^2.0.7\nflutter_swiper_null_safety: ^1.0.2\nscoped_model: ^2.0.0-nullsafety.0\nazlistview: ^2.0.0-nullsafety.0\nwebview_flutter: ^2.0.13\nflutter_linkify: ^5.0.2\nimage_picker: ^0.8.4\npackage_info: ^2.0.2\npath_provider: ^2.0.3\nurl_launcher: ^6.0.10\nflutter_html: ^2.1.3\nfluttertoast: ^8.0.1\nsqflite: ^2.0.0+4\nhtml: ^0.15.0\ndio: ^4.0.0"), "open_source_library_title": MessageLookupByLibrary.simpleMessage("所使用到的开源库"), + "parse_error_dialog_add_group": + MessageLookupByLibrary.simpleMessage("加入用户群报告问题"), + "parse_error_dialog_content": m7, + "parse_error_dialog_other_ways": + MessageLookupByLibrary.simpleMessage("试试其他导入方式"), + "parse_error_dialog_title": + MessageLookupByLibrary.simpleMessage("Oops,导入失败惹 TvT"), "password": MessageLookupByLibrary.simpleMessage("密码"), "password_error_toast": MessageLookupByLibrary.simpleMessage("密码错误 = =||"), @@ -307,8 +317,8 @@ class MessageLookup extends MessageLookupByLibrary { "view_lecture_subtitle": MessageLookupByLibrary.simpleMessage("查看南哪最新讲座信息,可一键导入至课表"), "view_lecture_title": MessageLookupByLibrary.simpleMessage("查看/添加讲座"), - "week": m7, - "week_duration": m8, + "week": m8, + "week_duration": m9, "week_num_invalid_dialog_content": MessageLookupByLibrary.simpleMessage("课程结束周数应大于起始周数"), "week_num_invalid_dialog_title": diff --git a/lib/generated/intl/messages_zh_CN.dart b/lib/generated/intl/messages_zh_CN.dart index 2a7c461..3b09dc8 100644 --- a/lib/generated/intl/messages_zh_CN.dart +++ b/lib/generated/intl/messages_zh_CN.dart @@ -34,9 +34,12 @@ class MessageLookup extends MessageLookupByLibrary { static String m6(num) => "已结束(${num}人已添加)"; - static String m7(num) => "第 ${num} 周"; + static String m7(code) => + "看起来导入失败了,都怪傻翠!\n\n本次导入错误码:${code}\n\n点击下方按钮将复制该错误码并加入用户群,你可以报告傻翠并等待修复,当然,也可以试试其他方式是否可以正常导入"; - static String m8(start, end) => "${start}-${end} 周"; + static String m8(num) => "第 ${num} 周"; + + static String m9(start, end) => "${start}-${end} 周"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -265,6 +268,13 @@ class MessageLookup extends MessageLookupByLibrary { "shared_preferences: ^2.0.7\nflutter_swiper_null_safety: ^1.0.2\nscoped_model: ^2.0.0-nullsafety.0\nazlistview: ^2.0.0-nullsafety.0\nwebview_flutter: ^2.0.13\nflutter_linkify: ^5.0.2\nimage_picker: ^0.8.4\npackage_info: ^2.0.2\npath_provider: ^2.0.3\nurl_launcher: ^6.0.10\nflutter_html: ^2.1.3\nfluttertoast: ^8.0.1\nsqflite: ^2.0.0+4\nhtml: ^0.15.0\ndio: ^4.0.0"), "open_source_library_title": MessageLookupByLibrary.simpleMessage("所使用到的开源库"), + "parse_error_dialog_add_group": + MessageLookupByLibrary.simpleMessage("加入用户群报告问题"), + "parse_error_dialog_content": m7, + "parse_error_dialog_other_ways": + MessageLookupByLibrary.simpleMessage("试试其他导入方式"), + "parse_error_dialog_title": + MessageLookupByLibrary.simpleMessage("Oops,导入失败惹 TvT"), "password": MessageLookupByLibrary.simpleMessage("密码"), "password_error_toast": MessageLookupByLibrary.simpleMessage("密码错误 = =||"), @@ -307,8 +317,8 @@ class MessageLookup extends MessageLookupByLibrary { "view_lecture_subtitle": MessageLookupByLibrary.simpleMessage("查看南哪最新讲座信息,可一键导入至课表"), "view_lecture_title": MessageLookupByLibrary.simpleMessage("查看/添加讲座"), - "week": m7, - "week_duration": m8, + "week": m8, + "week_duration": m9, "week_num_invalid_dialog_content": MessageLookupByLibrary.simpleMessage("课程结束周数应大于起始周数"), "week_num_invalid_dialog_title": diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index e993b39..ae1ad35 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -1220,6 +1220,46 @@ class S { ); } + /// `Oops,导入失败惹 TvT` + String get parse_error_dialog_title { + return Intl.message( + 'Oops,导入失败惹 TvT', + name: 'parse_error_dialog_title', + desc: '', + args: [], + ); + } + + /// `看起来导入失败了,都怪傻翠!\n\n本次导入错误码:{code}\n\n点击下方按钮将复制该错误码并加入用户群,你可以报告傻翠并等待修复,当然,也可以试试其他方式是否可以正常导入` + String parse_error_dialog_content(Object code) { + return Intl.message( + '看起来导入失败了,都怪傻翠!\n\n本次导入错误码:$code\n\n点击下方按钮将复制该错误码并加入用户群,你可以报告傻翠并等待修复,当然,也可以试试其他方式是否可以正常导入', + name: 'parse_error_dialog_content', + desc: '', + args: [code], + ); + } + + /// `加入用户群报告问题` + String get parse_error_dialog_add_group { + return Intl.message( + '加入用户群报告问题', + name: 'parse_error_dialog_add_group', + desc: '', + args: [], + ); + } + + /// `试试其他导入方式` + String get parse_error_dialog_other_ways { + return Intl.message( + '试试其他导入方式', + name: 'parse_error_dialog_other_ways', + desc: '', + args: [], + ); + } + /// `导入完成` String get import_success_toast { return Intl.message( diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index b242506..0651f60 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -116,6 +116,10 @@ "qrcode_name_error_toast": "读取课表名称失败,可能为链接错误", "qrcode_read_error_toast": "读取课程表,可能是 bug", "online_parse_error_toast": "导入课表失败,可能是 bug", + "parse_error_dialog_title": "Oops,导入失败惹 TvT", + "parse_error_dialog_content": "看起来导入失败了,都怪傻翠!\n\n本次导入错误码:{code}\n\n点击下方按钮将复制该错误码并加入用户群,你可以报告傻翠并等待修复,当然,也可以试试其他方式是否可以正常导入", + "parse_error_dialog_add_group": "加入用户群报告问题", + "parse_error_dialog_other_ways": "试试其他导入方式", "import_success_toast": "导入完成", "export_title": "导出课程表", "import_qr_title": "二维码导入", diff --git a/lib/l10n/intl_zh_CN.arb b/lib/l10n/intl_zh_CN.arb index 4c3f9de..f783fec 100644 --- a/lib/l10n/intl_zh_CN.arb +++ b/lib/l10n/intl_zh_CN.arb @@ -116,6 +116,10 @@ "qrcode_name_error_toast": "读取课表名称失败,可能为链接错误", "qrcode_read_error_toast": "读取课程表,可能是 bug", "online_parse_error_toast": "导入课表失败,可能是 bug", + "parse_error_dialog_title": "Oops,导入失败惹 TvT", + "parse_error_dialog_content": "看起来导入失败了,都怪傻翠!\n\n本次导入错误码:{code}\n\n点击下方按钮将复制该错误码并加入用户群,你可以报告傻翠并等待修复,当然,也可以试试其他方式是否可以正常导入", + "parse_error_dialog_add_group": "加入用户群报告问题", + "parse_error_dialog_other_ways": "试试其他导入方式", "import_success_toast": "导入完成", "export_title": "导出课程表", "import_qr_title": "二维码导入", diff --git a/pubspec.lock b/pubspec.lock index 44bef3b..baf0121 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,133 +5,112 @@ packages: dependency: transitive description: name: archive - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "3.2.1" + version: "3.3.0" args: dependency: transitive description: name: args - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.3.1" async: dependency: transitive description: name: async - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.8.2" azlistview: dependency: "direct main" description: name: azlistview - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" characters: dependency: transitive description: name: characters - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.2.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.3.1" - chewie: - dependency: transitive - description: - name: chewie - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.3.0" - chewie_audio: - dependency: transitive - description: - name: chewie_audio - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.1.0" collection: dependency: transitive description: name: collection - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" cross_file: dependency: transitive description: name: cross_file - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.3.2" + version: "0.3.3+1" crypto: dependency: transitive description: name: crypto - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" csslib: dependency: transitive description: name: csslib - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.17.1" - cupertino_icons: - dependency: transitive - description: - name: cupertino_icons - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "0.17.2" dio: dependency: "direct main" description: name: dio - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "4.0.4" + version: "4.0.6" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" ffi: dependency: transitive description: name: ffi - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "6.1.2" flutter: @@ -143,28 +122,21 @@ packages: dependency: "direct main" description: name: flutter_html - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" - flutter_layout_grid: - dependency: transitive - description: - name: flutter_layout_grid - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.0.3" + version: "3.0.0-alpha.5" flutter_linkify: dependency: "direct main" description: name: flutter_linkify - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "5.0.2" flutter_lints: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" flutter_localizations: @@ -172,41 +144,27 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_math_fork: - dependency: transitive - description: - name: flutter_math_fork - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.5.0" flutter_native_splash: dependency: "direct main" description: name: flutter_native_splash - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.2.0+1" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" - flutter_svg: - dependency: transitive - description: - name: flutter_svg - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.23.0+1" - flutter_swiper_null_safety: + version: "2.0.7" + flutter_swiper_null_safety_flutter3: dependency: "direct main" description: - name: flutter_swiper_null_safety - url: "https://pub.flutter-io.cn" + name: flutter_swiper_null_safety_flutter3 + url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "2.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -221,352 +179,338 @@ packages: dependency: "direct main" description: name: fluttertoast - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "8.0.8" + version: "8.0.9" html: dependency: "direct main" description: name: html - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "0.15.0" http: dependency: transitive description: name: http - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "0.13.4" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.1" image: dependency: transitive description: name: image - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "3.1.3" image_picker: dependency: "direct main" description: name: image_picker - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.5+3" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + url: "https://pub.dartlang.org" source: hosted - version: "0.8.4+9" + version: "0.8.5+1" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.6" + version: "2.1.8" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.5+6" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.4.4" + version: "2.5.0" in_app_review: dependency: "direct main" description: name: in_app_review - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.0.4" in_app_review_platform_interface: dependency: transitive description: name: in_app_review_platform_interface - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.0.3" intl: dependency: transitive description: name: intl - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "0.17.0" js: dependency: transitive description: name: js - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.6.4" linkify: dependency: transitive description: name: linkify - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "4.1.0" + lint: + dependency: transitive + description: + name: lint + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.2" lints: dependency: transitive description: name: lints - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "0.12.11" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "0.1.4" meta: dependency: transitive description: name: meta - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.7.0" - nested: - dependency: transitive - description: - name: nested - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.0.0" numerus: dependency: transitive description: name: numerus - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.1.1" package_info: dependency: "direct main" description: name: package_info - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.0.2" path: dependency: transitive description: name: path - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.8.0" - path_drawing: - dependency: transitive - description: - name: path_drawing - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.5.1+1" - path_parsing: - dependency: transitive - description: - name: path_parsing - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.2.1" + version: "1.8.1" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.9" + version: "2.0.11" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.16" path_provider_ios: dependency: transitive description: name: path_provider_ios - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.7" + version: "2.0.10" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "2.1.7" path_provider_macos: dependency: transitive description: name: path_provider_macos - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.0" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" + version: "5.0.0" platform: dependency: transitive description: name: platform - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.1.2" process: dependency: transitive description: name: process - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "4.2.4" - provider: - dependency: transitive - description: - name: provider - url: "https://pub.flutter-io.cn" - source: hosted - version: "6.0.2" qr: dependency: transitive description: name: qr - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" qr_code_scanner: dependency: "direct main" description: name: qr_code_scanner - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.5.2" + version: "1.0.1" qr_flutter: dependency: "direct main" description: name: qr_flutter - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "4.0.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.flutter-io.cn" - source: hosted - version: "3.0.1+1" scoped_model: dependency: "direct main" description: name: scoped_model - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0-nullsafety.0" scrollable_positioned_list: - dependency: transitive + dependency: "direct overridden" description: name: scrollable_positioned_list - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.2.3" + version: "0.3.2" share_extend: dependency: "direct main" description: name: share_extend - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" + version: "2.0.15" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.12" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" sky_engine: dependency: transitive description: flutter @@ -576,79 +520,72 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" sqflite: dependency: "direct main" description: name: sqflite - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.2.1+1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.1.0" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.0+2" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.2.0" test_api: dependency: transitive description: name: test_api - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.4.8" - tuple: - dependency: transitive - description: - name: tuple - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.0.0" + version: "0.4.9" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" umeng_common_sdk: dependency: "direct main" description: @@ -660,205 +597,128 @@ packages: dependency: transitive description: name: universal_io - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.0.4" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "6.0.20" + version: "6.1.5" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "6.0.15" + version: "6.0.17" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "6.0.15" + version: "6.0.17" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.0" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.0.12" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.1.1" - very_good_analysis: - dependency: transitive - description: - name: very_good_analysis - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.4.0" - video_player: - dependency: transitive - description: - name: video_player - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.2.18" - video_player_android: - dependency: transitive - description: - name: video_player_android - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.3.0" - video_player_avfoundation: - dependency: transitive - description: - name: video_player_avfoundation - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.3.0" - video_player_platform_interface: - dependency: transitive - description: - name: video_player_platform_interface - url: "https://pub.flutter-io.cn" - source: hosted - version: "5.1.0" - video_player_web: - dependency: transitive - description: - name: video_player_web - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.0.7" - wakelock: - dependency: transitive - description: - name: wakelock - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.6.1+1" - wakelock_macos: - dependency: transitive - description: - name: wakelock_macos - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.4.0" - wakelock_platform_interface: - dependency: transitive - description: - name: wakelock_platform_interface - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.3.0" - wakelock_web: - dependency: transitive - description: - name: wakelock_web - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.4.0" - wakelock_windows: - dependency: transitive - description: - name: wakelock_windows - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.2.0" + version: "2.1.2" webview_flutter: dependency: "direct main" description: name: webview_flutter - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.8.0" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.8.3" + version: "2.8.14" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.9.1" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.7.1" + version: "2.9.1" win32: dependency: transitive description: name: win32 - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.7.0" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "0.2.0+1" xml: dependency: transitive description: name: xml - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "5.3.1" + version: "5.4.1" yaml: dependency: transitive description: name: yaml - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.1.1" sdks: - dart: ">=2.15.1 <3.0.0" - flutter: ">=2.10.0" + dart: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 08ebcb2..b5a520f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: wheretosleepinnju # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 3.2.4+51 +version: 3.3.3+53 environment: sdk: ">=2.12.0 <3.0.0" @@ -18,7 +18,7 @@ dependencies: shared_preferences: ^2.0.7 # Android iOS Linux macOS web Windows - flutter_swiper_null_safety: ^1.0.2 + flutter_swiper_null_safety_flutter3: ^2.0.0 # Android iOS Linux macOS web Windows scoped_model: ^2.0.0-nullsafety.0 # Android iOS Linux macOS web Windows @@ -33,11 +33,11 @@ dependencies: umeng_common_sdk: path: ./lib/Libs/umeng_common_sdk # Android iOS - qr_code_scanner: ^1.0.0 + qr_code_scanner: ^1.0.1 # Android iOS flutter_linkify: ^5.0.2 # Android iOS Linux macOS web Windows - image_picker: ^0.8.4 + image_picker: ^0.8.5+3 # Android iOS web # auto_size_text: ^3.0.0 # Android iOS Linux macOS web Windows @@ -50,7 +50,7 @@ dependencies: # 但是只用在 iOS package_info: ^2.0.2 # Android iOS macOS - flutter_html: ^2.1.3 + flutter_html: ^3.0.0-alpha.5 # Android iOS share_extend: ^2.0.0 # Android iOS @@ -62,9 +62,12 @@ dependencies: # Android iOS macOS html: ^0.15.0 # Android iOS Linux macOS web Windows - dio: ^4.0.0 + dio: ^4.0.6 # Android iOS Linux macOS web Windows +dependency_overrides: + scrollable_positioned_list: 0.3.2 + dev_dependencies: flutter_lints: ^1.0.4 flutter_test: