Skip to content

Commit

Permalink
feat: 增加學習地圖(總學分計算)
Browse files Browse the repository at this point in the history
1. 學習地圖api
2. 頁面資管系可顯示學程

feat: 增加e-Profolio的公告

1. 公告api
2. 頁面可篩選公告
  • Loading branch information
Chinlinlee committed Jan 11, 2021
1 parent d585e5a commit 883570d
Show file tree
Hide file tree
Showing 9 changed files with 373 additions and 1 deletion.
46 changes: 46 additions & 0 deletions routes/api/announcement/controller/get_Announcement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const fetch = require('node-fetch');
const cheerio = require('cheerio');


module.exports = async function (req ,res) {
let ePortfolioIndex = "https://system8.ntunhs.edu.tw/myNTUNHS_student/Modules/Main/Index_student.aspx";
let ePortfolioRes = await fetch(ePortfolioIndex);
let resText = await ePortfolioRes.text();
let $ = cheerio.load(resText);
let resultNews = [];
$("#tableRssNews tr").each(function (index , element) {
if (index != 0) {
let news = $(element).find("a").text()
let newsURL = $(element).find("a").attr('href');
let spanTimeText = $(element).find("span").text();
//console.log(spanTimeText);
let time =spanTimeText.match(/\((.*?)\)/g)[0];
let newsObj = {
text : news ,
url : newsURL ,
time : time
}
resultNews.push(newsObj);
}
});

let resultInfo = [];
$("#tableRssInfo tr").each(function (index , element) {
if (index != 0 ) {
let time = $(element).find("td").eq(0).text();
let infoA = $(element).find("td").eq(1).find("a");
let info = infoA.text()
let infoURL = infoA.attr('href');
let infoObj = {
text : info ,
url : infoURL ,
time : time
}
resultInfo.push(infoObj);
}
});
res.send({
news : resultNews ,
info : resultInfo
});
}
6 changes: 6 additions & 0 deletions routes/api/announcement/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const express = require('express');
const router = express.Router();

router.get('/' , require('./controller/get_Announcement'));

module.exports = router;
91 changes: 91 additions & 0 deletions routes/api/learnMap/controller/get_learnMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
const myFunc = require("../../../My_Func");
const fetch = require('node-fetch');
const cheerio = require('cheerio');
const chrome = require('selenium-webdriver/chrome');
const webdriver = require('selenium-webdriver'); //导入selenium 库
const { courseProgram } = require('../../../../models/NTUNHS/CourseProgram/CourseProgram');
const _ = require('lodash');
const fs = require('fs');

module.exports = async function (req, res) {
let sessionLearnMap = req.session.learnMap;
if (sessionLearnMap) {
return res.send(sessionLearnMap);
}
let opt = new chrome.Options();
opt.addArguments('--headless');
opt.addArguments('--disable-gpu');
opt.addArguments('--incognito');
opt.setUserPreferences({ "download.default_directory": __dirname });
let driver = await new webdriver.Builder().forBrowser('chrome').setChromeOptions(opt).build();
let j = myFunc.getJar(req);
let cookieStr = j.getCookieStringSync("http://system8.ntunhs.edu.tw");
let aspSessionID = cookieStr.split("=")[1];
await driver.navigate().to("http://system8.ntunhs.edu.tw/myNTUNHS_student/Modules/Map/tab/Map_tab_14.aspx?dept=");
if (aspSessionID) {
await driver.manage().addCookie({
name: "ASP.NET_SessionId",
value: aspSessionID
});
}
await driver.navigate().to("http://system8.ntunhs.edu.tw/myNTUNHS_student/Modules/Map/qry/Map_qry_20.aspx");
try {
await driver.wait(webdriver.until.elementLocated(webdriver.By.id('pAlertMsg')), 2000);
let $ = cheerio.load(await driver.getPageSource());
let alertMsg = $("#pAlertMsg").text();
if (alertMsg.includes("請先登入系統")) {
req.logout();
req.flash("閒置過久,請重新登入");
return res.status(401).send();
}
} catch (e) {
/* $.post('Map_qry_20.aspx', { 'action': 'htmlCreditHis', 'group': $('select[id*=sltDeptGroup]').find('option:selected').attr('groupno'), 'deptno': $('select[id*=sltDeptGroup]').find('option:selected').attr('deptno'), 'year': $('input:hidden[id*=hidEnterYear]').val(), 'semno': $('input:hidden[id$=hidSEMNO]').val(), 'edutype': $('select[id*=sltDeptGroup]').find('option:selected').attr('edutype') }, function(data) { $('#divCreditHistory').html(data); setFrameSize(); return false; }, 'html');*/
await driver.sleep(500);
let $ = cheerio.load(await driver.getPageSource());

$("#divCreditInfo table").addClass("table table-bordered table-sm");
$("#divCreditInfo table").attr('style', '');
$("#divCreditInfo").find("span").remove();
let passCourse = [];
$(".tdCourse input").each(function (index, element) {
let isChecked = $(element).attr("defaultchecked") == "true";
if (isChecked) {
//first is input's parent (td)
//second is td's parnet tr
//get only text in trCourse
let course = $(element).parent().parent().children().text();
passCourse.push(course);
}
});
let tablehtml = $("#divCreditInfo").html();
await driver.quit();
let faculty = req.session.stuInfo.stuFaculty;
let myProgram = [];

for (let key in courseProgram[faculty]) {
programObj = {
key : key ,
course : [] ,
credit : 0
};
let program = courseProgram[faculty][key].course;
for (let i = 0 ; i < program.length ; i++) {
let course = program[i];
if (passCourse.findIndex(v => v == course.name) >=0 ) {
programObj.credit += course.credit;
programObj.course.push(course);
}
}
myProgram.push(programObj);
}
req.session.learnMap = {
hitCredit : tablehtml ,
program : myProgram
};
return res.send(req.session.learnMap);
}
/* let el = await driver.findElement(webdriver.By.id(`pAlertMsg`));
await driver.wait(webdriver.until.elementIsVisible(el),1000);*/
}


5 changes: 5 additions & 0 deletions routes/api/learnMap/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const express = require('express');
const router = express.Router();

