Browse Source

submit code

zhouxianguang 6 years ago
parent
commit
25737ac39d

+ 40 - 0
CourseDown.js

@@ -0,0 +1,40 @@
+var fs = require('fs');
+var logHelper = require("./helper/LjLogHelper.js");
+var fileHelper = require("./helper/LjFileHelper");
+
+/**
+ * The course down
+ */
+class CourseDown
+{
+    static downCourse(lessonJsonObj,callBack)
+    {
+        /*课件-Begin*/
+        //课程集合
+        var courseList = lessonJsonObj.data.list;
+        //课程数
+        var courseListSize = courseList.length;
+        //遍历课件
+        for (var i = 0; i < courseListSize; i++)
+        {
+            logHelper.debug(courseList[i].title);
+            //资源集合
+            var resourceList = courseList[i].list;
+
+            //资源数
+            var resourceSize = resourceList.length;
+
+            for (var j = 0; j < resourceSize; j++)
+            {
+                logHelper.debug(resourceList[j].url);
+                var url = resourceList[j].url;
+                fileHelper.downloadFile(url)
+            }
+        }
+        /*课件-End*/
+        logHelper.info("Succeed to down lesson【"+lessonJsonObj.data.title+"】");
+        callBack();
+    }
+}
+
+module.exports = CourseDown;

+ 0 - 5
_windows/laf.xml

@@ -1,5 +0,0 @@
-<application>
-  <component name="LafManager">
-    <laf class-name="com.intellij.ide.ui.laf.IntelliJLaf" />
-  </component>
-</application>

+ 98 - 0
app.js

@@ -0,0 +1,98 @@
+var http = require('http');
+var request = require('request');
+var fs = require('fs');
+var url = require('url');
+var ljConst = require("./const/LjConst.js");
+var CourseDown = require("./CourseDown");
+var async = require("async");
+
+var express = require('express');
+var app = express();
+
+//引入工具类
+var logHelper = require("./helper/LjLogHelper.js");
+var httpHelper = require("./helper/LjHttpHelper");
+var fileHelper = require("./helper/LjFileHelper");
+var apiHelper = require("./helper/LjApiHelper");
+var ljStringHelper = require("./helper/LjStringHelper");
+
+var videoUrl1 = 'https://efunvideo.ai160.com/vs2m/001/00101002/00101002002/00101002002.m3u8';
+var videoUrl2 = 'https://efunvideo.ai160.com/vs2m/801/C-01-01-0004/J-03-02-000365/J-03-02-000365.m3u8';
+var imgUrl = 'https://efunimgs.ai160.com/resources/J/02/01/500001.jpg';
+
+//downloadFile(videoUrl1);
+//downloadFile(videoUrl2);
+//fileHelper.downloadFile(imgUrl);
+
+var result = JSON.parse(fs.readFileSync("./lessonInfo.json"));
+CourseDown.downCourse(result,function()
+{
+    console.info("周现广");
+});
+
+
+/**
+ * 下载
+ */
+app.get('/down.do', function (req, res)
+{
+    var arg = url.parse(req.url, true).query;
+    var courseId = arg.courseId;
+    var eid = arg.eid;
+    var uid = arg.uid;
+    var token = arg.token;
+    var lessonId = arg.lessonId;
+    //获取参数
+    logHelper.info(arg);
+
+    //校验参数
+    if (ljStringHelper.isNull(courseId))
+    {
+        logHelper.info("null object of courseId");
+        return "null object of courseId";
+    }
+    if (ljStringHelper.isNull(lessonId))
+    {
+        logHelper.info("null object of lessonId");
+        return "null object of courseId";
+    }
+    if (ljStringHelper.isNull(eid))
+    {
+        logHelper.info("null object of eid");
+        return "null object of eid";
+    }
+    if (ljStringHelper.isNull(uid))
+    {
+        logHelper.info("null object of uid");
+        return "null object of uid";
+    }
+    if (ljStringHelper.isNull(token))
+    {
+        logHelper.info("null object of token");
+        return "null object of token";
+    }
+
+    var opt = {};
+    opt.eid = "100166681101003";
+    opt.uid = "100166681101001";
+    opt.token = token;
+    opt.lessonId = "02279ace371a11e8af2000163e08bde8";
+    courseId = "02549160371e11e88c3600163e08bde8";
+    opt.url = apiHelper.getApiForCourse(lessonId, courseId, eid);
+
+    httpHelper.request(opt, function (error, res, body)
+    {
+        logHelper.info(body);
+        let obj = JSON.parse(body);
+        logHelper.info(obj.code);
+
+        var result = JSON.parse(body);
+        CourseDown.downCourse(result);
+    });
+});
+
+//启动监听
+app.listen(9095, function ()
+{
+    logHelper.info("winBoxNode starting success");
+});

