diff --git a/docs/university.md b/docs/university.md
index 586b7eb67e..014c88bdb5 100644
--- a/docs/university.md
+++ b/docs/university.md
@@ -748,6 +748,16 @@ https://rsshub.app/**nuist**/`bulletin` 或 https://rsshub.app/**nuist**/`bullet
+### 教务处通知公告(全文输出)
+
+
+
+| 面向学生的通知 | 新闻中心 | 通知通告 | 教学运行 | 注册学务 | 研究办 | 教改办 | 综合办 | 工会与支部 |
+| -------------- | -------- | -------- | --------- | -------- | ------ | ------ | ------ | ---------- |
+| students | news | notice | operation | affairs | yjb | jgb | zhb | party |
+
+
+
## 上海科技大学
### 信息科技与技术学院活动
diff --git a/lib/router.js b/lib/router.js
index d4f1e31d00..5cba2976e0 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -558,6 +558,7 @@ router.get('/sjtu/seiee/bjwb/:type', require('./routes/universities/sjtu/seiee/b
router.get('/sjtu/seiee/xsb/:type?', require('./routes/universities/sjtu/seiee/xsb'));
router.get('/sjtu/gs/tzgg/:type?', require('./routes/universities/sjtu/gs/tzgg'));
+router.get('/sjtu/jwc/:type?', require('./routes/universities/sjtu/jwc'));
// 江南大学
router.get('/ju/jwc/:type?', require('./routes/universities/ju/jwc'));
diff --git a/lib/routes/universities/sjtu/jwc.js b/lib/routes/universities/sjtu/jwc.js
new file mode 100644
index 0000000000..e8c4bb826b
--- /dev/null
+++ b/lib/routes/universities/sjtu/jwc.js
@@ -0,0 +1,119 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const url = require('url');
+const iconv = require('iconv-lite');
+
+const urlRoot = 'http://www.jwc.sjtu.edu.cn/web/sjtu/';
+
+const transcode = (buffer) => {
+ const data = iconv.decode(buffer, 'gb2312');
+ return cheerio.load(data);
+};
+
+async function getFullArticle(link) {
+ try {
+ const response = await got({
+ method: 'get',
+ url: link,
+ responseType: 'buffer',
+ });
+ const fullArtData = transcode(response.data);
+ const fullArt = fullArtData('.main_r_co_fo').html();
+ return fullArt;
+ } catch (error) {
+ return '
这条消息被 -1s 了
';
+ }
+}
+
+module.exports = async (ctx) => {
+ const type = ctx.params.type || 'students';
+ const config = {
+ students: {
+ link: '198076.htm',
+ section: '面向学生的通知',
+ },
+ news: {
+ link: '198005.htm',
+ section: '新闻中心',
+ },
+ notice: {
+ link: '198392.htm',
+ section: '通知通告',
+ },
+ operation: {
+ link: '198042.htm',
+ section: '教学运行',
+ },
+ affairs: {
+ link: '198043.htm',
+ section: '注册学务',
+ },
+ yjb: {
+ link: '198044.htm',
+ section: '研究办',
+ },
+ jgb: {
+ link: '198046.htm',
+ section: '教改办',
+ },
+ zhb: {
+ link: '198047.htm',
+ section: '综合办',
+ },
+ party: {
+ link: '198097.htm',
+ section: '工会与支部',
+ },
+ };
+
+ const sectionLink = url.resolve(urlRoot, config[type].link);
+
+ const response = await got({
+ method: 'get',
+ url: sectionLink,
+ responseType: 'buffer',
+ });
+
+ const $ = transcode(response.data);
+
+ const out = await Promise.all(
+ $('.main_r_xuxian')
+ .find('tr')
+ .slice(0, 10)
+ .map(async (i, e) => {
+ const title = $(e)
+ .find('a')
+ .text()
+ .replace(/[\r\n]/g, ' ');
+ const relativeLink = $(e)
+ .find('a')
+ .attr('href');
+ const link = url.resolve(sectionLink, relativeLink);
+ const date = new Date(
+ $(e)
+ .children('td')
+ .eq(-1)
+ .text()
+ .match(/\d{4}-\d{2}-\d{2}/)[0]
+ );
+ const timeZone = 8;
+ const serverOffset = date.getTimezoneOffset() / 60;
+ const pubDate = new Date(date.getTime() - 60 * 60 * 1000 * (timeZone + serverOffset)).toUTCString();
+ const description = await ctx.cache.tryGet(link, async () => await getFullArticle(link));
+ const single = {
+ title,
+ link,
+ pubDate,
+ description,
+ };
+ return Promise.resolve(single);
+ })
+ .get()
+ );
+
+ ctx.state.data = {
+ title: '上海交通大学教务处 ' + config[type].section,
+ link: sectionLink,
+ item: out,
+ };
+};