├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── src
├── main
│ └── java
│ │ └── moe
│ │ └── snowflake
│ │ └── jwSystem
│ │ ├── course
│ │ ├── Score.java
│ │ ├── CourseReview.java
│ │ ├── FormMap.java
│ │ └── Course.java
│ │ ├── utils
│ │ ├── SectionConstants.java
│ │ ├── PasswordUtil.java
│ │ ├── HttpUtil.java
│ │ └── CourseDataHandler.java
│ │ ├── manager
│ │ ├── CourseReviewManager.java
│ │ ├── URLManager.java
│ │ └── CourseSelectManager.java
│ │ └── JWSystem.java
└── test
│ └── java
│ ├── TestCourseReview.java
│ ├── TestMyCourse.java
│ ├── TestSelectCourse.java
│ └── TestLocalSelectCourse.java
├── .gitignore
├── LICENSE
├── README.md
├── gradlew.bat
└── gradlew
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = "JWSystem"
2 |
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowf14k3/JWSystemLib/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Dec 20 04:48:11 CST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.2-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/course/Score.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.course;
2 |
3 | /**
4 | * 优秀 良好 中等 合格 不合格
5 | * excellence favorable medium qualified unqualified
6 | */
7 | public enum Score {
8 | excellence,favorable,medium,qualified,unqualified
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/utils/SectionConstants.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.utils;
2 |
3 | public class SectionConstants {
4 | public static String ONE2TWO = "1-1-";
5 | public static String THREE = "3--";
6 | public static String FOUR2FIVE = "4-5-";
7 | public static String SIX2SEVEN = "6-7-";
8 | public static String EIGHT2NINE = "8-9-";
9 | public static String TEN2TTWELVE = "10-11-12";
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build/
3 | !gradle/wrapper/gradle-wrapper.jar
4 | !**/src/main/**/build/
5 | !**/src/test/**/build/
6 |
7 | ### IntelliJ IDEA ###
8 | .idea/modules.xml
9 | .idea/jarRepositories.xml
10 | .idea/compiler.xml
11 | .idea/libraries/
12 | *.iws
13 | *.iml
14 | *.ipr
15 | out/
16 | !**/src/main/**/out/
17 | !**/src/test/**/out/
18 |
19 | ### Eclipse ###
20 | .apt_generated
21 | .classpath
22 | .factorypath
23 | .project
24 | .settings
25 | .springBeans
26 | .sts4-cache
27 | bin/
28 | !**/src/main/**/bin/
29 | !**/src/test/**/bin/
30 |
31 | ### NetBeans ###
32 | /nbproject/private/
33 | /nbbuild/
34 | /dist/
35 | /nbdist/
36 | /.nb-gradle/
37 |
38 | ### VS Code ###
39 | .vscode/
40 |
41 | ### Mac OS ###
42 | .DS_Store
43 | /.idea/
44 | /.gradle/
45 | /build/
46 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/utils/PasswordUtil.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.utils;
2 |
3 | public class PasswordUtil {
4 |
5 | /**
6 | * 通过逆向网页js,用于教务处方式进入的教务系统登录.
7 | *
8 | * 新版的教务系统都用这个,但是可以用它更底层的登录方式进行登录
9 | * @param dataStr 服务端获取的加密密钥
10 | * @param code 账号%%%密码
11 | * @return encoded 的数据
12 | */
13 | @Deprecated
14 | public static String encodeUserData(String dataStr, String code) {
15 | StringBuilder encoded = new StringBuilder();
16 | String scode = dataStr.split("#")[0];
17 | String sxh = dataStr.split("#")[1];
18 |
19 | for (int i = 0; i < code.length(); i++) {
20 | if (i < 20) {
21 | int end = Integer.parseInt(sxh.substring(i, i + 1));
22 | encoded.append(code.charAt(i)).append(scode, 0, end);
23 | scode = scode.substring(end);
24 | } else {
25 | encoded.append(code.substring(i));
26 | i = code.length();
27 | }
28 | }
29 | return encoded.toString();
30 | }
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 AlphaAutoLeak
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/test/java/TestCourseReview.java:
--------------------------------------------------------------------------------
1 | import moe.snowflake.jwSystem.JWSystem;
2 | import moe.snowflake.jwSystem.course.CourseReview;
3 | import moe.snowflake.jwSystem.course.Score;
4 | import moe.snowflake.jwSystem.manager.URLManager;
5 | import org.junit.jupiter.api.Test;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class TestCourseReview {
11 |
12 |
13 | @Test
14 | public void testReview() {
15 | // 使用备用路线登录
16 | // URLManager.useLocalNetServer(1);
17 |
18 | // 记得选课前去查看,本学期的 zbid 是多少,否则显示的就是上一学期的课程
19 | // 浏览器url上就有
20 | JWSystem.zbID = "09EC4EAFA547423EA6494389B2729552";
21 |
22 | JWSystem system = new JWSystem().login("username", "password");
23 |
24 | // W.I.P
25 | if (system.isJWLogged()) {
26 | // 拿到全部可评价的
27 | List courseReviewList = system.getCourseReviewManager().getAllCourseReview();
28 |
29 | // 获取第一个进行评价
30 | system.getCourseReviewManager().review(courseReviewList.get(0), Score.excellence);
31 |
32 | system.exit();
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/course/CourseReview.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.course;
2 |
3 | public class CourseReview {
4 | private final int index ;
5 | private final String term;
6 |
7 | private final String type;
8 |
9 | private final String reviewBatch;
10 |
11 | private final String start;
12 | private final String end;
13 |
14 | private final String link;
15 |
16 | public CourseReview(int index, String term, String type, String reviewBatch, String start, String end, String link) {
17 | this.index = index;
18 | this.term = term;
19 | this.type = type;
20 | this.reviewBatch = reviewBatch;
21 | this.start = start;
22 | this.end = end;
23 | this.link = link;
24 | }
25 |
26 |
27 | public int getIndex() {
28 | return index;
29 | }
30 |
31 | public String getTerm() {
32 | return term;
33 | }
34 |
35 | public String getType() {
36 | return type;
37 | }
38 |
39 | public String getReviewBatch() {
40 | return reviewBatch;
41 | }
42 |
43 | public String getStart() {
44 | return start;
45 | }
46 |
47 | public String getEnd() {
48 | return end;
49 | }
50 |
51 | public String getLink() {
52 | return link;
53 | }
54 |
55 | @Override
56 | public String toString() {
57 | return "CourseReview{" +
58 | "序号=" + index +
59 | ", 学年学期='" + term + '\'' +
60 | ", 评价类型='" + type + '\'' +
61 | ", 评价批次='" + reviewBatch + '\'' +
62 | ", 开始时间='" + start + '\'' +
63 | ", 结束时间='" + end + '\'' +
64 | ", 评价链接='" + link + '\'' +
65 | '}';
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/utils/HttpUtil.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.utils;
2 |
3 | import org.jsoup.Connection;
4 | import org.jsoup.Jsoup;
5 |
6 | import java.util.Map;
7 |
8 | /**
9 | * 引入jsoup的库,搭建的简单util
10 | */
11 | public class HttpUtil {
12 | public static Connection.Response sendGet(String url) {
13 | try {
14 | return Jsoup.connect(url)
15 | .followRedirects(true)
16 | .execute();
17 | } catch (Exception e) {
18 | return null;
19 | }
20 | }
21 |
22 | public static Connection.Response sendGet(String url, Map headers) {
23 | try {
24 | return Jsoup.connect(url)
25 | .followRedirects(true)
26 | .headers(headers)
27 | .execute();
28 | } catch (Exception e) {
29 | return null;
30 | }
31 | }
32 |
33 | public static Connection.Response sendPost(String url, Map form) {
34 | try {
35 | return Jsoup.connect(url)
36 | .data(form)
37 | .method(Connection.Method.POST)
38 | .followRedirects(true)
39 | .execute().charset("UTF-8");
40 | } catch (Exception e) {
41 | return null;
42 | }
43 | }
44 |
45 | public static Connection.Response sendPost(String url, Map form, Map headers) {
46 | try {
47 | return Jsoup.connect(url)
48 | .data(form).method(Connection.Method.POST)
49 | .followRedirects(false)
50 | .headers(headers)
51 | .execute().charset("UTF-8");
52 | } catch (Exception e) {
53 | return null;
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/test/java/TestMyCourse.java:
--------------------------------------------------------------------------------
1 | import moe.snowflake.jwSystem.JWSystem;
2 | import moe.snowflake.jwSystem.course.Course;
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.io.IOException;
6 | import java.util.ArrayList;
7 | import java.util.Scanner;
8 |
9 | public class TestMyCourse {
10 |
11 | @Test
12 | public void test() throws IOException {
13 | // 记得选课前去查看,本学期的 zbid 是多少,否则显示的就是上一学期的课程
14 | // 浏览器url上就有
15 | JWSystem.zbID = "09EC4EAFA547423EA6494389B2729552";
16 | JWSystem system = new JWSystem().login("username", "password");
17 |
18 | if (system.isCourseLogged()) {
19 |
20 | System.out.println("当前课程查询结果: ");
21 | ArrayList courses = system.getCourseSelectManager().getCurrentCourses();
22 |
23 | for (int i = 0; i < courses.size(); i++) {
24 | Course course = courses.get(i);
25 | // 输出课程名称 老师 jxid
26 | System.out.printf("%s,%s,%s,%s%n", i+1,course.getName(), course.getTeacher(), course.getJxID());
27 | }
28 |
29 | // 进行退课操作
30 | Scanner sr = new Scanner(System.in);
31 | while (true) {
32 | int select = sr.nextInt() - 1;
33 | String reason = sr.next();
34 |
35 | if (select > 0 && select < courses.size()) {
36 | Course selected = courses.get(select);
37 | // 选择那个课程
38 | if (system.getCourseSelectManager().exitSelectedCourse(selected,reason)) {
39 | System.out.println(selected.getName() + " 退课成功");
40 | continue;
41 | }
42 | System.out.println("退课失败");
43 | } else if (select == -2) {
44 | // -1 取消选课
45 | break;
46 | }
47 | }
48 | //关闭流
49 | sr.close();
50 | // 退出系统
51 | system.exit();
52 | } else {
53 | System.err.println("登录失败");
54 | }
55 |
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JWSystem (W.I.P)
2 | _**这是一个支持 广科师(强智)教务系统实现 | 评教 | 查课 | 抢课| 退课 的第三方库**_
3 |
4 | ## 支持功能
5 | | 评教(大概率不会支持了) | 查课 | 抢课 | 退课 |
6 | |:------------:| :--: | :--: | :--: |
7 | | × | √ | √ | √ |
8 |
9 | ## 声明
10 | 1. 本项目使用 `MIT License`,根据协议允许您进行任意修改/发布/传播,且造成后果与本项目无关.
11 | 2. 特别感谢 JetBrains 与 JSoup 对这个项目的支持。
12 | 3. 本项目仅为实现教务系统一些功能,不提供编写好的程序.
13 | ---
14 |
15 | ## 代码引入
16 |
17 | 1. 你能够将此代码引入Android进行开发第三方的app
18 |
19 | 2. 甚至你能使用它编写小脚本在termux的模拟环境下实现
20 |
21 | 登录教务系统和选课等操作
22 |
23 | ```java
24 | public class Test{
25 |
26 | public static void main(String[] args) {
27 | // 使用内置内网第二条备用路线登录
28 | URLManager.useLocalNetServer(2);
29 |
30 | // 登录使用
31 | JWSystem system = new JWSystem().login("username", "password");
32 | // 直接通过搜索获取全部的网课
33 | ArrayList courses = system.getCourseSelectManager().getElectiveCourseByTeacher("网络课程");
34 | // 通过筛选获得course对象...
35 | system.getCourseSelectManager().selectCourse(courses.get(select));
36 | // 其他API...自行阅读代码
37 | }
38 |
39 |
40 | public static void setBaseURL(String baseURL){
41 | // 自个指定学校的jw系统地址
42 | // 也支持内网的url
43 | URLManager.BASE_URL = "http://jw.xxxx.edu.com";
44 | }
45 |
46 | /**
47 | * KCID 每年都一样
48 | * JXID 每年不固定
49 | * @param system 登录的instance
50 | */
51 | public static void selectCourseByCreate(JWSystem system){
52 | Course course = new Course("kcid","jxid");
53 |
54 | // 选择课程
55 | boolean statement = system.getCourseSelectManager().selectCourse(course);
56 |
57 | if (statement) {
58 | System.out.println("退课成功");
59 | } else {
60 | System.out.println("退课失败");
61 | }
62 |
63 | }
64 |
65 | }
66 | ```
67 |
68 | ## 例子
69 |
70 | 1. [选课](https://github.com/ciallo-dev/JWSystemLib/blob/master/src/test/java/TestSelectCourse.java) 例子1
71 | 2. [查已选课程退课](https://github.com/ciallo-dev/JWSystemLib/blob/master/src/test/java/TestMyCourse.java) 例子2
72 | 3. [学生课程评价](https://github.com/ciallo-dev/JWSystemLib/blob/master/src/test/java/TestCourseReview.java) 例子3
73 | 4. [各种请求的URL详解](https://github.com/ciallo-dev/JWSystemLib/blob/master/src/main/java/moe/snowflake/jwSystem/manager/URLManager.java) 预览
74 |
75 | ---
76 |
--------------------------------------------------------------------------------
/src/test/java/TestSelectCourse.java:
--------------------------------------------------------------------------------
1 | import moe.snowflake.jwSystem.JWSystem;
2 | import moe.snowflake.jwSystem.course.Course;
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Scanner;
7 |
8 | public class TestSelectCourse {
9 |
10 | @Test
11 | public void test() {
12 | // 记得选课前去查看,本学期的 zbid 是多少,否则显示的就是上一学期的课程
13 | // 浏览器url上就有
14 | JWSystem.zbID = "09EC4EAFA547423EA6494389B2729552";
15 |
16 | // 登录
17 | JWSystem system = new JWSystem().login("username", "password");
18 |
19 | // 检测两个系统是否都登录了
20 | if (system.isJWLogged()) {
21 | // 查找课程
22 | ArrayList courses = system.getCourseSelectManager().getAllElectiveCourse();
23 | // ArrayList courses = system.getCourseSelectManager().getElectiveCourseByTeacher("网络课程");
24 | // ArrayList courses = system.getCourseSelectManager().getAllRequiredList();
25 |
26 | for (int i = 0; i < courses.size(); i++) {
27 | Course course = courses.get(i);
28 | // System.out.printf("%s,%s,%s,%s,%s,%s,%s%n", course.getName(), course.getType(), course.getTeacher(), course.getKcid(), course.getJxID(), course.getScore(), course.getRemain());
29 | System.out.printf("序号 %d | 老师: %s | 课程名称: %s | 剩余数量: %s %n", i + 1, course.getTeacher(), course.getName(), course.getRemain());
30 | }
31 |
32 | Scanner sr = new Scanner(System.in);
33 | while (true) {
34 | int select = sr.nextInt() - 1;
35 |
36 | if (select > 0 && select < courses.size()) {
37 | Course selected = courses.get(select);
38 | // 选择那个课程
39 | if (system.getCourseSelectManager().selectCourse(selected)
40 | ) {
41 | System.out.println("选课成功 ");
42 | } else {
43 | System.out.println("选课失败");
44 | }
45 | } else if (select == -2) {
46 | // -1 取消选课
47 | break;
48 | }
49 | }
50 | //关闭流
51 | sr.close();
52 | system.exit();
53 | } else {
54 | System.out.println("error");
55 | }
56 |
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/course/FormMap.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.course;
2 |
3 | import java.util.LinkedHashMap;
4 |
5 | /**
6 | * 自定义表单类
7 | */
8 | public class FormMap extends LinkedHashMap {
9 |
10 | public FormMap() {
11 | }
12 |
13 | /**
14 | * @param sEcho 不知道
15 | * @param start 开始的 索引值
16 | * @param size 显示课程的个数
17 | */
18 | public void putRequiredFormData(String sEcho, int start, int size) {
19 | /*不知道是啥玩意*/
20 | this.put("sEcho", sEcho);
21 | /* 必修固定11列*/
22 | this.put("iColumns", "11");
23 | this.put("sColumns", "");
24 | this.put("iDisplayStart", String.valueOf(start));
25 | this.put("iDisplayLength", String.valueOf(size));
26 | /* 下面对应每列的数据 */
27 | this.put("mDataProp_0", "kch");
28 | this.put("mDataProp_1", "kcmc");
29 | this.put("mDataProp_2", "fzmc");
30 | this.put("mDataProp_3", "ktmc");
31 | this.put("mDataProp_4", "xf");
32 | this.put("mDataProp_5", "skls");
33 | this.put("mDataProp_6", "sksj");
34 | this.put("mDataProp_7", "skdd");
35 | this.put("mDataProp_8", "xqmc");
36 | this.put("mDataProp_9", "ctsm");
37 | this.put("mDataProp_10", "czOper");
38 | }
39 |
40 | /**
41 | * @param sEcho 不知道
42 | * @param start 开始的 索引值
43 | * @param size 显示课程的个数
44 | */
45 | public void putElectiveFormData(String sEcho, int start, int size) {
46 | /*不知道是啥玩意*/
47 | this.put("sEcho", sEcho);
48 | /* 选修固定13列*/
49 | this.put("iColumns", "13");
50 | this.put("sColumns", "");
51 | this.put("iDisplayStart", String.valueOf(start));
52 | this.put("iDisplayLength", String.valueOf(size));
53 | /* 下面对应每列的数据 */
54 | this.put("mDataProp_0", "kch");
55 | this.put("mDataProp_1", "kcmc");
56 | this.put("mDataProp_2", "xf");
57 | this.put("mDataProp_3", "skls");
58 | this.put("mDataProp_4", "sksj");
59 | this.put("mDataProp_5", "skdd");
60 | this.put("mDataProp_6", "xqmc");
61 | this.put("mDataProp_7", "xxrs");
62 | this.put("mDataProp_8", "xkrs");
63 | this.put("mDataProp_9", "syrs");
64 | this.put("mDataProp_10", "ctsm");
65 | this.put("mDataProp_11", "szkcflmc");
66 | this.put("mDataProp_12", "czOper");
67 | }
68 |
69 | public void putCourseReviewSave(){
70 | // W.I.P.
71 | }
72 |
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/test/java/TestLocalSelectCourse.java:
--------------------------------------------------------------------------------
1 | import moe.snowflake.jwSystem.JWSystem;
2 | import moe.snowflake.jwSystem.course.Course;
3 | import moe.snowflake.jwSystem.manager.CourseSelectManager;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import java.io.File;
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.Scanner;
11 |
12 | public class TestLocalSelectCourse {
13 |
14 |
15 | @Test
16 | public void loadLocalCourse(){
17 | List courses = CourseSelectManager.loadLocalCourse
18 | (new File("/courses.csv"));
19 |
20 | for (int i = 0; i < courses.size(); i++) {
21 | Course course = courses.get(i);
22 | // 输出课程名称 老师 jxid kcid
23 | System.out.printf("%s,%s,%s,%s,%s%n", i + 1, course.getName(), course.getTeacher(), course.getJxID(),course.getKcid());
24 | }
25 | }
26 |
27 | @Test
28 | public void test() {
29 | // 记得选课前去查看,本学期的 zbid 是多少,否则显示的就是上一学期的课程
30 | // 浏览器url上就有
31 | JWSystem.zbID = "09EC4EAFA547423EA6494389B2729552";
32 | JWSystem system = new JWSystem().login("username", "password");
33 |
34 | // 要求必须对选课系统进行登录
35 | // 否则选课系统不会返回任何数据
36 | if (system.isCourseLogged()) {
37 |
38 | List courses = CourseSelectManager.loadLocalCourse
39 | (new File("/courses.csv"));
40 |
41 | for (int i = 0; i < courses.size(); i++) {
42 | Course course = courses.get(i);
43 | // 输出课程名称 老师 jxid kcid
44 | System.out.printf("%s,%s,%s,%s,%s%n", i + 1, course.getName(), course.getTeacher(), course.getJxID(),course.getKcid());
45 | }
46 |
47 | Scanner sr = new Scanner(System.in);
48 | while (true) {
49 | int select = sr.nextInt() - 1;
50 |
51 | if (select > 0 && select < courses.size()) {
52 | Course selected = courses.get(select);
53 | // 选择那个课程
54 | if (system.getCourseSelectManager().selectCourse(selected)
55 | ) {
56 | System.out.println("选课成功 ");
57 | } else {
58 | System.out.println("选课失败");
59 | }
60 | } else if (select == -2) {
61 | // -1 取消选课
62 | break;
63 | }
64 | }
65 | //关闭流
66 | sr.close();
67 | // 退出系统
68 | system.exit();
69 | } else {
70 | System.err.println("登录失败");
71 | }
72 |
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/utils/CourseDataHandler.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.utils;
2 |
3 | import com.google.gson.*;
4 | import moe.snowflake.jwSystem.course.Course;
5 |
6 | import java.util.ArrayList;
7 |
8 | /**
9 | *
10 | * BACKUP DATA
11 | *
12 | *
13 | */
14 | public class CourseDataHandler {
15 |
16 | // 新建json
17 | public static Gson gson = new GsonBuilder().setPrettyPrinting().create();
18 |
19 | /**
20 | * 获取课程的全部个数
21 | * @param json 服务器返回json数据
22 | * @return
23 | */
24 | @Deprecated()
25 | public static String getTotalRecords(String json) {
26 | JsonObject jsonObject = gson.fromJson(json, JsonObject.class);
27 | return jsonObject.get("iTotalRecords").getAsString();
28 | }
29 |
30 | /**
31 | *
32 | * @param json 服务器返回json数据
33 | * @return 实例化为course列表
34 | */
35 | public static ArrayList getCourses(String json) {
36 | JsonObject jsonObject = gson.fromJson(json, JsonObject.class);
37 |
38 | ArrayList list = new ArrayList<>();
39 |
40 | if (!jsonObject.has("aaData")) {
41 | return list;
42 | }
43 |
44 | JsonArray jsonArray = jsonObject.get("aaData").getAsJsonArray();
45 | for (JsonElement jo : jsonArray.asList()) {
46 | JsonObject object = jo.getAsJsonObject();
47 |
48 | Course course = new Course();
49 | // KCID
50 | course.setKCID(object.get("jx02id").getAsString());
51 | // KCID2
52 | course.setJxID(object.get("jx0404id").getAsString());
53 | // 上课校区
54 | course.setArea(object.get("xqmc").getAsString());
55 | // 课程名
56 | course.setName(object.get("kcmc").getAsString());
57 | // 老师
58 | course.setTeacher(object.get("skls").getAsString());
59 |
60 | JsonElement remain = object.get("syrs");
61 | if (remain.isJsonNull()) {
62 | course.setRemain("9999");
63 | } else {
64 | course.setRemain(remain.getAsString());
65 | }
66 | // 剩余人数
67 |
68 | // 学分
69 | course.setScore(object.get("xf").getAsString());
70 | // 类型
71 | JsonElement type = object.get("szkcflmc");
72 | if (type.isJsonNull()) {
73 | course.setType("Required");
74 | course.setRequiredCourse(true);
75 | } else {
76 | course.setType(type.getAsString());
77 | course.setRequiredCourse(false);
78 | }
79 | // 添加进list里
80 | list.add(course);
81 | }
82 | return list;
83 | }
84 |
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/course/Course.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.course;
2 |
3 | public class Course {
4 | private String kcid;
5 | private String jxID;
6 | private String area;
7 | private String teacher;
8 | private String score;
9 | private String type;
10 | private String name;
11 |
12 | private int remain;
13 |
14 | private boolean isRequiredCourse;
15 |
16 | public Course(){
17 | }
18 |
19 | /**
20 | * 自行创建使用
21 | * @param kcid 课程ID
22 | * @param jxID jxID
23 | */
24 | public Course(String kcid, String jxID) {
25 | this.kcid = kcid;
26 | this.jxID = jxID;
27 | }
28 |
29 | /**
30 | *
31 | *
32 | * 参数默认值
33 | *
34 | * trjf: 投入积分
35 | *
36 | * xkzy: 选课志愿
37 | *
38 | * cfbs: null
39 | *
40 | * @param kcid 课程ID jx02id
41 | * @param jxID jxID jx0404id
42 | * @param teacher 老师 skls
43 | */
44 | public Course(String kcid, String jxID, String teacher) {
45 | this.kcid = kcid;
46 | this.jxID = jxID;
47 | this.teacher = teacher;
48 | }
49 |
50 | public boolean isRequiredCourse() {
51 | return isRequiredCourse;
52 | }
53 |
54 | public void setRequiredCourse(boolean requiredCourse) {
55 | isRequiredCourse = requiredCourse;
56 | }
57 |
58 | public void setKCID(String KCID) {
59 | this.kcid = KCID;
60 | }
61 |
62 | public void setJxID(String jxID) {
63 | this.jxID = jxID;
64 | }
65 |
66 | public void setArea(String area) {
67 | this.area = area;
68 | }
69 |
70 | public void setTeacher(String teacher) {
71 | this.teacher = teacher;
72 | }
73 |
74 | public void setScore(String score) {
75 | this.score = score;
76 | }
77 |
78 | public void setType(String type) {
79 | this.type = type;
80 | }
81 |
82 | public void setName(String name) {
83 | this.name = name;
84 | }
85 |
86 | public void setRemain(String remain) {
87 | this.remain = Integer.parseInt(remain);
88 | }
89 |
90 | public String getKcid() {
91 | return kcid;
92 | }
93 |
94 | public String getJxID() {
95 | return jxID;
96 | }
97 |
98 | public String getArea() {
99 | return area;
100 | }
101 |
102 | public String getTeacher() {
103 | return teacher.replace(",","&");
104 | }
105 |
106 | public String getScore() {
107 | return score;
108 | }
109 |
110 | public String getType() {
111 | return type;
112 | }
113 |
114 | public String getName() {
115 | return name;
116 | }
117 |
118 | public int getRemain() {
119 | return remain;
120 | }
121 |
122 | @Override
123 | public String toString() {
124 | return "Course{" +
125 | "kcid='" + kcid + '\'' +
126 | ", jxID='" + jxID + '\'' +
127 | ", area='" + area + '\'' +
128 | ", teacher='" + teacher + '\'' +
129 | ", score='" + score + '\'' +
130 | ", type='" + type + '\'' +
131 | ", name='" + name + '\'' +
132 | ", remain='" + remain + '\'' +
133 | '}';
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/manager/CourseReviewManager.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.manager;
2 |
3 | import moe.snowflake.jwSystem.JWSystem;
4 | import moe.snowflake.jwSystem.course.CourseReview;
5 | import moe.snowflake.jwSystem.course.Score;
6 | import moe.snowflake.jwSystem.utils.HttpUtil;
7 | import org.jsoup.Connection;
8 | import org.jsoup.nodes.Document;
9 | import org.jsoup.nodes.Element;
10 | import org.jsoup.select.Elements;
11 |
12 | import java.io.IOException;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | public class CourseReviewManager {
17 |
18 | private final JWSystem system;
19 |
20 |
21 | public CourseReviewManager(JWSystem system) {
22 | this.system = system;
23 | }
24 |
25 |
26 | public void review(CourseReview courseReview, Score score) {
27 | try {
28 | Connection.Response response = HttpUtil.sendGet(courseReview.getLink());
29 |
30 | if (response == null) {
31 | System.err.println("评价 " + courseReview.getTerm() + " 失败");
32 | return;
33 | }
34 | Document document = response.parse();
35 |
36 | // 因为只有一个table
37 | Element table = document.getElementsByTag("table").first();
38 | // wtf ?
39 | if (table == null) return;
40 | // 一个tr就是一行,就是一个评价科目
41 | Elements subjects = table.getElementsByTag("tr");
42 | // 不处理第一个
43 | for (int i = 1; i < subjects.size(); i++) {
44 | Element tr = subjects.get(i);
45 |
46 | // tr 下面还含有 td a
47 | Elements tdElements = tr.getElementsByTag("td");
48 | StringBuilder sb = new StringBuilder();
49 |
50 | for (Element td : tdElements) sb.append(td.ownText()).append(",");
51 |
52 | // 删除多余的 ,
53 | sb.delete(sb.length() - 2, sb.length() - 1);
54 | // 拿操作符号的a
55 | Elements aElements = tr.getElementsByTag("a");
56 | Element hrefElements = aElements.first();
57 |
58 | if (hrefElements != null) sb.append(URLManager.BASE_URL).append(hrefElements.attr("href"));
59 |
60 | // W.I.P.
61 | System.out.println(sb);
62 | }
63 | } catch (Exception e) {
64 | e.printStackTrace();
65 | }
66 |
67 | }
68 |
69 |
70 | /**
71 | * 查询目前已有学生课程评价
72 | *
73 | * @return 评价表格数据
74 | */
75 | public List getAllCourseReview() {
76 | Connection.Response response = HttpUtil.sendGet(URLManager.REVIEW_COURSE_FIND, this.system.headers);
77 |
78 | if (response == null) {
79 | throw new RuntimeException("network error....");
80 | }
81 |
82 | // 不读取 th 标签的数据
83 | StringBuilder sb = new StringBuilder();
84 |
85 | ArrayList courseReviews = new ArrayList<>();
86 |
87 | try {
88 | Document document = response.parse();
89 |
90 | // 依旧是拿table
91 | Elements elements = document.getElementsByTag("table");
92 |
93 | // 默认第一个table
94 | Element element = elements.first();
95 |
96 | if (element == null) {
97 | throw new RuntimeException("element not found document \n" + document.outerHtml());
98 | }
99 | // 再取tr 标签
100 | Elements trElements = element.getElementsByTag("tr");
101 |
102 | // 不读取第一个tr标签
103 | for (int i = 1; i < trElements.size(); i++) {
104 | Element tr = trElements.get(i);
105 |
106 | Elements tdElements = tr.getElementsByTag("td");
107 |
108 | for (Element td : tdElements) sb.append(td.ownText()).append(",");
109 | // 删除多余的 ,
110 | sb.delete(sb.length() - 2, sb.length() - 1);
111 |
112 | // 拿操作符号的a
113 | Elements aElements = tr.getElementsByTag("a");
114 | Element hrefElements = aElements.first();
115 |
116 | if (hrefElements != null) sb.append(URLManager.BASE_URL).append(hrefElements.attr("href"));
117 |
118 | String[] split = sb.toString().split(",");
119 | // 序号,学年学期,评价分类,评价批次,开始时间,结束时间
120 | courseReviews.add(new CourseReview(Integer.parseInt(split[0]), split[1], split[2], split[3], split[4], split[5], split[6]));
121 | }
122 | } catch (IOException e) {
123 | throw new RuntimeException("处理数据时发生异常");
124 | }
125 | return courseReviews;
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/JWSystem.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem;
2 |
3 |
4 | import moe.snowflake.jwSystem.manager.CourseSelectManager;
5 | import moe.snowflake.jwSystem.manager.CourseReviewManager;
6 | import moe.snowflake.jwSystem.manager.URLManager;
7 | import moe.snowflake.jwSystem.utils.HttpUtil;
8 | import moe.snowflake.jwSystem.utils.PasswordUtil;
9 | import org.jsoup.Connection;
10 | import org.jsoup.nodes.Element;
11 |
12 | import java.io.IOException;
13 | import java.util.*;
14 |
15 | public class JWSystem {
16 | public Connection.Response jwLoggedResponse;
17 | public Connection.Response courseSelectSystemResponse;
18 | public Map headers = new HashMap<>();
19 | private final boolean loginCourseSelectWeb;
20 | private final CourseSelectManager courseSelectManager;
21 | private final CourseReviewManager courseReviewManager;
22 |
23 | public JWSystem() {
24 | this(true);
25 | }
26 |
27 | public JWSystem(boolean loginCourseSelectWeb) {
28 | this.loginCourseSelectWeb = loginCourseSelectWeb;
29 | this.courseSelectManager = new CourseSelectManager(this);
30 | this.courseReviewManager = new CourseReviewManager(this);
31 | }
32 |
33 | /**
34 | * 判断教务是否登录成功
35 | *
36 | * @return 是否登录成功
37 | */
38 | public boolean isJWLogged() {
39 | try {
40 | if (this.jwLoggedResponse != null) {
41 | // 检测标题
42 | // 如果标题为登录即为登录失败
43 | if (this.jwLoggedResponse.parse().title().equals("登录")) return false;
44 | }
45 | } catch (Exception e) {
46 | return false;
47 | }
48 | return true;
49 | }
50 |
51 | /**
52 | * 判断选课系统是否登录成功
53 | *
54 | * @return 选课系统是否登录
55 | */
56 | public boolean isCourseLogged() {
57 | try {
58 | if (!this.isJWLogged() ||
59 | this.courseSelectSystemResponse == null) return false;
60 | this.courseSelectSystemResponse.parse();
61 | return !this.courseSelectSystemResponse.parse().title().contains("登录");
62 | } catch (IOException e) {
63 | return false;
64 | }
65 | }
66 |
67 | /**
68 | * 设置全局的 headers,包含cookie
69 | * jsoup设置的cookie无法识别
70 | *
71 | * @param cookie cookie
72 | */
73 | private void setHeaders(String cookie) {
74 | headers.put("Cookie", "JSESSIONID=" + cookie);
75 | }
76 |
77 | /**
78 | * 直接导向目标API的登录
79 | *
80 | * @param username 用户名
81 | * @param password 密码
82 | */
83 | public JWSystem login(String username, String password) {
84 | Map formData = new HashMap<>();
85 | formData.put("userAccount", username);
86 | formData.put("userPassword", "");
87 | // 很明显的两个base64加密
88 | formData.put("encoded", new String(Base64.getEncoder().encode(username.getBytes())) + "%%%" +
89 | new String(Base64.getEncoder().encode(password.getBytes())));
90 |
91 | // 登录成功的 响应
92 | Connection.Response response = HttpUtil.sendPost(URLManager.LOGIN, formData);
93 | if (response == null) {
94 | System.err.println("network error...");
95 | return this;
96 | }
97 | this.jwLoggedResponse = response;
98 | this.setHeaders(response.cookie("JSESSIONID"));
99 | this.loginCourseWeb();
100 | return this;
101 | }
102 |
103 | public static String zbID = "F17F6D4A35AF4EDA8727F42C3BCAF124";
104 |
105 | /**
106 | * 用于直接登录选课系统
107 | * 先登录学生选课系统,让后台存JSESSIONID
108 | * 并且设置登录成功的
109 | */
110 | public void loginCourseWeb() {
111 | // 是否登录选课系统
112 | if (isLoginCourseSelectWeb()) {
113 | this.courseSelectSystemResponse = HttpUtil.sendGet(URLManager.COURSE_LOGIN_WEB
114 | .replace("",zbID), this.headers);
115 |
116 | if (this.courseSelectSystemResponse == null) {
117 | System.out.println("network error !");
118 | return;
119 | }
120 |
121 | // 检测是否在选课时间内
122 | if (this.courseSelectSystemResponse.body().contains("时间范围")) this.courseSelectSystemResponse = null;
123 |
124 | }
125 | }
126 |
127 | /**
128 | * 更慢的登录
129 | *
130 | * @param username 账号
131 | * @param password 密码
132 | */
133 | @Deprecated
134 | public JWSystem login1(String username, String password) {
135 | Connection.Response keyGet = HttpUtil.sendGet(URLManager.LOGIN_DATA);
136 | if (keyGet == null || keyGet.statusCode() != 200) {
137 | System.err.println("network error");
138 | return this;
139 | }
140 | // 拿数据的
141 | String dataStr = keyGet.body();
142 |
143 | // 先检测他能否拿到加密数据的密钥
144 | if (dataStr.split("#").length < 2) {
145 | throw new RuntimeException("server or network error !");
146 | }
147 |
148 | // 获取加密后的密码数据
149 | String encoded = PasswordUtil.encodeUserData(dataStr, username + "%%%" + password);
150 | // 测试数据
151 |
152 | Map formData = new HashMap<>();
153 | formData.put("userAccount", "");
154 | formData.put("userPassword", "");
155 | formData.put("encoded", encoded);
156 |
157 | Connection.Response response = HttpUtil.sendPost(URLManager.LOGIN2, formData, this.headers);
158 |
159 | if (response == null) {
160 | throw new RuntimeException("network error !");
161 | }
162 |
163 | // 重定向到 URLManager.LOGIN2 + method= jwxt + ticqzket= token
164 | Connection.Response ref = HttpUtil.sendGet(response.header("Location"));
165 | // 登录成功分发 cookie
166 | this.jwLoggedResponse = ref;
167 |
168 | if (this.jwLoggedResponse != null) {
169 | this.setHeaders(ref.cookie("JSESSIONID"));
170 | this.loginCourseWeb();
171 | } else {
172 | System.err.println("response error....");
173 | }
174 | return this;
175 | }
176 |
177 | /**
178 | * 退出系统使用
179 | */
180 | public void exit() {
181 | // 退出选课系统
182 | if (isLoginCourseSelectWeb()) exitCourseSelect();
183 | // 退出JW整个系统
184 | Connection.Response exitAll = HttpUtil.sendGet(URLManager.EXIT_JWSYSTEM, this.headers);
185 |
186 | if (exitAll != null && this.isJWLogged()) {
187 | // 教务系统退出
188 | if (exitAll.body().contains("jsxsd")) System.out.println("退出教务系统成功");
189 | return;
190 | }
191 | System.err.println("unknown error !");
192 | }
193 |
194 | public void exitCourseSelect(){
195 | // 退出选课系统
196 | Connection.Response exitSelect = HttpUtil.sendGet(URLManager.EXIT_COURSE_WEB, this.headers);
197 | if (exitSelect != null) {
198 | // 退出选课系统的response body
199 | if (exitSelect.body().contains("true")) System.out.println("退出选课系统成功");
200 | // 教务系统退出
201 | return;
202 | }
203 | System.err.println("unknown error !");
204 | }
205 |
206 |
207 | public boolean isLoginCourseSelectWeb() {
208 | return this.loginCourseSelectWeb;
209 | }
210 |
211 | public CourseSelectManager getCourseSelectManager() {
212 | return courseSelectManager;
213 | }
214 |
215 | public CourseReviewManager getCourseReviewManager() {
216 | return courseReviewManager;
217 | }
218 |
219 | }
220 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/manager/URLManager.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.manager;
2 |
3 | public class URLManager {
4 | // ################### URL ###################
5 |
6 | /**
7 | * 使用内网服务器
8 | */
9 | public static void useLocalNetServer(int mode){
10 | switch (mode){
11 | case 1:
12 | BASE_URL = BACKUP_SERVER1;
13 | break;
14 | case 2:
15 | BASE_URL = BACKUP_SERVER2;
16 | break;
17 | case 3:
18 | BASE_URL = BACKUP_SERVER3;
19 | break;
20 | case 4:
21 | BASE_URL = BACKUP_SERVER4;
22 | default:
23 | System.err.println("error while switching backup server ..");
24 | break;
25 | }
26 | }
27 |
28 | /**
29 | * HOST地址
30 | */
31 | public static String BASE_URL = "https://jw.gxstnu.edu.cn";
32 |
33 | /**
34 | * 备用内网服务器1
35 | */
36 | public static String BACKUP_SERVER1 = "http://172.20.0.72:80";
37 |
38 | /**
39 | * 备用内网服务器2
40 | */
41 | public static String BACKUP_SERVER2 = "http://172.20.0.73:80";
42 |
43 | /**
44 | * 备用内网服务器3
45 | */
46 | public static String BACKUP_SERVER3 = "http://172.20.0.74:80";
47 |
48 | /**
49 | * 备用内网服务器4
50 | */
51 | public static String BACKUP_SERVER4 = "http://172.20.0.75:80";
52 |
53 | /**
54 | * METHOD:GET
55 | *
56 | * 登录加密密钥
57 | */
58 | public static String LOGIN_DATA = BASE_URL + "/Logon.do?method=logon&flag=sess";
59 | /**
60 | * METHOD:POST
61 | *
62 | * 登录教务系统请求
63 | */
64 | public static String LOGIN2 = BASE_URL + "/Logon.do?method=logon";
65 | /**
66 | * METHOD:POST
67 | *
68 | * 使用 BASE64的登录数据
69 | */
70 | public static String LOGIN = BASE_URL + "/jsxsd/xk/LoginToXk";
71 |
72 | /**
73 | * METHOD:GET
74 | *
75 | * 登录选课系统
76 | */
77 | public static String COURSE_LOGIN_WEB = BASE_URL + "/jsxsd/xsxk/xsxk_index?jx0502zbid=";
78 |
79 | /**
80 | * METHOD:GET
81 | * 退课
82 | */
83 | public static String EXIT_COURSE = BASE_URL + "/jsxsd/xsxkjg/xstkOper?jx0404id=&tkyy=";
84 |
85 | /**
86 | * METHOD:GET
87 | *
88 | * 退出教务系统
89 | */
90 | public static String EXIT_JWSYSTEM = BASE_URL + "/jsxsd/xk/LoginToXk?method=exit&tktime=" + System.currentTimeMillis();
91 | /**
92 | * METHOD:GET
93 | *
94 | * 退出选课系统
95 | */
96 | public static String EXIT_COURSE_WEB = BASE_URL + "/jsxsd/xsxk/xsxk_exit?jx0404id=1";
97 |
98 | /**
99 | * METHOD:POST
100 | *
101 | * * 参数
102 | *
103 | * kcxx 课程名称
104 | *
105 | * xx课 格式
106 | *
107 | *
108 | * =============================================
109 | * skls 授课老师
110 | *
111 | * xx老师 格式 url encode x2
112 | *
113 | * =============================================
114 | * skjc 节次 (需要同时选择上课星期)
115 | *
116 | * 1-2- 1-2节
117 | *
118 | * 3-- 3节
119 | *
120 | * 4-5- 4-5节
121 | *
122 | * 6-7- 6-7节
123 | *
124 | * 8-9- 8-9节
125 | *
126 | * 10-11-12 10-12杰
127 | *
128 | * =============================================
129 | * skxq 上课星期
130 | *
131 | * 1-7 表示 星期一 ~ 星期天
132 | * =============================================
133 | * sfym 过滤已满课程
134 | *
135 | * false 默认值
136 | *
137 | * =============================================
138 | * sfct 过滤冲突课程
139 | *
140 | * false 默认值
141 | *
142 | * =============================================
143 | * szjylb 类别索引
144 | *
145 | * 17 德育教育类
146 | *
147 | * 14 美育教育类
148 | *
149 | * 13 教师教育类
150 | *
151 | * 12 语言应用类
152 | *
153 | * 10 英语应用
154 | *
155 | * 9 其他
156 | *
157 | * 8 汉语应用
158 | *
159 | * 7 公共艺术
160 | *
161 | * 6 综合素质
162 | *
163 | * 5 四史教育类
164 | *
165 | * 4 身心素质类
166 | *
167 | * 3 社会素养类
168 | *
169 | * 2 科学素养类
170 | *
171 | * 1 人文素养类
172 | *
173 | * 空白 显示全部课程
174 | *
175 | * =============================================
176 | * sfxx 过滤限选课程
177 | *
178 | * true 默认值
179 | * =============================================
180 | * 表单数据
181 | * xxx 默认值 解释
182 | * =============================================
183 | * sEcho: 2
184 | *
185 | * iColumns: 13 列数
186 | *
187 | * sColumns: ""
188 | *
189 | * iDisplayStart: 0
190 | *
191 | * iDisplayLength: 15 一页显示15个
192 | *
193 | * mDataProp_0: kch 课程号
194 | *
195 | * mDataProp_2: kcmc 课程名称
196 | *
197 | * mDataProp_2: xf 学分
198 | *
199 | * mDataProp_3: skls 授课老师
200 | *
201 | * mDataProp_4 sksj 授课时间
202 | *
203 | * mDataProp_5 skdd 授课地点
204 | *
205 | * mDataProp_6 sqxq 上课校区
206 | *
207 | * mDataProp_7 xxrs 限选人数
208 | *
209 | * mDataProp_8 xkrs 选课人数
210 | *
211 | * mDataProp_9 syrs 剩余人数
212 | *
213 | * mDataProp_10 ctsm 时间冲突
214 | *
215 | * mDataProp_11 szkcflmc 类别
216 | *
217 | * mDataProp_12 czOper 选课操作的按钮
218 | *
219 | * iTotalRecords 178 总记录
220 | *
221 | * =============================================
222 | * backup
223 | * kcxx=&skls=&skxq=&skjc=&sfym=false&sfct=false&szjylb=&sfxx=true
224 | */
225 | public static String ELECTIVE_COURSE_LIST = BASE_URL + "/jsxsd/xsxkkc/yl_xsxkGgxxkxk";
226 | /**
227 | * METHOD:POST
228 | *
229 | * * 参数
230 | *
skxq_xx0103
231 | *
232 | * 1 北校区
233 | *
234 | * 2 南校区
235 | *
236 | * 3 来宾校区
237 | *
238 | * ==================================
239 | *
240 | * 请参考选修LIST
241 | *
242 | * sEcho: 1
243 | *
244 | * iColumns: 11 列数
245 | *
246 | * sColumns:
247 | *
248 | * iDisplayStart: 0
249 | *
250 | * iDisplayLength: 15
251 | *
252 | * mDataProp_0: kch
253 | *
254 | * mDataProp_1: kcmc
255 | *
256 | * mDataProp_2: fzmc
257 | *
258 | * mDataProp_3: ktmc
259 | *
260 | * mDataProp_4: xf
261 | *
262 | * mDataProp_5: skls
263 | *
264 | * mDataProp_6: sksj
265 | *
266 | * mDataProp_7: skdd
267 | *
268 | * mDataProp_8: xqmc
269 | *
270 | * mDataProp_9: ctsm
271 | *
272 | * mDataProp_10: czOper
273 | */
274 | public static String REQUIRED_COURSE_LIST = BASE_URL + "/jsxsd/xsxkkc/xsxkBxxk?skxq_xx0103=";
275 |
276 | /**
277 | * METHOD:GET
278 | *
279 | * * 选课操作
280 | *
281 | * ==================================
282 | *
283 | * kcid(jx02id) 课程ID
284 | *
285 | * jx0404id 不知道是什么id
286 | *
287 | * ==================================
288 | *
289 | * replace以下两个参数
290 | *
291 | *
292 | *
293 | *
294 | *
295 | * response :
296 | *
297 | * {"success":true,"message":"选课成功","jfViewStr":""}
298 | *
299 | */
300 | public static String ELECTIVE_COURSE_SELECT = BASE_URL + "/jsxsd/xsxkkc/ggxxkxkOper?kcid=&cfbs=null&jx0404id=&xkzy=&trjf=";
301 |
302 | /**
303 | * METHOD:GET
304 | *
305 | * 选课操作
306 | *
307 | * ==================================
308 | *
309 | * kcid(jx02id) 课程ID
310 | *
311 | * jx0404id 不知道是什么id
312 | *
313 | * ==================================
314 | *
315 | * replace以下两个参数
316 | *
317 | *
318 | *
319 | *
320 | *
321 | * response :
322 | *
323 | * {"success":true,"message":"选课成功","jfViewStr":""}
324 | *
325 | */
326 | public static String REQUIRED_COURSE_SELECT = BASE_URL + "/jsxsd/xsxkkc/bxxkOper?kcid=&cfbs=null&jx0404id=&xkzy=&trjf=";
327 |
328 | /**
329 | * METHOD:GET
330 | *
331 | * 现在当前课程的列表
332 | */
333 | public static String MY_COURSE_LIST = BASE_URL + "/jsxsd/xsxkjg/comeXkjglb";
334 |
335 | /**
336 | * METHOD:GET
337 | *
338 | * 查找有哪些课程可评价
339 | */
340 | public static String REVIEW_COURSE_FIND = BASE_URL + "/jsxsd/xspj/xspj_find.do";
341 |
342 | /**
343 | * METHOD:POST
344 | *
345 | * 提交评课数据
346 | */
347 | public static String REVIEW_COURSE_SAVE = BASE_URL + "/jsxsd/xspj/xspj_save.do";
348 |
349 | }
350 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/src/main/java/moe/snowflake/jwSystem/manager/CourseSelectManager.java:
--------------------------------------------------------------------------------
1 | package moe.snowflake.jwSystem.manager;
2 |
3 | import moe.snowflake.jwSystem.JWSystem;
4 | import moe.snowflake.jwSystem.course.Course;
5 | import moe.snowflake.jwSystem.course.FormMap;
6 | import moe.snowflake.jwSystem.utils.CourseDataHandler;
7 | import moe.snowflake.jwSystem.utils.HttpUtil;
8 | import org.jsoup.Connection;
9 | import org.jsoup.nodes.Document;
10 | import org.jsoup.nodes.Element;
11 | import org.jsoup.select.Elements;
12 |
13 | import java.io.File;
14 | import java.io.IOException;
15 | import java.nio.file.Files;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 | import java.util.stream.Stream;
19 |
20 | public class CourseSelectManager {
21 | private final JWSystem system;
22 |
23 |
24 | public CourseSelectManager(JWSystem system) {
25 | this.system = system;
26 | }
27 |
28 | /**
29 | * 获取自己已选课程的List
30 | *
31 | * @return 课程列表
32 | */
33 | public ArrayList getCurrentCourses() throws IOException {
34 | ArrayList list = new ArrayList<>();
35 | Connection.Response response = HttpUtil.sendGet(URLManager.MY_COURSE_LIST, this.system.headers);
36 |
37 | if (response == null) {
38 | throw new RuntimeException("response was null");
39 | }
40 |
41 | // 返回值转化成Document
42 | Document document = response.parse();
43 |
44 | Elements elements = document.getElementsByTag("table");
45 | // 只有一个table
46 | Element element = elements.first();
47 |
48 | if (element == null) {
49 | throw new RuntimeException("element not found !");
50 | }
51 |
52 | // 获取全部tr tag的标签下的子元素
53 | Elements trElements = element.getElementsByTag("tr");
54 | for (Element tr : trElements) {
55 | Elements tdElements = tr.getElementsByTag("td");
56 | // 必定大于 5
57 | // 这边不处理顶部的th元素检测
58 | if (tdElements.size() < 5) {
59 | continue;
60 | }
61 | Course course = new Course();
62 |
63 | // 固定顺序
64 | course.setName(tdElements.get(1).ownText());
65 | course.setTeacher(tdElements.get(4).ownText());
66 |
67 | Element kcidElement = tr.getElementsByTag("a").first();
68 |
69 | if (kcidElement == null) {
70 | continue;
71 | }
72 |
73 | // 通过replaceKCID
74 | String JXID = kcidElement.attr("href")
75 | .replace("');", "")
76 | .replace("javascript:xstkOper('", "");
77 | course.setJxID(JXID);
78 | list.add(course);
79 | }
80 | return list;
81 | }
82 |
83 | /**
84 | * 获取当前已选选修课
85 | * 横向排列,无格式化
86 | */
87 | public String getCurrentCoursesStr() {
88 | Connection.Response response = HttpUtil.sendGet(URLManager.MY_COURSE_LIST, this.system.headers);
89 |
90 | // 是否响应异常
91 | if (response == null) {
92 | throw new RuntimeException("response was null");
93 | }
94 |
95 | try {
96 | // 返回值转化成Document
97 | Document document = response.parse();
98 |
99 | Elements elements = document.getElementsByTag("table");
100 | // 只有一个table
101 | Element element = elements.first();
102 |
103 | if (element == null) {
104 | throw new RuntimeException("element not found !");
105 | }
106 |
107 | // 获取全部tr tag的标签下的子元素
108 | Elements trElements = element.getElementsByTag("tr");
109 |
110 | StringBuilder result = new StringBuilder();
111 | for (Element tr : trElements) {
112 | // 拿三个
113 | Elements thElements = tr.getElementsByTag("th");
114 | Elements tdElements = tr.getElementsByTag("td");
115 |
116 | // 判断是否为课程详细的行
117 | if (!tdElements.isEmpty()) {
118 | // 循环课程表的具体信息
119 | for (Element td : tdElements) {
120 | result.append(td.ownText()).append(" ");
121 | }
122 | }
123 |
124 | if (!thElements.isEmpty()) {
125 | // 循环课程表上的信息
126 | for (Element th : thElements) {
127 | result.append(th.ownText()).append(" ");
128 | }
129 | }
130 | result.append("\n");
131 | }
132 | return result.toString();
133 | } catch (Exception e) {
134 | return "error";
135 | }
136 | }
137 |
138 | /**
139 | * 退出自己已选课程,建议搭配getCurrentCourses()使用.
140 | *
141 | * {"success": true}
142 | *
143 | * {"success":false,"message":"退课失败:此课堂未开放,不能进行退课!"}
144 | *
145 | *
146 | * @param course 课程实例
147 | * @param reason 退课原因
148 | */
149 | public boolean exitSelectedCourse(Course course, String reason) {
150 | Connection.Response exitSelectResponse = HttpUtil.sendGet(URLManager.EXIT_COURSE
151 | .replace("", course.getJxID())
152 | .replace("", reason), this.system.headers);
153 |
154 | if (exitSelectResponse == null) {
155 | return false;
156 | }
157 | // 退出选课判断
158 | return exitSelectResponse.body().contains("true");
159 | }
160 |
161 |
162 | /**
163 | * 选择公共必修课
164 | *
165 | * 选择公共选修课
166 | * @param course 课程的对象
167 | */
168 | public boolean selectCourse(Course course) {
169 | return course.isRequiredCourse() ? selectCourse(URLManager.REQUIRED_COURSE_SELECT, course) :
170 | selectCourse(URLManager.ELECTIVE_COURSE_SELECT, course);
171 | }
172 |
173 | /**
174 | * @param url 选课的 URL
175 | * @param course 课程的id
176 | */
177 | private boolean selectCourse(String url, Course course) {
178 |
179 | // 得事先登录学生选课系统,让后台存JSESSIONID
180 | Connection.Response response = HttpUtil.sendGet(url
181 | .replace("", course.getKcid())
182 | .replace("", course.getJxID()), this.system.headers);
183 |
184 | //response
185 | // {"success":true,"message":"选课成功","jfViewStr":""}
186 | // {"success":[true,false],"message":"选课失败:此课堂选课人数已满!"}
187 | // {"success":false,"message":"选课失败:当前教学班已选择!"}
188 |
189 | // 必修课
190 | //{"success":false,"message":"选课失败:当前课程已选择其它教学班!"}
191 |
192 | if (response == null) {
193 | return false;
194 | }
195 | return !response.body().contains("false");
196 | }
197 |
198 | /**
199 | * 列出全部必修课,理论上必修选课最多课程不超过30个
200 | */
201 | public ArrayList getAllRequiredList() {
202 | return searchRequiredList(30);
203 | }
204 |
205 | /**
206 | * 列出必修课的列表
207 | *
208 | * @param size 显示课程大小
209 | */
210 | public ArrayList searchRequiredList(int size) {
211 | FormMap formMap = new FormMap();
212 | formMap.putRequiredFormData("3", 0, size);
213 |
214 | Connection.Response response = HttpUtil.sendPost(URLManager.REQUIRED_COURSE_LIST, formMap, this.system.headers);
215 |
216 | if (response != null) {
217 | return CourseDataHandler.getCourses(response.body());
218 | }
219 |
220 | return new ArrayList<>();
221 | }
222 |
223 | /**
224 | * @param courseName 课程名称
225 | * @param teacher 授课老师
226 | * @param week 星期
227 | * @param section 节次
228 | * @param removeFull 过滤已满课程
229 | * @param removeConflict 过滤冲突课程
230 | * @param loc 过滤限选课程
231 | * @param size 显示数量
232 | */
233 | public ArrayList searchElectiveList(String courseName, String teacher, int week, String section, boolean removeFull, boolean removeConflict, String courseType, boolean loc, int size) {
234 | FormMap formMap = new FormMap();
235 |
236 | String weekStr = "";
237 | if (week != 0) {
238 | weekStr = String.valueOf(week);
239 | }
240 |
241 | formMap.putElectiveFormData("3", 0, size);
242 |
243 | // 查询的参数
244 | String args = "?kcxx=" + courseName + "&skls=" + teacher + "&skxq=" + weekStr + "&skjc=" + section + "&sfym=" + removeFull + "&sfct=" + removeConflict + "&szjylb=" + courseType + "&sfxx=" + loc;
245 |
246 |
247 | Connection.Response response = HttpUtil.sendPost(URLManager.ELECTIVE_COURSE_LIST + args, formMap, this.system.headers);
248 | if (response != null) {
249 | String json = response.body();
250 | return CourseDataHandler.getCourses(json);
251 | }
252 | // 如果是网络原因返回空
253 | return new ArrayList<>();
254 | }
255 |
256 | /**
257 | * 获取全部公共选修课列表
258 | */
259 | public ArrayList getAllElectiveCourse() {
260 | return this.searchElectiveList("", "", 0, "", false, false, "", true, 200);
261 | }
262 |
263 | /**
264 | * 通过课程名称获取课程
265 | *
266 | * @param courseName 课程名称
267 | */
268 | public ArrayList getElectiveCourseByName(String courseName) {
269 | return this.searchElectiveList(courseName, "", 0, "", false, false, "", true, 200);
270 | }
271 |
272 | /**
273 | * 通过老师名称搜索课程,支持模糊搜索
274 | *
275 | * @param teacher 老师名称
276 | */
277 | public ArrayList getElectiveCourseByTeacher(String teacher) {
278 | return this.searchElectiveList("", teacher, 0, "", false, false, "", true, 200);
279 | }
280 |
281 | /**
282 | * 按照时间搜索课程
283 | *
284 | * @param week 星期
285 | * @param section 节次
286 | * @return 筛选出的课程
287 | */
288 | public ArrayList getElectiveCourseByWeek(int week, String section) {
289 | return this.searchElectiveList("", "", week, section, false, false, "", true, 200);
290 | }
291 |
292 | /**
293 | * @param removeFull 过滤已满课程
294 | * @param removeConflict 过滤冲突课程
295 | * @param loc 过滤限选课程
296 | * @return 筛选出的课程
297 | */
298 | public ArrayList getElectiveCourseByStatement(boolean removeFull, boolean removeConflict, boolean loc) {
299 | return this.searchElectiveList("", "", 0, "", removeFull, removeConflict, "", loc, 200);
300 | }
301 |
302 | /**
303 | * 通过本地文件读取课程信息,达到控制台直接选课
304 | * 格式:一行为一个课程 使用 ' , ' 进行分割,
305 | *
0 -> 课程名称
306 | *
1 -> 课程类型
307 | *
2 -> 授课老师
308 | *
3 -> kcid
309 | *
4 -> jxid
310 | *
311 | * @param file
312 | */
313 | public static List loadLocalCourse(File file){
314 | ArrayList courses = new ArrayList<>();
315 | try (Stream stream = Files.lines(file.toPath())){
316 | stream.forEach(line ->{
317 | String[] c = line.split(",");
318 |
319 | Course course = new Course(c[3],c[4]);
320 |
321 | // 课程名称
322 | course.setName(c[0]);
323 |
324 | // 课程类型
325 | course.setType(c[1]);
326 |
327 | // 授课老师
328 | course.setTeacher(c[2]);
329 |
330 | courses.add(course);
331 | });
332 | } catch (IOException e) {
333 | throw new RuntimeException(e);
334 | }
335 | return courses;
336 | }
337 |
338 |
339 | }
340 |
--------------------------------------------------------------------------------