From 65ca1bc1ca3663c1e70ae59ba899f51b986c784b Mon Sep 17 00:00:00 2001 From: chin Date: Thu, 24 Jun 2021 22:07:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=BE=8C=E7=BA=8C?= =?UTF-8?q?=E7=B5=A6=E5=88=86=E9=9B=A2=E7=9A=84=E5=89=8D=E7=AB=AF=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E7=99=BB=E5=85=A5api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat(courseSearch): 新增等待載入頁面 feat(courseSearch): 手機版預排課表新增紅色xx刪除課程 refactor: 更改名稱myBg-dark>labelBg-dark 只用在個人課表的class,更改名稱為label docs: readme新增啟動 build: 新增給pm2用的設定檔 feat: 新增改angular前端用的cors --- README.md | 6 +- ecosystem.config.js | 22 ++ routes/api/Course/controller/get_Course.js | 3 - routes/routes.js | 366 ++++++++++----------- server.js | 7 +- views/atm/Course_Search.html | 17 + views/atm/Schedule.html | 2 +- views/atm/css/Course_Search.css | 7 + views/atm/css/dark.css | 5 +- views/atm/css/loading.css | 59 ++++ views/atm/css/main.css | 2 +- 11 files changed, 303 insertions(+), 193 deletions(-) create mode 100644 ecosystem.config.js create mode 100644 views/atm/css/loading.css diff --git a/README.md b/README.md index c38743a..f86f809 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ module.exports = { "viewsRoot": "./views", "httpPort": 30087, - "httpsPort": 7878, //這個應該沒用 "host" : "127.0.0.1" , "timeout": 30000 }, @@ -44,3 +43,8 @@ module.exports = } }; ``` + +## 啟動 +```bash= +node server.js +``` diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 0000000..dff84d9 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,22 @@ +module.exports = { + apps: [{ + name: 'mycosim', + script: 'server.js', + watch: false, + ignore_watch: ["node_modules", "pm2log", "docx", "pdf", "picture", "xlsx", "*.log"], + exec_mode: 'cluster', + instances: 5, + max_memory_restart: '1000M', + time: true, + log_date_format: 'YYYY-MM-DD HH:mm Z', + force: true, + wait_ready: false, + max_restarts: 10, + // 單位為 ms, 預設為 0, 若有指定時間,則 app 會等待指定時間過後重啟 + autorestart: true, + error_file: './pm2log/err.log', + // 正常輸出 log 的指定位置 + out_file: './pm2log/out.log', + log_file: './pm2log/log.log' + }] +}; \ No newline at end of file diff --git a/routes/api/Course/controller/get_Course.js b/routes/api/Course/controller/get_Course.js index 45d4782..b194ae1 100644 --- a/routes/api/Course/controller/get_Course.js +++ b/routes/api/Course/controller/get_Course.js @@ -19,9 +19,6 @@ module.exports = async function (req, res) { return res.send(result); } async function getCourse(req) { - /*if (req.session.Course.length > 0) { - return Promise.resolve(req.session.Course); - }*/ let semno = req.query.semno; let courseJson = await getCourseJson(req , semno); if (!courseJson) { diff --git a/routes/routes.js b/routes/routes.js index 018964d..a9508ad 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -5,275 +5,275 @@ const fs = require('fs'); const Cryptjs = require('crypto-js'); const My_Func = require('./My_Func.js'); const request = require("request"); -module.exports = -/** - * - * @param {*} app - * @param {passport} passport - */ - function (app , passport) - { - - app.use('/api/Course' , require('./api/Course')); - app.use('/api/Today_Schedule' , require('./api/Today_Schedule')); - app.use('/api/Scores' , require('./api/Scores')); - app.use('/api/History_Scores' , require('./api/History_Scores')); - app.use('/api/Course_Search' , require('./api/Course_Search')); - app.use('/api/pdfmake' , require('./api/pdfmake')); - 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')) ; +module.exports = + /** + * + * @param {*} app + * @param {passport} passport + */ + function (app, passport) { + + app.use('/api/Course', require('./api/Course')); + app.use('/api/Today_Schedule', require('./api/Today_Schedule')); + app.use('/api/Scores', require('./api/Scores')); + app.use('/api/History_Scores', require('./api/History_Scores')); + app.use('/api/Course_Search', require('./api/Course_Search')); + app.use('/api/pdfmake', require('./api/pdfmake')); + 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) - { - // request was via https, so do no special handling - next(); - } else - { - // request was via http, so redirect to https - res.redirect('https://' + req.headers.host + req.url); - } - });*/ + /* app.use (function (req, res, next) { + if (req.secure) + { + // request was via https, so do no special handling + next(); + } else + { + // request was via http, so redirect to https + res.redirect('https://' + req.headers.host + req.url); + } + });*/ //HOME PAGE (login page) - app.get('/' ,My_Func.IsLoggedInHome, function(req , res) - { + app.get('/', My_Func.IsLoggedInHome, function (req, res) { res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0 '); - res.render('index_login.html', {messages:req.flash('error')[0]} ); + res.render('index_login.html', { messages: req.flash('error')[0] }); }); //login authenticate page - app.post('/login' , passport.authenticate('local-login' , - { - failureRedirect : '/', - failureFlash : true, - session : true, - }), function(res , req) - { - if (req.req.headers['referer']!= undefined && req.req.headers['referer'].includes('Course_Search')) + app.post('/login', passport.authenticate('local-login', { + failureRedirect: '/', + failureFlash: true, + session: true, + }), function (res, req) { + if (req.req.headers['referer'] != undefined && req.req.headers['referer'].includes('Course_Search')) { req.redirect('/Course_Search'); - } - else - { + } else if (req.req.headers['referer'] != undefined && req.req.headers['referer'].includes('historyScoreChart')) { + let refererSplit = req.req.headers['referer'].split("/"); + let redirectUrl = refererSplit[refererSplit.length-1]; + req.redirect(redirectUrl); + } else { req.redirect('/Today_Schedule'); } }); - app.get('/logout', function(req, res){ + app.get('/logout', function (req, res) { req.logout(); req.session.destroy(); res.redirect('/'); - }); -//#region web view - app.get('/Schedule' , My_Func.IsLoggedIn,function (req , res) - { + }); + + app.post('/api/login' , async function (req , res , next) { + + passport.authenticate('local-login', async function (err, user, info) { + if (err) { return next(err); } + if (!user) { + return res.json(info); + } + + req.logIn(user, function (err) { + // Should not cause any errors + if (err) { return next(err); } + if (req.headers['referer'] != undefined && req.headers['referer'].includes('Course_Search')) { + return res.json("success"); + } else if (req.headers['referer'] != undefined && req.headers['referer'].includes('historyScoreChart')) { + let refererSplit = req.req.headers['referer'].split("/"); + let redirectUrl = refererSplit[refererSplit.length-1]; + return res.json("success"); + } else { + return res.json("success"); + } + }); + })(req, res, next); + }); + + app.get('/api/logout', function (req, res) { + req.logout(); + req.session.destroy(); + res.redirect('/'); + }); + + app.get('/api/user', My_Func.IsLoggedIn, function (req, res) { + res.send(req.user); + }); + + app.post('/api/lineid', async function (req, res) { + var urlStr = QueryParams.normalize(url.parse(req.url, false).query); + var instance = QueryParams.getQueryStringToJSON(urlStr); + var item = await data_log.Getdata('Students', { "lineid": instance.id }); + if (item.length < 1) { + res.send("no lineid"); + } + else { + res.send({ username: item[0].username, lineid: item[0].lineid }); + } + }); + + //#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'); - // res.locals.CurrentUser = req.user; - res.render('./atm/Schedule.html' , { - user : req.user.toString() , IsUpdate:false + // res.locals.CurrentUser = req.user; + res.render('./atm/Schedule.html', { + user: req.user.toString(), IsUpdate: false }); }); - app.get('/Course' , My_Func.IsLoggedIn , function(req, res) - { + app.get('/Course', 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'); - res.render('./atm/Course.html' , {user : req.user.toString()}); + res.render('./atm/Course.html', { user: req.user.toString() }); }); - - app.get('/Today_Schedule' , My_Func.IsLoggedIn , function(req, res) - { + + app.get('/Today_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'); - res.render('./atm/TS.html' , {user : req.user.toString(), IsUpdate:false}); + res.render('./atm/TS.html', { user: req.user.toString(), IsUpdate: false }); }); - app.get('/Scores' , My_Func.IsLoggedIn , function(req, res) - { + app.get('/Scores', 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'); - res.render('./atm/Scores.html' , {user : req.user.toString()}); + res.render('./atm/Scores.html', { user: req.user.toString() }); }); - app.get('/History_Scores' , My_Func.IsLoggedIn , function(req, res) - { + app.get('/History_Scores', 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'); - res.render('./atm/History_Scores.html' , {user : req.user.toString()}); + res.render('./atm/History_Scores.html', { user: req.user.toString() }); }); - app.get('/Course_Search' , function(req, res) - { + app.get('/Course_Search', 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/Course_Search.html'); }); - app.get('/CTE_BOT' , function(req, res) - { + app.get('/CTE_BOT', 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/CTE_BOT.html'); }); - app.get('/announcement' , function(req, res) - { + 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) - { + 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'); }); - app.get('/historyScoreChart' , function(req, res) - { + app.get('/historyScoreChart', 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/historyScoreChart.html'); }); -//#endregion - app.get('/api/user' , My_Func.IsLoggedIn , function(req, res) - { - res.send(req.user); - }); - - app.post('/api/lineid' ,async function(req , res) - { - var urlStr = QueryParams.normalize(url.parse(req.url,false).query); - var instance = QueryParams.getQueryStringToJSON(urlStr); - var item = await data_log.Getdata('Students' , {"lineid" : instance.id}); - if (item.length <1) - { - res.send("no lineid"); - } - else - { - res.send({ username:item[0].username , lineid: item[0].lineid}); - } - }); - app.get('/updatedata' , function(req , res) - { + //#endregion + + app.get('/updatedata', function (req, res) { res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'); - // res.locals.CurrentUser = req.user; - res.render('./atm/TS.html' , { - user : req.user.toString(), IsUpdate : true + // res.locals.CurrentUser = req.user; + res.render('./atm/TS.html', { + user: req.user.toString(), IsUpdate: true }); }) - app.route('/api/log' , My_Func.IsLoggedIn).all(async function(req ,res ,next) - { - var urlStr = QueryParams.normalize(url.parse(req.url,false).query); + app.route('/api/log', My_Func.IsLoggedIn).all(async function (req, res, next) { + var urlStr = QueryParams.normalize(url.parse(req.url, false).query); var instance = QueryParams.getQueryStringToJSON(urlStr); - switch(req.method) - { + switch (req.method) { case "GET": - if (req.user == null || req.user !=instance.User) - { + if (req.user == null || req.user != instance.User) { res.send("no Access or not login"); } - var items = await data_log.Getdata("Schedule" , {"user": instance.User }); + var items = await data_log.Getdata("Schedule", { "user": instance.User }); var Result = []; - if (items.length >=1) - { - items[0].Schedule.forEach(item=> - { - Result.push({"Period": item.節次 , "Time":item.時間 ,"Mon":item.星期一,"Tue":item.星期二,"Wed":item.星期三,"Thu":item.星期四,"Fri":item.星期五,"Sat":item.星期六,"Sun":item.星期日}); + if (items.length >= 1) { + items[0].Schedule.forEach(item => { + Result.push({ "Period": item.節次, "Time": item.時間, "Mon": item.星期一, "Tue": item.星期二, "Wed": item.星期三, "Thu": item.星期四, "Fri": item.星期五, "Sat": item.星期六, "Sun": item.星期日 }); }); res.send(Result); } - else - { + else { res.send(null); } break; case "POST": - if (instance.method ==="getnewdata") - { - var result =""; + if (instance.method === "getnewdata") { + var result = ""; //讀取檔案 //將讀取的資料轉成Json ////將Json前面加入擁有者的學號 - var Schedule_jsondata =fs.readFileSync("../../Schedule/" + instance.User + ".json",'utf8'); + var Schedule_jsondata = fs.readFileSync("../../Schedule/" + instance.User + ".json", 'utf8'); var Schedule = JSON.parse(Schedule_jsondata); - var Schedule_json = {user : instance.User , Schedule}; - var Courses_jsondata = fs.readFileSync("../../Courses/" + instance.User + ".json" , "utf8"); + var Schedule_json = { user: instance.User, Schedule }; + var Courses_jsondata = fs.readFileSync("../../Courses/" + instance.User + ".json", "utf8"); delete Courses_jsondata[0]; var Courses = JSON.parse(Courses_jsondata); - var Courses_json = {user : instance.User , Courses}; - var Score_jsondata = fs.readFileSync("../../Scores/" + instance.User + ".json" , "utf8"); + var Courses_json = { user: instance.User, Courses }; + var Score_jsondata = fs.readFileSync("../../Scores/" + instance.User + ".json", "utf8"); var Scores = JSON.parse(Score_jsondata); - var Score_json = {user : instance.User , Scores}; - var HS_jsondata = fs.readFileSync("../../AllScores/" + instance.User + ".json" , "utf8"); + var Score_json = { user: instance.User, Scores }; + var HS_jsondata = fs.readFileSync("../../AllScores/" + instance.User + ".json", "utf8"); var History_Con_Scores = JSON.parse(HS_jsondata); - var HS_All_jsondata = fs.readFileSync("../../AllScores/" + instance.User + "_All.json" , "utf8"); + var HS_All_jsondata = fs.readFileSync("../../AllScores/" + instance.User + "_All.json", "utf8"); var History_Scores = JSON.parse(HS_All_jsondata); - var History_Scores_json = {user : instance.User , History_Scores,History_Con_Scores}; - var Stu_Inf_jsondata = fs.readFileSync("../../Stu_Num/" + instance.User + "_inf.json" ,"utf8"); - var Stu_Inf = JSON.parse(Stu_Inf_jsondata); + var History_Scores_json = { user: instance.User, History_Scores, History_Con_Scores }; + var Stu_Inf_jsondata = fs.readFileSync("../../Stu_Num/" + instance.User + "_inf.json", "utf8"); + var Stu_Inf = JSON.parse(Stu_Inf_jsondata); var Stu_Inf_json = Stu_Inf; //檢查是否有資料了 //有:更新 //沒有:插入 - var IsExist = await data_log.Getdata("Schedule" , {"user": instance.User}); - if (IsExist.length >=1) - { - result = await data_log.Updatedata("Schedule" , {"user" : instance.User} , {$set :{"Schedule" : Schedule_json.Schedule}}); - result = await data_log.Updatedata("Courses" , {"user" : instance.User} , {$set :{"Courses" : Courses_json.Courses}}); - result = await data_log.Updatedata("Scores" , {"user" : instance.User} , {$set :{"Scores" : Score_json.Scores}}); - result = await data_log.Updatedata("History_Scores" , {"user" : instance.User} ,{$set:{"History_Scores":History_Scores_json.History_Scores ,"History_Con_Scores" : History_Scores_json.History_Con_Scores}}); + var IsExist = await data_log.Getdata("Schedule", { "user": instance.User }); + if (IsExist.length >= 1) { + result = await data_log.Updatedata("Schedule", { "user": instance.User }, { $set: { "Schedule": Schedule_json.Schedule } }); + result = await data_log.Updatedata("Courses", { "user": instance.User }, { $set: { "Courses": Courses_json.Courses } }); + result = await data_log.Updatedata("Scores", { "user": instance.User }, { $set: { "Scores": Score_json.Scores } }); + result = await data_log.Updatedata("History_Scores", { "user": instance.User }, { $set: { "History_Scores": History_Scores_json.History_Scores, "History_Con_Scores": History_Scores_json.History_Con_Scores } }); + } + else { + result = await data_log.Insertdata("Schedule", Schedule_json); + result = await data_log.Insertdata("Courses", Courses_json); + result = await data_log.Insertdata("Scores", Score_json); + result = await data_log.Insertdata("History_Scores", History_Scores_json); } - else - { - result = await data_log.Insertdata("Schedule" , Schedule_json); - result = await data_log.Insertdata("Courses" , Courses_json); - result = await data_log.Insertdata("Scores" , Score_json); - result = await data_log.Insertdata("History_Scores" , History_Scores_json); - } - result = await data_log.Updatedata("Students" , {"username": instance.User} , {$set:{"Inf" : Stu_Inf_json }}); - var UpDay =await Get_Date_YYYYMM(); - result = await data_log.Updatedata("Students" , {"username" : instance.User} , {$set: {"Last_Up_Time" : UpDay}}); - (result === "fail") ? res.send('fail') : res.send('success'); + result = await data_log.Updatedata("Students", { "username": instance.User }, { $set: { "Inf": Stu_Inf_json } }); + var UpDay = await Get_Date_YYYYMM(); + result = await data_log.Updatedata("Students", { "username": instance.User }, { $set: { "Last_Up_Time": UpDay } }); + (result === "fail") ? res.send('fail') : res.send('success'); } - else if (instance.method =="updatedata") - { + else if (instance.method == "updatedata") { var userpwd = ""; - if (req.session.userpwd !=null || req.session.userpwd != undefined) - { - userpwd = req.session.userpwd ; + if (req.session.userpwd != null || req.session.userpwd != undefined) { + userpwd = req.session.userpwd; } - else if (instance.userpwd) - { - var mypromise = () => - { - return new Promise ((resolve)=> - { - request( - { - url : 'http://system8.ntunhs.edu.tw/myNTUNHS_student/Common/UserControls/loginModule.aspx', - qs : {txtid : instance.User , txtpwd : instance.userpwd , select : "student"} - } , function (err , response , body) - { - resolve(body); + else if (instance.userpwd) { + var mypromise = () => { + return new Promise((resolve) => { + request( + { + url: 'http://system8.ntunhs.edu.tw/myNTUNHS_student/Common/UserControls/loginModule.aspx', + qs: { txtid: instance.User, txtpwd: instance.userpwd, select: "student" } + }, function (err, response, body) { + resolve(body); + }); }); - }); }; var loginresult = await mypromise(); - if (loginresult.split('_').length < 2) - { - res.send('error pwd'); - return; + if (loginresult.split('_').length < 2) { + res.send('error pwd'); + return; } userpwd = instance.userpwd; } - var cryptpwd = Cryptjs.AES.encrypt(userpwd , "jhytjtrfewfwfrehtergwe"); - var cryptpwd_2 = Cryptjs.AES.encrypt(cryptpwd.toString() , "jkyro0gkeprof,ewopf,owep"); - var cryptpwd_3 = Cryptjs.AES.encrypt(cryptpwd_2.toString() , "yureoqrueiwqrieowqprwep"); - var cryptpwd_4 = Cryptjs.AES.encrypt(cryptpwd_3.toString() , "hotropwgjreiognehoie"); + var cryptpwd = Cryptjs.AES.encrypt(userpwd, "jhytjtrfewfwfrehtergwe"); + var cryptpwd_2 = Cryptjs.AES.encrypt(cryptpwd.toString(), "jkyro0gkeprof,ewopf,owep"); + var cryptpwd_3 = Cryptjs.AES.encrypt(cryptpwd_2.toString(), "yureoqrueiwqrieowqprwep"); + var cryptpwd_4 = Cryptjs.AES.encrypt(cryptpwd_3.toString(), "hotropwgjreiognehoie"); let encData = Cryptjs.enc.Base64.stringify(Cryptjs.enc.Utf8.parse(cryptpwd_4)); - res.send({user :instance.User , pwd: encData}); + res.send({ user: instance.User, pwd: encData }); } break; default: @@ -282,19 +282,17 @@ module.exports = }); app.route('/*').get((req, res) => { res.status(404).json({ - status: 404, - message: "not found" + status: 404, + message: "not found" }); }); }; -async function Get_Date_YYYYMM() -{ - return new Promise((resolve)=> - { +async function Get_Date_YYYYMM() { + return new Promise((resolve) => { var year = new Date().getFullYear(); - var month = new Date().getUTCMonth() +1; + var month = new Date().getUTCMonth() + 1; var yyyymm = year.toString() + month.toString(); - return resolve(yyyymm); + return resolve(yyyymm); }); } diff --git a/server.js b/server.js index 09dba00..928ee3a 100644 --- a/server.js +++ b/server.js @@ -23,7 +23,12 @@ app.use(compression()); //app.set('views', config.HTTPServer.viewsRoot); app.use(express.static(config.HTTPServer.viewsRoot)); app.use(flash()); -app.use(cors()); +app.use(cors({ + origin : [ + "http://localhost:4200" + ] , + credentials : true +})); app.use(bodyPareser.urlencoded({extended: true , limit : '50mb'})); app.use(bodyPareser.json({limit: '50mb'})); app.use(cookieParser( "myNtunhsCookieSecret")); diff --git a/views/atm/Course_Search.html b/views/atm/Course_Search.html index d154c9c..92f9a3e 100644 --- a/views/atm/Course_Search.html +++ b/views/atm/Course_Search.html @@ -19,6 +19,7 @@ +