diff --git a/docs/other.md b/docs/other.md
index 256ee7374..595e1921a 100644
--- a/docs/other.md
+++ b/docs/other.md
@@ -782,7 +782,9 @@ type 为 all 时,category 参数不支持 cost 和 free
### 专题
+
此为专题广场更新提示=>集合型而非单篇文章.与下方"专题内文章更新"存在明显区别!
+
### 专题内文章更新
@@ -960,6 +962,50 @@ type 为 all 时,category 参数不支持 cost 和 free
+## 学堂在线
+
+### 课程信息
+
+
+
+课程信息类型
+
+| 课程开始时间 | 课程结束时间 | 课程进度 |
+| ------------ | ------------ | -------- |
+| start | end | status |
+
+
+
+### 课程列表
+
+
+
+课程模式
+
+| 自主 | 随堂 | 付费 | 全部 |
+| ---- | ---- | ---- | ---- |
+| 0 | 1 | 2 | -1 |
+
+课程状态
+
+| 即将开课 | 已开课 | 已结课 | 全部 |
+| -------- | ------ | ------ | ---- |
+| 1 | 2 | 3 | -1 |
+
+课程认证类型
+
+| 签字认证 | 认证开放 | 全部 |
+| -------- | -------- | ---- |
+| 1 | 2 | -1 |
+
+学科分类
+
+| 全部 | 计算机 | 经管·会计 | 创业 | 电子 | 工程 | 环境·地球 | 医学·健康 | 生命科学 | 数学 | 物理 | 化学 | 社科·法律 | 文学 | 历史 | 哲学 | 艺术·设计 | 外语 | 教育 | 其他 | 大学先修课 | 公共管理 | 建筑 | 职场 | 全球胜任力 |
+| ---- | ------ | --------- | ---- | ---- | ---- | --------- | --------- | -------- | ---- | ---- | ---- | --------- | ---- | ---- | ---- | --------- | ---- | ---- | ---- | ---------- | -------- | ---- | ---- | ---------- |
+| -1 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 201 | 2550 | 2783 | 2952 | 6200 |
+
+
+
## 异次元软件世界
### 首页
diff --git a/lib/router.js b/lib/router.js
index 56470d9d0..42ebc8742 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1538,4 +1538,8 @@ router.get('/afdian/dynamic/:uid', require('./routes/afdian/dynamic'));
// 《明日方舟》游戏
router.get('/arknights/news', require('./routes/arknights/news'));
+// 学堂在线
+router.get('/xuetangx/course/:cid/:type', require('./routes/xuetangx/course_info'));
+router.get('/xuetangx/course/list/:mode/:credential/:status/:type?', require('./routes/xuetangx/course_list'));
+
module.exports = router;
diff --git a/lib/routes/xuetangx/course_info.js b/lib/routes/xuetangx/course_info.js
new file mode 100644
index 000000000..108447e5d
--- /dev/null
+++ b/lib/routes/xuetangx/course_info.js
@@ -0,0 +1,51 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const { cid, type } = ctx.params;
+ const link = `http://www.xuetangx.com/courses/${cid}/about`;
+ const res = await got(link);
+ const $ = cheerio.load(res.data);
+
+ const courseTitle = $('#title1').text();
+ const infoTag = $('#course_data');
+ let title,
+ description = '',
+ startTime,
+ endTime,
+ status;
+ switch (type) {
+ case 'start':
+ title = '开课时间';
+ startTime = infoTag.attr('data-start');
+ description = `开课时间: ${startTime ? new Date(startTime).toUTCString() : '暂无'}`;
+ break;
+ case 'end':
+ title = '结课时间';
+ endTime = infoTag.attr('data-end');
+ description = `结课时间: ${endTime ? new Date(endTime).toUTCString() : '永久开课'}`;
+ break;
+ case 'status':
+ title = '课程进度';
+ status = infoTag.attr('data-serialized');
+ description = `课程进度: ${Number(status) > -1 ? `连载至第${status}讲` : '暂无'}`;
+ break;
+ }
+ const item = [];
+ if (title && description) {
+ item.push({
+ title,
+ description,
+ link,
+ guid: description,
+ });
+ }
+
+ ctx.state.data = {
+ title: `${courseTitle} - ${title}`,
+ description: `${courseTitle} - ${title}`,
+ link,
+ item,
+ allowEmpty: true,
+ };
+};
diff --git a/lib/routes/xuetangx/course_list.js b/lib/routes/xuetangx/course_list.js
new file mode 100644
index 000000000..ab7935208
--- /dev/null
+++ b/lib/routes/xuetangx/course_list.js
@@ -0,0 +1,57 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const { type = '', credential, mode, status } = ctx.params;
+ const baseUrl = 'http://www.xuetangx.com';
+ const link = `${baseUrl}/courses`;
+ const query = {
+ page_type: type,
+ course_mode: mode,
+ process: status,
+ credential,
+ };
+ Object.keys(query).forEach((key) => Number(query[key]) === -1 && (query[key] = ''));
+ const res = await got(link, {
+ query,
+ });
+ const $ = cheerio.load(res.data);
+
+ const item = $('#list_style .list_inner')
+ .map((_, node) => {
+ const $item = cheerio.load(node);
+ const title = $item('.coursetitle').text();
+ const link = `${baseUrl}${$item('.coursename > a').attr('href')}`;
+ const posterImg = baseUrl + $item('.course-cover').attr('src');
+ const baseInfo = $item('.coursename_ref')
+ .text()
+ .trim()
+ .replace(/\s+/g, '/');
+ const teacherInfo = $item('div.fl.name > ul > li:nth-child(1)').text();
+ const extraInfo = $item('div.fl.name > ul > li:nth-child(2)')
+ .text()
+ .replace('$', '');
+ const description = `
+ ${baseInfo}
+ ${teacherInfo}
+ ${extraInfo}
+ ${$item('.txt')}
+ ${$item('.ctxt')}
+ 
+ `;
+ return {
+ title,
+ link,
+ description,
+ };
+ })
+ .get();
+
+ ctx.state.data = {
+ title: `学堂在线-课程列表`,
+ description: `学堂在线-课程列表`,
+ link,
+ item,
+ allowEmpty: true,
+ };
+};