+ 0 - 12
codestyles/Default.xml

@@ -1,12 +0,0 @@
-<code_scheme name="Default" version="173">
-  <JSCodeStyleSettings>
-    <option name="FUNCTION_EXPRESSION_BRACE_STYLE" value="2" />
-  </JSCodeStyleSettings>
-  <codeStyleSettings language="JavaScript">
-    <option name="BRACE_STYLE" value="2" />
-    <option name="CLASS_BRACE_STYLE" value="2" />
-    <option name="METHOD_BRACE_STYLE" value="2" />
-    <option name="ELSE_ON_NEW_LINE" value="true" />
-    <option name="IF_BRACE_FORCE" value="1" />
-  </codeStyleSettings>
-</code_scheme>

+ 12 - 0
const/LjConst.js

@@ -0,0 +1,12 @@
+const constBase = {
+    BASE_DIR:'c:\\efunbox\\',
+    VIDEO_TYPE_M3U8 : '',
+    VIDEO_TYPE_MP4 : ''
+}
+
+const constApi = {
+    GET_COURSE_WARE_LIST_BY_LESSON_ID:'http://tt-web.api.ai160.com/lesson/02279ace371a11e8af2000163e08bde8?courseId=02549160371e11e88c3600163e08bde8&eid=100166681101002&cache=true'
+}
+
+module.exports.constBase = constBase;
+module.exports.constApi = constApi;

+ 0 - 13
debugger.xml

@@ -1,13 +0,0 @@
-<application>
-  <component name="XDebuggerSettings">
-    <data-views />
-    <general />
-    <debuggers>
-      <debugger id="javascript">
-        <configuration>
-          <custom-object-presentation />
-        </configuration>
-      </debugger>
-    </debuggers>
-  </component>
-</application>

+ 0 - 7
find.xml

@@ -1,7 +0,0 @@
-<application>
-  <component name="FindSettings">
-    <option name="customScope" value="All Places" />
-    <option name="defaultScopeName" value="All Places" />
-    <option name="SEARCH_SCOPE" value="All Places" />
-  </component>
-</application>

+ 26 - 0
helper/LjApiHelper.js

@@ -0,0 +1,26 @@
+var request = require('request');
+var cryptoJS = require("crypto-js");
+
+/**
+ * The helper of api
+ */
+class LjApiHelper
+{
+    //获取课程信息
+    static getApiForCourse(lessonId, courseId, eid)
+    {
+        var http = "http://tt-web.api.ai160.com/lesson/" + lessonId;
+        http += "?courseId=" + courseId
+        http += "&eid=" + eid
+        http += "&cache=true";
+
+        return http;
+    }
+
+    static getApiForDown(lessonId)
+    {
+        return "http://tt-web.api.ai160.com/callback/download/add?lessonId=" + lessonId;
+    }
+}
+
+module.exports = LjApiHelper;

+ 411 - 0
helper/LjFileHelper.js

