1e3&&(u=1e3));let l=await baseDao.getSelectData(e),{result:c,hasMore:d,total:p,getCount:f,pageIndex:g,pageSize:m,fieldJson:b}=l;m>0&&!p&&!f&&(p=m),i.pubfn.isNotNull(b)&&(c=c.field(b));let h={};if(f&&0===p)h={data:[]};else{let t=p;mr&&(n=r-t);let o=c.skip(t).limit(n).get();i.push(o)}try{h=(await Promise.all(i)).reduce((e,t)=>({data:e.data.concat(t.data),errMsg:e.errMsg}))}catch(t){throw console.error("vk.baseDao.select-异常",e,t),new Error("msg:vk.baseDao.select-异常")}}let y={};return y.total=f?p:h.data?h.data.length:0,y.hasMore=d,y.rows=h.data,y.code=0,y.msg="查询成功",y.pagination={pageIndex:g,pageSize:m},o&&(y.rows=y.rows[0]),s?y.rows:y},sum:async function(e){let{vk:t,db:n,_:i}=util$1,{dbName:a,fieldName:r,whereJson:o,db:s}=e,u=s||n;const l=u.command.aggregate;let c=u.collection(a).aggregate();t.pubfn.isNotNull(o)&&c.match(o),c.group({_id:null,num:l.sum("$"+r)});let d=await c.end();return d.data&&d.data[0]?d.data[0].num:0},avg:async function(e){let{vk:t,db:n,_:i}=util$1,{dbName:a,fieldName:r,whereJson:o,db:s}=e,u=s||n;const l=u.command.aggregate;let c=u.collection(a).aggregate();t.pubfn.isNotNull(o)&&c.match(o),c.group({_id:null,num:l.avg("$"+r)});let d=await c.end();return d.data&&d.data[0]?d.data[0].num:null},max:async function(e){let{vk:t,db:n,_:i}=util$1,{dbName:a,fieldName:r,whereJson:o,db:s}=e,u=s||n;const l=u.command.aggregate;let c=u.collection(a).aggregate();t.pubfn.isNotNull(o)&&c.match(o),c.group({_id:null,num:l.max("$"+r)});let d=await c.end();return d.data&&d.data[0]?d.data[0].num:null},min:async function(e){let{vk:t,db:n,_:i}=util$1,{dbName:a,fieldName:r,whereJson:o,db:s}=e,u=s||n;const l=u.command.aggregate;let c=u.collection(a).aggregate();t.pubfn.isNotNull(o)&&c.match(o),c.group({_id:null,num:l.min("$"+r)});let d=await c.end();return d.data&&d.data[0]?d.data[0].num:null},sample:async function(e){let{vk:t,db:n,_:i}=util$1,{dbName:a,whereJson:r,size:o,fieldJson:s,db:u}=e,l=u||n;l.command.aggregate;let c=l.collection(a).aggregate();return t.pubfn.isNotNull(r)&&c.match(r),c.sample({size:o}).limit(o),t.pubfn.isNotNull(s)&&c.project(s),(await c.end()).data},selects:async function(e={}){let{vk:t,db:n,_:i}=util$1;if(t.pubfn.isNotNull(e.treeProps))return await baseDao.tree(e);"string"==typeof e.pageIndex&&(e.pageIndex=parseInt(e.pageIndex)),"string"==typeof e.pageSize&&(e.pageSize=parseInt(e.pageSize));let{db:a,dbName:r,foreignKey:o="_id",pageIndex:s=1,pageSize:u=10,getCount:l=!1,getOne:c=!1,getMain:d=!1,whereJson:p={},unwindJson:f,groupJson:g,sortArr:m=[],foreignDB:b=[],lastWhereJson:h,lastSortArr:y=[],fieldJson:w={},addFields:_}=e,k=a||n;-1==u&&(s=1,u=999999999,l=!1),c&&(u=1,l=!1);let v,x=0,N=!1;if(t.pubfn.isNotNull(p))for(let e in p)p[e]&&"object"==typeof p[e]&&"geoNear"===p[e].operator&&(v=t.pubfn.copyObject(p[e]),v.keyName=e,v.limit=s*u,delete p[e]);if(l){if(t.pubfn.isNullAll(g,f,h)){let e;e=t.pubfn.isNotNull(p)?await k.collection(r).where(p).count():await k.collection(r).count(),x=e.total}else{let e=k.collection(r).aggregate();t.pubfn.isNotNull(p)&&(t.pubfn.isNotNull(v)?e=baseDao.getGeoNearJson({runDB:k,result:e,geoNearJson:v,whereJson:p}):e.match(p)),t.pubfn.isNotNull(f)&&(e=baseDao.getTnwind({result:e,unwindJson:f})),t.pubfn.isNotNull(g)&&e.group(g),t.pubfn.isNotNull(h)&&(t.pubfn.isNotNull(b)&&(e=baseDao.addForeignDB({foreignDB:b,foreignKey:o,result:e})),e.match(h)),e=await e.count("total").end(),x=e.data[0]?e.data[0].total:0}s=u),$.rows=O,$.code=0,$.msg="查询成功",$.pagination={pageIndex:s,pageSize:u},c&&($.rows=$.rows[0]),d?$.rows:$},listToObjectByLimit1:function(e){let{vk:t,db:n,_:i}=util$1,{list:a,foreignDB:r}=e;if(t.pubfn.isNotNull(r))for(let e in a)for(let n in r){let{as:i,limit:o,foreignDB:s,dbName:u}=r[n];i||(i=u),t.pubfn.isNotNull(s)&&(a[e][i]=baseDao.listToObjectByLimit1({list:a[e][i],foreignDB:s})),1===o&&(t.pubfn.isArray(a[e][i])?a[e][i]&&a[e][i].length>0?a[e][i]=a[e][i][0]:a[e][i]={}:void 0===a[e][i]&&(a[e][i]={}))}return a},addForeignDB:function(e){let{vk:t,db:n,_:i}=util$1,{foreignDB:a,foreignKey:r,result:o}=e;const s=i.aggregate;for(let e in a){let n,{dbName:u,foreignKey:l,localKey:c,localKeyType:d="",foreignKeyType:p="",as:f,limit:g,getOne:m,whereJson:b,fieldJson:h,sortArr:y,foreignDB:w,addFields:_}=a[e];f||(f=u),n=t.pubfn.isNotNull(c)?c:"object"==typeof r?r[e]:r;let k,v="string"==typeof n?"$"+n:n,x="string"==typeof l?"$"+l:l,N="$$foreignKey"+baseDao.getForeignKeyName(n),$="foreignKey"+baseDao.getForeignKeyName(n);k="array"===d.toLowerCase()?[s.cond({if:s.isArray(N),then:s.in([x,N]),else:s.eq([x,N])})]:"array"===p.toLowerCase()?[s.cond({if:s.isArray(x),then:s.in([N,x]),else:s.eq([x,N])})]:[s.eq([x,N])];let D=s.pipeline().match(i.expr(s.and(k)));if(t.pubfn.isNotNull(b)&&(D=D.match(b)),t.pubfn.isNotNull(y)){let e={};for(let t in y){let n=y[t],i=n.name,a=n.type;a=null==a||""==a||"asc"==a?1:-1,e[i]=a}D=D.sort(e)}g&&(D=D.limit(g)),t.pubfn.isNotNull(w)&&(D=baseDao.addForeignDB({foreignDB:w,result:D})),t.pubfn.isNotNull(h)&&(h=baseDao.foreignDBToProject({fieldJson:h,foreignDB:w}),D=D.project(h)),t.pubfn.isNotNull(_)&&(D=D.addFields(_)),D=D.done();let T={};T[$]=v;let O={from:u,let:T,pipeline:D,as:f};o=o.lookup(O),(1===g&&!1!==m||!0===m)&&(o=o.unwind({path:"$"+f,preserveNullAndEmptyArrays:!0}))}return o},getForeignKeyName:function(e){return"string"==typeof e?e.replace(new RegExp("\\.","g"),"__"):"__vk__foreignKey1"},addWhereJson:function(e,t={},n="whereJson"){let{vk:i,db:a,_:r}=util$1,{formData:o,columns:s}=e;for(let e in s){let a,u=s[e],{key:l,mode:c,defaultValue:d,type:p="",lastWhereJson:f,auxiliary:g=!0,trim:m=!0,isNumber:b=!1}=u;if("lastWhereJson"===n&&!f)continue;if("lastWhereJson"!==n&&f)continue;let h=l;if(i.pubfn.isNotNull(u.fieldName)&&(h=u.fieldName),a=i.pubfn.isNotNull(u.value)?u.value:o[l],i.pubfn.isNull(a)&&i.pubfn.isNotNull(d)&&(a=d),i.pubfn.isNull(c)&&(c=["address","province","city","area"].indexOf(p)>-1?"address":"[object Array]"===Object.prototype.toString.call(a)&&a.length>=2?"[]":"="),i.pubfn.isNotNull(a))if("string"==typeof a&&m&&"function"==typeof a.trim&&(a=a.trim()),b&&!isNaN(a)&&(a=Number(a)),"custom"===c);else if("%%"===c)try{t[h]=new RegExp(a)}catch(e){}else if("%*"===c)try{t[h]=new RegExp("^"+a)}catch(e){}else if("*%"===c)try{t[h]=new RegExp(a+"$")}catch(e){}else if(">"===c)t[h]=t[h]?t[h].gt(a):r.gt(a);else if(">="===c)t[h]=t[h]?t[h].gte(a):r.gte(a);else if("<"===c)t[h]=t[h]?t[h].lt(a):r.lt(a);else if("<="===c)t[h]=t[h]?t[h].lte(a):r.lte(a);else if("in"===c)t[h]=r.in(a);else if("nin"===c)t[h]=r.nin(a);else if("!="===c)t[h]=r.neq(a);else if("[]"===c)t[h]=r.gte(a[0]).lte(a[1]);else if("[)"===c)t[h]=r.gte(a[0]).lt(a[1]);else if("(]"===c)t[h]=r.gt(a[0]).lte(a[1]);else if("()"===c)t[h]=r.gt(a[0]).lt(a[1]);else if("address"===c){let e={};a.province&&a.province.code&&(e["province.code"]=a.province.code),a.city&&a.city.code&&(e["city.code"]=a.city.code),a.area&&a.area.code&&(e["area.code"]=a.area.code),t[h]=e}else t[h]=g?"___empty-array___"===a?[]:"___empty-object___"===a?{}:"___non-existent___"===a?r.exists(!1):"___existent___"===a?r.exists(!0):a:a}return t},addLastWhereJson:function(e,t={}){return baseDao.addWhereJson(e,t,"lastWhereJson")},getTableData:async function(e){let{vk:t,db:n,_:i,config:a}=util$1,{db:r,dbName:o,data:s={},getCount:u=!0,getMain:l,whereJson:c,unwindJson:d,fieldJson:p,sortArr:f,treeProps:g,groupJson:m,foreignKey:b,foreignDB:h,lastWhereJson:y,lastSortArr:w,addFields:_}=e,{pageIndex:k,pageSize:v,pagination:x,sortRule:N,lastSortRule:$,formData:D,columns:T}=s;x&&(k=x.pageIndex,v=x.pageSize);let O,A={},I={},S=[],E={};if(t.pubfn.isNotNull(f))S=f;else{let e=t.pubfn.getData(a,"vk.db.unicloud.getTableData.sortArr");t.pubfn.isNotNull(e)?S=e:S.push({name:"_id",type:"desc"})}if(t.pubfn.isNotNull(N)&&(S=N),t.pubfn.isNotNull($)&&(w=$),I=baseDao.addWhereJson(s),E=baseDao.addLastWhereJson(s),t.pubfn.isNotNull(c)&&(c.operator&&c.operands&&["or","and"].indexOf(c.operator)>-1?I=i.and([I,c]):t.pubfn.objectAssign(I,c)),t.pubfn.isNotNull(p)&&t.pubfn.objectAssign(A,p),t.pubfn.isNotNull(y)&&t.pubfn.objectAssign(E,y),t.pubfn.isNotNull(I))for(let e in I)"object"==typeof I[e]&&I[e]&&"geoNear"===I[e].operator&&(O=!0);return t.pubfn.isNullAll(h,m,g,d,O)?await t.baseDao.select({db:r,dbName:o,getMain:l,getCount:u,pageIndex:k,pageSize:v,fieldJson:A,whereJson:I,sortArr:S}):await t.baseDao.selects({db:r,dbName:o,foreignKey:b,getMain:l,getCount:u,pageIndex:k,pageSize:v,whereJson:I,unwindJson:d,fieldJson:A,sortArr:S,treeProps:g,groupJson:m,foreignDB:h,lastWhereJson:E,lastSortArr:w,addFields:_})},startTransaction:async function(e){let{vk:t,db:n,_:i}=util$1;return await n.startTransaction()},rollbackTransaction:async function(e){let{db:t,msg:n="【异常】操作失败",tips:i="事务已回滚。",err:a={},code:r=-1}=e;console.error("transaction error",a);let o={code:r,msg:n,tips:i};await t.rollback();let s={message:a.message,stack:a.stack};try{s.body=JSON.parse(a.message),"object"==typeof s.body&&void 0!==s.body.code&&(s.body.msg,1)&&(o.msg=s.body.msg)}catch(e){}return console.error("transaction errJson",s),o.err=s,o},group:async function(e){let{vk:t,db:n,_:i}=util$1,{dbName:a,whereJson:r,groupJson:o,sortArr:s,pageIndex:u=1,pageSize:l=10,getCount:c=!1,lookupJson:d,db:p}=e,f=p||n;l<=0&&(l=999999999);i.aggregate;let g,m=f.collection(a).aggregate();if(t.pubfn.isNotNull(r)&&(m=m.match(r)),t.pubfn.isNotNull(o)&&(m=m.group(o)),t.pubfn.isNotNull(s)){let e={};for(let t in s){let n=s[t],i=n.name,a=n.type;a=null==a||""==a||"asc"==a?1:-1,e[i]=a}m=m.sort(e)}m=m.skip((u-1)*l).limit(l),t.pubfn.isNotNull(d)&&(g=d.returnObject,delete d.returnObject,m=m.lookup(d)),m=await m.end();let b,h=m.data;if(g)for(let e in h)h[e][d.as]=h[e][d.as][0];let y=!1;if(c){let e=f.collection(a).aggregate();t.pubfn.isNotNull(r)&&(e=e.match(r)),t.pubfn.isNotNull(o)&&(e=e.group(o));let n=await e.count("total").end();b=n.data[0]?n.data[0].total:0,u=l;return{hasMore:y,total:b,rows:h,code:0,key:1,pageIndex:u,pageSize:l}},tree:async function(e){let{vk:t,db:n,_:i}=util$1,{dbName:a,whereJson:r={},pageIndex:o=1,pageSize:s=10,getCount:u=!1,sortArr:l=[],fieldJson:c={},lastWhereJson:d,treeProps:p={}}=e;e.foreignDB||(e.foreignDB=[]);let{id:f="_id",parent_id:g="parent_id",children:m="children",level:b=10,limit:h=500}=p;if(b<1||b>20)throw new Error("msg:treeProps.level的范围必须在[1,20]");delete e.treeProps,e.whereJson||(e.whereJson={[g]:null}),e.foreignDB.unshift({dbName:a,localKey:f,foreignKey:g,as:m,limit:h,whereJson:p.whereJson,fieldJson:p.fieldJson||e.fieldJson,sortArr:p.sortArr,foreignDB:t.pubfn.copyObject(e.foreignDB)});let y=t.pubfn.copyObject(e.foreignDB);for(let n=1;n{"[object object]"===Object.prototype.toString.call(e.content)&&(e.content=JSON.stringify(e.content)),void 0===e.dataType&&(e.dataType="json"),"default"!=e.dataType&&""!==e.dataType||delete e.dataType,e.useContent&&(e.content=JSON.stringify(e.data)),e.method||(e.method="POST"),e.method=e.method.toUpperCase(),void 0===e.headers&&void 0!==e.header&&(e.headers=e.header);let t=await uniCloud.httpclient.request(e.url,e);return!e.needOriginalRes&&t&&t.data?t.data:t};var vk_request=request;const callFunction=async(e={})=>{let{name:t,url:n,data:i={},uniIdToken:a,clientInfo:r={},event:o={},uniCloud:s}=e;if(o&&o.originalParam&&o.originalParam.context){let e=o.originalParam.context;a=o.uniIdToken,r={...e,appId:e.APPID,platform:e.PLATFORM,locale:e.LOCALE,clientIP:e.CLIENTIP,os:e.OS,userAgent:e.CLIENTUA,deviceId:e.DEVICEID,uniIdToken:a}}let u,l=s||uniCloud;u=l.$context&&l.$context.FUNCTION_NAME?l.$context.FUNCTION_NAME:l.$options&&l.$options.context&&l.$options.context.FUNCTION_NAME?l.$options.context.FUNCTION_NAME:"router",a||r.uniIdToken&&(a=r.uniIdToken);let c={...i,vk_context:{appId:r.appId,platform:r.platform,locale:r.locale,clientIP:r.clientIP,os:r.os,userAgent:r.userAgent,deviceId:r.deviceId}};t||(t=u);let d=await l.callFunction({name:t,data:{$url:n,uniIdToken:a,data:c}});return d&&d.result};var vk_callFunction=callFunction,util$2={formValidateItem:function(e,t,n){let i={code:0,msg:"ok"},a=getData(e,t);void 0===a&&(a=e[t]);for(let e in n){let r=n[e];if(void 0===a&&r.required){i={type:"undefined",code:-1,msg:"字段:"+t+" 名称错误,请检查!",key:t,value:a};break}if(r.required&&(null==a||null==a||""===a||0==a.length)){i={type:"required",code:-1,msg:r.message,key:t,value:a};break}if(r.type&&void 0!==a){if(Object.prototype.toString.call(a).toLowerCase().toLowerCase()!==`[object ${r.type}]`.toLowerCase()){i={type:"type",code:-1,msg:r.message,key:t,value:a};break}}if(r.len&&a.length!=r.len){i={type:"len",code:-1,msg:r.message,key:t,value:a};break}if(r.min&&isNotNull(a))if("number"==r.type){if(ar.max){i={type:"max",code:-1,msg:r.message,key:t,value:a};break}}else if(a.length>r.max){i={type:"max",code:-1,msg:r.message,key:t,value:a};break}if("function"==typeof r.validator){let e,n,o=0,s=r.validator(r,a,(function(e){return n||(n=e),e}));if(n||(n=s),void 0!==n&&!0!==n&&(o=-1,"object"==typeof n?e||(e=n.message||n.msg,n.code&&(o=n.code)):"string"==typeof n&&(e||(e=n))),o){i={type:"validator",code:o,msg:e||r.message,key:t,value:a};break}}}return i}},formValidate=function(e={}){let t={code:0,msg:"ok"},{data:n,rules:i}=e;if(i)for(let e in i){let a=i[e];if(t=util$2.formValidateItem(n,e,a),0!=t.code)break}return t};function isNotNull(e){return-1===[void 0,null,""].indexOf(e)}function getData(e,t,n){let i=JSON.parse(JSON.stringify(e));t=t.replace(/\s+/g,"")+".";let a="";for(let e=0;e0&&(n=util$3.treeToArrayFn(l[o],t,n,l[a])),s&&delete l[o]}return n},util$3.arrayToTree=function(e,t){let n=deepClone(e),{id:i="_id",parent_id:a="parent_id",children:r="children",deleteParentId:o=!1,need_field:s}=t,u=[],l={};for(let e=0;e=10&&(e=Number(e)),"number"==typeof e)10==e.toString().length&&(e*=1e3),n=new Date(e);else if("object"==typeof e)n=new Date(e.getTime());else if("string"==typeof e){let i=t=util$4.getTargetTimezone(t),a=t>=0?"+":"";t>=0&&t<10?i="0"+t:t<0&&t>-10&&(i="-0"+-1*t);let r,o=e.split(" "),s=o[0]||"",u=o[1]||"";r=s.indexOf("-")>-1?s.split("-"):s.split("/");let l=u.split(":"),c={year:Number(r[0]),month:Number(r[1])||1,day:Number(r[2])||1,hour:Number(l[0])||0,minute:Number(l[1])||0,second:Number(l[2])||0};for(let e in c)c[e]>=0&&c[e]<10&&(c[e]="0"+c[e]);let d=`${c.year}-${c.month}-${c.day}T${c.hour}:${c.minute}:${c.second}${a}${i}:00`;n=new Date(d)}return n},getTimeByTimeZone:function(e,t){let n=util$4.getDateObject(e);t=util$4.getTargetTimezone(t);let i=60*n.getTimezoneOffset()*1e3+60*t*60*1e3,a=n.getTime()+i;return n=new Date(a),n},timeFormat:function(e,t="yyyy-MM-dd hh:mm:ss",n){try{if(!e)return"";n=util$4.getTargetTimezone(n);let i=util$4.getTimeByTimeZone(e,n),a={"M+":i.getMonth()+1,"d+":i.getDate(),"h+":i.getHours(),"m+":i.getMinutes(),"s+":i.getSeconds(),"q+":Math.floor((i.getMonth()+3)/3),S:i.getMilliseconds(),Z:`${n>=0?"+":"-"}${Math.abs(n).toString().padStart(2,"0")}:00`};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(i.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}catch(e){return time}},getDateInfo:function(e=new Date,t){let n=util$4.getTimeByTimeZone(e,t),i=n.getFullYear()+"",a=n.getMonth()+1<10?"0"+(n.getMonth()+1):n.getMonth()+1,r=n.getDate()<10?"0"+n.getDate():n.getDate(),o=n.getHours()<10?"0"+n.getHours():n.getHours(),s=n.getMinutes()<10?"0"+n.getMinutes():n.getMinutes(),u=n.getSeconds()<10?"0"+n.getSeconds():n.getSeconds(),l=n.getMilliseconds(),c=n.getDay(),d=Math.floor((n.getMonth()+3)/3);return{year:Number(i),month:Number(a),day:Number(r),hour:Number(o),minute:Number(s),second:Number(u),millisecond:Number(l),week:Number(c),quarter:Number(d)}},getCommonTime:function(e=new Date,t){let n={},i=util$4.getDateObject(e);t=util$4.getTargetTimezone(t);const a=60*i.getTimezoneOffset()*1e3+60*t*60*1e3,{year:r,month:o,day:s,hour:u,minute:l,second:c,millisecond:d,week:p,quarter:f}=util$4.getDateInfo(i,t);n.now={year:r,month:o,day:s,hour:u,minute:l,second:c,millisecond:d,week:p,quarter:f,date_str:util$4.timeFormat(i,"yyyy-MM-dd hh:mm:ss",t),date_day_str:util$4.timeFormat(i,"yyyy-MM-dd",t),date_month_str:util$4.timeFormat(i,"yyyy-MM",t)};let g=new Date(r,o,0).getDate(),m=new Date(r,12,0).getDate();n.todayStart=new Date(`${r}/${o}/${s}`).getTime()-a,n.today12End=new Date(`${r}/${o}/${s}`).getTime()+43199999-a,n.todayEnd=new Date(`${r}/${o}/${s}`).getTime()+86399999-a,n.monthStart=new Date(`${r}/${o}/1`).getTime()-a,n.monthEnd=new Date(`${r}/${o}/${g}`).getTime()+86399999-a,n.yearStart=new Date(r+"/1/1").getTime()-a,n.yearEnd=new Date(`${r}/12/${m}`).getTime()+86399999-a,n.hourStart=new Date(`${r}/${o}/${s} ${u}:00:00`).getTime()-a,n.hourEnd=new Date(`${r}/${o}/${s} ${u}:59:59`).getTime()-a;let b=r,h=o-1;0===h&&(h=12,b=r-1);let y=new Date(b,h,0).getDate();n.lastMonthStart=new Date(`${b}/${h}/1`).getTime()-a,n.lastMonthEnd=new Date(`${b}/${h}/${y}`).getTime()+86399999-a,n.yesterdayStart=n.todayStart-864e5,n.yesterday12End=n.today12End-864e5,n.yesterdayEnd=n.todayEnd-864e5;let w=util$4.getWeekOffsetStartAndEnd(0,i,t);n.weekStart=w.startTime,n.weekEnd=w.endTime,n.months=[],n.months[0]={startTime:n.monthStart,endTime:n.monthEnd,startTimeStr:util$4.timeFormat(n.monthStart,"yyyy-MM-dd hh:mm:ss",t),endTimeStr:util$4.timeFormat(n.monthEnd,"yyyy-MM-dd hh:mm:ss",t),monthStart:n.monthStart,monthEnd:n.monthEnd};for(let e=1;e<=12;e++){let i=new Date(r,e,0).getDate(),o=new Date(`${r}/${e}/1`).getTime()-a,s=new Date(`${r}/${e}/${i}`).getTime()+86399999-a;n.months[e]={startTime:o,endTime:s,startTimeStr:util$4.timeFormat(o,"yyyy-MM-dd hh:mm:ss",t),endTimeStr:util$4.timeFormat(s,"yyyy-MM-dd hh:mm:ss",t),monthStart:o,monthEnd:s}}n.days=[],n.days[0]={startTime:n.todayStart,endTime:n.todayEnd,startTimeStr:util$4.timeFormat(n.todayStart,"yyyy-MM-dd hh:mm:ss",t),endTimeStr:util$4.timeFormat(n.todayEnd,"yyyy-MM-dd hh:mm:ss",t)};for(let e=1;e<=g;e++){let i=n.monthStart+864e5*(e-1),{startTime:a,endTime:r}=util$4.getDayOffsetStartAndEnd(0,i,t);n.days[e]={startTime:a,endTime:r,startTimeStr:util$4.timeFormat(a,"yyyy-MM-dd hh:mm:ss",t),endTimeStr:util$4.timeFormat(r,"yyyy-MM-dd hh:mm:ss",t)}}for(let e in n)"number"==typeof n[e]&&13===n[e].toString().length&&(n[e+"Str"]=util$4.timeFormat(n[e],"yyyy-MM-dd hh:mm:ss",t));return n},getMonthStartAndEnd:function(e,t){t=util$4.getTargetTimezone(t);let n={startTime:null,endTime:null},{year:i,month:a}=e;if(i>0&&a>0){const e=60*(new Date).getTimezoneOffset()*1e3+60*t*60*1e3;let r=new Date(i,a,0).getDate();n.startTime=new Date(`${i}/${a}/1`).getTime()-e,n.endTime=new Date(`${i}/${a}/${r}`).getTime()+86399999-e}return n},getHourOffsetStartAndEnd:function(e=0,t=new Date,n){let i=util$4.getDateObject(t);n=util$4.getTargetTimezone(n);let a={};const r=60*i.getTimezoneOffset()*1e3+60*n*60*1e3;i=new Date(i.getTime()+36e5*e);let o=util$4.getDateInfo(i);return a.startTime=new Date(`${o.year}/${o.month}/${o.day} ${o.hour}:00:00`).getTime()-r,a.endTime=new Date(`${o.year}/${o.month}/${o.day} ${o.hour}:00:00`).getTime()+3599999-r,a},getDayOffsetStartAndEnd:function(e=0,t=new Date,n){let i=util$4.getDateObject(t);n=util$4.getTargetTimezone(n);let a={};const r=60*i.getTimezoneOffset()*1e3+60*n*60*1e3;i=new Date(i.getTime()+864e5*e);let o=util$4.getDateInfo(i);return a.startTime=new Date(`${o.year}/${o.month}/${o.day}`).getTime()-r,a.endTime=new Date(`${o.year}/${o.month}/${o.day}`).getTime()+86399999-r,a},getWeekOffsetStartAndEnd:function(e=0,t=new Date,n){let i={},a=util$4.getDateObject(t);n=util$4.getTargetTimezone(n);const r=60*a.getTimezoneOffset()*1e3+60*n*60*1e3;let o=0===a.getDay()?7:a.getDay();a.setDate(a.getDate()-o+1+7*e);let s=util$4.getDateInfo(a);a.setDate(a.getDate()+7);let u=util$4.getDateInfo(a);return i.startTime=new Date(`${s.year}/${s.month}/${s.day}`).getTime()-r,i.endTime=new Date(`${u.year}/${u.month}/${u.day}`).getTime()-1-r,i},getMonthOffsetStartAndEnd:function(e=0,t=new Date,n){let i={},a=util$4.getDateObject(t),r=util$4.getDateInfo(a),o=r.month+e,s=r.year;o>12?(s+=Math.floor(o/12),o=Math.abs(o)%12):o<=0&&(s=s-1-Math.floor(Math.abs(o)/12),o=12-Math.abs(o)%12);let u=new Date(s,o,0).getDate();return i.startTime=util$4.getDateObject(`${s}/${o}/01`,n).getTime(),i.endTime=util$4.getDateObject(`${s}/${o}/${u}`,n).getTime()+86399999,i},getQuarterOffsetStartAndEnd:function(e=0,t=new Date,n){let i={},a=util$4.getDateObject(t);a.setMonth(a.getMonth()+3*e),n=util$4.getTargetTimezone(n);const r=60*a.getTimezoneOffset()*1e3+60*n*60*1e3;let o=util$4.getDateInfo(a).month;[1,2,3].indexOf(o)>-1?o=1:[4,5,6].indexOf(o)>-1?o=4:[7,8,9].indexOf(o)>-1?o=7:[10,11,12].indexOf(o)>-1&&(o=10),a.setMonth(o-1);let s=util$4.getDateInfo(a);a.setMonth(a.getMonth()+3);let u=util$4.getDateInfo(a);return i.startTime=new Date(`${s.year}/${s.month}/1`).getTime()-r,i.endTime=new Date(`${u.year}/${u.month}/1`).getTime()-1-r,i},getYearOffsetStartAndEnd:function(e=0,t=new Date,n){let i={},a=util$4.getDateObject(t);n=util$4.getTargetTimezone(n);const r=60*a.getTimezoneOffset()*1e3+60*n*60*1e3;let o=util$4.getDateInfo(a).year+e;return i.startTime=new Date(o+"/1/1").getTime()-r,i.endTime=new Date(o+"/12/31").getTime()+86399999-r,i},getOffsetTime:function(e=new Date,t,n){let i=util$4.getDateObject(e),a=util$4.getDateInfo(i);n=util$4.getTargetTimezone(n);const r=60*i.getTimezoneOffset()*1e3+60*n*60*1e3;let o=t.year||t.y||0,s=t.month||t.m||0,u=t.day||t.d||0,l=t.hour||t.hours||t.hh||0,c=t.minute||t.minutes||t.mm||0,d=t.second||t.seconds||t.ss||0,{mode:p="after"}=t;"before"==p&&(o*=-1,s*=-1,u*=-1,l*=-1,c*=-1,d*=-1);let f={year:a.year+o,month:a.month+s,day:a.day+u,hour:a.hour+l,minute:a.minute+c,second:a.second+d};return i=new Date(f.year,f.month-1,f.day,f.hour,f.minute,f.second),i.getTime()-r},isLeapYear:function(e){if(void 0===e){let{now:t}=util$4.getCommonTime();e=t.year}else if("object"==typeof e){let{now:t}=util$4.getCommonTime(e);e=t.year}return e%4==0&&e%100!=0||e%400==0},isQingming:function(e=new Date){let{now:t}=util$4.getCommonTime(e),{year:n,month:i,day:a}=t,r=!1;return util$4.isLeapYear(n)||util$4.isLeapYear(n-1)?4===i&&4===a&&(r=!0):4===i&&5===a&&(r=!0),r},getFullTime:function(e,t=0,n){if(!e)return"";n=util$4.getTargetTimezone(n);let i=util$4.getDateObject(e);const a=60*i.getTimezoneOffset()*1e3+60*n*60*1e3,r=i.getTime()+a;i=new Date(r);let o=i.getFullYear()+"",s=i.getMonth()+1<10?"0"+(i.getMonth()+1):i.getMonth()+1,u=i.getDate()<10?"0"+i.getDate():i.getDate(),l=i.getHours()<10?"0"+i.getHours():i.getHours(),c=i.getMinutes()<10?"0"+i.getMinutes():i.getMinutes(),d=i.getSeconds()<10?"0"+i.getSeconds():i.getSeconds();return 2===t?{YYYY:Number(o),MM:Number(s),DD:Number(u),hh:Number(l),mm:Number(c),ss:Number(d),year:Number(o),month:Number(s),day:Number(u),hour:Number(l),minute:Number(c),second:Number(d)}:1===t?o+""+s+u+l+c+d:o+"-"+s+"-"+u+" "+l+":"+c+":"+d}},timeUtil=util$4,pubfn={};pubfn.formValidate=formValidate,pubfn.treeUtil=treeUtil,pubfn.timeUtil=timeUtil,pubfn.sleep=e=>new Promise(t=>setTimeout(t,e)),pubfn.timeFormat=pubfn.timeUtil.timeFormat,pubfn.getDateInfo=pubfn.timeUtil.getDateInfo,pubfn.getFullTime=pubfn.timeUtil.getFullTime,pubfn.getCommonTime=pubfn.timeUtil.getCommonTime,pubfn.getOffsetTime=pubfn.timeUtil.getOffsetTime,pubfn.getHourOffsetStartAndEnd=pubfn.timeUtil.getHourOffsetStartAndEnd,pubfn.getDayOffsetStartAndEnd=pubfn.timeUtil.getDayOffsetStartAndEnd,pubfn.getWeekOffsetStartAndEnd=pubfn.timeUtil.getWeekOffsetStartAndEnd,pubfn.getWeekStartAndEnd=pubfn.timeUtil.getWeekOffsetStartAndEnd,pubfn.getMonthOffsetStartAndEnd=pubfn.timeUtil.getMonthOffsetStartAndEnd,pubfn.getQuarterOffsetStartAndEnd=pubfn.timeUtil.getQuarterOffsetStartAndEnd,pubfn.getYearOffsetStartAndEnd=pubfn.timeUtil.getYearOffsetStartAndEnd,pubfn.getMonthStartAndEnd=pubfn.timeUtil.getMonthStartAndEnd,pubfn.validator=function(e){return function(t,n,i){let a=pubfn.test(n,e);return"function"!=typeof i||!a&&n?i(!1):void i()}},pubfn.test=function(e,t="",n=!1){let i;if(t=t.toLowerCase(),n&&(""===e||null==e))return!0;switch(t){case"mobile":return new RegExp(/^1[3|4|5|6|7|8|9][0-9]{9}$/).test(e);case"tel":return new RegExp(/^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/).test(e);case"card":return new RegExp(/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/).test(e);case"mobilecode":return new RegExp(/^[0-9]{6}$/).test(e);case"username":return new RegExp(/^[a-zA-Z]([-_a-zA-Z0-9]{2,31})$/).test(e);case"pwd":case"password":return new RegExp(/^([a-zA-Z0-9_@]){6,18}$/).test(e);case"paypwd":return new RegExp(/^[0-9]{6}$/).test(e);case"postal":return new RegExp(/[1-9]\d{5}(?!\d)/).test(e);case"qq":return new RegExp(/^[1-9][0-9]{4,9}$/).test(e);case"email":return new RegExp(/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/).test(e);case"money":return new RegExp(/^\d*(?:\.\d{0,2})?$/).test(e);case"url":return new RegExp(/^(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/).test(e);case"ip":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(e);case"date":return new RegExp(/^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/).test(e);case"time":return new RegExp(/^(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/).test(e);case"datetime":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(e);case"english+number":return new RegExp(/^[a-zA-Z0-9]+$/).test(e);case"english+number+_":return new RegExp(/^[a-zA-Z0-9_]+$/).test(e);case"english+number+_-":return new RegExp(/^[a-zA-Z0-9_-]+$/).test(e);case"version":return new RegExp(/^([1-9]\d|[1-9])(.([1-9]\d|\d)){2}$/).test(e);case"number":return new RegExp(/^[0-9]+$/).test(e);case"english":return new RegExp(/^[a-zA-Z]+$/).test(e);case"chinese":return new RegExp(/^[\u4e00-\u9fa5]+$/gi).test(e);case"lower":return new RegExp(/^[a-z]+$/).test(e);case"upper":return new RegExp(/^[A-Z]+$/).test(e);case"html":return new RegExp(/<("[^"]*"|'[^']*'|[^'">])*>/).test(e);case"image":return i=e.split("?")[0],new RegExp(/\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)$/).test(i);case"video":return i=e.split("?")[0],new RegExp(/\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8|3gp)$/).test(i);case"audio":return i=e.split("?")[0],new RegExp(/\.(mp3)$/).test(i);default:return!0}},pubfn.checkStr=pubfn.test,pubfn.priceFilter=function(e,t=""){return pubfn.isNull(e)?t:isNaN(e)?e:("string"==typeof e&&(e=parseFloat(e)),(e/100).toFixed(2))},pubfn.priceLeftFilter=function(e){let t="";return e&&(t=pubfn.priceFilter(e).split(".")[0]),t},pubfn.priceRightFilter=function(e){let t="";return e&&(t=pubfn.priceFilter(e).split(".")[1]),t},pubfn.percentageFilter=function(e,t=!0,n=""){return pubfn.isNull(e)?n:(isNaN(e)||("string"==typeof e&&(e=parseFloat(e)),e=parseFloat((100*e).toFixed(2)),t&&(e+="%")),e)},pubfn.discountFilter=function(e,t=!0,n=""){return pubfn.isNull(e)?n:isNaN(e)?e:("string"==typeof e&&(e=parseFloat(e)),(e=parseFloat((10*e).toFixed(2)))>10?"折扣不可以大于原价":10==e?"原价":0==e?"免费":e<0?"折扣不可以小于0":(t&&(e+=" 折"),e))},pubfn.objectDeleteInvalid=function(e){return Object.keys(e).forEach(t=>{void 0===e[t]&&delete e[t]}),e},pubfn.objectAssign=function(e,t,n=!0){return n&&pubfn.objectDeleteInvalid(t),Object.assign(e,t)},pubfn.copyObject=function(e){return void 0!==e?JSON.parse(JSON.stringify(e)):e},pubfn.deepClone=function(e){if([null,void 0,NaN,!1].includes(e))return e;if("object"!=typeof e&&"function"!=typeof e)return e;let t="[object Array]"===Object.prototype.toString.call(e)?[]:{};for(let n in e)e.hasOwnProperty(n)&&(t[n]="object"==typeof e[n]?pubfn.deepClone(e[n]):e[n]);return t},pubfn.formAssign=function(e,t){let n=pubfn.copyObject(e);return pubfn.objectAssign(n,t)},pubfn.arr_concat=function(e,t,n){n||(n="id"),e||(e=[]),t||(t=[]);let i=e.concat(t),a=[];if(-1!=n){let e=[];for(let t in i)-1==e.indexOf(i[t][n])&&(e.push(i[t][n]),a.push(i[t]))}else a=i;return a},pubfn.getData=function(e,t,n){let i=JSON.parse(JSON.stringify(e));t=t.replace(/\s+/g,"")+".";let a="";for(let e=0;ee[t])},pubfn.random=function(e,t,n){let i;if(pubfn.isNull(n))i=pubfn.randomFn(e,t);else{let a=0,r=1e5;do{a++,i=pubfn.randomFn(e,t)}while(n.indexOf(i)>-1&&ae){n+="0123456789"[i[e].charCodeAt()%10]}else n="0"+n;return n},pubfn.hidden=function(e="",t=0,n=0){let i=e.length-t-n,a="";for(let e=0;e-1&&(n=!0);return n},pubfn.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},pubfn.isObject=function(e){return"[object Object]"===Object.prototype.toString.call(e)},pubfn.calcFreights=function(e,t){return pubfn.calcFreightDetail(e,t).total_amount},pubfn.calcFreightDetail=function(e,t){let{first_weight:n,first_weight_price:i,continuous_weight:a,continuous_weight_price:r,max_weight:o}=e;o||(o=1e9);let s=t,u=0,l=o,c=!1,d=0;for(;t>0;)c?(d++,t-=a,l-=a):(c=!0,u++,l=o,t-=n,l-=n),l<=0&&(c=!1);let p=i*u+r*d;return{weight:s,first_weight:n,first_weight_price:i,first_weight_count:u,continuous_weight:a,continuous_weight_price:r,continuous_weight_count:d,first_weight_amount:u*i,continuous_weight_amount:r*d,total_amount:p,formula:`${i} * ${u} + ${r} * ${d} = ${p}`}},pubfn.getNewObject=function(e,t){let n=pubfn.copyObject(e),i={};if(t&&t.length>0)for(let e in t){let a=t[e];pubfn.isNotNull(n[a])&&(i[a]=n[a])}else i=n;return i},pubfn.deleteObjectKeys=function(e,t=[]){var n={};if(e)for(let i in e)-1==t.indexOf(i)&&(n[i]=e[i]);return n},pubfn.arrayToTree=pubfn.treeUtil.arrayToTree,pubfn.treeToArray=pubfn.treeUtil.treeToArray,pubfn.wildcardTestOne=function(e,t){if(!t)return!1;let n=t.replace(new RegExp("\\*"),"(.*)"),i=0!==t.indexOf("*")?"^":"",a="*"!==t[t.length-1]?"$":"";return new RegExp(i+n+a).test(e)},pubfn.wildcardTest=function(e,t){let n=0;if("string"==typeof t)pubfn.wildcardTestOne(e,t)&&n++;else if("object"==typeof t)for(let i=0;i0?l=r+"天":o>0?l=o+"小时":s>0?l=s+"分钟":u>0&&(l=u+"秒"),l+=t},pubfn.dateDiff2=function(e,t="1秒"){if(!e)return"";"string"!=typeof e||isNaN(e)||(e=Number(e)),"number"==typeof e&&(10==e.toString().length&&(e*=1e3),e=new Date(e),e=pubfn.timeFormat(e)),"string"==typeof e&&(e=e=e.replace("T"," "),e=new Date(e.replace(/-/g,"/")));var n=new Date,i=864e5,a=36e5,r=e.getTime()-n.getTime(),o=Math.floor(r/i),s=Math.floor(r%i/a),u=Math.floor(r%i%a/6e4),l=Math.round(r%i%a%6e4/1e3),c=t;return o>0?c=o+"天":s>0?c=s+"小时":u>0?c=u+"分钟":l>0&&(c=l+"秒"),c},pubfn.numStr=function(e){"string"==typeof e&&(e=parseFloat(e));var t=e;if(e<1e3)t=e;else if(e<1e4){t=Math.floor(e/100)/10+"千"}else if(e<1e6){t=Math.floor(e/1e3)/10+"万"}else if(e<1e7){t=Math.floor(e/1e6)+"百万"}else if(e<1e8){t=Math.floor(e/1e7)+"千万"}else if(e>=1e8){t=Math.floor(e/1e7)/10+"亿"}return t},pubfn.calcSize=function(e=0,t,n,i=2,a="auto"){let r=0,o="";if((e=parseFloat(e))parseObjectKeys(e,t)))}return e}pubfn.snake2camel=function(e){return e.replace(isSnakeCase,(e,t)=>t?t.toUpperCase():"")},pubfn.camel2snake=function(e){return e.replace(isCamelCase,e=>"_"+e.toLowerCase())},pubfn.snake2camelJson=function(e){return parseObjectKeys(e,"snake2camel")},pubfn.camel2snakeJson=function(e){return parseObjectKeys(e,"camel2snake")},pubfn.string2Number=function(e,t={}){switch(Object.prototype.toString.call(e).slice(8,-1).toLowerCase()){case"string":if(e&&!isNaN(e)){let{mobile:n=!0,idCard:i=!0,startFrom0:a=!0,maxLength:r=14}=t;return e.length>r||(n&&pubfn.test(e,"mobile")||i&&pubfn.test(e,"card")||a&&e.length>1&&0===e.indexOf("0")&&1!==e.indexOf("."))?e:Number(e)}return e;case"object":const n=Object.keys(e);for(let t=0;t-1&&(t=e.substring(n+1)),t},pubfn.checkFileSuffix=function(e,t){let n=!1,i=pubfn.getFileSuffix(e);for(let e=0;e-1){n=!0;break}return n},pubfn.splitArray=function(e,t){let n=[];for(let i=0;i-1){var o=a.indexOf('"',r),s=a.substring(r,o);if(o>r){var u=a.indexOf("---",o),l=a.substring(o+1,u).trim();n[s]=l}}}return n},pubfn.getPlatform=function(e){return"web"===e?e="h5":"app"===e&&(e="app-plus"),e},pubfn.getClientUAByContext=function(e={}){return e.ua||e.CLIENTUA},pubfn.getPlatformForUniId=function(e={}){let t=e.PLATFORM;if(t=pubfn.getPlatform(t),"h5"===t){pubfn.getClientUAByContext(e).toLowerCase().indexOf("micromessenger")>-1&&(t="h5-weixin")}return t},pubfn.getUniCloudContext=function(){let e;try{e=uniCloud.context}catch(e){}return e},pubfn.getUniCloudFunctionName=function(){let e;try{let t=pubfn.getUniCloudContext();e=t.FUNCTION_NAME||t.function_name}catch(e){}return e},pubfn.getUniCloudProvider=function(){let e;try{e=uniCloud.context.SPACEINFO.provider}catch(e){}return e},pubfn.getUniCloudRequestId=function(){let e;try{e=pubfn.getUniCloudContext().requestId}catch(e){}return e},pubfn.getUniIdConfig=function(e={},t,n){const i=e.uni;let a;if(pubfn.isArray(i)){let e=uniCloud.env&&uniCloud.env.APPID?uniCloud.env.APPID:uniCloud.$context.APPID;a=pubfn.getListItem(i,"dcloudAppid",e),pubfn.isNull(a)&&(a=pubfn.getListItem(i,"isDefaultConfig",!0))}else a=i;if(pubfn.isNotNull(t)){let e=pubfn.getData(a,t);return pubfn.isNull(e)?n:e}return a},pubfn.batchRun=async function(e){let{main:t,data:n=[],concurrency:i=50}=e;if(pubfn.isArray(t))return pubfn.batchRun2(e);let a=n.length,r=[];if(0==a)return{stack:r,total:a};if(1===i){for(let e=0;e=a)break;let u=t(n[s],s);e.push(u)}try{await Promise.all(e).then(e=>{r=r.concat(e)})}catch(e){console.error(e)}}return{stack:r,total:a}}},pubfn.batchRun2=async function(e){let{main:t,concurrency:n=100}=e,i=t.length,a=[];if(0==i)return{stack:a,total:i};if(1===n){for(let e=0;e=i)break;let s=(0,t[o])();e.push(s)}try{await Promise.all(e).then(e=>{a=a.concat(e)})}catch(e){console.error(e)}}return{stack:a,total:i}}},pubfn.randomAsync=async function(e,t,n,i=500){let a;if("function"==typeof n){let r=0;do{r++,a=pubfn.randomFn(e,t)}while(!await n(a)&&r0?(new Date).getTime()+1e3*n:0};dataCache[e]=i},util$5.del=function(e){delete dataCache[e]},util$5.clear=function(e){if(e)for(let t in dataCache)0==t.indexOf(e)&&delete dataCache[t];else dataCache={}},util$5.isExpired=function(e){let t=!0,n=dataCache[e];return n&&(0==n.expired||n.expired>(new Date).getTime())&&(t=!1),t},util$5.getAll=function(e){let t={};if(e)for(let n in dataCache)0==n.indexOf(e)&&(t[e]=dataCache[e]);else t=dataCache;for(let e in t)util$5.isExpired(e)&&(delete t[e],delete dataCache[e]);return t};var temporaryCache=util$5,globalDataCache={},util$6={},globalDataDao={};globalDataCache.init=function(e){globalDataDao=(util$6=e).vk.system.globalDataDao},globalDataCache.get=async function(e,t=0,n,i=!0){return"function"==typeof n?globalDataCache.autoGet(e,t,n,i):globalDataCache._get(e)},globalDataCache.autoGet=async function(e,t=0,n,i=!0){let a,{vk:r}=util$6;try{a=await globalDataCache._get(e),r.pubfn.isNull(a)&&"function"==typeof n&&(a=await n(),void 0!==a&&i&&await r.globalDataCache.set(e,a,t))}catch(e){return}return a},globalDataCache._get=async function(e){let t;try{let n=await globalDataDao.find(e);if(n){let{value:i,expired_at:a}=n;globalDataCache.isExpired(n)?await globalDataCache.del(e):t=i}}catch(e){return}return t},globalDataCache.set=async function(e,t,n=0,i){let a;e&&void 0!==e.key&&void 0!==e.value?(a=e.key,t=e.value,n=e.second,i=e.comment):a=e;let r={code:0,msg:"ok"};try{if(!a)return{code:-1,msg:"key值不能为空"};let e=n>0?(new Date).getTime()+1e3*n:0;r=await globalDataDao.set({key:a,value:t,expired_at:e,comment:i})}catch(e){return console.error(e),{code:-1,msg:"异常"}}return r},globalDataCache.del=async function(e){await globalDataDao.del(e)},globalDataCache.clear=async function(e){if(e)return await globalDataDao.deleteByWhere({key:new RegExp("^"+e)})},globalDataCache.list=async function(e){return await globalDataDao.list(e)},globalDataCache.count=async function(e){return await globalDataDao.count(e)},globalDataCache.isExpired=function(e){let t=!0;return e&&(!e.expired_at||0==e.expired_at||e.expired_at>(new Date).getTime())&&(t=!1),t},globalDataCache.inc=async function(e,t=1,n=0){let i;e&&void 0!==e.key&&void 0!==e.value?(i=e.key,t=e.value,n=e.second):i=e;let a={code:0,msg:"ok"};try{if(!i)return{code:-1,msg:"key值不能为空"};let e=n>0?(new Date).getTime()+1e3*n:0;a=await globalDataDao.inc({key:i,value:t,expired_at:e})}catch(e){return{code:-1,msg:"异常",err:e}}return a},globalDataCache.uniqueAdd=async function(e,t=1,n=5){let{vk:i}=util$6,a={code:0,msg:"ok"};try{if(!e)return{code:-1,msg:"key值不能为空"};let r=n>0?(new Date).getTime()+1e3*n:0;await i.globalDataCache.deleteExpired(e);a.id=await globalDataDao.add({key:e,value:t,expired_at:r})}catch(e){return console.error(e),{code:-1,msg:"异常"}}return a},globalDataCache.deleteExpired=async function(e){await globalDataDao.deleteExpired(e)};var globalDataCache_1=globalDataCache,util$7={aes:{}};const aesKey="5fb2cd73c7b53918728417c50762e6d45fb2cd73c7b53918728417c50762e6d4",AESMODE={AES192:"aes192",AES256ECB:"aes-256-ecb"};util$7.aes.MODE=AESMODE,util$7.aes.encrypt=function(e){let{data:t,key:n,mode:i=AESMODE.AES192}=e,a=uniCloud.vk,{crypto:r,config:o}=a.getUnicloud();if(n||(n=a.pubfn.getData(o.vk,"crypto.aes",aesKey)),"object"==typeof t&&(t=JSON.stringify(t)),i===AESMODE.AES256ECB)return encryptUseAes256Ecb(t,n);if(i===AESMODE.AES192)return encryptUseAes192(t,n);throw new Error(`msg:不支持 ${i} 加密算法`)},util$7.aes.decrypt=function(e){let{data:t,key:n,mode:i=AESMODE.AES192}=e,a=uniCloud.vk,{crypto:r,config:o}=a.getUnicloud();if(a.pubfn.isNull(t))throw new Error("msg:待解密原文不能为空");if(n||(n=a.pubfn.getData(o.vk,"crypto.aes",aesKey)),i===AESMODE.AES256ECB)return decryptUseAes256Ecb(t,n);if(i===AESMODE.AES192)return decryptUseAes192(t,n);throw new Error(`msg:不支持 ${i} 加密算法`)};var crypto=util$7;function encryptUseAes192(e,t){let n=uniCloud.vk,{crypto:i}=n.getUnicloud();const a=i.createCipher(AESMODE.AES192,t);let r=a.update(e,"utf8","hex");return r+=a.final("hex"),r}function decryptUseAes192(e,t){let n,i=uniCloud.vk,{crypto:a}=i.getUnicloud();try{const i=a.createDecipher(AESMODE.AES192,t);n=i.update(e,"hex","utf8"),n+=i.final("utf8");try{n=JSON.parse(n)}catch(e){}}catch(e){throw"msg:解密失败"}return n}function encryptUseAes256Ecb(e,t){let n=uniCloud.vk,{crypto:i}=n.getUnicloud(),a=Buffer.from(e),r=t;r.length>32&&(r=r.substring(0,32)),r=Buffer.from(r);const o=i.createCipheriv(AESMODE.AES256ECB,r,"");o.setAutoPadding(!1);const s=16-a.length%16,u=Buffer.alloc(s,s);a=Buffer.concat([a,u]);let l=o.update(a,null,"base64");return l+=o.final("base64"),l}function decryptUseAes256Ecb(e,t){let n=uniCloud.vk,{crypto:i}=n.getUnicloud(),a=t;a.length>32&&(a=a.substring(0,32)),a=Buffer.from(a);try{const t=i.createDecipheriv(AESMODE.AES256ECB,a,"");t.setAutoPadding(!1);let n=t.update(e,"base64");n+=t.final();const r=n.charCodeAt(n.length-1);n=n.slice(0,n.length-r);try{n=JSON.parse(n)}catch(e){}return n}catch(e){throw"解密失败"}}var alipay={},ALIPAY_ALGORITHM_MAPPING={RSA:"RSA-SHA1",RSA2:"RSA-SHA256"};alipay.sign=function(e,t,n){let i=JSON.parse(JSON.stringify(t)),a=Object.assign({method:e,app_id:n.appid,charset:n.charset||"utf-8",version:n.version||"1.0",sign_type:n.signType||"RSA2"},i);n.appCertSn&&n.alipayRootCertSn&&(a=Object.assign({app_cert_sn:n.appCertSn,alipay_root_cert_sn:n.alipayRootCertSn},a));const r=i.bizContent||i.biz_content;r&&(a.biz_content=JSON.stringify(r));const o=alipay.sortObj(a);let s=alipay.objectToUrl(o);const u="PKCS8"===(n.keyType||"PKCS8")?"PRIVATE KEY":"RSA PRIVATE KEY";let l=alipay.formatKey(n.privateKey,u);const c=crypto$1.createSign(ALIPAY_ALGORITHM_MAPPING[a.sign_type]).update(s,"utf8").sign(l,"base64");return Object.assign(o,{sign:c})},alipay.formatUrl=function(e,t="https://openapi.alipay.com/gateway.do"){let n=t;const i=["app_id","method","format","charset","sign_type","sign","timestamp","version","notify_url","return_url","auth_token","app_auth_token","ws_service_url"];for(const t in e)if(i.indexOf(t)>-1){const i=encodeURIComponent(e[t]);n=`${n}${n.includes("?")?"&":"?"}${t}=${i}`,delete e[t]}return{execParams:e,url:n}},alipay.sortObj=function(e){new Array;let t=Object.keys(e).sort(),n={};for(let i in t)n[t[i]]=e[t[i]];return n},alipay.objectToUrl=function(e){let t="";for(let n in e)e[n]&&(t+=`&${n}=${e[n]}`);return t&&(t=t.substring(1)),t},alipay.formatKey=function(e,t){return`-----BEGIN ${t}-----\n${e}\n-----END ${t}-----`},alipay.getRequestRes=function(e,t){return e[t.replace(new RegExp("\\.","g"),"_")+"_response"]||e.error_response};var util$8=alipay,alipay$1={},util$9={};const serviceUrl="https://openapi.alipay.com/gateway.do",configKey="mp-alipay.oauth.alipay";function returnRes(e){return e.code=e.sub_code||e.code||0,e.msg=e.sub_msg||e.msg||"",e}alipay$1.init=function(e){util$9=e},alipay$1.getConfig=function(){let{vk:e,config:t}=util$9;return e.pubfn.getUniIdConfig(t)},alipay$1.request=async function(e={}){let{vk:t}=util$9,{method:n,data:i={},successText:a}=e,r=alipay$1.auth.getAppidInfo(e),o=Date.now(),s={timestamp:t.pubfn.timeFormat(o,"yyyy-MM-dd hh:mm:ss"),...i};const u=util$8.sign(n,s,r),{url:l,execParams:c}=util$8.formatUrl(u,serviceUrl);let d=await t.request({url:l,method:"POST",data:c}),p=await util$8.getRequestRes(d,n);return p.code&&"10000"!==p.code||(p.code=0,p.msg=a),p=returnRes(p),p},alipay$1.auth={},alipay$1.auth.getAppidInfo=function(e={}){let{appid:t,privateKey:n}=e,{vk:i,config:a}=util$9;const r=alipay$1.getConfig();if(t){if(!n){let e=i.pubfn.getData(a,"vk.oauth.alipay.list")||[],r=i.pubfn.getListItem(e,"appid",t)||{};if(t=r.appid,n=r.privateKey,i.pubfn.isNullOne(t,n))throw console.log("config",e),new Error(`你使用了多小程序登录模式,但未找到${t}对应的 privateKey 请先在 uni-config-center/vk-unicloud/index.js 中配置支付宝小程序(vk.oauth.alipay.list)的appid和privateKey`)}}else{let e=i.pubfn.getData(r,configKey)||{};if(t=e.appid,n=e.privateKey,i.pubfn.isNullOne(t,n))throw console.log("config",r),new Error(`请先在 uni-config-center/uni-id/config.json 中配置支付宝小程序(${configKey})的appid和privateKey`)}return{appid:t,privateKey:n}},alipay$1.auth.code2Session=async function(e={}){let{vk:t,uniID:n}=util$9,{platform:i,needKey:a=!1}=e;i||(i="mp-alipay");let r=await alipay$1.auth.code2SessionMp(e);try{let e=t.crypto.aes.encrypt({data:r});r.encryptedKey=e}catch(e){}return a||(delete r.sessionKey,delete r.accessToken,delete r.refreshToken),delete r.privateKey,r.platform=i,r.openid=r.userId,r},alipay$1.auth.code2SessionMp=async function(e={}){let{appid:t}=alipay$1.auth.getAppidInfo(e),n=e.code||e.js_code,{vk:i}=util$9,a=await alipay$1.request({method:"alipay.system.oauth.token",data:{code:n,grant_type:"authorization_code"}});return{...i.pubfn.snake2camelJson(a),appid:t,code:0,msg:"ok"}},alipay$1.security={},alipay$1.security.msgSecCheck=async function(e={}){return{code:-1,msg:"支付宝未提供此API"}},alipay$1.security.imgSecCheck=async function(e={}){return{code:-1,msg:"支付宝未提供此API"}},alipay$1.acode={},alipay$1.acode.getMiniCode=async function(e={}){let{page:t,scene:n="miniCode=1",line_color:i}=e,a={url_param:t,query_param:n,describe:"推广",color:i};return await alipay$1.request({method:"alipay.open.app.qrcode.create",data:{biz_content:a},successText:"生成成功"})},alipay$1.subscribeMessage={},alipay$1.subscribeMessage.send=async function(e={}){let{touser:t,form_id:n,template_id:i,page:a,data:r}=e,{appid:o}=alipay$1.auth.getAppidInfo(e),s={to_user_id:t,form_id:n,user_template_id:i,page:a,data:r};return await alipay$1.request({method:"alipay.open.app.mini.templatemessage.send",data:{biz_content:s},successText:"发送成功"})};var alipay_1=alipay$1,baidu={},util$a={};baidu.init=function(e){util$a=e},baidu.open={},baidu.open.auth={},baidu.open.auth.getAppidInfo=function(e={}){let{appid:t,appsecret:n}=e,{vk:i,config:a}=util$a;if(!t){let e=i.pubfn.getData(a,"vk.service.openapi.baidu")||{};t=e.appid,n=e.appsecret}if(i.pubfn.isNullOne(t,n))throw new Error("请在uniCloud/cloudfunctions/common/uni-config-center/vk-unicloud/index.js中配置并检查百度开放平台的appid和appsecret是否正确,参数路径:vk.service.openapi.baidu");return{appid:t,appsecret:n}},baidu.open.auth.getAccessTokenFn=async function(e={}){let{appid:t,appsecret:n}=baidu.open.auth.getAppidInfo(e),{vk:i,config:a}=util$a,r=await i.request({url:`https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${t}&client_secret=${n}`,method:"GET"});return r.error_code?(console.error("getAccessToken失败:",r),{code:r.error_code,msg:r.error_msg,err:r}):{...r,code:0,msg:"ok"}},baidu.open.auth.getAccessToken=async function(e={}){let t,{appid:n,appsecret:i}=baidu.open.auth.getAppidInfo(e),{cache:a=!0}=e,{vk:r}=util$a,o="openapi-baidu-"+n;if(a&&(t=await r.globalDataCache.get(o)),r.pubfn.isNull(t)){let n=await baidu.open.auth.getAccessTokenFn(e);0===n.code&&(t=n.access_token,await r.globalDataCache.set(o,t,n.expires_in-3600),await r.globalDataCache.deleteExpired())}return t},baidu.open.ocr={},baidu.open.ocr.business_license=async function(e={}){let{image:t,url:n}=e;return await baidu.open.request({...e,action:"ocr/v1/business_license",actionVersion:"2.0",data:{image:t,url:n}})},baidu.open.ocr.idcard=async function(e={}){let{image:t,url:n,id_card_side:i,detect_risk:a,detect_photo:r}=e;return await baidu.open.request({...e,action:"ocr/v1/idcard",actionVersion:"2.0",data:{image:t,url:n,id_card_side:i,detect_risk:a,detect_photo:r}})},baidu.open.request=async function(e={}){let{vk:t}=util$a,n=await baidu.open.auth.getAccessToken(e);if(!n)return{code:-1,msg:"获取access_token失败,请检查vk-unicloud配置下vk.service.openapi.baidu配置的appid和appsecret是否正确"};let{action:i,actionVersion:a="2.0",header:r={"content-type":"application/x-www-form-urlencoded"},data:o}=e,s=await t.request({url:`https://aip.baidubce.com/rest/${a}/${i}?access_token=${n}`,method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},data:o});return s.error_code?{code:s.error_code,msg:s.error_msg,err:s}:{...s,code:0,msg:"ok"}};var baidu_1=baidu,douyin={},util$b={};const serviceUrl$1="https://developer.toutiao.com",configKey$1="mp-toutiao.oauth.toutiao";function returnRes$1(e){return e.code=e.err_no||0,e.msg=e.err_tips||"",e}douyin.init=function(e){util$b=e},douyin.getConfig=function(){let{vk:e,config:t}=util$b;return e.pubfn.getUniIdConfig(t)},douyin.request=async function(e={}){let{vk:t}=util$b,{url:n,data:i={}}=e,{appid:a,appsecret:r}=douyin.auth.getAppidInfo(e);if(!0===i.access_token){let t=await douyin.auth.getAccessToken(e);if(!t)return{code:-1,msg:`获取access_token失败,请检查uni-id配置${configKey$1}配置下的appid和appsecret是否正确`};i.access_token=t}-1===n.indexOf("http")&&(n=`${serviceUrl$1}/${n}`);let o=await t.request({contentType:"json",dataType:"json",...e,url:n});return o=returnRes$1(o),o},douyin.auth={},douyin.auth.getAppidInfo=function(e={}){let{appid:t,appsecret:n}=e,{vk:i,config:a}=util$b;const r=douyin.getConfig();if(t){if(!n){let e=i.pubfn.getData(a,"vk.oauth.toutiao.list")||[],r=i.pubfn.getListItem(e,"appid",t)||{};if(t=r.appid,n=r.appsecret,i.pubfn.isNullOne(t,n))throw console.log("config",e),new Error(`你使用了多小程序登录模式,但未找到${t}对应的 appsecret 请先在 uni-config-center/vk-unicloud/index.js 中配置抖音小程序(vk.oauth.toutiao.list)的appid和appsecret`)}}else{let e=i.pubfn.getData(r,configKey$1)||{};if(t=e.appid,n=e.appsecret,i.pubfn.isNullOne(t,n))throw console.log("config",r),new Error(`请先在 uni-config-center/uni-id/config.json 中配置抖音小程序(${configKey$1})的appid和appsecret`)}return{appid:t,appsecret:n}},douyin.auth.getAccessTokenFn=async function(e={}){let{appid:t,appsecret:n}=douyin.auth.getAppidInfo(e),{vk:i,config:a}=util$b,r=await i.request({url:serviceUrl$1+"/api/apps/v2/token",method:"POST",data:{appid:t,secret:n,grant_type:"client_credential"},contentType:"json",dataType:"json"});return r.err_no?(console.error("getAccessToken失败:",r),{code:r.err_no,msg:r.err_tips,err:r}):{code:0,msg:"ok",access_token:r.data.access_token,expires_in:r.data.expires_in}},douyin.auth.getAccessToken=async function(e={}){let t,{appid:n,appsecret:i}=douyin.auth.getAppidInfo(e),{cache:a=!0}=e,{vk:r}=util$b,o="mp-toutiao-access_token-"+n;if(a&&(t=await r.globalDataCache.get(o)),r.pubfn.isNull(t)){let n=await douyin.auth.getAccessTokenFn(e);0===n.code&&(t=n.access_token,await r.globalDataCache.set(o,t,240),await r.globalDataCache.deleteExpired())}return t},douyin.auth.code2Session=async function(e={}){let{vk:t,uniID:n}=util$b,{platform:i,needKey:a=!1}=e;i||(i="mp-toutiao");let r=await douyin.auth.code2SessionMp(e);try{let e=t.crypto.aes.encrypt({data:r});r.encryptedKey=e}catch(e){}return a||(delete r.sessionKey,delete r.accessToken,delete r.refreshToken),delete r.appsecret,r.platform=i,r},douyin.auth.code2SessionMp=async function(e={}){let{appid:t,appsecret:n}=douyin.auth.getAppidInfo(e),i=e.code||e.js_code,a=e.anonymousCode,{vk:r}=util$b,o=await douyin.request({url:"api/apps/v2/jscode2session",method:"POST",data:{appid:t,secret:n,code:i,anonymous_code:a}});return o.code?(40018!==o.code&&40019!==o.code||(o.msg="无效code,请重新获取"),o):{...r.pubfn.snake2camelJson(o.data),appid:t,appsecret:n,code:0,msg:"ok"}},douyin.security={},douyin.security.msgSecCheck=async function(e={}){let{content:t,tasks:n}=e,{appid:i,appsecret:a}=douyin.auth.getAppidInfo(e),r=await douyin.auth.getAccessToken(e);if(!r)return{code:-1,msg:`获取access_token失败,请检查uni-id配置${configKey$1}配置下的appid和appsecret是否正确`};n||(n=[{content:t}]);let o=await douyin.request({url:"api/v2/tags/text/antidirt",method:"POST",header:{"X-Token":r},data:{tasks:n}});try{let e,t;o.data.map((n,i)=>{n.predicts.map((n,a)=>{n.hit&&(e||(e=!0,t=i))})}),e?(o.taskIndex=t,o.code=87014):o.code=0}catch(e){}return 40001===o.code&&(o.msg="access_token错误"),87014===o.code&&(o.msg="内容含有违法违规内容,请检查!"),0===o.code&&(o.msg="ok"),o},douyin.security.imgSecCheck=async function(e={}){let{image:t,access_token:n=!0}=e,i=e.base64||e.image_data,{appid:a,appsecret:r}=douyin.auth.getAppidInfo(e);if(i){let e=i.indexOf("base64,");e>-1&&(i=i.substring(e+"base64,".length))}let o=await douyin.request({url:"api/apps/censor/image",method:"POST",data:{app_id:a,access_token:n,image:t,image_data:i}});try{let e;o.predicts.map((t,n)=>{t.hit&&(e=!0)}),o.code=e?87014:0}catch(e){}return 87014===o.code&&(o.msg="内容含有违法违规内容,请检查!"),0===o.code&&(o.msg="ok"),o},douyin.acode={},douyin.acode.getMiniCode=async function(e={}){let{path:t,appname:n="douyin",width:i,line_color:a,background:r,set_icon:o,access_token:s=!0}=e,{appid:u,appsecret:l}=douyin.auth.getAppidInfo(e),c=await douyin.request({url:"api/apps/qrcode",method:"POST",data:{access_token:s,appname:n,path:t,width:i,line_color:a,background:r,set_icon:o},dataType:"default",useContent:!0,header:{"content-type":"application/json;charset=utf8"}});if(c.length<500){let e=c.toString();try{return e=JSON.parse(e),{code:e.errcode,msg:e.errmsg}}catch(e){}return{code:-1,err:err}}return c},douyin.subscribeMessage={},douyin.subscribeMessage.send=async function(e={}){let{touser:t,template_id:n,page:i,data:a,access_token:r=!0}=e,{appid:o,appsecret:s}=douyin.auth.getAppidInfo(e);return await douyin.request({url:"api/apps/subscribe_notification/developer/v1/notify",method:"POST",data:{access_token:r,app_id:o,tpl_id:n,open_id:t,data:a,page:i}})};var douyin_1=douyin,qq={},util$c={};const serviceUrl$2="https://api.q.qq.com",configKey$2="mp-qq.oauth.qq";function returnRes$2(e){return e.code=e.errcode||e.errCode||0,e.msg=e.errmsg||e.errMsg||"",e}qq.init=function(e){util$c=e},qq.getConfig=function(){let{vk:e,config:t}=util$c;return e.pubfn.getUniIdConfig(t)},qq.request=async function(e={}){let{vk:t}=util$c,{url:n,method:i,data:a={}}=e;if(-1===n.indexOf("http")&&(n=`${serviceUrl$2}/${n}`),!0===a.access_token){delete a.access_token;let t=await qq.auth.getAccessToken(e);if(!t)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-qq配置的appid和appsecret是否正确"};n+=-1===n.indexOf("?")?"?":"&",n+="access_token="+t}let r=await t.request({...e,url:n});return r=returnRes$2(r),r},qq.auth={},qq.auth.getAppidInfo=function(e={}){let{appid:t,appsecret:n}=e,{vk:i,config:a}=util$c;const r=qq.getConfig();if(t){if(!n){let e=i.pubfn.getData(a,"vk.oauth.qq.list")||[],r=i.pubfn.getListItem(e,"appid",t)||{};if(t=r.appid,n=r.appsecret,i.pubfn.isNullOne(t,n))throw console.log("config",e),new Error(`你使用了多小程序登录模式,但未找到${t}对应的 appsecret 请先在 uni-config-center/vk-unicloud/index.js 中配置QQ小程序(vk.oauth.qq.list)的appid和appsecret`)}}else{let e=i.pubfn.getData(r,configKey$2)||{};if(t=e.appid,n=e.appsecret,i.pubfn.isNullOne(t,n))throw console.log("config",r),new Error("请先在 uni-config-center/uni-id/config.json 中配置QQ小程序(mp-qq.oauth.qq)的appid和appsecret")}return{appid:t,appsecret:n}},qq.auth.getAccessTokenFn=async function(e={}){let{appid:t,appsecret:n}=qq.auth.getAppidInfo(e),{vk:i,config:a}=util$c,r=await i.request({url:`https://api.q.qq.com/api/getToken?grant_type=client_credential&appid=${t}&secret=${n}`,method:"GET"});return r.errcode?(console.error("getAccessToken失败:",r),{code:r.errcode,msg:r.errmsg,err:r}):{code:0,msg:"ok",access_token:r.access_token,expires_in:r.expires_in}},qq.auth.getAccessToken=async function(e={}){let t,{appid:n,appsecret:i}=qq.auth.getAppidInfo(e),{cache:a=!0}=e,{vk:r}=util$c,o="mp-qq-access_token-"+n;if(a&&(t=await r.globalDataCache.get(o)),r.pubfn.isNull(t)){let n=await qq.auth.getAccessTokenFn(e);0===n.code&&(t=n.access_token,await r.globalDataCache.set(o,t,240),await r.globalDataCache.deleteExpired())}return t},qq.auth.code2Session=async function(e={}){let{vk:t,uniID:n}=util$c,{platform:i,needKey:a=!1}=e;i||(i="mp-qq");let r=await qq.auth.code2SessionMpWeixin(e);try{let e=t.crypto.aes.encrypt({data:r});r.encryptedKey=e}catch(e){}return a||(delete r.sessionKey,delete r.accessToken,delete r.refreshToken),delete r.appsecret,r.platform=i,r},qq.auth.code2SessionMpWeixin=async function(e={}){let{appid:t,appsecret:n}=qq.auth.getAppidInfo(e),i=e.code||e.js_code,{vk:a}=util$c,r=await qq.request({url:`sns/jscode2session?appid=${t}&secret=${n}&js_code=${i}&grant_type=authorization_code`,method:"GET"});return r.code?(-101600007===r.code&&(r.msg="appid错误"),-101222100===r.code&&(r.msg="appsecret错误"),-2100===r.code&&(r.msg="无效code,请重新获取"),r):(r=a.pubfn.snake2camelJson(r),{appid:t,appsecret:n,...r,code:0,msg:"ok"})},qq.security={},qq.security.msgSecCheck=async function(e={}){let{content:t,access_token:n=!0}=e,{appid:i,appsecret:a}=qq.auth.getAppidInfo(e),r=await qq.request({url:"api/json/security/MsgSecCheck",method:"POST",data:{access_token:n,appid:i,content:t}});return 40001===r.code&&(r.msg="access_token错误"),87014===r.code&&(r.msg="内容含有违法违规内容,请检查!"),r},qq.security.imgSecCheck=async function(e={}){let{vk:t}=util$c,{dataBuffer:n,formData:i,base64:a}=e,{appid:r,appsecret:o}=qq.auth.getAppidInfo(e),s=await qq.auth.getAccessToken(e);if(!s)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-qq配置的appid和appsecret是否正确"};if(a&&!n){let e="base64,",t=a.indexOf(e);t>-1&&(a=a.substring(t+e.length)),n=new Buffer(a,"base64")}n&&!i&&(i=new t.formDataUtil.FormData,i.append("appid",r),i.append("media",n,{filename:Date.now()+".png",contentType:"image/png"}));let u=await qq.request({url:"api/json/security/ImgSecCheck?access_token="+s,content:i.getBuffer(),headers:i.getHeaders()});switch(u.code){case 40001:u.msg="access_token错误";break;case 87014:u.msg="图片内容含有违法违规内容,请检查!";break;case 40006:u.msg="图片大小不能超过1M"}return u},qq.acode={},qq.acode.getMiniCode=async function(e={}){let{path:t,access_token:n=!0}=e,{appid:i,appsecret:a}=qq.auth.getAppidInfo(e),r=await qq.request({url:"api/json/qqa/CreateMiniCode",method:"POST",data:{access_token:n,appid:i,path:t},dataType:"default",useContent:!0,header:{"content-type":"application/json;charset=utf8"}});if(r.length<500){let e=r.toString();try{e=JSON.parse(e)}catch(e){}return r=returnRes$2(e),40001===r.code&&(r.msg="access_token错误"),41030===r.code&&(r.msg="小程序页面不存在!"),r}return r},qq.subscribeMessage={},qq.subscribeMessage.send=async function(e={}){let{vk:t}=util$c,{touser:n,template_id:i,page:a,data:r,emphasis_keyword:o,oac_appid:s,use_robot:u}=e,l=await qq.auth.getAccessToken(e);if(!l)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-qq配置的appid和appsecret是否正确"};let c=await t.request({url:`${serviceUrl$2}/api/json/subscribe/SendSubscriptionMessage?access_token=${l}`,method:"POST",data:{touser:n,template_id:i,page:a,data:r,emphasis_keyword:o,oac_appid:s,use_robot:u},useContent:!0,header:{"content-type":"application/json;charset=utf8"}});switch(c=returnRes$2(c),c.code){case 40003:c.msg="touser字段openid为空或者不正确";break;case 40037:c.msg="订阅模板id为空不正确";break;case 43101:c.msg="用户未订阅该消息";break;case 40036:c.msg="您的小程序不支持发送长期订阅消息";break;case 47003:c.msg="模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错";break;case 41030:c.msg="page路径不正确,需要保证在现网版本小程序中存在"}return c};var qq_1=qq,weixin={},util$d={};function returnRes$3(e){return e.code=e.errcode||0,e.msg=e.errmsg||"",e}weixin.init=function(e){util$d=e},weixin.getConfig=function(){let{vk:e,config:t}=util$d;return e.pubfn.getUniIdConfig(t)},weixin.request=async function(e={}){let{vk:t}=util$d,{url:n,method:i,data:a,access_token:r}=e;if(r||(r=await weixin.auth.getAccessToken(e)),!r)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};-1===n.indexOf("http")&&(n="https://api.weixin.qq.com/"+n),i||(i=t.pubfn.isNull(a)?"GET":"POST"),i&&"POST"===i.toUpperCase()&&void 0===e.useContent&&(e.useContent=!0),n+=-1===n.indexOf("?")?"?":"&",n+="access_token="+r;let o=await t.request({...e,url:n});return o=returnRes$3(o),o},weixin.decrypt={},weixin.decrypt.getPhoneNumber=async function(e={}){let{vk:t}=util$d,{code:n}=e;if(!n&&e.encryptedData)return await weixin.decrypt.getPhoneNumberByEncryptedData(e);let i={code:0,msg:"ok"},a=t.pubfn.isNullOneByObject({code:n});if(a)return{code:-1,msg:a+"不能为空"};let r=await t.openapi.weixin.request({method:"POST",url:"wxa/business/getuserphonenumber",data:{code:n}});return 0!==r.code?r:(i.data=r.phone_info,i.phone=i.data.phoneNumber,i.mobile=i.data.phoneNumber,i)},weixin.decrypt.getPhoneNumberByEncryptedData=async function(e={}){let t,{vk:n}=util$d,{encryptedData:i,iv:a,sessionKey:r,encryptedKey:o,code:s}=e,u={code:0,msg:"ok"},l=n.pubfn.isNullOneByObject({encryptedData:i,iv:a});if(l)return{code:-1,msg:l+"不能为空"};if(o){let e=n.crypto.aes.decrypt({data:o});t=e.appid,r=e.sessionKey}else{t=weixin.auth.getAppidInfo(e).appid}return u.data=weixin.decrypt.decryptData({appid:t,encryptedData:i,iv:a,sessionKey:r}),u.phone=u.data.phoneNumber,u.mobile=u.data.phoneNumber,u},weixin.decrypt.decryptData=function(e={}){let t,{appid:n,encryptedData:i,iv:a,sessionKey:r}=e,{vk:o,crypto:s}=util$d,u=new Buffer(r,"base64"),l=new Buffer(i,"base64"),c=new Buffer(a,"base64");try{let e=s.createDecipheriv("aes-128-cbc",u,c);e.setAutoPadding(!0),t=e.update(l,"binary","utf8"),t+=e.final("utf8"),t=JSON.parse(t)}catch(e){throw new Error(e)}return t.watermark.appid!==n?{code:-1,msg:"appid不一致"}:t},weixin.auth={},weixin.auth.getAppidInfo=function(e={}){let{appid:t,appsecret:n}=e,{vk:i,config:a}=util$d;const r=weixin.getConfig();if(t){if(!n){let e=i.pubfn.getData(a,"vk.oauth.weixin.list")||[],r=i.pubfn.getListItem(e,"appid",t)||{};if(t=r.appid,n=r.appsecret,i.pubfn.isNullOne(t,n))throw console.log("config",e),new Error(`你使用了多小程序登录模式,但未找到${t}对应的 appsecret 请先在 uni-config-center/vk-unicloud/index.js 中配置微信小程序(vk.oauth.weixin.list)的appid和appsecret`)}}else{let e=i.pubfn.getData(r,"mp-weixin.oauth.weixin")||{};if(t=e.appid,n=e.appsecret,i.pubfn.isNullOne(t,n))throw console.log("config",r),new Error("请先在 uni-config-center/uni-id/config.json 中配置微信小程序(mp-weixin)的appid和appsecret")}return{appid:t,appsecret:n}},weixin.auth.getAccessTokenFn=async function(e={}){let{appid:t,appsecret:n}=weixin.auth.getAppidInfo(e),{vk:i,config:a}=util$d,r=await i.request({url:`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${t}&secret=${n}`,method:"GET"});return r.errcode?(console.error("getAccessToken失败:",r),{code:r.errcode,msg:r.errmsg,err:r}):{code:0,msg:"ok",access_token:r.access_token,expires_in:r.expires_in}},weixin.auth.getAccessToken=async function(e={}){let t,{appid:n,appsecret:i}=weixin.auth.getAppidInfo(e),{cache:a=!0}=e,{vk:r}=util$d,o="mp-weixin-"+n;if(a&&(t=await r.globalDataCache.get(o)),r.pubfn.isNull(t)){let n=await weixin.auth.getAccessTokenFn(e);0===n.code&&(t=n.access_token,await r.globalDataCache.set(o,t,240),await r.globalDataCache.deleteExpired())}return t},weixin.auth.code2Session=async function(e={}){let t,{vk:n,uniID:i}=util$d,{platform:a,context:r,needKey:o=!1}=e;a||(a=n.pubfn.getPlatformForUniId(r)||"mp-weixin"),t="mp-weixin"===a?await weixin.auth.code2SessionMpWeixin(e):"h5-weixin"===a?await weixin.h5.auth.code2Session(e):await i.code2SessionWeixin(e);try{let e=n.crypto.aes.encrypt({data:t});t.encryptedKey=e}catch(e){}return o||(delete t.sessionKey,delete t.accessToken,delete t.refreshToken),delete t.appsecret,t.platform=a,t},weixin.auth.code2SessionMpWeixin=async function(e={}){let{appid:t,appsecret:n}=weixin.auth.getAppidInfo(e),i=e.code||e.js_code,{vk:a}=util$d,r=await a.request({url:`https://api.weixin.qq.com/sns/jscode2session?appid=${t}&secret=${n}&js_code=${i}&grant_type=authorization_code`,method:"GET"});if(r.errcode){let e=r.errmsg;return 40163===r.errcode&&(e="该code已被使用,请重新获取"),40029===r.errcode&&(e="无效code,请重新获取"),{...r,code:r.errcode,msg:e}}return r=a.pubfn.snake2camelJson(r),{appid:t,appsecret:n,...r,code:0,msg:"ok"}},weixin.wxacode={},weixin.wxacode.getUnlimited=async function(e={}){let{vk:t}=util$d,{access_token:n,page:i,scene:a,check_path:r,env_version:o,width:s,auto_color:u,line_color:l,is_hyaline:c}=e;if(n||(n=await weixin.auth.getAccessToken(e)),!n)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};let d=await t.request({url:"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+n,method:"POST",data:{page:i,scene:a,check_path:r,env_version:o,width:s,auto_color:u,line_color:l,is_hyaline:c},dataType:"default",useContent:!0,headers:{encoding:null}});if(d.length<500){let e=d.toString();try{e=JSON.parse(e)}catch(e){}return d=returnRes$3(e),40001===d.code&&(d.msg="access_token错误"),41030===d.code&&(d.msg="小程序页面不存在!"),d}return Buffer.isBuffer(d)?d:returnRes$3(d)},weixin.urlscheme={},weixin.urlscheme.generate=async function(e={}){let{vk:t}=util$d,{access_token:n,jump_wxa:i,is_expire:a,expire_time:r,expire_type:o,expire_interval:s}=e;if(n||(n=await weixin.auth.getAccessToken(e)),!n)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};let u=await t.request({url:"https://api.weixin.qq.com/wxa/generatescheme?access_token="+n,method:"POST",data:{jump_wxa:i,is_expire:a,expire_time:r,expire_type:o,expire_interval:s},useContent:!0});return u=returnRes$3(u),40001===u.code&&(u.msg="access_token错误"),40165===u.code&&(u.msg="小程序页面不存在!"),u},weixin.urllink={},weixin.urllink.generate=async function(e={}){let{vk:t}=util$d,{access_token:n,path:i,query:a,is_expire:r,expire_type:o,expire_time:s,expire_interval:u,cloud_base:l,env_version:c}=e;if(n||(n=await weixin.auth.getAccessToken(e)),!n)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};let d=await t.request({url:"https://api.weixin.qq.com/wxa/generate_urllink?access_token="+n,method:"POST",data:{path:i,query:a,is_expire:r,expire_type:o,expire_time:s,expire_interval:u,cloud_base:l,env_version:c},useContent:!0});return d=returnRes$3(d),40001===d.code&&(d.msg="access_token错误"),40165===d.code&&(d.msg="小程序页面不存在!"),d},weixin.security={},weixin.security.msgSecCheck=async function(e={}){let{vk:t}=util$d,{content:n,version:i,scene:a,openid:r,title:o,nickname:s,signature:u}=e,l=await weixin.auth.getAccessToken(e);if(!l)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};let c=await t.request({url:"https://api.weixin.qq.com/wxa/msg_sec_check?access_token="+l,method:"POST",data:{content:n,version:i,scene:a,openid:r,title:o,nickname:s,signature:u},useContent:!0});return c=returnRes$3(c),40001===c.code&&(c.msg="access_token错误"),87014===c.code&&(c.msg="内容含有违法违规内容,请检查!"),2===i&&c.result&&100!==c.result.label&&(c.code=c.result.label,c.msg="内容含有违法违规内容,请检查!"),c},weixin.security.imgSecCheck=async function(e={}){let{vk:t}=util$d,{dataBuffer:n,formData:i,base64:a}=e,r=await weixin.auth.getAccessToken(e);if(!r)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};if(a&&!n){let e="base64,",t=a.indexOf(e);t>-1&&(a=a.substring(t+e.length)),n=new Buffer(a,"base64")}n&&!i&&(i=new t.formDataUtil.FormData,i.append("media",n,{filename:Date.now()+".png",contentType:"image/png"}));let o=await t.request({url:"https://api.weixin.qq.com/wxa/img_sec_check?access_token="+r,content:i.getBuffer(),headers:i.getHeaders()});switch(o=returnRes$3(o),o.code){case 40001:o.msg="access_token错误";break;case 87014:o.msg="图片内容含有违法违规内容,请检查!";break;case 40006:o.msg="图片大小不能超过1M"}return o},weixin.riskControl={},weixin.riskControl.getUserRiskRank=async function(e={}){let{vk:t}=util$d,{appid:n,openid:i,scene:a,mobile_no:r,client_ip:o,email_address:s,extended_info:u,is_test:l}=e,c=await weixin.auth.getAccessToken(e);if(!c)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};let d=await t.request({url:"https://api.weixin.qq.com/wxa/getuserriskrank?access_token="+c,method:"POST",data:{appid:n,openid:i,scene:a,mobile_no:r,client_ip:o,email_address:s,extended_info:u,is_test:l},useContent:!0});return d=returnRes$3(d),40001===d.code&&(d.msg="access_token错误"),d},weixin.subscribeMessage={},weixin.subscribeMessage.send=async function(e={}){let{vk:t}=util$d,{touser:n,template_id:i,page:a,data:r,miniprogram_state:o="formal",lang:s="zh_CN"}=e,u=await weixin.auth.getAccessToken(e);if(!u)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};let l=await t.request({url:"https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="+u,method:"POST",data:{touser:n,template_id:i,page:a,data:r,miniprogram_state:o,lang:s},useContent:!0});switch(l=returnRes$3(l),l.code){case 40003:l.msg="touser字段openid为空或者不正确";break;case 40037:l.msg="订阅模板id为空不正确";break;case 43101:l.msg="用户未订阅该消息";break;case 47003:l.msg="模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错";break;case 41030:l.msg="page路径不正确,需要保证在现网版本小程序中存在"}return l},weixin.uniformMessage={},weixin.uniformMessage.send=async function(e={}){let{vk:t}=util$d,{appid:n,touser:i,template_appid:a,template_id:r,url:o,miniprogram:s,data:u}=e,l=await weixin.auth.getAccessToken(e);if(!l)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};if(!a){a=weixin.h5.auth.getAppidInfo({appid:a}).appid}let c=await t.request({url:"https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token="+l,method:"POST",data:{touser:i,mp_template_msg:{appid:a,template_id:r,url:o,miniprogram:s,data:u}},useContent:!0});switch(c=returnRes$3(c),c.code){case 40003:c.msg="touser字段openid为空或者不正确";break;case 40037:c.msg="订阅模板id为空不正确";break;case 43101:c.msg="用户未订阅该消息";break;case 47003:c.msg="模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错";break;case 41030:c.msg="page路径不正确,需要保证在现网版本小程序中存在"}return c},weixin.livebroadcast={},weixin.livebroadcast.getLiveInfo=async function(e={}){let{vk:t}=util$d,{pageIndex:n=1,pageSize:i=100}=e,a=await weixin.auth.getAccessToken(e);if(!a)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的mp-weixin配置的appid和appsecret是否正确"};if(n<=0)return{code:-1,msg:"pageIndex必须是大于0的整数"};let r=(n-1)*i,o=i,s=await t.request({url:"https://api.weixin.qq.com/wxa/business/getliveinfo?access_token="+a,method:"POST",data:{start:r,limit:o},useContent:!0});switch(s=returnRes$3(s),s.code){case 941e4:s.msg="直播间列表为空"}return s},weixin.app={},weixin.app.auth={},weixin.app.auth.getAppidInfo=function(e={}){let{appid:t,appsecret:n}=e,{vk:i,config:a}=util$d;const r=weixin.getConfig();if(t){if(!n){let e=i.pubfn.getData(a,"vk.oauth.weixin.list")||[],r=i.pubfn.getListItem(e,"appid",t)||{};t=r.appid,n=r.appsecret}}else{let e=i.pubfn.getData(r,"app-plus.oauth.weixin")||{};t=e.appid,n=e.appsecret}if(i.pubfn.isNullOne(t,n))throw console.log("config",r),new Error("请先在 uni-config-center/uni-id/config.json 中配置微信app登录(app-plus)的appid和appsecret");return{appid:t,appsecret:n}},weixin.app.auth.getAccessToken=async function(e={}){let{appid:t,appsecret:n}=weixin.app.auth.getAppidInfo(e),{vk:i,config:a}=util$d,{code:r}=e,o=await i.request({url:`https://api.weixin.qq.com/sns/oauth2/access_token?appid=${t}&secret=${n}&code=${r}&grant_type=authorization_code`,method:"GET"});return o.errcode?(console.error("getAccessToken失败:",o),{code:o.errcode,msg:o.errmsg,err:o}):{...o,code:0,msg:"ok"}},weixin.app.auth.getUserInfo=async function(e={}){let{vk:t,config:n}=util$d,{access_token:i,openid:a,lang:r="zh-CN"}=e;if(!i)return{code:-1,msg:"access_token不能为空"};let o=await t.request({url:`https://api.weixin.qq.com/sns/userinfo?access_token=${i}&openid=${a}$lang=${r}`,method:"GET"});return o.errcode?(console.error("getUserInfo失败:",o),{code:o.errcode,msg:o.errmsg,err:o}):{...o,code:0,msg:"ok",avatar:o.headimgurl,gender:o.sex}},weixin.h5={},weixin.h5.request=async function(e={}){let{vk:t}=util$d,{url:n,method:i,data:a,access_token:r}=e;if(r||(r=await weixin.h5.auth.getAccessToken(e)),!r)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的h5-weixin配置的appid和appsecret是否正确"};-1===n.indexOf("http")&&(n="https://api.weixin.qq.com/"+n),i||(i=t.pubfn.isNull(a)?"GET":"POST"),i&&"POST"===i.toUpperCase()&&void 0===e.useContent&&(e.useContent=!0),n+=-1===n.indexOf("?")?"?":"&",n+="access_token="+r;let o=await t.request({...e,url:n});return o=returnRes$3(o),o},weixin.h5.auth={},weixin.h5.auth.getAppidInfo=function(e={}){let{appid:t,appsecret:n}=e,{vk:i,config:a}=util$d;const r=weixin.getConfig();if(t){if(!n){let e=i.pubfn.getData(a,"vk.oauth.weixin.list")||[],r=i.pubfn.getListItem(e,"appid",t)||{};t=r.appid,n=r.appsecret}}else{let e=i.pubfn.getData(r,"h5-weixin.oauth.weixin")||{};t=e.appid,n=e.appsecret}if(i.pubfn.isNullOne(t,n))throw console.log("config",r),new Error("请先配置微信公众号appid和appsecret");return{appid:t,appsecret:n}},weixin.h5.auth.code2Session=async function(e={}){let{appid:t,appsecret:n}=weixin.h5.auth.getAppidInfo(e),{code:i}=e,{vk:a}=util$d,r=await a.request({url:`https://api.weixin.qq.com/sns/oauth2/access_token?appid=${t}&secret=${n}&code=${i}&grant_type=authorization_code`,method:"GET"});if(r.errcode){let e=r.errmsg;return 40163===r.errcode&&(e="该code已被使用,请重新获取"),40029===r.errcode&&(e="无效code,请重新获取"),{...r,code:r.errcode,msg:e}}return r=a.pubfn.snake2camelJson(r),{appid:t,appsecret:n,...r,code:0,msg:"ok"}},weixin.h5.auth.getAccessToken=async function(e={}){let t,{appid:n,appsecret:i}=weixin.h5.auth.getAppidInfo(e),{cache:a=!0}=e,{vk:r}=util$d,o="h5-weixin-"+n;if(a&&(t=await r.globalDataCache.get(o)),r.pubfn.isNull(t)){let n=await weixin.h5.auth.getAccessTokenFn(e);if(0===n.code)t=n.access_token,await r.globalDataCache.set(o,t,240),await r.globalDataCache.deleteExpired();else if(console.log("获取微信公众号access_token失败:",n),40164===n.code)throw{code:n.code,msg:"请将固定IP全部加入微信公众号IP白名单,详见搜索文档:固定ip",err:n}}return t},weixin.h5.auth.getAccessTokenFn=async function(e={}){let t,{appid:n,appsecret:i}=weixin.h5.auth.getAppidInfo(e),{vk:a,config:r}=util$d;if("aliyun"===a.pubfn.getUniCloudProvider()){let e=await uniCloud.httpProxyForEip.get("https://api.weixin.qq.com/cgi-bin/token",{grant_type:"client_credential",appid:n,secret:i});if("string"==typeof e)try{e=JSON.parse(e)}catch(e){t={errcode:-1,errmsg:"异常"+e.message}}t="object"==typeof e?e.body:{errcode:-1,errmsg:"异常:getRes未获取到值"}}else t=await a.request({url:`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${n}&secret=${i}`,method:"GET"});return t.errcode?(console.error("getAccessToken失败:",t),{code:t.errcode,msg:t.errmsg,err:t}):{code:0,msg:"ok",access_token:t.access_token,expires_in:t.expires_in}},weixin.h5.subscribeMessage={},weixin.h5.subscribeMessage.send=async function(e={}){let{vk:t}=util$d,{touser:n,template_id:i,page:a,data:r,miniprogram:o}=e,s=await weixin.h5.auth.getAccessToken(e);if(!s)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的h5-weixin配置的appid和appsecret是否正确"};let u=await t.request({url:"https://api.weixin.qq.com/cgi-bin/message/subscribe/bizsend?access_token="+s,method:"POST",data:{touser:n,template_id:i,page:a,data:r,miniprogram:o},useContent:!0});switch(u=returnRes$3(u),u.code){case 40003:u.msg="touser字段openid为空或者不正确";break;case 40037:u.msg="订阅模板id为空不正确";break;case 43101:u.msg="用户未订阅该消息";break;case 47003:u.msg="模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错";break;case 41030:u.msg="page路径不正确,需要保证在现网版本小程序中存在"}return u},weixin.h5.templateMessage={},weixin.h5.templateMessage.send=async function(e={}){let{vk:t}=util$d,{touser:n,template_id:i,url:a,miniprogram:r,data:o}=e,s=await weixin.h5.auth.getAccessToken(e);if(!s)return{code:-1,msg:"获取access_token失败,请检查uni-id配置下的h5-weixin配置的appid和appsecret是否正确"};let u=await t.request({url:"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+s,method:"POST",data:{touser:n,template_id:i,url:a,miniprogram:r,data:o},useContent:!0});switch(u=returnRes$3(u),u.code){case 40003:u.msg="touser字段openid为空或者不正确";break;case 40037:u.msg="订阅模板id为空不正确";break;case 43101:u.msg="用户未订阅该消息";break;case 47003:u.msg="模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错";break;case 41030:u.msg="page路径不正确,需要保证在现网版本小程序中存在"}return u},weixin.loginByWeixin=async function(e={},t,n){let i,a,r;e.context?(i=e.data||{},a=e.context,r=e.custom,e.appid&&(i.appid=e.appid),e.appsecret&&(i.appsecret=e.appsecret)):(i=e,a=t,r=n);let o,s,{vk:u,uniID:l,_:c}=util$d,{code:d,platform:p,type:f,appid:g}=i;if(p||(p=u.pubfn.getPlatformForUniId(a),i.platform=p),g&&["mp-weixin","h5-weixin","app-plus"].indexOf(p)>-1){let e;"mp-weixin"===p?e=weixin.auth.getAppidInfo(i):"h5-weixin"===p?e=weixin.h5.auth.getAppidInfo(i):"app-plus"===p&&(e=weixin.app.auth.getAppidInfo(i));let{appid:t,appsecret:n}=e,r=u.pubfn.copyObject(weixin.getConfig());u.pubfn.setData(r,p+".oauth.weixin",{appid:t,appsecret:n}),i.platform=p,s=l.createInstance({context:a,config:r})}s||(s=l);try{delete i.role,o=await s.loginByWeixin(i);try{if(o.uid&&!o.msg&&(o.msg="register"===o.type?"注册成功":"登录成功"),o.uid&&"register"===o.type){let e={},t={last_login_date:Date.now(),last_login_ip:a.CLIENTIP};if(["h5-weixin","app-plus"].indexOf(p)>-1){let t=await u.openapi.weixin.app.auth.getUserInfo({access_token:o.accessToken,openid:o.openid});e={nickname:t.nickname,avatar:t.headimgurl}}["mp-weixin"].indexOf(p)>-1&&(e={nickname:i.nickname,avatar:i.avatar}),u.pubfn.isNotNull(r)&&(e=u.pubfn.objectAssign(e,r)),u.pubfn.isNotNull(t)&&(e=u.pubfn.objectAssign(e,t)),u.pubfn.isNotNull(e)&&(o.userInfo=await u.baseDao.updateAndReturn({dbName:"uni-id-users",whereJson:{_id:o.uid||"___",nickname:c.exists(!1)},dataJson:e}))}}catch(e){console.error("保存用户头像昵称异常:",e)}if(0===o.code)try{let t=u.crypto.aes.encrypt({data:{code:0,sessionKey:o.sessionKey,openid:o.openid,unionid:o.unionid,uid:o.uid,accessToken:o.accessToken,accessTokenExpired:o.accessTokenExpired,refreshToken:o.refreshToken}});o.encryptedKey=t,e.needKey||(delete o.sessionKey,delete o.accessToken,delete o.refreshToken)}catch(e){}}catch(e){console.error("loginByWeixin异常:",e);let t=e.message||"";throw e.message.indexOf("code been used")>-1&&(t="该code已被使用,请重新获取"),e.message.indexOf("invalid code")>-1&&(t="无效code,请重新获取"),new Error("msg:"+t)}return o};var weixin_1=weixin,openapi={};openapi.alipay=alipay_1,openapi.baidu=baidu_1,openapi.douyin=douyin_1,openapi.qq=qq_1,openapi.weixin=weixin_1,openapi.init=function(e){openapi.alipay.init(e),openapi.baidu.init(e),openapi.douyin.init(e),openapi.qq.init(e),openapi.weixin.init(e)};var openapi_1=openapi,builder=class{constructor(){this._shouldUseCache=!1,this._cachedBuffer=null,this._lineBreak="\r\n",this._boundary="------FormDataBaseBoundary"+Math.random().toString(36).substring(2),this.dataList=[]}_addData(e){if(this._shouldUseCache=!1,0===this.dataList.length)return void this.dataList.push(e);const t=this.dataList[this.dataList.length-1];switch(`${Buffer.isBuffer(t)?"buffer":"other"}_${Buffer.isBuffer(e)?"buffer":"other"}`){case"buffer_buffer":this.dataList.push(this._lineBreak),this.dataList.push(e);break;case"buffer_other":this.dataList.push(this._lineBreak+e);break;case"other_buffer":this.dataList[this.dataList.length-1]=t+"\r\n",this.dataList.push(e);break;case"other_other":this.dataList[this.dataList.length-1]=t+"\r\n"+e}}append(e,t,n){this._addData("--"+this._boundary);let i=`Content-Disposition: form-data; name="${encodeURIComponent(e)}"`;if(Buffer.isBuffer(t)){if(!n.filename||!n.contentType)throw new Error("filename and contentType required");i+=`; filename="${encodeURIComponent(n.filename)}"`,this._addData(i),this._addData("Content-Type: "+n.contentType),this._addData(""),this._addData(t)}else this._addData(i),this._addData(""),this._addData(t)}getHeaders(e){const t={"Content-Type":"multipart/form-data; boundary="+this._boundary};return Object.assign(t,e)}getBuffer(){if(this._shouldUseCache)return this._cachedBuffer;this._shouldUseCache=!0;let e=Buffer.alloc(0);return this.dataList.forEach(t=>{e=Buffer.isBuffer(t)?Buffer.concat([e,t]):Buffer.concat([e,Buffer.from(""+t)])}),e=Buffer.concat([e,Buffer.from(`${this._lineBreak}--${this._boundary}--`)]),this._cachedBuffer=e,e}};const BOUNDARY_REG=/^multipart\/.+?(?:;\s*boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i,LEADING_REG=/Content-Disposition:\sform-data;\sname="(.+?)"(?:;\sfilename="(.+?)")?/i,TYPE_REG=/Content-Type:\s(.+?)$/i,lineBreak="\r\n";function split(e,t){let n=0,i=0,a=[];for(;-1!==(i=e.indexOf(t,n));)a.push(e.slice(n,i)),n=i+t.length,i=e.indexOf(t,n);return a}function readParam(e){let t=e.indexOf("\r\n")+"\r\n".length,n=t,i=e.lastIndexOf("\r\n"),a=[];for(;-1!==(n=e.indexOf("\r\n",t));)if(a.push(e.slice(t,n)),t=n+"\r\n".length,0===a[a.length-1].length){a.push(e.slice(t,i));break}return a}var parser=e=>{const t=(e.headers["content-type"]||e.headers["Content-Type"]).match(BOUNDARY_REG),n=t[1]||t[2],i=split(Buffer.from(e.body,"base64"),Buffer.from("--"+n)).map(e=>readParam(e).filter(e=>e.length>0)).filter(e=>2===e.length||3===e.length||4===e.length).map(e=>{const t={},n=e[0].toString().match(LEADING_REG);switch(t.name=decodeURIComponent(n[1]),e.length){case 2:t.value=e[1].toString();break;case 3:t.filename=decodeURIComponent(n[2]),t.contentType=e[1].toString().match(TYPE_REG)[1],t.fileContent=e[2];break;case 4:t.filename=decodeURIComponent(n[2]),t.contentType=e[1].toString().match(TYPE_REG)[1],t.fileContent=e[3]}return t}),a={};return i.forEach(e=>{const t=e.name;delete e.name,a[t]=e.fileContent?e:e.value}),a},formDataUtils={FormData:builder,formParser:parser};const dbName_role="uni-id-roles",dbName_menu="opendb-admin-menus",dbName_permission="uni-id-permissions";var dao={},util$e={};dao.init=function(e){util$e=e},dao.findRoleById=async(e="___")=>{let t,{vk:n,db:i,_:a}=util$e;return t=await n.baseDao.findByWhereJson({dbName:dbName_role,whereJson:{role_id:e}}),t},dao.roleBindPermission=async(e={})=>{let{vk:t,db:n,_:i}=util$e,a={code:0,msg:""},{role_id:r="___",permissionList:o=[],reset:s=!1}=e;if(!s){let e=await dao.findRoleById(r),{permission:t=[]}=e;o=t.concat(o),o=[...new Set(o)]}return a.num=await t.baseDao.update({dbName:dbName_role,whereJson:{role_id:r},dataJson:{permission:i.set(o)}}),a},dao.roleBindMenu=async(e={})=>{let{vk:t,db:n,_:i}=util$e,a={code:0,msg:""},{role_id:r="___",menuList:o=[],reset:s=!1,addPermission:u=!1}=e,l=[],c=await dao.findRoleById(r),{menu:d=[],permission:p=[]}=c;if(s?l=compareArray(o,d):(o=d.concat(o),o=[...new Set(o)]),a.num=await t.baseDao.update({dbName:dbName_role,whereJson:{role_id:r},dataJson:{menu:i.set(o)}}),u){let e=await dao.findMenuByIdsToPermission(o),n=[];if(s&&t.pubfn.isNotNull(l)){n=compareArray(e,await dao.findMenuByIdsToPermission(l))}p=p.concat(e),p=compareArray(n,p),p=[...new Set(p)],dao.roleBindPermission({role_id:r,permissionList:p,reset:!0})}return a},dao.findPermissionById=async(e="___")=>{let t,{vk:n,db:i,_:a}=util$e;return t=await n.baseDao.findByWhereJson({dbName:dbName_permission,whereJson:{permission_id:e}}),t},dao.findMenuByIdsToPermission=async e=>{let{vk:t,db:n,_:i}=util$e,a=await dao.findMenuByIds(e);if(t.pubfn.isNull(a))return[];let r=[];for(let e in a){let n=a[e].permission;t.pubfn.isNotNull(n)&&(r=r.concat(n))}return r=[...new Set(r)],r},dao.listPermissionToTree=async(e={})=>{let t,{vk:n,db:i,_:a}=util$e,{getCount:r=!1,pageSize:o=500,pageIndex:s=1,whereJson:u={parent_id:a.in([null,""])},sortArr:l=[{name:"sort",type:"asc"}],treeProps:c={}}=e,{level:d=3,limit:p=500,whereJson:f}=c;u&&!u.permission_id&&(u.permission_id=a.exists(!0)),t=await n.baseDao.selects({dbName:dbName_permission,pageIndex:s,pageSize:o,getCount:r,whereJson:u,sortArr:l,treeProps:{id:"permission_id",parent_id:"parent_id",children:"children",level:d,limit:p,whereJson:f,sortArr:l}});let g={id:"permission_id",parent_id:"parent_id",children:"children"},m=t.rows;m=n.pubfn.treeToArray(m,g),t.list=n.pubfn.copyObject(m);for(let e in m){let t=m[e],i="",a="";if(n.pubfn.isNotNull(t.level)){i=` - ${["未分类","子弹级","炸弹级","榴弹级","核弹级"][t.level]}(LV:${t.level})`}if(n.pubfn.isNotNull(t.curd_category)){a=" - "+["未分类","增","删","改","查","特殊"][t.curd_category]}m[e].label=`${t.permission_name}(${t.permission_id})${a}${i}`}return m=n.pubfn.arrayToTree(m,g),t.rows=m,t},dao.findMenuById=async(e="___")=>{let t,{vk:n,db:i,_:a}=util$e;return t=await n.baseDao.findByWhereJson({dbName:dbName_menu,whereJson:{menu_id:e}}),t},dao.findMenuByIds=async e=>{let t,{vk:n,db:i,_:a}=util$e;return n.pubfn.isNull(e)?[]:(t=(await n.baseDao.select({dbName:dbName_menu,pageIndex:1,pageSize:500,whereJson:{menu_id:a.in(e)}})).rows,t)},dao.listMenuByRole=async(e={})=>{let{vk:t,db:n,_:i}=util$e,a={code:0,msg:"",menus:[],menuList:[]},{role:r,treeProps:o={}}=e,s=[],u={enable:!0},l={enable:!0};if(!(r.indexOf("admin")>-1)){if(t.pubfn.isNull(r))return a;let e=await t.baseDao.select({dbName:dbName_role,pageSize:500,whereJson:{role_id:i.in(r),enable:!0},fieldJson:{menu:!0}});for(let n in e.rows){let{menu:i}=e.rows[n];t.pubfn.isNotNull(i)&&(s=s.concat(i))}if(0==s.length)return a;s=[...new Set(s)],u.menu_id=i.in(s),l.menu_id=i.in(s)}u.parent_id=i.in([null,""]);let c=[{name:"sort",type:"asc"}],{level:d=3,limit:p=500}=o,f=await t.baseDao.selects({dbName:dbName_menu,pageIndex:1,pageSize:500,whereJson:u,sortArr:c,treeProps:{id:"menu_id",parent_id:"parent_id",children:"children",level:d,limit:p,whereJson:l,sortArr:c}});return a.menus=f.rows,a.menuList=t.pubfn.treeToArray(f.rows,{id:"menu_id",parent_id:"parent_id",children:"children"}),a},dao.menuBindPermission=async(e={})=>{let{vk:t,db:n,_:i}=util$e,a={code:0,msg:""},{menu_id:r="___",permissionList:o=[],reset:s=!1}=e;if(!s){let e=await dao.findMenuById(r),{permission:t=[]}=e;o=t.concat(o),o=[...new Set(o)]}return a.num=await t.baseDao.update({dbName:dbName_menu,whereJson:{menu_id:r},dataJson:{permission:i.set(o)}}),a},dao.listMenuToTree=async(e={})=>{let t,{vk:n,db:i,_:a}=util$e,{getCount:r=!1,pageSize:o=500,pageIndex:s=1,whereJson:u={parent_id:a.in([null,""]),menu_id:a.exists(!0)},sortArr:l=[{name:"sort",type:"asc"}],treeProps:c={}}=e,{level:d=3,limit:p=500,whereJson:f}=c;u&&!u.menu_id&&(u.menu_id=a.exists(!0)),t=await n.baseDao.selects({dbName:dbName_menu,pageIndex:s,pageSize:o,getCount:r,whereJson:u,sortArr:l,treeProps:{id:"menu_id",parent_id:"parent_id",children:"children",level:d,limit:p,whereJson:f,sortArr:l}});let g={id:"menu_id",parent_id:"parent_id",children:"children"},m=t.rows;m=n.pubfn.treeToArray(m,g),t.list=n.pubfn.copyObject(m);for(let e in m){let t=m[e];m[e].label=`${t.name}(${t.menu_id})`}return m=n.pubfn.arrayToTree(m,g),t.rows=m,t};var sysDao=dao;function compareArray(e,t){let n=new Set(e);return t.filter(e=>!n.has(e))}const dbName="vk-global-data";var dao$1={},util$f={};dao$1.init=function(e){util$f=e},dao$1.find=async e=>{let{vk:t,db:n,_:i}=util$f,a={};return a=await t.baseDao.findById({dbName:dbName,id:e}),a},dao$1.del=async e=>{let{vk:t,db:n,_:i}=util$f,a={};return a=await t.baseDao.deleteById({dbName:dbName,id:e}),a},dao$1.deleteByWhere=async e=>{let{vk:t,db:n,_:i}=util$f,a={};return a=await t.baseDao.del({dbName:dbName,whereJson:e}),a},dao$1.deleteExpired=async e=>{let{vk:t,db:n,_:i}=util$f,a={},r={};"string"==typeof e?r._id=e:"object"==typeof e&&(r=e);let o=(new Date).getTime();return a=await t.baseDao.del({dbName:dbName,whereJson:{...r,expired_at:i.gt(0).lte(o)}}),a},dao$1.update=async e=>{let{vk:t,db:n,_:i}=util$f,a={},{key:r,value:o,comment:s,expired_at:u}=e;return a=await t.baseDao.updateById({dbName:dbName,id:r,dataJson:{value:i.set(o),comment:s,expired_at:u}}),a},dao$1.add=async e=>{let{vk:t,db:n,_:i}=util$f,a={},{key:r,value:o,comment:s,expired_at:u}=e;return a=await t.baseDao.add({dbName:dbName,dataJson:{_id:r,key:r,value:o,comment:s,expired_at:u}}),a},dao$1.count=async e=>{let{vk:t,db:n,_:i}=util$f,a={};return a=await t.baseDao.count({dbName:dbName,whereJson:e}),a},dao$1.set=async e=>{let{vk:t,db:n,_:i}=util$f,a={code:0,msg:"ok"},r=new Date;e._add_time=r.getTime(),e._add_time_str=t.pubfn.timeFormat(r,"yyyy-MM-dd hh:mm:ss");let o=await n.collection(dbName).doc(e.key).set(e);return o.upsertedId?(a.id=o.upsertedId,a.mode="add"):(a.mode="update",a.updated=o.updated),a.num=1,a},dao$1.inc=async e=>{let{vk:t,db:n,_:i}=util$f,{key:a,value:r,expired_at:o}=e,s={},u=await t.baseDao.updateById({dbName:dbName,id:a,dataJson:{value:i.inc(r),expired_at:o}});if(0==u){0===await dao$1.count({_id:a})&&(s.id=await dao$1.add(e),s.num=1,s.mode="add")}else s.num=u,s.mode="update";return s},dao$1.list=async e=>{let{vk:t,db:n,_:i}=util$f,a={},{pageIndex:r,pageSize:o,whereJson:s,sortArr:u}=e;return a=await t.baseDao.select({dbName:dbName,pageIndex:r,pageSize:o,whereJson:s,sortArr:u}),a};var globalDataDao$1=dao$1,util$g={},smsUtil={init:function(e){util$g=e}},aliyun={specialUrlEncode:function(e){return(e=encodeURIComponent(e)).replace(/\+/g,"%20").replace(/\*/g,"%2A").replace(/%7E/g,"~")},sign:function(e,t){let{crypto:n}=util$g;return n.createHmac("sha1",e).update(t).digest("base64")}};smsUtil.sendSms=async function(e){let{vk:t,config:n}=util$g,{provider:i,appid:a,smsKey:r,smsSecret:o,signName:s,phone:u,templateId:l,data:c}=e,d={};if("aliyun"===i){let i=t.pubfn.getData(n,"vk.service.sms.aliyun");t.pubfn.isNotNull(i)&&(r||(e.smsKey=i.accessKeyId),o||(e.smsSecret=i.accessKeySecret),s||(e.signName=i.signName)),d=await smsUtil.sendSmsByAliyun(e)}else{if("unicloud"!==i)return{code:-1,msg:`暂不支持${i}供应商`};{let i=t.pubfn.getUniIdConfig(n,"service.sms");t.pubfn.isNotNull(i)&&(r||(e.smsKey=i.smsKey),o||(e.smsSecret=i.smsSecret),s||(e.signName=i.signName)),d=await smsUtil.sendSmsByUnicloud(e)}}return d.requestParam={provider:i,phone:u},d},smsUtil.sendSmsByAliyun=async function(e){let{vk:t,config:n}=util$g,{provider:i,appid:a,smsKey:r,smsSecret:o,signName:s,phone:u,templateId:l,data:c}=e,d={code:0,msg:""};try{if(t.pubfn.isNullOne(r,o))return{code:-1,msg:"阿里云短信配置错误,请检查vk-unicloud配置下的vk.service.sms.aliyun配置的accessKeyId和accessKeySecret是否正确"};let e="https://dysmsapi.aliyuncs.com",n=t.pubfn.timeFormat(new Date,"yyyy-MM-ddThh:mm:ssZ",0),i=(new Date).getTime().toString().substring(7)+t.pubfn.random(30);"object"==typeof c&&(c=JSON.stringify(c));let a={SignatureMethod:"HMAC-SHA1",SignatureNonce:i,AccessKeyId:r,SignatureVersion:"1.0",Timestamp:n,Format:"json",Action:"SendSms",Version:"2017-05-25",PhoneNumbers:u,SignName:s,TemplateParam:c,TemplateCode:l};delete a.Signature;let p=[];for(let e in a)p.push(e);p.sort();let f=!1,g="";for(let e in p){let t=p[e];g+="&"+aliyun.specialUrlEncode(t)+"="+aliyun.specialUrlEncode(a[t])}g=g.substring(1);let m="GET&"+aliyun.specialUrlEncode("/")+"&"+aliyun.specialUrlEncode(g),b=aliyun.sign(o+"&",m),h=aliyun.specialUrlEncode(b),y="Signature="+h+"&"+g;f&&(console.log("\r\n随机数\r\n"),console.log(a.SignatureNonce),console.log("\r\n=========\r\n"),console.log(a.Timestamp),console.log("\r\n====sortedQueryString====\r\n"),console.log(g),console.log("\r\n=====stringToSign====\r\n"),console.log(m),console.log("\r\n=====sign====\r\n"),console.log(b),console.log("\r\n=====signature====\r\n"),console.log(h),console.log("\r\n=========\r\n"),console.log(e+"/?"+y));t.pubfn.urlStringToJson(y);let w=await t.request({url:`${e}?${y}`,method:"GET"});return d="OK"===w.Code?{code:0,msg:"ok",requestRes:w}:{code:-1,msg:w.Message,requestRes:w},d}catch(e){return{code:-1,msg:"短信发送失败",err:{message:e.message,stack:e.stack}}}},smsUtil.sendSmsByUnicloud=async function(e){let{vk:t,config:n}=util$g,{provider:i,appid:a,smsKey:r,smsSecret:o,signName:s,phone:u,templateId:l,data:c}=e,d={code:0,msg:""};try{if(t.pubfn.isNullOne(r,o))return{code:-1,msg:"unicloud短信配置错误,请检查uni-id配置下的service.sms配置的smsKey和smsSecret是否正确"};let e=await uniCloud.sendSms({smsKey:r,smsSecret:o,phone:u,templateId:l,data:c});d=0==e.code||0==e.errCode?{code:0,msg:"ok",requestRes:e}:{code:-1,msg:e.errMessage||e.errMsg,requestRes:e}}catch(e){return{code:-1,msg:"短信发送失败",err:{message:e.message,stack:e.stack}}}return d},smsUtil.sendSmsVerifyCode=async function(e){let t,{vk:n,config:i,uniID:a}=util$g,{provider:r,phone:o,code:s,type:u,expiresIn:l=180}=e,c={code:0,msg:""};if("unicloud"===r){t=n.pubfn.getUniIdConfig(i,"service.sms.templateId");let e=n.pubfn.getUniIdConfig(i,"service.sms.codeExpiresIn");e&&(l=e);let a=n.pubfn.getUniIdConfig(i,"service.sms.name"),u=Math.ceil(l/60).toString();c=await n.system.smsUtil.sendSms({provider:r,phone:o,templateId:t,data:{code:s,name:a,action:"身份验证",expMinute:u}})}else t=n.pubfn.getData(i,`vk.service.sms.${r}.templateCode.verifyCode`),c=await n.system.smsUtil.sendSms({provider:r,phone:o,templateId:t,data:{code:s}});return 0===c.code&&await a.setVerifyCode({mobile:o,code:s,expiresIn:l,type:u}),c};var smsUtil_1=smsUtil,system={};system.sysDao=sysDao,system.globalDataDao=globalDataDao$1,system.smsUtil=smsUtil_1,system.init=function(e){let t=["sysDao","globalDataDao","smsUtil"];for(let n in t){let i=t[n];"function"==typeof system[i].init&&system[i].init(e)}};var system_1=system,vkunicloud={};class VK{constructor(e){this.router=router,this.md5=md5,this.baseDao=vkBaseDao,this.request=vk_request,this.callFunction=vk_callFunction,this.pubfn=_function,this.temporaryCache=temporaryCache,this.globalDataCache=globalDataCache_1,this.crypto=crypto,this.openapi=openapi_1,this.formDataUtil=formDataUtils,this.system=system_1,this.baseDir=null,e&&this.init(e)}require(e){return vkunicloud.requireFn(this.baseDir+"/"+e)}requireFn(e){try{return vkunicloud.requireFn(e)}catch(e){let{message:t=""}=e;return void(-1==t.indexOf("Cannot find module")&&-1==t.indexOf("no such file or directory")&&console.error(e))}}use(e,t){for(let n in e)e[n]&&"function"==typeof e[n].init&&e[n].init(t),this[n]=e[n]}getGlobalObject(){return"object"==typeof globalThis?globalThis:"object"==typeof self?self:"object"==typeof window?window:"object"==typeof commonjsGlobal?commonjsGlobal:void 0}init(e={}){let t=this;if(e.requireFn&&(vkunicloud.requireFn=e.requireFn),e.baseDir&&(t.baseDir=e.baseDir),e.configCenter||(e.configCenter=t.requireFn("uni-config-center")),e.uniID||(e.uniID=t.requireFn("uni-id")),e.uniPay||(e.uniPay=t.requireFn("uni-pay")),e.middlewareService||(e.middlewareService=t.requireFn("./middleware/index")),e.daoCenter||(e.daoCenter=t.requireFn("./dao/index")),e.crypto||(e.crypto=t.requireFn("crypto")),e.urlrewrite||(e.urlrewrite=t.requireFn("./util/urlrewrite")),e.config||(e.config=e.configCenter({pluginId:"vk-unicloud"}).requireFile("index.js")),!e.config)throw new Error("配置文件:uniCloud/cloudfunctions/common/uni-config-center/vk-unicloud/index.js \n编译错误,请检查!");if(!e.db)try{e.db=uniCloud.database()}catch(e){}if(t.vkPay=t.requireFn("vk-uni-pay"),e.pubFun||(e.pubFun=t.requireFn("./util/pubFunction")),e.pubFun&&(t.myfn=e.pubFun),e.redis||(e.redis=t.requireFn("vk-redis")),e.redis)t.redisUtil=e.redis,t.redis=e.redis.redis,t.newRedis=e.redis.newRedis;else try{t.redis=uniCloud.redis}catch(e){}e.uniMap||(e.uniMap=t.requireFn("uni-map-common")),e.uniMap&&(t.uniMap=e.uniMap),e.db&&(vkunicloud.db=e.db,vkunicloud._=e.db.command),vkunicloud.pubfn=t.pubfn,e.configCenter&&(vkunicloud.configCenter=e.configCenter),e.config&&(vkunicloud.config=e.config),e.uniID&&(vkunicloud.uniID=e.uniID),e.uniPay&&(vkunicloud.uniPay=e.uniPay),e.middlewareService&&(vkunicloud.middlewareService=e.middlewareService),e.pubFun&&(vkunicloud.pubFun=e.pubFun),e.customUtil&&(vkunicloud.customUtil=e.customUtil),e.crypto&&(vkunicloud.crypto=e.crypto),e.urlrewrite&&(vkunicloud.urlrewrite=e.urlrewrite);const n={vk:t,...vkunicloud};t.use({daoCenter:e.daoCenter,baseDao:t.baseDao,openapi:t.openapi,globalDataCache:t.globalDataCache,system:t.system,pubFun:e.pubFun},n);try{let n=t.getGlobalObject();"object"==typeof n&&e.middlewareService&&(n.vk=t)}catch(e){}}getUnicloud(){return vkunicloud}createInstance(e){return new VK(e)}}var src=new VK;module.exports=src;
diff --git a/uni_modules/vk-unicloud/uniCloud/cloudfunctions/common/vk-unicloud/package.json b/uni_modules/vk-unicloud/uniCloud/cloudfunctions/common/vk-unicloud/package.json
new file mode 100644
index 0000000..cb547fc
--- /dev/null
+++ b/uni_modules/vk-unicloud/uniCloud/cloudfunctions/common/vk-unicloud/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "vk-unicloud",
+ "version": "2.15.3",
+ "description": "【云函数端SDK】VK云函数路由模式uniCloud开发框架,在router目录下执行 npm i vk-unicloud 进行安装和升级",
+ "main": "index.js",
+ "homepage": "https://gitee.com/vk-uni/vk-uni-cloud-router.git",
+ "repository": {
+ "type": "git",
+ "url": "git+https://gitee.com/vk-uni/vk-uni-cloud-router.git"
+ },
+ "files": [
+ "dist"
+ ],
+ "author": "VK",
+ "license": "Apache-2.0"
+}
\ No newline at end of file
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/index.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/index.js
new file mode 100644
index 0000000..e3eebe7
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/index.js
@@ -0,0 +1,190 @@
+/**
+ * vk-unicloud框架客户端(前端)
+ * author VK
+ */
+import userCenter from './libs/vk-unicloud/vk-unicloud-user-center'
+import callFunctionUtil from './libs/vk-unicloud/vk-unicloud-callFunctionUtil'
+import pubfn from './libs/function/index'
+import modal from './libs/function/modal'
+import navigate from './libs/function/vk.navigate'
+import localStorage from './libs/function/vk.localStorage'
+import sessionStorage from './libs/function/vk.sessionStorage'
+import aliyunOSSUtil from './libs/function/aliyunOSSUtil'
+import openapi from './libs/openapi/index'
+import requestUtil from './libs/function/vk.request'
+import importObject from './libs/function/vk.importObject'
+
+import filters from './libs/function/vk.filters'
+import mixin from './libs/mixin/mixin.js'
+import initPermission from './libs/function/permission'
+import storeMixin from './libs/store/mixin/mixin'
+import initGlobalError from './libs/store/libs/error'
+import consoleLog from './libs/install/console.log'
+import updateManager from './libs/function/updateManager.js'
+// #ifdef H5
+import h5 from './libs/function/vk.h5'
+// #endif
+
+
+
+var vk = {
+ userCenter,
+ callFunctionUtil,
+ /**
+ * 发起一个云函数请求
+ */
+ callFunction: callFunctionUtil.callFunction,
+ getToken: callFunctionUtil.getToken,
+ checkToken: callFunctionUtil.checkToken,
+ uploadFile: callFunctionUtil.uploadFile,
+ getConfig: callFunctionUtil.getConfig,
+ emitRefreshToken: callFunctionUtil.emitRefreshToken,
+ onRefreshToken: callFunctionUtil.onRefreshToken,
+ offRefreshToken: callFunctionUtil.offRefreshToken,
+ pubfn,
+
+ // #ifdef H5
+ h5,
+ // #endif
+
+ alert: modal.alert,
+ toast: modal.toast,
+ confirm: modal.confirm,
+ prompt: modal.prompt,
+ showActionSheet: modal.showActionSheet,
+ showLoading: modal.showLoading,
+ hideLoading: modal.hideLoading,
+ setLoading: modal.setLoading,
+
+ navigate,
+ // 保留当前页面,并进行页面跳转
+ navigateTo: navigate.navigateTo,
+ // 关闭当前页面,并进行页面跳转
+ redirectTo: navigate.redirectTo,
+ // 并关闭所有页面,并进行页面跳转
+ reLaunch: navigate.reLaunch,
+ // 并关闭所有非tab页面,并进行tab面跳转
+ switchTab: navigate.switchTab,
+ // 页面返回
+ navigateBack: navigate.navigateBack,
+ // 跳转到首页
+ navigateToHome: navigate.navigateToHome,
+ // 跳转到登录页
+ navigateToLogin: navigate.navigateToLogin,
+ // 跳转到小程序
+ navigateToMiniProgram: navigate.navigateToMiniProgram,
+ // 触发全局的自定义事件,附加参数都会传给监听器回调函数。
+ $emit: navigate.$emit,
+ // 监听全局的自定义事件,事件由 uni.$emit 触发,回调函数会接收事件触发函数的传入参数。
+ $on: navigate.$on,
+ // 触发全局的自定义事件,附加参数都会传给监听器回调函数。
+ $once: navigate.$once,
+ // 移除全局自定义事件监听器。
+ $off: navigate.$off,
+ // 本地持久
+ localStorage: localStorage,
+ // 本地会话缓存
+ sessionStorage: sessionStorage,
+
+ // 获取应用语言列表
+ getLocaleList: pubfn.getLocaleList,
+ // 获取应用当前语言
+ getLocale: pubfn.getLocale,
+ // 获取应用当前语言对象
+ getLocaleObject: pubfn.getLocaleObject,
+ // 设置应用当前语言
+ setLocale: pubfn.setLocale,
+
+
+ // 本地持久缓存
+ ...localStorage,
+ // 本地会话缓存
+ ...sessionStorage,
+ // 阿里云oss
+ aliyunOSSUtil,
+ // 更新管理器
+ updateManager,
+ // 开放API
+ openapi,
+ // 请求库
+ requestUtil,
+ // 发起URL请求
+ request: requestUtil.request,
+ // 导出云对象
+ importObject
+};
+// vk实例初始化
+vk.init = function(obj = {}) {
+ let {
+ Vue, // Vue实例
+ config, // 配置
+ store, // vuex简写法则(新版本无需传store)
+ } = obj;
+ if (typeof store !== "undefined") {
+ // 兼容旧版本
+ Vue.use(store);
+ } else {
+ // 新版本无需传store
+ Vue.mixin(storeMixin);
+ if (config.globalError) {
+ Vue.use(initGlobalError);
+ }
+ }
+ // 自定义云函数路由配置
+ vk.callFunctionUtil.setConfig(config);
+ // 重写 console.log
+ Vue.use(consoleLog);
+};
+
+vk.getGlobalObject = function() {
+ if (typeof globalThis === "object") return globalThis;
+ if (typeof self === "object") return self;
+ if (typeof window === "object") return window;
+ if (typeof global === "object") return global;
+};
+// 加载拓展功能
+vk.use = function(obj, util) {
+ for (let name in obj) {
+ if (obj[name] && typeof obj[name].init === "function") {
+ obj[name].init(util);
+ }
+ vk[name] = obj[name];
+ }
+};
+
+const install = Vue => {
+ // 全局混入
+ Vue.mixin(mixin);
+ // #ifndef VUE3
+ // 加载全局过滤器开始
+ for (let i in filters) {
+ Vue.filter(i, filters[i]);
+ }
+ Vue.prototype.vk = vk;
+ Vue.prototype.$fn = vk.pubfn;
+
+ // #endif
+
+ // #ifdef VUE3
+ // 将vk挂载到Vue实例
+ Vue.config.globalProperties.vk = vk;
+ Vue.config.globalProperties.$fn = vk.pubfn;
+ // #endif
+
+ // 将vk挂载到uni对象
+ if (typeof uni == "object") uni.vk = vk;
+ // 将vk挂载到全局
+ let vkGlobalThis = vk.getGlobalObject();
+ if (typeof vkGlobalThis == "object") vkGlobalThis.vk = vk;
+ let util = { vk };
+ // 加载插件
+ vk.use({
+ callFunctionUtil: vk.callFunctionUtil,
+ openapi: vk.openapi
+ }, util);
+ initPermission(Vue);
+}
+
+export default {
+ install
+}
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/aliyunOSSUtil.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/aliyunOSSUtil.js
new file mode 100644
index 0000000..6ec7911
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/aliyunOSSUtil.js
@@ -0,0 +1,274 @@
+/**
+ * 阿里云oss工具类
+ */
+var aliyunOSSUtil = {};
+var counterNum = 0;
+
+/**
+ * 上传至阿里云oss
+vk.callFunctionUtil.uploadFile({
+ filePath:tempFilePath,
+ fileType:"image",
+ provider:"aliyun",
+ index,
+ onUploadProgress:function(res){
+ // 上传过程中
+ if (res.progress > 0) {
+ if(list[index]){
+ list[index].progress = res.progress;
+
+ }
+ }
+ },
+ success:function(res){
+ // 上传成功
+
+ },
+ fail:function(res){
+ // 上传失败
+
+ }
+});
+ */
+aliyunOSSUtil.uploadFile = function(obj) {
+ let {
+ filePath,
+ fileType = "image",
+ name = "file",
+ header = {
+ "x-oss-forbid-overwrite": true,
+ },
+ index = 0,
+ file = {},
+ needSave = false,
+ category_id,
+ title,
+ cloudPathRemoveChinese = true, // 删除文件名中的中文
+ cloudDirectory,
+ } = obj;
+ let vk = getApp().globalData.vk;
+ if (title) vk.showLoading(title);
+ let fileNameObj = createFileName(obj);
+ let aliyunOSS = getConfig();
+ let fileName = fileNameObj.fileFullName;
+ let formData = vk.pubfn.copyObject(aliyunOSS.uploadData);
+ formData["key"] = fileName; // 存储在oss的文件路径
+ /**
+ * 特别说明
+ * 若已知本地图片,则使用formData["name"] = filePath
+ * 若已知base64,则是用formData["file"] = file;// file base64字符串转成blob对象
+ */
+ if (filePath.indexOf(";base64,") > -1) {
+ formData["file"] = dataURLtoBlob(filePath);
+ } else {
+ formData["name"] = filePath;
+ }
+ let Logger = {};
+ Logger.startTime = new Date().getTime();
+ Logger.filePath = filePath;
+ return new Promise((resolve, reject) => {
+ let uploadTask = uni.uploadFile({
+ url: aliyunOSS.action,
+ filePath,
+ name,
+ header,
+ formData: formData,
+ success: function(res) {
+ if (title) vk.hideLoading();
+ if (![200, 201].includes(res.statusCode)) {
+ if (typeof obj.fail === "function") obj.fail(res);
+ Logger.error = res;
+ } else {
+ // 上传成功
+ res.fileID = fileNameObj.url;
+ res.url = fileNameObj.url;
+ Logger.result = res;
+ if (typeof obj.success === "function") obj.success(res);
+ resolve(res);
+ if (needSave) {
+ // 保存文件记录到数据库
+ vk.userCenter.addUploadRecord({
+ data: {
+ url: res.fileID,
+ name: file.name,
+ size: file.size,
+ file_id: res.fileID,
+ provider: "aliyun",
+ category_id
+ },
+ filePath,
+ fileType,
+ success: function() {
+ if (typeof obj.addSuccess == "function") obj.addSuccess(res);
+ },
+ fail: function(res) {
+ if (typeof obj.addFail === "function") obj.addFail(res);
+ }
+ });
+ }
+ }
+ },
+ fail: function(res) {
+ if (title) vk.hideLoading();
+ Logger.error = res;
+ if (res.errMsg && res.errMsg.indexOf('fail url not in domain list') > -1) {
+ vk.toast('上传域名未在白名单中');
+ }
+ if (typeof obj.fail === "function") obj.fail(res);
+ },
+ complete: function() {
+ let vk = getApp().globalData.vk;
+ let config = vk.callFunctionUtil.config;
+ if (config.debug) {
+ Logger.endTime = new Date().getTime();
+ Logger.runTime = (Logger.endTime - Logger.startTime);
+ let colorArr = config.logger.colorArr;
+ let colorStr = colorArr[counterNum % colorArr.length];
+ counterNum++;
+ console.log("%c--------【开始】【阿里云oss文件上传】--------", 'color: ' + colorStr + ';font-size: 12px;font-weight: bold;');
+ console.log("【本地文件】: ", Logger.filePath);
+ console.log("【返回数据】: ", Logger.result);
+ console.log("【预览地址】: ", Logger.result.fileID);
+ console.log("【上传耗时】: ", Logger.runTime, "毫秒");
+ console.log("【上传时间】: ", vk.pubfn.timeFormat(Logger.startTime, "yyyy-MM-dd hh:mm:ss"));
+ if (Logger.error) console.error("【error】:", Logger.error);
+ console.log("%c--------【结束】【阿里云oss文件上传】--------", 'color: ' + colorStr + ';font-size: 12px;font-weight: bold;');
+ }
+ }
+ });
+ uploadTask.onProgressUpdate((res) => {
+ if (res.progress > 0) {
+ if (typeof obj.onUploadProgress === "function") obj.onUploadProgress(res);
+ }
+ });
+ });
+};
+
+
+export default aliyunOSSUtil;
+
+
+// 获取配置
+function getConfig() {
+ let vk = getApp().globalData.vk;
+ let aliyunOSS = vk.getConfig("service.aliyunOSS");
+ let configData = {};
+ if (aliyunOSS && aliyunOSS.uploadData && aliyunOSS.uploadData.OSSAccessKeyId) {
+ try {
+ // 只有开启按userId分组且开启了vk的vuex功能,才可以自动按userId分组
+ if (aliyunOSS.groupUserId && typeof vk.getVuex === "function") {
+ let userInfo = vk.getVuex("$user.userInfo");
+ if (vk.pubfn.isNotNull(userInfo) && userInfo._id) {
+ aliyunOSS.dirname += `/${userInfo._id}`;
+ }
+ }
+ } catch (err) {}
+ configData = {
+ uploadData: {
+ OSSAccessKeyId: aliyunOSS.uploadData.OSSAccessKeyId,
+ policy: aliyunOSS.uploadData.policy,
+ signature: aliyunOSS.uploadData.signature,
+ success_action_status: 200,
+ key: "test.png"
+ },
+ action: aliyunOSS.action,
+ dirname: aliyunOSS.dirname,
+ host: aliyunOSS.host,
+ };
+ }
+ return configData;
+}
+// 生成文件名
+function createFileName(obj = {}) {
+ let {
+ file,
+ filePath,
+ index = 0,
+ cloudPathRemoveChinese = true,
+ cloudDirectory
+ } = obj;
+ let vk = getApp().globalData.vk;
+ let aliyunOSS = getConfig();
+ let dirname = aliyunOSS.dirname;
+ let host = aliyunOSS.host;
+ let fileObj = {};
+
+ let suffix = getFileSuffix(obj);
+ let oldName = index + "." + suffix;
+ if (file && file.name) {
+ let suffixName = file.name.substring(file.name.lastIndexOf(".") + 1);
+ if (suffixName && suffixName.length < 5) oldName = file.name;
+ // 只保留["数字","英文",".","-"]
+ if (cloudPathRemoveChinese) {
+ oldName = oldName.replace(/[^a-zA-Z.-d]/g, '');
+ }
+ if (oldName.indexOf(".") == 0) oldName = "0" + oldName;
+ }
+ let date = new Date();
+ let dateYYYYMMDD = vk.pubfn.timeFormat(date, "yyyy/MM/dd");
+ let dateTime = date.getTime().toString(); // 时间戳
+ // 时间戳后8位
+ let dateTimeEnd8 = dateTime.substring(dateTime.length - 8, dateTime.length);
+ let randomNumber = vk.pubfn.random(8); // 8位随机数
+ // 文件路径 = 固定路径名 + 业务路径
+
+ // 业务路径
+ let servicePath = "";
+ if (cloudDirectory) {
+ // 如果自定义了上传目录,则使用自定义的上传目录
+ if (cloudDirectory.lastIndexOf("/") !== cloudDirectory.length-1) {
+ cloudDirectory = cloudDirectory + "/";
+ }
+ servicePath = cloudDirectory;
+ } else {
+ // 否则,使用年月日作为上传目录
+ servicePath = dateYYYYMMDD + "/";
+ }
+ // 文件名 = 时间戳后8位 - 随机数8位 + 后缀名
+ let fileNickName = dateTimeEnd8 + randomNumber + "-" + oldName;
+ // 文件相对路径 = 业务目录 + 文件名
+ let fileRelativePath = servicePath + fileNickName;
+ // 文件名全称(包含文件路径) = 根目录 + 文件相对路径
+ let fileFullName = dirname + "/" + fileRelativePath;
+ // 外网地址 = 外网域名 + 文件名全称
+ let url = host + "/" + fileFullName;
+ fileObj.url = url;
+ fileObj.fileFullName = fileFullName;
+ fileObj.fileNickName = fileNickName;
+ return fileObj;
+}
+
+function getFileSuffix(obj = {}) {
+ let {
+ file,
+ filePath,
+ suffix = "png"
+ } = obj;
+ if (filePath) {
+ let suffixName = filePath.substring(filePath.lastIndexOf(".") + 1);
+ if (suffixName && suffixName.length < 5) suffix = suffixName;
+ }
+ if (file) {
+ if (file.path) {
+ let suffixName = file.path.substring(file.path.lastIndexOf(".") + 1);
+ if (suffixName && suffixName.length < 5) suffix = suffixName;
+ }
+ if (file.name) {
+ let suffixName = file.name.substring(file.name.lastIndexOf(".") + 1);
+ if (suffixName && suffixName.length < 5) suffix = suffixName;
+ }
+ }
+ return suffix;
+}
+
+function dataURLtoBlob(dataurl) {
+ let arr = dataurl.split(','),
+ mime = arr[0].match(/:(.*?);/)[1],
+ bstr = atob(arr[1]),
+ n = bstr.length,
+ u8arr = new Uint8Array(n);
+ while (n--) {
+ u8arr[n] = bstr.charCodeAt(n);
+ }
+ return new Blob([u8arr], { type: mime });
+}
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/debounce.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/debounce.js
new file mode 100644
index 0000000..485521e
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/debounce.js
@@ -0,0 +1,34 @@
+let timeoutArr = [];
+/**
+ * 防抖函数
+ * 防抖原理:一定时间内,只有最后一次或第一次调用,回调函数才会执行
+ * @param {Function} fn 要执行的回调函数
+ * @param {Number} time 延时的时间
+ * @param {Boolean} isImmediate 是否立即执行 默认true
+ * @param {String} timeoutName 定时器ID
+ * @return null
+vk.pubfn.debounce(() => {
+
+}, 1000);
+ */
+function debounce(fn, time = 500, isImmediate = true, timeoutName = "default") {
+ // 清除定时器
+ if(!timeoutArr[timeoutName]) timeoutArr[timeoutName] = null;
+ if (timeoutArr[timeoutName] !== null) clearTimeout(timeoutArr[timeoutName]);
+ // 立即执行一次
+ if (isImmediate) {
+ var callNow = !timeoutArr[timeoutName];
+ timeoutArr[timeoutName] = setTimeout(() => {
+ timeoutArr[timeoutName] = null;
+ }, time);
+ if (callNow){
+ if(typeof fn === 'function') return fn();
+ }
+ } else {
+ // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时time毫秒后执行fn回调方法
+ timeoutArr[timeoutName] = setTimeout(() => {
+ if(typeof fn === 'function') return fn();
+ }, time);
+ }
+}
+export default debounce
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/deepClone.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/deepClone.js
new file mode 100644
index 0000000..3db999a
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/deepClone.js
@@ -0,0 +1,23 @@
+// 判断arr是否为一个数组,返回一个bool值
+function isArray (arr) {
+ return Object.prototype.toString.call(arr) === '[object Array]';
+}
+
+// 深度克隆
+function deepClone (obj) {
+ // 对常见的“非”值,直接返回原来值
+ if([null, undefined, NaN, false].includes(obj)) return obj;
+ if(typeof obj !== "object" && typeof obj !== 'function') {
+ //原始类型直接返回
+ return obj;
+ }
+ var o = isArray(obj) ? [] : {};
+ for(let i in obj) {
+ if(obj.hasOwnProperty(i)){
+ o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
+ }
+ }
+ return o;
+}
+
+export default deepClone;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/deepMerge.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/deepMerge.js
new file mode 100644
index 0000000..81d2d18
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/deepMerge.js
@@ -0,0 +1,30 @@
+import deepClone from "./deepClone";
+
+// JS对象深度合并
+function deepMerge(target = {}, source = {}) {
+ target = deepClone(target);
+ if (typeof target !== 'object' || typeof source !== 'object') return false;
+ for (var prop in source) {
+ if (!source.hasOwnProperty(prop)) continue;
+ if (prop in target) {
+ if (typeof target[prop] !== 'object') {
+ target[prop] = source[prop];
+ } else {
+ if (typeof source[prop] !== 'object') {
+ target[prop] = source[prop];
+ } else {
+ if (target[prop].concat && source[prop].concat) {
+ target[prop] = target[prop].concat(source[prop]);
+ } else {
+ target[prop] = deepMerge(target[prop], source[prop]);
+ }
+ }
+ }
+ } else {
+ target[prop] = source[prop];
+ }
+ }
+ return target;
+}
+
+export default deepMerge;
\ No newline at end of file
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/index.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/index.js
new file mode 100644
index 0000000..dbd1091
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/index.js
@@ -0,0 +1,2430 @@
+/**
+ * 通用公共函数
+ */
+var pubfn = {};
+// 防抖
+import debounce from './debounce.js'
+// 限流
+import throttle from './throttle.js'
+// url参数
+import queryParams from './queryParams.js'
+// H5版本的复制
+import setClipboardData from './setClipboardData.js'
+// 时间
+import timeUtil from './timeUtil.js'
+// 树形结构转换
+import treeUtil from './treeUtil.js'
+
+/**
+ * 树形结构转换
+ */
+pubfn.treeUtil = treeUtil;
+/**
+ * 时间工具类
+ */
+pubfn.timeUtil = timeUtil;
+/**
+ * 防抖函数
+ */
+pubfn.debounce = debounce;
+/**
+ * 节流函数
+ */
+pubfn.throttle = throttle;
+/**
+ * 对象转url参数
+ * @param {*} data,对象
+ * @param {*} isPrefix,是否自动加上"?"
+ * 此函数参考uView
+ * vk.pubfn.queryParams(json);
+ */
+pubfn.queryParams = queryParams;
+/**
+ * 设置剪贴板
+ */
+pubfn.setClipboardData = setClipboardData;
+
+/**
+ * 休眠,等待(单位毫秒)
+ * @param {Number} ms 毫秒
+ * await vk.pubfn.sleep(1000);
+ */
+pubfn.sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+/**
+ * 日期格式化
+ * @param {Date || Number} date 需要格式化的时间
+ * vk.pubfn.timeFormat(new Date(),"yyyy-MM-dd hh:mm:ss");
+ */
+pubfn.timeFormat = pubfn.timeUtil.timeFormat;
+/**
+ * 解析日期对象属性
+ * @param {Date || Number} date 需要转换的时间
+ * vk.pubfn.getDateInfo(new Date());
+ */
+pubfn.getDateInfo = pubfn.timeUtil.getDateInfo;
+
+/**
+ * 日期对象转换(此API已弃用,建议用vk.pubfn.timeFormat代替)
+ * @param {Date || Number} date 需要转换的时间
+ * @param {Number} type 转换方式
+ * type = 0 返回 2020-08-03 12:12:12
+ * type = 1 返回 20200803121212
+ * type = 2 返回 { YYYY, MM, DD, hh, mm, ss }
+ */
+pubfn.getFullTime = pubfn.timeUtil.getFullTime;
+
+/**
+ * 获取时间范围
+ * @param {Date} date 日期对象 可以指定时间计算节点,默认使用当前时间进行计算
+ * 返回的是时间戳(防止时区问题)
+ * 返回数据如下:
+ {
+ todayStart 今日开始时间
+ todayEnd 今日结束时间
+ today12End 今日上午结束时间
+ monthStart 本月开始时间
+ monthEnd 本月结束时间
+ yearStart 本年开始时间
+ yearEnd 本年结束时间
+ weekStart 本周开始时间
+ weekEnd 本周结束时间
+ now 现在的时间点(含月年日时分秒)
+ months 本年度每月的开始和结束时间 months[1] 代表1月
+ }
+ * vk.pubfn.getCommonTime();
+ */
+pubfn.getCommonTime = pubfn.timeUtil.getCommonTime;
+
+/**
+ * 获得指定时间偏移 year年 month月 day天 hours时 minutes分 seconds秒前或后的时间戳
+ * 返回时间戳形式
+vk.pubfn.getOffsetTime(new Date(), {
+ year:0,
+ month:0,
+ day:0,
+ hours:0,
+ minutes:0,
+ seconds:0,
+ mode:"after", // after 之后 before 之前
+});
+ */
+pubfn.getOffsetTime = pubfn.timeUtil.getOffsetTime;
+
+/**
+ * 获得相对当前时间的偏移 count 小时的起止日期(小时的开始和结束)
+ * @param {Number} count 默认0 (0代表当前小时 为-1代表上一个小时 为1代表下一个小时以此类推)
+ * @param {Date || Number} date 指定从哪个时间节点开始计算
+ * vk.pubfn.getHourOffsetStartAndEnd(0);
+ */
+pubfn.getHourOffsetStartAndEnd = pubfn.timeUtil.getHourOffsetStartAndEnd;
+
+
+/**
+ * 获得相对当前时间的偏移 count 天的起止日期(日的开始和结束)
+ * @param {Number} count 默认0 (0代表今日 为-1代表昨日 为1代表明日以此类推)
+ * @param {Date || Number} date 指定从那天开始计算
+ * vk.pubfn.getDayOffsetStartAndEnd(0);
+ */
+pubfn.getDayOffsetStartAndEnd = pubfn.timeUtil.getDayOffsetStartAndEnd;
+
+/**
+ * 获得相对当前周addWeekCount个周的起止日期
+ * @param {Number} addWeekCount 默认0 (0代表本周 为-1代表上周 为1代表下周以此类推 为2代表下下周)
+ * vk.pubfn.getWeekOffsetStartAndEnd(0);
+ */
+pubfn.getWeekOffsetStartAndEnd = pubfn.timeUtil.getWeekOffsetStartAndEnd; // 新版写法
+pubfn.getWeekStartAndEnd = pubfn.timeUtil.getWeekOffsetStartAndEnd; // 兼容老版本写法
+
+/**
+ * 获得相对当前时间的偏移 count 月的起止日期(月的开始和结束)
+ * @param {Number} count 默认0 (0代表本月 为-1代表上月 为1代表下月以此类推)
+ * @param {Date || Number} date 指定从那天开始计算
+ * vk.pubfn.getMonthOffsetStartAndEnd(0);
+ */
+pubfn.getMonthOffsetStartAndEnd = pubfn.timeUtil.getMonthOffsetStartAndEnd;
+
+/**
+ * 获得相对当前时间的偏移 count 个季度的起止日期(季度的开始和结束时间戳)
+ * @param {Number} count 默认0(0代表本季度 -1代表上个季度 1代表下个季度以此类推)
+ * @param {Date || Number} date 指定从哪个时间节点开始计算
+ * vk.pubfn.getQuarterOffsetStartAndEnd(0);
+ */
+pubfn.getQuarterOffsetStartAndEnd = pubfn.timeUtil.getQuarterOffsetStartAndEnd;
+
+
+/**
+ * 获得相对当前时间的偏移 count 年的起止日期(年的开始和结束)
+ * @param {Number} count 默认0 (0代表今年 为-1代表去年 为1代表明年以此类推)
+ * @param {Date || Number} date 指定从那天开始计算
+ * vk.pubfn.getYearOffsetStartAndEnd(0);
+ */
+pubfn.getYearOffsetStartAndEnd = pubfn.timeUtil.getYearOffsetStartAndEnd;
+
+/**
+ * 获得指定年份和月份后的该月的开始时间和结束时间
+ * 返回数据如下:(时间戳形式)
+ {
+ startTime 该月开始时间
+ endTime 该月结束时间
+ }
+vk.pubfn.getMonthStartAndEnd({
+ year:2021
+ month:1
+});
+ */
+pubfn.getMonthStartAndEnd = pubfn.timeUtil.getMonthStartAndEnd;
+
+/**
+ * Vue 全局表单验证器扩展
+rules: {
+ receiver_mobile:[
+ { validator:vk.pubfn.validator("mobile"), message: '手机号格式错误', trigger: 'blur' }
+ ],
+},
+ */
+pubfn.validator = function(type) {
+ return function(rule, value, callback) {
+ let key = pubfn.test(value, type);
+ if (typeof callback === "function") {
+ if (key || !value) {
+ callback();
+ } else {
+ return callback(false);
+ }
+ } else {
+ return callback(false);
+ }
+ }
+};
+
+/**
+ * 检测文本是否满足指定格式
+ * @param {String} str 需要检测的文本
+ * @param {String} type 检测类型(忽略大小写)
+ * @param {Boolean} allowEmpty 是否允许为空
+ * 包含
+ * mobile 手机号码
+ * tel 座机
+ * card 身份证
+ * mobileCode 6位数字验证码
+ * username 账号以字母开头,长度在3~32之间,只能包含字母、数字和下划线
+ * pwd 密码长度在6~18之间,只能包含字母、数字和下划线
+ * password 与pwd效果一致,密码长度在6~18之间,只能包含字母、数字和下划线
+ * paypwd 支付密码 6位纯数字
+ * postal 邮政编码
+ * qq QQ号
+ * email 邮箱
+ * money 金额(小数点只允许2位)
+ * url 网址
+ * ip IP地址
+ * date 日期 2020-08-03
+ * time 时间 12:12:12
+ * dateTime 日期+时间 2020-08-03 12:12:12
+ * number 纯数字
+ * english 纯英文
+ * chinese 纯中文
+ * english+number 英文+数字
+ * english+number+_ 英文+数字+_
+ * english+number+_- 英文+数字+_-
+ * lower 小写
+ * upper 大写
+ * version 版本号 xx.xx.xx (xx必须是数字)
+ * html html格式
+ * image 图片
+ * video 视频
+ * audio 音频
+ * vk.pubfn.test(str, type, allowEmpty);
+ */
+pubfn.test = function(str, type = "", allowEmpty=false) {
+ type = type.toLowerCase();
+ let newStr;
+ if (allowEmpty && (str === "" || str === null || str === undefined)) {
+ return true;
+ }
+ switch (type) {
+ case 'mobile': //手机号码
+ return new RegExp(/^1[3|4|5|6|7|8|9][0-9]{9}$/).test(str);
+ case 'tel': //座机
+ return new RegExp(/^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/).test(str);
+ case 'card': //身份证
+ return new RegExp(/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/).test(str);
+ case 'mobilecode': //6位数字验证码
+ return new RegExp(/^[0-9]{6}$/).test(str);
+ case 'username': //账号以字母开头,长度在3~32之间,只能包含字母、数字和下划线
+ return new RegExp(/^[a-zA-Z]([-_a-zA-Z0-9]{2,31})$/).test(str)
+ case 'pwd': //密码长度在6~18之间,只能包含字母、数字和下划线和@
+ return new RegExp(/^([a-zA-Z0-9_@]){6,18}$/).test(str)
+ case 'password': //密码长度在6~18之间,只能包含字母、数字和下划线和@
+ return new RegExp(/^([a-zA-Z0-9_@]){6,18}$/).test(str)
+ case 'paypwd': //支付密码 6位纯数字
+ return new RegExp(/^[0-9]{6}$/).test(str)
+ case 'postal': //邮政编码
+ return new RegExp(/[1-9]\d{5}(?!\d)/).test(str);
+ case 'qq': //QQ号
+ return new RegExp(/^[1-9][0-9]{4,9}$/).test(str);
+ case 'email': //邮箱
+ return new RegExp(/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/).test(str);
+ case 'money': //金额(小数点2位)
+ return new RegExp(/^\d*(?:\.\d{0,2})?$/).test(str);
+ case 'url': //网址
+ return new RegExp(/^(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/).test(str);
+ case 'ip': //IP
+ 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(
+ str);
+ case 'date': //日期 2014-01-01
+ 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);
+ case 'time': //时间 12:00:00
+ return new RegExp(/^(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$/).test(str);
+ case 'datetime': //日期+时间 2014-01-01 12:00:00
+ 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);
+ case 'english+number': //英文+数字(空字符串算通过)
+ return new RegExp(/^[a-zA-Z0-9]+$/).test(str);
+ case 'english+number+_': //英文+数字+_(空字符串算通过)
+ return new RegExp(/^[a-zA-Z0-9_]+$/).test(str);
+ case 'english+number+_-': //英文+数字+_-(空字符串算通过)
+ return new RegExp(/^[a-zA-Z0-9_-]+$/).test(str);
+ case 'version': //版本号 xx.xx.xx(xx必须是数字)
+ return new RegExp(/^([1-9]\d|[1-9])(.([1-9]\d|\d)){2}$/).test(str);
+ case 'number': //数字(空字符串算通过)
+ return new RegExp(/^[0-9]+$/).test(str);
+ case 'english': //英文(空字符串算通过)
+ return new RegExp(/^[a-zA-Z]+$/).test(str);
+ case 'chinese': //中文(空字符串算通过)
+ return new RegExp(/^[\u4e00-\u9fa5]+$/gi).test(str);
+ case 'lower': //小写(空字符串算通过)
+ return new RegExp(/^[a-z]+$/).test(str);
+ case 'upper': //大写(空字符串算通过)
+ return new RegExp(/^[A-Z]+$/).test(str);
+ case 'html': //HTML标记
+ return new RegExp(/<("[^"]*"|'[^']*'|[^'">])*>/).test(str);
+ case 'image': //是否图片格式
+ newStr = str.split("?")[0];
+ return new RegExp(/\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)$/).test(newStr);
+ case 'video': //是否视频格式
+ newStr = str.split("?")[0];
+ return new RegExp(/\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8|3gp)$/).test(newStr);
+ case 'audio': //是否音频格式
+ newStr = str.split("?")[0];
+ return new RegExp(/\.(mp3)$/).test(newStr);
+ default:
+ return true;
+ }
+};
+// 保留之前的函数名
+pubfn.checkStr = pubfn.test;
+/**
+ * 删除对象中所有值为无效值的属性(如:undefined)
+ * @param {Object} obj
+ * vk.pubfn.objectDeleteInvalid(obj);
+ */
+pubfn.objectDeleteInvalid = function(obj = {}) {
+ Object.keys(obj).forEach(item => {
+ if (obj[item] === undefined) {
+ delete obj[item];
+ }
+ });
+ return obj;
+};
+/**
+ * 对象属性拷贝(浅拷贝)
+ * @description 将 obj2 的属性赋值给 obj1(如果obj1中有对应的属性,则会被obj2的属性值覆盖)
+ * @param {Object} obj1
+ * @param {Object} obj2
+ * vk.pubfn.objectAssign(obj1, obj2);
+ * vk.pubfn.objectAssign(obj1, obj2, true);
+ * vk.pubfn.objectAssign(obj1, obj2, false);
+ */
+pubfn.objectAssign = function(obj1, obj2, deleteInvalid = true) {
+ if (deleteInvalid) pubfn.objectDeleteInvalid(obj2);
+ return Object.assign(obj1, obj2);
+};
+/**
+ * 复制一份对象-没有映射关系
+ * @description 主要用于解除映射关系(不支持克隆函数)
+ * @param {Object} obj
+ * let newObj = vk.pubfn.copyObject(obj);
+ */
+pubfn.copyObject = function(obj) {
+ if (typeof obj !== "undefined") {
+ return JSON.parse(JSON.stringify(obj));
+ } else {
+ return obj;
+ }
+};
+/**
+ * 深度克隆一个对象-没有映射关系
+ * @description 主要用于解除映射关系(支持克隆函数)
+ * @param {Object} obj
+ * let newObj = vk.pubfn.deepClone(obj);
+ */
+pubfn.deepClone = function(obj) {
+ // 对常见的“非”值,直接返回原来值
+ if ([null, undefined, NaN, false].includes(obj)) return obj;
+ if (typeof obj !== "object" && typeof obj !== 'function') {
+ //原始类型直接返回
+ return obj;
+ }
+ let o = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {};
+ for (let i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ o[i] = typeof obj[i] === "object" ? pubfn.deepClone(obj[i]) : obj[i];
+ }
+ }
+ return o;
+};
+/**
+ * 表单自动填充数据
+ * @description 主要用于表单修改时,数据库没有默认字段会报错的问题
+ * @param {Object} defaultData 默认数据
+ * @param {Object} itemData 当前数据
+ * that.form1 = vk.pubfn.formAssign(defaultData,itemData);
+ */
+pubfn.formAssign = function(defaultData, itemData) {
+ let newDefaultData = pubfn.copyObject(defaultData);
+ return pubfn.objectAssign(newDefaultData, itemData);
+};
+
+
+/**
+ * 两个(元素为对象)的数组合并,并去除重复的数据
+ * @param {Array} arr1 第一个数组(arr1和aar2没有顺序要求)
+ * @param {Array} aar2 第二个数组
+ * @param {String} flag 判断标识,默认用id来判断,若flag传-1,代表不去除重复数据
+ * let arr = vk.pubfn.arr_concat(arr1, arr2, "_id");
+ */
+pubfn.arr_concat = function(arr1, arr2, flag) {
+ if (!flag) flag = "id"; // 默认用id来判断是否是同一个对象元素
+ if (!arr1) arr1 = [];
+ if (!arr2) arr2 = [];
+ let arr3 = arr1.concat(arr2); // 新旧数据合并
+ let arr = []; // 定义一个临时数组 存放对象
+ if (flag != -1) {
+ let arr_id = []; // 定义一个临时数组 存放id
+ for (let i in arr3) { // 循环遍历当前数组
+ // 判断当前数组下标为i的元素是否已经保存到临时数组
+ // 如果已保存,则跳过,否则将此元素保存到临时数组中
+ if (arr_id.indexOf(arr3[i][flag]) == -1) {
+ arr_id.push(arr3[i][flag]); // 添加id到数组
+ arr.push(arr3[i]); // 添加对象到数组
+ }
+ }
+ } else {
+ arr = arr3;
+ }
+ return arr;
+};
+/**
+ * 自动根据字符串路径获取对象中的值支持.和[] , 且任意一个值为undefined时,不会报错,会直接返回undefined
+ * @param {Object} dataObj 数据源
+ * @param {String} name 支持a.b 和 a[b]
+ * @param {String} defaultValue undefined时的默认值
+ * vk.pubfn.getData(dataObj, name);
+ */
+pubfn.getData = function(dataObj, name, defaultValue) {
+ let newDataObj;
+ if (pubfn.isNotNull(dataObj)) {
+ newDataObj = JSON.parse(JSON.stringify(dataObj));
+ let k = "",
+ d = ".",
+ l = "[",
+ r = "]";
+ name = name.replace(/\s+/g, k) + d;
+ let tstr = k;
+ for (let i = 0; i < name.length; i++) {
+ let theChar = name.charAt(i);
+ if (theChar != d && theChar != l && theChar != r) {
+ tstr += theChar;
+ } else if (newDataObj) {
+ if (tstr != k) newDataObj = newDataObj[tstr];
+ tstr = k;
+ }
+ }
+ }
+ if (typeof newDataObj === "undefined" && typeof defaultValue !== "undefined") newDataObj = defaultValue;
+ return newDataObj;
+};
+/**
+ * 自动根据字符串路径设置对象中的值 支持.和[]
+ * @param {Object} dataObj 数据源
+ * @param {String} name 支持a.b 和 a[b]
+ * @param {String} value 值
+ * vk.pubfn.setData(dataObj, name, value);
+ */
+pubfn.setData = function(dataObj, name, value) {
+ // 通过正则表达式 查找路径数据
+ let dataValue;
+ if (typeof value === "object") {
+ dataValue = pubfn.copyObject(value);
+ } else {
+ dataValue = value;
+ }
+ let regExp = new RegExp("([\\w$-]+)|\\[(:\\d)\\]", "g");
+ const patten = name.match(regExp);
+ // 遍历路径 逐级查找 最后一级用于直接赋值
+ for (let i = 0; i < patten.length - 1; i++) {
+ let keyName = patten[i];
+ if (typeof dataObj[keyName] !== "object") dataObj[keyName] = {};
+ dataObj = dataObj[keyName];
+ }
+ // 最后一级
+ dataObj[patten[patten.length - 1]] = dataValue;
+};
+
+/**
+ * 检测参数是否为空 其中 undefined、null、{}、[]、"" 均为空值 true 空值 false 有值
+ * vk.pubfn.isNull(value);
+ */
+pubfn.isNull = function(value) {
+ let key = false;
+ if (
+ typeof value == "undefined" ||
+ Object.prototype.toString.call(value) == "[object Null]" ||
+ JSON.stringify(value) == "{}" ||
+ JSON.stringify(value) == "[]" ||
+ value === "" ||
+ JSON.stringify(value) === undefined
+ ) {
+ key = true;
+ }
+ return key;
+};
+/**
+ * 检测参数是否不为空 结果与 vk.pubfn.isNull 相反
+ * vk.pubfn.isNotNull(value);
+ */
+pubfn.isNotNull = function(value) {
+ return !pubfn.isNull(value);
+};
+/**
+ * 检测所有参数 - 是否至少有一个为空
+ * vk.pubfn.isNullOne(value1,value2,value3);
+ */
+pubfn.isNullOne = function(...strS) {
+ let key = false;
+ for (let i = 0; i < strS.length; i++) {
+ let str = strS[i];
+ if (pubfn.isNull(str)) {
+ key = true;
+ break;
+ }
+ }
+
+ return key;
+};
+/**
+ * 检测整个对象是否没有一个属性是空值,如果有空值,则返回首个是空值的属性名
+ let nullKey = vk.pubfn.isNullOneByObject({ value1,value2,value3 });
+ if(nullKey) return { code : -1, msg : `${nullKey}不能为空` };
+ */
+pubfn.isNullOneByObject = function(obj) {
+ let key;
+ for (let name in obj) {
+ let val = obj[name];
+ if (pubfn.isNull(val)) {
+ key = name;
+ break;
+ }
+ }
+ return key;
+};
+/**
+ * 检测所有参数 - 是否全部为空
+ * vk.pubfn.isNullAll(value1,value2,value3);
+ */
+pubfn.isNullAll = function(...strS) {
+ let key = true;
+ for (let i = 0; i < strS.length; i++) {
+ let str = strS[i];
+ if (pubfn.isNotNull(str)) {
+ key = false;
+ break;
+ }
+ }
+ return key;
+};
+
+/**
+ * 检测所有参数 - 是否全部都不为空
+ * vk.pubfn.isNotNullAll(value1,value2,value3);
+ */
+pubfn.isNotNullAll = function(...strS) {
+ return !pubfn.isNullOne(...strS);
+};
+/**
+ * 获取对象数组中的某一个item,根据指定的键名和键值
+ * @description 主要用于在一个对象数组中快速获取 _id = 1 的对象
+ * @param {Array} list 数据源
+ * @param {String} key 键名(不可为空)
+ * @param {String} value 键值 (不可为空)
+ * vk.pubfn.getListItem(list, key, value);
+ */
+pubfn.getListItem = function(list, key, value) {
+ let item;
+ for (let i = 0; i < list.length; i++) {
+ if (list[i][key] === value) {
+ item = list[i];
+ break;
+ }
+ }
+ return item;
+};
+/**
+ * 获取对象数组中某个元素的index,根据指定的键名和键值
+ * @description 主要用于在一个对象数组中快速获取 _id = 1 的index
+ * @param {Array} list 数据源
+ * @param {String} key 键名
+ * @param {String} value 键值
+ * vk.pubfn.getListIndex(list, key, value);
+ */
+pubfn.getListIndex = function(list, key, value) {
+ let index = -1;
+ for (let i = 0; i < list.length; i++) {
+ if (list[i][key] === value) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+};
+/**
+ * 获取对象数组中某个元素的index,根据指定的键名和键值
+ * @description 主要用于在一个对象数组中快速获取 _id = 1 的index
+ * @param {Array} list 数据源
+ * @param {String} key 键名
+ * @param {String} value 键值
+ * vk.pubfn.getListItemIndex(list, key, value);
+ */
+pubfn.getListItemIndex = function(list, key, value) {
+ let obj = {};
+ let item;
+ let index = -1;
+ for (let i = 0; i < list.length; i++) {
+ if (list[i][key] === value) {
+ index = i;
+ item = list[i];
+ break;
+ }
+ }
+ obj = {
+ item,
+ index
+ }
+ return obj;
+};
+/**
+ * 数组转对象 - 将对象数组转成json
+ * 如[{"_id":"001","name":"name1","sex":1},{"_id":"002","name":"name2","sex":2}]
+ * 转成
+ * {"001",{"_id":"001","name":"name1","sex":1},"002":{"_id":"002","name":"name2","sex":2}}
+ * vk.pubfn.arrayToJson(list, "_id");
+ */
+pubfn.arrayToJson = function(list, key) {
+ let json = {};
+ for (let i in list) {
+ let item = list[i];
+ json[item[key]] = item;
+ }
+ return json;
+};
+pubfn.listToJson = pubfn.arrayToJson;
+
+/**
+ * 从数组中提取指定字段形式成为新的数组
+ * 如[{"_id":"001","name":"name1","sex":1},{"_id":"002","name":"name2","sex":2}]
+ * 提取_id字段转成
+ * ["001","002"]
+ * let idArr = vk.pubfn.arrayObjectGetArray(list, "_id");
+ */
+pubfn.arrayObjectGetArray = function(list, key) {
+ return list.map(obj => { return obj[key] });
+};
+
+/**
+ * 产生指定位数的随机数(支持任意字符,默认纯数字)
+ * @param {Number} length 随机数固定位数
+ * @param {String} range 指定的字符串中随机范围
+ * @param {Array} arr 产生的随机数不会和此数组的任意一项重复
+ * vk.pubfn.random(6);
+ * vk.pubfn.random(6, "abcdefghijklmnopqrstuvwxyz0123456789");
+ * vk.pubfn.random(1,"12",["1","2"]);
+ */
+pubfn.random = function(length, range, arr) {
+ let s;
+ if (pubfn.isNull(arr)) {
+ s = pubfn.randomFn(length, range);
+ } else {
+ let i = 0;
+ let maxForCount = 100000;
+ do {
+ i++;
+ s = pubfn.randomFn(length, range);
+ } while (arr.indexOf(s) > -1 && i < maxForCount);
+ if (i === maxForCount) {
+ s = undefined;
+ }
+ }
+ return s;
+};
+/**
+ * 产生指定位数的随机数(支持任意字符,默认纯数字)
+ * @param {Number} length 随机数固定位数
+ * @param {String} range 指定的字符串中随机范围
+ * vk.pubfn.random(6);
+ * vk.pubfn.random(6, "abcdefghijklmnopqrstuvwxyz0123456789");
+ */
+pubfn.randomFn = function(length, range) {
+ let s = "";
+ let list = "123456789";
+ //0123456789QWERTYUIPASDFGHJKLZXCVBNM
+ if (pubfn.isNotNull(range)) {
+ if (range == "a-z,0-9") {
+ range = "abcdefghijklmnopqrstuvwxyz0123456789";
+ } else if (range == "A-Z,0-9") {
+ range = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ } else if (range == "a-z,A-Z,0-9" || range == "A-Z,a-z,0-9") {
+ range = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ }
+ list = range;
+ }
+ for (let i = 0; i < length; i++) {
+ let code = list[Math.floor(Math.random() * list.length)];
+ s += code;
+ }
+ return s;
+};
+
+/**
+ * 将字符串id转化为指定位数的纯数字字符串id(会重复)
+ * vk.pubfn.stringIdToNumberId(uid,8);
+ */
+pubfn.stringIdToNumberId = function(str, length) {
+ let s = "";
+ let list = "0123456789";
+ for (let i = 0; i < length; i++) {
+ if (str.length > i) {
+ let index = str[i].charCodeAt() % 10;
+ s += list[index];
+ } else {
+ s = "0" + s;
+ }
+ }
+ return s;
+};
+
+/**
+ * 将手机号,账号等隐藏中间字段
+ * @param {String} str 需要转换的字符串
+ * @param {Number} first 前面显示的字符数量
+ * @param {Number} last 后面显示的字符数量
+ * vk.pubfn.hidden(str, first, last);
+ */
+pubfn.hidden = function(str = "", first = 0, last = 0) {
+ let len = str.length - first - last;
+ let xing = '';
+ for (let i = 0; i < len; i++) {
+ xing += '*';
+ }
+ return str.substring(0, first) + xing + str.substring(str.length - last);
+};
+/**
+ * 判断常量数组A是否至少有一个元素在常量数组B中存在(两数组有交集)
+ * @param {Array} arr1 数组A
+ * @param {Array} arr2 数组B
+ * vk.pubfn.checkArrayIntersection(arr1, arr2);
+ */
+pubfn.checkArrayIntersection = function(arr1 = [], arr2 = []) {
+ let checkKey = false;
+ for (let i = 0; i < arr2.length; i++) {
+ if (arr1.indexOf(arr2[i]) > -1) {
+ checkKey = true;
+ }
+ }
+ return checkKey;
+};
+/**
+ * 检测数据源是否满足表达式规则
+ * @param {Object} data 数据源
+ * @param {String} expText 表达式文本
+ * vk.pubfn.checkDataExpText(data, expText);
+ */
+pubfn.checkDataExpText = function(data = {}, expText) {
+ expText = expText.replace(new RegExp("\\s", "g"), "");
+ //console.log("expText:",expText);
+ let orArr = expText.split("||");
+ //console.log("orArr",orArr);
+ let checkKey = false;
+ for (let index1 = 0; index1 < orArr.length; index1++) {
+ let orItem = orArr[index1];
+ let andArr = orItem.split("&&");
+ //console.log("andArr",andArr);
+ let itemKey = true;
+ for (let index2 = 0; index2 < andArr.length; index2++) {
+ let andItem = andArr[index2];
+ //console.log("andItem",andItem);
+ if (andItem.indexOf("!=") > -1) {
+ let andItemArr = andItem.split("!=");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ let formValue = pubfn.getData(data,key);
+
+ itemKey = String(formValue) !== value ? true : false;
+
+ } else if (andItem.indexOf("==") > -1) {
+ let andItemArr = andItem.split("==");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ let formValue = pubfn.getData(data,key);
+
+ itemKey = String(formValue) == value ? true : false;
+
+ } else if (andItem.indexOf(">=") > -1) {
+ let andItemArr = andItem.split(">=");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ let formValue = pubfn.getData(data,key);
+ if (isNaN(value)) {
+ if (typeof formValue !== "undefined") itemKey = String(formValue) >= value ? true : false;
+ if (typeof formValue === "undefined" || formValue === null) itemKey = false;
+ } else {
+ if (typeof formValue !== "undefined") itemKey = formValue >= Number(value) ? true : false;
+ if (typeof formValue === "undefined" || formValue === null) itemKey = false;
+ }
+ } else if (andItem.indexOf(">") > -1) {
+ let andItemArr = andItem.split(">");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ let formValue = pubfn.getData(data,key);
+ if (isNaN(value)) {
+ if (typeof formValue !== "undefined") itemKey = String(formValue) > value ? true : false;
+ if (typeof formValue === "undefined" || formValue === null) itemKey = false;
+ } else {
+ if (typeof formValue !== "undefined") itemKey = formValue > Number(value) ? true : false;
+ if (typeof formValue === "undefined" || formValue === null) itemKey = false;
+ }
+ } else if (andItem.indexOf("<=") > -1) {
+ let andItemArr = andItem.split("<=");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ if (isNaN(value)) {
+ if (typeof data[key] !== "undefined") itemKey = String(data[key]) <= value ? true : false;
+ if (typeof data[key] === "undefined" || data[key] === null) itemKey = false;
+ } else {
+ if (typeof data[key] !== "undefined") itemKey = data[key] <= Number(value) ? true : false;
+ if (typeof data[key] === "undefined" || data[key] === null) itemKey = false;
+ }
+ } else if (andItem.indexOf("<") > -1) {
+ let andItemArr = andItem.split("<");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ let formValue = pubfn.getData(data,key);
+ if (isNaN(value)) {
+ if (typeof formValue !== "undefined") itemKey = String(formValue) < value ? true : false;
+ if (typeof formValue === "undefined" || formValue === null) itemKey = false;
+ } else {
+ if (typeof formValue !== "undefined") itemKey = formValue < Number(value) ? true : false;
+ if (typeof formValue === "undefined" || formValue === null) itemKey = false;
+ }
+ } else if (andItem.indexOf("{in}") > -1) {
+ let andItemArr = andItem.split("{in}");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ let formValue = pubfn.getData(data,key);
+ if (Array.isArray(formValue)) {
+ let index = formValue.findIndex(item => {
+ return item.toString() === value.toString();
+ });
+ itemKey = index > -1 ? true : false;
+ } else {
+ itemKey = false;
+ }
+ //itemKey = (Array.isArray(formValue) && formValue.indexOf(value) > -1 ) ? true : false;
+ } else if (andItem.indexOf("{nin}") > -1) {
+ let andItemArr = andItem.split("{nin}");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ let formValue = pubfn.getData(data,key);
+ if (Array.isArray(formValue)) {
+ let index = formValue.findIndex(item => {
+ return item.toString() === value.toString();
+ });
+ itemKey = index < 0 ? true : false;
+ } else {
+ itemKey = false;
+ }
+ //itemKey = (Array.isArray(formValue) && formValue.indexOf(value) < 0 ) ? true : false;
+ } else {
+ let andItemArr = andItem.split("=");
+ let key = andItemArr[0];
+ let value = andItemArr[1];
+ let formValue = pubfn.getData(data,key);
+
+ itemKey = String(formValue) == value ? true : false;
+
+ //console.log("key:",key,"value:",value,"formValue",formValue.toString(),"itemKey:",itemKey);
+ }
+ if (!itemKey) {
+ break;
+ }
+ }
+ if (itemKey) {
+ checkKey = true;
+ break;
+ }
+ }
+ return checkKey;
+};
+
+/**
+ * 判断变量是否是数组
+ * vk.pubfn.isArray(value);
+ */
+pubfn.isArray = function(value) {
+ return Object.prototype.toString.call(value) === "[object Array]" ? true : false;
+};
+/**
+ * 判断变量是否是对象
+ * vk.pubfn.isObject(value);
+ */
+pubfn.isObject = function(value) {
+ return Object.prototype.toString.call(value) === "[object Object]" ? true : false;
+};
+
+
+
+/**
+ * 计算运费
+ * @param {Object} freightItem 运费模板
+ {
+ first_weight Number 首重(KG)
+ first_weight_price Number 首重 首重价格(100=1元)
+ continuous_weight Number 续重(KG)
+ continuous_weight_price Number 续重价格(100=1元)
+ max_weight Number 重量达到此值时(KG),会多计算首重的价格,并少一次续重的价格 倍乘(相当于拆分多个包裹)
+ }
+ * @param {Number} weight 运费重量
+ * 返回值
+ * @return {Number} 最终运费金额(100=1元)
+ * vk.pubfn.calcFreights(freightItem, weight);
+ */
+pubfn.calcFreights = function(freightItem, weight) {
+ let freightRes = vk.pubfn.calcFreightDetail(freightItem, weight);
+ return freightRes.total_amount;
+};
+
+/**
+ * 计算运费,返回细节
+ * @param {Object} freightItem 运费模板
+ {
+ first_weight Number 首重(KG)
+ first_weight_price Number 首重 首重价格(100=1元)
+ continuous_weight Number 续重(KG)
+ continuous_weight_price Number 续重价格(100=1元)
+ max_weight Number 重量达到此值时(KG),会多计算首重的价格,并少一次续重的价格 倍乘(相当于拆分多个包裹)
+ }
+ * @param {Number} weight 需要计算的商品重量
+ * 返回值
+ * @return {Number} weight 运费重量(KG)
+ * @return {Number} first_weight_price 首重金额(100=1元)
+ * @return {Number} continuous_weight_price 续重金额(100=1元)
+ * @return {Number} total_amount 最终运费金额(100=1元)
+ * @return {String} formula 运费计算公式字符串
+ * let freightRes = vk.pubfn.calcFreightDetail(freightItem, weight);
+ */
+pubfn.calcFreightDetail = function(freightItem, weight) {
+ let {
+ first_weight, // 首重(KG)
+ first_weight_price, // 首重价格(元)
+ continuous_weight, // 续重(KG)
+ continuous_weight_price, // 续重价格(元)
+ max_weight, // 拆包裹,每个包裹最大重量(KG)
+ } = freightItem;
+ if (!max_weight) max_weight = 1000000000;
+ let originalWeight = weight;
+ let money = 0; // 运费
+ let first_weight_count = 0; // 包裹数量
+ let packagesSurplusWeight = max_weight; // 包裹剩余重量
+ let first_weight_key = false; // 是否已减过首重
+ let continuous_weight_count = 0; // 续重次数
+ let logArr = [];
+ let logRun = false;
+ while (weight > 0) {
+ if (!first_weight_key) {
+ // 首重
+ first_weight_key = true;
+ first_weight_count++;
+ packagesSurplusWeight = max_weight; // 还原包裹剩余重量
+ weight -= first_weight;
+ packagesSurplusWeight -= first_weight;
+ } else {
+ // 续重
+ continuous_weight_count++;
+ weight -= continuous_weight;
+ packagesSurplusWeight -= continuous_weight;
+ }
+ if (logRun) logArr.push({
+ "总重量剩余": weight,
+ "当前包裹重量剩余": packagesSurplusWeight,
+ "当前第几个包裹": first_weight_count,
+ "续重计算次数": continuous_weight_count
+ });
+
+ if (packagesSurplusWeight <= 0) {
+ // 需要增加一个新的包裹
+ first_weight_key = false; // 新包裹设置没有减过首重
+ }
+ }
+ if (logRun) console.log(JSON.stringify(logArr));
+ let total_amount = first_weight_price * first_weight_count + continuous_weight_price * continuous_weight_count;
+ let res = {
+ weight: originalWeight, // 商品重量(KG)
+ first_weight, // 首重步长
+ first_weight_price, // 首重单价
+ first_weight_count, // 首重计算次数
+ continuous_weight, // 续重步长
+ continuous_weight_price, // 续重单价
+ continuous_weight_count, // 续重计算次数
+ first_weight_amount: first_weight_count * first_weight_price, // 首重总金额
+ continuous_weight_amount: continuous_weight_price * continuous_weight_count, // 续重总金额
+ total_amount, // 最终运费金额
+ formula: `${first_weight_price} * ${first_weight_count} + ${continuous_weight_price} * ${continuous_weight_count} = ${total_amount}`, // 运费计算公式
+ };
+ return res;
+};
+
+
+/**
+ * 从一个对象中取多个属性,并生成一个全新的对象,会过滤空字符串,空数组,空对象
+ * @param {Object} obj 对象
+ * @param {Array} keys 键名数组
+ * vk.pubfn.getNewObject(obj, keys);
+ */
+pubfn.getNewObject = function(obj, keys) {
+ let selectedObj = pubfn.copyObject(obj);
+ let newObject = {};
+ if (keys && keys.length > 0) {
+ for (let i in keys) {
+ let key = keys[i];
+ if (pubfn.isNotNull(selectedObj[key])) {
+ newObject[key] = selectedObj[key];
+ }
+ }
+ } else {
+ newObject = selectedObj;
+ }
+ return newObject;
+};
+
+/**
+ * 对象删除指定的字段,返回新的对象
+ * @param {Object} data 操作对象
+ * @param {Array} deleteKeys 需要删除的键名(数组形式)
+ * vk.pubfn.deleteObjectKeys(data, deleteKeys);
+ */
+pubfn.deleteObjectKeys = function(data, deleteKeys = []) {
+ let newData = {};
+ if (data) {
+ for (let key in data) {
+ if (deleteKeys.indexOf(key) == -1) {
+ newData[key] = data[key];
+ }
+ }
+ }
+ return newData;
+}
+
+/**
+ * 数组结构转树形结构
+ * @param {Array} treeData 数据源
+ * @param {Object} treeProps 树结构配置
+ * { id:"_id", parent_id:"parent_id", children:"children",need_field:["_id","name"],deleteParentId:true }
+ * vk.pubfn.arrayToTree(treeData, treeProps);
+ */
+pubfn.arrayToTree = pubfn.treeUtil.arrayToTree;
+/**
+ * 树形结构转数组结构
+ * @param {Array} treeData 数据源
+ * @param {Object} treeProps 树结构配置
+ * { id:"_id", parent_id:"parent_id", children:"children", deleteChildren:true }
+ * vk.pubfn.treeToArray(treeData, treeProps);
+ */
+pubfn.treeToArray = pubfn.treeUtil.treeToArray;
+
+/**
+ * 通配符匹配
+ * @param {String} text 被匹配的文本
+ * @param {String} expText 通配符规则
+ * vk.pubfn.wildcardTestOne(text, expText);
+ */
+pubfn.wildcardTestOne = function(text, expText) {
+ if (!expText) return false;
+ let regExpText = expText.replace(new RegExp("\\*"), "(.*)");
+ let startText = expText.indexOf("*") !== 0 ? "^" : "";
+ let endText = expText[expText.length - 1] !== "*" ? "$" : "";
+ let regExp = new RegExp(startText + regExpText + endText);
+ return regExp.test(text);
+};
+/**
+ * 通配符匹配 expText支持数组
+ * @param {String} text 被匹配的文本
+ * @param {String | Array} expText 通配符规则
+ * vk.pubfn.wildcardTest(text, expText);
+ */
+pubfn.wildcardTest = function(text, expText) {
+ let matchNum = 0; // 被匹配的次数
+ let regExp1 = new RegExp("\\*");
+ if (typeof expText === "string") {
+ // 字符串
+ if (pubfn.wildcardTestOne(text, expText)) {
+ matchNum++;
+ }
+ } else if (typeof expText === "object") {
+ // 数组
+ for (let i = 0; i < expText.length; i++) {
+ let expTextItem = expText[i];
+ if (pubfn.wildcardTestOne(text, expTextItem)) {
+ matchNum++;
+ }
+ }
+ }
+ return matchNum;
+}
+
+/**
+ * 正则匹配
+ * @param {String} text 被匹配的文本
+ * @param {String} expText 正则表达式规则
+ * vk.pubfn.regExpTestOne(text, expText);
+ */
+pubfn.regExpTestOne = function(text, expText) {
+ if (!expText) return false;
+ let regExp = new RegExp(expText);
+ return regExp.test(text);
+};
+
+/**
+ * 正则匹配
+ * @param {String} text 被匹配的文本
+ * @param {String || Array} wildcardExp 正则表达式规则
+ * vk.pubfn.regExpTest(text, regExp);
+ */
+pubfn.regExpTest = function(text, expText) {
+ let matchNum = 0; // 被匹配的次数
+ if (typeof expText === "string") {
+ // 字符串
+ if (pubfn.regExpTestOne(text, expText)) {
+ matchNum++;
+ }
+ } else if (typeof expText === "object") {
+ // 数组
+ for (let i = 0; i < expText.length; i++) {
+ let expTextItem = expText[i];
+ if (pubfn.regExpTestOne(text, expTextItem)) {
+ matchNum++;
+ }
+ }
+ }
+ return matchNum;
+}
+
+/**
+ * 产生订单号,不依赖数据库,高并发时性能高(理论上会重复,但概率非常非常低)
+ * @param {String} prefix 前缀
+ * @param {Number} num 位数,建议在25-30之间,默认25
+ * vk.pubfn.createOrderNo();
+ */
+pubfn.createOrderNo = function(prefix = "", num = 25) {
+ // 获取当前时间字符串格式如20200803093000123
+ let fullTime = vk.pubfn.timeFormat(new Date(), "yyyyMMddhhmmss");
+ fullTime = fullTime.substring(2);
+ let randomNum = num - (prefix + fullTime).length;
+ return prefix + fullTime + pubfn.random(randomNum);
+};
+
+const isSnakeCase = new RegExp('_(\\w)', 'g');
+const isCamelCase = new RegExp('[A-Z]', 'g');
+
+function parseObjectKeys(obj, type) {
+ let parserReg;
+ let parser;
+ switch (type) {
+ case 'snake2camel':
+ parser = pubfn.snake2camel
+ parserReg = isSnakeCase
+ break
+ case 'camel2snake':
+ parser = pubfn.camel2snake
+ parserReg = isCamelCase
+ break
+ }
+ for (const key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
+ if (parserReg.test(key)) {
+ const keyCopy = parser(key)
+ obj[keyCopy] = obj[key]
+ delete obj[key]
+ if (Object.prototype.toString.call((obj[keyCopy])) === '[object Object]') {
+ obj[keyCopy] = parseObjectKeys(obj[keyCopy], type)
+ } else if (Array.isArray(obj[keyCopy])) {
+ obj[keyCopy] = obj[keyCopy].map((item) => {
+ return parseObjectKeys(item, type)
+ })
+ }
+ }
+ }
+ }
+ return obj
+}
+/**
+ * 字符串 - 蛇形转驼峰
+ * @param {String} value
+ * vk.pubfn.snake2camel(value);
+ */
+pubfn.snake2camel = function(value) {
+ return value.replace(isSnakeCase, (_, c) => (c ? c.toUpperCase() : ''))
+}
+/**
+ * 字符串 - 驼峰转蛇形
+ * @param {String} value
+ * vk.pubfn.camel2snake(value);
+ */
+pubfn.camel2snake = function(value) {
+ return value.replace(isCamelCase, str => '_' + str.toLowerCase())
+}
+
+/**
+ * 对象内的属性名 - 蛇形转驼峰
+ * @param {Object} obj
+ * vk.pubfn.snake2camelJson(obj);
+ */
+pubfn.snake2camelJson = function(obj) {
+ return parseObjectKeys(obj, 'snake2camel');
+};
+/**
+ * 对象内的属性名 - 驼峰转蛇形
+ * @param {Object} obj
+ * vk.pubfn.camel2snakeJson(obj);
+ */
+pubfn.camel2snakeJson = function(obj) {
+ return parseObjectKeys(obj, 'camel2snake');
+};
+
+/**
+ * 将能转成数字的字符串转数字(支持字符串、对象、数组)
+ * @param {Any} obj
+ * @param {Object} option 哪些格式需要排除
+ * 默认排除
+ * mobile:true 手机号,如 15200000001
+ * idCard:true 身份证,如 330154202109301214
+ * startFrom0:true 第一位是0,且长度大于1的,同时第二位不是.的字符串 如 01,057189101254
+ * maxLength:14 超过此长度的字符串排除
+ * vk.pubfn.string2Number(obj, option);
+ */
+pubfn.string2Number = function(obj, option = {}) {
+ const type = Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
+ switch (type) {
+ case 'string':
+ if (obj && !isNaN(obj)) {
+ let {
+ mobile = true,
+ idCard = true,
+ startFrom0 = true,
+ maxLength = 14,
+ } = option;
+ if (obj.length > maxLength) {
+ return obj;
+ } else if (mobile && pubfn.test(obj, "mobile")) {
+ return obj;
+ } else if (idCard && pubfn.test(obj, "card")) {
+ return obj;
+ } else if (startFrom0 && obj.length > 1 && obj.indexOf("0") === 0 && obj.indexOf(".") !== 1) {
+ return obj;
+ }
+ return Number(obj);
+ } else {
+ return obj;
+ }
+ case 'object':
+ const keys = Object.keys(obj);
+ for (let i = 0; i < keys.length; i++) {
+ const key = keys[i];
+ obj[key] = pubfn.string2Number(obj[key]);
+ }
+ return obj;
+ case 'array':
+ for (let i = 0; i < obj.length; i++) {
+ obj[i] = pubfn.string2Number(obj[i]);
+ }
+ return obj;
+ default:
+ return obj;
+ }
+};
+
+/**
+ * 保留小数
+ * @param {Number} val 原值
+ * @param {Number} precision 精度
+ * vk.pubfn.toDecimal(val, 2);
+ */
+pubfn.toDecimal = function(val, precision = 0) {
+ if (typeof val === "string") val = Number(val);
+ return parseFloat(val.toFixed(precision));
+};
+
+/**
+ * 判断文件url的类型
+ * @param {String} url 文件的url路径
+ * vk.pubfn.getFileType(url);
+ * 返回值为字符串
+ * image 图片
+ * video 视频
+ * audio 音频
+ * other 其他
+ */
+pubfn.getFileType = function(url) {
+ let fileType;
+ if (pubfn.checkFileSuffix(url, ["png", "jpg", "jpeg", "gif", "bmp", "svg"])) {
+ fileType = "image";
+ } else if (pubfn.checkFileSuffix(url, ["avi", "mp4", "3gp", "mov", "rmvb", "rm", "flv", "mkv"])) {
+ fileType = "video";
+ } else if (pubfn.checkFileSuffix(url, ["mp3"])) {
+ fileType = "audio";
+ } else {
+ fileType = "other";
+ }
+ return fileType;
+};
+/**
+ * 获取文件url的后缀名
+ * @param {String} url 文件的url路径,必须带
+ * vk.pubfn.getFileSuffix(url);
+ */
+pubfn.getFileSuffix = function(url) {
+ let suffix;
+ let index = url.lastIndexOf(".");
+ if (index > -1) {
+ suffix = url.substring(index + 1);
+ }
+ return suffix;
+};
+
+/**
+ * 判断文件url是否在指定后缀名数组内
+ * @param {String} url 文件的url路径
+ * @param {Array} list 后缀名列表
+ * vk.pubfn.checkFileSuffix(url,["png", "jpg", "jpeg", "gif", "bmp", "svg"]);
+ */
+pubfn.checkFileSuffix = function(url, list) {
+ let key = false;
+ let suffix = pubfn.getFileSuffix(url);
+ for (let i = 0; i < list.length; i++) {
+ if (list.indexOf(suffix) > -1) {
+ key = true;
+ break;
+ }
+ }
+ return key;
+};
+// 前端专属开始 -----------------------------------------------------------
+/**
+ * 将时间显示成1秒前、1天前
+ * @description 主要用于 文章最后回复时间: 1分钟前
+ * @param {String || Number} startTime 需要计算的时间 如文章最后回复时间
+ * vk.pubfn.dateDiff(startTime);
+ */
+pubfn.dateDiff = function(startTime, suffix = "前") {
+ if (!startTime) {
+ return "";
+ }
+ if (typeof startTime === "string" && !isNaN(startTime)) startTime = Number(startTime);
+ if (typeof startTime == "number") {
+ if (startTime.toString().length == 10) startTime *= 1000;
+ startTime = new Date(startTime);
+ startTime = pubfn.timeFormat(startTime);
+ }
+ if (typeof startTime == "string") {
+ startTime = startTime.replace("T", " ");
+ startTime = startTime;
+ startTime = new Date(startTime.replace(/-/g, "/")); //将-转化为/,使用new Date
+ }
+ let endTime = new Date(); //获取当前时间
+ let nd = 1000 * 24 * 60 * 60; //一天的毫秒数
+ let nh = 1000 * 60 * 60; //一小时的毫秒数
+ let nm = 1000 * 60; //一分钟的毫秒数
+ let ns = 1000; //一秒钟的毫秒数long diff;try {
+ let diff = endTime.getTime() - startTime.getTime();
+ let day = Math.floor(diff / nd); //计算差多少天
+ let hour = Math.floor(diff % nd / nh); //计算差多少小时
+ let min = Math.floor(diff % nd % nh / nm); //计算差多少分钟
+ let sec = Math.round(diff % nd % nh % nm / ns); //计算差多少秒//输出结果
+ let showStr = "1 秒";
+ if (day > 0) {
+ showStr = day + "天";
+ } else if (hour > 0) {
+ showStr = hour + "小时";
+ } else if (min > 0) {
+ showStr = min + "分钟";
+ } else if (sec > 0) {
+ showStr = sec + "秒";
+ }
+ showStr += suffix;
+ return showStr;
+}
+/**
+ * 将时间显示成1秒、1天
+ * @description 主要用于 到期时间剩余 : 3天 这样的场景
+ * @param {String || Number} endTime 需要计算的时间 如到期时间
+ * vk.pubfn.dateDiff2(endTime);
+ */
+pubfn.dateDiff2 = function(startTime, str = "1秒") {
+ if (!startTime) {
+ return "";
+ }
+ if (typeof startTime === "string" && !isNaN(startTime)) startTime = Number(startTime);
+ if (typeof startTime == "number") {
+ if (startTime.toString().length == 10) startTime *= 1000;
+ startTime = new Date(startTime);
+ startTime = pubfn.timeFormat(startTime);
+ }
+ if (typeof startTime == "string") {
+ startTime = startTime.replace("T", " ");
+ startTime = startTime;
+ startTime = new Date(startTime.replace(/-/g, "/")); //将-转化为/,使用new Date
+ }
+ let endTime = new Date(); //获取当前时间
+ let nd = 1000 * 24 * 60 * 60; //一天的毫秒数
+ let nh = 1000 * 60 * 60; //一小时的毫秒数
+ let nm = 1000 * 60; //一分钟的毫秒数
+ let ns = 1000; //一秒钟的毫秒数long diff;try {
+ let diff = startTime.getTime() - endTime.getTime();
+ let day = Math.floor(diff / nd);
+ let hour = Math.floor(diff % nd / nh);
+ let min = Math.floor(diff % nd % nh / nm);
+ let sec = Math.round(diff % nd % nh % nm / ns);
+ let showStr = str;
+ if (day > 0) {
+ showStr = day + "天";
+ } else if (hour > 0) {
+ showStr = hour + "小时";
+ } else if (min > 0) {
+ showStr = min + "分钟";
+ } else if (sec > 0) {
+ showStr = sec + "秒";
+ }
+ return showStr;
+};
+/**
+ * 将大数字转中文
+ * @description 主要用于展示浏览量等不需要非常精确显示的场景
+ * 如:
+ * 3210 -> 3千
+ * 31210 -> 3万
+ * 1523412 -> 1百万
+ * 15234120 ->1千万
+ * @param {Number} n 需要转换的数字
+ * vk.pubfn.numStr(n);
+ */
+pubfn.numStr = function(n) {
+ if (typeof n == "string") {
+ n = parseFloat(n);
+ }
+ let str = n;
+ if (n < 1000) {
+ str = n;
+ } else if (n < 10000) {
+ let n1 = Math.floor(n / 100);
+ str = n1 / 10 + "千"
+ } else if (n < 1000000) {
+ let n1 = Math.floor(n / 1000);
+ str = n1 / 10 + "万"
+ } else if (n < 10000000) {
+ let n1 = Math.floor(n / 1000000);
+ str = n1 + "百万"
+ } else if (n < 100000000) {
+ let n1 = Math.floor(n / 10000000);
+ str = n1 + "千万"
+ } else if (n >= 100000000) {
+ let n1 = Math.floor(n / 10000000);
+ str = n1 / 10 + "亿"
+ }
+ return str;
+};
+/**
+ * 金额显示过滤器(已分为单位,将100 转成 1)
+ * @param {Number} money 金额
+ * vk.pubfn.priceFilter(money);
+ */
+pubfn.priceFilter = function(money, defaultValue = "") {
+ if (pubfn.isNull(money)) {
+ return defaultValue;
+ }
+ if (isNaN(money)) {
+ return money;
+ }
+ if (typeof money == "string") {
+ money = parseFloat(money);
+ }
+ return (money / 100).toFixed(2);
+};
+// 金额过滤器 - 只显示小数点左边
+pubfn.priceLeftFilter = function(n) {
+ let s = "";
+ if (n) {
+ s = pubfn.priceFilter(n).split(".")[0];
+ }
+ return s;
+};
+// 金额过滤器 - 只显示小数点右边
+pubfn.priceRightFilter = function(n) {
+ let s = "";
+ if (n) {
+ s = pubfn.priceFilter(n).split(".")[1];
+ }
+ return s;
+};
+/**
+ * 百分比过滤器 将 0.01 显示成 1% 1 显示成 100%
+ * @param {Number} value 百分比值
+ * @param {Boolean} needShowSymbol 显示 % 这个符号
+ * @param {String | Number} defaultValue value为空时的默认值
+ * vk.pubfn.percentageFilter(money);
+ */
+pubfn.percentageFilter = function(value, needShowSymbol = true, defaultValue = "") {
+ if (pubfn.isNull(value)) {
+ return defaultValue;
+ }
+ if (isNaN(value)) {
+ return value;
+ }
+ if (typeof value == "string") {
+ value = parseFloat(value);
+ }
+ value = parseFloat((value * 100).toFixed(2));
+ if (needShowSymbol) {
+ value += "%";
+ }
+ return value;
+};
+/**
+ * 折扣过滤器 将 0.1 显示成 1折 1 显示成 原价 0 显示成免费
+ * @param {Number} value 折扣值
+ * @param {Boolean} needShowSymbol 显示 折 这个中文字符
+ * @param {String | Number} defaultValue value为空时的默认值
+ * vk.pubfn.discountFilter(value);
+ */
+pubfn.discountFilter = function(value, needShowSymbol = true, defaultValue = "") {
+ if (pubfn.isNull(value)) {
+ return defaultValue;
+ }
+ if (isNaN(value)) {
+ return value;
+ }
+ if (typeof value == "string") {
+ value = parseFloat(value);
+ }
+ value = parseFloat((value * 10).toFixed(2));
+ if (value > 10) {
+ return "折扣不可以大于原价";
+ }
+ if (value == 10) {
+ return "原价";
+ }
+ if (value == 0) {
+ return "免费";
+ }
+ if (value < 0) {
+ return "折扣不可以小于0";
+ }
+ if (needShowSymbol) {
+ value += " 折";
+ }
+ return value;
+};
+/**
+ * 将字符串格式的时间转为时间戳
+ * @param {String} dateString 格式为:2020-08-08 12:12:12
+ */
+pubfn.toTimeLong = function(dateString) {
+ if (!dateString) {
+ return "";
+ }
+ dateString = dateString.substring(0, 19);
+ dateString = dateString.replace(new RegExp(/-/, "g"), '/');
+ let time = new Date(dateString).getTime();
+ if (isNaN(time)) {
+ time = "";
+ }
+ return time;
+};
+
+/**
+ * 单位进制换算
+ * length 换算前大小
+ * arr 进制的数组,如["B","KB","MB","GB"]
+ * ary 进制,如KB-MB-GB,进制1024
+ * precision 数值精度
+ * vk.pubfn.calcSize(length,["B","KB","MB","GB"],1024,3);
+ */
+pubfn.calcSize = function(length = 0, arr, ary, precision = 2, showType = "auto") {
+ length = parseFloat(length);
+ let size = 0;
+ let type = "";
+ if (length < ary || arr.length <= 1) {
+ type = arr[0];
+ size = parseFloat(length.toFixed(precision));
+ } else {
+ for (let i = 1; i < arr.length; i++) {
+ let currentType = arr[i];
+ length = length / ary;
+ if (showType === "auto") {
+ if (length < ary) {
+ type = currentType;
+ size = parseFloat(length.toFixed(precision));
+ break;
+ }
+ } else {
+ if (showType === currentType) {
+ type = currentType;
+ size = parseFloat(length.toFixed(precision));
+ break;
+ }
+ }
+ }
+ }
+ return {
+ size: size,
+ type: type,
+ title: size + " " + type
+ }
+};
+
+/**
+ * 将一个大数组拆分成N个小数组(分割数组)
+ * @param {Array} array 大数组
+ * @param {Number} size 小数组每组最大多少个
+ * 代码示例
+ * let newArray = vk.pubfn.splitArray(array, 2);
+ */
+pubfn.splitArray = function(array, size) {
+ let data = [];
+ for (let i = 0; i < array.length; i += size) {
+ data.push(array.slice(i, i + size))
+ }
+ return data
+};
+
+/**
+ * 将对象内的属性按照ASCII字符顺序进行排序,返回排序后的对象
+ * @param {Object} obj 需要排序对象
+ * 代码示例
+ * let newObj = vk.pubfn.objectKeySort(obj);
+ */
+pubfn.objectKeySort = function(obj) {
+ let keys = Object.keys(obj).sort();
+ let newObject = {};
+ for (let i in keys) {
+ newObject[keys[i]] = (obj[keys[i]]);
+ }
+ return newObject;
+};
+
+// 以下是前端专属API-----------------------------------------------------------
+
+/**
+ * 手机端长列表分页加载数据 2.0版本
+ * @param {Vue页面对象} that 页面数据对象this
+ * @param {String} url 请求地址(云函数路径)
+ * @param {String} listName 后端返回的list数组的字段名称,默认rows(二选一即可)
+ * @param {String} listKey 后端返回的list数组的字段名称,默认rows(二选一即可)
+ * @param {String} formKey 表单请求的对象数据源字段名称,默认queryForm1
+ * @param {Object} data 额外数据
+ * @param {function} dataPreprocess 数据预处理函数
+ *
+ * 代码示例
+ vk.pubfn.getListData2({
+ that : this,
+ url : "template/db_api/pub/select",
+ data : {
+ a : 1
+ },
+ dataPreprocess : function(list){
+ return list;
+ }
+ });
+ */
+pubfn.getListData2 = function(obj = {}) {
+ let vk = uni.vk;
+ let {
+ that,
+ listName,
+ listKey = "rows",
+ formKey = "queryForm1",
+ url,
+ dataPreprocess,
+ idKeyName = "_id"
+ } = obj;
+ if (listName) listKey = listName;
+ /**
+ * 2.0与1.0的区别
+ * 2.0使用的queryForm1作为查询,而1.0是form1
+ * 2.0云函数端是getTableData,而1.0是selects
+ */
+ let queryForm1 = that[formKey] || that.queryForm1 || that.queryForm;
+ // 标记为请求中
+ that.loading = true;
+ let hasMore = true;
+ if (queryForm1.pagination.pageIndex === 1) {
+ that.firstLoading = true;
+ }
+ vk.callFunction({
+ url: url,
+ data: queryForm1,
+ success: function(data) {
+ let list = data[listKey] || [];
+ // 数据预处理
+ if (typeof dataPreprocess == "function") {
+ list = dataPreprocess(list);
+ }
+ if (queryForm1.pagination.pageIndex > 1) {
+ // 翻页
+ if (list.length == 0) {
+ // 无数据时
+ hasMore = false;
+ queryForm1.pagination.pageIndex--;
+ list = that.data.list;
+ } else {
+ // 有数据时
+ if (list.length < queryForm1.pagination.pageSize) {
+ hasMore = false;
+ }
+ // 数据合并
+ list = vk.pubfn.arr_concat(that.data.list, list, idKeyName);
+ }
+ } else if (queryForm1.pagination.pageIndex == 1) {
+ // 第一页
+ if (list.length < queryForm1.pagination.pageSize) {
+ hasMore = false;
+ }
+ if (list.length == 0) {
+ that.state.isEmpty = true;
+ } else {
+ that.state.isEmpty = false;
+ }
+ }
+ // 如果后端返回了hasMore,则使用后端的hasMore值
+ if (typeof data.hasMore !== "undefined") {
+ hasMore = data.hasMore;
+ }
+ data = {
+ ...data,
+ total: data.total,
+ list: list,
+ hasMore: hasMore,
+ pageIndex: data.pageIndex,
+ pageSize: data.pageSize
+ };
+ that.state.loadmore = hasMore ? "loadmore" : "nomore"; // 更新状态
+ that.data = vk.pubfn.objectAssign(that.data, data); // 更新数据
+ if (typeof obj.success == "function") obj.success(data);
+ },
+ fail: function(err) {
+ that.state.loadmore = "loadmore";
+ if (queryForm1.pagination.pageIndex > 1) {
+ queryForm1.pagination.pageIndex--;
+ }
+ if (typeof obj.fail == "function") {
+ obj.fail(data);
+ } else if (err && err.msg) {
+ vk.toast(err.msg, "none");
+ }
+ },
+ complete: function(res) {
+ that.loading = false;
+ if (queryForm1.pagination.pageIndex === 1) {
+ that.state.firstLoading = false;
+ }
+ if (typeof obj.complete == "function") obj.complete(res);
+ }
+ });
+};
+
+/**
+ * 手机端长列表分页加载数据(1.0版本)
+ * @param {Vue页面对象} that 页面数据对象this
+ * @param {String} url 请求地址(云函数路径)
+ * @param {String} listName 后端返回的list数组的字段名称,默认rows
+ * @param {String} listKey 后端返回的list数组的字段名称,默认rows
+ * @param {String} formKey 表单请求的对象数据源字段名称,默认form1
+ * @param {Object} data 额外数据
+ * @param {function} dataPreprocess 数据预处理函数
+ *
+ * 代码示例
+ vk.pubfn.getListData({
+ that : this,
+ url : "template/db_api/pub/select",
+ listKey : "rows",
+ formKey : "form1",
+ data : {
+ a : 1
+ },
+ dataPreprocess : function(list){
+ return list;
+ }
+ });
+ */
+pubfn.getListData = function(obj = {}) {
+ let {
+ that,
+ listName,
+ listKey = "rows",
+ formKey = "form1",
+ url,
+ dataPreprocess,
+ loading
+ } = obj;
+ let vk = uni.vk;
+ if (listName) listKey = listName;
+ let { data = {} } = that;
+ let form1 = that[formKey] || {};
+ let { pageKey = true } = data;
+ if (!form1.pageIndex) form1.pageIndex = 1;
+ if (!form1.pageSize) form1.pageSize = 20;
+ let addTime = form1.addTime;
+ let endTime = form1.endTime;
+ if (endTime) endTime += " 23:59:59";
+ if (!pageKey && form1.pageIndex > 1) {
+ form1.pageIndex--;
+ return false;
+ }
+
+ if (addTime) form1.addTimeLong = pubfn.toTimeLong(addTime);
+ if (endTime) form1.endTimeLong = pubfn.toTimeLong(endTime);
+ if (obj.data && JSON.stringify(obj.data) != "{}") {
+ pubfn.objectAssign(form1, obj.data);
+ }
+ let title = obj.title;
+ if (typeof obj.title == "undefined" && !loading) {
+ title = form1.pageIndex == 1 ? "请求中..." : "";
+ }
+ vk.callFunction({
+ url: url,
+ data: form1,
+ title: title,
+ loading: loading,
+ success: function(data) {
+ let list = data[listKey] || [];
+ // 数据预处理
+ if (typeof dataPreprocess == "function") {
+ list = dataPreprocess(list);
+ }
+ if (form1.pageIndex > 1) {
+ // 翻页
+ if (list.length == 0) {
+ // 无数据时
+ pageKey = false;
+ form1.pageIndex--;
+ list = that.data.list;
+ } else {
+ // 有数据时
+ if (list.length < form1.pageSize) {
+ pageKey = false;
+ }
+ let oldList = that.data.list;
+ // 数据合并
+ list = pubfn.arr_concat(oldList, list, "_id");
+ }
+ } else if (form1.pageIndex == 1) {
+ if (list.length < form1.pageSize) {
+ pageKey = false;
+ }
+ }
+ //console.log(pageKey,list.length,form1.pageSize);
+ data = {
+ ...data,
+ total: data.total,
+ list: list,
+ pageKey: pageKey,
+ loadmore: pageKey ? "loadmore" : "nomore" // 更新状态
+ };
+ that.data = pubfn.objectAssign(that.data, data); // 更新数据
+ if (typeof obj.success == "function") obj.success(data);
+ },
+ fail: function(err) {
+ if (form1.pageIndex > 1) { form1.pageIndex--; }
+ if (typeof obj.fail == "function") {
+ obj.fail(data);
+ } else if (err && err.msg) {
+ vk.toast(err.msg, "none");
+ }
+ },
+ complete: function(res) {
+ if (typeof obj.complete == "function") obj.complete(res);
+ },
+ });
+};
+
+/**
+ * 动态组件数据获取
+ * @description 主要用于动态组件的数据获取
+ * @param {Vue页面对象} that 页面数据对象this
+ * @param {String} ids 动态数据组件的ID
+ *
+ * 代码示例
+ * 如:放置一个动态数据的 公告组件 和 一个轮播图组件
+ * view 核心:自定义组件接收一个 Object 类型的属性 datas
+
+
+ 在页面数据变量中新增 componentsDynamic
+ data() {
+ return {
+ // 动态组件数据集合
+ componentsDynamic:{}
+ }
+ }
+ 在页面初始化方法中执行下面的函数
+ this.vk.pubfn.getComponentsDynamicData({
+ that : this,
+ ids : ["notice-bar-01","index-swiper-01"]
+ });
+ */
+pubfn.getComponentsDynamicData = function(obj = {}) {
+ let {
+ that,
+ keyName = "componentsDynamic",
+ title,
+ url = "plugs/components_dynamic/client/pub/getComponentsDynamicData",
+ ids
+ } = obj;
+ let vk = uni.vk;
+ let form1 = {
+ ids: ids
+ };
+ if (obj.data && JSON.stringify(obj.data) != "{}") {
+ pubfn.objectAssign(form1, obj.data);
+ }
+ // 读取缓存开始-----------------------------------------------------------
+ let cacheKey = "pub-componentsDynamic";
+ let cacheData = uni.getStorageSync(cacheKey) || {};
+ let cacheDataKey = JSON.stringify(ids);
+ if (cacheData[cacheDataKey]) {
+ // 渲染本地数据
+ that[keyName] = cacheData[cacheDataKey];
+ }
+ // 读取缓存结束-----------------------------------------------------------
+ vk.callFunction({
+ url: url,
+ data: form1,
+ title: title,
+ success: function(data) {
+ if (JSON.stringify(cacheData[cacheDataKey]) !== JSON.stringify(data.componentsDynamic)) {
+ // 渲染服务器数据
+ that[keyName] = data.componentsDynamic;
+ // 同时将组件数据进行缓存
+ cacheData[cacheDataKey] = data.componentsDynamic;
+ uni.setStorageSync(cacheKey, cacheData);
+ }
+ if (typeof obj.success == "function") obj.success(data);
+ },
+ fail: function(err) {
+ console.error(err);
+ if (typeof obj.fail == "function") obj.fail(data);
+ },
+ complete: function() {
+ if (typeof obj.complete == "function") obj.complete(data);
+ },
+ });
+};
+
+/**
+ * 将../../ 形式的页面相对路径 转成 页面绝对路径
+ * @param {String} url 需要转换的url
+ * vk.pubfn.getPageFullPath(url);
+ */
+pubfn.getPageFullPath = function(url) {
+ let fullPath = url;
+ if (fullPath.indexOf("/") !== 0) {
+ if (fullPath.indexOf("./") === 0) {
+ //fullPath = "." + fullPath;
+ fullPath = fullPath.substring(2);
+ }
+ let urlSplit = fullPath.split("../");
+ // 向上目录级数,0:根目录 1:向上1级
+ let level = urlSplit.length;
+ // 尾部路径
+ let urlEnd = urlSplit[level - 1];
+ // 获取当前页面的页面全路径
+ let pages = getCurrentPages();
+ let currentPage = pages[pages.length - 1];
+ let currentPagePath = currentPage.route;
+ // 分割成目录,最后一段是页面名称
+ let urlArr = currentPagePath.split("/");
+ let urlSplicing = "";
+ // 开始拼接
+ for (let i = 0; i < urlArr.length - level; i++) {
+ urlSplicing += urlArr[i] + "/";
+ }
+ // 完整页面路径
+ fullPath = urlSplicing + urlEnd;
+ if (fullPath.indexOf("/") != 0) {
+ fullPath = "/" + fullPath;
+ }
+ }
+ return fullPath;
+};
+/**
+ * 获取平台信息
+ * let platform = vk.pubfn.getPlatform();
+ */
+pubfn.getPlatform = function() {
+ let platform;
+ // #ifdef APP-PLUS || APP-NVUE || APP-PLUS-NVUE
+ platform = "app-plus";
+ // #endif
+ // #ifdef H5
+ platform = "h5";
+ // #endif
+ // #ifdef MP-WEIXIN
+ platform = "mp-weixin";
+ // #endif
+ // #ifdef MP-ALIPAY
+ platform = "mp-alipay";
+ // #endif
+ // #ifdef MP-BAIDU
+ platform = "mp-baidu";
+ // #endif
+ // #ifdef MP-TOUTIAO
+ platform = "mp-toutiao";
+ // #endif
+ // #ifdef MP-QQ
+ platform = "mp-qq";
+ // #endif
+ // #ifdef MP-360
+ platform = "mp-360";
+ // #endif
+ // #ifdef MP-KUAISHOU
+ platform = "mp-toutiao";
+ // #endif
+ return platform;
+};
+/**
+ * 获取当前页面实例
+ * 返回数据
+ * fullPath 当前打开页面的完整路径(带页面参数)
+ * pagePath 当前打开页面的路径(不含参数)
+ * options 当前打开页面的参数
+ * route 当前打开页面路由地址
+ * $vm 当前打开页面的vue实例
+ * vk.pubfn.getCurrentPage();
+ */
+pubfn.getCurrentPage = function() {
+ let res = {};
+ let pages = getCurrentPages();
+ let page = pages[pages.length - 1];
+ if (page.route.indexOf("/") == 0) page.route = page.route.substring(1);
+ let pagePath = `/${page.route}`;
+ let fullPath = `/${page.route}`;
+ let options = page.options;
+ if (page.$page) {
+ if (typeof page.$page.fullPath !== "undefined") {
+ fullPath = page.$page.fullPath;
+ } else if (typeof options === "object") {
+ let optionsStr = pubfn.queryParams(options);
+ fullPath = pagePath + optionsStr;
+ }
+ }
+ res.fullPath = fullPath;
+ res.pagePath = pagePath;
+ res.options = options;
+ res.route = page.route;
+ res.$vm = page.$vm;
+ return res;
+};
+/**
+ * 获取当前页面路由
+ * vk.pubfn.getCurrentPageRoute();
+ */
+pubfn.getCurrentPageRoute = function(removeSlash) {
+ let pages = getCurrentPages();
+ let page = pages[pages.length - 1];
+ if (removeSlash) {
+ return page.route;
+ } else {
+ return "/" + page.route;
+ }
+};
+/**
+ * 文件转base64
+
+方式一
+
+vk.pubfn.fileToBase64({
+ file:res.tempFiles[0],
+ success:function(base64){
+
+ }
+});
+
+方式二
+
+vk.pubfn.fileToBase64({ file }).then(base64 => {
+
+});
+ */
+pubfn.fileToBase64 = function(obj = {}) {
+ let { file } = obj;
+ let filePath = typeof file === "object" ? file.path : file;
+ return new Promise(function(resolve, reject) {
+ // #ifdef H5
+ let reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.onload = function(res) {
+ let base64 = this.result;
+ if (base64.indexOf(";base64,") == -1) {
+ base64 = "data:image/jpeg;base64," + base64;
+ }
+ if (obj.success) obj.success(base64);
+ if (obj.complete) obj.complete(base64);
+ resolve(base64);
+ };
+ reader.onerror = function(err) {
+ if (obj.fail) obj.fail(err);
+ if (obj.complete) obj.complete(err);
+ reject(err);
+ };
+ // #endif
+ // #ifdef MP
+ uni.getFileSystemManager().readFile({
+ filePath: filePath,
+ encoding: "base64",
+ success: function(res) {
+ let base64 = res.data;
+ if (base64.indexOf(";base64,") == -1) {
+ base64 = "data:image/jpeg;base64," + base64;
+ }
+ if (obj.success) obj.success(base64);
+ if (obj.complete) obj.complete(base64);
+ resolve(base64);
+ },
+ fail: function(err) {
+ if (obj.fail) obj.fail(err);
+ reject(err);
+ },
+ complete: obj.complete
+ });
+ // let base64 = uni.getFileSystemManager().readFileSync(file.path, 'base64');
+ // if(obj.success) obj.success(base64);
+ // if(obj.complete) obj.complete(base64);
+ // resolve(base64);
+ // #endif
+ // #ifdef APP-PLUS
+ plus.io.resolveLocalFileSystemURL(pubfn.getLocalFilePath(filePath), function(entry) {
+ entry.file(function(file) {
+ let fileReader = new plus.io.FileReader();
+ fileReader.onload = function(data) {
+ if (obj.success) obj.success(data.target.result);
+ if (obj.complete) obj.complete(data.target.result);
+ resolve(data.target.result);
+ }
+ fileReader.onerror = function(err) {
+ if (obj.fail) obj.fail(err);
+ reject(err);
+ }
+ fileReader.readAsDataURL(file)
+ }, function(err) {
+ if (obj.fail) obj.fail(err);
+ reject(err);
+ })
+ }, function(err) {
+ if (obj.fail) obj.fail(err);
+ reject(err);
+ })
+ // #endif
+ });
+};
+
+/**
+ * base64转文件
+方式一
+
+vk.pubfn.base64ToFile({
+ base64:base64,
+ success:function(file){
+
+ }
+});
+
+方式二
+
+vk.pubfn.base64ToFile({ base64 }).then(file => {
+
+});
+ */
+pubfn.base64ToFile = function(obj = {}) {
+ let {
+ base64 = "",
+ filePath
+ } = obj;
+ let extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/);
+ if (extName) {
+ extName = extName[1];
+ } else {
+ reject(new Error('base64 error'));
+ }
+ if (!filePath) {
+ filePath = pubfn.random(32, "abcdefghijklmnopqrstuvwxyz0123456789") + '.' + extName;
+ }
+ let index = base64.indexOf("base64,");
+ let base64Data = base64;
+ if (index > -1) {
+ base64Data = base64.substring(base64.indexOf("base64,") + 7);
+ }
+ let savePath;
+ return new Promise(function(resolve, reject) {
+ // #ifdef MP
+ savePath = wx.env.USER_DATA_PATH + '/' + filePath;
+ let fs = uni.getFileSystemManager();
+ fs.writeFile({
+ filePath: savePath,
+ data: base64Data,
+ encoding: "base64",
+ success: function(res) {
+ let file = {
+ path: savePath,
+ lastModifiedDate: new Date(),
+ name: filePath
+ };
+ if (obj.success) obj.success(file);
+ resolve(file);
+ },
+ fail: function(res) {
+ if (obj.fail) obj.fail(res);
+ reject(res);
+ },
+ complete: obj.complete
+ });
+ // #endif
+ // #ifdef H5
+ savePath = filePath;
+ let blob = pubfn.base64toBlob(base64);
+ let file = pubfn.blobToFile(blob, savePath);
+ if (obj.success) obj.success(file);
+ if (obj.complete) obj.complete(file);
+ resolve(file);
+ // #endif
+ // #ifdef APP-PLUS
+ let fileName = filePath;
+ let basePath = '_user_resources';
+ let dirPath = 'vk_temp';
+ savePath = basePath + '/' + dirPath + '/' + fileName;
+ let bitmap = new plus.nativeObj.Bitmap(fileName);
+ bitmap.loadBase64Data(base64, function() {
+ bitmap.save(savePath, {}, function() {
+ bitmap.clear();
+ let file = {
+ path: savePath,
+ lastModifiedDate: new Date(),
+ name: filePath
+ };
+ if (obj.success) obj.success(file);
+ if (obj.complete) obj.complete(file);
+ resolve(file);
+ }, function(error) {
+ bitmap.clear();
+ if (obj.fail) obj.fail(error);
+ reject(error);
+ })
+ }, function(error) {
+ bitmap.clear();
+ if (obj.fail) obj.fail(error);
+ reject(error);
+ })
+ // #endif
+ });
+};
+/**
+ * 将base64转换为blob (H5独有)
+ vk.pubfn.base64toBlob(base64);
+ */
+pubfn.base64toBlob = function(base64) {
+ let arr = base64.split(',');
+ let mime = arr[0].match(/:(.*?);/)[1];
+ let bstr = atob(arr[1]);
+ let n = bstr.length;
+ let u8arr = new Uint8Array(n);
+ while (n--) {
+ u8arr[n] = bstr.charCodeAt(n);
+ }
+ return new Blob([u8arr], { type: mime });
+};
+/**
+ * //将blob转换为file
+ vk.pubfn.blobToFile(base64);
+ */
+pubfn.blobToFile = function(blob, fileName) {
+ blob.lastModifiedDate = new Date();
+ blob.name = fileName;
+ blob.path = URL.createObjectURL(blob);
+ return blob;
+};
+
+/**
+ * 小程序订阅消息 前端无需再写 #ifdef MP-WEIXIN
+ vk.pubfn.requestSubscribeMessage({
+ tmplIds: ['NcspDBQpH6CGHos3mMADrrQpEv2gHmtfOPa5KTLs92E']
+ });
+ */
+pubfn.requestSubscribeMessage = function(obj) {
+ // #ifdef MP-WEIXIN
+ return uni.requestSubscribeMessage(obj);
+ // #endif
+};
+
+/**
+ * 检测是否需要登录 此方法目前为测试版
+ * vk.pubfn.checkLogin();
+ */
+pubfn.checkLogin = function(obj = {}) {
+ let vk = uni.vk;
+ let loginUrl = vk.getConfig("login.url");
+ try {
+ let url;
+ try {
+ url = obj.url || vk.pubfn.getCurrentPageRoute();
+ } catch (err) {
+ url = vk.getConfig("index.url") || "/pages/index/index";
+ }
+ vk.navigate.checkNeedLogin({
+ url: url,
+ success: function(res) {
+ if (res.needLogin) {
+ // 记录下原本要跳转的页面
+ url = vk.pubfn.getPageFullPath(obj.fullPath || url);
+ vk.navigate.setOriginalPage({ url });
+ if (obj.isOnLaunch) vk.navigate.isOnLaunchToLogin = true; // 标记为首次启动的页面需要登录
+ uni.reLaunch({
+ url: loginUrl,
+ success: () => {
+ // #ifdef MP-WEIXIN
+ setTimeout(() => {
+ uni.hideHomeButton();
+ }, 400);
+ // #endif
+ }
+ });
+ } else {
+ // #ifdef H5
+ // 解决微信公众号登录无法跳回原页面的问题
+ if (!obj.options || !obj.options.code || !obj.options.state) {
+ vk.navigate.setOriginalPage(null);
+ }
+ // #endif
+ // #ifndef H5
+ vk.navigate.setOriginalPage(null);
+ // #endif
+ }
+ }
+ });
+ } catch (err) {
+ console.error("catch", err);
+ uni.reLaunch({
+ url: loginUrl
+ });
+ // #ifdef MP-WEIXIN
+ uni.hideHomeButton();
+ // #endif
+ }
+};
+/**
+ * 获取文件本地路径
+ * @param {Object} path
+ */
+pubfn.getLocalFilePath = function(path) {
+ if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
+ return path
+ }
+ if (path.indexOf('file://') === 0) {
+ return path
+ }
+ if (path.indexOf('/storage/emulated/0/') === 0) {
+ return path
+ }
+ if (path.indexOf('/') === 0 && typeof plus !== "undefined") {
+ let localFilePath = plus.io.convertAbsoluteFileSystem(path)
+ if (localFilePath !== path) {
+ return localFilePath
+ } else {
+ path = path.substr(1)
+ }
+ }
+ return '_www/' + path
+};
+
+/**
+ * 获取当前支持的应用语言
+ * let localeList = vk.pubfn.getLocaleList();
+ */
+pubfn.getLocaleList = function() {
+ let localeList = [
+ { value: "zh-Hans", label: "简体中文" },
+ { value: "zh-Hant", label: "繁體中文" },
+ { value: "en", label: "English" }
+ ];
+ return localeList;
+};
+/**
+ * 获取当前应用语言
+ * let locale = vk.pubfn.getLocale();
+ */
+pubfn.getLocale = function() {
+ let localeValue;
+ if (typeof uni.getLocale === "function") {
+ localeValue = uni.getLocale();
+ } else {
+ localeValue = "zh-Hans"; // 默认中文简体
+ }
+ let localeObj = {
+ "zh_CN": "zh-Hans", // 中国大陆(简体)
+ "zh_HK": "zh-Hant", // 香港(繁体)
+ "zh_MO": "zh-Hant", // 澳门(繁体)
+ "zh_SG": "zh-Hans", // 新加坡(简体)
+ "zh_TW": "zh-Hant", // 台湾(繁体)
+ };
+ if (localeObj[localeValue]) localeValue = localeObj[localeValue];
+ return localeValue;
+};
+/**
+ * 获取当前应用语言
+ * let localeObj = vk.pubfn.getLocaleObject();
+ */
+pubfn.getLocaleObject = function() {
+ let value = pubfn.getLocale();
+ let list = pubfn.getLocaleList();
+ return pubfn.getListItem(list, "value", value);
+};
+/**
+ * 设置当前应用语言
+ */
+pubfn.setLocale = function(...e) {
+ return uni.setLocale(...e);
+};
+
+/**
+ * 将obj2的数据赋值给obj1,并使vue双向绑定(vue2对象新增属性不会双向绑定)
+ * @description 将 obj2 的属性赋值给 obj1 (如果obj1中有对应的属性,则会被obj2的属性值覆盖)
+ * @param {Object} obj1
+ * @param {Object} obj2
+ * @param {Object} that 页面实例
+ * vk.pubfn.objectAssignForVue(obj1, obj2, that);
+ */
+pubfn.objectAssignForVue = function(obj1, obj2, that) {
+ pubfn.objectDeleteInvalid(obj2);
+ for (let key in obj2) {
+ that.$set(obj1, key, obj2[key]);
+ }
+};
+
+// 前端专属结束 -----------------------------------------------------------
+export default pubfn;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/modal.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/modal.js
new file mode 100644
index 0000000..98bd6a5
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/modal.js
@@ -0,0 +1,326 @@
+/**
+ * 函数 - 弹窗
+ */
+import { Message, MessageBox, Loading } from 'element-ui';
+let loadingInstance = null
+const localeObj = {
+ title: {
+ "zh-Hans": "提示",
+ "zh-Hant": "提示",
+ "en": "Tips"
+ },
+ confirmText: {
+ "zh-Hans": "确定",
+ "zh-Hant": "確定",
+ "en": "OK"
+ },
+ cancelText: {
+ "zh-Hans": "取消",
+ "zh-Hant": "取消",
+ "en": "Cancel"
+ },
+ placeholderText: {
+ "zh-Hans": "请输入",
+ "zh-Hant": "請輸入",
+ "en": "Please enter"
+ }
+};
+export default {
+ /**
+ vk.alert("内容");
+ vk.alert("内容","提示","好的",function(){
+
+ });
+ */
+ alert: function(a = " ", b, c, d) {
+ let vk = uni.vk;
+ let locale = vk.getLocale();
+ let obj = {
+ title: localeObj.title[locale],
+ confirmText: localeObj.confirmText[locale],
+ placeholderText: localeObj.placeholderText[locale],
+ content: a,
+ showCancel: false
+ };
+ if (typeof d === 'function') {
+ obj.title = b;
+ obj.confirmText = c;
+ obj.success = d;
+ } else if (typeof c === 'function') {
+ obj.title = b;
+ obj.success = c;
+ } else if (typeof b === 'function') {
+ obj.success = b;
+ } else if (b != undefined) {
+ obj.title = b;
+ if (c != undefined) {
+ obj.confirmText = c;
+ }
+ }
+ if (typeof obj.content === 'number') {
+ obj.content = obj.content + "";
+ } else if (typeof obj.content === 'object') {
+ obj.content = JSON.stringify(obj.content);
+ }
+ return MessageBox({
+ title: obj.title,
+ message: obj.content,
+ confirmButtonText: obj.confirmText,
+ })
+ // return uni.showModal(obj);
+ },
+ /**
+ vk.confirm("内容","提示","确定","取消",(res) => {
+ if(res.confirm){
+
+ }
+ });
+ */
+ confirm: function(a, b, c, d, e) {
+ let vk = uni.vk;
+ let locale = vk.getLocale();
+ let obj = {
+ showCancel: true,
+ cancelColor: "#999",
+ title: localeObj.title[locale],
+ confirmText: localeObj.confirmText[locale],
+ cancelText: localeObj.cancelText[locale],
+ placeholderText: localeObj.placeholderText[locale],
+ };
+ if (typeof a === "object") {
+ obj = a;
+ } else {
+ if (typeof a === "string") {
+ obj.content = a;
+ }
+ if (typeof e === 'function') {
+ obj.title = b;
+ obj.confirmText = c;
+ obj.cancelText = d;
+ obj.success = e;
+ } else if (typeof d === 'function') {
+ obj.title = b;
+ obj.confirmText = c;
+ obj.success = d;
+ } else if (typeof c === 'function') {
+ obj.title = b;
+ obj.success = c;
+ } else if (typeof b === 'function') {
+ obj.success = b;
+ } else if (b != undefined) {
+ obj.title = b;
+ if (c != undefined) {
+ obj.confirmText = c;
+ }
+ }
+ }
+ return uni.showModal(obj);
+ },
+ /**
+ vk.prompt("请输入","提示","确定","取消",function(res){
+ if(res.confirm){
+ console.log(res.content);
+ }
+ },"输入框内初始内容");
+ */
+ prompt: function(a, b, c, d, e, f) {
+ let vk = uni.vk;
+ let locale = vk.getLocale();
+ let obj = {
+ showCancel: true,
+ editable: true,
+ cancelColor: "#999",
+ title: localeObj.title[locale],
+ confirmText: localeObj.confirmText[locale],
+ cancelText: localeObj.cancelText[locale],
+ placeholderText: localeObj.placeholderText[locale],
+ };
+ if (typeof a === "object") {
+ obj = a;
+ } else {
+ if (typeof a === "string") {
+ obj.placeholderText = a;
+ }
+ if (typeof e === 'function') {
+ obj.title = b;
+ obj.confirmText = c;
+ obj.cancelText = d;
+ obj.success = e;
+ obj.content = f;
+ } else if (typeof d === 'function') {
+ obj.title = b;
+ obj.confirmText = c;
+ obj.success = d;
+ obj.content = e;
+ } else if (typeof c === 'function') {
+ obj.title = b;
+ obj.success = c;
+ obj.content = d;
+ } else if (typeof b === 'function') {
+ obj.success = b;
+ obj.content = c;
+ }
+ }
+ return uni.showModal(obj);
+ },
+ /**
+ vk.toast("提示内容","none");
+ */
+ toast: function(a, b, c, d, e) {
+ let vk = uni.vk;
+ if (typeof a === 'number') {
+ a = a.toString();
+ } else if (typeof a === 'object') {
+ a = JSON.stringify(a);
+ }
+ let title = a;
+ let icon = "none";
+ let type = "info";
+ let image = "";
+ let mask = false;
+ let duration = 1500;
+ let fn;
+
+ if (typeof e !== "undefined") {
+ if (typeof e == "function") fn = e;
+ if (typeof e == "number") duration = e;
+ if (typeof e == "boolean") mask = e;
+ }
+ if (typeof d !== "undefined") {
+ if (typeof d == "function") fn = d;
+ if (typeof d == "number") duration = d;
+ if (typeof d == "boolean") mask = d;
+ }
+ if (typeof c !== "undefined") {
+ if (typeof c == "function") fn = c;
+ if (typeof c == "number") duration = c;
+ if (typeof c == "boolean") mask = c;
+ }
+
+ if (typeof b !== "undefined") {
+ if (typeof b == "function") fn = b;
+ if (typeof b == "number") duration = b;
+ if (typeof b == "boolean") mask = b;
+ if (typeof b == 'string') {
+ if (b == "ok") b = "success";
+ if (b == "success" || b == "loading" || b == "none" || b == "error") {
+ icon = b;
+ } else {
+ image = b;
+ }
+ }
+ }
+
+
+ return Message({
+ message: title,
+ type: icon,
+ duration: duration,
+ onClose: function(res) {
+ if (typeof fn === 'function') {
+ setTimeout(function() {
+ fn(res);
+ }, duration);
+ }
+ }
+ })
+
+ // return uni.showToast({
+ // title: title,
+ // icon: icon,
+ // image: image,
+ // mask: mask,
+ // duration: duration,
+ // success: function(res) {
+ // if (typeof fn === 'function') {
+ // setTimeout(function() {
+ // fn(res);
+ // }, duration);
+ // }
+ // }
+ // });
+ },
+ /**
+ * 操作菜单
+ vk.showActionSheet({
+ title:"",
+ list:["位置","@好友"],
+ color:"rgb(0, 0, 0)",
+ success:function(res){
+ if(res.index==0){
+
+ }else if(res.index==1){
+
+ }
+ }
+ });
+ */
+ showActionSheet: function(object) {
+ let vk = uni.vk;
+ let title = object.title;
+ let list = object.list;
+ let color = object.color || "#000000";
+ let success = object.success;
+ let fail = object.fail;
+ let complete = object.complete;
+ return uni.showActionSheet({
+ itemList: list,
+ itemColor: color,
+ success: function(res) {
+ let index = res.tapIndex;
+ let text = list[index];
+ let g = { index, text };
+ //console.log(g);
+ if (typeof success == "function") success(g);
+ },
+ fail: function(res) {
+ //console.log(res);
+ if (typeof fail == "function") fail(res);
+ },
+ complete: function(res) {
+ if (typeof complete == "function") complete(res);
+ }
+ });
+ },
+ showLoading: function(obj) {
+ if (typeof obj == "string") {
+ let title = obj;
+ obj = {
+ title: title,
+ mask: true
+ };
+ }
+ loadingInstance = Loading.service({
+ text: obj.title
+ })
+ // uni.showLoading(obj);
+ },
+ hideLoading: function() {
+ if(loadingInstance != null) {
+ loadingInstance.close();
+ }
+ uni.hideLoading();
+ },
+ // 设置当前页面的loading变量的值
+ setLoading: function(loading = true, obj = true) {
+ try {
+ let vk = uni.vk;
+ if (typeof obj === "boolean") {
+ let pages = getCurrentPages();
+ let page = pages[pages.length - 1];
+ let that = page.$vm;
+ that.loading = loading;
+ } else if (typeof obj === "object") {
+ let { data, name, that } = obj;
+ if (!data) data = that;
+ vk.pubfn.setData(data, name, loading);
+ } else if (typeof obj === "string") {
+ let pages = getCurrentPages();
+ let page = pages[pages.length - 1];
+ let that = page.$vm;
+ let name = obj;
+ vk.pubfn.setData(that, name, loading);
+ }
+ } catch (err) {}
+ },
+}
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/permission.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/permission.js
new file mode 100644
index 0000000..e79e439
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/permission.js
@@ -0,0 +1,33 @@
+function $hasRole(...args) {
+ const userRoles = this.$store.state.$user.userInfo.role || [];
+ return args.some(arg => {
+ if (Array.isArray(arg)) {
+ return arg.every(role => userRoles.includes(role));
+ } else {
+ return userRoles.includes(arg);
+ }
+ });
+}
+
+function $hasPermission(...args) {
+ const userPermission = this.$store.state.$user.permission || []
+ return args.some(arg => {
+ if (Array.isArray(arg)) {
+ return arg.every(permission => userPermission.includes(permission));
+ } else {
+ return userPermission.includes(arg);
+ }
+ });
+}
+
+export default function(Vue) {
+ // #ifndef VUE3
+ Vue.prototype.$hasRole = $hasRole;
+ Vue.prototype.$hasPermission = $hasPermission;
+ // #endif
+
+ // #ifdef VUE3
+ Vue.config.globalProperties.$hasRole = $hasRole;
+ Vue.config.globalProperties.$hasPermission = $hasPermission;
+ // #endif
+}
\ No newline at end of file
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/queryParams.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/queryParams.js
new file mode 100644
index 0000000..e2cc086
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/queryParams.js
@@ -0,0 +1,60 @@
+/**
+ * 对象转url参数
+ * @param {*} data,对象
+ * @param {*} isPrefix,是否自动加上"?"
+ * 此函数参考uView
+ */
+function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
+ let newData = JSON.parse(JSON.stringify(data));
+ let prefix = isPrefix ? '?' : ''
+ let _result = []
+ if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets';
+ for (let key in newData) {
+ let value = newData[key]
+ // 去掉为空的参数
+ if (['', undefined, null].indexOf(value) >= 0) {
+ continue;
+ }
+ // 如果值为数组,另行处理
+ if (value.constructor === Array) {
+ // e.g. {ids: [1, 2, 3]}
+ switch (arrayFormat) {
+ case 'indices':
+ // 结果: ids[0]=1&ids[1]=2&ids[2]=3
+ for (let i = 0; i < value.length; i++) {
+ _result.push(key + '[' + i + ']=' + value[i])
+ }
+ break;
+ case 'brackets':
+ // 结果: ids[]=1&ids[]=2&ids[]=3
+ value.forEach(_value => {
+ _result.push(key + '[]=' + _value)
+ })
+ break;
+ case 'repeat':
+ // 结果: ids=1&ids=2&ids=3
+ value.forEach(_value => {
+ _result.push(key + '=' + _value)
+ })
+ break;
+ case 'comma':
+ // 结果: ids=1,2,3
+ let commaStr = "";
+ value.forEach(_value => {
+ commaStr += (commaStr ? "," : "") + _value;
+ })
+ _result.push(key + '=' + commaStr)
+ break;
+ default:
+ value.forEach(_value => {
+ _result.push(key + '[]=' + _value)
+ })
+ }
+ } else {
+ _result.push(key + '=' + value)
+ }
+ }
+ return _result.length ? prefix + _result.join('&') : ''
+}
+
+export default queryParams;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/setClipboardData.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/setClipboardData.js
new file mode 100644
index 0000000..71d5773
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/setClipboardData.js
@@ -0,0 +1,51 @@
+
+// #ifdef H5
+ uni.setClipboardData = function setClipboardData({
+ data,
+ success,
+ fail,
+ complete
+ } = {}) {
+ try {
+ const x = window.scrollX
+ const y = window.scrollY
+ const input = document.createElement('input')
+ input.setAttribute('readonly', 'readonly')
+ input.setAttribute('value', data)
+ input.style.position = 'absolute'
+ input.style.width = '100px'
+ input.style.left = '-10000px'
+ document.body.appendChild(input)
+ input.focus()
+ window.scrollTo(x, y)
+ input.setSelectionRange(0, input.value.length)
+ document.execCommand('copy')
+ document.body.removeChild(input)
+ setTimeout(() => {
+ const res = {
+ errMsg: 'setClipboardData:ok',
+ data
+ }
+ success && success(res)
+ complete && complete(res)
+ })
+ } catch (e) {
+ setTimeout(() => {
+ const res = {
+ errMsg: 'setClipboardData:fail'
+ }
+ fail && fail(res)
+ complete && complete(res)
+ })
+ }
+ }
+ // #endif
+
+// JS对象深度合并
+function setClipboardData(obj = {}) {
+ uni.setClipboardData({
+ ...obj
+ });
+}
+
+export default setClipboardData;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/throttle.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/throttle.js
new file mode 100644
index 0000000..60cd436
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/throttle.js
@@ -0,0 +1,37 @@
+let timeoutArr = [];
+let flagArr = [];
+/**
+ * 节流函数
+ * 节流原理:在一定时间内,只能触发一次
+ * @param {Function} fn 要执行的回调函数
+ * @param {Number} time 延时的时间
+ * @param {Boolean} isImmediate 是否立即执行
+ * @param {String} timeoutName 定时器ID
+ * @return null
+vk.pubfn.throttle(function() {
+
+}, 1000);
+ */
+function throttle(fn, time = 500, isImmediate = true, timeoutName = "default") {
+ if(!timeoutArr[timeoutName]) timeoutArr[timeoutName] = null;
+ if (isImmediate) {
+ if (!flagArr[timeoutName]) {
+ flagArr[timeoutName] = true;
+ // 如果是立即执行,则在time毫秒内开始时执行
+ if(typeof fn === 'function') fn();
+ timeoutArr[timeoutName] = setTimeout(() => {
+ flagArr[timeoutName] = false;
+ }, time);
+ }
+ } else {
+ if (!flagArr[timeoutName]) {
+ flagArr[timeoutName] = true;
+ // 如果是非立即执行,则在time毫秒内的结束处执行
+ timeoutArr[timeoutName] = setTimeout(() => {
+ flagArr[timeoutName] = false;
+ if(typeof fn === 'function') fn();
+ }, time);
+ }
+ }
+};
+export default throttle
\ No newline at end of file
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/timeUtil.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/timeUtil.js
new file mode 100644
index 0000000..dc2b4c3
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/timeUtil.js
@@ -0,0 +1,642 @@
+/**
+ * 时间工具类
+ */
+var util = {};
+util.getTargetTimezone = function(val) {
+ if (typeof val === "number") {
+ return val;
+ }
+ let vk = uni.vk;
+ let defaultValue = 8;
+ let targetTimezone = defaultValue;
+ try {
+ const config = vk.callFunctionUtil.getConfig();
+ targetTimezone = config.targetTimezone;
+ if (typeof targetTimezone !== "number") {
+ targetTimezone = defaultValue;
+ }
+ } catch (err) {}
+ return targetTimezone;
+};
+
+// 尽可能的将参数转成正确的时间对象
+util.getDateObject = function(date, targetTimezone) {
+ if (!date) return "";
+ let nowDate;
+ // 如果是字符串,且纯数字,则强制转数值
+ if (typeof date === "string" && !isNaN(date) && date.length >= 10) date = Number(date);
+ if (typeof date === "number") {
+ if (date.toString().length == 10) date *= 1000;
+ nowDate = new Date(date); // 转时间对象
+ } else if (typeof date === "object") {
+ nowDate = new Date(date.getTime()); // 新建一个时间对象
+ } else if (typeof date === "string") {
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ let targetTimezoneStr = targetTimezone;
+ let targetTimezoneF = targetTimezone >= 0 ? "+" : "";
+ if (targetTimezone >= 0 && targetTimezone < 10) {
+ targetTimezoneStr = `0${targetTimezone}`;
+ } else if (targetTimezone < 0 && targetTimezone > -10) {
+ targetTimezoneStr = `-0${targetTimezone*-1}`;
+ }
+ let arr1 = date.split(" ");
+ let arr1_1 = arr1[0] || "";
+ let arr1_2 = arr1[1] || "";
+ let arr2;
+ if (arr1_1.indexOf("-") > -1) {
+ arr2 = arr1_1.split("-");
+ } else {
+ arr2 = arr1_1.split("/");
+ }
+ let arr3 = arr1_2.split(":");
+ let dateObj = {
+ year: Number(arr2[0]),
+ month: Number(arr2[1]) || 1,
+ day: Number(arr2[2]) || 1,
+ hour: Number(arr3[0]) || 0,
+ minute: Number(arr3[1]) || 0,
+ second: Number(arr3[2]) || 0,
+ };
+ for (let key in dateObj) {
+ if (dateObj[key] >= 0 && dateObj[key] < 10) dateObj[key] = `0${dateObj[key]}`;
+ }
+ // 格式 2022-10-01T00:00:00+08:00
+ let dateStr = `${dateObj.year}-${dateObj.month}-${dateObj.day}T${dateObj.hour}:${dateObj.minute}:${dateObj.second}${targetTimezoneF}${targetTimezoneStr}:00`;
+ nowDate = new Date(dateStr);
+ }
+ return nowDate;
+};
+
+// 获取时间在不同时区下的时间对象
+util.getTimeByTimeZone = function(date, targetTimezone) {
+ let nowDate = util.getDateObject(date);
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ let timezoneOffset = nowDate.getTimezoneOffset();
+ let offset = timezoneOffset * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ let targetTime = nowDate.getTime() + offset;
+ nowDate = new Date(targetTime);
+ return nowDate;
+};
+
+
+/**
+ * 日期格式化
+ * @param {Date || Number} date 需要格式化的时间
+ * vk.pubfn.timeFormat(new Date(),"yyyy-MM-dd hh:mm:ss");
+ */
+util.timeFormat = function(date, fmt = 'yyyy-MM-dd hh:mm:ss', targetTimezone) {
+ try {
+ if (!date) return "";
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ let nowDate = util.getTimeByTimeZone(date, targetTimezone);
+ let opt = {
+ "M+": nowDate.getMonth() + 1, //月份
+ "d+": nowDate.getDate(), //日
+ "h+": nowDate.getHours(), //小时
+ "m+": nowDate.getMinutes(), //分
+ "s+": nowDate.getSeconds(), //秒
+ "q+": Math.floor((nowDate.getMonth() + 3) / 3), //季度
+ "S": nowDate.getMilliseconds(), //毫秒
+ "Z": `${targetTimezone >= 0 ? '+' : '-'}${Math.abs(targetTimezone).toString().padStart(2, '0')}:00` // 时区
+ };
+ if (/(y+)/.test(fmt)) {
+ fmt = fmt.replace(RegExp.$1, (nowDate.getFullYear() + "").substr(4 - RegExp.$1.length));
+ }
+ for (let k in opt) {
+ if (new RegExp("(" + k + ")").test(fmt)) {
+ fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (opt[k]) : (("00" + opt[k]).substr(("" + opt[k]).length)));
+ }
+ }
+ return fmt;
+ } catch (err) {
+ // 若格式错误,则原值显示
+ return time;
+ }
+};
+
+
+/**
+ * 解析日期对象属性
+ * @param {Date || Number} date 需要转换的时间
+ * vk.pubfn.getDateInfo(new Date());
+ */
+util.getDateInfo = function(date = new Date(), targetTimezone) {
+ let nowDate = util.getTimeByTimeZone(date, targetTimezone);
+ let year = nowDate.getFullYear() + '';
+ let month = (nowDate.getMonth() + 1 < 10 ? '0' + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1);
+ let day = (nowDate.getDate() < 10 ? '0' + (nowDate.getDate()) : nowDate.getDate());
+ let hour = (nowDate.getHours() < 10 ? '0' + (nowDate.getHours()) : nowDate.getHours());
+ let minute = (nowDate.getMinutes() < 10 ? '0' + (nowDate.getMinutes()) : nowDate.getMinutes());
+ let second = (nowDate.getSeconds() < 10 ? '0' + (nowDate.getSeconds()) : nowDate.getSeconds());
+ let millisecond = nowDate.getMilliseconds(); //毫秒
+ let week = nowDate.getDay(); // 周
+ let quarter = Math.floor((nowDate.getMonth() + 3) / 3); //季度
+ return {
+ year: Number(year),
+ month: Number(month),
+ day: Number(day),
+ hour: Number(hour),
+ minute: Number(minute),
+ second: Number(second),
+ millisecond: Number(millisecond),
+ week: Number(week),
+ quarter: Number(quarter),
+ };
+};
+
+
+/**
+ * 获取时间范围
+ * @param {Date} date 日期对象 可以指定时间计算节点,默认使用当前时间进行计算
+ * 返回的是时间戳
+ * 返回数据如下:
+ {
+ todayStart 今日开始时间(时间戳)
+ todayEnd 今日结束时间(时间戳)
+ today12End 今日上午结束时间(时间戳)
+ monthStart 本月开始时间(时间戳)
+ monthEnd 本月结束时间(时间戳)
+ yearStart 本年开始时间(时间戳)
+ yearEnd 本年结束时间(时间戳)
+ weekStart 本周开始时间(时间戳)
+ weekEnd 本周结束时间(时间戳)
+ hourStart 当前小时开始时间(时间戳)
+ hourEnd 当前小时结束时间(时间戳)
+ yesterdayStart 昨天开始时间(时间戳)
+ yesterday12End 昨天上午结束时间(时间戳)
+ yesterdayEnd 昨天结束时间(时间戳)
+ lastMonthStart 上月开始时间(时间戳)
+ lastMonthEnd 上月结束时间(时间戳)
+ now 现在的时间点(含月年日时分秒)
+ months 本年度每月的开始和结束时间 months[1] 代表1月
+ days 本月每天的开始和结束时间 days[1] 代表1日
+ }
+ * vk.pubfn.getCommonTime();
+ */
+util.getCommonTime = function(date = new Date(), targetTimezone) {
+ let res = {};
+ let nowDate = util.getDateObject(date);
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ const { year, month, day, hour, minute, second, millisecond, week, quarter } = util.getDateInfo(nowDate, targetTimezone);
+ const oneDayTime = 24 * 60 * 60 * 1000;
+ // 现在的时间
+ res.now = {
+ year,
+ month,
+ day,
+ hour,
+ minute,
+ second,
+ millisecond,
+ week,
+ quarter,
+ date_str: util.timeFormat(nowDate, "yyyy-MM-dd hh:mm:ss", targetTimezone),
+ date_day_str: util.timeFormat(nowDate, "yyyy-MM-dd", targetTimezone),
+ date_month_str: util.timeFormat(nowDate, "yyyy-MM", targetTimezone),
+ };
+ // 获取本月最大天数
+ let month_last_day = new Date(year, month, 0).getDate();
+ // 获取今年12月最大天数
+ let year_last_day = new Date(year, 12, 0).getDate();
+ // 今日开始时间
+ res.todayStart = new Date(`${year}/${month}/${day}`).getTime() - timeDif;
+ // 今日12点时间
+ res.today12End = new Date(`${year}/${month}/${day}`).getTime() + (12 * 60 * 60 * 1000 - 1) - timeDif;
+ // 今日结束时间
+ res.todayEnd = new Date(`${year}/${month}/${day}`).getTime() + (oneDayTime - 1) - timeDif;
+ // 本月开始时间
+ res.monthStart = new Date(`${year}/${month}/1`).getTime() - timeDif;
+ // 本月结束时间
+ res.monthEnd = new Date(`${year}/${month}/${month_last_day}`).getTime() + (oneDayTime - 1) - timeDif;
+ // 本年开始时间
+ res.yearStart = new Date(`${year}/1/1`).getTime() - timeDif;
+ // 本年结束时间
+ res.yearEnd = new Date(`${year}/12/${year_last_day}`).getTime() + (oneDayTime - 1) - timeDif;
+ // 当前小时开始时间
+ res.hourStart = new Date(`${year}/${month}/${day} ${hour}:00:00`).getTime() - timeDif;
+ // 当前小时结束时间
+ res.hourEnd = new Date(`${year}/${month}/${day} ${hour}:59:59`).getTime() - timeDif;
+ // 计算上月开始-----------------------------------------------------------
+ let year_last = year;
+ let month_last = month - 1;
+ if (month_last === 0) {
+ month_last = 12;
+ year_last = year - 1;
+ }
+ let month_last_day_last = new Date(year_last, month_last, 0).getDate();
+ // 上月开始时间
+ res.lastMonthStart = new Date(`${year_last}/${month_last}/1`).getTime() - timeDif;
+ // 上月结束时间
+ res.lastMonthEnd = new Date(`${year_last}/${month_last}/${month_last_day_last}`).getTime() + (oneDayTime - 1) - timeDif;
+ // 计算上月结束-----------------------------------------------------------
+
+ // 昨天开始时间
+ res.yesterdayStart = res.todayStart - 1000 * 3600 * 24;
+ // 昨天上午结束时间
+ res.yesterday12End = res.today12End - 1000 * 3600 * 24;
+ // 昨天结束时间
+ res.yesterdayEnd = res.todayEnd - 1000 * 3600 * 24;
+
+ let weekObj = util.getWeekOffsetStartAndEnd(0, nowDate, targetTimezone);
+ // 本周开始时间
+ res.weekStart = weekObj.startTime;
+ // 本周结束时间
+ res.weekEnd = weekObj.endTime;
+ // 本年1-12月的起止时间
+ res.months = [];
+ res.months[0] = {
+ startTime: res.monthStart,
+ endTime: res.monthEnd,
+ startTimeStr: util.timeFormat(res.monthStart, "yyyy-MM-dd hh:mm:ss", targetTimezone),
+ endTimeStr: util.timeFormat(res.monthEnd, "yyyy-MM-dd hh:mm:ss", targetTimezone),
+ monthStart: res.monthStart, // 兼容旧版
+ monthEnd: res.monthEnd, // 兼容旧版
+ };
+ for (let i = 1; i <= 12; i++) {
+ // 获取此月最大天数
+ let month_last_day = new Date(year, i, 0).getDate();
+ // 此月开始时间
+ let startTime = new Date(`${year}/${i}/1`).getTime() - timeDif;
+ // 此月结束时间
+ let endTime = new Date(`${year}/${i}/${month_last_day}`).getTime() + (oneDayTime - 1) - timeDif;
+ res.months[i] = {
+ startTime,
+ endTime,
+ startTimeStr: util.timeFormat(startTime, "yyyy-MM-dd hh:mm:ss", targetTimezone),
+ endTimeStr: util.timeFormat(endTime, "yyyy-MM-dd hh:mm:ss", targetTimezone),
+ monthStart: startTime, // 兼容旧版
+ monthEnd: endTime, // 兼容旧版
+ };
+ }
+ // 本月1号到最后一天每天的起止时间
+ res.days = [];
+ res.days[0] = {
+ startTime: res.todayStart,
+ endTime: res.todayEnd,
+ startTimeStr: util.timeFormat(res.todayStart, "yyyy-MM-dd hh:mm:ss", targetTimezone),
+ endTimeStr: util.timeFormat(res.todayEnd, "yyyy-MM-dd hh:mm:ss", targetTimezone)
+ };
+ for (let i = 1; i <= month_last_day; i++) {
+ let nowTime = res.monthStart + ((i - 1) * oneDayTime);
+ let { startTime, endTime } = util.getDayOffsetStartAndEnd(0, nowTime, targetTimezone);
+ res.days[i] = {
+ startTime,
+ endTime,
+ startTimeStr: util.timeFormat(startTime, "yyyy-MM-dd hh:mm:ss", targetTimezone),
+ endTimeStr: util.timeFormat(endTime, "yyyy-MM-dd hh:mm:ss", targetTimezone)
+ };
+ }
+ for (let key in res) {
+ if (typeof res[key] === "number" && res[key].toString().length === 13) {
+ res[`${key}Str`] = util.timeFormat(res[key], "yyyy-MM-dd hh:mm:ss", targetTimezone);
+ }
+ }
+ return res;
+};
+
+/**
+ * 获得指定年份和月份后的该月的开始时间和结束时间
+ * 返回数据如下:(时间戳形式)
+ {
+ startTime 该月开始时间
+ endTime 该月结束时间
+ }
+vk.pubfn.getMonthStartAndEnd({
+ year:2021
+ month:1
+});
+ */
+util.getMonthStartAndEnd = function(obj, targetTimezone) {
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ let res = {
+ startTime: null,
+ endTime: null
+ };
+ let { year, month } = obj;
+ if (year > 0 && month > 0) {
+ const dif = new Date().getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ let month_last_day = new Date(year, month, 0).getDate();
+ // 开始时间
+ res.startTime = new Date(`${year}/${month}/1`).getTime() - timeDif;
+ // 结束时间
+ res.endTime = new Date(`${year}/${month}/${month_last_day}`).getTime() + (24 * 60 * 60 * 1000 - 1) - timeDif;
+ }
+ return res;
+}
+
+/**
+ * 获得相对当前时间的偏移 count 小时的起止日期(返回小时的开始和结束时间戳)
+ * @param {Number} count 默认0(0代表当前小时 -1代表上一个小时 1代表下一个小时以此类推)
+ * @param {Date || Number} date 指定从哪个时间节点开始计算
+ * vk.pubfn.getHourOffsetStartAndEnd(0);
+ */
+util.getHourOffsetStartAndEnd = function(count = 0, date = new Date(), targetTimezone) {
+ let nowDate = util.getDateObject(date);
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ let res = {};
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ // 一天的毫秒数
+ let offsetMillisecond = 1000 * 60 * 60;
+ // 相对于当前日期count个天的日期
+ nowDate = new Date(nowDate.getTime() + (offsetMillisecond * 1 * count));
+ let dateInfo = util.getDateInfo(nowDate);
+ // 获得当天的起始时间
+ res.startTime = new Date(`${dateInfo.year}/${dateInfo.month}/${dateInfo.day} ${dateInfo.hour}:00:00`).getTime() - timeDif;
+ // 获得当天的结束时间
+ res.endTime = new Date(`${dateInfo.year}/${dateInfo.month}/${dateInfo.day} ${dateInfo.hour}:00:00`).getTime() + (offsetMillisecond - 1) - timeDif;
+ return res;
+}
+
+
+/**
+ * 获得相对当前时间的偏移 count 天的起止日期(返回日的开始和结束)
+ * @param {Number} count 默认0(0代表今日 -1代表昨日 1代表明日以此类推)
+ * @param {Date || Number} date 指定从哪个时间节点开始计算
+ * vk.pubfn.getDayOffsetStartAndEnd(0);
+ */
+util.getDayOffsetStartAndEnd = function(count = 0, date = new Date(), targetTimezone) {
+ let nowDate = util.getDateObject(date);
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ let res = {};
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ // 一天的毫秒数
+ let offsetMillisecond = 1000 * 60 * 60 * 24;
+ // 相对于当前日期count个天的日期
+ nowDate = new Date(nowDate.getTime() + (offsetMillisecond * 1 * count));
+ let dateInfo = util.getDateInfo(nowDate);
+ // 获得当天的起始时间
+ res.startTime = new Date(`${dateInfo.year}/${dateInfo.month}/${dateInfo.day}`).getTime() - timeDif;
+ // 获得当天的结束时间
+ res.endTime = new Date(`${dateInfo.year}/${dateInfo.month}/${dateInfo.day}`).getTime() + (offsetMillisecond - 1) - timeDif;
+ return res;
+}
+
+/**
+ * 获得相对当前周count个周的起止日期(返回周的开始和结束)
+ * @param {Number} count 默认0(0代表本周 -1代表上周 1代表下周以此类推)
+ * vk.pubfn.getWeekOffsetStartAndEnd(0);
+ */
+util.getWeekOffsetStartAndEnd = function(count = 0, date = new Date(), targetTimezone) {
+ let res = {};
+ let nowDate = util.getDateObject(date);
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ let nowDay = nowDate.getDay() === 0 ? 7 : nowDate.getDay();
+ nowDate.setDate(nowDate.getDate() - nowDay + 1 + count * 7);
+ let dateInfo1 = util.getDateInfo(nowDate);
+ nowDate.setDate(nowDate.getDate() + 7);
+ let dateInfo2 = util.getDateInfo(nowDate);
+ // 开始时间
+ res.startTime = new Date(`${dateInfo1.year}/${dateInfo1.month}/${dateInfo1.day}`).getTime() - timeDif;
+ // 结束时间
+ res.endTime = new Date(`${dateInfo2.year}/${dateInfo2.month}/${dateInfo2.day}`).getTime() - 1 - timeDif;
+ return res;
+}
+
+/**
+ * 获得相对当前时间的偏移 count 个月的起止日期(月的开始和结束时间戳)
+ * @param {Number} count 默认0(0代表本月 -1代表上月 1代表下月以此类推)
+ * @param {Date || Number} date 指定从哪个时间节点开始计算
+ * vk.pubfn.getMonthOffsetStartAndEnd(0);
+ */
+util.getMonthOffsetStartAndEnd = function(count = 0, date = new Date(), targetTimezone) {
+ let res = {};
+ let nowDate = util.getDateObject(date);
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ let dateInfo = util.getDateInfo(nowDate);
+ let month = dateInfo.month + count;
+ let year = dateInfo.year;
+ if (month > 12) {
+ year = year + Math.floor(month / 12);
+ month = Math.abs(month) % 12;
+ } else if (month <= 0) {
+ year = year - 1 - Math.floor(Math.abs(month) / 12);
+ month = 12 - Math.abs(month) % 12;
+ }
+ let month_last_day = new Date(year, month, 0).getDate();
+ // 开始时间
+ res.startTime = new Date(`${year}/${month}/1`).getTime() - timeDif;
+ // 结束时间
+ res.endTime = new Date(`${year}/${month}/${month_last_day}`).getTime() + (24 * 60 * 60 * 1000 - 1) - timeDif;
+ return res;
+}
+
+
+/**
+ * 获得相对当前时间的偏移 count 个季度的起止日期(季度的开始和结束时间戳)
+ * @param {Number} count 默认0(0代表本季度 -1代表上个季度 1代表下个季度以此类推)
+ * @param {Date || Number} date 指定从哪个时间节点开始计算
+ * vk.pubfn.getQuarterOffsetStartAndEnd(0);
+ */
+util.getQuarterOffsetStartAndEnd = function(count = 0, date = new Date(), targetTimezone) {
+ let res = {};
+ let nowDate = util.getDateObject(date);
+ nowDate.setMonth(nowDate.getMonth() + count * 3);
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ let dateInfo = util.getDateInfo(nowDate);
+ let month = dateInfo.month;
+ if ([1, 2, 3].indexOf(month) > -1) {
+ // 第1季度
+ month = 1;
+ } else if ([4, 5, 6].indexOf(month) > -1) {
+ // 第2季度
+ month = 4;
+ } else if ([7, 8, 9].indexOf(month) > -1) {
+ // 第3季度
+ month = 7;
+ } else if ([10, 11, 12].indexOf(month) > -1) {
+ // 第4季度
+ month = 10;
+ }
+ nowDate.setMonth(month - 1); // 因为0代表1月,所以这里要减1
+ let dateInfo1 = util.getDateInfo(nowDate);
+ nowDate.setMonth(nowDate.getMonth() + 3);
+ let dateInfo2 = util.getDateInfo(nowDate);
+ // 开始时间
+ res.startTime = new Date(`${dateInfo1.year}/${dateInfo1.month}/1`).getTime() - timeDif;
+ // 结束时间
+ res.endTime = new Date(`${dateInfo2.year}/${dateInfo2.month}/1`).getTime() - 1 - timeDif;
+ return res;
+}
+
+/**
+ * 获得相对当前时间的偏移 count 年的起止日期(年的开始和结束时间戳)
+ * @param {Number} count 默认0 (0代表今年 -1代表去年 1代表明年以此类推)
+ * @param {Date || Number} date 指定从哪个时间节点开始计算
+ * vk.pubfn.getYearOffsetStartAndEnd(0);
+ */
+util.getYearOffsetStartAndEnd = function(count = 0, date = new Date(), targetTimezone) {
+ let res = {};
+ let nowDate = util.getDateObject(date);
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ let dateInfo = util.getDateInfo(nowDate);
+ let year = dateInfo.year + count;
+ // 开始时间
+ res.startTime = new Date(`${year}/1/1`).getTime() - timeDif;
+ // 结束时间
+ res.endTime = new Date(`${year}/12/31`).getTime() + (24 * 60 * 60 * 1000 - 1) - timeDif;
+ return res;
+};
+
+
+/**
+ * 获得指定时间偏移 year年 month月 day天 hours时 minutes分 seconds秒前或后的时间戳
+ * 返回时间戳
+vk.pubfn.getOffsetTime(new Date(), {
+ year:0,
+ month:0,
+ day:0,
+ hours:0,
+ minutes:0,
+ seconds:0,
+ mode:"after", // after 之后 before 之前
+});
+
+vk.pubfn.getOffsetTime(new Date(), {
+ y:0,
+ m:0,
+ d:0,
+ hh:0,
+ mm:0,
+ ss:0,
+ mode:"after" // after 之后 before 之前
+});
+ */
+util.getOffsetTime = function(date = new Date(), obj, targetTimezone) {
+ let nowDate = util.getDateObject(date);
+ let dateInfo = util.getDateInfo(nowDate);
+
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+
+ let year = obj.year || obj.y || 0;
+ let month = obj.month || obj.m || 0;
+ let day = obj.day || obj.d || 0;
+ let hour = obj.hour || obj.hours || obj.hh || 0;
+ let minute = obj.minute || obj.minutes || obj.mm || 0;
+ let second = obj.second || obj.seconds || obj.ss || 0;
+ let { mode = "after" } = obj;
+ if (mode == "before") {
+ year *= -1;
+ month *= -1;
+ day *= -1;
+ hour *= -1;
+ minute *= -1;
+ second *= -1;
+ }
+ let offsetObj = {
+ year: dateInfo.year + year,
+ month: dateInfo.month + month,
+ day: dateInfo.day + day,
+ hour: dateInfo.hour + hour,
+ minute: dateInfo.minute + minute,
+ second: dateInfo.second + second
+ };
+ nowDate = new Date(offsetObj.year, offsetObj.month - 1, offsetObj.day, offsetObj.hour, offsetObj.minute, offsetObj.second);
+ return nowDate.getTime() - timeDif;
+}
+
+/**
+ * 判断是否是闰年
+ * @param {Number | Date} year 需要计算的年份或时间,默认使用当前时间的年份
+ * vk.pubfn.timeUtil.isLeapYear(year);
+ */
+util.isLeapYear = function(year) {
+ if (typeof year === "undefined") {
+ let { now } = util.getCommonTime();
+ year = now.year;
+ } else if (typeof year === "object") {
+ let { now } = util.getCommonTime(year);
+ year = now.year;
+ }
+ if (((year % 4) == 0) && ((year % 100) != 0) || ((year % 400) == 0)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+/**
+ * 判断是否是清明节
+ * @param {Date} date 日期对象 可以指定时间计算节点,默认使用当前时间进行计算
+vk.pubfn.timeUtil.isQingming(new Date());
+ */
+util.isQingming = function(data = new Date()) {
+ let { now } = util.getCommonTime(data);
+ let { year, month, day } = now;
+ let key = false;
+ // 清明节的日期是不固定的,规律是:闰年开始的前2年是4月4日,闰年开始的第3年和第4年是4月5日
+ if (util.isLeapYear(year) || util.isLeapYear(year - 1)) {
+ if (month === 4 && day === 4) {
+ key = true;
+ }
+ } else {
+ if (month === 4 && day === 5) {
+ key = true;
+ }
+ }
+ return key;
+}
+
+/**
+ * 日期对象转换(已弃用,建议不要使用此API)
+ * @param {Date || Number} date 需要转换的时间
+ * @param {Number} type 转换方式
+ * type = 0 返回 2020-08-03 12:12:12
+ * type = 1 返回 20200803121212
+ * type = 2 返回 { YYYY, MM, DD, hh, mm, ss }
+ */
+util.getFullTime = function(date, type = 0, targetTimezone) {
+ if (!date) return "";
+ targetTimezone = util.getTargetTimezone(targetTimezone);
+ let nowDate = util.getDateObject(date);
+ const dif = nowDate.getTimezoneOffset();
+ const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+ const east8time = nowDate.getTime() + timeDif;
+ nowDate = new Date(east8time);
+
+ let YYYY = nowDate.getFullYear() + '';
+ let MM = (nowDate.getMonth() + 1 < 10 ? '0' + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1);
+ let DD = (nowDate.getDate() < 10 ? '0' + (nowDate.getDate()) : nowDate.getDate());
+ let hh = (nowDate.getHours() < 10 ? '0' + (nowDate.getHours()) : nowDate.getHours());
+ let mm = (nowDate.getMinutes() < 10 ? '0' + (nowDate.getMinutes()) : nowDate.getMinutes());
+ let ss = (nowDate.getSeconds() < 10 ? '0' + (nowDate.getSeconds()) : nowDate.getSeconds());
+ if (type === 2) {
+ return {
+ YYYY: Number(YYYY),
+ MM: Number(MM),
+ DD: Number(DD),
+ hh: Number(hh),
+ mm: Number(mm),
+ ss: Number(ss),
+
+ year: Number(YYYY),
+ month: Number(MM),
+ day: Number(DD),
+ hour: Number(hh),
+ minute: Number(mm),
+ second: Number(ss),
+ };
+ } else if (type === 1) {
+ return YYYY + "" + MM + "" + DD + "" + hh + "" + mm + "" + ss;
+ } else {
+ return YYYY + "-" + MM + "-" + DD + " " + hh + ":" + mm + ":" + ss;
+ }
+};
+
+
+export default util;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/treeUtil.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/treeUtil.js
new file mode 100644
index 0000000..1853d13
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/treeUtil.js
@@ -0,0 +1,93 @@
+
+import deepClone from './deepClone'
+var util = {};
+/**
+ * 将树形结构转成数组结构
+ * @param {Array} treeData 数据源
+ * @param {Object} treeProps 树结构配置 { id : "menu_id", children : "children" }
+ * vk.pubfn.treeToArray(treeData);
+ */
+util.treeToArray = function(treeData, treeProps) {
+ let newTreeData = deepClone(treeData);
+ return util.treeToArrayFn(newTreeData, treeProps);
+};
+util.treeToArrayFn = function(treeData, treeProps = {}, arr=[], current_parent_id) {
+ let { id="_id", parent_id="parent_id", children = "children", deleteChildren = true } = treeProps;
+ for(let i in treeData){
+ let item = treeData[i];
+ if(current_parent_id) item[parent_id] = current_parent_id;
+ arr.push(item);
+ if(item[children] && item[children].length>0){
+ arr = util.treeToArrayFn(item[children], treeProps, arr, item[id]);
+ }
+ if(deleteChildren){
+ delete item[children];
+ }
+ }
+ return arr;
+};
+/**
+ * 数组结构转树形结构
+let tree = vk.pubfn.arrayToTree(arrayData,{
+ id:"code",
+ parent_id:"parent_code",
+});
+ */
+
+util.arrayToTree = function(originalArrayData,treeProps) {
+ let arrayData = deepClone(originalArrayData);
+ let {
+ id="_id",
+ parent_id="parent_id",
+ children = "children",
+ deleteParentId = false,
+ need_field
+ } = treeProps;
+ let result = [];
+ let temp = {};
+ for (let i = 0; i < arrayData.length; i++) {
+ temp[arrayData[i][id]] = arrayData[i]; // 以id作为索引存储元素,可以无需遍历直接定位元素
+ }
+ for (let j = 0; j < arrayData.length; j++) {
+ let currentElement = arrayData[j];
+ let newCurrentElement = {};
+ if(need_field){
+ need_field = uniqueArr(need_field.concat([id,parent_id,children]));
+ for(let keyName in currentElement){
+ if(need_field.indexOf(keyName) === -1){
+ delete currentElement[keyName];
+ }
+ }
+ }
+ let tempCurrentElementParent = temp[currentElement[parent_id]]; // 临时变量里面的当前元素的父元素
+ if (tempCurrentElementParent) {
+ // 如果存在父元素
+ if (!tempCurrentElementParent[children]) {
+ // 如果父元素没有chindren键
+ tempCurrentElementParent[children] = []; // 设上父元素的children键
+ }
+ if(deleteParentId){
+ delete currentElement[parent_id];
+ }
+ tempCurrentElementParent[children].push(currentElement); // 给父元素加上当前元素作为子元素
+ } else {
+ // 不存在父元素,意味着当前元素是一级元素
+ result.push(currentElement);
+ }
+ }
+ return result;
+};
+
+// 最简单数组去重法
+function uniqueArr(array) {
+ let n = []; //一个新的临时数组
+ //遍历当前数组
+ for (let i = 0; i < array.length; i++) {
+ //如果当前数组的第i已经保存进了临时数组,那么跳过,
+ //否则把当前项push到临时数组里面
+ if (n.indexOf(array[i]) == -1) n.push(array[i]);
+ }
+ return n;
+}
+
+export default util;
\ No newline at end of file
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/updateManager.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/updateManager.js
new file mode 100644
index 0000000..470e3fe
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/updateManager.js
@@ -0,0 +1,61 @@
+var updateManager = {};
+/**
+ * 本API返回全局唯一的版本更新管理器对象: updateManager,用于管理小程序更新。
+ * vk.updateManager.updateReady();
+ */
+updateManager.updateReady = function(obj) {
+ // #ifdef MP
+ updateManagerByMP(obj);
+ // #endif
+};
+
+
+export default updateManager;
+
+
+function updateManagerByMP(obj = {}) {
+ let {
+ title = "更新提示",
+ content = "新版本已经准备好,点击更新!",
+ autoUpdate = true,
+ showCancel = false,
+ confirmText = "一键更新"
+ } = obj;
+ const updateManager = uni.getUpdateManager();
+
+ updateManager.onCheckForUpdate(function(res) {
+ // 请求完新版本信息的回调
+ // console.log(res.hasUpdate);
+ });
+
+ updateManager.onUpdateReady(function(res) {
+ uni.showModal({
+ title,
+ content,
+ showCancel,
+ confirmText,
+ success(res) {
+ if (res.confirm) {
+ if (typeof obj.success === "function") {
+ obj.success({
+ applyUpdate: updateManager.applyUpdate
+ });
+ }
+ if (typeof obj.complete === "function") obj.complete();
+ if (autoUpdate) {
+ // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
+ updateManager.applyUpdate();
+ }
+ }
+ },
+
+ });
+ });
+
+ updateManager.onUpdateFailed(function(res) {
+ // 新的版本下载失败
+ console.error("onUpdateFailed", res);
+ if (typeof obj.fail === "function") obj.fail(res);
+ if (typeof obj.complete === "function") obj.complete();
+ });
+}
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.filters.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.filters.js
new file mode 100644
index 0000000..1b338ff
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.filters.js
@@ -0,0 +1,63 @@
+/**
+ * vk.filters
+ * 全局过滤器
+ */
+import pubfn from './index.js'
+var util = {};
+// 将时间显示成1秒前、1天前
+util.dateDiff = function(starttime, showType) {
+ return pubfn.dateDiff(starttime, showType);
+}
+util.dateDiff2 = function(starttime, showType) {
+ return pubfn.dateDiff2(starttime, showType);
+};
+// 计数器1
+util.numStr = function(n) {
+ return pubfn.numStr(n);
+};
+
+util.timeStr = function(date) {
+ return pubfn.timeFormat(date);
+};
+/**
+ * 日期对象转字符串
+ * @description 最终转成 2020-08-01 12:12:12
+ * @param {Date || Number} date 需要转换的时间
+ * date参数支持
+ * 支持:时间戳
+ * 支持:2020-08
+ * 支持:2020-08-24
+ * 支持:2020-08-24 12
+ * 支持:2020-08-24 12:12
+ * 支持:2020-08-24 12:12:12
+ */
+util.timeFilter = function(date, fmt) {
+ return pubfn.timeFormat(date, fmt);
+};
+// 金额过滤器
+util.priceFilter = function(n, defaultValue = " - ") {
+ return pubfn.priceFilter(n, defaultValue);
+};
+// 金额过滤器 - 只显示小数点左边
+util.priceLeftFilter = function(n) {
+ return pubfn.priceLeftFilter(n);
+};
+// 金额过滤器 - 只显示小数点右边
+util.priceRightFilter = function(n) {
+ return pubfn.priceRightFilter(n);
+};
+// 百分比过滤器
+util.percentageFilter = function(n, needShowSymbol, defaultValue = " - ") {
+ return pubfn.percentageFilter(n, needShowSymbol, defaultValue);
+};
+// 折扣过滤器
+util.discountFilter = function(n, needShowSymbol, defaultValue = " - ") {
+ return pubfn.discountFilter(n, needShowSymbol, defaultValue);
+};
+// 大小过滤器 sizeFilter(1024,3,["B","KB","MB","GB"])
+util.sizeFilter = function(...obj) {
+ let res = pubfn.calcSize(...obj);
+ return res.title;
+};
+
+export default util;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.h5.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.h5.js
new file mode 100644
index 0000000..d77d5b3
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.h5.js
@@ -0,0 +1,60 @@
+// #ifdef H5
+/**
+ * H5专用的一些函数,会涉及到window等H5专用的内置对象。
+ */
+var h5 = {};
+
+// 引入 微信公众号 js_sdk 包
+import wx from './weixin-js-sdk'
+h5.wx = wx;
+
+/**
+ * 获取当前H5所在的环境
+ * let env = vk.h5.getEnv();
+ */
+h5.getEnv = function() {
+ let ua = window.navigator.userAgent.toLowerCase();
+ if (ua.match(/MicroMessenger/i) == 'micromessenger' && (ua.match(/miniprogram/i) == 'miniprogram')) {
+ // 微信小程序
+ return "mp-weixin";
+ }
+ if (ua.match(/MicroMessenger/i) == 'micromessenger') {
+ // 微信公众号
+ return "h5-weixin";
+ }
+ if (ua.match(/alipay/i) == 'alipay' && ua.match(/miniprogram/i) == 'miniprogram') {
+ return "mp-alipay";
+ }
+ if (ua.match(/alipay/i) == 'alipay') {
+ return "h5-alipay";
+ }
+ // 外部 H5
+ return "h5";
+};
+
+/**
+ * 获取当前项目根目录访问地址
+ * https://www.aaa.com/pages/index/index?a=1&b=1
+ * http://192.168.66.66:8080/pages/index/index?a=1&b=1
+ * 获取当前H5的url地址的https://www.aaa.com 部分
+ * let getRootPath = vk.h5.getRootPath();
+ * let getRootPath = vk.h5.getRootPath({ projectName:true });
+ */
+h5.getRootPath = function(obj={}) {
+ let {
+ projectName: _projectName = false
+ } = obj;
+ let wwwPath = window.location.href;
+ let pathName = window.location.pathname;
+ let pos = wwwPath.indexOf(pathName);
+ let localhostPaht = wwwPath.substring(0, pos);
+ let projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
+ let rootPath = localhostPaht;
+ if (_projectName) {
+ rootPath = localhostPaht + projectName;
+ }
+ return rootPath;
+};
+
+export default h5;
+// #endif
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.importObject.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.importObject.js
new file mode 100644
index 0000000..a0fb08b
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.importObject.js
@@ -0,0 +1,59 @@
+/**
+ * 导出云对象实例
+ * @param {String} name 云对象路径,如:client/pub
+ * @example const pubObject = uni.vk.importObject('client/pub'); // 导入云对象
+ * 注意,只能在声明 async 的函数内使用,如:
+async test(){
+ let res = await pubObject.getList({
+ title: "请求中",
+ data: {
+ a: 1,
+ b: "2"
+ }
+ });
+}
+ */
+var importObject = function(name, importObjectOptions = {}) {
+ const newObj = new Proxy(importObject, {
+ get: function(target, key, receiver) {
+ /**
+ * 导出云对象内的某个方法
+ * @param {Object} data 请求参数,如 { a:1, b:"2" } 云对象内可通过 let { a, b } = data; 获取参数
+ * @param {String} title 遮罩层提示语,为空或不传则代表不显示遮罩层。
+ * @param {Boolean} needAlert 为true代表请求错误时,会有弹窗提示。默认为true
+ * @param {Object} loading 与title二选一,格式为 { name: "loading", that: that } name是变量名,that是数据源,当发起请求时,自动that[name] = true; 请求结束后,自动that[name] = false;
+ */
+ return async function(options) {
+ // 如果importObjectOptions中指定了easy为true,代表options的值就是请求参数
+ if (importObjectOptions.easy) {
+ options = {
+ data: options
+ }
+ }
+ // 如果importObjectOptions中指定了data,代表有默认请求参数,需要加到请求参数中
+ if (importObjectOptions.data) {
+ if (typeof importObjectOptions.data === "function") {
+ options.data = Object.assign({}, importObjectOptions.data(), options.data)
+ } else {
+ options.data = Object.assign({}, importObjectOptions.data, options.data)
+ }
+ }
+ return uni.vk.callFunction({
+ ...importObjectOptions,
+ ...options,
+ url: `${name}.${key}`
+ });
+ }
+ },
+ // set: function(target, key, value, receiver) {
+ // console.log("set");
+ // console.log("target",target);
+ // console.log("key",key);
+ // console.log("value",value);
+ // console.log("receiver", receiver);
+ // },
+ });
+ return newObj;
+};
+
+export default importObject;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.localStorage.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.localStorage.js
new file mode 100644
index 0000000..63dca97
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.localStorage.js
@@ -0,0 +1,131 @@
+/**
+ * vk依赖扩展 - localStorage 本地缓存
+ * pub - 公共的可随时删除的缓存
+ * kh - 跟登录账号有关联的缓存
+ * sys - 系统级缓存 - 一般不删除
+ *
+ * 储存缓存
+ * vk.setStorageSync(key, data);
+ * 获取缓存
+ * vk.getStorageSync(key);
+ */
+var localStorage = {};
+/**
+ * 将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。
+ * @param {String} key 本地缓存中的指定的 key
+ * @param {Any} data 需要存储的内容,只支持原生类型、及能够通过 JSON.stringify 序列化的对象
+ */
+localStorage.setStorageSync = function(key, data) {
+ uni.setStorageSync(key, data);
+ watchLocalStorage({ type: "set", key, data });
+};
+
+/**
+ * 从本地缓存中异步获取指定 key 对应的内容。
+ * @param {String} key 本地缓存中的指定的 key
+ */
+localStorage.getStorageSync = function(key) {
+ let data = uni.getStorageSync(key);
+ // get 没有必要监听
+ // watchLocalStorage({ type:"get", key, data });
+ return data;
+};
+
+/**
+ * 同步获取当前 storage 的相关信息。
+ */
+localStorage.getStorageInfoSync = function() {
+ let info = uni.getStorageInfoSync();
+ let sizeInfo = calcSize(Number(info.currentSize), 1024, 3, ["KB", "MB", "GB"]);
+ info.sizeInfo = sizeInfo;
+ return info;
+};
+
+/**
+ * 从本地缓存中同步移除指定 key。
+ * @param {String} key 本地缓存中的指定的 key
+ */
+localStorage.removeStorageSync = function(key) {
+ uni.removeStorageSync(key);
+ watchLocalStorage({ type: "remove", key });
+};
+/**
+ * 从本地缓存中异步移除指定 key。
+ */
+localStorage.removeStorage = function(obj) {
+ uni.removeStorage({
+ key: obj.key,
+ success: (res) => {
+ watchLocalStorage({ type: "remove", key: obj.key });
+ if (obj.success) obj.success(res);
+ },
+ fail: obj.fail,
+ complete: obj.complete
+ });
+};
+
+/**
+ * 同步清理本地数据缓存。若key有值,则清除键值为指定字符串开头的缓存
+ * @param {String} key 本地缓存中的指定的 key
+ * vk.clearStorageSync();
+ */
+localStorage.clearStorageSync = function(key) {
+ if (key) {
+ let { keys } = uni.getStorageInfoSync();
+ if (keys) {
+ keys.map((keyName) => {
+ if (keyName.indexOf(key) == 0) {
+ localStorage.removeStorage({
+ key: keyName
+ });
+ }
+ });
+ }
+ } else {
+ uni.clearStorage();
+ watchLocalStorage({ type: "clear" });
+ }
+};
+
+export default localStorage;
+
+
+
+/**
+ * 单位进制换算
+ * length 换算前大小
+ * ary 进制,如KB-MB-GB,进制1024
+ * precision 数值精度
+ * arr 进制的数组,如["B","KB","MB","GB"]
+ * calcSize(length,1024,3,["B","KB","MB","GB"]);
+ */
+function calcSize(length = 0, ary, precision, arr) {
+ var size = parseFloat(length);
+ var mySize = 0;
+ var type = "";
+ if (size < ary || arr.length <= 1) {
+ type = arr[0];
+ mySize = parseFloat(size.toFixed(precision));
+ } else {
+ for (var i = 1; i < arr.length; i++) {
+ var g = arr[i];
+ size = size / ary;
+ if (size < ary) {
+ type = g;
+ mySize = parseFloat(size.toFixed(precision));
+ break;
+ }
+ }
+ }
+ return {
+ size: mySize,
+ type: type,
+ title: mySize + " " + type
+ }
+};
+
+function watchLocalStorage(obj) {
+ if (typeof localStorage.watch === "function") {
+ localStorage.watch(obj);
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.navigate.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.navigate.js
new file mode 100644
index 0000000..f4cb84b
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.navigate.js
@@ -0,0 +1,462 @@
+/**
+ * 函数 - 页面导航
+ */
+// #ifndef VUE3
+var config;
+try {
+ config = require('@/app.config.js');
+ if (typeof config.default === "object") {
+ config = config.default;
+ }
+} catch (e) {
+ config = {};
+}
+// #endif
+
+// #ifdef VUE3
+import config from '@/app.config.js'
+// #endif
+
+
+var util = {};
+var lastNavigate = {
+ url: "",
+ time: 0
+};
+/**
+ * 保留当前页面,跳转到应用内的某个页面,使用vk.navigateBack可以返回到原页面。
+ * vk.navigateTo(url);
+ */
+util.navigateTo = function(obj) {
+ let vk = uni.vk;
+ if (typeof obj == "string") {
+ let url = obj;
+ obj = {
+ url: url
+ };
+ } else if (typeof obj == "undefined") {
+ obj = {};
+ }
+ if (!obj.url) {
+ vk.toast("url不能为空!");
+ return false;
+ }
+ let time = Date.now();
+ if (lastNavigate.url === obj.url && (time - lastNavigate.time) < 200) {
+ return false;
+ }
+ lastNavigate = { url: obj.url, time };
+ util.checkNeedLogin({
+ url: obj.url,
+ success: function(res) {
+ if (res.needLogin) {
+ obj.url = vk.pubfn.getPageFullPath(obj.url);
+ vk.navigate.setOriginalPage(obj);
+ obj.url = config.login.url;
+ // login拦截器开始-----------------------------------------------------------
+ let { interceptor = {} } = config;
+ if (typeof interceptor.login === "function") {
+ let key = interceptor.login({
+ vk,
+ params: obj,
+ res: {
+ ...res,
+ code: 30204,
+ msg: "本地token校验未通过"
+ }
+ });
+ if (typeof key === "undefined" || key !== true) return false;
+ }
+ // login拦截器结束-----------------------------------------------------------
+ } else {
+ vk.navigate.setOriginalPage(null);
+ }
+ util._navigateTo(obj);
+ }
+ });
+};
+util._navigateTo = function(obj) {
+ let { interceptor = {} } = config;
+ if (typeof interceptor.navigateTo === "function") {
+ let vk = uni.vk;
+ obj.pagePath = vk.pubfn.getPageFullPath(obj.url);
+ let key = interceptor.navigateTo({
+ ...obj,
+ vk
+ });
+ if (typeof key == "boolean" && key === false) return false;
+ }
+ let {
+ url,
+ animationType = "pop-in",
+ animationDuration = 300,
+ events,
+ mode = "navigateTo"
+ } = obj;
+ // 此处写法仅为支持vue3,vue3不支持uni[apiName]的形式调用
+ let navigateFn;
+ if (mode === "navigateTo") {
+ navigateFn = uni.navigateTo;
+ } else if (mode === "redirectTo") {
+ navigateFn = uni.redirectTo;
+ } else if (mode === "reLaunch") {
+ navigateFn = uni.reLaunch;
+ } else if (mode === "switchTab") {
+ navigateFn = uni.switchTab;
+ } else {
+ navigateFn = uni.navigateTo;
+ }
+ // 此处写法仅为支持vue3,vue3不支持uni[apiName]的形式调用
+ navigateFn({
+ url: url,
+ animationType: animationType,
+ animationDuration: animationDuration,
+ events: events, // 参考 https://uniapp.dcloud.io/api/router?id=navigateto
+ success: function(res) {
+ if (typeof obj.success == "function") obj.success(res);
+ },
+ fail: function(err) {
+ if (err.errMsg.indexOf("not found") > -1) {
+ let vk = uni.vk;
+ let errUrl = vk.pubfn.getPageFullPath(url);
+ vk.toast(`页面 ${errUrl} 不存在`, "none");
+ console.error(err);
+ return false;
+ }
+ uni.switchTab({
+ url: url,
+ success: obj.success,
+ fail: function() {
+ uni.redirectTo({
+ url: url,
+ success: obj.success,
+ fail: function(err) {
+ console.error(err);
+ if (typeof obj.fail == "function") obj.fail(err);
+ }
+ });
+ }
+ });
+ },
+ complete: function(res) {
+ if (typeof obj.complete == "function") obj.complete(res);
+ }
+ });
+};
+
+/**
+ * 关闭当前页面,跳转到应用内的某个页面。
+ * vk.redirectTo(url);
+ */
+util.redirectTo = function(obj) {
+ obj = util.paramsInit(obj);
+ obj.mode = "redirectTo";
+ util.navigateTo(obj);
+};
+
+/**
+ * 关闭所有页面,打开到应用内的某个页面。
+ * vk.reLaunch(url);
+ */
+util.reLaunch = function(obj) {
+ obj = util.paramsInit(obj);
+ obj.mode = "reLaunch";
+ util.navigateTo(obj);
+};
+
+/**
+ * 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
+ * vk.switchTab(url);
+ */
+util.switchTab = function(obj) {
+ obj = util.paramsInit(obj);
+ obj.mode = "switchTab";
+ util.navigateTo(obj);
+};
+/**
+ * 关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。
+ * vk.navigateBack();
+ */
+util.navigateBack = function(obj) {
+ let vk = uni.vk;
+ if (typeof obj == "number") {
+ let delta = obj;
+ obj = {
+ delta: delta
+ };
+ } else if (typeof obj == "undefined") {
+ obj = {};
+ }
+ let {
+ delta = 1,
+ animationType = "pop-out",
+ animationDuration = 300
+ } = obj;
+ uni.navigateBack({
+ delta: delta,
+ animationType: animationType,
+ animationDuration: animationDuration,
+ success: function() {
+ if (typeof obj.success == "function") obj.success();
+ },
+ fail: function(res) {
+ console.error(res);
+ if (typeof obj.fail == "function") obj.fail();
+ },
+ complete: function() {
+ if (typeof obj.complete == "function") obj.complete();
+ }
+ });
+};
+/**
+ * 跳转到登录前的页面
+ * vk.navigate.originalTo();
+ */
+util.originalTo = function() {
+ let vk = uni.vk;
+ let originalPage = vk.navigate.getOriginalPage();
+ vk.navigate.setOriginalPage(null);
+ util.redirectTo(originalPage);
+};
+
+/**
+ * 获取登录前的页面
+ * vk.navigate.getOriginalPage();
+ */
+util.getOriginalPage = function() {
+ if (typeof uni.vk.getVuex === "function") {
+ // 有安装vuex则使用vuex
+ return uni.vk.getVuex('$app.originalPage');
+ } else {
+ // 未安装则使用本地缓存
+ return uni.vk.getStorageSync('vk.navigate.originalPage');
+ }
+};
+
+/**
+ * 设置登录前的页面
+ * vk.navigate.setOriginalPage(originalPage);
+ */
+util.setOriginalPage = function(originalPage) {
+ uni.vk.navigate.originalPage = originalPage; // 兼容老版本
+ if (typeof uni.vk.getVuex === "function") {
+ // 有安装vuex则使用vuex
+ return uni.vk.setVuex('$app.originalPage', originalPage);
+ } else {
+ // 未安装则使用本地缓存
+ return uni.vk.setStorageSync('vk.navigate.originalPage', originalPage);
+ }
+};
+
+
+/**
+ * 跳转到首页
+ * vk.navigateToHome();
+ */
+util.navigateToHome = function(obj = {}) {
+ let vk = uni.vk;
+ let {
+ mode = "reLaunch"
+ } = obj;
+ vk[mode](config.index.url);
+};
+
+/**
+ * 跳转到登录页
+ * vk.navigateToLogin();
+ */
+util.navigateToLogin = function(obj = {}) {
+ let vk = uni.vk;
+ let {
+ mode = "reLaunch"
+ } = obj;
+ vk[mode](config.login.url);
+};
+
+/**
+ * 检测是否满足条件(内部方法)
+ util.checkWildcardTest({
+ url:url,
+ pagesRule:config.checkTokenPages,
+ success:function(res){
+ if(res.success){
+
+ }
+ }
+ })
+ */
+util.checkWildcardTest = function(obj) {
+ let vk = uni.vk;
+ let {
+ url,
+ pagesRule
+ } = obj;
+ // ../ 转成绝对路径
+ url = vk.pubfn.getPageFullPath(url);
+ let key = false;
+ if (vk.pubfn.isNotNull(pagesRule)) {
+ let { mode = 0, list = [] } = pagesRule;
+ if (mode > 0) {
+ let regExpKey = false;
+ let path = util.getPagePath(url);
+ for (let i = 0; i < list.length; i++) {
+ let pageRegExp = list[i];
+ regExpKey = vk.pubfn.wildcardTest(path, pageRegExp);
+ if (regExpKey) {
+ break;
+ }
+ }
+ if (mode === 1 && regExpKey) {
+ key = true;
+ } else if (mode === 2 && !regExpKey) {
+ key = true;
+ }
+ }
+ }
+ return {
+ url,
+ key
+ };
+};
+
+
+/**
+ * 检测是否需要登录(内部方法)
+ util.checkNeedLogin({
+ url:url,
+ success:function(res){
+ if(res.needLogin){
+
+ }
+ }
+ })
+ */
+util.checkNeedLogin = function(obj) {
+ let vk = uni.vk;
+ let { url, success } = obj;
+ let needLogin = false; // 用户是否需要重新登录
+ let pageNeedLogin = false; // 该页面是否需要登录才能访问
+ let pagesRule = config.checkTokenPages;
+ if (pagesRule) {
+ let res = util.checkWildcardTest({
+ url,
+ pagesRule
+ });
+ pageNeedLogin = res.key;
+ if (pageNeedLogin) {
+ // 本地判断token有效期(联网会浪费性能)
+ if (!vk.checkToken()) {
+ needLogin = true;
+ }
+ }
+ }
+ success({
+ url,
+ needLogin,
+ pageNeedLogin
+ });
+};
+
+
+// 获取?前面的地址
+util.getPagePath = function(url) {
+ let pathIndex = url.indexOf("?");
+ let path = url;
+ if (pathIndex > -1) {
+ path = path.substring(0, pathIndex);
+ }
+ return path;
+};
+
+util.paramsInit = function(obj) {
+ let vk = uni.vk;
+ if (typeof obj == "string") {
+ let url = obj;
+ obj = {
+ url: url
+ };
+ } else if (typeof obj == "undefined") {
+ obj = {};
+ }
+ if (!obj.url) {
+ vk.toast("url不能为空!");
+ return false;
+ }
+ return obj;
+}
+
+
+
+/**
+ * 跳转到小程序
+ vk.navigateToMiniProgram({
+ appId: 'appId',
+ path: 'pages/index/index',
+ extraData:{
+ //发送数据携带的参数
+ },
+ success(res) {
+ // 打开成功
+
+ }
+ })
+ */
+util.navigateToMiniProgram = function(obj) {
+ let vk = uni.vk;
+ // #ifdef H5
+ vk.toast("不支持打开小程序", "none");
+ // #endif
+
+ // #ifndef H5
+ uni.navigateToMiniProgram(obj);
+ // #endif
+};
+
+
+/**
+ * 检测是否可以分享(内部方法)
+ util.checkAllowShare({
+ url:url,
+ });
+ */
+util.checkAllowShare = function(obj) {
+ let vk = uni.vk;
+ let { url, success } = obj;
+ let pagesRule = config.checkSharePages || {};
+ if (pagesRule && pagesRule.mode > 0) {
+ let res = util.checkWildcardTest({
+ url,
+ pagesRule
+ });
+ // #ifdef MP
+ let menus = pagesRule.menus || ['shareAppMessage', 'shareTimeline'];
+ if (res.key) {
+ //console.log("允许分享");
+ uni.showShareMenu({
+ withShareTicket: false,
+ menus
+ });
+ } else {
+ //console.log("禁止分享");
+ uni.hideShareMenu({
+ menus
+ })
+ }
+ // #endif
+ }
+};
+
+util.$emit = function(...obj) {
+ return uni.$emit(...obj);
+};
+util.$on = function(...obj) {
+ return uni.$on(...obj);
+};
+util.$once = function(...obj) {
+ return uni.$once(...obj);
+};
+util.$off = function(...obj) {
+ return uni.$off(...obj);
+};
+
+export default util;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.request.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.request.js
new file mode 100644
index 0000000..ee3e9ca
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.request.js
@@ -0,0 +1,434 @@
+var requestUtil = {};
+
+
+requestUtil.config = {
+ // 请求配置
+ request: {
+ // 公共请求参数(每次请求都会带上的参数)
+ dataParam: {}
+ },
+ requestGlobalParamKeyName: "vk_url_request_global_param",
+ debug: process.env.NODE_ENV !== "production",
+ // 日志风格
+ logger: {
+ colorArr: [
+ "#0095ff",
+ "#67C23A"
+ ]
+ },
+};
+var counterNum = 0;
+/**
+ * request 请求库
+ * 注意: 该请求库目前主要是框架自身使用,且近期变动频率较高,目前请勿使用在你自己的业务中。
+ * @param {String} url 服务器接口地址
+ * @param {Object/String/ArrayBuffer} data 请求的参数 App(自定义组件编译模式)不支持ArrayBuffer类型
+ * @param {Object} header 设置请求的 header,header 中不能设置 Referer。 App、H5端会自动带上cookie,且H5端不可手动修改
+ * @param {String} method 默认 POST 可选 GET
+ * @param {Number} timeout 超时时间,单位 ms 默认3000(30秒)
+ * @param {String} dataType 默认json 如果设为 json,会尝试对返回的数据做一次 JSON.parse
+ * @param {String} responseType 默认 text 设置响应的数据类型。合法值:text、arraybuffer App和支付宝小程序不支持
+ * @param {Boolean} sslVerify 默认 true 是否需要验证ssl证书 仅App安卓端支持(HBuilderX 2.3.3+) 仅App安卓端支持(HBuilderX 2.3.3+)
+ * @param {Boolean} withCredentials 默认 false 跨域请求时是否携带凭证(cookies) 仅H5支持(HBuilderX 2.6.15+)
+ * @param {Boolean} firstIpv4 默认 false DNS解析时优先使用ipv4 仅 App-Android 支持 (HBuilderX 2.8.0+)
+ * @param {String} success 成功回调
+ * @param {String} fail 失败回调
+ * @param {String} complete 完成回调
+ * 以下为特殊参数
+ * @param {String} errorCodeName 服务器返回的错误码的字段名,若不为空,则会对返回结果进行判断
+ * @param {String} errorMsgName 服务器返回的错误码的字符串含义,若不为空,且errorCodeName对应的值不为0,则会alert弹窗
+ * @param {Boolean} needAlert 服务器返回的错误时,是否需要alert弹出提示
+ *
+ * 调用示例
+vk.request({
+ url: `https://www.xxx.com/api/xxxx`,
+ method:"POST",
+ header:{
+ "content-type": "application/json; charset=utf-8",
+ },
+ data:{
+
+ },
+ success: function(data){
+
+ },
+ fail: function(err){
+
+ }
+});
+ */
+
+requestUtil.request = function(obj = {}) {
+ let vk = uni.vk;
+ // 去除值为 undefined 的参数
+ if (typeof obj.data === "object") {
+ obj.data = vk.pubfn.copyObject(obj.data);
+ }
+ // 注入自定义全局参数开始-----------------------------------------------------------
+ let config = requestUtil.config;
+ let globalParam = uni.getStorageSync(config.requestGlobalParamKeyName) || {};
+ // 根据正则规格自动匹配全局请求参数
+ for (let i in globalParam) {
+ let customDate = globalParam[i];
+ if (customDate.regExp) {
+ if (typeof customDate.regExp === "object") {
+ // 数组形式
+ for (let i = 0; i < customDate.regExp.length; i++) {
+ let regExp = new RegExp(customDate.regExp[i]);
+ if (regExp.test(obj.url)) {
+ obj.data = Object.assign(customDate.data, obj.data);
+ break;
+ }
+ }
+ } else {
+ // 字符串形式
+ let regExp = new RegExp(customDate.regExp);
+ if (regExp.test(obj.url)) {
+ obj.data = Object.assign(customDate.data, obj.data);
+ }
+ }
+ }
+ }
+ // 根据指定globalParamName匹配全局请求参数
+ let customDate = requestUtil.getRequestGlobalParam(obj.globalParamName);
+ if (customDate && JSON.stringify(customDate) !== "{}") {
+ if (customDate.regExp) {
+ obj.data = Object.assign(customDate.data, obj.data); // 新版本
+ } else {
+ obj.data = Object.assign(customDate, obj.data); // 兼容旧版本
+ }
+ }
+ // 注入自定义全局参数结束-----------------------------------------------------------
+
+ if (!obj.method) obj.method = "POST"; // 默认POST请求
+ if (typeof obj.dataType === "undefined") obj.dataType = "json";
+ if (obj.dataType == "default" || obj.dataType === "") delete obj.dataType;
+ if (typeof obj.header === "undefined" && typeof obj.headers !== "undefined") {
+ obj.header = obj.headers;
+ }
+
+ // 自动注入token到请求头开始-----------------------------------------------------------
+ // 注意:自2.15.1开始,需要手动指定uniIdToken: true 才会自动添加token到请求头里
+ if (typeof vk.getToken === "function" && obj.uniIdToken) {
+ let uni_id_token;
+ if (obj.uniIdToken === true) {
+ uni_id_token = vk.getToken();
+ } else if (typeof obj.uniIdToken === "boolean") {
+ uni_id_token = obj.uniIdToken;
+ }
+ if (uni_id_token) {
+ if (!obj.header) obj.header = {};
+ obj.header["uni-id-token"] = uni_id_token;
+ }
+ }
+ // 自动注入token到请求头结束-----------------------------------------------------------
+ let interceptor = obj.interceptor;
+ delete obj.interceptor;
+ if (interceptor && typeof interceptor.invoke === "function") {
+ let interceptorRes = interceptor.invoke(obj);
+ if (interceptorRes === false) {
+ return;
+ }
+ }
+ if (typeof obj.timeout === "undefined") obj.timeout = 30000; // 超时时间,单位 ms(默认30秒)
+ let Logger = {};
+ if (config.debug) {
+ Logger.params = (typeof obj.data == "object") ? vk.pubfn.copyObject(obj.data) : obj.data;
+ Logger.startTime = new Date().getTime();
+ let url = obj.url;
+ let path = obj.url.split("?")[0];
+ if (path.indexOf("://") > -1) {
+ path = path.substring(path.indexOf("://") + 3);
+ Logger.domainName = path.substring(0, path.indexOf("/"));
+ } else {
+ Logger.domainName = "";
+ }
+ Logger.action = path.substring(path.indexOf("/") + 1);
+ Logger.url = url;
+ }
+ if (obj.title) vk.showLoading(obj.title);
+ if (obj.loading) vk.setLoading(true, obj.loading);
+ let promiseAction = new Promise(function(resolve, reject) {
+ uni.request({
+ ...obj,
+ success: (res) => {
+ if (interceptor && typeof interceptor.success === "function") {
+ let interceptorRes = interceptor.success(res);
+ if (interceptorRes === false) {
+ return;
+ }
+ }
+ requestSuccess({
+ res,
+ params: obj,
+ Logger,
+ resolve,
+ reject
+ });
+ },
+ fail: (res) => {
+ if (interceptor && typeof interceptor.fail === "function") {
+ let interceptorRes = interceptor.fail(res);
+ if (interceptorRes === false) {
+ return;
+ }
+ }
+ requestFail({
+ res,
+ params: obj,
+ Logger,
+ reject
+ });
+ },
+ complete: (res) => {
+ if (interceptor && typeof interceptor.complete === "function") {
+ let interceptorRes = interceptor.complete(res);
+ if (interceptorRes === false) {
+ return;
+ }
+ }
+ requestComplete({
+ res,
+ params: obj,
+ Logger
+ });
+ }
+ });
+ });
+ promiseAction.catch(error => {});
+ return promiseAction;
+}
+// 请求成功回调
+function requestSuccess(obj = {}) {
+ let vk = uni.vk;
+ let config = requestUtil.config;
+ let {
+ res = {},
+ params,
+ Logger,
+ resolve,
+ reject
+ } = obj;
+ let {
+ title,
+ needOriginalRes,
+ dataType,
+ errorCodeName,
+ errorMsgName,
+ success,
+ loading
+ } = params;
+ let data = res.data || {};
+ if (vk.pubfn.isNotNullAll(errorCodeName, data[errorCodeName])) {
+ data.code = data[errorCodeName];
+ delete data[errorCodeName];
+ }
+ if (vk.pubfn.isNotNullAll(errorMsgName, data[errorMsgName])) {
+ data.msg = data[errorMsgName];
+ if (typeof data[errorMsgName] === "string") {
+ delete data[errorMsgName];
+ }
+ }
+ if (config.debug) Logger.result = (typeof data == "object") ? vk.pubfn.copyObject(data) : data;
+ if ([1301, 1302, 30201, 30202, 30203, 30204].indexOf(data.code) > -1 && data.msg.indexOf("token") > -1) {
+ // 执行 login 拦截器函数(跳转到页面页面)
+ let { interceptor = {} } = vk.callFunctionUtil;
+ if (typeof interceptor.login === "function") {
+ interceptor.login({
+ res: data,
+ params,
+ vk
+ });
+ }
+ reject(data);
+ } else if (res.statusCode >= 400 || data.code) {
+ requestFail({
+ res: data,
+ params,
+ Logger,
+ reject
+ });
+ } else {
+ if (title) vk.hideLoading();
+ if (loading) vk.setLoading(false, loading);
+ if (needOriginalRes) data.originalRes = vk.pubfn.copyObject(res);
+ if (data.vk_uni_token) vk.callFunctionUtil.saveToken(data.vk_uni_token);
+ if (data.userInfo && data.needUpdateUserInfo) vk.callFunctionUtil.updateUserInfo(data);
+ if (typeof success === "function") success(data);
+ if (typeof resolve === "function") resolve(data);
+ }
+}
+
+// 请求失败回调
+function requestFail(obj = {}) {
+ let vk = uni.vk;
+ let config = requestUtil.config;
+ let {
+ res = {},
+ params,
+ Logger,
+ reject
+ } = obj;
+ let {
+ title,
+ needAlert,
+ fail,
+ loading
+ } = params;
+ if (typeof needAlert === "undefined") {
+ needAlert = (typeof fail === "function") ? false : true;
+ }
+
+ let errMsg = "";
+ let sysErr = false;
+ if (typeof res.code !== "undefined") {
+ errMsg = res.msg;
+ } else {
+ sysErr = true;
+ errMsg = JSON.stringify(res);
+ }
+ if (errMsg.indexOf("fail timeout") > -1) {
+ sysErr = true;
+ errMsg = "请求超时,请重试!";
+ }
+ if (config.debug) Logger.error = res;
+ if (title) vk.hideLoading();
+ if (loading) vk.setLoading(false, loading);
+ let runKey = true;
+ // 自定义拦截器开始-----------------------------------------------------------
+ let { interceptor = {} } = vk.callFunctionUtil.getConfig();
+ if (interceptor.request && typeof interceptor.request.fail == "function") {
+ runKey = interceptor.request.fail({
+ vk,
+ res: res,
+ params: params
+ });
+ if (runKey === undefined) runKey = true;
+ }
+ // 自定义拦截器结束-----------------------------------------------------------
+ if (runKey) {
+ if (needAlert && vk.pubfn.isNotNull(errMsg)) {
+ if (sysErr) {
+ vk.toast("网络开小差了!", "none");
+ } else {
+ vk.alert(errMsg);
+ }
+ }
+ if (typeof fail === "function") fail(res);
+ if (typeof reject === "function") reject(res);
+ }
+
+}
+
+// 请求完成回调
+function requestComplete(obj = {}) {
+ let vk = uni.vk;
+ let config = requestUtil.config;
+ let {
+ res = {},
+ params,
+ Logger
+ } = obj;
+ let {
+ title,
+ needOriginalRes,
+ complete
+ } = params;
+ if (config.debug) {
+ Logger.endTime = new Date().getTime();
+ Logger.runTime = (Logger.endTime - Logger.startTime);
+ let colorArr = config.logger.colorArr;
+ let colorStr = colorArr[counterNum % colorArr.length];
+ counterNum++;
+ console.log("%c--------【开始】【服务器请求】【" + Logger.action + "】--------", 'color: ' + colorStr + ';font-size: 12px;font-weight: bold;');
+ console.log("【请求地址】: ", Logger.url);
+ console.log("【请求参数】: ", Logger.params);
+ console.log("【返回数据】: ", Logger.result);
+ console.log("【请求状态】: ", res.statusCode, "【http状态码】");
+ console.log("【总体耗时】: ", Logger.runTime, "毫秒【含页面渲染】");
+ console.log("【请求时间】: ", vk.pubfn.timeFormat(Logger.startTime, "yyyy-MM-dd hh:mm:ss"));
+ if (Logger.error) {
+ let errorLog = console.warn || console.error;
+ if (Logger.error.err && Logger.error.err.stack) {
+ console.error("【Error】: ", Logger.error);
+ console.error("【Stack】: ", Logger.error.err.stack);
+ } else {
+ errorLog("【Error】: ", Logger.error);
+ }
+ }
+ console.log("%c--------【结束】【服务器请求】【" + Logger.action + "】--------", 'color: ' + colorStr + ';font-size: 12px;font-weight: bold;');
+ }
+ let data = res.data;
+ if (needOriginalRes) data.originalRes = vk.pubfn.copyObject(res);
+ if (typeof complete === "function") complete(data);
+}
+
+/**
+ * 修改请求配置中的公共请求参数
+ * 若把shop-manage改成*则代表全局
+ vk.requestUtil.updateRequestGlobalParam({
+ "shop-manage":{
+ regExp:"^xxx/kh/",
+ data:{
+ shop_id : shop_id
+ }
+ }
+ });
+ 对应的request中增加参数globalParamName:"shop-manage"
+ vk.request({
+ url: 'xxx/xxxxxx',
+ title: '请求中...',
+ globalParamName:"shop-manage",// 如果设置了正则规则,则不需要此参数
+ data: {},
+ success(data) {
+ }
+ });
+ */
+requestUtil.updateRequestGlobalParam = (data = {}, setKey) => {
+ let vk = uni.vk;
+ let config = requestUtil.config;
+ if (setKey) {
+ // 覆盖对象
+ config.request.dataParam = data;
+ } else {
+ // 覆盖参数(有就覆盖,没有则新增)
+ config.request.dataParam = Object.assign(config.request.dataParam, data);
+ }
+ vk.setStorageSync(config.requestGlobalParamKeyName, config.request.dataParam);
+}
+
+/**
+ * 获取请求配置中的公共请求参数
+ vk.requestUtil.getRequestGlobalParam();
+ */
+requestUtil.getRequestGlobalParam = (globalParamName = "*") => {
+ let vk = uni.vk;
+ let config = requestUtil.config;
+ let data = config.request.dataParam;
+ if (!data || JSON.stringify(data) === "{}") {
+ data = uni.getStorageSync(config.requestGlobalParamKeyName) || {};
+ config.request.dataParam = data;
+ }
+ let param = data[globalParamName] || {};
+ return JSON.parse(JSON.stringify(param));
+}
+
+/**
+ * 删除请求配置中的公共请求参数
+ * globalParamName 不传代表删除所有
+ vk.requestUtil.deleteRequestGlobalParam(globalParamName);
+ */
+requestUtil.deleteRequestGlobalParam = (globalParamName) => {
+ let vk = uni.vk;
+ let config = requestUtil.config;
+ let globalParam = uni.getStorageSync(config.requestGlobalParamKeyName) || {};
+ if (globalParamName) {
+ delete globalParam[globalParamName];
+ } else {
+ globalParam = {};
+ }
+ config.request.dataParam = globalParam;
+ vk.setStorageSync(config.requestGlobalParamKeyName, globalParam);
+}
+
+export default requestUtil;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.sessionStorage.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.sessionStorage.js
new file mode 100644
index 0000000..fd29637
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/vk.sessionStorage.js
@@ -0,0 +1,146 @@
+/**
+ * vk依赖扩展 - sessionStorage 本地会话缓存(仅H5可用)
+ * sessionStorage 属性允许你访问一个,对应当前源的 session Storage 对象。
+ * 它与 localStorage 相似,不同之处在于 localStorage 里面存储的数据没有过期时间设置
+ * 而存储在 sessionStorage 里面的数据在页面会话结束时会被清除。
+ * pub - 公共的可随时删除的缓存
+ * kh - 跟登录账号有关联的缓存
+ * sys - 系统级缓存 - 一般不删除
+ *
+ * 储存缓存
+ * vk.setSessionStorageSync(key, data);
+ * 获取缓存
+ * vk.getSessionStorageSync(key);
+ */
+var storage = {};
+/**
+ * 将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。
+ * @param {String} key 本地缓存中的指定的 key
+ * @param {Any} data 需要存储的内容,只支持原生类型、及能够通过 JSON.stringify 序列化的对象
+ * vk.setSessionStorageSync(key, data);
+ */
+storage.setSessionStorageSync = function(key, data = "") {
+ // #ifdef H5
+ let type = typeof data;
+ let value = {
+ type: typeof data,
+ data: data
+ };
+ sessionStorage.setItem(key, JSON.stringify(value));
+ watchSessionStorage({ type: "set", key, data });
+ // #endif
+
+ // #ifndef H5
+ console.warn("非H5环境不支持此API");
+ // #endif
+};
+
+/**
+ * 从本地缓存中异步获取指定 key 对应的内容。
+ * @param {String} key 本地缓存中的指定的 key
+ * vk.getSessionStorageSync(key);
+ */
+storage.getSessionStorageSync = function(key) {
+ // #ifdef H5
+ let data;
+ try {
+ let value = JSON.parse(sessionStorage.getItem(key));
+ data = value.data;
+ } catch (err) {
+ data = sessionStorage.getItem(key);
+ }
+ // get 没有必要监听
+ // watchSessionStorage({ type:"get", key, data });
+ return data;
+ // #endif
+
+ // #ifndef H5
+ console.warn("非H5环境不支持此API");
+ // #endif
+};
+
+/**
+ * 从本地缓存中同步移除指定 key。
+ * @param {String} key 本地缓存中的指定的 key
+ * vk.removeSessionStorageSync(key);
+ */
+storage.removeSessionStorageSync = function(key) {
+ // #ifdef H5
+ sessionStorage.removeItem(key);
+ watchSessionStorage({ type: "remove", key });
+ // #endif
+
+ // #ifndef H5
+ console.warn("非H5环境不支持此API");
+ // #endif
+};
+
+/**
+ * 同步清理本地数据缓存。若key有值,则清除键值为指定字符串开头的缓存
+ * @param {String} key 本地缓存中的指定的 key
+ * vk.clearSessionStorageSync();
+ */
+storage.clearSessionStorageSync = function(key) {
+ // #ifdef H5
+ if (key) {
+ let keys = Object.keys(sessionStorage);
+ if (keys) {
+ keys.map((keyName) => {
+ if (keyName.indexOf(key) == 0) {
+ sessionStorage.removeItem(keyName);
+ }
+ });
+ }
+ } else {
+ sessionStorage.clear();
+ watchSessionStorage({ type: "clear" });
+ }
+ // #endif
+
+ // #ifndef H5
+ console.warn("非H5环境不支持此API");
+ // #endif
+};
+
+export default storage;
+
+
+
+/**
+ * 单位进制换算
+ * length 换算前大小
+ * ary 进制,如KB-MB-GB,进制1024
+ * precision 数值精度
+ * arr 进制的数组,如["B","KB","MB","GB"]
+ * calcSize(length,1024,3,["B","KB","MB","GB"]);
+ */
+function calcSize(length = 0, ary, precision, arr) {
+ var size = parseFloat(length);
+ var mySize = 0;
+ var type = "";
+ if (size < ary || arr.length <= 1) {
+ type = arr[0];
+ mySize = parseFloat(size.toFixed(precision));
+ } else {
+ for (var i = 1; i < arr.length; i++) {
+ var g = arr[i];
+ size = size / ary;
+ if (size < ary) {
+ type = g;
+ mySize = parseFloat(size.toFixed(precision));
+ break;
+ }
+ }
+ }
+ return {
+ size: mySize,
+ type: type,
+ title: mySize + " " + type
+ }
+};
+
+function watchSessionStorage(obj) {
+ if (typeof storage.watch === "function") {
+ storage.watch(obj);
+ }
+}
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/weixin-js-sdk.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/weixin-js-sdk.js
new file mode 100644
index 0000000..b605321
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/function/weixin-js-sdk.js
@@ -0,0 +1,890 @@
+function n(o, e) {
+ if (!o.jWeixin) {
+ var n,
+ c = {
+ config: "preVerifyJSAPI",
+ onMenuShareTimeline: "menu:share:timeline",
+ onMenuShareAppMessage: "menu:share:appmessage",
+ onMenuShareQQ: "menu:share:qq",
+ onMenuShareWeibo: "menu:share:weiboApp",
+ onMenuShareQZone: "menu:share:QZone",
+ previewImage: "imagePreview",
+ getLocation: "geoLocation",
+ openProductSpecificView: "openProductViewWithPid",
+ addCard: "batchAddCard",
+ openCard: "batchViewCard",
+ chooseWXPay: "getBrandWCPayRequest",
+ openEnterpriseRedPacket: "getRecevieBizHongBaoRequest",
+ startSearchBeacons: "startMonitoringBeacons",
+ stopSearchBeacons: "stopMonitoringBeacons",
+ onSearchBeacons: "onBeaconsInRange",
+ consumeAndShareCard: "consumedShareCard",
+ openAddress: "editAddress"
+ },
+ a = (function() {
+ var e = {};
+ for (var n in c) e[c[n]] = n;
+ return e;
+ })(),
+ i = o.document,
+ t = i.title,
+ r = navigator.userAgent.toLowerCase(),
+ s = navigator.platform.toLowerCase(),
+ d = !(!s.match("mac") && !s.match("win")),
+ u = -1 != r.indexOf("wxdebugger"),
+ l = -1 != r.indexOf("micromessenger"),
+ p = -1 != r.indexOf("android"),
+ f = -1 != r.indexOf("iphone") || -1 != r.indexOf("ipad"),
+ m = (n =
+ r.match(/micromessenger\/(\d+\.\d+\.\d+)/) ||
+ r.match(/micromessenger\/(\d+\.\d+)/)) ?
+ n[1] :
+ "",
+ g = {
+ initStartTime: L(),
+ initEndTime: 0,
+ preVerifyStartTime: 0,
+ preVerifyEndTime: 0
+ },
+ h = {
+ version: 1,
+ appId: "",
+ initTime: 0,
+ preVerifyTime: 0,
+ networkType: "",
+ isPreVerifyOk: 1,
+ systemType: f ? 1 : p ? 2 : -1,
+ clientVersion: m,
+ url: encodeURIComponent(location.href)
+ },
+ v = {},
+ S = { _completes: [] },
+ y = { state: 0, data: {} };
+ O(function() {
+ g.initEndTime = L();
+ });
+ var I = !1,
+ _ = [],
+ w = {
+ config: function(e) {
+ B("config", (v = e));
+ var t = !1 !== v.check;
+ O(function() {
+ if (t)
+ M(
+ c.config, {
+ verifyJsApiList: C(v.jsApiList),
+ verifyOpenTagList: C(v.openTagList)
+ },
+ (function() {
+ (S._complete = function(e) {
+ (g.preVerifyEndTime = L()), (y.state = 1), (y.data = e);
+ }),
+ (S.success = function(e) {
+ h.isPreVerifyOk = 0;
+ }),
+ (S.fail = function(e) {
+ S._fail ? S._fail(e) : (y.state = -1);
+ });
+ var t = S._completes;
+ return (
+ t.push(function() {
+ !(function() {
+ if (
+ !(
+ d ||
+ u ||
+ v.debug ||
+ m < "6.0.2" ||
+ h.systemType < 0
+ )
+ ) {
+ var i = new Image();
+ (h.appId = v.appId),
+ (h.initTime = g.initEndTime - g
+ .initStartTime),
+ (h.preVerifyTime =
+ g.preVerifyEndTime - g
+ .preVerifyStartTime),
+ w.getNetworkType({
+ isInnerInvoke: !0,
+ success: function(e) {
+ h.networkType =
+ e
+ .networkType;
+ var n =
+ "https://open.weixin.qq.com/sdk/report?v=" +
+ h.version +
+ "&o=" +
+ h
+ .isPreVerifyOk +
+ "&s=" +
+ h
+ .systemType +
+ "&c=" +
+ h
+ .clientVersion +
+ "&a=" +
+ h.appId +
+ "&n=" +
+ h
+ .networkType +
+ "&i=" +
+ h.initTime +
+ "&p=" +
+ h
+ .preVerifyTime +
+ "&u=" +
+ h.url;
+ i.src = n;
+ }
+ });
+ }
+ })();
+ }),
+ (S.complete = function(e) {
+ for (var n = 0, i = t.length; n < i; ++n) t[n]
+ ();
+ S._completes = [];
+ }),
+ S
+ );
+ })()
+ ),
+ (g.preVerifyStartTime = L());
+ else {
+ y.state = 1;
+ for (var e = S._completes, n = 0, i = e.length; n < i; ++n)
+ e[n]();
+ S._completes = [];
+ }
+ }),
+ w.invoke ||
+ ((w.invoke = function(e, n, i) {
+ o.WeixinJSBridge && WeixinJSBridge.invoke(e, x(n), i);
+ }),
+ (w.on = function(e, n) {
+ o.WeixinJSBridge && WeixinJSBridge.on(e, n);
+ }));
+ },
+ ready: function(e) {
+ 0 != y.state ? e() : (S._completes.push(e), !l && v.debug && e());
+ },
+ error: function(e) {
+ m < "6.0.2" || (-1 == y.state ? e(y.data) : (S._fail = e));
+ },
+ checkJsApi: function(e) {
+ M(
+ "checkJsApi", { jsApiList: C(e.jsApiList) },
+ ((e._complete = function(e) {
+ if (p) {
+ var n = e.checkResult;
+ n && (e.checkResult = JSON.parse(n));
+ }
+ e = (function(e) {
+ var n = e.checkResult;
+ for (var i in n) {
+ var t = a[i];
+ t && ((n[t] = n[i]), delete n[i]);
+ }
+ return e;
+ })(e);
+ }),
+ e)
+ );
+ },
+ onMenuShareTimeline: function(e) {
+ P(
+ c.onMenuShareTimeline, {
+ complete: function() {
+ M(
+ "shareTimeline", {
+ title: e.title || t,
+ desc: e.title || t,
+ img_url: e.imgUrl || "",
+ link: e.link || location.href,
+ type: e.type || "link",
+ data_url: e.dataUrl || ""
+ },
+ e
+ );
+ }
+ },
+ e
+ );
+ },
+ onMenuShareAppMessage: function(n) {
+ P(
+ c.onMenuShareAppMessage, {
+ complete: function(e) {
+ "favorite" === e.scene ?
+ M("sendAppMessage", {
+ title: n.title || t,
+ desc: n.desc || "",
+ link: n.link || location.href,
+ img_url: n.imgUrl || "",
+ type: n.type || "link",
+ data_url: n.dataUrl || ""
+ }) :
+ M(
+ "sendAppMessage", {
+ title: n.title || t,
+ desc: n.desc || "",
+ link: n.link || location.href,
+ img_url: n.imgUrl || "",
+ type: n.type || "link",
+ data_url: n.dataUrl || ""
+ },
+ n
+ );
+ }
+ },
+ n
+ );
+ },
+ onMenuShareQQ: function(e) {
+ P(
+ c.onMenuShareQQ, {
+ complete: function() {
+ M(
+ "shareQQ", {
+ title: e.title || t,
+ desc: e.desc || "",
+ img_url: e.imgUrl || "",
+ link: e.link || location.href
+ },
+ e
+ );
+ }
+ },
+ e
+ );
+ },
+ onMenuShareWeibo: function(e) {
+ P(
+ c.onMenuShareWeibo, {
+ complete: function() {
+ M(
+ "shareWeiboApp", {
+ title: e.title || t,
+ desc: e.desc || "",
+ img_url: e.imgUrl || "",
+ link: e.link || location.href
+ },
+ e
+ );
+ }
+ },
+ e
+ );
+ },
+ onMenuShareQZone: function(e) {
+ P(
+ c.onMenuShareQZone, {
+ complete: function() {
+ M(
+ "shareQZone", {
+ title: e.title || t,
+ desc: e.desc || "",
+ img_url: e.imgUrl || "",
+ link: e.link || location.href
+ },
+ e
+ );
+ }
+ },
+ e
+ );
+ },
+ updateTimelineShareData: function(e) {
+ M(
+ "updateTimelineShareData", { title: e.title, link: e.link, imgUrl: e.imgUrl },
+ e
+ );
+ },
+ updateAppMessageShareData: function(e) {
+ M(
+ "updateAppMessageShareData", {
+ title: e.title,
+ desc: e.desc,
+ link: e.link,
+ imgUrl: e
+ .imgUrl
+ },
+ e
+ );
+ },
+ startRecord: function(e) {
+ M("startRecord", {}, e);
+ },
+ stopRecord: function(e) {
+ M("stopRecord", {}, e);
+ },
+ onVoiceRecordEnd: function(e) {
+ P("onVoiceRecordEnd", e);
+ },
+ playVoice: function(e) {
+ M("playVoice", { localId: e.localId }, e);
+ },
+ pauseVoice: function(e) {
+ M("pauseVoice", { localId: e.localId }, e);
+ },
+ stopVoice: function(e) {
+ M("stopVoice", { localId: e.localId }, e);
+ },
+ onVoicePlayEnd: function(e) {
+ P("onVoicePlayEnd", e);
+ },
+ uploadVoice: function(e) {
+ M(
+ "uploadVoice", {
+ localId: e.localId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ downloadVoice: function(e) {
+ M(
+ "downloadVoice", {
+ serverId: e.serverId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ translateVoice: function(e) {
+ M(
+ "translateVoice", {
+ localId: e.localId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ chooseImage: function(e) {
+ M(
+ "chooseImage", {
+ scene: "1|2",
+ count: e.count || 9,
+ sizeType: e.sizeType || ["original", "compressed"],
+ sourceType: e.sourceType || ["album", "camera"]
+ },
+ ((e._complete = function(e) {
+ if (p) {
+ var n = e.localIds;
+ try {
+ n && (e.localIds = JSON.parse(n));
+ } catch (e) {}
+ }
+ }),
+ e)
+ );
+ },
+ getLocation: function(e) {},
+ previewImage: function(e) {
+ M(c.previewImage, { current: e.current, urls: e.urls }, e);
+ },
+ uploadImage: function(e) {
+ M(
+ "uploadImage", {
+ localId: e.localId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ downloadImage: function(e) {
+ M(
+ "downloadImage", {
+ serverId: e.serverId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ getLocalImgData: function(e) {
+ !1 === I ?
+ ((I = !0),
+ M(
+ "getLocalImgData", { localId: e.localId },
+ ((e._complete = function(e) {
+ if (((I = !1), 0 < _.length)) {
+ var n = _.shift();
+ wx.getLocalImgData(n);
+ }
+ }),
+ e)
+ )) :
+ _.push(e);
+ },
+ getNetworkType: function(e) {
+ M(
+ "getNetworkType", {},
+ ((e._complete = function(e) {
+ e = (function(e) {
+ var n = e.errMsg;
+ e.errMsg = "getNetworkType:ok";
+ var i = e.subtype;
+ if ((delete e.subtype, i)) e.networkType = i;
+ else {
+ var t = n.indexOf(":"),
+ o = n.substring(t + 1);
+ switch (o) {
+ case "wifi":
+ case "edge":
+ case "wwan":
+ e.networkType = o;
+ break;
+ default:
+ e.errMsg = "getNetworkType:fail";
+ }
+ }
+ return e;
+ })(e);
+ }),
+ e)
+ );
+ },
+ openLocation: function(e) {
+ M(
+ "openLocation", {
+ latitude: e.latitude,
+ longitude: e.longitude,
+ name: e.name || "",
+ address: e.address || "",
+ scale: e.scale || 28,
+ infoUrl: e.infoUrl || ""
+ },
+ e
+ );
+ },
+ getLocation: function(e) {
+ M(
+ c.getLocation, { type: (e = e || {}).type || "wgs84" },
+ ((e._complete = function(e) {
+ delete e.type;
+ }),
+ e)
+ );
+ },
+ hideOptionMenu: function(e) {
+ M("hideOptionMenu", {}, e);
+ },
+ showOptionMenu: function(e) {
+ M("showOptionMenu", {}, e);
+ },
+ closeWindow: function(e) {
+ M("closeWindow", {}, (e = e || {}));
+ },
+ hideMenuItems: function(e) {
+ M("hideMenuItems", { menuList: e.menuList }, e);
+ },
+ showMenuItems: function(e) {
+ M("showMenuItems", { menuList: e.menuList }, e);
+ },
+ hideAllNonBaseMenuItem: function(e) {
+ M("hideAllNonBaseMenuItem", {}, e);
+ },
+ showAllNonBaseMenuItem: function(e) {
+ M("showAllNonBaseMenuItem", {}, e);
+ },
+ scanQRCode: function(e) {
+ M(
+ "scanQRCode", {
+ needResult: (e = e || {}).needResult || 0,
+ scanType: e.scanType || ["qrCode", "barCode"]
+ },
+ ((e._complete = function(e) {
+ if (f) {
+ var n = e.resultStr;
+ if (n) {
+ var i = JSON.parse(n);
+ e.resultStr = i && i.scan_code && i.scan_code.scan_result;
+ }
+ }
+ }),
+ e)
+ );
+ },
+ openAddress: function(e) {
+ M(
+ c.openAddress, {},
+ ((e._complete = function(e) {
+ e = (function(e) {
+ return (
+ (e.postalCode = e.addressPostalCode),
+ delete e.addressPostalCode,
+ (e.provinceName = e.proviceFirstStageName),
+ delete e.proviceFirstStageName,
+ (e.cityName = e.addressCitySecondStageName),
+ delete e.addressCitySecondStageName,
+ (e.countryName = e.addressCountiesThirdStageName),
+ delete e.addressCountiesThirdStageName,
+ (e.detailInfo = e.addressDetailInfo),
+ delete e.addressDetailInfo,
+ e
+ );
+ })(e);
+ }),
+ e)
+ );
+ },
+ openProductSpecificView: function(e) {
+ M(
+ c.openProductSpecificView, {
+ pid: e.productId,
+ view_type: e.viewType || 0,
+ ext_info: e.extInfo
+ },
+ e
+ );
+ },
+ addCard: function(e) {
+ for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+ var r = n[t],
+ a = { card_id: r.cardId, card_ext: r.cardExt };
+ i.push(a);
+ }
+ M(
+ c.addCard, { card_list: i },
+ ((e._complete = function(e) {
+ var n = e.card_list;
+ if (n) {
+ for (var i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) {
+ var o = n[i];
+ (o.cardId = o.card_id),
+ (o.cardExt = o.card_ext),
+ (o.isSuccess = !!o.is_succ),
+ delete o.card_id,
+ delete o.card_ext,
+ delete o.is_succ;
+ }
+ (e.cardList = n), delete e.card_list;
+ }
+ }),
+ e)
+ );
+ },
+ chooseCard: function(e) {
+ M(
+ "chooseCard", {
+ app_id: v.appId,
+ location_id: e.shopId || "",
+ sign_type: e.signType || "SHA1",
+ card_id: e.cardId || "",
+ card_type: e.cardType || "",
+ card_sign: e.cardSign,
+ time_stamp: e.timestamp + "",
+ nonce_str: e.nonceStr
+ },
+ ((e._complete = function(e) {
+ (e.cardList = e.choose_card_info), delete e.choose_card_info;
+ }),
+ e)
+ );
+ },
+ openCard: function(e) {
+ for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+ var r = n[t],
+ a = { card_id: r.cardId, code: r.code };
+ i.push(a);
+ }
+ M(c.openCard, { card_list: i }, e);
+ },
+ consumeAndShareCard: function(e) {
+ M(
+ c.consumeAndShareCard, { consumedCardId: e.cardId, consumedCode: e.code },
+ e
+ );
+ },
+ chooseWXPay: function(e) {
+ M(c.chooseWXPay, V(e), e);
+ },
+ openEnterpriseRedPacket: function(e) {
+ M(c.openEnterpriseRedPacket, V(e), e);
+ },
+ startSearchBeacons: function(e) {
+ M(c.startSearchBeacons, { ticket: e.ticket }, e);
+ },
+ stopSearchBeacons: function(e) {
+ M(c.stopSearchBeacons, {}, e);
+ },
+ onSearchBeacons: function(e) {
+ P(c.onSearchBeacons, e);
+ },
+ openEnterpriseChat: function(e) {
+ M(
+ "openEnterpriseChat", { useridlist: e.userIds, chatname: e.groupName },
+ e
+ );
+ },
+ launchMiniProgram: function(e) {
+ M(
+ "launchMiniProgram", {
+ targetAppId: e.targetAppId,
+ path: (function(e) {
+ if ("string" == typeof e && 0 < e.length) {
+ var n = e.split("?")[0],
+ i = e.split("?")[1];
+ return (n += ".html"), void 0 !== i ? n + "?" + i : n;
+ }
+ })(e.path),
+ envVersion: e.envVersion
+ },
+ e
+ );
+ },
+ openBusinessView: function(e) {
+ M(
+ "openBusinessView", {
+ businessType: e.businessType,
+ queryString: e.queryString || "",
+ envVersion: e.envVersion
+ },
+ ((e._complete = function(n) {
+ if (p) {
+ var e = n.extraData;
+ if (e)
+ try {
+ n.extraData = JSON.parse(e);
+ } catch (e) {
+ n.extraData = {};
+ }
+ }
+ }),
+ e)
+ );
+ },
+ miniProgram: {
+ navigateBack: function(e) {
+ (e = e || {}),
+ O(function() {
+ M(
+ "invokeMiniProgramAPI", {
+ name: "navigateBack",
+ arg: {
+ delta: e
+ .delta || 1
+ }
+ },
+ e
+ );
+ });
+ },
+ navigateTo: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI", { name: "navigateTo", arg: { url: e.url } },
+ e
+ );
+ });
+ },
+ redirectTo: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI", { name: "redirectTo", arg: { url: e.url } },
+ e
+ );
+ });
+ },
+ switchTab: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI", { name: "switchTab", arg: { url: e.url } },
+ e
+ );
+ });
+ },
+ reLaunch: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI", { name: "reLaunch", arg: { url: e.url } },
+ e
+ );
+ });
+ },
+ postMessage: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI", { name: "postMessage", arg: e.data || {} },
+ e
+ );
+ });
+ },
+ getEnv: function(e) {
+ O(function() {
+ e({ miniprogram: "miniprogram" === o.__wxjs_environment });
+ });
+ }
+ }
+ },
+ T = 1,
+ k = {};
+ return (
+ i.addEventListener(
+ "error",
+ function(e) {
+ if (!p) {
+ var n = e.target,
+ i = n.tagName,
+ t = n.src;
+ if ("IMG" == i || "VIDEO" == i || "AUDIO" == i || "SOURCE" == i)
+ if (-1 != t.indexOf("wxlocalresource://")) {
+ e.preventDefault(), e.stopPropagation();
+ var o = n["wx-id"];
+ if ((o || ((o = T++), (n["wx-id"] = o)), k[o])) return;
+ (k[o] = !0),
+ wx.ready(function() {
+ wx.getLocalImgData({
+ localId: t,
+ success: function(e) {
+ n.src = e.localData;
+ }
+ });
+ });
+ }
+ }
+ },
+ !0
+ ),
+ i.addEventListener(
+ "load",
+ function(e) {
+ if (!p) {
+ var n = e.target,
+ i = n.tagName;
+ n.src;
+ if ("IMG" == i || "VIDEO" == i || "AUDIO" == i || "SOURCE" == i) {
+ var t = n["wx-id"];
+ t && (k[t] = !1);
+ }
+ }
+ },
+ !0
+ ),
+ e && (o.wx = o.jWeixin = w),
+ w
+ );
+ }
+
+ function M(n, e, i) {
+ o.WeixinJSBridge ?
+ WeixinJSBridge.invoke(n, x(e), function(e) {
+ A(n, e, i);
+ }) :
+ B(n, i);
+ }
+
+ function P(n, i, t) {
+ o.WeixinJSBridge ?
+ WeixinJSBridge.on(n, function(e) {
+ t && t.trigger && t.trigger(e), A(n, e, i);
+ }) :
+ B(n, t || i);
+ }
+
+ function x(e) {
+ return (
+ ((e = e || {}).appId = v.appId),
+ (e.verifyAppId = v.appId),
+ (e.verifySignType = "sha1"),
+ (e.verifyTimestamp = v.timestamp + ""),
+ (e.verifyNonceStr = v.nonceStr),
+ (e.verifySignature = v.signature),
+ e
+ );
+ }
+
+ function V(e) {
+ return {
+ timeStamp: e.timestamp + "",
+ nonceStr: e.nonceStr,
+ package: e.package,
+ paySign: e.paySign,
+ signType: e.signType || "SHA1"
+ };
+ }
+
+ function A(e, n, i) {
+ ("openEnterpriseChat" != e && "openBusinessView" !== e) ||
+ (n.errCode = n.err_code),
+ delete n.err_code,
+ delete n.err_desc,
+ delete n.err_detail;
+ var t = n.errMsg;
+ t ||
+ ((t = n.err_msg),
+ delete n.err_msg,
+ (t = (function(e, n) {
+ var i = e,
+ t = a[i];
+ t && (i = t);
+ var o = "ok";
+ if (n) {
+ var r = n.indexOf(":");
+ "confirm" == (o = n.substring(r + 1)) && (o = "ok"),
+ "failed" == o && (o = "fail"),
+ -1 != o.indexOf("failed_") && (o = o.substring(7)),
+ -1 != o.indexOf("fail_") && (o = o.substring(5)),
+ ("access denied" !=
+ (o = (o = o.replace(/_/g, " ")).toLowerCase()) &&
+ "no permission to execute" != o) ||
+ (o = "permission denied"),
+ "config" == i && "function not exist" == o && (o = "ok"),
+ "" == o && (o = "fail");
+ }
+ return (n = i + ":" + o);
+ })(e, t)),
+ (n.errMsg = t)),
+ (i = i || {})._complete && (i._complete(n), delete i._complete),
+ (t = n.errMsg || ""),
+ v.debug && !i.isInnerInvoke && alert(JSON.stringify(n));
+ var o = t.indexOf(":");
+ switch (t.substring(o + 1)) {
+ case "ok":
+ i.success && i.success(n);
+ break;
+ case "cancel":
+ i.cancel && i.cancel(n);
+ break;
+ default:
+ i.fail && i.fail(n);
+ }
+ i.complete && i.complete(n);
+ }
+
+ function C(e) {
+ if (e) {
+ for (var n = 0, i = e.length; n < i; ++n) {
+ var t = e[n],
+ o = c[t];
+ o && (e[n] = o);
+ }
+ return e;
+ }
+ }
+
+ function B(e, n) {
+ if (!(!v.debug || (n && n.isInnerInvoke))) {
+ var i = a[e];
+ i && (e = i),
+ n && n._complete && delete n._complete,
+ console.log('"' + e + '",', n || "");
+ }
+ }
+
+ function L() {
+ return new Date().getTime();
+ }
+
+ function O(e) {
+ l &&
+ (o.WeixinJSBridge ?
+ e() :
+ i.addEventListener &&
+ i.addEventListener("WeixinJSBridgeReady", e, !1));
+ }
+};
+
+export default n(window);
\ No newline at end of file
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/install/console.log.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/install/console.log.js
new file mode 100644
index 0000000..e4beb6a
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/install/console.log.js
@@ -0,0 +1,18 @@
+let debug = process.env.NODE_ENV !== 'production';
+const install = Vue => {
+ let vk = Vue.prototype ? Vue.prototype.vk : Vue.config.globalProperties.vk;
+ if (vk) {
+ vk.log = console.log;
+ if (typeof vk.getConfig === "function") {
+ debug = vk.getConfig().debug;
+ }
+ if(!debug){
+ console.log = function(...obj){};
+ }
+ }
+}
+
+export default {
+ install
+}
+
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/mixin/mixin.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/mixin/mixin.js
new file mode 100644
index 0000000..68910e3
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/mixin/mixin.js
@@ -0,0 +1,40 @@
+var isOnLaunch = true;
+export default {
+ data() {
+ return {}
+ },
+ onLoad() {
+ // 将vk实例挂载到app.globalData上,方便在非Vue页面自身函数中调用vk实例(因为获取不到this)
+ let app = getApp({ allowDefault: true });
+ if (app && app.globalData && !app.globalData.vk) {
+ app.globalData.vk = this.vk;
+ }
+ if (this.vk) {
+ const url = this.vk.pubfn.getCurrentPageRoute();
+ // 检测是否可以分享(小程序专属)
+ this.vk.navigate.checkAllowShare({ url });
+ // 检测是否需要登录,只有首次启动的页面才需要检测,其他页面通过 vk.navigateTo 跳转前会自动判断。
+ if (isOnLaunch && !this.vk.checkToken() && getCurrentPages().length == 1) {
+ isOnLaunch = false; // 重新标记为非首次页面
+ const currentPage = this.vk.pubfn.getCurrentPage() || {};
+ let pagePath = currentPage.pagePath || `/${currentPage.route}` || url;
+ let fullPath = currentPage.fullPath;
+ let options = currentPage.options;
+ this.vk.pubfn.checkLogin({ url: pagePath, fullPath, options, isOnLaunch: true }); // 检测是否需要登录
+ }
+ }
+ },
+ created() {
+ // 将vk实例挂载到app.globalData上,方便在非Vue页面自身函数中调用vk实例(因为获取不到this)
+ let app = getApp({ allowDefault: true });
+ if (app && app.globalData && !app.globalData.vk) {
+ app.globalData.vk = this.vk;
+ }
+ },
+ methods: {
+ $getData(data, key, defaultValue) {
+ let { vk } = this;
+ return vk.pubfn.getData(data, key, defaultValue);
+ }
+ }
+}
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/openapi/baidu/index.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/openapi/baidu/index.js
new file mode 100644
index 0000000..5fa7d5f
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/openapi/baidu/index.js
@@ -0,0 +1,170 @@
+/**
+ * 百度API
+ */
+var baidu = {};
+var vk = {};
+var baiduOpenApiAccessTokenCacheName = "vk_openapi_baidu_open_token";
+baidu.init = function(util={}) {
+ vk = util.vk;
+};
+
+// 百度开放平台api
+baidu.open = {};
+// 文字识别
+baidu.open.ocr = {};
+
+/**
+ * 营业执照识别
+ * 以下data参数三选一即可
+ * @param {File} file 文件对象
+ * @param {String} image 图像base64编码后进行urlencode
+ * @param {String} url 图片完整URL
+ *
+vk.openapi.baidu.open.ocr.business_license({
+ title:"识别中...",
+ data: {
+ file: res.tempFiles[0]
+ },
+ success: (res) => {
+ that.data = res.data;
+ },
+});
+ */
+baidu.open.ocr.business_license = function(obj={}){
+ obj.action = "ocr/v1/business_license";
+ let file = obj.data.file;
+ if(file){
+ vk.pubfn.fileToBase64({ file }).then(base64 => {
+ obj.data.image = base64;
+ delete obj.data.file;
+ baidu.request(obj);
+ });
+ }else{
+ baidu.request(obj);
+ }
+}
+
+/**
+ * 身份证识别
+ * 以下data参数三选一即可
+ * @param {File} file 文件对象
+ * @param {String} image 图像base64编码后进行urlencode
+ * @param {String} url 图片完整URL
+vk.openapi.baidu.open.ocr.idcard({
+ title:"识别中...",
+ data: {
+ image:base64,
+ id_card_side:"front", // front:身份证含照片的一面 back:身份证带国徽的一面
+ },
+ success: (res) => {
+ that.data = res.data;
+ },
+});
+ */
+baidu.open.ocr.idcard = function(obj={}){
+ obj.action = "ocr/v1/idcard";
+ let file = obj.data.file;
+ if(!obj.data.id_card_side) obj.data.id_card_side = "front";
+ if(file){
+ vk.pubfn.fileToBase64({ file }).then(base64 => {
+ obj.data.image = base64;
+ delete obj.data.file;
+ baidu.request(obj);
+ });
+ }else{
+ baidu.request(obj);
+ }
+}
+
+/**
+ * 百度开放平台通用请求接口
+ * @param {String} action 接口名称
+ * @param {String} actionVersion 接口版本名称 默认2.0
+ * @param {String} title loading文字
+ * @param {object} data 请求参数
+ * @param {String} success 成功回调
+ * @param {String} fail 失败回调
+ * @param {String} complete 完成回调
+ * 使用示例
+vk.openapi.baidu.request({
+ action: 'ocr/v1/business_license',
+ title:"识别中...",
+ data: {
+ image:base64
+ },
+ success: (data) => {
+ that.data = data;
+ },
+});
+ */
+baidu.request = function(obj={}){
+ let {
+ title
+ } = obj;
+ if(title) vk.showLoading(title);
+ let baiduApiAccessToken = vk.getStorageSync(baiduOpenApiAccessTokenCacheName);
+ if(baiduApiAccessToken && baiduApiAccessToken.expTime > new Date().getTime()){
+ // 获取缓存中的token
+ obj.accessToken = baiduApiAccessToken.accessToken;
+ request(obj);
+ }else{
+ // 发起请求获取token
+ vk.callFunction({
+ url: 'plugs/baidu/client/pub/getAccessToken',
+ success:function(tokenRes) {
+ vk.setStorageSync(baiduOpenApiAccessTokenCacheName,{
+ accessToken : tokenRes.access_token,
+ expTime : 2590000000 + new Date().getTime(),
+ });
+ obj.accessToken = tokenRes.access_token;
+ request(obj);
+ },
+ fail:function(res){
+ if(title) vk.hideLoading();
+ if(typeof obj.fail === "function") obj.fail(res);
+ if(typeof obj.complete === "function") obj.complete(res);
+ }
+ });
+ }
+}
+
+function request(obj={}){
+ let {
+ action,
+ actionVersion = "2.0",
+ accessToken,
+ header = { "content-type": "application/x-www-form-urlencoded" },
+ data,
+ title
+ } = obj;
+ vk.request({
+ url: `https://aip.baidubce.com/rest/${actionVersion}/${action}?access_token=${accessToken}`,
+ method:"POST",
+ header:{
+ "content-type": "application/x-www-form-urlencoded",
+ },
+ errorCodeName:"error_code",
+ errorMsgName:"error_msg",
+ data,
+ needAlert:true,
+ success: function(data){
+ if(title) vk.hideLoading();
+ if(data.code){
+ if(typeof obj.fail === "function") obj.fail(data);
+ }else{
+ if(typeof obj.success === "function") obj.success(data);
+ }
+ },
+ fail: function(data){
+ if(title) vk.hideLoading();
+ // 如果是因为token失效报的错误,则清空下本地token缓存
+ if(data && data.code === 110) vk.removeStorageSync(baiduOpenApiAccessTokenCacheName);
+ if(typeof obj.fail === "function") obj.fail(data);
+ },
+ complete: function(data){
+ if(typeof obj.complete === "function") obj.complete(data);
+ }
+ });
+}
+
+export default baidu;
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/openapi/index.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/openapi/index.js
new file mode 100644
index 0000000..531c653
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/openapi/index.js
@@ -0,0 +1,14 @@
+/**
+ * 开放API
+ */
+import baidu from './baidu'
+
+var openapi = {};
+openapi.baidu = baidu;
+openapi.init = function(util){
+ openapi.baidu.init(util);
+}
+// 微信小程序API
+export default openapi;
+
+
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/store/libs/error.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/store/libs/error.js
new file mode 100644
index 0000000..4cc9271
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/store/libs/error.js
@@ -0,0 +1,25 @@
+
+const install = Vue => {
+ const debug = process.env.NODE_ENV !== 'production';
+ let vk = Vue.prototype ? Vue.prototype.vk : Vue.config.globalProperties.vk;
+ if (debug && vk) {
+ const oldErrorHandler = Vue.config.errorHandler;
+ Vue.config.errorHandler = function errorHandler(err, vm, info) {
+ const route = vm.$page && vm.$page.route;
+ let date = new Date();
+ let log = {
+ err: err.toString(),
+ info,
+ route,
+ time: date.getTime(),
+ timeStr: date.toLocaleTimeString()
+ };
+ if(vk.vuex) vk.vuex.dispatch('$error/add', log);
+ return oldErrorHandler(err, vm, info);
+ }
+ }
+}
+
+export default {
+ install
+}
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/store/mixin/mixin.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/store/mixin/mixin.js
new file mode 100644
index 0000000..72d96ee
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/store/mixin/mixin.js
@@ -0,0 +1,67 @@
+export default {
+ beforeCreate() {
+ // 将vuex方法挂在到vk实例中 beforeCreate created
+ let { vk, $store } = this;
+ if (typeof $store !== "undefined" && typeof vk.getVuexStore === "undefined") {
+ vk.getVuexStore = function() {
+ return $store;
+ };
+ vk.vuex = (name, value) => {
+ $store.commit('updateStore', { name, value });
+ };
+ /**
+ * (推荐) 设置vuex
+ * vk.vuex.set('$user.userInfo.avatar', avatar);
+ */
+ vk.vuex.set = (name, value) => {
+ $store.commit('updateStore', { name, value });
+ };
+ /**
+ * (推荐) 读取vuex(具有解除对象内存印射功能,且任意一层数据为undefined,不会报错)
+ * vk.vuex.get('$user.userInfo.avatar');
+ */
+ vk.vuex.get = (name, defaultValue) => {
+ let value = vk.pubfn.getData($store.state, name);
+ if (typeof value === "undefined") return (typeof defaultValue !== "undefined") ? defaultValue : "";
+ return JSON.parse(JSON.stringify(value));
+ };
+ vk.vuex.getters = (name) => {
+ return $store.getters[name];
+ };
+ /**
+ * 触发vuex的指定actions(异步)
+ * $user是模块名,addFootprint是对应模块的action名称
+ * vk.vuex.dispatch('$user/addFootprint', data);
+ */
+ vk.vuex.dispatch = $store.dispatch;
+ /**
+ * 触发vuex的指定mutations
+ * $user是模块名,setFootprint是对应模块的action名称
+ * vk.vuex.commit('$user/setFootprint', data);
+ */
+ vk.vuex.commit = $store.commit;
+
+ /* 另一种方式 */
+ /**
+ * vk.setVuex('$user.userInfo.avatar', avatar);
+ */
+ vk.setVuex = vk.vuex.set;
+ /**
+ * vk.getVuex('$user.userInfo.avatar');
+ */
+ vk.getVuex = vk.vuex.get;
+ /* 兼容老版本 */
+ vk.state = vk.vuex.get;
+ try {
+ if (!vk.checkToken()) {
+ vk.callFunctionUtil.deleteUserInfo({
+ log: false
+ });
+ }
+ } catch (err) {}
+ }
+ },
+ computed: {
+
+ }
+}
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/vk-unicloud/vk-unicloud-callFunctionUtil.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/vk-unicloud/vk-unicloud-callFunctionUtil.js
new file mode 100644
index 0000000..2ef380d
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/vk-unicloud/vk-unicloud-callFunctionUtil.js
@@ -0,0 +1,1040 @@
+var vk = {};
+var counterNum = 0;
+var uniCloudEnvs = {}; // uniCloud 环境列表
+var lastToLoginTime = 0;
+class CallFunctionUtil {
+ constructor() {
+ this.config = {
+ // 是否开启测试环境的云函数,true:使用测试环境,false:使用正式环境,默认true
+ isTest: false,
+ // 设为false可关闭打印日志
+ debug: true,
+ // 云函数路由(主函数名)
+ functionName: "router",
+ // 云函数路由(开发测试函数名)
+ testFunctionName: "router-test",
+ // 云函数url化后对应的url地址
+ functionNameToUrl: {
+ "router": "https://xxxxxxx.bspapp.com/http/router",
+ "router-test": "https://xxxxxxx.bspapp.com/http/router"
+ },
+ // vk.callFunction的isRequest的默认值
+ isRequestDefault: false,
+ // 默认时区(中国为8)
+ targetTimezone: 8,
+ // 客户端登录页面地址
+ login: {
+ url: '/pages_template/uni-id/login/index/index'
+ },
+ // 请求配置
+ request: {
+ // 公共请求参数(每次请求都会带上的参数)
+ dataParam: {}
+ },
+ // 日志风格
+ logger: {
+ colorArr: [
+ "#0095ff",
+ "#67C23A"
+ ]
+ },
+ // 缓存键名 - token(请勿修改)
+ uniIdTokenKeyName: "uni_id_token",
+ // 缓存键名 - token过期时间(请勿修改)
+ uniIdTokenExpiredKeyName: "uni_id_token_expired",
+ // 缓存键名 - 当前登录用户信息(请勿修改)
+ uniIdUserInfoKeyName: "uni_id_user_info",
+ // 缓存键名 - 公共请求参数(请勿修改)
+ requestGlobalParamKeyName: "vk_request_global_param",
+ // 监听token刷新事件的事件名
+ onRefreshTokenEventName: "onRefreshToken",
+ // 自定义组件配置
+ components: {}
+ }
+ /**
+ * 获取我的token
+ * vk.getToken();
+ */
+ this.getToken = (res = {}) => {
+ let config = this.config;
+ return vk.getStorageSync(config.uniIdTokenKeyName);
+ }
+ /**
+ * 保存新的token
+ * 可通过下方的代码监听token的改变(写在app.vue的onLaunch内)
+ vk.$on('onRefreshToken',(data) => {
+ console.log('token改变监听:', data);
+ });
+ */
+ this.saveToken = (res = {}) => {
+ let config = this.config;
+ vk.setStorageSync(config.uniIdTokenKeyName, res.token);
+ vk.setStorageSync(config.uniIdTokenExpiredKeyName, res.tokenExpired);
+ this.emitRefreshToken(res); // 触发token刷新事件
+ if (this.config.debug) console.log("--------【token已更新】--------");
+ }
+ // 删除token,并删除userInfo缓存
+ this.deleteToken = () => {
+ let config = this.config;
+ vk.removeStorageSync(config.uniIdTokenKeyName);
+ vk.removeStorageSync(config.uniIdTokenExpiredKeyName);
+ this.deleteUserInfo();
+ this.emitRefreshToken(); // 触发token刷新事件
+ if (this.config.debug) console.log("--------【token已删除】--------");
+ }
+ // 更新userInfo缓存
+ this.updateUserInfo = (res = {}) => {
+ let config = this.config;
+ let {
+ userInfo = {}
+ } = res;
+ if (typeof vk.setVuex === "function") {
+ // 有安装vuex则使用vuex
+ vk.setVuex('$user.userInfo', userInfo);
+ } else {
+ // 否则使用本地缓存
+ vk.setStorageSync(config.uniIdUserInfoKeyName, userInfo);
+ }
+ //if (this.config.debug) console.log("--------【用户信息已更新】--------");
+ }
+ // 删除userInfo缓存
+ this.deleteUserInfo = (res = {}) => {
+ let {
+ log = true
+ } = res;
+ let config = this.config;
+ if (typeof vk.setVuex === "function") {
+ // 有安装vuex则使用vuex
+ vk.setVuex('$user.userInfo', {});
+ vk.setVuex('$user.permission', []);
+ vk.removeStorageSync(config.uniIdUserInfoKeyName);
+ } else {
+ // 否则使用本地缓存
+ vk.removeStorageSync(config.uniIdUserInfoKeyName);
+ }
+ if (this.config.debug && log) console.log("--------【用户信息已删除】--------");
+ }
+ // 检查token是否有效(本地版)
+ // let valid = vk.callFunctionUtil.checkToken();
+ this.checkToken = (res = {}) => {
+ let config = this.config;
+ let token = uni.getStorageSync(config.uniIdTokenKeyName);
+ let tokenExpired = uni.getStorageSync(config.uniIdTokenExpiredKeyName);
+ let valid = false;
+ if (token && tokenExpired && tokenExpired > Date.now()) {
+ valid = true;
+ }
+ return valid;
+ }
+ /**
+ * 触发监听token更新事件
+ */
+ this.emitRefreshToken = (data = {}) => {
+ let config = this.config;
+ return vk.$emit(config.onRefreshTokenEventName, data); // 触发token刷新事件
+ }
+ /**
+ * 监听token更新事件
+ */
+ this.onRefreshToken = (callback) => {
+ let config = this.config;
+ return vk.$on(config.onRefreshTokenEventName, callback);
+ }
+ /**
+ * 移除token更新事件
+ */
+ this.offRefreshToken = (callback) => {
+ let config = this.config;
+ return vk.$off(config.onRefreshTokenEventName, callback);
+ }
+ /**
+ * 修改请求配置中的公共请求参数
+ * 若把shop-manage改成*则代表全局
+ vk.callFunctionUtil.updateRequestGlobalParam({
+ "shop-manage":{
+ regExp:"^xxx/kh/",
+ data:{
+ shop_id : shop_id
+ }
+ }
+ });
+ 对应的callFunction中增加参数globalParamName:"shop-manage"
+ vk.callFunction({
+ url: 'xxx/xxxxxx',
+ title: '请求中...',
+ globalParamName:"shop-manage",// 如果设置了正则规则,则不需要此参数
+ data: {},
+ success(data) {
+ }
+ });
+ */
+ this.updateRequestGlobalParam = (data = {}, setKey) => {
+ let config = this.config;
+ if (setKey) {
+ // 覆盖对象
+ config.request.dataParam = data;
+ } else {
+ // 覆盖参数(有就覆盖,没有则新增)
+ let dataParam = uni.getStorageSync(config.requestGlobalParamKeyName) || {};
+ config.request.dataParam = Object.assign(dataParam, data);
+ }
+ vk.setStorageSync(config.requestGlobalParamKeyName, config.request.dataParam);
+ }
+ /**
+ * 获取请求配置中的公共请求参数
+ vk.callFunctionUtil.getRequestGlobalParam();
+ */
+ this.getRequestGlobalParam = (globalParamName = "*") => {
+ let config = this.config;
+ let data = config.request.dataParam;
+ if (!data || JSON.stringify(data) === "{}") {
+ data = uni.getStorageSync(config.requestGlobalParamKeyName) || {};
+ config.request.dataParam = data;
+ }
+ let param = data[globalParamName] || {};
+ return JSON.parse(JSON.stringify(param));
+ }
+ /**
+ * 删除请求配置中的公共请求参数
+ * globalParamName 不传代表删除所有
+ vk.callFunctionUtil.deleteRequestGlobalParam(globalParamName);
+ */
+ this.deleteRequestGlobalParam = (globalParamName) => {
+ let config = this.config;
+ let globalParam = uni.getStorageSync(config.requestGlobalParamKeyName) || {};
+ if (globalParamName) {
+ delete globalParam[globalParamName];
+ } else {
+ globalParam = {};
+ }
+ config.request.dataParam = globalParam;
+ vk.setStorageSync(config.requestGlobalParamKeyName, globalParam);
+ }
+ // 拦截器
+ this.interceptor = {
+ // 拦截1301、1302错误码(非法token和token失效)
+ login: (obj = {}) => {
+ let nowTime = Date.now();
+ if (nowTime - lastToLoginTime < 300) {
+ return false;
+ }
+ lastToLoginTime = nowTime;
+ let {
+ params,
+ res
+ } = obj;
+ let config = this.config;
+ let callFunction = this.callFunction;
+ if (config.debug) console.log("跳登录页面");
+ let { tokenExpiredAutoDelete = true } = config;
+ if (tokenExpiredAutoDelete) this.deleteToken();
+ setTimeout(() => {
+ if (config.login.url) {
+ let currentPage = getCurrentPages()[getCurrentPages().length - 1];
+ if (currentPage && currentPage.route && "/" + currentPage.route === config.login.url) {
+ return false;
+ }
+ // 此处代码是为了防止首页启动时检测和正常检测冲突-----------------------------------------------------------
+ if (vk.navigate.isOnLaunchToLogin) {
+ setTimeout(() => {
+ vk.navigate.isOnLaunchToLogin = false;
+ }, 500);
+ return false;
+ }
+ // 此处代码是为了防止首页启动时检测和正常检测冲突-----------------------------------------------------------
+ uni.navigateTo({
+ url: config.login.url,
+ events: {
+ // 监听登录成功后的事件
+ loginSuccess: function(data) {
+ let num = 2;
+ let pages = getCurrentPages();
+ if (pages.length >= num) {
+ let that = pages[pages.length - num];
+ if (typeof that.onLoad == "function") {
+ // 重新执行页面onLoad函数
+ that.onLoad(that.options);
+ } else if (typeof that.init == "function") {
+ // 重新执行页面初始化函数
+ that.init(that.options);
+ } else {
+ // 重新执行一次云函数调用
+ callFunction(params);
+ }
+ } else {
+ // 重新执行一次云函数调用
+ callFunction(params);
+ }
+ }
+ }
+ });
+ } else {
+ if (params.needAlert) {
+ vk.alert(res.result.msg);
+ }
+ }
+ }, 0);
+ },
+ // 全局请求失败拦截器
+ fail: (obj = {}) => {
+ return true;
+ }
+ }
+ /**
+ * 云函数请求封装 - 统一入口
+ * @description 通过云函数路由,1个云函数实现多个云函数的效果。
+ * @param {String} name 大云函数名称(默认router)
+ * @param {String} url 请求路径
+ * @param {Object} data 请求参数,如 { a:1, b:"2" } 云函数内可通过 let { a, b } = data; 获取参数
+ * @param {String} title 遮罩层提示语,为空或不传则代表不显示遮罩层。
+ * @param {Boolean|Object} loading 若设置为false,即使title有值也不显示遮罩层
+ * @param {Boolean} isRequest 是否使用云函数url化地址访问云函数,默认false
+ * @param {String} env 云空间环境 文档:https://vkdoc.fsq.pub/client/question/q9.html#%E5%89%8D%E7%AB%AF%E8%AF%B7%E6%B1%82%E5%A4%9A%E6%9C%8D%E5%8A%A1%E7%A9%BA%E9%97%B4
+ * @param {Boolean} needAlert 为true代表请求错误时,会有弹窗提示,默认为true
+ * @param {Number} retryCount 系统异常重试机制(表单提交时慎用,建议只用在查询请求中,即无任何数据库修改的请求中)
+ * @param {Function} success 请求成功时,执行的回调函数
+ * @param {Function} fail 请求失败时,执行的回调函数
+ * @param {Function} complete 无论请求成功与否,都会执行的回调函数
+ */
+ this.callFunction = (obj = {}) => {
+ let that = this;
+ let { config } = that;
+ let {
+ url,
+ data = {},
+ globalParamName
+ } = obj;
+
+ if (!url) {
+ vk.toast('vk.callFunction的url参数不能为空');
+ return;
+ }
+
+ if (obj.retryCount) {
+ // 系统异常重试机制(表单提交时慎用,建议只用在查询请求中,即无任何数据库修改的请求中)
+ return that.callFunctionRetry(obj);
+ }
+ // 去除值为 undefined 的参数
+ if (typeof data === "object") {
+ obj.data = vk.pubfn.copyObject(data);
+ }
+ // 注入自定义全局参数开始-----------------------------------------------------------
+ let globalParam = uni.getStorageSync(config.requestGlobalParamKeyName) || {};
+ // 根据正则规格自动匹配全局请求参数
+ for (let i in globalParam) {
+ let customDate = globalParam[i];
+ if (customDate.regExp) {
+ if (typeof customDate.regExp === "object") {
+ // 数组形式
+ for (let i = 0; i < customDate.regExp.length; i++) {
+ let regExp = new RegExp(customDate.regExp[i]);
+ if (regExp.test(url)) {
+ obj.data = Object.assign(customDate.data, obj.data);
+ break;
+ }
+ }
+ } else {
+ // 字符串形式
+ let regExp = new RegExp(customDate.regExp);
+ if (regExp.test(url)) {
+ obj.data = Object.assign(customDate.data, obj.data);
+ }
+ }
+ }
+ }
+ // 根据指定globalParamName匹配全局请求参数
+ let customDate = that.getRequestGlobalParam(globalParamName);
+ if (customDate && JSON.stringify(customDate) !== "{}") {
+ if (customDate.regExp) {
+ obj.data = Object.assign(customDate.data, obj.data); // 新版本
+ } else {
+ obj.data = Object.assign(customDate, obj.data); // 兼容旧版本
+ }
+ }
+ // 注入自定义全局参数结束-----------------------------------------------------------
+ // 若执行的函数不是pub类型函数,则先本地判断下token,可以提高效率。
+ // if (url.indexOf("/pub/") == -1 && url.indexOf("/pub_") == -1) {
+ // 若执行的函数是kh或sys类型函数,先本地判断下token,可以提高效率。
+ if (url.indexOf("/kh/") > -1 || url.indexOf("/sys/") > -1 || (url.indexOf(".") > -1 && url.indexOf("pub_") == -1 && url.indexOf("/pub/") == -1 && url.indexOf(
+ "/pub.") == -1 && url.indexOf("pub.") !== 0 && url.indexOf("pub_") !== 0)) {
+ if (!vk.checkToken()) {
+ // 若本地token校验未通过,则直接执行 login 拦截器函数
+ return new Promise((resolve, reject) => {
+ // 执行 login 拦截器函数(跳转到页面页面)
+ let res = { code: 30204, msg: "本地token校验未通过" };
+ let params = obj;
+ if (typeof that.interceptor.login === "function") {
+ that.interceptor.login({
+ res,
+ params,
+ vk
+ });
+ }
+ reject(res);
+ });
+ }
+ }
+ if (typeof obj.isRequest === "undefined") {
+ obj.isRequest = config.isRequestDefault;
+ }
+ // 执行请求
+ if (obj.isRequest) {
+ return that.runRequest(obj);
+ } else {
+ return that.runCallFunction(obj);
+ }
+ }
+
+ // 设置全局默认配置
+ this.setConfig = (customConfig = {}) => {
+ for (let key in customConfig) {
+ if (key === "vk") {
+ vk = customConfig[key];
+ } else if (key === "interceptor") {
+ this.interceptor = Object.assign(this.interceptor, customConfig[key]);
+ this.config.interceptor = customConfig[key];
+ } else if (key === "myfn") {
+ vk.myfn = customConfig[key];
+ } else if (key === "loginPagePath") {
+ // 兼容老版本
+ this.config.login.url = customConfig[key];
+ } else if (key === "uniCloud") {
+ let uniCloudConfig = customConfig[key];
+ if (uniCloudConfig && uniCloudConfig.envs) {
+ for (let envKey in uniCloudConfig.envs) {
+ let envItem = uniCloudConfig.envs[envKey];
+ if (envItem && envItem.provider && envItem.spaceId) {
+ let initConifg = {
+ provider: envItem.provider,
+ spaceId: envItem.spaceId
+ };
+ if (envItem.clientSecret) initConifg.clientSecret = envItem.clientSecret;
+ if (envItem.endpoint) initConifg.endpoint = envItem.endpoint;
+ uniCloudEnvs[envKey] = uniCloud.init(initConifg);
+ }
+ }
+ }
+ } else if (typeof customConfig[key] === "object" && typeof this.config[key] === "object") {
+ this.config[key] = Object.assign(this.config[key], customConfig[key]);
+ } else if (typeof customConfig[key] !== "undefined") {
+ this.config[key] = customConfig[key];
+ }
+ }
+ }
+ /**
+ * 获取vk前端配置
+ * 示例
+ * vk.callFunctionUtil.getConfig();
+ * vk.callFunctionUtil.getConfig("login.url");
+ */
+ this.getConfig = (key) => {
+ let config = this.config;
+ if (key) {
+ return vk.pubfn.getData(config, key);
+ } else {
+ return config;
+ }
+ }
+
+ // 初始化
+ this.init = (obj = {}) => {
+ vk = obj.vk;
+ }
+ /**
+ * 云函数上传图片
+ * @param {String} title 上传时的loading提示语
+ * @param {String} file 要上传的文件对象,file与filePath二选一即可
+ * @param {String} filePath 要上传的文件路径,file与filePath二选一即可
+ * @param {String} suffix 指定上传后的文件后缀,如果传了file 参数,则此参数可不传
+ * @param {String} provider 云存储供应商,支持:unicloud、aliyun
+ * @param {String} cloudPath 指定上传后的云端文件路径(不指定会自动生成)cloudPath优先级大于cloudDirectory
+ * @param {String} cloudDirectory 指定上传后的云端文件目录(不指定会自动生成)
+ * @param {String} needSave 是否需要将图片信息保存到admin素材库
+ * @param {String} category_id 素材库分类id,当needSave为true时生效
+ * @param {String} uniCloud 上传到其他空间时使用,uniCloud和env二选一即可
+ * @param {String} env 上传到其他空间时使用,uniCloud和env二选一即可
+ * @param {String} cloudPathAsRealPath 阿里云目录支持,需HBX3.8.5以上版本才支持
+ * @param {String} cloudPathRemoveChinese 删除文件名中的中文
+ * @param {String} fileType 文件类型,可选image、video、audio 不用传,会自动识别
+ * @param {Function} onUploadProgress 上传进度回调
+ * @param {Function} success 上传成功时,执行的回调函数
+ * @param {Function} fail 上传失败时,执行的回调函数
+ * @param {Function} complete 无论上传成功与否,都会执行的回调函数
+ * vk.callFunctionUtil.uploadFile
+ */
+ this.uploadFile = (obj = {}) => {
+ let that = this;
+ let config = that.config;
+ if (!obj.filePath && obj.file && obj.file.path) obj.filePath = obj.file.path;
+ let {
+ filePath,
+ cloudPath,
+ title,
+ errorToast,
+ needAlert,
+ success,
+ fail,
+ complete,
+ type,
+ provider,
+ file = {},
+ needSave = false,
+ category_id,
+ uniCloud: myCloud,
+ env = "default",
+ cloudPathAsRealPath = true, // 阿里云目录支持,需HBX3.8.5以上版本才支持
+ cloudPathRemoveChinese = true, // 删除文件名中的中文
+ cloudDirectory,
+ } = obj;
+ // 获取文件类型(image:图片 video:视频 other:其他)
+ let fileType = this.getFileType(obj);
+ obj.fileType = fileType;
+ if (type && !provider) provider = type;
+ if (!provider) {
+ let aliyunOSS = vk.pubfn.getData(config, "service.aliyunOSS");
+ if (aliyunOSS && aliyunOSS.isDefault) {
+ provider = "aliyun";
+ } else {
+ provider = "unicloud";
+ }
+ }
+ if (provider === "aliyun") {
+ return vk.aliyunOSSUtil.uploadFile(obj);
+ }
+ if (title) vk.showLoading(title);
+ if (errorToast) needAlert = false;
+ // 生成文件名
+ if (!cloudPath) cloudPath = this.createFileName(obj);
+ let Logger = {};
+ if (config.debug) Logger.filePath = filePath;
+ if (config.debug) Logger.startTime = Date.now();
+ let runCloud = myCloud || uniCloudEnvs[env] || uniCloud;
+ return new Promise((resolve, reject) => {
+ runCloud.uploadFile({
+ filePath: filePath,
+ cloudPath: cloudPath,
+ fileType: fileType,
+ cloudPathAsRealPath,
+ onUploadProgress: function(progressEvent) {
+ let percentCompleted = Math.round(
+ (progressEvent.loaded * 100) / progressEvent.total
+ );
+ if (typeof obj.onUploadProgress == "function") {
+ obj.onUploadProgress({
+ progressEvent,
+ percentCompleted,
+ progress: percentCompleted
+ });
+ }
+ },
+ success(res) {
+ if (config.debug) Logger.result = typeof res == "object" ? JSON.parse(JSON.stringify(res)) : res;
+ if (title) vk.hideLoading();
+ uniCloud.getTempFileURL({
+ fileList: [res.fileID],
+ success(data) {
+ let { fileID, tempFileURL } = data.fileList[0];
+ res.fileID = tempFileURL;
+ res.url = tempFileURL;
+ res.file_id = fileID;
+ if (config.debug) Logger.result.url = tempFileURL;
+ if (typeof success == "function") success(res);
+ resolve(res);
+ if (needSave) {
+ // 保存文件记录到数据库
+ vk.userCenter.addUploadRecord({
+ data: {
+ url: res.url,
+ name: file.name,
+ size: file.size,
+ file_id: res.file_id,
+ provider,
+ category_id,
+ },
+ filePath,
+ fileType,
+ success: function() {
+ if (typeof obj.addSuccess == "function") obj.addSuccess(res);
+ },
+ fail: function(res) {
+ if (typeof obj.addFail === "function") obj.addFail(res);
+ }
+ });
+ }
+ }
+ });
+ },
+ fail(err) {
+ if (title) vk.hideLoading();
+ if (config.debug) Logger.error = err;
+ if (errorToast) vk.toast(JSON.stringify(err), "none");
+ if (needAlert) {
+ if (config.debug) vk.alert(JSON.stringify(err));
+ }
+ if (typeof fail == "function") fail(err);
+ reject(err);
+ },
+ complete() {
+ if (config.debug) {
+ Logger.endTime = Date.now();
+ Logger.runTime = (Logger.endTime - Logger.startTime);
+ let colorArr = config.logger.colorArr;
+ let colorStr = colorArr[counterNum % colorArr.length];
+ counterNum++;
+ console.log("%c--------【开始】【文件上传】--------", 'color: ' + colorStr + ';font-size: 12px;font-weight: bold;');
+ console.log("【本地文件】: ", Logger.filePath);
+ console.log("【返回数据】: ", Logger.result);
+ console.log("【预览地址】: ", Logger.result.fileID);
+ console.log("【上传耗时】: ", Logger.runTime, "毫秒");
+ console.log("【上传时间】: ", vk.pubfn.timeFormat(Logger.startTime, "yyyy-MM-dd hh:mm:ss"));
+ if (Logger.error) console.error("【error】:", Logger.error);
+ console.log("%c--------【结束】【文件上传】--------", 'color: ' + colorStr + ';font-size: 12px;font-weight: bold;');
+ }
+ if (typeof complete == "function") complete();
+ }
+ });
+ });
+ }
+ }
+ // 云函数普通请求
+ runCallFunction(obj = {}) {
+ let that = this;
+ let config = that.config;
+ let {
+ url,
+ data,
+ title,
+ loading,
+ isRequest,
+ name,
+ complete,
+ uniCloud: myCloud,
+ env = "default"
+ } = obj;
+ if (title) vk.showLoading(title);
+ if (loading) vk.setLoading(true, loading);
+ if (!name) name = config.isTest ? config.testFunctionName : config.functionName;
+ obj.name = name;
+ let Logger = {};
+ if (config.debug) Logger.params = typeof data == "object" ? JSON.parse(JSON.stringify(data)) : data;
+ let promiseAction = new Promise(function(resolve, reject) {
+ if (config.debug) Logger.startTime = Date.now();
+ let runCloud = myCloud || uniCloudEnvs[env] || uniCloud;
+ runCloud.callFunction({
+ name: name,
+ data: {
+ $url: url,
+ data: data
+ },
+ success(res = {}) {
+ that.callFunctionSuccess({
+ res: res.result,
+ params: obj,
+ Logger,
+ resolve,
+ reject
+ });
+ },
+ fail(res) {
+ that.callFunctionFail({
+ res,
+ params: obj,
+ Logger,
+ reject,
+ sysFail: true
+ });
+ },
+ complete(res) {
+ that.callFunctionComplete({
+ res,
+ params: obj,
+ Logger
+ });
+ }
+ });
+ });
+ promiseAction.catch(error => {});
+ return promiseAction;
+ }
+
+ // 云函数url化请求
+ runRequest(obj = {}) {
+ let that = this;
+ let config = that.config;
+ let {
+ url,
+ data,
+ title,
+ loading,
+ name,
+ complete
+ } = obj;
+ if (typeof obj.needAlert === "undefined") obj.needAlert = true;
+ if (!name) name = config.isTest ? config.testFunctionName : config.functionName;
+ obj.name = name;
+ let requestUrl = config.functionNameToUrl[name];
+ let Logger = {};
+ if (config.debug) Logger.params = typeof data == "object" ? JSON.parse(JSON.stringify(data)) : data;
+ let uniIdToken = uni.getStorageSync(config.uniIdTokenKeyName);
+ let tokenExpired = uni.getStorageSync(config.uniIdTokenExpiredKeyName);
+ if (title) vk.showLoading(title);
+ if (loading) vk.setLoading(true, loading);
+ let promiseAction = new Promise(function(resolve, reject) {
+ if (config.debug) Logger.startTime = Date.now();
+ uni.request({
+ method: "POST",
+ url: requestUrl,
+ data: {
+ $url: url,
+ data: data,
+ uniIdToken: uniIdToken
+ },
+ success(res = {}) {
+ that.callFunctionSuccess({
+ res: res.data,
+ params: obj,
+ Logger,
+ resolve,
+ reject
+ });
+ },
+ fail(res) {
+ that.callFunctionFail({
+ res,
+ params: obj,
+ Logger,
+ reject,
+ sysFail: true
+ });
+ },
+ complete(res) {
+ that.callFunctionComplete({
+ res,
+ params: obj,
+ Logger
+ });
+ }
+ });
+ });
+ promiseAction.catch(error => {});
+ return promiseAction;
+ }
+
+ // 云函数请求成功时执行
+ callFunctionSuccess(obj) {
+ let that = this;
+ let config = that.config;
+ let {
+ res = {},
+ params,
+ Logger,
+ resolve,
+ reject
+ } = obj;
+ let {
+ title,
+ loading,
+ success
+ } = params;
+ if (title) vk.hideLoading();
+ if (loading) vk.setLoading(false, loading);
+ if (typeof res.code === "undefined" && typeof res.errCode !== "undefined") res.code = res.errCode;
+ let code = res.code;
+ if (config.debug) Logger.result = typeof res == "object" ? JSON.parse(JSON.stringify(res)) : res;
+ if (code == 0 || res.key == 1 || (code == undefined && res.uid)) {
+ if (res.vk_uni_token) that.saveToken(res.vk_uni_token);
+ if (res.userInfo && res.needUpdateUserInfo) that.updateUserInfo(res);
+ if (typeof success == "function") success(res);
+ resolve(res);
+ } else if ([1301, 1302, 30201, 30202, 30203, 30204].indexOf(code) > -1 && res.msg.indexOf("token") > -1) {
+ // 执行 login 拦截器函数(跳转到页面页面)
+ if (typeof that.interceptor.login === "function") {
+ that.interceptor.login({
+ res,
+ params,
+ vk
+ });
+ }
+ reject(res);
+ } else {
+ that.callFunctionFail({
+ res,
+ params,
+ Logger,
+ reject
+ });
+ }
+ }
+
+ // 云函数请求失败时执行
+ callFunctionFail(obj) {
+ let that = this;
+ let config = that.config;
+ let { globalErrorCode = {} } = config;
+ let {
+ res = {},
+ params,
+ Logger,
+ reject,
+ sysFail
+ } = obj;
+ let {
+ title,
+ loading,
+ errorToast,
+ noAlert,
+ needAlert,
+ fail,
+ } = params;
+ // 只有是系统异常时才进行重试
+ if (params.needRetry) {
+ if (sysFail || (res.code && [90001].indexOf(res.code) > -1)) {
+ if (!obj.hookResult || (typeof obj.hookResult === "function" && !obj.hookResult(err))) {
+ Logger.sysFail = true;
+ if (typeof params.retry == "function") params.retry(res, params);
+ return false;
+ }
+ }
+ }
+
+ if (typeof noAlert !== "undefined") needAlert = !noAlert;
+ if (typeof needAlert === "undefined") {
+ needAlert = (typeof fail === "function") ? false : true;
+ }
+ if (errorToast) needAlert = false;
+ if (title) vk.hideLoading();
+ if (loading) vk.setLoading(false, loading);
+ let errMsg = "";
+ let sysErr = false;
+ if (typeof res.code !== "undefined") {
+ if (res.msg) {
+ errMsg = res.msg;
+ } else if (res.errMsg) {
+ errMsg = res.errMsg;
+ } else if (res.message) {
+ errMsg = res.message;
+ }
+ } else {
+ sysErr = true;
+ errMsg = JSON.stringify(res);
+ }
+ if (typeof errMsg !== "string") errMsg = JSON.stringify(errMsg);
+ if (!errMsg) errMsg = "";
+ if (res.code >= 90001 && errMsg.indexOf("数据库") > -1) {
+ sysErr = true;
+ } else if ([404, 500].indexOf(res.code) > -1 && errMsg.indexOf("云函数") > -1) {
+ sysErr = true;
+ } else if ((res.code === 501 && errMsg.indexOf("timeout for 10000ms") > -1) || (res.code === "SYS_ERR" && errMsg.indexOf(": request:ok") > -1)) {
+ errMsg = globalErrorCode["cloudfunction-unusual-timeout"] || "请求超时,但请求还在执行,请重新进入页面。";
+ } else if (typeof errMsg.toLowerCase === "function" && (errMsg.toLowerCase().indexOf("timeout") > -1 || errMsg.toLowerCase().indexOf("etimedout") > -1)) {
+ sysErr = true;
+ errMsg = globalErrorCode["cloudfunction-timeout"] || "请求超时,请重试!";
+ } else if (errMsg.indexOf("reaches burst limit") > -1) {
+ errMsg = globalErrorCode["cloudfunction-reaches-burst-limit"] || "系统繁忙,请稍后再试。";
+ } else if (res.code === "InternalServerError") {
+ sysErr = true;
+ }
+ let runKey = true;
+ if (typeof that.interceptor.fail == "function") {
+ runKey = that.interceptor.fail({
+ vk,
+ res: res,
+ params: params
+ });
+ if (runKey === undefined) runKey = true;
+ }
+ if (runKey) {
+ Logger.error = res;
+ if (errorToast) vk.toast(errMsg, "none");
+ if (needAlert && vk.pubfn.isNotNull(errMsg)) {
+ if (sysErr) {
+ let toastMsg = globalErrorCode["cloudfunction-system-error"] || "网络开小差了!";
+ vk.toast(toastMsg, "none");
+ } else {
+ vk.alert(errMsg);
+ }
+ }
+ if (typeof fail == "function") fail(res);
+ }
+ if (typeof reject == "function") reject(res);
+ }
+
+ // 云函数请求完成后执行
+ callFunctionComplete(obj) {
+ let that = this;
+ let config = that.config;
+ let {
+ res = {},
+ params,
+ Logger
+ } = obj;
+ let {
+ name,
+ url,
+ isRequest,
+ complete,
+ debug: debugLog
+ } = params;
+ if (params.needRetry && Logger.sysFail) {
+ return false;
+ }
+ if (typeof debugLog === "undefined") debugLog = config.debug;
+ if (debugLog) {
+ Logger.endTime = Date.now();
+ if (isRequest) {
+ Logger.label = "【url化】";
+ } else {
+ Logger.label = "";
+ }
+ Logger.runTime = (Logger.endTime - Logger.startTime);
+ let colorArr = config.logger.colorArr;
+ let colorStr = colorArr[counterNum % colorArr.length];
+ counterNum++;
+ let functionType = url.indexOf(".") > -1 ? "云对象" : "云函数";
+ console.log(`%c--------【开始】${Logger.label}【${functionType}请求】【${name}】【${url}】--------`, `color: ${colorStr};font-size: 12px;font-weight: bold;`);
+ console.log("【请求参数】: ", Logger.params);
+ console.log("【返回数据】: ", Logger.result);
+ console.log("【总体耗时】: ", Logger.runTime, "毫秒【含页面渲染】");
+ console.log("【请求时间】: ", vk.pubfn.timeFormat(Logger.startTime, "yyyy-MM-dd hh:mm:ss"));
+ if (Logger.error) {
+ let errorLog = console.warn || console.error;
+ if (Logger.error.err && Logger.error.err.stack) {
+ console.error("【Error】: ", Logger.error);
+ console.error("【Stack】: ", Logger.error.err.stack);
+ } else {
+ errorLog("【Error】: ", Logger.error);
+ }
+ }
+ console.log(`%c--------【结束】${Logger.label}【${functionType}请求】【${name}】【${url}】--------`, `color: ${colorStr};font-size: 12px;font-weight: bold;`);
+ }
+ if (typeof complete == "function") complete(res);
+ }
+ // 生成文件名
+ createFileName(obj = {}) {
+ let {
+ file,
+ filePath,
+ index = 0,
+ cloudPathRemoveChinese = true,
+ cloudDirectory
+ } = obj;
+ let suffix = this.getFileSuffix(obj);
+ let oldName = index + "." + suffix;
+ // 注意:小程序无法获取到 file.name
+ if (file && file.name) {
+ let suffixName = file.name.substring(file.name.lastIndexOf(".") + 1);
+ if (suffixName && suffixName.length < 5) oldName = file.name;
+ // 只保留["数字","英文",".","-"]
+ if (cloudPathRemoveChinese) {
+ oldName = oldName.replace(/[^a-zA-Z.-d]/g, '');
+ }
+ if (oldName.indexOf(".") == 0) oldName = "0" + oldName;
+ }
+ let date = new Date();
+ let dateYYYYMMDD = vk.pubfn.timeFormat(date, "yyyy/MM/dd");
+ let dateTime = date.getTime().toString(); // 时间戳
+ // 时间戳后8位
+ let dateTimeEnd8 = dateTime.substring(dateTime.length - 8, dateTime.length);
+ let randomNumber = vk.pubfn.random(8); // 8位随机数
+ // 文件路径
+ let newFilePath = "";
+ if (cloudDirectory) {
+ // 如果自定义了上传目录,则使用自定义的上传目录
+ if (cloudDirectory.lastIndexOf("/") !== cloudDirectory.length-1) {
+ cloudDirectory = cloudDirectory + "/";
+ }
+ newFilePath = cloudDirectory;
+ } else {
+ // 否则,使用年月日作为上传目录
+ newFilePath = dateYYYYMMDD + "/";
+ }
+ // 文件名 = 时间戳后8位 - 随机数8位 + 原本文件名
+ let fileNickName = dateTimeEnd8 + "-" + randomNumber + "-" + oldName;
+ // 文件名全称(包含文件路径) = 文件路径 + 文件名
+ let fileFullName = newFilePath + fileNickName;
+ return fileFullName;
+ }
+
+ getFileSuffix(obj = {}) {
+ let {
+ file,
+ filePath,
+ suffix = "png"
+ } = obj;
+ if (filePath) {
+ let suffixName = filePath.substring(filePath.lastIndexOf(".") + 1);
+ if (suffixName && suffixName.length < 5) suffix = suffixName;
+ }
+ if (file) {
+ if (file.path) {
+ let suffixName = file.path.substring(file.path.lastIndexOf(".") + 1);
+ if (suffixName && suffixName.length < 5) suffix = suffixName;
+ }
+ if (file.name) {
+ let suffixName = file.name.substring(file.name.lastIndexOf(".") + 1);
+ if (suffixName && suffixName.length < 5) suffix = suffixName;
+ }
+ }
+ return suffix;
+ }
+ getFileType(obj = {}) {
+ let {
+ file,
+ filePath
+ } = obj;
+ let fileType = "other";
+ let suffix = this.getFileSuffix(obj);
+ if (["png", "jpg", "jpeg", "gif", "bmp", "svg", "webp"].indexOf(suffix) > -1) {
+ fileType = "image";
+ } else if (["avi", "mp3", "mp4", "3gp", "mov", "rmvb", "rm", "flv", "mkv"].indexOf(suffix) > -1) {
+ fileType = "video";
+ }
+ return fileType;
+ }
+
+ // 系统异常重试机制(表单提交时慎用,建议只用在查询请求中,即无任何数据库修改的请求中)
+ callFunctionRetry(obj = {}) {
+ let { retryCount } = obj;
+ delete obj.retryCount;
+ return new Promise((resolve, reject) => {
+ this.callRetryFn(obj, resolve, reject, retryCount);
+ });
+ }
+ // 重试实现
+ callRetryFn(obj, resolve, reject, retryCount) {
+ let that = this;
+ let debug = that.config.debug;
+ that.callFunction({
+ ...obj,
+ needRetry: retryCount ? true : false, // 判断是否需要重试
+ retry: function(err) {
+ obj.runCount = obj.runCount ? obj.runCount + 1 : 1;
+ obj.needRetry = retryCount > obj.runCount ? true : false; // 判断是否需要重试
+ let errorMsg = err.message ? `异常信息:${err.message}` : "";
+ if (debug) console.log(`【请求失败】正在第【${obj.runCount}】次重试:${obj.url}`);
+ if (obj.retryInterval) {
+ setTimeout(function() {
+ that._callRetryFn(obj, resolve, reject, retryCount);
+ }, obj.retryInterval);
+ } else {
+ // 如果无延迟,则不写setTimeout,因为setTimeout 即使time为0,也有一定延迟。
+ that._callRetryFn(obj, resolve, reject, retryCount);
+ }
+ }
+ });
+ }
+
+ _callRetryFn(obj, resolve, reject, retryCount) {
+ if (obj.runCount < retryCount) {
+ this.callRetryFn(obj, resolve, reject, retryCount);
+ } else {
+ this.callFunction(obj).catch((err) => {
+ reject();
+ });
+ }
+ }
+
+
+}
+
+export default new CallFunctionUtil
diff --git a/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/vk-unicloud/vk-unicloud-user-center.js b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/vk-unicloud/vk-unicloud-user-center.js
new file mode 100644
index 0000000..770fc31
--- /dev/null
+++ b/uni_modules/vk-unicloud/vk_modules/vk-unicloud-page/libs/vk-unicloud/vk-unicloud-user-center.js
@@ -0,0 +1,1068 @@
+/**
+ * unicloud-user-center 接口类(uni-id封装)
+ * author VK
+ */
+import callFunctionUtil from './vk-unicloud-callFunctionUtil.js'
+var { callFunction, config, saveToken, deleteToken } = callFunctionUtil;
+import debounce from '../function/debounce.js'
+
+const debounceTime = 1000; // 防抖时长
+
+const localeObj = {
+ "zh-Hans": {
+ "loading": "请求中...",
+ "login": "登录中...",
+ "register": "注册中...",
+ "create": "生成中...",
+ },
+ "zh-Hant": {
+ "loading": "請求中...",
+ "login": "登入中...",
+ "register": "注册中...",
+ "create": "生成中...",
+ },
+ "en": {
+ "loading": "loading...",
+ "login": "login...",
+ "register": "register...",
+ "create": "create...",
+ }
+};
+
+function addLoading(obj, title) {
+ if (typeof obj.loading === "undefined" && !obj.title && title) {
+ let locale;
+ if (typeof uni.vk !== "undefined") {
+ locale = localeObj[uni.vk.pubfn.getLocale()];
+ } else {
+ locale = localeObj["zh-Hans"];
+ }
+ obj.title = locale[title] || "loading...";
+ }
+ return obj;
+}
+
+export default {
+ /**
+ * 用户注册(用户名+密码)
+ * data 请求参数 说明
+ * @param {String} username 用户名
+ * @param {String} password 密码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} token 注册完成自动登录之后返回的token信息
+ * @param {String} tokenExpired token过期时间
+ * @param {Object} userInfo 用户信息
+ * @param {String} uid 用户ID
+ */
+ register(obj = {}) {
+ return debounce(() => {
+ addLoading(obj, "register");
+ return callFunction({
+ ...obj,
+ url: 'user/pub/register'
+ });
+ }, debounceTime, true, "login");
+ },
+ /**
+ * 用户登录(用户名+密码)
+ * data 请求参数 说明
+ * @param {String} username 用户名
+ * @param {String} password 密码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} token 注册完成自动登录之后返回的token信息
+ * @param {String} tokenExpired token过期时间
+ * @param {Object} userInfo 用户信息
+ * @param {String} uid 用户ID
+ */
+ login(obj = {}) {
+ addLoading(obj, "login");
+ return callFunction({
+ ...obj,
+ url: 'user/pub/login'
+ });
+ },
+ /**
+ * 登出(退出)
+ * data 请求参数 说明
+ * 无
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ logout(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/pub/logout',
+ success(res) {
+ deleteToken();
+ if (typeof obj.success == "function") obj.success(res);
+ }
+ });
+ },
+ /**
+ * 修改密码
+ * @description 修改成功后,需要重新登录获取新的token
+ * data 请求参数 说明
+ * @param {String} oldPassword 旧密码
+ * @param {String} newPassword 新密码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ updatePwd(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/updatePwd',
+ });
+ },
+ /**
+ * 重置密码
+ * data 请求参数 说明
+ * @param {String} password 重置后的密码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ resetPwd(obj) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/resetPwd',
+ });
+ },
+ /**
+ * 设置头像
+ * data 请求参数 说明
+ * @param {String} avatar 头像地址
+ * @param {Boolean} deleteOldFile 是否同时删除云储存内的头像文件
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ setAvatar(obj = {}) {
+ addLoading(obj, "loading");
+ //obj.isRequest = true;
+ return callFunction({
+ ...obj,
+ url: 'user/kh/setAvatar',
+ });
+ },
+ /**
+ * 设置昵称等用户展示的个人信息
+ * data 请求参数 说明
+ * @param {String} nickname 昵称
+ * @param {String} avatar 头像
+ * @param {Number} gender 性别
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ updateUser(obj = {}) {
+ addLoading(obj, "loading");
+ callFunction({
+ ...obj,
+ url: 'user/kh/updateUser'
+ });
+ },
+ /**
+ * 获取用户最新信息
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 错误信息
+ * @param {Object} userInfo 用户信息
+ */
+ getCurrentUserInfo(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/getMyUserInfo',
+ });
+ },
+ /**
+ * token校验
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} uid 当前token对应的用户uid
+ * @param {Object} userInfo 当前用户信息
+ * @param {Array} role 当前用户角色
+ * @param {Array} permission 当前用户权限
+ */
+ checkToken(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/pub/checkToken',
+ });
+ },
+ /**
+ * 绑定手机号
+ * data 请求参数 说明
+ * @param {String} mobile 手机号
+ * @param {String} code 手机收到的验证码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ bindMobile(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/bindMobile',
+ });
+ },
+ /**
+ * 解绑手机号
+ * data 请求参数 说明
+ * @param {String} mobile 手机号
+ * @param {String} code 手机收到的验证码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ unbindMobile(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/unbindMobile',
+ });
+ },
+ /**
+ * 绑定新的手机号(换绑手机号)
+ * data 请求参数 说明
+ * @param {String} oldMobile 旧手机号码
+ * @param {String} oldMobileCode 旧手机收到的验证码
+ * @param {String} mobile 新手机号码
+ * @param {String} code 新手机收到的验证码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ bindNewMobile(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/bindNewMobile',
+ });
+ },
+ /**
+ * 手机号登录(手机号+手机验证码)
+ * data 请求参数 说明
+ * @param {String} mobile 手机号
+ * @param {String} code 验证码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} token 注册完成自动登录之后返回的token信息
+ * @param {String} tokenExpired token过期时间
+ */
+ loginBySms(obj = {}) {
+ return debounce(() => {
+ addLoading(obj, "login");
+ return callFunction({
+ url: 'user/pub/loginBySms',
+ ...obj
+ });
+ }, debounceTime, true, "login");
+ },
+ /**
+ * 发送手机号验证码
+ * data 请求参数 说明
+ * @param {String} mobile 手机号
+ * @param {String} type 验证码类型
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {Object} requestRes 原始返回数据
+ * @param {Object} requestParam 包含服务供应商和发送的手机号
+ */
+ sendSmsCode(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/pub/sendSmsCode',
+ });
+ },
+ /**
+ * APP端 手机一键登录
+ * data 请求参数 说明
+ * @param {String} access_token uni.login登录成功后,返回的access_token参数
+ * @param {String} openid uni.login登录成功后,返回的openid参数
+ * @param {String} type 指定操作类型,可选值为login、register,不传此参数时表现为手机号已注册则登录,手机号未注册则进行注册
+ * @param {String} password 密码,type为register时生效
+ * @param {String} inviteCode 邀请人的邀请码,type为register时生效
+ * @param {String} myInviteCode 设置当前注册用户自己的邀请码,type为register时生效
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} uid 当前token对应的用户uid
+ * @param {String} type 操作类型,login为登录、register为注册
+ * @param {String} mobile 登录者手机号
+ * @param {String} userInfo 用户全部信息
+ * @param {String} token 登录成功之后返回的token信息
+ * @param {String} tokenExpired token过期时间
+ */
+ loginByUniverify(obj = {}) {
+ addLoading(obj, "login");
+ if (typeof obj.needAlert === "undefined") obj.needAlert = true;
+ // #ifdef APP-PLUS
+ uni.login({
+ provider: 'univerify',
+ univerifyStyle: obj.univerifyStyle,
+ success(res) {
+ let dataJson = Object.assign(obj.data, res.authResult);
+ callFunction({
+ url: 'user/pub/loginByUniverify',
+ ...obj,
+ data: dataJson,
+ });
+ },
+ fail: obj.fail,
+ complete: (res) => {
+ uni.vk.hideLoading();
+ }
+ });
+ // #endif
+ // #ifndef APP-PLUS
+ uni.vk.toast("请在APP中使用本机号码一键登录", "none");
+ // #endif
+ },
+
+ /**
+ * 绑定邮箱
+ * data 请求参数 说明
+ * @param {String} email 邮箱
+ * @param {String} code 邮箱收到的验证码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ bindEmail(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/bindEmail',
+ });
+ },
+ /**
+ * 解绑邮箱
+ * @param {String} email 邮箱
+ * @param {String} code 邮箱收到的验证码
+ */
+ unbindEmail(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/unbindEmail',
+ });
+ },
+ /**
+ * 绑定新的邮箱(换绑邮箱)
+ * @param {String} oldEmail 旧邮箱码
+ * @param {String} oldEmailCode 旧邮箱收到的验证码
+ * @param {String} email 新邮箱码
+ * @param {String} code 新邮箱收到的验证码
+ */
+ bindNewEmail(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/bindNewEmail',
+ });
+ },
+ /**
+ * 邮箱登录(邮箱+邮箱验证码)
+ * data 请求参数 说明
+ * @param {String} email 邮箱
+ * @param {String} code 邮箱收到的验证码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} token 注册完成自动登录之后返回的token信息
+ * @param {String} tokenExpired token过期时间
+ */
+ loginByEmail(obj = {}) {
+ addLoading(obj, "login");
+ return callFunction({
+ url: 'user/pub/loginByEmail',
+ ...obj
+ });
+ },
+ /**
+ * 发送邮件验证码
+ * data 请求参数 说明
+ * @param {String} email 邮箱
+ * @param {String} type 验证码类型
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} email 手机号
+ * @param {String} verifyCode 验证码
+ */
+ sendEmailCode(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/pub/sendEmailCode',
+ });
+ },
+ /**
+ * 根据邮箱+验证码重置密码
+ * data 请求参数 说明
+ * @param {String} password 重置后的密码
+ * @param {String} code 验证码
+ * @param {String} email 邮箱号码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ resetPasswordByEmail(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/pub/resetPasswordByEmail',
+ });
+ },
+ /**
+ * 设置验证码
+ * @description 设置验证码(此接口正式环境不要暴露,故写在了sys目录下)
+ * data 请求参数 说明
+ * @param {String} email 邮箱
+ * @param {String} mobile 手机号
+ * @param {String} type 验证码类型
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} email 邮箱
+ * @param {String} mobile 手机号
+ * @param {String} verifyCode 验证码(uni 1.1.2开始不再返回verifyCode)
+ */
+ setVerifyCode(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/sys/setVerifyCode',
+ });
+ },
+ /**
+ * 微信登录获取用户code
+ */
+ getWeixinCode() {
+ return new Promise((resolve, reject) => {
+ // #ifdef MP-WEIXIN
+ uni.login({
+ provider: 'weixin',
+ success(res) {
+ resolve(res.code)
+ },
+ fail(err) {
+ reject(new Error('微信登录失败'))
+ }
+ })
+ // #endif
+ // #ifdef APP-PLUS
+ plus.oauth.getServices((services) => {
+ let weixinAuthService = services.find((service) => {
+ return service.id === 'weixin';
+ });
+ if (weixinAuthService) {
+ weixinAuthService.authorize(function(res) {
+ resolve(res.code);
+ }, function(err) {
+ console.log(err);
+ reject(new Error('微信登录失败'));
+ });
+ }
+ });
+ // #endif
+ // #ifdef H5
+ resolve();
+ // #endif
+ })
+ },
+ /**
+ * 用户登录(微信授权)
+ * @description 用户登录(微信授权)
+ * data 请求参数 说明
+ * @param {String} code 微信登录返回的code
+ * @param {String} platform 客户端类型:mp-weixin、app-plus,默认uni-id会自动取客户端类型,但是在云函数url化等场景无法取到客户端类型,可以使用此参数指定
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} token 登录成功之后返回的token信息
+ * @param {String} tokenExpired token过期时间
+ */
+ loginByWeixin(obj = {}) {
+ let that = this;
+ debounce(() => {
+ addLoading(obj, "login");
+ let { data = {} } = obj;
+ that.getWeixinCode().then((code) => {
+ // #ifdef H5
+ // H5平台需要区分环境(如微信公众号?网页H5?)
+ data.vk_platform = uni.vk.h5.getEnv();
+ // #endif
+ callFunction({
+ url: 'user/pub/loginByWeixin',
+ ...obj,
+ data: {
+ code,
+ ...data
+ }
+ });
+ });
+ }, debounceTime, true, "login");
+ },
+ /**
+ * 获取微信openid
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} openid 用户openid
+ * @param {String} unionid 用户unionid,可以取到此值时返回
+ * @param {String} sessionKey 客户端为微信小程序时返回
+ * @param {String} accessToken 客户端为APP时返回
+ * @param {String} expiresIn 客户端为APP时返回,accessToken 接口调用凭证超时时间,单位(秒)
+ * @param {String} refreshToken 客户端为APP时返回,用于刷新accessToken
+ */
+ code2SessionWeixin(obj = {}) {
+ let that = this;
+ addLoading(obj, "loading");
+ let { data = {} } = obj;
+ that.getWeixinCode().then((code) => {
+ callFunction({
+ ...obj,
+ url: 'user/pub/code2SessionWeixin',
+ data: {
+ code,
+ ...data,
+ }
+ });
+ });
+ },
+ /**
+ * 绑定微信
+ * @description 将当前登录用户绑定微信
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ bindWeixin(obj = {}) {
+ let that = this;
+ addLoading(obj, "loading");
+ let { data = {} } = obj;
+ that.getWeixinCode().then((code) => {
+ // #ifdef H5
+ // H5平台需要区分环境(如微信公众号?网页H5?)
+ data.vk_platform = uni.vk.h5.getEnv();
+ // #endif
+ callFunction({
+ ...obj,
+ url: 'user/kh/bindWeixin',
+ data: {
+ code,
+ ...data
+ }
+ });
+ });
+ },
+ /**
+ * 解绑微信
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ unbindWeixin(obj = {}) {
+ addLoading(obj, "loading");
+ let { data = {} } = obj;
+ // #ifdef H5
+ // H5平台需要区分环境(如微信公众号?网页H5?)
+ data.vk_platform = uni.vk.h5.getEnv();
+ obj.data = data;
+ // #endif
+ return callFunction({
+ ...obj,
+ url: 'user/kh/unbindWeixin',
+ });
+ },
+ /**
+ * 获取微信绑定的手机号(后面会支持支付宝)
+ * data 请求参数
+ * @param {String} encryptedData
+ * @param {String} iv
+ * @param {String} sessionKey
+ */
+ getPhoneNumber(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/pub/getPhoneNumber'
+ });
+ },
+ /**
+ * 通过微信小程序绑定的手机号登录
+ * data 请求参数 说明
+ * @param {String} encryptedData
+ * @param {String} iv
+ * @param {String} sessionKey
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} token 登录成功之后返回的token信息
+ * @param {String} tokenExpired token过期时间
+ */
+ loginByWeixinPhoneNumber(obj = {}) {
+ return debounce(() => {
+ addLoading(obj, "login");
+ return callFunction({
+ url: 'user/pub/loginByWeixinPhoneNumber',
+ ...obj
+ });
+ }, debounceTime, true, "login");
+ },
+ /**
+ * 生成微信小程序码
+ * @param {String} scene 自定义参数最大32个可见字符 只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~
+ * @param {String} page 必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面
+ * @param {number} width 二维码的宽度,单位 px,最小 280px,最大 1280px
+ * @param {boolean} auto_color 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false
+ * @param {Object} line_color auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示
+ * @param {boolean} is_hyaline 是否需要透明底色,为 true 时,生成透明底色的小程序
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ getWeixinMPqrcode(obj = {}) {
+ addLoading(obj, "create");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/getWeixinMPqrcode',
+ });
+ },
+ /**
+ * 生成微信小程序scheme码
+ * data 请求参数 说明
+ * @param {String} path 小程序页面路径
+ * @param {String} query 小程序页面参数
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ getWeixinMPscheme(obj = {}) {
+ addLoading(obj, "create");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/getWeixinMPscheme',
+ });
+ },
+ /**
+ * 生成微信小程序url链接
+ * data 请求参数 说明
+ * @param {String} path 小程序页面路径
+ * @param {String} query 小程序页面参数
+ * @param {String} env_version 默认值"release"。要打开的小程序版本。正式版为 "release",体验版为"trial",开发版为"develop",仅在微信外打开时生效
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ getWeixinMPurl(obj = {}) {
+ addLoading(obj, "create");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/getWeixinMPurl',
+ });
+ },
+ /**
+ * 获取支付宝code
+ */
+ getAlipayCode() {
+ // #ifdef APP-PLUS || MP-ALIPAY
+ return new Promise((resolve, reject) => {
+ uni.login({
+ provider: 'alipay',
+ success(res) {
+ resolve(res.code);
+ },
+ fail(err) {
+ reject(new Error('支付宝登录失败'));
+ }
+ });
+ });
+ // #endif
+ },
+ /**
+ * 支付宝登录
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} token 登录成功之后返回的token信息
+ * @param {String} tokenExpired token过期时间
+ */
+ loginByAlipay(obj = {}) {
+ let that = this;
+ debounce(() => {
+ addLoading(obj, "login");
+ let { data = {} } = obj;
+ that.getAlipayCode().then((code) => {
+ callFunction({
+ url: 'user/pub/loginByAlipay',
+ ...obj,
+ data: {
+ ...data,
+ code: code
+ }
+ });
+ });
+ }, debounceTime, true, "login");
+ },
+ /**
+ * 获取支付宝openid
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} openid 用户openid
+ * @param {String} accessToken 客户端为APP时返回
+ * @param {String} expiresIn 客户端为APP时返回,accessToken 接口调用凭证超时时间,单位(秒)
+ * @param {String} refreshToken 客户端为APP时返回,用于刷新accessToken
+ * @param {String} reExpiresIn refreshToken超时时间,单位(秒)
+ */
+ code2SessionAlipay(obj = {}) {
+ let that = this;
+ addLoading(obj, "loading");
+ let { data = {} } = obj;
+ that.getAlipayCode().then((code) => {
+ callFunction({
+ ...obj,
+ url: 'user/pub/code2SessionAlipay',
+ data: {
+ ...data,
+ code: code
+ }
+ });
+ });
+ },
+ /**
+ * 绑定支付宝
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ bindAlipay(obj = {}) {
+ let that = this;
+ addLoading(obj, "loading");
+ let { data = {} } = obj;
+ that.getAlipayCode().then((code) => {
+ callFunction({
+ ...obj,
+ url: 'user/kh/bindAlipay',
+ data: {
+ ...data,
+ code: code
+ }
+ });
+ });
+ },
+ /**
+ * 解绑支付宝
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ unbindAlipay(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/unbindAlipay',
+ });
+ },
+ /**
+ * 生成支付宝小程序码
+ * @param {String} page 必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面
+ * @param {String} scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ getAlipayMiniCode(obj = {}) {
+ addLoading(obj, "create");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/getAlipayMiniCode',
+ });
+ },
+ /**
+ * 密码加密测试(暂不用)
+ */
+ encryptPwd(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/sys/encryptPwd',
+ });
+ },
+ // 1.1.2新增
+ /**
+ * 设置用户邀请码(自动生成)
+ * @description 针对未生成邀请码的用户使用此方法生成邀请码(自动生成)
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ * @param {String} myInviteCode 最终设置的邀请码
+ */
+ setUserInviteCode(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/setUserInviteCode',
+ });
+ },
+ /**
+ * 用户接受邀请
+ * @description 此接口用于在注册之后再填写邀请码的场景,多数情况下不会用到此接口而是在注册时填写邀请码
+ * data 请求参数 说明
+ * @param {String} inviteCode 邀请人的邀请码
+ * res 返回参数说明
+ * @param {Number} code 错误码,0表示成功
+ * @param {String} msg 详细信息
+ */
+ acceptInvite(obj = {}) {
+ addLoading(obj, "loading");
+ return callFunction({
+ ...obj,
+ url: 'user/kh/acceptInvite',
+ });
+ },
+ /**
+ * 获取接受邀请的用户清单
+ * data 请求参数 说明
+ * @param {Number} pageIndex 当前页码
+ * @param {Number} pageSize 每页显示数量
+ * @param {Array