router.get('/' , require('./controller/get_learnMap'));
module.exports = router;
18 changes: 17 additions & 1 deletion routes/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ module.exports =
app.use('/api/CTE_BOT' , require('./api/CTE_BOT'));
app.use('/api/stuInfo' , require('./api/stuInfo'))
app.use('/api/Schedule' , require('./api/Schedule')) ;
app.use('/api/announcement' , require('./api/announcement')) ;
app.use('/api/learnMap' , require('./api/learnMap')) ;
//HTTP轉址HTTPS
/* app.use (function (req, res, next) {
if (req.secure)
Expand Down Expand Up @@ -65,7 +67,7 @@ module.exports =
req.session.destroy();
res.redirect('/');
});

//#region web view
app.get('/Schedule' , My_Func.IsLoggedIn,function (req , res)
{
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
Expand Down Expand Up @@ -113,6 +115,20 @@ module.exports =
res.render('./atm/CTE_BOT.html');
});

app.get('/announcement' , function(req, res)
{
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
res.set('Cache-Control', 'public, max-age=0');
res.render('./atm/Announcement.html');
});

app.get('/learnMap' , function(req, res)
{
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
res.set('Cache-Control', 'public, max-age=0');
res.render('./atm/learnMap.html');
});
//#endregion
app.get('/api/user' , My_Func.IsLoggedIn , function(req, res)
{
res.send(req.user);
Expand Down
67 changes: 67 additions & 0 deletions views/atm/Announcement.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html ng-app="announcementApp">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NTUNHS e-Portfolio公告</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="../externals/Bootstrap/bootstrap.min.css">
<link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">

<!-- Custom styles for this template -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="atm/css/main.css">
<link rel="stylesheet" href="atm/css/dark.css">
</head>

<body ng-controller="announcementCtrl">
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<a class="navbar-brand" href="/Today_Schedule">今日課表</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<nav-normal-item class="navbar-nav"></nav-normal-item>
</ul>
<ul class="navbar-nav ml-auto">
<darkmode></darkmode>
<div ng-include="'navRight.html'"></div>
</ul>
</div>
</nav>
<div class="container">
<input type="search" class="form-control" ng-model="q" placeholder="輸入標題或日期" />
<div class="my-3 p-3 rounded shadow-sm myAnnouncement">
<h3 class="border-bottom border-gray pb-2 mb-0 text-center">北護焦點</h3>
<div class="media text-muted pt-3" ng-repeat="new in news | filter:q">
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<a style="font-size: 16px;" ng-href="{{new.url}}">{{new.text}}</a>
<span>{{new.time}}</span>
</p>
</div>
</div>
<div class="my-3 p-3 rounded shadow-sm myAnnouncement">
<h3 class="border-bottom border-gray pb-2 mb-0 text-center">在校生公告</h3>
<div class="media text-muted pt-3" ng-repeat="item in info | filter:q">
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<span style="font-size: 18px;">{{item.time}}</span>
<a style="font-size: 16px;" ng-href="{{item.url}}">{{item.text}}</a>
</p>
</div>
</div>
</div>
<ng-include src="'footer.html'"></ng-include>
</body>

</html>
<script src="./externals/jquery/jquery-1.11.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js"></script>
<script src="../externals/Bootstrap/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<script src="./externals/angularjs/angular.min.js"></script>
<script src="./atm/scripts/Common.js"></script>
<script src="./atm/scripts/ngCommon.js"></script>
<script src="./atm/scripts/Announcement.js"></script>
55 changes: 55 additions & 0 deletions views/atm/learnMap.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html ng-app="learnMapApp">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NTUNHS 學習地圖</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="../externals/Bootstrap/bootstrap.min.css">
<link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">

<!-- Custom styles for this template -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="atm/css/main.css">
<link rel="stylesheet" href="atm/css/dark.css">
</head>

<body ng-controller="learnMapCtrl">
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<a class="navbar-brand" href="/Today_Schedule">今日課表</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<nav-normal-item class="navbar-nav"></nav-normal-item>
</ul>
<ul class="navbar-nav ml-auto">
<darkmode></darkmode>
<div ng-include="'navRight.html'"></div>
</ul>
</div>
</nav>
<div class="container">
<div ng-repeat="item in userProgram">
<h1>{{item.key}} : {{item.credit}}</h1>
<ul class="list-group" ng-repeat="course in item.course">
<li class="list-group-item text-center">name : {{course.name}}</li>
<li class="list-group-item text-center">credit : {{course.credit}}</li>
</ul>
</div>
</div>
<ng-include src="'footer.html'"></ng-include>
</body>

</html>
<script src="./externals/jquery/jquery-1.11.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js"></script>
<script src="../externals/Bootstrap/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<script src="./externals/angularjs/angular.min.js"></script>
<script src="./atm/scripts/Common.js"></script>
<script src="./atm/scripts/ngCommon.js"></script>
<script src="./atm/scripts/learnMap.js"></script>
43 changes: 43 additions & 0 deletions views/atm/scripts/Announcement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
let announcementApp = angular.module("announcementApp" , ["commonApp"]);

announcementApp.controller("announcementCtrl" , function ($scope , announcementService , commonService) {
$scope.Currentuser = "";
$scope.q = "";
commonService.user.getStuInfo().then(function (res) {
$scope.Currentuser = res.data;
});

$scope.news = {};
$scope.info = {};
announcementService.Get_data().then(function (res) {
$scope.news = res.data.news;
$scope.info = res.data.info;
});
});


announcementApp.service("announcementService" , function ($http) {
return (
{
Get_data : Get_data
}
);
function Get_data()
{
var request = $http(
{
method: "GET",
url : "api/announcement",
}
);
return (request.then(handleSuccess , handleError));
}
function handleSuccess(response) {
return (response);
}

function handleError(response) {
return (response);
}
});

Loading

0 comments on commit 883570d

Please sign in to comment.