@@ -0,0 +1,411 @@
+var request = require('request');
+var fs = require('fs');
+var ffmpeg = require('fluent-ffmpeg');
+var ljConst = require("../const/LjConst.js");
+var path = require('path');
+var logHelper = require("./LjLogHelper");
+
+/**
+ * The helper of file
+ */
+class LjFileHelper
+{
+    /**
+     * Download file
+     * @param fileUrl the file url
+     * @returns {boolean}
+     */
+    static downloadFile(fileUrl)
+    {
+        //获取文件属性对象
+        var filePropObj = this.getFileProperty(fileUrl);
+        if (filePropObj == null)
+        {
+            return false;
+        }
+
+        //视频处理
+        if (filePropObj.fileType == ljConst.constBase.VIDEO_TYPE_M3U8)
+        {
+            //未加密视频本地存储路径
+            var localFileDir = filePropObj.folderDir + filePropObj.fileName + ".mp4"
+
+            //M3U8视频转换MP4
+            ffmpeg(fileUrl).format(ljConst.constBase.VIDEO_TYPE_MP4)
+                .on('start', function (err)
+                {
+                    logHelper.info("Starting down video:" + fileUrl);
+                })
+                .on('error', function (err)
+                {
+                    logHelper.error("Succeeded to down video[" + fileUrl + "]: " + err.message);
+                })
+                .on('end', function ()
+                {
+                    //加密视频存储路径
+                    let localFileDirNew = filePropObj.folderDir + filePropObj.fileName + "_new" + ".mp4"
+                    logHelper.info("Succeeded to down video:" + localFileDirNew);
+
+                    //加密存储
+                    this.writeEncryptedStream(localFileDir, localFileDirNew);
+                    console.info("Succeeded to encrypt video:" + localFileDirNew);
+
+                    //删除文件(加密存储完成后删除未加密文件)
+                    fs.unlink(localFileDir, function (err)
+                    {
+                        if (err)
+                        {
+                            //删除失败
+                            logHelper.info("Failed to delete video[" + err.message + "]:" + localFileDir);
+                            throw err;
+                        }
+                        else
+                        {
+                            logHelper.info('Succeeded to delete video:' + localFileDir)
+                        }
+                    })
+                })
+                .save(localFileDir);
+        }//图片处理
+        else
+        {
+            //未加密图片本地存储地址
+            var localFileDir = filePropObj.folderDir + filePropObj.fileName + "." + filePropObj.fileType;
+
+            //读取图片
+            request(fileUrl).pipe(fs.createWriteStream(localFileDir)).on('close', function ()
+            {
+                //加密图片存储地址
+                var localFileDirNew = filePropObj.folderDir + filePropObj.fileName + "_new." + filePropObj.fileType;
+                logHelper.info("Succeeded to down image:" + localFileDirNew);
+
+                //加密图片
+                LjFileHelper.writeEncryptedStream(localFileDir, localFileDirNew);
+
+                logHelper.info("Succeeded to image video:" + localFileDirNew);
+
+                //删除文件(加密存储完成后删除未加密文件)
+                fs.unlink(localFileDir, function (err)
+                {
+                    if (err)
+                    {
+                        //删除失败
+                        logHelper.erro("Failed to delete image[" + err.message + "]:" + localFileDir);
+                        throw err;
+                    }
+                    else
+                    {
+                        logHelper.info('Succeeded to delete image:' + localFileDir)
+                    }
+                })
+            });
+        }
+    }
+
+    /**
+     * Gets file directory
+     * @param fileName the file name
+     * @returns {*|string} the file directory
+     */
+    static getFileDir(fileName)
+    {
+        var fileType = fileName.split(".")[1]
+
+        var newFileDir = "";
+        if (fileType == "m3u8")
+        {
+            fileName = fileName.replace(".m3u8", "_new.mp4")
+            newFileDir = constObj.baseDir + fileName.replace(/\*/g, '\\');
+        }
+        else
+        {
+            fileName = fileName.replace(".", "_new.")
+            newFileDir = constObj.baseDir + fileName.replace(/\*/g, '\\');
+        }
+
+        return newFileDir;
+    }
+
+    /**
+     * Makes directory
+     * @param dirname the directory name
+     * @returns {boolean} true or false
+     */
+    static mkdirsSync(dirname)
+    {
+        if (fs.existsSync(dirname))
+        {
+            return true;
+        }
+        else
+        {
+            if (this.mkdirsSync(path.dirname(dirname)))
+            {
+                fs.mkdirSync(dirname);
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Gets the file property object
+     * @param fileUrl the file URL
+     * @returns {null}
+     */
+    static getFileProperty(fileUrl)
+    {
+        if (fileUrl.startsWith("https://efunimgs.ai160.com") || fileUrl.startsWith("https://efunvideo.ai160.com"))
+        {
+            /*--文件夹目录-Begin--*/
+            var folderDir = ljConst.constBase.BASE_DIR;
+
+            var splitArr = fileUrl.split('/')
+            var arrLen = splitArr.length;
+            for (var i = 3; i < arrLen - 1; i++)
+            {
+                folderDir += splitArr[i] + "\\";
+            }
+            //创建文件夹目录
+            this.mkdirsSync(folderDir);
+
+            var filePropObj = {};
+            filePropObj.folderDir = folderDir;
+            //获取文件名称
+            filePropObj.fileName = splitArr[arrLen - 1].split(".")[0];
+            //获取文件类型
+            filePropObj.fileType = splitArr[arrLen - 1].split(".")[1];
+            /*--文件夹目录-Begin--*/
+
+            return filePropObj;
+        }
+
+        return null;
+    }
+
+    static Encrypted(c)
+    {
+        var b = '';
+        for (var i = 0; i < c.length; i++)
+        {
+            var ch = c[i];
+            if (ch == '0')
+            {
+                ch = 'f';
+            }
+            else if (ch == 'f')
+            {
+                ch = '0';
+            }
+            b = b + ch;
+            //console.log(ch);
+        }
+        return b;
+    }
+
+
+    static Decrypted(c)
+    {
+        var b = '';
+        for (var i = 0; i < c.length; i++)
+        {
+            var ch = c[i];
+            if (ch == 'f')
+            {
+                ch = '0';
+            }
+            else if (ch == '0')
+            {
+                ch = 'f';
+            }
+            b = b + ch;
+            //console.log(ch);
+        }
+        return b;
+    }
+
+
+    /**
+     * Writes encrypted content, which is read from given source file, into given dest file
+     * @param fSrc the source file
+     * @param fDest the dest file
+     */
+    static writeEncryptedStream(fSrc, fDest)
+    {
+        var rs = fs.createReadStream(fSrc);
+        var ws = fs.createWriteStream(fDest);
+        rs.on('data', function (chunk)
+        {
+            let b = new Buffer(chunk, 'hex');
+            //console.log(b);
+
+            let c = b.toString('hex');
+            c = LjFileHelper.encryptedContent(c);
+            let d = Buffer.from(c, 'hex');
+
+            ws.write(d);
+        });
+
+        rs.on('end', function ()
+        {
+            ws.end();
+            logHelper.info('Succeeded in writing into encrypted stream[' + fDest + '].');
+        });
+
+        rs.on('error', function (err)
+        {
+            console.log(err.stack);
+        });
+    }
+
+    /**
+     * Encrypts the content
+     * @param c the content to be encrypted
+     * @return the encrypted content
+     */
+    static encryptedContent(c)
+    {
+        var b = '';
+        for (var i = 0; i < c.length; i++)
+        {
+            var ch = c[i];
+            if (ch == '0')
+            {
+                ch = 'f';
+            }
+            else if (ch == 'f')
+            {
+                ch = '0';
+            }
+            else if (ch == '1')
+            {
+                ch = 'e';
+            }
+            else if (ch == 'e')
+            {
+                ch = '1';
+            }
+            else if (ch == '2')
+            {
+                ch = 'd';
+            }
+            else if (ch == 'd')
+            {
+                ch = '2';
+            }
+            else if (ch == '3')
+            {
+                ch = 'c';
+            }
+            else if (ch == 'c')
+            {
+                ch = '3';
+            }
+            b = b + ch;
+            //console.log(ch);
+        }
+        return b;
+    }
+
+    /**
+     * Decrypts the encrypted content
+     * @param c the encrypted content
+     * @return the decrypted content
+     */
+    static decryptedContent(c)
+    {
+        var b = '';
+        for (var i = 0; i < c.length; i++)
+        {
+            var ch = c[i];
+            if (ch == 'f')
+            {
+                ch = '0';
+            }
+            else if (ch == '0')
+            {
+                ch = 'f';
+            }
+            else if (ch == 'e')
+            {
+                ch = '1';
+            }
+            else if (ch == '1')
+            {
+                ch = 'e';
+            }
+            else if (ch == 'd')
+            {
+                ch = '2';
+            }
+            else if (ch == '2')
+            {
+                ch = 'd';
+            }
+            else if (ch == 'c')
+            {
+                ch = '3';
+            }
+            else if (ch == '3')
+            {
+                ch = 'c';
+            }
+            b = b + ch;
+            //console.log(ch);
+        }
+        return b;
+    }
+
+    /**
+     * Reads decrypted content, which is read from given encrypted file, into HTTP response stream
+     * @param res the HTTP response stream
+     * @param fDest the encrypted file
+     */
+    static readDecryptedStream(res, fDest, contentType)
+    {
+        res.writeHead(200, {'Content-Type': contentType});
+        var rs = fs.createReadStream(fDest);
+        rs.on('data', function (chunk)
+        {
+            let b = new Buffer(chunk, 'hex');
+
+            let c = b.toString('hex');
+            c = decryptedContent(c);
+
+            let d = Buffer.from(c, 'hex');
+
+            res.write(d);
+        });
+
+        rs.on('end', function ()
+        {
+            res.end();
+            console.log('Succeeded in reading from decrypted stream[' + fDest + '].');
+        });
+
+        rs.on('error', function (err)
+        {
+            console.log(err.stack);
+        });
+    }
+
+    /**
+     * Is video
+     * @param dir the directory
+     * @returns {boolean}
+     */
+    isVideo(dir)
+    {
+        if (dir == "")
+        {
+            return false;
+        }
+        var fileType = dir.split(".")[1];
+        if ("m3u8" == fileType)
+        {
+            return true;
+        }
+        return false;
+    }
+}
+
+module.exports = LjFileHelper;

+ 35 - 0
helper/LjHttpHelper.js

@@ -0,0 +1,35 @@
+var request = require('request');
+var cryptoJS = require("crypto-js");
+var logHelper = require("./LjLogHelper");
+
+/**
+ * The helper of http
+ */
+class LjHttpHelper
+{
+    static request(optinons,callback)
+    {
+        //签名
+        const signStr = 'path='+optinons.url+'&uid='+optinons.uid+'&eid='+optinons.eid+'&'+optinons.token;
+        const sign = cryptoJS.MD5(signStr).toString();
+
+        logHelper.info(optinons);
+        let headers = {
+            'Content-Type':'application/json',
+            'eid':optinons.eid,
+            'uid':optinons.uid,
+            'sign':sign,
+            'terminal':"web",
+            'merchant':"angelbell",
+            'requestId':"11111111111111",
+        };
+
+        let optionsObj = {};
+        optionsObj.url = optinons.url;
+        optionsObj.headers = headers;
+        logHelper.info(optionsObj);
+        request(optionsObj, callback);
+    }
+}
+
+module.exports = LjHttpHelper;

+ 18 - 0
helper/LjLogHelper.js

@@ -0,0 +1,18 @@
+var log4js=require('log4js');
+
+log4js.configure({
+    appenders: {
+        out: { type: 'stdout' },//设置是否在控制台打印日志
+        info: { type: 'file', filename: './logs/info.log' }
+    },
+    categories: {
+        default: { appenders: [ 'out', 'info' ], level: 'info' }//去掉'out'。控制台不打印日志
+    }
+});
+
+var logger = log4js.getLogger('info');
+module.exports = logger;
+
+
+
+

+ 34 - 0
helper/LjStringHelper.js

@@ -0,0 +1,34 @@
+class LjStringHelper
+{
+    /**
+     * Is null
+     * @param str the string
+     * @returns {boolean} true or false
+     */
+    static isNull(str)
+    {
+        if(str == null || str.trim() == '')
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Is non null
+     * @param str the string
+     * @returns {boolean} true or false
+     */
+    static isNonNull(str)
+    {
+        if(str != null && str.trim() != '')
+        {
+            return true;
+        }
+
+        return false;
+    }
+}
+
+module.exports = LjStringHelper;

+ 0 - 0
helper/logs/info.log


+ 0 - 8
ide.general.xml

@@ -1,8 +0,0 @@
-<application>
-  <component name="GeneralSettings">
-    <option name="showTipsOnStartup" value="false" />
-  </component>
-  <component name="Registry">
-    <entry key="ide.tooltip.show.with.actions" value="true" />
-  </component>
-</application>

+ 247 - 0
lessonInfo.json

@@ -0,0 +1,247 @@
+{
+	"code": 200,
+	"success": true,
+	"message": null,
+	"data": {
+		"id": "02279ace371a11e8af2000163e08bde8",
+		"code": "K-02-700004",
+		"title": "位置:左右",
+		"list": [{
+			"id": "022b3a3a371a11e8af2000163e08bde8",
+			"code": "J-02-01-7012",
+			"category": "预习",
+			"title": "预习课参考教学流程",
+			"type": 3,
+			"list": [{
+				"id": "66692",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701201.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66693",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701202.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66694",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701203.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66695",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701204.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66696",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701205.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66697",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701206.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66698",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701207.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66699",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701208.jpg",
+				"img": null,
+				"audio": null
+			}]
+		}, {
+			"id": "022f049e371a11e8af2000163e08bde8",
+			"code": "J-03-02-700008",
+			"category": "预习",
+			"title": "预习视频",
+			"type": 0,
+			"list": [{
+				"id": "66398",
+				"type": 0,
+				"url": "https://efunvideo.ai160.com/vs2m/001/00103023/00103023035/00103023035.m3u8",
+				"img": null,
+				"audio": null
+			}]
+		}, {
+			"id": "0232b3f0371a11e8af2000163e08bde8",
+			"code": "J-02-01-7013",
+			"category": "复习",
+			"title": "复习课参考教学流程",
+			"type": 3,
+			"list": [{
+				"id": "66701",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701301.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "1517367857757670",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701302.jpg",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66703",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701303.jpg",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66704",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701304.jpg",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "1517367884311325",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701305.jpg",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66706",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701306.jpg",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66707",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701307.jpg",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66708",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701308.jpg",
+				"img": null,
+				"audio": null
+			}]
+		}, {
+			"id": "0236f7b2371a11e8af2000163e08bde8",
+			"code": "J-01-01-700006",
+			"category": "复习",
+			"title": "左右的判定",
+			"type": 3,
+			"list": [{
+				"id": "66710",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/01/01/700006.jpg",
+				"img": null,
+				"audio": null
+			}]
+		}, {
+			"id": "023aabf0371a11e8af2000163e08bde8",
+			"code": "J-02-01-7014",
+			"category": "复习",
+			"title": "随堂闯关",
+			"type": 3,
+			"list": [{
+				"id": "66711",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701401.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66712",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701402.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66713",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701403.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66714",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701404.jpg",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66715",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701405.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66716",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701406.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66717",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701407.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66718",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701408.png",
+				"img": null,
+				"audio": null
+			}, {
+				"id": "66719",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/02/01/701409.png",
+				"img": null,
+				"audio": null
+			}]
+		}, {
+			"id": "023e6556371a11e8af2000163e08bde8",
+			"code": "J-01-01-700007",
+			"category": "复习",
+			"title": "钟表法判定左右",
+			"type": 3,
+			"list": [{
+				"id": "66721",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/01/01/700007.png",
+				"img": null,
+				"audio": null
+			}]
+		}, {
+			"id": "02422506371a11e8af2000163e08bde8",
+			"code": "J-01-01-700008",
+			"category": "复习",
+			"title": "小猴子说的对吗?",
+			"type": 3,
+			"list": [{
+				"id": "66722",
+				"type": 3,
+				"url": "https://efunimgs.ai160.com/resources/J/01/01/700008.jpg",
+				"img": null,
+				"audio": null
+			}]
+		}, {
+			"id": "0245d99e371a11e8af2000163e08bde8",
+			"code": "J-03-02-700009",
+			"category": "复习",
+			"title": "复习视频",
+			"type": 0,
+			"list": [{
+				"id": "66399",
+				"type": 0,
+				"url": "https://efunvideo.ai160.com/vs2m/015/01503007/01503007004/01503007004.m3u8",
+				"img": null,
+				"audio": null
+			}]
+		}]
+	}
+}

File diff suppressed because it is too large
+ 3714 - 0
logs/info.log


+ 1 - 0
node_register_service.bat

@@ -0,0 +1 @@
+node C:\John\WorkSpace\WebStorm\winBoxNode\app.js

+ 0 - 14
project.default.xml

@@ -1,14 +0,0 @@
-<application>
-  <component name="ProjectManager">
-    <defaultProject>
-      <component name="InspectionProjectProfileManager">
-        <option name="PROJECT_PROFILE" />
-        <version value="1.0" />
-      </component>
-      <component name="PropertiesComponent">
-        <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
-        <property name="nodejs_npm_path_reset_for_default_project" value="true" />
-      </component>
-    </defaultProject>
-  </component>
-</application>

+ 25 - 0
test/json.js

@@ -0,0 +1,25 @@
+var fs = require('fs');
+var logHelper = require("../helper/LjLogHelper.js");
+
+var lessonJsonObj = JSON.parse(fs.readFileSync("./lessonInfo.json"));
+/*课件-Begin*/
+//课程集合
+var courseList = lessonJsonObj.data.list;
+//课程数
+var courseListSize = courseList.length;
+//遍历课件
+for (var i = 0; i < courseListSize; i++)
+{
+    logHelper.info(courseList[i].title);
+    //资源集合
+    var resourceList = courseList[i].list;
+
+    //资源数
+    var resourceSize = resourceList.length;
+
+    for (var j = 0; j < resourceSize; j++)
+    {
+        logHelper.info(resourceList[j].url);
+    }
+}
+/*课件-End*/