Node.js(nodejs)對本地JSON檔案進行增、刪、改、查操作(輕車熟路)

你摯愛的強哥發表於2019-12-31

專案結構

index.js

//必須要安裝否則就別想執行了❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
//npm i body-parser -D & cnpm i express & cnpm i node-xlsx & cnpm i moment & node index
//全域性引入物件❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
global.SG = {
    config: require("./js/common/config.js"),//全域性配置檔案(不同專案可能需要換下里面的配置)
    $g: require("./js/common/sg.js"),//強哥全域性大物件方法
    express: require("express"),//cnpm i express
    bodyParser: require("body-parser"),//npm i body-parser -D
    fs: require("fs"),
    path: require("path"),
    xlsx: require("node-xlsx"),//cnpm i node-xlsx
    websocket: require("nodejs-websocket"),//cnpm i nodejs-websocket
    moment: require("moment"),//cnpm i moment
    multer: require("multer"),//cnpm i multer
    request: require("request"),
    xmlreader: require("xmlreader"),
    crypto: require("crypto")
};
global.SG.router = global.SG.express.Router();//全域性路由

//----------------------------------------------------------------
const app = global.SG.express(),
    bodyParser = global.SG.bodyParser,
    API_PATH = global.SG.config.API_PATH || "/api",
    port = global.SG.config.port || 9999;
app.listen(port, () => console.log(`測試讀取資料地址:http://127.0.0.1:${port}/api/demo/select`));//列印一下介面用例地址
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
//設定跨域訪問
app.all("*", (req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "*");
    res.header("Access-Control-Allow-Methods", "*");
    res.header("X-Powered-By", "http://www.shuzhiqiang.com");
    res.header("Content-Type", "application/json;charset=utf-8");
    res.header("Access-Control-Allow-Credentials", true);//攜帶cookie跨域請求
    req.method.toUpperCase() === "OPTIONS" ? res.sendStatus(200) : next();//防止在預請求階段就響應介面
});

//加入前端需要訪問的介面API名稱❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
//增刪改查----------------------------------------------------------------
app.use(API_PATH, require(`.${API_PATH}/demo/insert`));//增加資料
app.use(API_PATH, require(`.${API_PATH}/demo/delete`));//刪除資料
app.use(API_PATH, require(`.${API_PATH}/demo/update`));//修改資料
app.use(API_PATH, require(`.${API_PATH}/demo/select`));//查詢資料
app.use(API_PATH, require(`.${API_PATH}/demo/CURD`));//增刪改查資料

//WebSocket----------------------------------------------------------------
app.use(API_PATH, require(`.${API_PATH}/demo/websocket`));//websocket

//支付----------------------------------------------------------------
app.use(API_PATH, require(`.${API_PATH}/demo/wxpay`));//微信支付

//檔案處理----------------------------------------------------------------
app.use(API_PATH, require(`.${API_PATH}/demo/copyFileOrFolder`));//複製檔案or資料夾
app.use(API_PATH, require(`.${API_PATH}/demo/deleteFileOrFolder`));//刪除檔案or資料夾
app.use(API_PATH, require(`.${API_PATH}/demo/exportAndDownloadExcel`));//匯出並下載Excel
app.use(API_PATH, require(`.${API_PATH}/demo/uploadExcel`));//上傳並解析Excel

js/common/config.js

module.exports = {
    API_PATH: "/api",//介面統一字首以及介面檔案目錄資料夾名
    port: 9999//設定埠號,如果埠號被佔用需要自己修改,否則無法跑起來(建議不要用80和8080,一般情況都會被佔用)
};

 js/common/sg.js

module.exports = {
    //CURD________________________
    CURD: {
        hasAndNoHasFields(req, hasFields = [], noHasFields = []) {
            const a = hasFields.length === 0 ? this.hasExceptFields(req, noHasFields) : this.hasFields(req, hasFields, true);
            const b = noHasFields.length === 0 ? !this.hasExceptFields(req, hasFields) : this.hasFields(req, noHasFields, false);
            return a && b;
        },
        hasExceptFields(body, exceptFields) {
            for (let key in body) {
                if (!exceptFields.includes(key)) return true;//判斷是否包含指定欄位以外的未知欄位
            }
            return false;//不包含指定欄位以外的欄位
        },
        hasFields(body, fields, isHasOrNoHas) {
            let fieldLen = 0;
            for (let i = 0, len = fields.length; i < len; i++) {
                let field = fields[i];
                if (isHasOrNoHas) {
                    body.hasOwnProperty(field) && fieldLen++;//判斷是否都包含
                } else {
                    body.hasOwnProperty(field) || fieldLen++; //判斷是否都不包含
                }
            }
            return fields.length === fieldLen;
        }
    },
    //對檔案路徑的處理________________________
    dir: {
        delayDestroyFile(filePath, delayDestroyFileSecond = 60) {
            setTimeout(() => {
                    global.SG.fs.exists(filePath, exists => {
                        if (exists) {
                            global.SG.fs.statSync(filePath).isFile() ? global.SG.fs.unlink(filePath, err => console.log(`${module.exports.date.nowtime()}刪除${filePath}${err ? "失敗" : "成功"}`)) : console.log(`${module.exports.date.nowtime()}刪除失敗(該路徑不是一個有效的檔案路徑,注意需要檔案而不是資料夾的路徑!)`);
                        } else {
                            console.log(`${module.exports.date.nowtime()}刪除失敗(該路徑${filePath}所對應的檔案或者資料夾不存在!)`);
                        }
                    });
                }
                , 1000 * delayDestroyFileSecond);
        },//延時銷燬伺服器檔案
        mkdirsByFolderPath: (folderPath, callback) => global.SG.fs.exists(folderPath, exists => (exists ? callback() : (module.exports.dir.mkdirsByFolderPath(global.SG.path.dirname(folderPath), () => global.SG.fs.mkdir(folderPath, callback))))),//遞迴建立資料夾目錄(基於資料夾路徑)
        mkdirsByFilePath: (filePath, callback) => (filePath = global.SG.path.dirname(filePath), global.SG.fs.exists(filePath, exists => exists ? callback() : module.exports.dir.mkdirsByFilePath(filePath, () => global.SG.fs.mkdir(filePath, callback))))//遞迴建立資料夾目錄(基於檔案路徑)
    },
    json: {
        //返回體報文結構公共方法________________________
        res(req, res, msg, data, success = true) {
            res.json({nowtime: module.exports.date.nowtime(), token: req.headers.token, code: success ? 0 : -1, success, msg, data});
        }
    },
    array: {
        /* 判斷一個陣列(支援一個字串)裡面的是否有任何一個元素被包含在了某個字串裡面 */
        isStringContain(str, arr) {
            Array.isArray(arr) || (arr = [arr]);
            for (let i = 0, len = arr.length; i < len; i++) {
                if (str.includes(arr[i])) return true; //只要有一個元素被包含了就終止迴圈
            }
            return false;
        },
        /**獲取陣列最大值*/
        getMax(arr) {
            // 利用apply 將陣列元素拆成一個個引數讓Math.max去計算
            // return Math.max.apply(null, arr);  // ES5寫法;
            return Math.max(...arr); // ES6寫法;
        },
        /**獲取陣列最小值*/
        getMin(arr) {
            // 利用apply 將陣列元素拆成一個個引數讓Math.min去計算
            // return Math.min.apply(null, arr);// ES5寫法
            return Math.min(...arr); // ES6寫法;
        },
        /**判斷是否為陣列型別*/
        isArray(o) {
            return Object.prototype.toString.call(o) == "[object Array]";
        },
        /**刪除陣列中指定元素*/
        removeFirstByValue(val) {
            for (let i = 0, len = arr.length; i < len; i++) {
                let a = arr[i];
                if (a == val) {
                    arr.splice(i, 1);
                    break;
                }
            }
            return arr;
            /*測試用例*/
            /*let arr = ["mon", "tue", "wed", "thur"];
            alert(removeFirstByValue(arr, "wed"));*/
        },
        /**刪除陣列中指定匹配的所有元素*/
        removeAllByValue(val) {
            let newArr = [];
            for (let i = 0, len = arr.length; i < len; i++) {
                let a = arr[i];
                a != val && newArr.push(a);
            }
            return newArr;
            /*測試用例*/
            /*let arr = ["mon", "tue", "wed","wed","wed", "thur"];
            alert(removeAllByValue(arr, "wed"));*/
        },
        /**刪除對應鍵值的→第一個元素*/
        removeFirstByMatchKey(arr, macthKey, matchKeyValue) {
            for (let i = 0, len = arr.length; i < len; i++) {
                let a = arr[i];
                if (a[macthKey] == matchKeyValue) {
                    arr.splice(i, 1);
                    break;
                }
            }
            return arr;
        },
        /**刪除對應鍵值的→所有元素*/
        removeAllByMatchKey(arr, macthKey, matchKeyValue) {
            let newArr = [];
            for (let i = 0, len = arr.length; i < len; i++) {
                let a = arr[i];
                a[macthKey] != matchKeyValue && newArr.push(a);
            }
            return newArr;
        },
        /**移動陣列裡面的對應元素step個位置,注意!!!會直接修改原陣列*/
        moveArray(arr, index, step) {
            /*如step為負數,則往前面移動對應步數。如:-2往前移動兩步,3往後移動三步*/
            let moveToIndex = index + step;
            moveToIndex < 0 && (moveToIndex = arr.length - 1);
            moveToIndex > arr.length - 1 && (moveToIndex = 0);
            arr.splice(moveToIndex, 0, arr.splice(index, 1)[0]);
            return arr;
            /*測試用例*/
            /*let arr = ['第一個', '第二個', '第三個', '第四個']; array.moveArray(arr, 1, -2); /!*第二個元素往前移動2步,將會移動到陣列最後一個位置*!/ console.log(arr);*/
        },
        /**把陣列裡面的對應元素插入到某個位置,注意!!!會直接修改原陣列*/
        jumpQueue(arr, currentIndex, targetIndex) {
            /*把陣列arr裡面的currentIndex索引插到targetIndex索引位置*/
            if (!arr || arr.length === 0) return console.log("%c報錯資訊:", "background:red;color:white;padding:5px;border-radius:5px;", "arr不能為空");
            if (currentIndex < 0 || targetIndex < 0 || currentIndex > arr.length - 1 || targetIndex > arr.length - 1) return console.log("%c報錯資訊:", "background:red;color:white;padding:5px;border-radius:5px;", "currentIndex或者targetIndex超出了arr的索引範圍");
            arr.splice(targetIndex, 0, arr.splice(currentIndex, 1)[0]);
            return arr;
            /*測試用例*/
            /*let arr = ['第一個', '第二個', '第三個', '第四個']; array.jumpQueue(arr, 3, 0); /!*第四個元素插隊到第一個位置*!/ console.log(arr);*/
        },
        /**對比兩個陣列不同元素,從第一個陣列裡面排除第二個陣列裡面相同元素,isAddBdiffPart為true時加入第二個陣列不同部分返回結果*/
        getdiffarr(A, B, isAddBdiffPart) {
            let C = [];
            let D = [];
            let Astr = "," + A.toString() + ",";
            let Bstr = "," + B.toString() + ",";
            for (let i in A) {
                if (!Bstr.includes("," + A[i] + ",")) {
                    C.push(A[i]);
                }
            }
            for (let p in B) {
                if (!Astr.includes("," + B[p] + ",")) {
                    D.push(B[p]);
                }
            }
            return isAddBdiffPart ? C.concat(D) : C;
            /*測試用例*/
            /*let F = array.getdiffarr([9, 7, 1, 2, 3, 4], [3, 4, 1, 8], true); console.log(F);*/
        },
        /**陣列排序:isAsc=true升序;isAsc=false降序*/
        getSort(arr, isAsc) {
            var arr = arr.concat();
            arr.sort((a, b) => {
                return isAsc ? a - b : b - a;
            });
            return arr;
        },
        /**關聯陣列排序:isAsc=true升序;isAsc=false降序*/
        getSortByKey(arr, key, isAsc) {
            let o = arr.concat();
            o.sort((a, b) => {
                return isAsc ? a[key] - b[key] : b[key] - a[key];
            });
            return o;
        },
        /**陣列物件根據某個值相同合併分組(collectKeyName是用於比對合並的鍵值,addOtherKeys是附加的鍵值)*/
        collect(arr, collectKeyName, addOtherKeys) {
            let map = {},
                arr2 = [];
            for (let i = 0, len = arr.length; i < len; i++) {
                let a = arr[i];
                if (!map[a[collectKeyName]]) {
                    let obj = {collectName: a[collectKeyName], collectValue: [a]};
                    /*追加可選鍵值*/
                    let arr3 = addOtherKeys || [];
                    for (let k = 0, len3 = arr3.length; k < len3; k++) {
                        let c = arr3[k];
                        obj[c] = a[c];
                    }
                    arr2.push(obj);
                    map[a[collectKeyName]] = a;
                } else {
                    for (let j = 0, len2 = arr2.length; j < len2; j++) {
                        let b = arr2[j];
                        if (b.collectName == a[collectKeyName]) {
                            b.collectValue.push(a);
                            break;
                        }
                    }
                }
            }
            return arr2;
        },
        /**獲取ID→對應的記錄*/
        getById(arr, id) {
            return this.getByMatchKey(arr, "id", id);
        },
        /**獲取ID→對應的值*/
        getValueById(arr, id) {
            let re = this.getById(arr, id);
            return re ? re.value : null;
        },
        /**獲取對應值的→ID*/
        getIdByValue(arr, value) {
            let re = this.getByMatchKey(arr, "value", value);
            return re ? re.id : null;
        },
        /**獲取對應值的→記錄*/
        getByMatchKey(arr, matchKey, matchKeyValue) {
            for (let k in arr) {
                let a = arr[k];
                if (a && a[matchKey] == matchKeyValue) {
                    return a;
                }
            }
        },
        /**獲取對應值的→鍵的值*/
        getValueByMatchKey(arr, matchKey, matchKeyValue, keyName) {
            let re = this.getByMatchKey(arr, matchKey, matchKeyValue);
            return re ? re[keyName] : null;
        },
        /**設定陣列對應ID→對應的key值*/
        setKeyValueById(arr, id, keyName, keyValue) {
            this.setValueByMatchKey(arr, "id", id, keyName, keyValue);
        },
        /**設定陣列對應自定義匹配key→對應的值keyValue*/
        setValueByMatchKey(arr, matchKey, matchKeyValue, keyName, keyValue) {
            for (let k in arr) {
                let a = arr[k];
                if (a && a[matchKey] == matchKeyValue) {
                    a[keyName] = keyValue;
                }
            }
        },
        /**根據對應自定義匹配key→對應的值index*/
        getIndexByMatchKey(arr, matchKey, matchKeyValue) {
            for (let k in arr) {
                let a = arr[k];
                if (a && a[matchKey] == matchKeyValue) {
                    return k; //返回值記得用parseInt()轉換為int型別,如果搜尋的arr是一個object物件則不用轉換值型別,返回的就是key的字串
                }
            }
        },
        /**根據value的值獲取元素索引值index*/
        getIndexByValue(arr, value) {
            return this.getIndexByMatchKey(arr, "value", value);
        },
        /**根據id的值獲取元素索引值index*/
        getIndexById(arr, id) {
            return this.getIndexByMatchKey(arr, "id", id);
        },
        /**獲取陣列對應key→對應的valueKey值(key的格式{key: "id", value: 2, valueKey: "b"}),指定對應id等於2的b欄位返回值;valueKey為空時返回整個元素記錄*/
        getkeyValueByKeyValue(arr, key) {
            for (let k in arr) {
                let a = arr[k];
                if (a[key.key] == key.value) {
                    return key.valueKey ? a[key.valueKey] : a;
                }
            }
            /*測試用例*/
            /* console.log(getkeyValueByKeyValue([{id: 1, a: 11, b: 111}, {id: 2, a: 22, b: 222}], {key: "id", value: 2, valueKey: "b"}));*/
        },
        /**設定陣列對應key→對應的valueKey值(key的格式{key: "id", value: 2, setKey: "b", setValue: "999"}),設定對應id等於2的b欄位的值為999*/
        setkeyValueByKeyValue(arr, key) {
            for (let k in arr) {
                let a = arr[k];
                if (a[key.key] == key.value) {
                    a[key.setKey] = key.setValue;
                }
            }
            return arr;
            /*測試用例*/
            /* console.log(setkeyValueByKeyValue([{id: 1, a: 11, b: 111}, {id: 2, a: 22, b: 222}], {key: "id", value: 2, setKey: "b", setValue: 999}));*/
        },
        /**根據by陣列的key對應的值→去from的arr陣列裡面查詢key對應的值相同的項並返回陣列,o的結構: { from: { arr: arr1, key: "value", }, by: { arr: arr2, key: "id", } } */
        getArrayByTwoKey(o) {
            let reArr = [];
            let arr1 = o.from.arr,
                k1 = o.from.key,
                arr2 = o.by.arr,
                k2 = o.by.key;
            for (let i = 0, len = arr2.length; i < len; i++) {
                let b = arr2[i];
                arr1.forEach(a => {
                    a[k1] == (k2 ? b[k2] : b) && reArr.push(a);
                });
            }
            return reArr;
        },
        __convertToKeyValueObject(obj) {
            for (let i in obj) {
                let a = obj[i];
                return {"key": i, "value": a};
            }
        },
        /**模糊搜尋key→對應的value值(obj的格式{keyName:keyValue})*/
        searchArrayByKey(arr, obj) {
            let reArr = [];
            obj = this.__convertToKeyValueObject(obj);
            for (let k in arr) {
                let a = arr[k];
                if (a[obj.key].toString().includes(obj.value)) {
                    reArr.push(a);
                }
            }
            return reArr;
        },
        /**模糊搜尋→全欄位值匹配*/
        searchArrayByValue(arr, value) {
            let reArr = [];
            for (let i = 0, len = arr.length; i < len; i++) {
                let a = arr[i];
                for (let k in a) {
                    let b = a[k];
                    if (b.toString().toLowerCase().includes(value.toLowerCase())) {
                        reArr.push(a);
                        break;
                    }
                }
            }
            return reArr;
        },
        /**獲取longString字串中被startStr和end重複夾住的字串*/
        getBetween(longString, startStr, endStr) {
            let arr = longString.split(startStr),
                reArr = [];
            arr.shift();
            for (let i = 0, len = arr.length; i < len; i++) {
                let a = arr[i];
                reArr.push(a.split(endStr)[0]);
            }
            return reArr;
        },
        /**用指定字串分割將相同元素歸類,並返回新的陣列*/
        getSortOutArrayBySplit(arr, splitStr) {
            let retArr = [],
                ind = -1,
                oldValue;
            for (let i = 0, len = arr.length; i < len; i++) {
                let newValue = arr[i];
                oldValue == newValue ? (retArr[ind] = retArr[ind] + (splitStr || "/") + newValue) : (oldValue = newValue, ind++, retArr[ind] = newValue);
            }
            return retArr;
            /* 測試用例
             let subList = [1, 1, 1, 2, 2, 3, 3];
             console.log(array.getSortOutArrayBySplit(subList,'/'));//output: ["1/1/1", "2/2", "3/3"];
             */
        },
        /**去重(效率最高的方法)*/
        distinct(arr) {
            let re = [],
                obj = {};
            for (let i of arr) {
                obj[i] || (re.push(i), obj[i] = true);
            }
            return re;
            // return [...new Set(arr)];//去重最精簡方法
        },
        /** es6語法:過濾JS陣列中的空值,假值等(es6語法) */
        filterNullUndefined: arr => arr.filter(item => item)
        //測試用例
        //console.log(array.filterNullUndefined([undefined, undefined, 1, "", "false", false, true, null, "null"]));
    },
    /**驗證一切*/
    checkEverything(type, s) {
        switch (type.toString().toLocaleLowerCase()) {
            case "postcode":
                /**驗證郵政編碼*/
                return /^(0[1234567]|1[012356]|2[01234567]|3[0123456]|4[01234567]|5[1234567]|6[1234567]|7[012345]|8[013456])\d{4}$/.test(s);
            case "uppercase":
                /**驗證是否包含大寫字母*/
                return /[A-Z]/.test(s);
            case "car":
                s = s.toString();
                if (s.length == 8) {
                    return /^[京津滬渝冀豫雲遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陝吉閩貴粵青藏川寧瓊使領A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/.test(s);
                } else if (s.length == 7) {
                    return /^[京津滬渝冀豫雲遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陝吉閩貴粵青藏川寧瓊使領A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9掛學警港澳]{1}$/.test(s);
                } else {
                    return false;
                }
            case "integer":
                return /^[0-9]+$/.test(s);
            case "special":
                return /[\<\>]/.test(s);
            case "name":
                /*中文名*/
                return /^[\u4E00-\u9FA5\uf900-\ufa2d·s]{2,20}$/.test(s);
            case "cn":
                /*包含中文*/
                return /[\u4E00-\u9FA5]/i.test(s);
            case "id":
                /*身份證*/
                return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(s);
            case "user":
                /*賬號*/
                return /^[a-zA-z]\w{3,15}$/.test(s);
            case "httpurl":
                return /(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(s);
            case "url":
                return /^(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/.test(s);
            case "mobile":
                /*手機號*/
                return /^1\d{10}$/.test(s);
            case "tel":
                /*座機號*/
                return /^0\d{2,3}-?\d{7,8}$/.test(s);
            case "email":
                return /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/.test(s);
            case "number":
                return /^\d+$/g.test(s);
            case "password":
                if (s == "") {
                    return false;
                } else if (s.split(" ").length != 1) {
                    return false;
                } else {
                    if ((s.search(/^[a-zA-Z]+$/g) != -1) || (s.search(/^[0-9]+$/g) != -1)) {
                        return false;
                    } else if (s.search(/^[a-zA-Z0-9]+$/g) != -1) {
                        return false;
                    } else {
                        return false;
                    }
                }
                return true;
        }
    },
    date: {
        nowtime: () => global.SG.moment().format("YYYY-MM-DD HH:mm:ss:ms"),//獲取當前時間(含毫秒)
        timestamp: () => (global.SG.moment().format("YYYYMMDDHHmmssms") + new Date().getTime() + Math.random()).replace(/\./g, ""),//獲取時間戳()
        //新方法(時:分:秒)
        HH_mm_ss(date = null) {
            return new Date(date).toLocaleString("zh-Hans-CN", {hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false});
        },
        //新方法(年-月-日)
        yyyy_MM_dd(date = null) {
            return new Date(date).toLocaleString("zh-Hans-CN", {year: "numeric", month: "2-digit", day: "2-digit"}).replace(/\//g, "-");
        },
        //新方法(年-月-日 時:分:秒)
        yyyy_MM_dd_HH_mm_ss(date = null) {
            return new Date(date).toLocaleString("zh-Hans-CN", {year: "numeric", month: "2-digit", day: "2-digit", hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit"}).replace(/\//g, "-");
        },
        yearMonthDay() {
            return new Date().getFullYear() + ("0" + (new Date().getMonth() + 1)).slice(-2) + ("0" + new Date().getDate()).slice(-2);
        },
        year_Month_Day() {
            return new Date().getFullYear() + "-" + ("0" + (new Date().getMonth() + 1)).slice(-2) + "-" + ("0" + new Date().getDate()).slice(-2);
        },
        yMd(dt, split) {
            dt || (dt = new Date());
            split || (split = "-");
            return dt.getFullYear() + split + ("0" + (dt.getMonth() + 1)).slice(-2) + split + ("0" + dt.getDate()).slice(-2);
        },
        /**判斷是否逾期*/
        over(endDate, isEqual) {
            let d1 = new Date().getTime(),
                d2 = new Date(endDate).getTime();
            return isEqual ? d1 >= d2 : d1 > d2;
        },
        /**比較日期大小,前一個日期大於(isEqual=true時 比較大於等於)後一個日期時返回true*/
        compare(d1, d2, isEqual) {
            d1 = new Date(d1).getTime(), d2 = new Date(d2).getTime();
            return isEqual ? d1 >= d2 : d1 > d2;
        },
        /**獲取指定日期之前/之後的某天*/
        pointDate(dt, n) {
            if (!n) return dt;
            let s = "/";
            if (dt.indexOf("-") > -1) {
                s = "-", dt = dt.replace(/-/g, "/");
            } else if (dt.indexOf(".") > -1) {
                s = ".", dt = dt.replace(/\./g, "/");
            }
            let d = new Date(dt),
                lw = new Date(Number(d) + 1000 * 60 * 60 * 24 * Math.floor(n)),
                /*n天數*/
                ly = lw.getFullYear(),
                lm = lw.getMonth() + 1,
                ld = lw.getDate(),
                sd = ly + s + (lm < 10 ? "0" + lm : lm) + s + (ld < 10 ? "0" + ld : ld);
            return sd;
        },
        /**獲得當前日期之前之後任意天的日期*/
        anyDate(n) {
            let dt = new Date();
            dt.setDate(dt.getDate() + n);
            return date.yMd(dt);
        },
        /**獲得當前日期之前之後任意天的日期+時間*/
        anyDateTime(n) {
            let dt = new Date();
            dt.setDate(dt.getDate() + n);
            return formatDateTime(dt);
        },
        /**獲得任意天的日期時間戳:n為負數就是過去的天數,正數則為未來的天數*/
        anyDateTimeStamp(n) {
            return new Date(date.anyDate(n) + " 00:00:00").getTime();
        },
        /**獲得本月的開始日期、結束日期*/
        monthStartOrEndDate(isStart) {
            let now = new Date(),
                m = now.getMonth(),
                y = now.getFullYear(),
                msd = new Date(y, m, Boolean(isStart) ? 1 : new Date(y, m + 1, 0).getDate());
            return date.yMd(msd);
        },
        /**獲得本週的開始日期、結束日期*/
        weekStartOrEndDate(isStart) {
            let now = new Date(),
                d = now.getDay(),
                nd = now.getDate(),
                m = now.getMonth(),
                y = now.getFullYear(),
                wsd = new Date(y, m, nd + (Boolean(isStart) ? -d : 6 - d));
            return date.yMd(wsd);
        },
        /**計算指定日期加上多少天、加多少月、加多少年的日期*/
        add(type, number, date) {
            let d = date ? (date instanceof Date ? date : new Date(date)) : new Date();
            switch (type) {
                case "y":
                    d.setFullYear(d.getFullYear() + number);
                    return d;
                case "q":
                    d.setMonth(d.getMonth() + number * 3);
                    return d;
                case "m":
                    d.setMonth(d.getMonth() + number);
                    return d;
                case "w":
                    d.setDate(d.getDate() + number * 7);
                    return d;
                case "d":
                    d.setDate(d.getDate() + number);
                    return d;
                case "h":
                    d.setHours(d.getHours() + number);
                    return d;
                case "m":
                    d.setMinutes(d.getMinutes() + number);
                    return d;
                case "s":
                    d.setSeconds(d.getSeconds() + number);
                    return d;
                default:
                    d.setDate(d.getDate() + number);
                    return d;
            }
            /*/!* 加2天.*!/ alert(date.add("d ", 2).toLocaleString()) /!* 加2月.*!/ alert(date.add("m ", 2).toLocaleString()) /!* 加2年*!/ alert(date.add("y ", 2).toLocaleString());*/
        },
        format(date, fmt) {
            date = date instanceof Date ? date : new Date(date);
            let o = {
                "M+": date.getMonth() + 1,
                "d+": date.getDate(),
                "h+": date.getHours() % 12 == 0 ? 12 : date.getHours() % 12,
                "H+": date.getHours(),
                "m+": date.getMinutes(),
                "s+": date.getSeconds(),
                "q+": Math.floor((date.getMonth() + 3) / 3),
                "S": date.getMilliseconds()
            };
            if (/(y+)/.test(fmt)) {
                fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
            }
            if (/(E+)/.test(fmt)) {
                fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "星期" : "周") : "") + "日一二三四五六".charAt(date.getDay()));
            }
            for (let k in o) {
                if (new RegExp("(" + k + ")").test(fmt)) {
                    fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
                }
            }
            return fmt;
        },
        /**格式化日期:yyyy-MM-dd HH:mm:ss */
        formatDate(timeStamp) {
            return date.format(timeStamp ? (timeStamp instanceof Date ? timeStamp : new Date(timeStamp)) : new Date(), "yyyy-MM-dd");
        },
        /**格式化日期:yyyy-MM-dd HH:mm:ss */
        formatDateTime(timeStamp) {
            return date.format(timeStamp ? (timeStamp instanceof Date ? timeStamp : new Date(timeStamp)) : new Date(), "yyyy-MM-dd HH:mm:ss");
        },
        /**格式化日期:yyyy年MM月dd日 HH:mm:ss */
        formatToyyyyMMddHHmmssEE(timeStamp) {
            return date.format(timeStamp ? (timeStamp instanceof Date ? timeStamp : new Date(timeStamp)) : new Date(), "yyyy年MM月dd日 HH:mm:ss EE");
        },
        getDay() {
            return "星期" + "日一二三四五六".charAt(new Date().getDay());
        },
        /**轉換Date為24小時計時時間格式*/
        to24hours(date) {
            let now = date ? (date instanceof Date ? date : new Date(date)) : new Date();
            now = now.toLocaleTimeString("zh-Hans-CN", {hour12: false}),
                now = now.substr(0, now.lastIndexOf(":"));
            return now;
        },
        /**將秒數量轉換為時分秒字串*/
        toHourMinuteSecond(second, data) {
            let t = "",
                s = Math.round(second),
                d = data.isDoubleDigits, //顯示雙位數
                hz = data.hideZero, //隱藏為0的時間單位
                hh = data.hideHour, //隱藏小時
                hm = data.hideMinute, //隱藏分鐘
                hs = data.hideSecond; //隱藏秒鐘
            if (s > 0) {
                let hour = Math.floor(s / 3600),
                    min = Math.floor(s / 60) % 60,
                    sec = s % 60;
                hh || (hz && !hour) || (d && hour < 10 && (t += "0"), t += hour + "時");
                hm || (hz && !min) || (d && min < 10 && (t += "0"), t += min + "分");
                hs || (hz && !sec) || (d && sec < 10 && (t += "0"), t += sec + "秒");
            }
            return t;
            //測試用例
            /*alert(toHourMinuteSecond(3661,{
                // isDoubleDigits:true,
                hideZero:true,
                // hideHour:true,
                // hideMinute:true,
                // hideSecond:true,
            }));*/
        },
        /**獲取最近幾個月的年月份*/
        getRecentSeveralMonth(n) {
            let date = new Date();
            let nearMonth = [];
            for (let i = 1; i <= n; i++) {
                date.setMonth(date.getMonth() - 1);
                nearMonth.unshift(date.getFullYear() + "/" + (date.getMonth() + 1));
            }
            return nearMonth;
        },
        /**把時間轉換為分鐘數*/
        hourMinuteToMinute(timeString) {
            timeString = timeString.replace(/:/g, ":").replace(/\ |\ /g, "").replace(/::/g, ":").split(":");
            return parseInt(timeString[0] * 60) + parseInt(timeString[1]);
        },
        /**顯示幾分鐘前剛剛釋出文章*/
        timeAgo(timeStamp) {
            let minute = 1000 * 60,
                hour = minute * 60,
                day = hour * 24,
                week = day * 7,
                month = day * 30,
                now = new Date().getTime(),
                diffValue = now - timeStamp;
            let minC = diffValue / minute,
                hourC = diffValue / hour,
                dayC = diffValue / day,
                weekC = diffValue / week,
                monthC = diffValue / month,
                res;
            if (monthC > 3 && monthC < 12) {
                res = "半年前";
            } else if (monthC >= 1 && monthC <= 3) {
                res = parseInt(monthC) + "月前";
            } else if (weekC >= 1 && weekC < 4) {
                res = parseInt(weekC) + "周前";
            } else if (dayC >= 1 && dayC < 7) {
                res = parseInt(dayC) + "天前";
            } else if (hourC >= 1 && hourC < 24) {
                res = parseInt(hourC) + "小時前";
            } else if (minC >= 1 && minC < 60) {
                res = parseInt(minC) + "分鐘前";
            } else if (diffValue >= 0 && diffValue <= minute) {
                res = "剛剛";
            } else {
                res = this.formatDateTime(timeStamp);
            }
            return res;
        },
        between(startDate, endDate) {
            startDate = startDate instanceof Date ? startDate : new Date(startDate);
            endDate = endDate instanceof Date ? endDate : new Date(endDate);
            var today = new Date().getTime(),
                startDate = new Date(startDate).getTime(),
                endDate = new Date(endDate).getTime();
            return startDate < today && today < endDate;
        },
        /**計算兩個日期相差天數*/
        getDayBetween(startDate, endDate) {
            startDate = startDate instanceof Date ? startDate : new Date(startDate);
            endDate = endDate instanceof Date ? endDate : new Date(endDate);
            return Math.floor(this.getMillisecondBetween(startDate, endDate));
        },
        /**計算兩個日期相差毫秒數*/
        getMillisecondBetween(startDate, endDate) {
            startDate = startDate instanceof Date ? startDate : new Date(startDate);
            endDate = endDate instanceof Date ? endDate : new Date(endDate);
            return Math.abs((Date.parse(endDate) - Date.parse(startDate)) / 86400000);
        }
    }
};

api/demo/insert.js

const $g = global.SG.$g, fs = global.SG.fs, router = global.SG.router;
module.exports = global.SG.router;

const writeJSON = (url, params, success, fail) => {
    fs.readFile(url, (err, data) => {
        if (err) {
            fail && fail({code: -1, msg: "讀取資料失敗", data: err});
            return console.error($g.date.nowtime() + "\n", err, "\n----新增失敗----");
        }
        data = JSON.parse(data.toString());
        data.push(params);
        fs.writeFile(url, JSON.stringify(data), err => {
            if (err) {
                fail && fail({code: -1, msg: "寫入資料失敗", data: err});
                return console.error($g.date.nowtime() + "\n", err, "\n----新增失敗----");
            }
            success && success({change: params, data});//回顯發生改變的內容用於關聯表處理的前端業務邏輯
            console.log($g.date.nowtime() + "\n", data, "\n----新增成功----");
        });
    });
};

//新增資料(all方法支援POST、GET、PUT、PATCH、DELETE傳參方式)
router.all("/demo/insert", (req, res) => {
    const name = req.body.name || req.query.name;
    const tel = req.body.tel || req.query.tel;
    let params = {id: $g.date.timestamp(), name: name, tel: tel};
    if (!params.name) return $g.json.res(req, res, "缺少姓名欄位", params, false);
    if (!params.tel) return $g.json.res(req, res, "缺少手機號欄位", data, false);
    if (!$g.checkEverything("mobile", params.tel)) return $g.json.res(req, res, "手機號格式不正確", params, false);
    writeJSON("json/demo/demo.json", params, data => $g.json.res(req, res, "新增成功", data, true), err => $g.json.res(req, res, err.msg || "新增失敗", err.data, false));
});

 api/demo/delete.js

const $g = global.SG.$g, fs = global.SG.fs, router = global.SG.router;
module.exports = global.SG.router;

const writeJSON = (url, id, success, fail) => {
    const ids = Array.isArray(id) ? id : [id.toString()]; //批量刪除功能
    fs.readFile(url, (err, data) => {
        if (err) {
            fail && fail({code: -1, msg: "讀取資料失敗", data: err});
            return console.error($g.date.nowtime() + "\n", err, "\n----刪除失敗----");
        }
        data = JSON.parse(data.toString());
        let arr = data, re = [], successIds = [], changes = [];
        for (let i = 0, len = arr.length; i < len; i++) {
            let a = arr[i];
            ids.includes((a.id || "null").toString()) ? (successIds.push(a.id), changes.push(a)) : re.push(a);
        }
        if (!successIds.length) {
            fail && fail({code: -1, msg: `沒有找到對應id:${ids}的記錄,刪除失敗`, data});
            return console.error($g.date.nowtime(), "\n----刪除失敗----");
        }
        fs.writeFile(url, JSON.stringify(re), err => {
            if (err) {
                fail && fail({code: -1, msg: "寫入資料失敗", data: err});
                return console.error($g.date.nowtime() + "\n", err, "\n----刪除失敗----");
            }
            success && success({change: changes, data: re});//回顯發生改變的內容用於關聯表處理的前端業務邏輯
            console.log($g.date.nowtime() + "\n", re, `\n----id:${successIds}刪除成功----`);
        });
    });
};

//刪除資料(all方法支援POST、GET、PUT、PATCH、DELETE傳參方式)
router.all("/demo/delete", (req, res) => {
    const id = req.body.id || req.query.id;
    if (!id) return $g.json.res(req, res, "缺少id欄位", id, false);
    writeJSON("json/demo/demo.json", id, data => $g.json.res(req, res, "刪除成功", data, true), err => $g.json.res(req, res, err.msg || "刪除失敗", err.data, false));
});

 api/demo/update.js

const $g = global.SG.$g, fs = global.SG.fs, router = global.SG.router;
module.exports = global.SG.router;

const writeJSON = (url, params, success, fail) => {
    let id = params.id;
    delete params.id;
    fs.readFile(url, (err, data) => {
        if (err) {
            fail && fail({code: -1, msg: "讀取資料失敗", data: err});
            return console.error($g.date.nowtime() + "\n", err, "\n----修改失敗----");
        }
        data = JSON.parse(data.toString());
        let change = null, arr = data;
        for (let i = 0, len = arr.length; i < len; i++) {
            let a = arr[i];
            if (a.id === id) {
                for (let key in params) a[key] = params[key];
                change = a;
                break;
            }
        }
        if (!change) {
            fail && fail({code: -1, msg: `沒有找到對應${id}的記錄,修改失敗`, data});
            return console.error($g.date.nowtime(), "\n----修改失敗----");
        }
        fs.writeFile(url, JSON.stringify(data), err => {
            if (err) {
                fail && fail({code: -1, msg: "寫入資料失敗", data: err});
                return console.error($g.date.nowtime() + "\n", err, "\n----修改失敗----");
            }
            success && success({change, data});//回顯發生改變的內容用於關聯表處理的前端業務邏輯
            console.log($g.date.nowtime() + "\n", data, `\n----id:${id}修改成功----`);
        });
    });
};

//修改資料(all方法支援POST、GET、PUT、PATCH、DELETE傳參方式)
router.all("/demo/update", (req, res) => {
    const id = req.body.id || req.query.id;
    const name = req.body.name || req.query.name;
    const tel = req.body.tel || req.query.tel;
    let params = {};
    id && (params.id = id);
    name && (params.name = name);
    tel && (params.tel = tel);
    if (!params.id) return $g.json.res(req, res, "缺少id欄位", params, false);
    if (params.tel && !$g.checkEverything("mobile", params.tel)) return $g.json.res(req, res, "請輸入正確的手機號", params, false);
    writeJSON("json/demo/demo.json", params, data => $g.json.res(req, res, "修改成功", data, true), err => $g.json.res(req, res, err.msg || "修改失敗", err.data, false));
});

api/demo/select.js

const $g = global.SG.$g, fs = global.SG.fs, router = global.SG.router;
module.exports = global.SG.router;

const isMatch = (record, obj) => {
    let countDefault = 0;
    let countMatch = 0;
    for (let key in obj) {
        countDefault++;
        let value = obj[key];
        record[key] == value && (countMatch++);
    }
    return countDefault === countMatch;
};

const readJSON = (url, params, success, fail) => {
    let pageNum = parseInt(params.pageNum || 0);//預設從第1頁開始
    pageNum < 0 && (pageNum = 0);
    let pageSize = parseInt(params.pageSize || 0);//不傳參就顯示所有資料
    pageSize < 0 && (pageSize = 10);
    delete params.pageNum;
    delete params.pageSize;
    fs.readFile(url, (err, data) => {
        if (err) {
            fail && fail({code: -1, msg: "讀取資料失敗", data: err});
            return console.error($g.date.nowtime() + "\n", err, "\n----查詢失敗----");
        }
        data = JSON.parse(data.toString());
        let re = [];
        let arr = data;
        for (let i = 0, len = arr.length; i < len; i++) {
            let a = arr[i];
            isMatch(a, params) && re.push(a);
        }
        re = re.slice(pageNum * pageSize, pageSize ? (pageNum + 1) * pageSize : re.length);
        success && success({data: re, total: re.length, pageNum: pageNum, pageSize: pageSize});
        console.log($g.date.nowtime() + "\n", re, "\n----查詢成功----");
    });
};

//查詢資料(all方法支援POST、GET、PUT、PATCH、DELETE傳參方式)
router.all("/demo/select", (req, res) => {
    const id = req.body.id || req.query.id;
    const name = req.body.name || req.query.name;
    const tel = req.body.tel || req.query.tel;
    const pageNum = req.body.pageNum || req.query.pageNum;
    const pageSize = req.body.pageSize || req.query.pageSize;
    let params = {};
    id && (params.id = id);
    name && (params.name = name);
    tel && (params.tel = tel);
    pageNum && (params.pageNum = pageNum);
    pageSize && (params.pageSize = pageSize);
    readJSON("json/demo/demo.json", params, data => $g.json.res(req, res, "查詢成功", data, true), err => $g.json.res(req, res, err.msg || "查詢失敗", err.data, false));
});

 json/demo/demo.json

[
  {
    "id": 1,
    "name": "張三",
    "tel": "13888888888"
  },
  {
    "id": 2,
    "name": "李四",
    "tel": "13888888888"
  },
  {
    "id": 3,
    "name": "王五",
    "tel": "13888888888"
  }
]

按照上面的方式建立好專案後,記得在根目錄執行:

npm i body-parser -D & cnpm i express & cnpm i node-xlsx & node index

啟動後訪問:

http://127.0.0.1:9999/api/demo/select

相關文章