项目结构
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
启动后访问: