index.js 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214
  1. /**
  2. * 通用公共函数
  3. */
  4. var pubfn = {};
  5. // 防抖
  6. import debounce from './debounce.js'
  7. // 限流
  8. import throttle from './throttle.js'
  9. // url参数
  10. import queryParams from './queryParams.js'
  11. // H5版本的复制
  12. import setClipboardData from './setClipboardData.js'
  13. // 时间
  14. import timeUtil from './timeUtil.js'
  15. // 树形结构转换
  16. import treeUtil from './treeUtil.js'
  17. /**
  18. * 树形结构转换
  19. */
  20. pubfn.treeUtil = treeUtil;
  21. /**
  22. * 时间工具类
  23. */
  24. pubfn.timeUtil = timeUtil;
  25. /**
  26. * 防抖函数
  27. */
  28. pubfn.debounce = debounce;
  29. /**
  30. * 节流函数
  31. */
  32. pubfn.throttle = throttle;
  33. /**
  34. * 对象转url参数
  35. * @param {*} data,对象
  36. * @param {*} isPrefix,是否自动加上"?"
  37. * 此函数参考uView
  38. * vk.pubfn.queryParams(json);
  39. */
  40. pubfn.queryParams = queryParams;
  41. /**
  42. * 设置剪贴板
  43. */
  44. pubfn.setClipboardData = setClipboardData;
  45. /**
  46. * 休眠,等待(单位毫秒)
  47. * @param {Number} ms 毫秒
  48. * await vk.pubfn.sleep(1000);
  49. */
  50. pubfn.sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  51. /**
  52. * 日期格式化
  53. * @param {Date || Number} date 需要格式化的时间
  54. * vk.pubfn.timeFormat(new Date(),"yyyy-MM-dd hh:mm:ss");
  55. */
  56. pubfn.timeFormat = pubfn.timeUtil.timeFormat;
  57. /**
  58. * 日期对象转换(云函数端会自动转成东八区时间)
  59. * @param {Date || Number} date 需要转换的时间
  60. * @param {Number} type 转换方式
  61. * type = 0 返回 2020-08-03 12:12:12
  62. * type = 1 返回 20200803121212
  63. * type = 2 返回 { YYYY, MM, DD, hh, mm, ss }
  64. * vk.pubfn.getFullTime(new Date());
  65. */
  66. pubfn.getFullTime = pubfn.timeUtil.getFullTime;
  67. /**
  68. * 获取时间范围
  69. * @param {Date} date 日期对象 可以指定时间计算节点,默认使用当前时间进行计算
  70. * 返回的是时间戳(防止时区问题)
  71. * 返回数据如下:
  72. {
  73. todayStart 今日开始时间
  74. todayEnd 今日结束时间
  75. today12End 今日上午结束时间
  76. monthStart 本月开始时间
  77. monthEnd 本月结束时间
  78. yearStart 本年开始时间
  79. yearEnd 本年结束时间
  80. weekStart 本周开始时间
  81. weekEnd 本周结束时间
  82. now 现在的时间点(含月年日时分秒)
  83. months 本年度每月的开始和结束时间 months[1] 代表1月
  84. }
  85. * vk.pubfn.getCommonTime();
  86. */
  87. pubfn.getCommonTime = pubfn.timeUtil.getCommonTime;
  88. /**
  89. * 获得指定时间偏移 year年 month月 day天 hours时 minutes分 seconds秒前或后的时间戳
  90. * 返回时间戳形式
  91. vk.pubfn.getOffsetTime(new Date(), {
  92. year:0,
  93. month:0,
  94. day:0,
  95. hours:0,
  96. minutes:0,
  97. seconds:0,
  98. mode:"after", // after 之后 before 之前
  99. });
  100. */
  101. pubfn.getOffsetTime = pubfn.timeUtil.getOffsetTime;
  102. /**
  103. * 获得相对当前周addWeekCount个周的起止日期
  104. * @param {Number} addWeekCount 默认0 (0代表本周 为-1代表上周 为1代表下周以此类推 为2代表下下周)
  105. * vk.pubfn.getWeekStartAndEnd(0);
  106. */
  107. pubfn.getWeekStartAndEnd = pubfn.timeUtil.getWeekStartAndEnd;
  108. /**
  109. * 获得相对当前时间的偏移 count 天的起止日期(日的开始和结束)
  110. * @param {Number} count 默认0 (0代表今日 为-1代表昨日 为1代表明日以此类推)
  111. * @param {Date || Number} date 指定从那天开始计算
  112. * vk.pubfn.getDayOffsetStartAndEnd(0);
  113. */
  114. pubfn.getDayOffsetStartAndEnd = pubfn.timeUtil.getDayOffsetStartAndEnd;
  115. /**
  116. * 获得相对当前时间的偏移 count 月的起止日期(月的开始和结束)
  117. * @param {Number} count 默认0 (0代表本月 为-1代表上月 为1代表下月以此类推)
  118. * @param {Date || Number} date 指定从那天开始计算
  119. * vk.pubfn.getMonthOffsetStartAndEnd(0);
  120. */
  121. pubfn.getMonthOffsetStartAndEnd = pubfn.timeUtil.getMonthOffsetStartAndEnd;
  122. /**
  123. * 获得相对当前时间的偏移 count 年的起止日期(年的开始和结束)
  124. * @param {Number} count 默认0 (0代表今年 为-1代表去年 为1代表明年以此类推)
  125. * @param {Date || Number} date 指定从那天开始计算
  126. * vk.pubfn.getYearOffsetStartAndEnd(0);
  127. */
  128. pubfn.getYearOffsetStartAndEnd = pubfn.timeUtil.getYearOffsetStartAndEnd;
  129. /**
  130. * 获得指定年份和月份后的该月的开始时间和结束时间
  131. * 返回数据如下:(时间戳形式)
  132. {
  133. startTime 该月开始时间
  134. endTime 该月结束时间
  135. }
  136. vk.pubfn.getMonthStartAndEnd({
  137. year:2021
  138. month:1
  139. });
  140. */
  141. pubfn.getMonthStartAndEnd = pubfn.timeUtil.getMonthStartAndEnd;
  142. /**
  143. * Vue 全局表单验证器扩展
  144. rules: {
  145. receiver_mobile:[
  146. { validator:vk.pubfn.validator("mobile"), message: '手机号格式错误', trigger: 'blur' }
  147. ],
  148. },
  149. */
  150. pubfn.validator = function(type) {
  151. return function(rule, value, callback) {
  152. let key = pubfn.test(value, type);
  153. if (typeof callback === "function") {
  154. if (key || !value) {
  155. callback();
  156. } else {
  157. return callback(false);
  158. }
  159. } else {
  160. return callback(false);
  161. }
  162. }
  163. };
  164. /**
  165. * 检测文本是否满足指定格式
  166. * @param {String} str 需要检测的文本
  167. * @param {String} type 检测类型
  168. * 包含
  169. * mobile 手机号码
  170. * tel 座机
  171. * card 身份证
  172. * mobileCode 6位数字验证码
  173. * username 账号以字母开头,长度在6~18之间,只能包含字母、数字和下划线
  174. * pwd 密码长度在6~18之间,只能包含字母、数字和下划线和@
  175. * payPwd 支付密码 6位纯数字
  176. * postal 邮政编码
  177. * QQ QQ号
  178. * email 邮箱
  179. * URL 网址
  180. * IP IP地址
  181. * date 日期 2020-08-03
  182. * time 时间 12:12:12
  183. * dateTime 日期+时间 2020-08-03 12:12:12
  184. * number 数字
  185. * english 英文
  186. * chinese 中文
  187. * HTML HTML标记
  188. * vk.pubfn.test(str, type);
  189. */
  190. pubfn.test = function(str, type = "") {
  191. type = type.toLowerCase();
  192. switch (type) {
  193. case 'mobile': //手机号码
  194. return new RegExp(/^1[3|4|5|6|7|8|9][0-9]{9}$/).test(str);
  195. case 'tel': //座机
  196. return new RegExp(/^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/).test(str);
  197. case 'card': //身份证
  198. return new RegExp(/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/).test(str);
  199. case 'mobilecode': //6位数字验证码
  200. return new RegExp(/^[0-9]{6}$/).test(str);
  201. case 'username': //账号以字母开头,长度在6~18之间,只能包含字母、数字和下划线
  202. return new RegExp(/^[a-zA-Z]([-_a-zA-Z0-9]{5,17})$/).test(str)
  203. case 'pwd': //密码长度在6~18之间,只能包含字母、数字和下划线和@
  204. return new RegExp(/^([a-zA-Z0-9_@]){6,18}$/).test(str)
  205. case 'password': //密码长度在6~18之间,只能包含字母、数字和下划线和@
  206. return new RegExp(/^([a-zA-Z0-9_@]){6,18}$/).test(str)
  207. case 'paypwd': //支付密码 6位纯数字
  208. return new RegExp(/^[0-9]{6}$/).test(str)
  209. case 'postal': //邮政编码
  210. return new RegExp(/[1-9]\d{5}(?!\d)/).test(str);
  211. case 'qq': //QQ号
  212. return new RegExp(/^[1-9][0-9]{4,9}$/).test(str);
  213. case 'email': //邮箱
  214. return new RegExp(/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/).test(str);
  215. case 'money': //金额(小数点2位)
  216. return new RegExp(/^\d*(?:\.\d{0,2})?$/).test(str);
  217. case 'url': //网址
  218. return new RegExp(/(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/).test(str);
  219. case 'ip': //IP
  220. return new RegExp(/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/).test(
  221. str);
  222. case 'date': //日期 2014-01-01
  223. return new RegExp(/^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/).test(str);
  224. case 'time': //时间 12:00:00
  225. return new RegExp(/^(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/).test(str);
  226. case 'datetime': //日期+时间 2014-01-01 12:00:00
  227. return new RegExp(/^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/).test(str);
  228. case 'english+number': //英文+数字
  229. return new RegExp(/^[a-zA-Z0-9]*$/).test(str);
  230. case 'english+number+_': //英文+数字+_
  231. return new RegExp(/^[a-zA-Z0-9_]*$/).test(str);
  232. case 'english+number+_-': //英文+数字+_-
  233. return new RegExp(/^[a-zA-Z0-9_-]*$/).test(str);
  234. case 'number': //数字
  235. return new RegExp(/^[0-9]*$/).test(str);
  236. case 'english': //英文
  237. return new RegExp(/^[a-zA-Z]+$/).test(str);
  238. case 'chinese': //中文
  239. return new RegExp(/^[\u4e00-\u9fa5]+$/gi).test(str);
  240. case 'lower': //小写
  241. return new RegExp(/^[a-z]+$/).test(str);
  242. case 'upper': //大写
  243. return new RegExp(/^[A-Z]+$/).test(str);
  244. case 'html': //HTML标记
  245. return new RegExp(/<("[^"]*"|'[^']*'|[^'">])*>/).test(str);
  246. default:
  247. return true;
  248. }
  249. };
  250. // 保留之前的函数名
  251. pubfn.checkStr = pubfn.test;
  252. /**
  253. * 对象属性拷贝(浅拷贝)
  254. * @description 将 obj2 的属性赋值给 obj1 (如果obj1中有对应的属性,则会被obj2的属性值覆盖)
  255. * @param {Object} obj1
  256. * @param {Object} obj2
  257. * vk.pubfn.objectAssign(obj1, obj2);
  258. */
  259. pubfn.objectAssign = function(obj1, obj2) {
  260. return Object.assign(obj1, obj2);
  261. };
  262. /**
  263. * 复制一份对象-没有映射关系
  264. * @description 主要用于解除映射关系(不支持克隆函数)
  265. * @param {Object} obj
  266. * let newObj = vk.pubfn.copyObject(obj);
  267. */
  268. pubfn.copyObject = function(obj) {
  269. if (typeof obj !== "undefined") {
  270. return JSON.parse(JSON.stringify(obj));
  271. } else {
  272. return obj;
  273. }
  274. };
  275. /**
  276. * 深度克隆一个对象-没有映射关系
  277. * @description 主要用于解除映射关系(支持克隆函数)
  278. * @param {Object} obj
  279. * let newObj = vk.pubfn.deepClone(obj);
  280. */
  281. pubfn.deepClone = function(obj) {
  282. // 对常见的“非”值,直接返回原来值
  283. if ([null, undefined, NaN, false].includes(obj)) return obj;
  284. if (typeof obj !== "object" && typeof obj !== 'function') {
  285. //原始类型直接返回
  286. return obj;
  287. }
  288. let o = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {};
  289. for (let i in obj) {
  290. if (obj.hasOwnProperty(i)) {
  291. o[i] = typeof obj[i] === "object" ? pubfn.deepClone(obj[i]) : obj[i];
  292. }
  293. }
  294. return o;
  295. };
  296. /**
  297. * 表单自动填充数据
  298. * @description 主要用于表单修改时,数据库没有默认字段会报错的问题
  299. * @param {Object} defaultData 默认数据
  300. * @param {Object} itemData 当前数据
  301. * that.form1 = vk.pubfn.formAssign(defaultData,itemData);
  302. */
  303. pubfn.formAssign = function(defaultData, itemData) {
  304. let newDefaultData = pubfn.copyObject(defaultData);
  305. return pubfn.objectAssign(newDefaultData, itemData);
  306. };
  307. /**
  308. * 两个(元素为对象)的数组合并,并去除重复的数据
  309. * @param {Array} arr1 第一个数组(arr1和aar2没有顺序要求)
  310. * @param {Array} aar2 第二个数组
  311. * @param {String} flag 判断标识,默认用id来判断,若flag传-1,代表不去除重复数据
  312. * let arr = vk.pubfn.arr_concat(arr1, arr2, "_id");
  313. */
  314. pubfn.arr_concat = function(arr1, arr2, flag) {
  315. if (!flag) flag = "id"; // 默认用id来判断是否是同一个对象元素
  316. var arr3 = arr1.concat(arr2); // 新旧数据合并
  317. var arr = []; // 定义一个临时数组 存放对象
  318. if (flag != -1) {
  319. var arr_id = []; // 定义一个临时数组 存放id
  320. for (var i in arr3) { // 循环遍历当前数组
  321. // 判断当前数组下标为i的元素是否已经保存到临时数组
  322. // 如果已保存,则跳过,否则将此元素保存到临时数组中
  323. if (arr_id.indexOf(arr3[i][flag]) == -1) {
  324. arr_id.push(arr3[i][flag]); // 添加id到数组
  325. arr.push(arr3[i]); // 添加对象到数组
  326. }
  327. }
  328. } else {
  329. arr = arr3;
  330. }
  331. return arr;
  332. };
  333. /**
  334. * 自动根据字符串路径获取对象中的值支持.和[] , 且任意一个值为undefined时,不会报错,会直接返回undefined
  335. * @param {Object} dataObj 数据源
  336. * @param {String} name 支持a.b 和 a[b]
  337. * @param {String} defaultValue undefined时的默认值
  338. * vk.pubfn.getData(dataObj, name);
  339. */
  340. pubfn.getData = function(dataObj, name, defaultValue) {
  341. let newDataObj;
  342. if (pubfn.isNotNull(dataObj)) {
  343. newDataObj = JSON.parse(JSON.stringify(dataObj));
  344. let k = "",
  345. d = ".",
  346. l = "[",
  347. r = "]";
  348. name = name.replace(/\s+/g, k) + d;
  349. let tstr = k;
  350. for (let i = 0; i < name.length; i++) {
  351. let theChar = name.charAt(i);
  352. if (theChar != d && theChar != l && theChar != r) {
  353. tstr += theChar;
  354. } else if (newDataObj) {
  355. if (tstr != k) newDataObj = newDataObj[tstr];
  356. tstr = k;
  357. }
  358. }
  359. }
  360. if (typeof newDataObj === "undefined" && typeof defaultValue !== "undefined") newDataObj = defaultValue;
  361. return newDataObj;
  362. };
  363. /**
  364. * 自动根据字符串路径设置对象中的值 支持.和[]
  365. * @param {Object} dataObj 数据源
  366. * @param {String} name 支持a.b 和 a[b]
  367. * @param {String} value 值
  368. * vk.pubfn.setData(dataObj, name, value);
  369. */
  370. pubfn.setData = function(dataObj, name, value) {
  371. // 通过正则表达式 查找路径数据
  372. let dataValue;
  373. if (typeof value === "object") {
  374. dataValue = pubfn.copyObject(value);
  375. } else {
  376. dataValue = value;
  377. }
  378. let regExp = new RegExp("([\\w$]+)|\\[(:\\d)\\]", "g");
  379. const patten = name.match(regExp);
  380. // 遍历路径 逐级查找 最后一级用于直接赋值
  381. for (let i = 0; i < patten.length - 1; i++) {
  382. let keyName = patten[i];
  383. if (typeof dataObj[keyName] !== "object") dataObj[keyName] = {};
  384. dataObj = dataObj[keyName];
  385. }
  386. // 最后一级
  387. dataObj[patten[patten.length - 1]] = dataValue;
  388. };
  389. /**
  390. * 检测参数是否为空 其中 undefined、null、{}、[]、"" 均为空值 true 空值 false 有值
  391. * vk.pubfn.isNull(value);
  392. */
  393. pubfn.isNull = function(value) {
  394. let key = false;
  395. if (
  396. typeof value == "undefined" ||
  397. Object.prototype.toString.call(value) == "[object Null]" ||
  398. JSON.stringify(value) == "{}" ||
  399. JSON.stringify(value) == "[]" ||
  400. value === "" ||
  401. JSON.stringify(value) === undefined
  402. ) {
  403. key = true;
  404. }
  405. return key;
  406. };
  407. /**
  408. * 检测参数是否不为空 结果与 vk.pubfn.isNull 相反
  409. * vk.pubfn.isNotNull(value);
  410. */
  411. pubfn.isNotNull = function(value) {
  412. return !pubfn.isNull(value);
  413. };
  414. /**
  415. * 检测所有参数 - 是否至少有一个为空
  416. * vk.pubfn.isNullOne(value1,value2,value3);
  417. */
  418. pubfn.isNullOne = function(...strS) {
  419. let key = false;
  420. for (let i = 0; i < strS.length; i++) {
  421. let str = strS[i];
  422. if (pubfn.isNull(str)) {
  423. key = true;
  424. break;
  425. }
  426. }
  427. return key;
  428. };
  429. /**
  430. * 检测整个对象是否没有一个属性是空值,如果有空值,则返回首个是空值的属性名
  431. let nullKey = vk.pubfn.isNullOneByObject({ value1,value2,value3 });
  432. if(nullKey) return { code : -1, msg : `${nullKey}不能为空` };
  433. */
  434. pubfn.isNullOneByObject = function(obj) {
  435. let key;
  436. for (let name in obj) {
  437. let val = obj[name];
  438. if (pubfn.isNull(val)) {
  439. key = name;
  440. break;
  441. }
  442. }
  443. return key;
  444. };
  445. /**
  446. * 检测所有参数 - 是否全部为空
  447. * vk.pubfn.isNullAll(value1,value2,value3);
  448. */
  449. pubfn.isNullAll = function(...strS) {
  450. let key = true;
  451. for (let i = 0; i < strS.length; i++) {
  452. let str = strS[i];
  453. if (pubfn.isNotNull(str)) {
  454. key = false;
  455. break;
  456. }
  457. }
  458. return key;
  459. };
  460. /**
  461. * 检测所有参数 - 是否全部都不为空
  462. * vk.pubfn.isNotNullAll(value1,value2,value3);
  463. */
  464. pubfn.isNotNullAll = function(...strS) {
  465. return !pubfn.isNullOne(...strS);
  466. };
  467. /**
  468. * 获取对象数组中的某一个item,根据指定的键名和键值
  469. * @description 主要用于在一个对象数组中快速获取 _id = 1 的对象
  470. * @param {Array} list 数据源
  471. * @param {String} key 键名(不可为空)
  472. * @param {String} value 键值 (不可为空)
  473. * vk.pubfn.getListItem(list, key, value);
  474. */
  475. pubfn.getListItem = function(list, key, value) {
  476. let item;
  477. for (let i = 0; i < list.length; i++) {
  478. if (list[i][key] === value) {
  479. item = list[i];
  480. break;
  481. }
  482. }
  483. return item;
  484. };
  485. /**
  486. * 获取对象数组中某个元素的index,根据指定的键名和键值
  487. * @description 主要用于在一个对象数组中快速获取 _id = 1 的index
  488. * @param {Array} list 数据源
  489. * @param {String} key 键名
  490. * @param {String} value 键值
  491. * vk.pubfn.getListIndex(list, key, value);
  492. */
  493. pubfn.getListIndex = function(list, key, value) {
  494. let index = -1;
  495. for (let i = 0; i < list.length; i++) {
  496. if (list[i][key] === value) {
  497. index = i;
  498. break;
  499. }
  500. }
  501. return index;
  502. };
  503. /**
  504. * 获取对象数组中某个元素的index,根据指定的键名和键值
  505. * @description 主要用于在一个对象数组中快速获取 _id = 1 的index
  506. * @param {Array} list 数据源
  507. * @param {String} key 键名
  508. * @param {String} value 键值
  509. * vk.pubfn.getListItemIndex(list, key, value);
  510. */
  511. pubfn.getListItemIndex = function(list, key, value) {
  512. let obj = {};
  513. let item;
  514. let index = -1;
  515. for (let i = 0; i < list.length; i++) {
  516. if (list[i][key] === value) {
  517. index = i;
  518. item = list[i];
  519. break;
  520. }
  521. }
  522. obj = {
  523. item,
  524. index
  525. }
  526. return obj;
  527. };
  528. /**
  529. * 数组转对象 - 将对象数组转成json
  530. * 如[{"_id":"001","name":"name1","sex":1},{"_id":"002","name":"name2","sex":2}]
  531. * 转成
  532. * {"001",{"_id":"001","name":"name1","sex":1},"002":{"_id":"002","name":"name2","sex":2}}
  533. * vk.pubfn.arrayToJson(list, "_id");
  534. */
  535. pubfn.arrayToJson = function(list, key) {
  536. let json = {};
  537. for (let i in list) {
  538. let item = list[i];
  539. json[item[key]] = item;
  540. }
  541. return json;
  542. };
  543. pubfn.listToJson = pubfn.arrayToJson;
  544. /**
  545. * 从数组中提取指定字段形式成为新的数组
  546. * 如[{"_id":"001","name":"name1","sex":1},{"_id":"002","name":"name2","sex":2}]
  547. * 提取_id字段转成
  548. * ["001","002"]
  549. * let idArr = vk.pubfn.arrayObjectGetArray(list, "_id");
  550. */
  551. pubfn.arrayObjectGetArray = function(list, key) {
  552. return list.map(obj => { return obj[key] });
  553. };
  554. /**
  555. * 产生指定位数的随机数(支持任意字符,默认纯数字)
  556. * @param {Number} length 数据源
  557. * @param {String} str 指定的字符串中随机范围
  558. * @param {Array} arr 产生的随机数不会和此数组的任意一项重复
  559. * vk.pubfn.random(6);
  560. * vk.pubfn.random(6, "abcdefghijklmnopqrstuvwxyz0123456789");
  561. * vk.pubfn.random(1,"12",["1","2"]);
  562. */
  563. pubfn.random = function(length, str, arr) {
  564. let s;
  565. if (pubfn.isNull(arr)) {
  566. s = pubfn.randomFn(length, str);
  567. } else {
  568. let i = 0;
  569. let maxForCount = 100000;
  570. do {
  571. i++;
  572. s = pubfn.randomFn(length, str);
  573. } while (arr.indexOf(s) > -1 && i < maxForCount);
  574. if (i === maxForCount) {
  575. s = undefined;
  576. }
  577. }
  578. return s;
  579. };
  580. /**
  581. * 产生指定位数的随机数(支持任意字符,默认纯数字)
  582. * @param {Number} length 数据源
  583. * @param {String} str 指定的字符串中随机范围
  584. * vk.pubfn.random(6);
  585. * vk.pubfn.random(6, "abcdefghijklmnopqrstuvwxyz0123456789");
  586. */
  587. pubfn.randomFn = function(length, str) {
  588. let s = "";
  589. let list = "123456789";
  590. //0123456789QWERTYUIPASDFGHJKLZXCVBNM
  591. if (pubfn.isNotNull(str)) {
  592. if (str == "a-z,0-9") {
  593. str = "abcdefghijklmnopqrstuvwxyz0123456789";
  594. } else if (str == "A-Z,0-9") {
  595. str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  596. } else if (str == "a-z,A-Z,0-9" || str == "A-Z,a-z,0-9") {
  597. str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  598. }
  599. list = str;
  600. }
  601. for (let i = 0; i < length; i++) {
  602. let code = list[Math.floor(Math.random() * list.length)];
  603. s += code;
  604. }
  605. return s;
  606. };
  607. /**
  608. * 将字符串id转化为指定位数的纯数字字符串id(会重复)
  609. * vk.pubfn.stringIdToNumberId(uid,8);
  610. */
  611. pubfn.stringIdToNumberId = function(str, length) {
  612. let s = "";
  613. let list = "0123456789";
  614. for (let i = 0; i < length; i++) {
  615. if (str.length > i) {
  616. let index = str[i].charCodeAt() % 10;
  617. s += list[index];
  618. } else {
  619. s = "0" + s;
  620. }
  621. }
  622. return s;
  623. };
  624. /**
  625. * 将手机号,账号等隐藏中间字段
  626. * @param {String} str 需要转换的字符串
  627. * @param {Number} first 前面显示的字符数量
  628. * @param {Number} last 后面显示的字符数量
  629. * vk.pubfn.hidden(str, first, last);
  630. */
  631. pubfn.hidden = function(str = "", first = 0, last = 0) {
  632. let len = str.length - first - last;
  633. let xing = '';
  634. for (let i = 0; i < len; i++) {
  635. xing += '*';
  636. }
  637. return str.substring(0, first) + xing + str.substring(str.length - last);
  638. };
  639. /**
  640. * 判断常量数组A是否至少有一个元素在常量数组B中存在(两数组有交集)
  641. * @param {Array} arr1 数组A
  642. * @param {Array} arr2 数组B
  643. * vk.pubfn.checkArrayIntersection(arr1, arr2);
  644. */
  645. pubfn.checkArrayIntersection = function(arr1 = [], arr2 = []) {
  646. let checkKey = false;
  647. for (let i = 0; i < arr2.length; i++) {
  648. if (arr1.indexOf(arr2[i]) > -1) {
  649. checkKey = true;
  650. }
  651. }
  652. return checkKey;
  653. };
  654. /**
  655. * 检测数据源是否满足表达式规则
  656. * @param {Object} data 数据源
  657. * @param {String} expText 表达式文本
  658. * vk.pubfn.checkDataExpText(data, expText);
  659. */
  660. pubfn.checkDataExpText = function(data = {}, expText) {
  661. expText = expText.replace(new RegExp("\\s", "g"), "");
  662. //console.log("expText:",expText);
  663. let orArr = expText.split("||");
  664. //console.log("orArr",orArr);
  665. let checkKey = false;
  666. for (let index1 = 0; index1 < orArr.length; index1++) {
  667. let orItem = orArr[index1];
  668. let andArr = orItem.split("&&");
  669. //console.log("andArr",andArr);
  670. let itemKey = true;
  671. for (let index2 = 0; index2 < andArr.length; index2++) {
  672. let andItem = andArr[index2];
  673. //console.log("andItem",andItem);
  674. if (andItem.indexOf("!=") > -1) {
  675. let andItemArr = andItem.split("!=");
  676. let key = andItemArr[0];
  677. let value = andItemArr[1];
  678. itemKey = data[key] != value ? true : false;
  679. } else if (andItem.indexOf("==") > -1) {
  680. let andItemArr = andItem.split("==");
  681. let key = andItemArr[0];
  682. let value = andItemArr[1];
  683. itemKey = (typeof data[key] !== "undefined" && data[key].toString() == value) ? true : false;
  684. } else if (andItem.indexOf(">=") > -1) {
  685. let andItemArr = andItem.split(">=");
  686. let key = andItemArr[0];
  687. let value = andItemArr[1];
  688. if (isNaN(value)) {
  689. itemKey = (typeof data[key] !== "undefined" && data[key].toString() >= value) ? true : false;
  690. } else {
  691. itemKey = (typeof data[key] !== "undefined" && data[key] >= Number(value)) ? true : false;
  692. }
  693. } else if (andItem.indexOf(">") > -1) {
  694. let andItemArr = andItem.split(">");
  695. let key = andItemArr[0];
  696. let value = andItemArr[1];
  697. if (isNaN(value)) {
  698. itemKey = (typeof data[key] !== "undefined" && data[key].toString() > value) ? true : false;
  699. } else {
  700. itemKey = (typeof data[key] !== "undefined" && data[key] > Number(value)) ? true : false;
  701. }
  702. } else if (andItem.indexOf("<=") > -1) {
  703. let andItemArr = andItem.split("<=");
  704. let key = andItemArr[0];
  705. let value = andItemArr[1];
  706. if (isNaN(value)) {
  707. itemKey = (typeof data[key] !== "undefined" && data[key].toString() <= value) ? true : false;
  708. } else {
  709. itemKey = (typeof data[key] !== "undefined" && data[key] <= Number(value)) ? true : false;
  710. }
  711. } else if (andItem.indexOf("<") > -1) {
  712. let andItemArr = andItem.split("<");
  713. let key = andItemArr[0];
  714. let value = andItemArr[1];
  715. if (isNaN(value)) {
  716. itemKey = (typeof data[key] !== "undefined" && data[key].toString() < value) ? true : false;
  717. } else {
  718. itemKey = (typeof data[key] !== "undefined" && data[key] < Number(value)) ? true : false;
  719. }
  720. } else {
  721. let andItemArr = andItem.split("=");
  722. let key = andItemArr[0];
  723. let value = andItemArr[1];
  724. itemKey = (typeof data[key] !== "undefined" && data[key].toString() == value) ? true : false;
  725. //console.log("key:",key,"value:",value,"data[key]",data[key].toString(),"itemKey:",itemKey);
  726. }
  727. if (!itemKey) {
  728. break;
  729. }
  730. }
  731. if (itemKey) {
  732. checkKey = true;
  733. break;
  734. }
  735. }
  736. return checkKey;
  737. };
  738. /**
  739. * 判断变量是否是数组
  740. * vk.pubfn.isArray(value);
  741. */
  742. pubfn.isArray = function(value) {
  743. return Object.prototype.toString.call(value) === "[object Array]" ? true : false;
  744. };
  745. /**
  746. * 判断变量是否是对象
  747. * vk.pubfn.isObject(value);
  748. */
  749. pubfn.isObject = function(value) {
  750. return Object.prototype.toString.call(value) === "[object Object]" ? true : false;
  751. };
  752. /**
  753. * 计算运费
  754. * @param {Object} freightsItem 运费模板
  755. {
  756. first_weight Number 首重 单位KG,
  757. first_weight_price Number 首重 首重价格
  758. continuous_weight Number 续重 单位KG
  759. continuous_weight_price Number 续重价格
  760. max_weight Number 重量达到此值时,会多计算首重的价格,并少一次续重的价格 倍乘(相当于拆分多个包裹)
  761. }
  762. * @param {Number} weight 运费重量
  763. * vk.pubfn.calcFreights(freightsItem, weight);
  764. */
  765. pubfn.calcFreights = function(freightsItem, weight) {
  766. let {
  767. first_weight,
  768. first_weight_price,
  769. continuous_weight,
  770. continuous_weight_price,
  771. max_weight = 100000000
  772. } = freightsItem;
  773. let money = 0; // 运费
  774. let packagesNum = 0; // 包裹数量
  775. let packagesSurplusWeight = max_weight; // 包裹剩余重量
  776. let first_weight_key = false; // 是否已减过首重
  777. let continuous_weight_count = 0; // 续重次数
  778. let logArr = [];
  779. let logRun = false;
  780. while (weight > 0) {
  781. if (!first_weight_key) {
  782. // 首重
  783. first_weight_key = true;
  784. packagesNum++;
  785. packagesSurplusWeight = max_weight; // 还原包裹剩余重量
  786. weight -= first_weight;
  787. packagesSurplusWeight -= first_weight;
  788. } else {
  789. // 续重
  790. continuous_weight_count++;
  791. weight -= continuous_weight;
  792. packagesSurplusWeight -= continuous_weight;
  793. }
  794. if (logRun) logArr.push({
  795. "总重量剩余": weight,
  796. "当前包裹重量剩余": packagesSurplusWeight,
  797. "当前第几个包裹": packagesNum,
  798. "续重计算次数": continuous_weight_count
  799. });
  800. if (packagesSurplusWeight <= 0) {
  801. // 需要增加一个新的包裹
  802. first_weight_key = false; // 新包裹设置没有减过首重
  803. }
  804. }
  805. if (logRun) console.log(JSON.stringify(logArr));
  806. money = packagesNum * first_weight_price + continuous_weight_price * continuous_weight_count;
  807. return money;
  808. };
  809. /**
  810. * 从一个对象中取多个属性,并生成一个全新的对象,会过滤空字符串,空数组,空对象
  811. * @param {Object} obj 对象
  812. * @param {Array<String>} keys 键名数组
  813. * vk.pubfn.getNewObject(obj, keys);
  814. */
  815. pubfn.getNewObject = function(obj, keys) {
  816. let selectedObj = pubfn.copyObject(obj);
  817. let newObject = {};
  818. if (keys && keys.length > 0) {
  819. for (let i in keys) {
  820. let key = keys[i];
  821. if (pubfn.isNotNull(selectedObj[key])) {
  822. newObject[key] = selectedObj[key];
  823. }
  824. }
  825. } else {
  826. newObject = selectedObj;
  827. }
  828. return newObject;
  829. };
  830. /**
  831. * 对象删除指定的字段,返回新的对象
  832. * @param {Object} data 操作对象
  833. * @param {Array<String>} deleteKeys 需要删除的键名(数组形式)
  834. * vk.pubfn.deleteObjectKeys(data, deleteKeys);
  835. */
  836. pubfn.deleteObjectKeys = function(data, deleteKeys = []) {
  837. var newData = {};
  838. if (data) {
  839. for (let key in data) {
  840. if (deleteKeys.indexOf(key) == -1) {
  841. newData[key] = data[key];
  842. }
  843. }
  844. }
  845. return newData;
  846. }
  847. /**
  848. * 数组结构转树形结构
  849. * @param {Array} treeData 数据源
  850. * @param {Object} treeProps 树结构配置
  851. * { id:"_id", parent_id:"parent_id", children:"children",need_field:["_id","name"],deleteParentId:true }
  852. * vk.pubfn.arrayToTree(treeData, treeProps);
  853. */
  854. pubfn.arrayToTree = pubfn.treeUtil.arrayToTree;
  855. /**
  856. * 树形结构转数组结构
  857. * @param {Array} treeData 数据源
  858. * @param {Object} treeProps 树结构配置
  859. * { id:"_id", parent_id:"parent_id", children:"children", deleteChildren:true }
  860. * vk.pubfn.treeToArray(treeData, treeProps);
  861. */
  862. pubfn.treeToArray = pubfn.treeUtil.treeToArray;
  863. /**
  864. * 通配符匹配
  865. * @param {String} text 被匹配的文本
  866. * @param {String} expText 通配符规则
  867. * vk.pubfn.wildcardTestOne(text, expText);
  868. */
  869. pubfn.wildcardTestOne = function(text, expText) {
  870. if (!expText) return false;
  871. let regExpText = expText.replace(new RegExp("\\*"), "(.*)");
  872. let startText = expText.indexOf("*") !== 0 ? "^" : "";
  873. let endText = expText[expText.length - 1] !== "*" ? "$" : "";
  874. let regExp = new RegExp(startText + regExpText + endText);
  875. return regExp.test(text);
  876. };
  877. /**
  878. * 通配符匹配 expText支持数组
  879. * @param {String} text 被匹配的文本
  880. * @param {String | Array<String>} expText 通配符规则
  881. * vk.pubfn.wildcardTest(text, expText);
  882. */
  883. pubfn.wildcardTest = function(text, expText) {
  884. let matchNum = 0; // 被匹配的次数
  885. let regExp1 = new RegExp("\\*");
  886. if (typeof expText === "string") {
  887. // 字符串
  888. if (pubfn.wildcardTestOne(text, expText)) {
  889. matchNum++;
  890. }
  891. } else if (typeof expText === "object") {
  892. // 数组
  893. for (let i = 0; i < expText.length; i++) {
  894. let expTextItem = expText[i];
  895. if (pubfn.wildcardTestOne(text, expTextItem)) {
  896. matchNum++;
  897. }
  898. }
  899. }
  900. return matchNum;
  901. }
  902. /**
  903. * 正则匹配
  904. * @param {String} text 被匹配的文本
  905. * @param {String} expText 正则表达式规则
  906. * vk.pubfn.regExpTestOne(text, expText);
  907. */
  908. pubfn.regExpTestOne = function(text, expText) {
  909. if (!expText) return false;
  910. let regExp = new RegExp(expText);
  911. return regExp.test(text);
  912. };
  913. /**
  914. * 正则匹配
  915. * @param {String} text 被匹配的文本
  916. * @param {String || Array<String>} wildcardExp 正则表达式规则
  917. * vk.pubfn.regExpTest(text, regExp);
  918. */
  919. pubfn.regExpTest = function(text, expText) {
  920. let matchNum = 0; // 被匹配的次数
  921. if (typeof expText === "string") {
  922. // 字符串
  923. if (pubfn.regExpTestOne(text, expText)) {
  924. matchNum++;
  925. }
  926. } else if (typeof expText === "object") {
  927. // 数组
  928. for (let i = 0; i < expText.length; i++) {
  929. let expTextItem = expText[i];
  930. if (pubfn.regExpTestOne(text, expTextItem)) {
  931. matchNum++;
  932. }
  933. }
  934. }
  935. return matchNum;
  936. }
  937. /**
  938. * 产生订单号,不依赖数据库,高并发时性能高(理论上会重复,但概率非常非常低)
  939. * @param {String} prefix 前缀
  940. * @param {Number} num 位数,建议在25-30之间,默认25
  941. * vk.pubfn.createOrderNo();
  942. */
  943. pubfn.createOrderNo = function(prefix = "", num = 25) {
  944. // 获取当前时间字符串格式如20200803093000123
  945. let fullTime = pubfn.getFullTime(new Date(), 1);
  946. fullTime = fullTime.substring(2);
  947. let randomNum = num - (prefix + fullTime).length;
  948. return prefix + fullTime + pubfn.random(randomNum);
  949. };
  950. const isSnakeCase = new RegExp('_(\\w)', 'g');
  951. const isCamelCase = new RegExp('[A-Z]', 'g');
  952. function parseObjectKeys(obj, type) {
  953. let parserReg;
  954. let parser;
  955. switch (type) {
  956. case 'snake2camel':
  957. parser = pubfn.snake2camel
  958. parserReg = isSnakeCase
  959. break
  960. case 'camel2snake':
  961. parser = pubfn.camel2snake
  962. parserReg = isCamelCase
  963. break
  964. }
  965. for (const key in obj) {
  966. if (Object.prototype.hasOwnProperty.call(obj, key)) {
  967. if (parserReg.test(key)) {
  968. const keyCopy = parser(key)
  969. obj[keyCopy] = obj[key]
  970. delete obj[key]
  971. if (Object.prototype.toString.call((obj[keyCopy])) === '[object Object]') {
  972. obj[keyCopy] = parseObjectKeys(obj[keyCopy], type)
  973. } else if (Array.isArray(obj[keyCopy])) {
  974. obj[keyCopy] = obj[keyCopy].map((item) => {
  975. return parseObjectKeys(item, type)
  976. })
  977. }
  978. }
  979. }
  980. }
  981. return obj
  982. }
  983. /**
  984. * 字符串 - 蛇形转驼峰
  985. * @param {String} value
  986. * vk.pubfn.snake2camel(value);
  987. */
  988. pubfn.snake2camel = function(value) {
  989. return value.replace(isSnakeCase, (_, c) => (c ? c.toUpperCase() : ''))
  990. }
  991. /**
  992. * 字符串 - 驼峰转蛇形
  993. * @param {String} value
  994. * vk.pubfn.camel2snake(value);
  995. */
  996. pubfn.camel2snake = function(value) {
  997. return value.replace(isCamelCase, str => '_' + str.toLowerCase())
  998. }
  999. /**
  1000. * 对象内的属性名 - 蛇形转驼峰
  1001. * @param {Object} obj
  1002. * vk.pubfn.snake2camelJson(obj);
  1003. */
  1004. pubfn.snake2camelJson = function(obj) {
  1005. return parseObjectKeys(obj, 'snake2camel');
  1006. };
  1007. /**
  1008. * 对象内的属性名 - 驼峰转蛇形
  1009. * @param {Object} obj
  1010. * vk.pubfn.camel2snakeJson(obj);
  1011. */
  1012. pubfn.camel2snakeJson = function(obj) {
  1013. return parseObjectKeys(obj, 'camel2snake');
  1014. };
  1015. /**
  1016. * 将能转成数字的字符串转数字(支持字符串、对象、数组)
  1017. * @param {Any} obj
  1018. * @param {Object} option 哪些格式需要排除
  1019. * 默认排除
  1020. * mobile:true 手机号,如 15200000001
  1021. * idCard:true 身份证,如 330154202109301214
  1022. * startFrom0:true 第一位是0,且长度大于1的,同时第二位不是.的字符串 如 01,057189101254
  1023. * maxLength:14 超过此长度的字符串排除
  1024. * vk.pubfn.string2Number(obj, option);
  1025. */
  1026. pubfn.string2Number = function(obj, option = {}) {
  1027. const type = Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
  1028. switch (type) {
  1029. case 'string':
  1030. if (obj && !isNaN(obj)) {
  1031. let {
  1032. mobile = true,
  1033. idCard = true,
  1034. startFrom0 = true,
  1035. maxLength = 14,
  1036. } = option;
  1037. if (obj.length > maxLength) {
  1038. return obj;
  1039. } else if (mobile && pubfn.test(obj, "mobile")) {
  1040. return obj;
  1041. } else if (idCard && pubfn.test(obj, "card")) {
  1042. return obj;
  1043. } else if (startFrom0 && obj.length > 1 && obj.indexOf("0") === 0 && obj.indexOf(".") !== 1) {
  1044. return obj;
  1045. }
  1046. return Number(obj);
  1047. } else {
  1048. return obj;
  1049. }
  1050. case 'object':
  1051. const keys = Object.keys(obj);
  1052. for (let i = 0; i < keys.length; i++) {
  1053. const key = keys[i];
  1054. obj[key] = pubfn.string2Number(obj[key]);
  1055. }
  1056. return obj;
  1057. case 'array':
  1058. for (let i = 0; i < obj.length; i++) {
  1059. obj[i] = pubfn.string2Number(obj[i]);
  1060. }
  1061. return obj;
  1062. default:
  1063. return obj;
  1064. }
  1065. };
  1066. /**
  1067. * 保留小数
  1068. * @param {Number} val 原值
  1069. * @param {Number} precision 精度
  1070. * vk.pubfn.toDecimal(val, 2);
  1071. */
  1072. pubfn.toDecimal = function(val, precision = 0) {
  1073. if (typeof val === "string") val = Number(val);
  1074. return parseFloat(val.toFixed(precision));
  1075. };
  1076. /**
  1077. * 判断文件url的类型
  1078. * @param {String} url 文件的url路径
  1079. * vk.pubfn.getFileType(url);
  1080. * 返回值为字符串
  1081. * image 图片
  1082. * video 视频
  1083. * audio 音频
  1084. * other 其他
  1085. */
  1086. pubfn.getFileType = function(url) {
  1087. let fileType;
  1088. if (pubfn.checkFileSuffix(url, ["png", "jpg", "jpeg", "gif", "bmp", "svg"])) {
  1089. fileType = "image";
  1090. } else if (pubfn.checkFileSuffix(url, ["avi", "mp4", "3gp", "mov", "rmvb", "rm", "flv", "mkv"])) {
  1091. fileType = "video";
  1092. } else if (pubfn.checkFileSuffix(url, ["mp3"])) {
  1093. fileType = "audio";
  1094. } else {
  1095. fileType = "other";
  1096. }
  1097. return fileType;
  1098. };
  1099. /**
  1100. * 获取文件url的后缀名
  1101. * @param {String} url 文件的url路径,必须带
  1102. * vk.pubfn.getFileSuffix(url);
  1103. */
  1104. pubfn.getFileSuffix = function(url) {
  1105. let suffix;
  1106. let index = url.lastIndexOf(".");
  1107. if (index > -1) {
  1108. suffix = url.substring(index + 1);
  1109. }
  1110. return suffix;
  1111. };
  1112. /**
  1113. * 判断文件url是否在指定后缀名数组内
  1114. * @param {String} url 文件的url路径
  1115. * @param {Array<String>} list 后缀名列表
  1116. * vk.pubfn.checkFileSuffix(url,["png", "jpg", "jpeg", "gif", "bmp", "svg"]);
  1117. */
  1118. pubfn.checkFileSuffix = function(url, list) {
  1119. let key = false;
  1120. let suffix = pubfn.getFileSuffix(url);
  1121. for (let i = 0; i < list.length; i++) {
  1122. if (list.indexOf(suffix) > -1) {
  1123. key = true;
  1124. break;
  1125. }
  1126. }
  1127. return key;
  1128. };
  1129. // 前端专属开始 -----------------------------------------------------------
  1130. /**
  1131. * 将时间显示成1秒前、1天前
  1132. * @description 主要用于 文章最后回复时间: 1分钟前
  1133. * @param {String || Number} startTime 需要计算的时间 如文章最后回复时间
  1134. * vk.pubfn.dateDiff(startTime);
  1135. */
  1136. pubfn.dateDiff = function(startTime, suffix = "前") {
  1137. if (!startTime) {
  1138. return "";
  1139. }
  1140. if (typeof startTime === "string" && !isNaN(startTime)) startTime = Number(startTime);
  1141. if (typeof startTime == "number") {
  1142. if (startTime.toString().length == 10) startTime *= 1000;
  1143. startTime = new Date(startTime);
  1144. startTime = pubfn.getFullTime(startTime);
  1145. }
  1146. if (typeof startTime == "string") {
  1147. startTime = startTime.replace("T", " ");
  1148. startTime = startTime;
  1149. startTime = new Date(startTime.replace(/-/g, "/")); //将-转化为/,使用new Date
  1150. }
  1151. var endTime = new Date(); //获取当前时间
  1152. var nd = 1000 * 24 * 60 * 60; //一天的毫秒数
  1153. var nh = 1000 * 60 * 60; //一小时的毫秒数
  1154. var nm = 1000 * 60; //一分钟的毫秒数
  1155. var ns = 1000; //一秒钟的毫秒数long diff;try {
  1156. var diff = endTime.getTime() - startTime.getTime();
  1157. var day = Math.floor(diff / nd); //计算差多少天
  1158. var hour = Math.floor(diff % nd / nh); //计算差多少小时
  1159. var min = Math.floor(diff % nd % nh / nm); //计算差多少分钟
  1160. var sec = Math.round(diff % nd % nh % nm / ns); //计算差多少秒//输出结果
  1161. var showStr = "1 秒";
  1162. if (day > 0) {
  1163. showStr = day + "天";
  1164. } else if (hour > 0) {
  1165. showStr = hour + "小时";
  1166. } else if (min > 0) {
  1167. showStr = min + "分钟";
  1168. } else if (sec > 0) {
  1169. showStr = sec + "秒";
  1170. }
  1171. showStr += suffix;
  1172. return showStr;
  1173. }
  1174. /**
  1175. * 将时间显示成1秒、1天
  1176. * @description 主要用于 到期时间剩余 : 3天 这样的场景
  1177. * @param {String || Number} endTime 需要计算的时间 如到期时间
  1178. * vk.pubfn.dateDiff2(endTime);
  1179. */
  1180. pubfn.dateDiff2 = function(startTime, str = "1秒") {
  1181. if (!startTime) {
  1182. return "";
  1183. }
  1184. if (typeof startTime === "string" && !isNaN(startTime)) startTime = Number(startTime);
  1185. if (typeof startTime == "number") {
  1186. if (startTime.toString().length == 10) startTime *= 1000;
  1187. startTime = new Date(startTime);
  1188. startTime = pubfn.getFullTime(startTime);
  1189. }
  1190. if (typeof startTime == "string") {
  1191. startTime = startTime.replace("T", " ");
  1192. startTime = startTime;
  1193. startTime = new Date(startTime.replace(/-/g, "/")); //将-转化为/,使用new Date
  1194. }
  1195. var endTime = new Date(); //获取当前时间
  1196. var nd = 1000 * 24 * 60 * 60; //一天的毫秒数
  1197. var nh = 1000 * 60 * 60; //一小时的毫秒数
  1198. var nm = 1000 * 60; //一分钟的毫秒数
  1199. var ns = 1000; //一秒钟的毫秒数long diff;try {
  1200. var diff = startTime.getTime() - endTime.getTime();
  1201. var day = Math.floor(diff / nd);
  1202. var hour = Math.floor(diff % nd / nh);
  1203. var min = Math.floor(diff % nd % nh / nm);
  1204. var sec = Math.round(diff % nd % nh % nm / ns);
  1205. var showStr = str;
  1206. if (day > 0) {
  1207. showStr = day + "天";
  1208. } else if (hour > 0) {
  1209. showStr = hour + "小时";
  1210. } else if (min > 0) {
  1211. showStr = min + "分钟";
  1212. } else if (sec > 0) {
  1213. showStr = sec + "秒";
  1214. }
  1215. return showStr;
  1216. };
  1217. /**
  1218. * 将大数字转中文
  1219. * @description 主要用于展示浏览量等不需要非常精确显示的场景
  1220. * 如:
  1221. * 3210 -> 3千
  1222. * 31210 -> 3万
  1223. * 1523412 -> 1百万
  1224. * 15234120 ->1千万
  1225. * @param {Number} n 需要转换的数字
  1226. * vk.pubfn.numStr(n);
  1227. */
  1228. pubfn.numStr = function(n) {
  1229. if (typeof n == "string") {
  1230. n = parseFloat(n);
  1231. }
  1232. var str = n;
  1233. if (n < 1000) {
  1234. str = n;
  1235. } else if (n < 10000) {
  1236. var n1 = Math.floor(n / 100);
  1237. str = n1 / 10 + "千"
  1238. } else if (n < 1000000) {
  1239. var n1 = Math.floor(n / 1000);
  1240. str = n1 / 10 + "万"
  1241. } else if (n < 10000000) {
  1242. var n1 = Math.floor(n / 1000000);
  1243. str = n1 + "百万"
  1244. } else if (n < 100000000) {
  1245. var n1 = Math.floor(n / 10000000);
  1246. str = n1 + "千万"
  1247. } else if (n >= 100000000) {
  1248. var n1 = Math.floor(n / 10000000);
  1249. str = n1 / 10 + "亿"
  1250. }
  1251. return str;
  1252. };
  1253. /**
  1254. * 金额显示过滤器(已分为单位,将100 转成 1)
  1255. * @param {Number} money 金额
  1256. * vk.pubfn.priceFilter(money);
  1257. */
  1258. pubfn.priceFilter = function(money, defaultValue = "") {
  1259. if (pubfn.isNull(money)) {
  1260. return defaultValue;
  1261. }
  1262. if (isNaN(money)) {
  1263. return money;
  1264. }
  1265. if (typeof money == "string") {
  1266. money = parseFloat(money);
  1267. }
  1268. return (money / 100).toFixed(2);
  1269. };
  1270. // 金额过滤器 - 只显示小数点左边
  1271. pubfn.priceLeftFilter = function(n) {
  1272. let s = "";
  1273. if (n) {
  1274. s = pubfn.priceFilter(n).split(".")[0];
  1275. }
  1276. return s;
  1277. };
  1278. // 金额过滤器 - 只显示小数点右边
  1279. pubfn.priceRightFilter = function(n) {
  1280. let s = "";
  1281. if (n) {
  1282. s = pubfn.priceFilter(n).split(".")[1];
  1283. }
  1284. return s;
  1285. };
  1286. /**
  1287. * 百分比过滤器 将 0.01 显示成 1% 1 显示成 100%
  1288. * @param {Number} value 百分比值
  1289. * @param {Boolean} needShowSymbol 显示 % 这个符号
  1290. * @param {String | Number} defaultValue value为空时的默认值
  1291. * vk.pubfn.percentageFilter(money);
  1292. */
  1293. pubfn.percentageFilter = function(value, needShowSymbol = true, defaultValue = "") {
  1294. if (pubfn.isNull(value)) {
  1295. return defaultValue;
  1296. }
  1297. if (isNaN(value)) {
  1298. return value;
  1299. }
  1300. if (typeof value == "string") {
  1301. value = parseFloat(value);
  1302. }
  1303. value = parseFloat((value * 100).toFixed(2));
  1304. if (needShowSymbol) {
  1305. value += "%";
  1306. }
  1307. return value;
  1308. };
  1309. /**
  1310. * 折扣过滤器 将 0.1 显示成 1折 1 显示成 原价 0 显示成免费
  1311. * @param {Number} value 折扣值
  1312. * @param {Boolean} needShowSymbol 显示 折 这个中文字符
  1313. * @param {String | Number} defaultValue value为空时的默认值
  1314. * vk.pubfn.discountFilter(value);
  1315. */
  1316. pubfn.discountFilter = function(value, needShowSymbol = true, defaultValue = "") {
  1317. if (pubfn.isNull(value)) {
  1318. return defaultValue;
  1319. }
  1320. if (isNaN(value)) {
  1321. return value;
  1322. }
  1323. if (typeof value == "string") {
  1324. value = parseFloat(value);
  1325. }
  1326. value = parseFloat((value * 10).toFixed(2));
  1327. if (value > 10) {
  1328. return "折扣不可以大于原价";
  1329. }
  1330. if (value == 10) {
  1331. return "原价";
  1332. }
  1333. if (value == 0) {
  1334. return "免费";
  1335. }
  1336. if (value < 0) {
  1337. return "折扣不可以小于0";
  1338. }
  1339. if (needShowSymbol) {
  1340. value += " 折";
  1341. }
  1342. return value;
  1343. };
  1344. /**
  1345. * 将字符串格式的时间转为时间戳
  1346. * @param {String} dateString 格式为:2020-08-08 12:12:12
  1347. */
  1348. pubfn.toTimeLong = function(dateString) {
  1349. if (!dateString) {
  1350. return "";
  1351. }
  1352. dateString = dateString.substring(0, 19);
  1353. dateString = dateString.replace(new RegExp(/-/, "g"), '/');
  1354. let time = new Date(dateString).getTime();
  1355. if (isNaN(time)) {
  1356. time = "";
  1357. }
  1358. return time;
  1359. };
  1360. /**
  1361. * 单位进制换算
  1362. * length 换算前大小
  1363. * arr 进制的数组,如["B","KB","MB","GB"]
  1364. * ary 进制,如KB-MB-GB,进制1024
  1365. * precision 数值精度
  1366. * vk.pubfn.calcSize(length,["B","KB","MB","GB"],1024,3);
  1367. */
  1368. pubfn.calcSize = function(length = 0, arr, ary, precision = 2, showType = "auto") {
  1369. length = parseFloat(length);
  1370. let size = 0;
  1371. let type = "";
  1372. if (length < ary || arr.length <= 1) {
  1373. type = arr[0];
  1374. size = parseFloat(length.toFixed(precision));
  1375. } else {
  1376. for (let i = 1; i < arr.length; i++) {
  1377. let currentType = arr[i];
  1378. length = length / ary;
  1379. if (showType === "auto") {
  1380. if (length < ary) {
  1381. type = currentType;
  1382. size = parseFloat(length.toFixed(precision));
  1383. break;
  1384. }
  1385. } else {
  1386. if (showType === currentType) {
  1387. type = currentType;
  1388. size = parseFloat(length.toFixed(precision));
  1389. break;
  1390. }
  1391. }
  1392. }
  1393. }
  1394. return {
  1395. size: size,
  1396. type: type,
  1397. title: size + " " + type
  1398. }
  1399. };
  1400. /**
  1401. * 手机端长列表分页加载数据 2.0版本
  1402. * @param {Vue页面对象} that 页面数据对象this
  1403. * @param {String} url 请求地址(云函数路径)
  1404. * @param {String} listName 后端返回的list数组的字段名称,默认rows(二选一即可)
  1405. * @param {String} listKey 后端返回的list数组的字段名称,默认rows(二选一即可)
  1406. * @param {Object} data 额外数据
  1407. * @param {function} dataPreprocess 数据预处理函数
  1408. *
  1409. * 代码示例
  1410. vk.pubfn.getListData2({
  1411. that : this,
  1412. url : "template/db_api/pub/select",
  1413. data : {
  1414. a : 1
  1415. },
  1416. dataPreprocess : function(list){
  1417. return list;
  1418. }
  1419. });
  1420. */
  1421. pubfn.getListData2 = function(obj = {}) {
  1422. let {
  1423. that,
  1424. listName,
  1425. listKey = "rows",
  1426. url,
  1427. dataPreprocess,
  1428. idKeyName = "_id"
  1429. } = obj;
  1430. if (listName) listKey = listName;
  1431. /**
  1432. * 2.0与1.0的区别
  1433. * 2.0使用的queryForm1作为查询,而1.0是form1
  1434. * 2.0云函数端是getTableData,而1.0是selects
  1435. */
  1436. let { vk } = that;
  1437. let queryForm1 = that.queryForm1 || that.queryForm;
  1438. // 标记为请求中
  1439. that.loading = true;
  1440. let hasMore = true;
  1441. if (queryForm1.pagination.pageIndex === 1) {
  1442. that.firstLoading = true;
  1443. }
  1444. vk.callFunction({
  1445. url: url,
  1446. data: queryForm1,
  1447. success: function(data) {
  1448. let list = data[listKey] || [];
  1449. // 数据预处理
  1450. if (typeof dataPreprocess == "function") {
  1451. list = dataPreprocess(list);
  1452. }
  1453. if (queryForm1.pagination.pageIndex > 1) {
  1454. // 翻页
  1455. if (list.length == 0) {
  1456. // 无数据时
  1457. hasMore = false;
  1458. queryForm1.pagination.pageIndex--;
  1459. list = that.data.list;
  1460. } else {
  1461. // 有数据时
  1462. if (list.length < queryForm1.pagination.pageSize) {
  1463. hasMore = false;
  1464. }
  1465. // 数据合并
  1466. list = vk.pubfn.arr_concat(that.data.list, list, idKeyName);
  1467. }
  1468. } else if (queryForm1.pagination.pageIndex == 1) {
  1469. // 第一页
  1470. if (list.length < queryForm1.pagination.pageSize) {
  1471. hasMore = false;
  1472. }
  1473. if (list.length == 0) {
  1474. that.state.isEmpty = true;
  1475. } else {
  1476. that.state.isEmpty = false;
  1477. }
  1478. }
  1479. // 如果后端返回了hasMore,则使用后端的hasMore值
  1480. if (typeof data.hasMore !== "undefined") {
  1481. hasMore = data.hasMore;
  1482. }
  1483. data = {
  1484. ...data,
  1485. total: data.total,
  1486. list: list,
  1487. hasMore: hasMore,
  1488. pageIndex: data.pageIndex,
  1489. pageSize: data.pageSize
  1490. };
  1491. that.state.loadmore = hasMore ? "loadmore" : "nomore"; // 更新状态
  1492. that.data = vk.pubfn.objectAssign(that.data, data); // 更新数据
  1493. if (typeof obj.success == "function") obj.success(data);
  1494. },
  1495. fail: function(err) {
  1496. that.state.loadmore = "loadmore";
  1497. if (queryForm1.pagination.pageIndex > 1) {
  1498. queryForm1.pagination.pageIndex--;
  1499. }
  1500. if (typeof obj.fail == "function") {
  1501. obj.fail(data);
  1502. } else if (err && err.msg) {
  1503. vk.toast(err.msg, "none");
  1504. }
  1505. },
  1506. complete: function(res) {
  1507. that.loading = false;
  1508. if (queryForm1.pagination.pageIndex === 1) {
  1509. that.state.firstLoading = false;
  1510. }
  1511. if (typeof obj.complete == "function") obj.complete(res);
  1512. }
  1513. });
  1514. };
  1515. /**
  1516. * 手机端长列表分页加载数据(1.0版本)
  1517. * @param {Vue页面对象} that 页面数据对象this
  1518. * @param {String} url 请求地址(云函数路径)
  1519. * @param {String} listName 后端返回的list数组的字段名称,默认rows
  1520. * @param {String} listKey 后端返回的list数组的字段名称,默认rows
  1521. * @param {Object} data 额外数据
  1522. * @param {function} dataPreprocess 数据预处理函数
  1523. *
  1524. * 代码示例
  1525. vk.pubfn.getListData({
  1526. that : this,
  1527. url : "template/db_api/pub/select",
  1528. listKey : "rows",
  1529. data : {
  1530. a : 1
  1531. },
  1532. dataPreprocess : function(list){
  1533. return list;
  1534. }
  1535. });
  1536. */
  1537. pubfn.getListData = function(obj = {}) {
  1538. var {
  1539. that,
  1540. listName,
  1541. listKey = "rows",
  1542. url,
  1543. dataPreprocess,
  1544. loading
  1545. } = obj;
  1546. if (listName) listKey = listName;
  1547. var { form1 = {}, data = {} } = that;
  1548. var { pageKey = true } = data;
  1549. var vk = that.vk;
  1550. if (!form1.pageIndex) form1.pageIndex = 1;
  1551. if (!form1.pageSize) form1.pageSize = 20;
  1552. var addTime = form1.addTime;
  1553. var endTime = form1.endTime;
  1554. if (endTime) endTime += " 23:59:59";
  1555. if (!pageKey && form1.pageIndex > 1) {
  1556. form1.pageIndex--;
  1557. return false;
  1558. }
  1559. if (addTime) form1.addTimeLong = pubfn.toTimeLong(addTime);
  1560. if (endTime) form1.endTimeLong = pubfn.toTimeLong(endTime);
  1561. if (obj.data && JSON.stringify(obj.data) != "{}") {
  1562. pubfn.objectAssign(form1, obj.data);
  1563. }
  1564. let title = obj.title;
  1565. if (typeof obj.title == "undefined" && !loading) {
  1566. title = form1.pageIndex == 1 ? "请求中..." : "";
  1567. }
  1568. vk.callFunction({
  1569. url: url,
  1570. data: form1,
  1571. title: title,
  1572. loading: loading,
  1573. success: function(data) {
  1574. var list = data[listKey] || [];
  1575. // 数据预处理
  1576. if (typeof dataPreprocess == "function") {
  1577. list = dataPreprocess(list);
  1578. }
  1579. if (form1.pageIndex > 1) {
  1580. // 翻页
  1581. if (list.length == 0) {
  1582. // 无数据时
  1583. pageKey = false;
  1584. form1.pageIndex--;
  1585. list = that.data.list;
  1586. } else {
  1587. // 有数据时
  1588. if (list.length < form1.pageSize) {
  1589. pageKey = false;
  1590. }
  1591. let oldList = that.data.list;
  1592. // 数据合并
  1593. list = pubfn.arr_concat(oldList, list, "_id");
  1594. }
  1595. } else if (form1.pageIndex == 1) {
  1596. if (list.length < form1.pageSize) {
  1597. pageKey = false;
  1598. }
  1599. }
  1600. //console.log(pageKey,list.length,form1.pageSize);
  1601. data = {
  1602. ...data,
  1603. total: data.total,
  1604. list: list,
  1605. pageKey: pageKey,
  1606. loadmore: pageKey ? "loadmore" : "nomore" // 更新状态
  1607. };
  1608. that.data = pubfn.objectAssign(that.data, data); // 更新数据
  1609. if (typeof obj.success == "function") obj.success(data);
  1610. },
  1611. fail: function(err) {
  1612. if (form1.pageIndex > 1) { form1.pageIndex--; }
  1613. if (typeof obj.fail == "function") {
  1614. obj.fail(data);
  1615. } else if (err && err.msg) {
  1616. vk.toast(err.msg, "none");
  1617. }
  1618. },
  1619. complete: function(res) {
  1620. if (typeof obj.complete == "function") obj.complete(res);
  1621. },
  1622. });
  1623. };
  1624. /**
  1625. * 动态组件数据获取
  1626. * @description 主要用于动态组件的数据获取
  1627. * @param {Vue页面对象} that 页面数据对象this
  1628. * @param {String} ids 动态数据组件的ID
  1629. *
  1630. * 代码示例
  1631. * 如:放置一个动态数据的 公告组件 和 一个轮播图组件
  1632. * view 核心:自定义组件接收一个 Object 类型的属性 datas
  1633. <vk-u-notice-bar :datas='componentsDynamic["notice-bar-01"]'></vk-u-notice-bar>
  1634. <vk-u-swiper :datas='componentsDynamic["index-swiper-01"]' :custom-datas='{
  1635. "height":600,
  1636. }'></vk-u-swiper>
  1637. 在页面数据变量中新增 componentsDynamic
  1638. data() {
  1639. return {
  1640. // 动态组件数据集合
  1641. componentsDynamic:{}
  1642. }
  1643. }
  1644. 在页面初始化方法中执行下面的函数
  1645. this.vk.pubfn.getComponentsDynamicData({
  1646. that : this,
  1647. ids : ["notice-bar-01","index-swiper-01"]
  1648. });
  1649. */
  1650. pubfn.getComponentsDynamicData = function(obj = {}) {
  1651. var {
  1652. that,
  1653. keyName = "componentsDynamic",
  1654. title,
  1655. url = "plugs/components_dynamic/client/pub/getComponentsDynamicData",
  1656. ids
  1657. } = obj;
  1658. var vk = that.vk;
  1659. let form1 = {
  1660. ids: ids
  1661. };
  1662. if (obj.data && JSON.stringify(obj.data) != "{}") {
  1663. pubfn.objectAssign(form1, obj.data);
  1664. }
  1665. // 读取缓存开始-----------------------------------------------------------
  1666. let cacheKey = "pub-componentsDynamic";
  1667. let cacheData = uni.getStorageSync(cacheKey) || {};
  1668. let cacheDataKey = JSON.stringify(ids);
  1669. if (cacheData[cacheDataKey]) {
  1670. // 渲染本地数据
  1671. that[keyName] = cacheData[cacheDataKey];
  1672. }
  1673. // 读取缓存结束-----------------------------------------------------------
  1674. vk.callFunction({
  1675. url: url,
  1676. data: form1,
  1677. title: title,
  1678. success: function(data) {
  1679. if (JSON.stringify(cacheData[cacheDataKey]) !== JSON.stringify(data.componentsDynamic)) {
  1680. // 渲染服务器数据
  1681. that[keyName] = data.componentsDynamic;
  1682. // 同时将组件数据进行缓存
  1683. cacheData[cacheDataKey] = data.componentsDynamic;
  1684. uni.setStorageSync(cacheKey, cacheData);
  1685. }
  1686. if (typeof obj.success == "function") obj.success(data);
  1687. },
  1688. fail: function(err) {
  1689. console.error(err);
  1690. if (typeof obj.fail == "function") obj.fail(data);
  1691. },
  1692. complete: function() {
  1693. if (typeof obj.complete == "function") obj.complete(data);
  1694. },
  1695. });
  1696. };
  1697. /**
  1698. * 将../../ 形式的页面相对路径 转成 页面绝对路径
  1699. * @param {String} url 需要转换的url
  1700. * vk.pubfn.getPageFullPath(url);
  1701. */
  1702. pubfn.getPageFullPath = function(url) {
  1703. let fullPath = url;
  1704. if (fullPath.indexOf("/") !== 0) {
  1705. if (fullPath.indexOf("./") === 0) {
  1706. //fullPath = "." + fullPath;
  1707. fullPath = fullPath.substring(2);
  1708. }
  1709. let urlSplit = fullPath.split("../");
  1710. // 向上目录级数,0:根目录 1:向上1级
  1711. let level = urlSplit.length;
  1712. // 尾部路径
  1713. let urlEnd = urlSplit[level - 1];
  1714. // 获取当前页面的页面全路径
  1715. let pages = getCurrentPages();
  1716. let currentPage = pages[pages.length - 1];
  1717. let currentPagePath = currentPage.route;
  1718. // 分割成目录,最后一段是页面名称
  1719. let urlArr = currentPagePath.split("/");
  1720. let urlSplicing = "";
  1721. // 开始拼接
  1722. for (let i = 0; i < urlArr.length - level; i++) {
  1723. urlSplicing += urlArr[i] + "/";
  1724. }
  1725. // 完整页面路径
  1726. fullPath = urlSplicing + urlEnd;
  1727. if (fullPath.indexOf("/") != 0) {
  1728. fullPath = "/" + fullPath;
  1729. }
  1730. }
  1731. return fullPath;
  1732. };
  1733. /**
  1734. * 获取平台信息
  1735. * let platform = vk.pubfn.getPlatform();
  1736. */
  1737. pubfn.getPlatform = function() {
  1738. let platform;
  1739. // #ifdef APP-PLUS || APP-NVUE || APP-PLUS-NVUE
  1740. platform = "app-plus";
  1741. // #endif
  1742. // #ifdef H5
  1743. platform = "h5";
  1744. // #endif
  1745. // #ifdef MP-WEIXIN
  1746. platform = "mp-weixin";
  1747. // #endif
  1748. // #ifdef MP-ALIPAY
  1749. platform = "mp-alipay";
  1750. // #endif
  1751. // #ifdef MP-BAIDU
  1752. platform = "mp-baidu";
  1753. // #endif
  1754. // #ifdef MP-TOUTIAO
  1755. platform = "mp-toutiao";
  1756. // #endif
  1757. // #ifdef MP-QQ
  1758. platform = "mp-qq";
  1759. // #endif
  1760. // #ifdef MP-360
  1761. platform = "mp-360";
  1762. // #endif
  1763. // #ifdef MP-KUAISHOU
  1764. platform = "mp-toutiao";
  1765. // #endif
  1766. return platform;
  1767. };
  1768. /**
  1769. * 获取当前页面实例
  1770. * 返回数据
  1771. * fullPath 当前打开页面的完整路径(带页面参数)
  1772. * options 当前打开页面的参数
  1773. * route 当前打开页面的路径(不含参数)
  1774. * $vm 当前打开页面的vue实例
  1775. * vk.pubfn.getCurrentPage();
  1776. */
  1777. pubfn.getCurrentPage = function() {
  1778. let res = {};
  1779. let pages = getCurrentPages();
  1780. let page = pages[pages.length - 1];
  1781. res.fullPath = page.$page.fullPath;
  1782. res.options = page.options;
  1783. res.route = page.route;
  1784. res.$vm = page.$vm;
  1785. return res;
  1786. };
  1787. /**
  1788. * 获取当前页面路由
  1789. * vk.pubfn.getCurrentPageRoute();
  1790. */
  1791. pubfn.getCurrentPageRoute = function(removeSlash) {
  1792. let pages = getCurrentPages();
  1793. let page = pages[pages.length - 1];
  1794. if (removeSlash) {
  1795. return page.route;
  1796. } else {
  1797. return "/" + page.route;
  1798. }
  1799. };
  1800. /**
  1801. * 文件转base64
  1802. 方式一
  1803. vk.pubfn.fileToBase64({
  1804. file:res.tempFiles[0],
  1805. success:function(base64){
  1806. }
  1807. });
  1808. 方式二
  1809. vk.pubfn.fileToBase64({ file }).then(base64 => {
  1810. });
  1811. */
  1812. pubfn.fileToBase64 = function(obj = {}) {
  1813. let { file } = obj;
  1814. return new Promise(function(resolve, reject) {
  1815. // #ifdef H5
  1816. let reader = new FileReader();
  1817. reader.readAsDataURL(file);
  1818. reader.onload = function(res) {
  1819. let base64 = this.result;
  1820. if (base64.indexOf(";base64,") == -1) {
  1821. base64 = "data:image/jpeg;base64," + base64;
  1822. }
  1823. if (obj.success) obj.success(base64);
  1824. if (obj.complete) obj.complete(base64);
  1825. resolve(base64);
  1826. };
  1827. reader.onerror = function(err) {
  1828. if (obj.fail) obj.fail(err);
  1829. if (obj.complete) obj.complete(err);
  1830. reject(err);
  1831. };
  1832. // #endif
  1833. // #ifdef MP
  1834. uni.getFileSystemManager().readFile({
  1835. filePath: file.path,
  1836. encoding: "base64",
  1837. success: function(res) {
  1838. let base64 = res.data;
  1839. if (base64.indexOf(";base64,") == -1) {
  1840. base64 = "data:image/jpeg;base64," + base64;
  1841. }
  1842. if (obj.success) obj.success(base64);
  1843. if (obj.complete) obj.complete(base64);
  1844. resolve(base64);
  1845. },
  1846. fail: function(err) {
  1847. if (obj.fail) obj.fail(err);
  1848. reject(err);
  1849. },
  1850. complete: obj.complete
  1851. });
  1852. // let base64 = uni.getFileSystemManager().readFileSync(file.path, 'base64');
  1853. // if(obj.success) obj.success(base64);
  1854. // if(obj.complete) obj.complete(base64);
  1855. // resolve(base64);
  1856. // #endif
  1857. // #ifdef APP-PLUS
  1858. plus.io.resolveLocalFileSystemURL(pubfn.getLocalFilePath(file.path), function(entry) {
  1859. entry.file(function(file) {
  1860. let fileReader = new plus.io.FileReader();
  1861. fileReader.onload = function(data) {
  1862. if (obj.success) obj.success(data.target.result);
  1863. if (obj.complete) obj.complete(data.target.result);
  1864. resolve(data.target.result);
  1865. }
  1866. fileReader.onerror = function(err) {
  1867. if (obj.fail) obj.fail(err);
  1868. reject(err);
  1869. }
  1870. fileReader.readAsDataURL(file)
  1871. }, function(err) {
  1872. if (obj.fail) obj.fail(err);
  1873. reject(err);
  1874. })
  1875. }, function(err) {
  1876. if (obj.fail) obj.fail(err);
  1877. reject(err);
  1878. })
  1879. // #endif
  1880. });
  1881. };
  1882. /**
  1883. * base64转文件
  1884. 方式一
  1885. vk.pubfn.base64ToFile({
  1886. base64:base64,
  1887. success:function(file){
  1888. }
  1889. });
  1890. 方式二
  1891. vk.pubfn.base64ToFile({ base64 }).then(file => {
  1892. });
  1893. */
  1894. pubfn.base64ToFile = function(obj = {}) {
  1895. let {
  1896. base64 = "",
  1897. filePath
  1898. } = obj;
  1899. let extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/);
  1900. if (extName) {
  1901. extName = extName[1];
  1902. } else {
  1903. reject(new Error('base64 error'));
  1904. }
  1905. if (!filePath) {
  1906. filePath = pubfn.random(32, "abcdefghijklmnopqrstuvwxyz0123456789") + '.' + extName;
  1907. }
  1908. let index = base64.indexOf("base64,");
  1909. let base64Data = base64;
  1910. if (index > -1) {
  1911. base64Data = base64.substring(base64.indexOf("base64,") + 7);
  1912. }
  1913. let savePath;
  1914. return new Promise(function(resolve, reject) {
  1915. // #ifdef MP
  1916. savePath = wx.env.USER_DATA_PATH + '/' + filePath;
  1917. let fs = uni.getFileSystemManager();
  1918. fs.writeFile({
  1919. filePath: savePath,
  1920. data: base64Data,
  1921. encoding: "base64",
  1922. success: function(res) {
  1923. let file = {
  1924. path: savePath,
  1925. lastModifiedDate: new Date(),
  1926. name: filePath
  1927. };
  1928. if (obj.success) obj.success(file);
  1929. resolve(file);
  1930. },
  1931. fail: function(res) {
  1932. if (obj.fail) obj.fail(res);
  1933. reject(res);
  1934. },
  1935. complete: obj.complete
  1936. });
  1937. // #endif
  1938. // #ifdef H5
  1939. savePath = filePath;
  1940. let blob = pubfn.base64toBlob(base64);
  1941. let file = pubfn.blobToFile(blob, savePath);
  1942. if (obj.success) obj.success(file);
  1943. if (obj.complete) obj.complete(file);
  1944. resolve(file);
  1945. // #endif
  1946. // #ifdef APP-PLUS
  1947. let fileName = filePath;
  1948. let basePath = '_user_resources';
  1949. let dirPath = 'vk_temp';
  1950. savePath = basePath + '/' + dirPath + '/' + fileName;
  1951. let bitmap = new plus.nativeObj.Bitmap(fileName);
  1952. bitmap.loadBase64Data(base64, function() {
  1953. bitmap.save(savePath, {}, function() {
  1954. bitmap.clear();
  1955. let file = {
  1956. path: savePath,
  1957. lastModifiedDate: new Date(),
  1958. name: filePath
  1959. };
  1960. if (obj.success) obj.success(file);
  1961. if (obj.complete) obj.complete(file);
  1962. resolve(file);
  1963. }, function(error) {
  1964. bitmap.clear();
  1965. if (obj.fail) obj.fail(error);
  1966. reject(error);
  1967. })
  1968. }, function(error) {
  1969. bitmap.clear();
  1970. if (obj.fail) obj.fail(error);
  1971. reject(error);
  1972. })
  1973. // #endif
  1974. });
  1975. };
  1976. /**
  1977. * 将base64转换为blob (H5独有)
  1978. vk.pubfn.base64toBlob(base64);
  1979. */
  1980. pubfn.base64toBlob = function(base64) {
  1981. let arr = base64.split(',');
  1982. let mime = arr[0].match(/:(.*?);/)[1];
  1983. let bstr = atob(arr[1]);
  1984. let n = bstr.length;
  1985. let u8arr = new Uint8Array(n);
  1986. while (n--) {
  1987. u8arr[n] = bstr.charCodeAt(n);
  1988. }
  1989. return new Blob([u8arr], { type: mime });
  1990. };
  1991. /**
  1992. * //将blob转换为file
  1993. vk.pubfn.blobToFile(base64);
  1994. */
  1995. pubfn.blobToFile = function(blob, fileName) {
  1996. blob.lastModifiedDate = new Date();
  1997. blob.name = fileName;
  1998. blob.path = URL.createObjectURL(blob);
  1999. return blob;
  2000. };
  2001. /**
  2002. * 小程序订阅消息 前端无需再写 #ifdef MP-WEIXIN
  2003. vk.pubfn.requestSubscribeMessage({
  2004. tmplIds: ['NcspDBQpH6CGHos3mMADrrQpEv2gHmtfOPa5KTLs92E']
  2005. });
  2006. */
  2007. pubfn.requestSubscribeMessage = function(obj) {
  2008. // #ifdef MP-WEIXIN
  2009. return uni.requestSubscribeMessage(obj);
  2010. // #endif
  2011. };
  2012. /**
  2013. * 检测是否需要登录 此方法目前为测试版
  2014. * vk.pubfn.checkLogin();
  2015. */
  2016. pubfn.checkLogin = function(obj = {}) {
  2017. let vk = uni.vk;
  2018. let loginUrl = vk.getVuex("$app.config.login.url");
  2019. try {
  2020. let url;
  2021. try {
  2022. url = obj.url || vk.pubfn.getCurrentPageRoute();
  2023. } catch (err) {
  2024. url = vk.getVuex("$app.config.index.url") || "/pages/index/index";
  2025. }
  2026. vk.navigate.checkNeedLogin({
  2027. url: url,
  2028. success: function(res) {
  2029. if (res.needLogin) {
  2030. // 记录下原本要跳转的页面
  2031. url = vk.pubfn.getPageFullPath(url);
  2032. vk.navigate.originalPage = { url };
  2033. if (obj.isOnLaunch) vk.navigate.isOnLaunchToLogin = true; // 标记为首次启动的页面需要登录
  2034. uni.reLaunch({
  2035. url: loginUrl,
  2036. success: () => {
  2037. // #ifdef MP-WEIXIN
  2038. setTimeout(() => {
  2039. uni.hideHomeButton();
  2040. }, 400);
  2041. // #endif
  2042. }
  2043. });
  2044. } else {
  2045. vk.navigate.originalPage = null;
  2046. }
  2047. }
  2048. });
  2049. } catch (err) {
  2050. console.error("catch", err);
  2051. uni.reLaunch({
  2052. url: loginUrl
  2053. });
  2054. // #ifdef MP-WEIXIN
  2055. uni.hideHomeButton();
  2056. // #endif
  2057. }
  2058. };
  2059. /**
  2060. * 获取文件本地路径
  2061. * @param {Object} path
  2062. */
  2063. pubfn.getLocalFilePath = function(path) {
  2064. if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
  2065. return path
  2066. }
  2067. if (path.indexOf('file://') === 0) {
  2068. return path
  2069. }
  2070. if (path.indexOf('/storage/emulated/0/') === 0) {
  2071. return path
  2072. }
  2073. if (path.indexOf('/') === 0 && typeof plus !== "undefined") {
  2074. let localFilePath = plus.io.convertAbsoluteFileSystem(path)
  2075. if (localFilePath !== path) {
  2076. return localFilePath
  2077. } else {
  2078. path = path.substr(1)
  2079. }
  2080. }
  2081. return '_www/' + path
  2082. };
  2083. /**
  2084. * 获取当前支持的应用语言
  2085. * let localeList = vk.pubfn.getLocaleList();
  2086. */
  2087. pubfn.getLocaleList = function() {
  2088. let localeList = [
  2089. { value: "zh-Hans", label: "简体中文" },
  2090. { value: "zh-Hant", label: "繁體中文" },
  2091. { value: "en", label: "English" }
  2092. ];
  2093. return localeList;
  2094. };
  2095. /**
  2096. * 获取当前应用语言
  2097. * let locale = vk.pubfn.getLocale();
  2098. */
  2099. pubfn.getLocale = function() {
  2100. let localeValue;
  2101. if (typeof uni.getLocale === "function") {
  2102. localeValue = uni.getLocale();
  2103. } else {
  2104. localeValue = "zh-Hans"; // 默认中文简体
  2105. }
  2106. let localeObj = {
  2107. "zh_CN": "zh-Hans", // 中国大陆(简体)
  2108. "zh_HK": "zh-Hant", // 香港(繁体)
  2109. "zh_MO": "zh-Hant", // 澳门(繁体)
  2110. "zh_SG": "zh-Hans", // 新加坡(简体)
  2111. "zh_TW": "zh-Hant", // 台湾(繁体)
  2112. };
  2113. if (localeObj[localeValue]) localeValue = localeObj[localeValue];
  2114. return localeValue;
  2115. };
  2116. /**
  2117. * 获取当前应用语言
  2118. * let localeObj = vk.pubfn.getLocaleObject();
  2119. */
  2120. pubfn.getLocaleObject = function() {
  2121. let value = pubfn.getLocale();
  2122. let list = pubfn.getLocaleList();
  2123. return pubfn.getListItem(list, "value", value);
  2124. };
  2125. /**
  2126. * 设置当前应用语言
  2127. */
  2128. pubfn.setLocale = function(...e) {
  2129. return uni.setLocale(...e);
  2130. };
  2131. function biggerThan(v1, v2) {
  2132. let v1Array = v1.split('.')
  2133. let v2Array = v2.split('.')
  2134. let update = false
  2135. for (let index = 0; index < v2Array.length; index++) {
  2136. let diff = v1Array[index] - v2Array[index]
  2137. if (diff !== 0) {
  2138. update = diff > 0
  2139. break
  2140. }
  2141. }
  2142. return update
  2143. }
  2144. // 前端专属结束 -----------------------------------------------------------
  2145. export default pubfn;