Commit 8d31ed1d by 莫晓莉

残联二期项目APP页面

parents
<script>
import {
mapState,
mapMutations
} from 'vuex'
export default {
onLaunch: function() {
let uniIdToken = uni.getStorageSync('uniIdToken')
if (uniIdToken) {
this.login(uni.getStorageSync('username'))
}
console.log('App Launch');
},
onShow: function() {
console.log('App Show');
},
onHide: function() {
console.log('App Hide');
},
methods: {
...mapMutations(['login']),
}
}
</script>
<style>
@import './common/common.css';
/* 头条小程序需要把 iconfont 样式放到组件外 */
@import "components/m-icon/m-icon.css";
/*每个页面公共css */
page {
min-height: 100%;
display: flex;
font-size: 16px;
}
/* #ifdef MP-BAIDU */
page {
width: 100%;
height: 100%;
display: block;
}
swan-template {
width: 100%;
min-height: 100%;
display: flex;
}
/* 原生组件模式下需要注意组件外部样式 */
custom-component {
width: 100%;
min-height: 100%;
display: flex;
}
/* #endif */
/* #ifdef MP-ALIPAY */
page {
min-height: 100vh;
}
/* #endif */
/* 原生组件模式下需要注意组件外部样式 */
m-input {
width: 100%;
/* min-height: 100%; */
display: flex;
flex: 1;
}
.content {
display: flex;
flex: 1;
flex-direction: column;
background-color: #efeff4;
padding: 10px;
}
.input-group {
background-color: #ffffff;
margin-top: 20px;
position: relative;
}
.input-group::before {
position: absolute;
right: 0;
top: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #c8c7cc;
}
.input-group::after {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #c8c7cc;
}
.input-row {
display: flex;
flex-direction: row;
position: relative;
font-size: 18px;
line-height: 40px;
}
.input-row .title {
width: 100px;
padding-left: 15px;
}
.input-row.border::after {
position: absolute;
right: 0;
bottom: 0;
left: 8px;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #c8c7cc;
}
.btn-row {
margin-top: 25px;
padding: 10px;
}
button.primary {
background-color: #0faeff;
}
</style>
MIT License
Copyright (c) 2018 DCloud
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# uni-template-login
基于 uni-app & uniCloud 的前后一体登录模板
![](https://img-cdn-qiniu.dcloud.net.cn/7E6B79E2-B469-4CF3-8F4D-7502E72C4CB8.png?imageView2/0/w/375)
![](https://img-cdn-qiniu.dcloud.net.cn/659AE293-95F8-46E1-AC1F-D62FE3B080DB.png?imageView2/0/w/375)
## 快速体验
手机扫码体验:
![](https://img.cdn.aliyun.dcloud.net.cn/uni-app/uni-template-login-qr.png)
## 本地运行
1. 将项目拖入[HBuilderX](http://www.dcloud.io/hbuilderx.html)
2. 创建服务空间,详情参考[uniCloud 快速上手](https://uniapp.dcloud.net.cn/uniCloud/quickstart)
3. 上传 common 下的公用模块、在云函数 user-center 内安装 uni-id 模块并上传,[公用模块参考文档](https://uniapp.dcloud.io/uniCloud/cf-common)
4. 在 cloudfunctions 目录下的`db_init.json`右键初始化云数据库
5. 运行到 HBuilderX 内置浏览器体验
6. 如果运行到小程序,注意在小程序后台配置域名白名单,[详见](https://uniapp.dcloud.net.cn/uniCloud/quickstart?id=%e5%b0%8f%e7%a8%8b%e5%ba%8f%e4%b8%ad%e4%bd%bf%e7%94%a8unicloud%e7%9a%84%e7%99%bd%e5%90%8d%e5%8d%95%e9%85%8d%e7%bd%ae)
## 特点
- 前端基于uni-app实现,支持所有平台
- 服务端基于 uniCloud 实现,用户管理基于 [uni-id](https://uniapp.dcloud.net.cn/uniCloud/uni-id) 实现
- 使用 vuex 管理登录状态
- 支持账号密码、手机号验证等多种登录模式
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
{
"passwordSecret": "passwordSecret-demo",
"tokenSecret": "tokenSecret-demo",
"tokenExpiresIn": 7200,
"passwordErrorLimit": 6,
"bindTokenToDevice": true,
"passwordErrorRetryTime": 3600,
"app-plus": {
"tokenExpiresIn": 2592000,
"oauth" : {
"weixin" : {
"appid" : "weixin appid",
"appsecret" : "weixin appsecret"
}
}
},
"mp-weixin": {
"oauth" : {
"weixin" : {
"appid" : "weixin appid",
"appsecret" : "weixin appsecret"
}
}
},
"mp-alipay": {
"oauth" : {
"alipay" : {
"appid" : "alipay appid",
"privateKey" : "alipay privateKey"
}
}
},
"service": {
"sms": {
"name": "your app name",
"codeExpiresIn": 180,
"smsKey": "your sms key",
"smsSecret": "your sms secret"
}
}
}
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var t=e(require("crypto")),r=e(require("fs")),n=e(require("path")),o=e(require("buffer")),i=e(require("stream")),a=e(require("util")),s=e(require("querystring"));class c extends Error{constructor(e){super(e.message),this.errMsg=e.message||"",Object.defineProperties(this,{message:{get(){return`errCode: ${e.code||""} | errMsg: `+this.errMsg},set(e){this.errMsg=e}}})}}const u=Object.prototype.toString,f=Object.prototype.hasOwnProperty;function p(e,t){return f.call(e,t)}function d(e){return"[object Object]"===u.call(e)}function l(e){return"function"==typeof e}const h=/_(\w)/g,m=/[A-Z]/g;function g(e){return e.replace(h,(e,t)=>t?t.toUpperCase():"")}function y(e){return e.replace(m,e=>"_"+e.toLowerCase())}function w(e,t){let r,n;switch(t){case"snake2camel":n=g,r=h;break;case"camel2snake":n=y,r=m}for(const o in e)if(p(e,o)&&r.test(o)){const r=n(o);e[r]=e[o],delete e[o],d(e[r])?e[r]=w(e[r],t):Array.isArray(e[r])&&(e[r]=e[r].map(e=>w(e,t)))}return e}function v(e){return w(e,"snake2camel")}function b(e){return w(e,"camel2snake")}function _(e){return function(e,t="-"){e=e||new Date;const r=[];return r.push(e.getFullYear()),r.push(("00"+(e.getMonth()+1)).substr(-2)),r.push(("00"+e.getDate()).substr(-2)),r.join(t)}(e=e||new Date)+" "+function(e,t=":"){e=e||new Date;const r=[];return r.push(("00"+e.getHours()).substr(-2)),r.push(("00"+e.getMinutes()).substr(-2)),r.push(("00"+e.getSeconds()).substr(-2)),r.join(t)}(e)}function S(){"development"===process.env.NODE_ENV&&console.log(...arguments)}function E(e={},t){if(!t||!e)return e;const r=["_pre","_purify","_post"];t._pre&&(e=t._pre(e));let n={shouldDelete:new Set([])};if(t._purify){const e=t._purify;for(const t in e)e[t]=new Set(e[t]);n=Object.assign(n,e)}if(d(t))for(const o in t){const i=t[o];l(i)&&-1===r.indexOf(o)?e[o]=i(e):"string"==typeof i&&-1===r.indexOf(o)&&(e[o]=e[i],n.shouldDelete.add(i))}else l(t)&&(e=t(e));if(n.shouldDelete)for(const t of n.shouldDelete)delete e[t];return t._post&&(e=t._post(e)),e}function k(e,t){const r=new e(t);return new Proxy(r,{get:function(e,t){if("function"==typeof e[t]&&0!==t.indexOf("_")&&e._protocols&&e._protocols[t]){const r=e._protocols[t];return async function(n){n=E(n,r.args);let o=await e[t](n);return o=E(o,r.returnValue),o}}return e[t]}})}const x=uniCloud.database(),j=x.collection("uni-id-users"),T=x.collection("uni-verify");let O={};try{O=JSON.parse(r.readFileSync(n.resolve(__dirname,"config.json")))}catch(e){}function I(){const e=Object.assign(O,O[__ctx__.PLATFORM])||{},t=Object.assign({bindTokenToDevice:!0},e);return["passwordSecret","tokenSecret","tokenExpiresIn","passwordErrorLimit","passwordErrorRetryTime"].forEach(e=>{if(!t||!t[e])throw new Error("请在公用模块uni-id的config.json或init方法中内添加配置项:"+e)}),t}function R(e){let t,r,n=e-Date.now(),o="后";n<0&&(o="前",n=-n);const i=Math.floor(n/1e3),a=Math.floor(i/60),s=Math.floor(a/60),c=Math.floor(s/24),u=Math.floor(c/30),f=Math.floor(u/12);switch(!0){case f>0:t=f,r="年";break;case u>0:t=u,r="月";break;case c>0:t=c,r="天";break;case s>0:t=s,r="小时";break;case a>0:t=a,r="分钟";break;default:t=i,r="秒"}return`${t}${r}${o}`}function A(e){const r=I(),n=t.createHmac("sha1",r.passwordSecret.toString("ascii"));return n.update(e),n.digest("hex")}function P(e,t){return e(t={exports:{}},t.exports),t.exports}var C=P((function(e,t){var r=o.Buffer;function n(e,t){for(var r in e)t[r]=e[r]}function i(e,t,n){return r(e,t,n)}r.from&&r.alloc&&r.allocUnsafe&&r.allocUnsafeSlow?e.exports=o:(n(o,t),t.Buffer=i),i.prototype=Object.create(r.prototype),n(r,i),i.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return r(e,t,n)},i.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var o=r(e);return void 0!==t?"string"==typeof n?o.fill(t,n):o.fill(t):o.fill(0),o},i.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r(e)},i.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o.SlowBuffer(e)}})),$=(C.Buffer,C.Buffer);function N(e){if(this.buffer=null,this.writable=!0,this.readable=!0,!e)return this.buffer=$.alloc(0),this;if("function"==typeof e.pipe)return this.buffer=$.alloc(0),e.pipe(this),this;if(e.length||"object"==typeof e)return this.buffer=e,this.writable=!1,process.nextTick(function(){this.emit("end",e),this.readable=!1,this.emit("close")}.bind(this)),this;throw new TypeError("Unexpected data type ("+typeof e+")")}a.inherits(N,i),N.prototype.write=function(e){this.buffer=$.concat([this.buffer,$.from(e)]),this.emit("data",e)},N.prototype.end=function(e){e&&this.write(e),this.emit("end",e),this.emit("close"),this.writable=!1,this.readable=!1};var B=N,D=o.Buffer,M=o.SlowBuffer,V=K;function K(e,t){if(!D.isBuffer(e)||!D.isBuffer(t))return!1;if(e.length!==t.length)return!1;for(var r=0,n=0;n<e.length;n++)r|=e[n]^t[n];return 0===r}K.install=function(){D.prototype.equal=M.prototype.equal=function(e){return K(this,e)}};var L=D.prototype.equal,q=M.prototype.equal;function H(e){return(e/8|0)+(e%8==0?0:1)}K.restore=function(){D.prototype.equal=L,M.prototype.equal=q};var U={ES256:H(256),ES384:H(384),ES512:H(521)};var J=function(e){var t=U[e];if(t)return t;throw new Error('Unknown algorithm "'+e+'"')},F=C.Buffer;function G(e){if(F.isBuffer(e))return e;if("string"==typeof e)return F.from(e,"base64");throw new TypeError("ECDSA signature must be a Base64 string or a Buffer")}function z(e,t,r){for(var n=0;t+n<r&&0===e[t+n];)++n;return e[t+n]>=128&&--n,n}var W={derToJose:function(e,t){e=G(e);var r=J(t),n=r+1,o=e.length,i=0;if(48!==e[i++])throw new Error('Could not find expected "seq"');var a=e[i++];if(129===a&&(a=e[i++]),o-i<a)throw new Error('"seq" specified length of "'+a+'", only "'+(o-i)+'" remaining');if(2!==e[i++])throw new Error('Could not find expected "int" for "r"');var s=e[i++];if(o-i-2<s)throw new Error('"r" specified length of "'+s+'", only "'+(o-i-2)+'" available');if(n<s)throw new Error('"r" specified length of "'+s+'", max of "'+n+'" is acceptable');var c=i;if(i+=s,2!==e[i++])throw new Error('Could not find expected "int" for "s"');var u=e[i++];if(o-i!==u)throw new Error('"s" specified length of "'+u+'", expected "'+(o-i)+'"');if(n<u)throw new Error('"s" specified length of "'+u+'", max of "'+n+'" is acceptable');var f=i;if((i+=u)!==o)throw new Error('Expected to consume entire buffer, but "'+(o-i)+'" bytes remain');var p=r-s,d=r-u,l=F.allocUnsafe(p+s+d+u);for(i=0;i<p;++i)l[i]=0;e.copy(l,i,c+Math.max(-p,0),c+s);for(var h=i=r;i<h+d;++i)l[i]=0;return e.copy(l,i,f+Math.max(-d,0),f+u),l=(l=l.toString("base64")).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")},joseToDer:function(e,t){e=G(e);var r=J(t),n=e.length;if(n!==2*r)throw new TypeError('"'+t+'" signatures must be "'+2*r+'" bytes, saw "'+n+'"');var o=z(e,0,r),i=z(e,r,e.length),a=r-o,s=r-i,c=2+a+1+1+s,u=c<128,f=F.allocUnsafe((u?2:3)+c),p=0;return f[p++]=48,u?f[p++]=c:(f[p++]=129,f[p++]=255&c),f[p++]=2,f[p++]=a,o<0?(f[p++]=0,p+=e.copy(f,p,0,r)):p+=e.copy(f,p,o,r),f[p++]=2,f[p++]=s,i<0?(f[p++]=0,e.copy(f,p,r)):e.copy(f,p,r+i),f}},Z=C.Buffer,Y="secret must be a string or buffer",X="key must be a string or a buffer",Q="function"==typeof t.createPublicKey;function ee(e){if(!Z.isBuffer(e)&&"string"!=typeof e){if(!Q)throw oe(X);if("object"!=typeof e)throw oe(X);if("string"!=typeof e.type)throw oe(X);if("string"!=typeof e.asymmetricKeyType)throw oe(X);if("function"!=typeof e.export)throw oe(X)}}function te(e){if(!Z.isBuffer(e)&&"string"!=typeof e&&"object"!=typeof e)throw oe("key must be a string, a buffer or an object")}function re(e){return e.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function ne(e){var t=4-(e=e.toString()).length%4;if(4!==t)for(var r=0;r<t;++r)e+="=";return e.replace(/\-/g,"+").replace(/_/g,"/")}function oe(e){var t=[].slice.call(arguments,1),r=a.format.bind(a,e).apply(null,t);return new TypeError(r)}function ie(e){var t;return t=e,Z.isBuffer(t)||"string"==typeof t||(e=JSON.stringify(e)),e}function ae(e){return function(r,n){!function(e){if(!Z.isBuffer(e)){if("string"==typeof e)return e;if(!Q)throw oe(Y);if("object"!=typeof e)throw oe(Y);if("secret"!==e.type)throw oe(Y);if("function"!=typeof e.export)throw oe(Y)}}(n),r=ie(r);var o=t.createHmac("sha"+e,n);return re((o.update(r),o.digest("base64")))}}function se(e){return function(t,r,n){var o=ae(e)(t,n);return V(Z.from(r),Z.from(o))}}function ce(e){return function(r,n){te(n),r=ie(r);var o=t.createSign("RSA-SHA"+e);return re((o.update(r),o.sign(n,"base64")))}}function ue(e){return function(r,n,o){ee(o),r=ie(r),n=ne(n);var i=t.createVerify("RSA-SHA"+e);return i.update(r),i.verify(o,n,"base64")}}function fe(e){return function(r,n){te(n),r=ie(r);var o=t.createSign("RSA-SHA"+e);return re((o.update(r),o.sign({key:n,padding:t.constants.RSA_PKCS1_PSS_PADDING,saltLength:t.constants.RSA_PSS_SALTLEN_DIGEST},"base64")))}}function pe(e){return function(r,n,o){ee(o),r=ie(r),n=ne(n);var i=t.createVerify("RSA-SHA"+e);return i.update(r),i.verify({key:o,padding:t.constants.RSA_PKCS1_PSS_PADDING,saltLength:t.constants.RSA_PSS_SALTLEN_DIGEST},n,"base64")}}function de(e){var t=ce(e);return function(){var r=t.apply(null,arguments);return r=W.derToJose(r,"ES"+e)}}function le(e){var t=ue(e);return function(r,n,o){return n=W.joseToDer(n,"ES"+e).toString("base64"),t(r,n,o)}}function he(){return function(){return""}}function me(){return function(e,t){return""===t}}Q&&(X+=" or a KeyObject",Y+="or a KeyObject");var ge=function(e){var t={hs:ae,rs:ce,ps:fe,es:de,none:he},r={hs:se,rs:ue,ps:pe,es:le,none:me},n=e.match(/^(RS|PS|ES|HS)(256|384|512)$|^(none)$/i);if(!n)throw oe('"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".',e);var o=(n[1]||n[3]).toLowerCase(),i=n[2];return{sign:t[o](i),verify:r[o](i)}},ye=o.Buffer,we=function(e){return"string"==typeof e?e:"number"==typeof e||ye.isBuffer(e)?e.toString():JSON.stringify(e)},ve=C.Buffer;function be(e,t){return ve.from(e,t).toString("base64").replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function _e(e){var t=e.header,r=e.payload,n=e.secret||e.privateKey,o=e.encoding,i=ge(t.alg),s=function(e,t,r){r=r||"utf8";var n=be(we(e),"binary"),o=be(we(t),r);return a.format("%s.%s",n,o)}(t,r,o),c=i.sign(s,n);return a.format("%s.%s",s,c)}function Se(e){var t=e.secret||e.privateKey||e.key,r=new B(t);this.readable=!0,this.header=e.header,this.encoding=e.encoding,this.secret=this.privateKey=this.key=r,this.payload=new B(e.payload),this.secret.once("close",function(){!this.payload.writable&&this.readable&&this.sign()}.bind(this)),this.payload.once("close",function(){!this.secret.writable&&this.readable&&this.sign()}.bind(this))}a.inherits(Se,i),Se.prototype.sign=function(){try{var e=_e({header:this.header,payload:this.payload.buffer,secret:this.secret.buffer,encoding:this.encoding});return this.emit("done",e),this.emit("data",e),this.emit("end"),this.readable=!1,e}catch(e){this.readable=!1,this.emit("error",e),this.emit("close")}},Se.sign=_e;var Ee=Se,ke=C.Buffer,xe=/^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;function je(e){if(function(e){return"[object Object]"===Object.prototype.toString.call(e)}(e))return e;try{return JSON.parse(e)}catch(e){return}}function Te(e){var t=e.split(".",1)[0];return je(ke.from(t,"base64").toString("binary"))}function Oe(e){return e.split(".")[2]}function Ie(e){return xe.test(e)&&!!Te(e)}function Re(e,t,r){if(!t){var n=new Error("Missing algorithm parameter for jws.verify");throw n.code="MISSING_ALGORITHM",n}var o=Oe(e=we(e)),i=function(e){return e.split(".",2).join(".")}(e);return ge(t).verify(i,o,r)}function Ae(e,t){if(t=t||{},!Ie(e=we(e)))return null;var r=Te(e);if(!r)return null;var n=function(e,t){t=t||"utf8";var r=e.split(".")[1];return ke.from(r,"base64").toString(t)}(e);return("JWT"===r.typ||t.json)&&(n=JSON.parse(n,t.encoding)),{header:r,payload:n,signature:Oe(e)}}function Pe(e){var t=(e=e||{}).secret||e.publicKey||e.key,r=new B(t);this.readable=!0,this.algorithm=e.algorithm,this.encoding=e.encoding,this.secret=this.publicKey=this.key=r,this.signature=new B(e.signature),this.secret.once("close",function(){!this.signature.writable&&this.readable&&this.verify()}.bind(this)),this.signature.once("close",function(){!this.secret.writable&&this.readable&&this.verify()}.bind(this))}a.inherits(Pe,i),Pe.prototype.verify=function(){try{var e=Re(this.signature.buffer,this.algorithm,this.key.buffer),t=Ae(this.signature.buffer,this.encoding);return this.emit("done",e,t),this.emit("data",e),this.emit("end"),this.readable=!1,e}catch(e){this.readable=!1,this.emit("error",e),this.emit("close")}},Pe.decode=Ae,Pe.isValid=Ie,Pe.verify=Re;var Ce=Pe,$e={ALGORITHMS:["HS256","HS384","HS512","RS256","RS384","RS512","PS256","PS384","PS512","ES256","ES384","ES512"],sign:Ee.sign,verify:Ce.verify,decode:Ce.decode,isValid:Ce.isValid,createSign:function(e){return new Ee(e)},createVerify:function(e){return new Ce(e)}},Ne=function(e,t){t=t||{};var r=$e.decode(e,t);if(!r)return null;var n=r.payload;if("string"==typeof n)try{var o=JSON.parse(n);null!==o&&"object"==typeof o&&(n=o)}catch(e){}return!0===t.complete?{header:r.header,payload:n,signature:r.signature}:n},Be=function(e,t){Error.call(this,e),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name="JsonWebTokenError",this.message=e,t&&(this.inner=t)};(Be.prototype=Object.create(Error.prototype)).constructor=Be;var De=Be,Me=function(e,t){De.call(this,e),this.name="NotBeforeError",this.date=t};(Me.prototype=Object.create(De.prototype)).constructor=Me;var Ve=Me,Ke=function(e,t){De.call(this,e),this.name="TokenExpiredError",this.expiredAt=t};(Ke.prototype=Object.create(De.prototype)).constructor=Ke;var Le=Ke,qe=1e3,He=60*qe,Ue=60*He,Je=24*Ue,Fe=function(e,t){t=t||{};var r=typeof e;if("string"===r&&e.length>0)return function(e){if((e=String(e)).length>100)return;var t=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(!t)return;var r=parseFloat(t[1]);switch((t[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return 315576e5*r;case"weeks":case"week":case"w":return 6048e5*r;case"days":case"day":case"d":return r*Je;case"hours":case"hour":case"hrs":case"hr":case"h":return r*Ue;case"minutes":case"minute":case"mins":case"min":case"m":return r*He;case"seconds":case"second":case"secs":case"sec":case"s":return r*qe;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r;default:return}}(e);if("number"===r&&isFinite(e))return t.long?function(e){var t=Math.abs(e);if(t>=Je)return Ge(e,t,Je,"day");if(t>=Ue)return Ge(e,t,Ue,"hour");if(t>=He)return Ge(e,t,He,"minute");if(t>=qe)return Ge(e,t,qe,"second");return e+" ms"}(e):function(e){var t=Math.abs(e);if(t>=Je)return Math.round(e/Je)+"d";if(t>=Ue)return Math.round(e/Ue)+"h";if(t>=He)return Math.round(e/He)+"m";if(t>=qe)return Math.round(e/qe)+"s";return e+"ms"}(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))};function Ge(e,t,r,n){var o=t>=1.5*r;return Math.round(e/r)+" "+n+(o?"s":"")}var ze=function(e,t){var r=t||Math.floor(Date.now()/1e3);if("string"==typeof e){var n=Fe(e);if(void 0===n)return;return Math.floor(r+n/1e3)}return"number"==typeof e?r+e:void 0},We=P((function(e,t){var r;t=e.exports=F,r="object"==typeof process&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?function(){var e=Array.prototype.slice.call(arguments,0);e.unshift("SEMVER"),console.log.apply(console,e)}:function(){},t.SEMVER_SPEC_VERSION="2.0.0";var n=Number.MAX_SAFE_INTEGER||9007199254740991,o=t.re=[],i=t.src=[],a=0,s=a++;i[s]="0|[1-9]\\d*";var c=a++;i[c]="[0-9]+";var u=a++;i[u]="\\d*[a-zA-Z-][a-zA-Z0-9-]*";var f=a++;i[f]="("+i[s]+")\\.("+i[s]+")\\.("+i[s]+")";var p=a++;i[p]="("+i[c]+")\\.("+i[c]+")\\.("+i[c]+")";var d=a++;i[d]="(?:"+i[s]+"|"+i[u]+")";var l=a++;i[l]="(?:"+i[c]+"|"+i[u]+")";var h=a++;i[h]="(?:-("+i[d]+"(?:\\."+i[d]+")*))";var m=a++;i[m]="(?:-?("+i[l]+"(?:\\."+i[l]+")*))";var g=a++;i[g]="[0-9A-Za-z-]+";var y=a++;i[y]="(?:\\+("+i[g]+"(?:\\."+i[g]+")*))";var w=a++,v="v?"+i[f]+i[h]+"?"+i[y]+"?";i[w]="^"+v+"$";var b="[v=\\s]*"+i[p]+i[m]+"?"+i[y]+"?",_=a++;i[_]="^"+b+"$";var S=a++;i[S]="((?:<|>)?=?)";var E=a++;i[E]=i[c]+"|x|X|\\*";var k=a++;i[k]=i[s]+"|x|X|\\*";var x=a++;i[x]="[v=\\s]*("+i[k]+")(?:\\.("+i[k]+")(?:\\.("+i[k]+")(?:"+i[h]+")?"+i[y]+"?)?)?";var j=a++;i[j]="[v=\\s]*("+i[E]+")(?:\\.("+i[E]+")(?:\\.("+i[E]+")(?:"+i[m]+")?"+i[y]+"?)?)?";var T=a++;i[T]="^"+i[S]+"\\s*"+i[x]+"$";var O=a++;i[O]="^"+i[S]+"\\s*"+i[j]+"$";var I=a++;i[I]="(?:^|[^\\d])(\\d{1,16})(?:\\.(\\d{1,16}))?(?:\\.(\\d{1,16}))?(?:$|[^\\d])";var R=a++;i[R]="(?:~>?)";var A=a++;i[A]="(\\s*)"+i[R]+"\\s+",o[A]=new RegExp(i[A],"g");var P=a++;i[P]="^"+i[R]+i[x]+"$";var C=a++;i[C]="^"+i[R]+i[j]+"$";var $=a++;i[$]="(?:\\^)";var N=a++;i[N]="(\\s*)"+i[$]+"\\s+",o[N]=new RegExp(i[N],"g");var B=a++;i[B]="^"+i[$]+i[x]+"$";var D=a++;i[D]="^"+i[$]+i[j]+"$";var M=a++;i[M]="^"+i[S]+"\\s*("+b+")$|^$";var V=a++;i[V]="^"+i[S]+"\\s*("+v+")$|^$";var K=a++;i[K]="(\\s*)"+i[S]+"\\s*("+b+"|"+i[x]+")",o[K]=new RegExp(i[K],"g");var L=a++;i[L]="^\\s*("+i[x]+")\\s+-\\s+("+i[x]+")\\s*$";var q=a++;i[q]="^\\s*("+i[j]+")\\s+-\\s+("+i[j]+")\\s*$";var H=a++;i[H]="(<|>)?=?\\s*\\*";for(var U=0;U<35;U++)r(U,i[U]),o[U]||(o[U]=new RegExp(i[U]));function J(e,t){if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),e instanceof F)return e;if("string"!=typeof e)return null;if(e.length>256)return null;if(!(t.loose?o[_]:o[w]).test(e))return null;try{return new F(e,t)}catch(e){return null}}function F(e,t){if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),e instanceof F){if(e.loose===t.loose)return e;e=e.version}else if("string"!=typeof e)throw new TypeError("Invalid Version: "+e);if(e.length>256)throw new TypeError("version is longer than 256 characters");if(!(this instanceof F))return new F(e,t);r("SemVer",e,t),this.options=t,this.loose=!!t.loose;var i=e.trim().match(t.loose?o[_]:o[w]);if(!i)throw new TypeError("Invalid Version: "+e);if(this.raw=e,this.major=+i[1],this.minor=+i[2],this.patch=+i[3],this.major>n||this.major<0)throw new TypeError("Invalid major version");if(this.minor>n||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>n||this.patch<0)throw new TypeError("Invalid patch version");i[4]?this.prerelease=i[4].split(".").map((function(e){if(/^[0-9]+$/.test(e)){var t=+e;if(t>=0&&t<n)return t}return e})):this.prerelease=[],this.build=i[5]?i[5].split("."):[],this.format()}t.parse=J,t.valid=function(e,t){var r=J(e,t);return r?r.version:null},t.clean=function(e,t){var r=J(e.trim().replace(/^[=v]+/,""),t);return r?r.version:null},t.SemVer=F,F.prototype.format=function(){return this.version=this.major+"."+this.minor+"."+this.patch,this.prerelease.length&&(this.version+="-"+this.prerelease.join(".")),this.version},F.prototype.toString=function(){return this.version},F.prototype.compare=function(e){return r("SemVer.compare",this.version,this.options,e),e instanceof F||(e=new F(e,this.options)),this.compareMain(e)||this.comparePre(e)},F.prototype.compareMain=function(e){return e instanceof F||(e=new F(e,this.options)),z(this.major,e.major)||z(this.minor,e.minor)||z(this.patch,e.patch)},F.prototype.comparePre=function(e){if(e instanceof F||(e=new F(e,this.options)),this.prerelease.length&&!e.prerelease.length)return-1;if(!this.prerelease.length&&e.prerelease.length)return 1;if(!this.prerelease.length&&!e.prerelease.length)return 0;var t=0;do{var n=this.prerelease[t],o=e.prerelease[t];if(r("prerelease compare",t,n,o),void 0===n&&void 0===o)return 0;if(void 0===o)return 1;if(void 0===n)return-1;if(n!==o)return z(n,o)}while(++t)},F.prototype.inc=function(e,t){switch(e){case"premajor":this.prerelease.length=0,this.patch=0,this.minor=0,this.major++,this.inc("pre",t);break;case"preminor":this.prerelease.length=0,this.patch=0,this.minor++,this.inc("pre",t);break;case"prepatch":this.prerelease.length=0,this.inc("patch",t),this.inc("pre",t);break;case"prerelease":0===this.prerelease.length&&this.inc("patch",t),this.inc("pre",t);break;case"major":0===this.minor&&0===this.patch&&0!==this.prerelease.length||this.major++,this.minor=0,this.patch=0,this.prerelease=[];break;case"minor":0===this.patch&&0!==this.prerelease.length||this.minor++,this.patch=0,this.prerelease=[];break;case"patch":0===this.prerelease.length&&this.patch++,this.prerelease=[];break;case"pre":if(0===this.prerelease.length)this.prerelease=[0];else{for(var r=this.prerelease.length;--r>=0;)"number"==typeof this.prerelease[r]&&(this.prerelease[r]++,r=-2);-1===r&&this.prerelease.push(0)}t&&(this.prerelease[0]===t?isNaN(this.prerelease[1])&&(this.prerelease=[t,0]):this.prerelease=[t,0]);break;default:throw new Error("invalid increment argument: "+e)}return this.format(),this.raw=this.version,this},t.inc=function(e,t,r,n){"string"==typeof r&&(n=r,r=void 0);try{return new F(e,r).inc(t,n).version}catch(e){return null}},t.diff=function(e,t){if(X(e,t))return null;var r=J(e),n=J(t),o="";if(r.prerelease.length||n.prerelease.length){o="pre";var i="prerelease"}for(var a in r)if(("major"===a||"minor"===a||"patch"===a)&&r[a]!==n[a])return o+a;return i},t.compareIdentifiers=z;var G=/^[0-9]+$/;function z(e,t){var r=G.test(e),n=G.test(t);return r&&n&&(e=+e,t=+t),e===t?0:r&&!n?-1:n&&!r?1:e<t?-1:1}function W(e,t,r){return new F(e,r).compare(new F(t,r))}function Z(e,t,r){return W(e,t,r)>0}function Y(e,t,r){return W(e,t,r)<0}function X(e,t,r){return 0===W(e,t,r)}function Q(e,t,r){return 0!==W(e,t,r)}function ee(e,t,r){return W(e,t,r)>=0}function te(e,t,r){return W(e,t,r)<=0}function re(e,t,r,n){switch(t){case"===":return"object"==typeof e&&(e=e.version),"object"==typeof r&&(r=r.version),e===r;case"!==":return"object"==typeof e&&(e=e.version),"object"==typeof r&&(r=r.version),e!==r;case"":case"=":case"==":return X(e,r,n);case"!=":return Q(e,r,n);case">":return Z(e,r,n);case">=":return ee(e,r,n);case"<":return Y(e,r,n);case"<=":return te(e,r,n);default:throw new TypeError("Invalid operator: "+t)}}function ne(e,t){if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),e instanceof ne){if(e.loose===!!t.loose)return e;e=e.value}if(!(this instanceof ne))return new ne(e,t);r("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===oe?this.value="":this.value=this.operator+this.semver.version,r("comp",this)}t.rcompareIdentifiers=function(e,t){return z(t,e)},t.major=function(e,t){return new F(e,t).major},t.minor=function(e,t){return new F(e,t).minor},t.patch=function(e,t){return new F(e,t).patch},t.compare=W,t.compareLoose=function(e,t){return W(e,t,!0)},t.rcompare=function(e,t,r){return W(t,e,r)},t.sort=function(e,r){return e.sort((function(e,n){return t.compare(e,n,r)}))},t.rsort=function(e,r){return e.sort((function(e,n){return t.rcompare(e,n,r)}))},t.gt=Z,t.lt=Y,t.eq=X,t.neq=Q,t.gte=ee,t.lte=te,t.cmp=re,t.Comparator=ne;var oe={};function ie(e,t){if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),e instanceof ie)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new ie(e.raw,t);if(e instanceof ne)return new ie(e.value,t);if(!(this instanceof ie))return new ie(e,t);if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e,this.set=e.split(/\s*\|\|\s*/).map((function(e){return this.parseRange(e.trim())}),this).filter((function(e){return e.length})),!this.set.length)throw new TypeError("Invalid SemVer Range: "+e);this.format()}function ae(e){return!e||"x"===e.toLowerCase()||"*"===e}function se(e,t,r,n,o,i,a,s,c,u,f,p,d){return((t=ae(r)?"":ae(n)?">="+r+".0.0":ae(o)?">="+r+"."+n+".0":">="+t)+" "+(s=ae(c)?"":ae(u)?"<"+(+c+1)+".0.0":ae(f)?"<"+c+"."+(+u+1)+".0":p?"<="+c+"."+u+"."+f+"-"+p:"<="+s)).trim()}function ce(e,t,n){for(var o=0;o<e.length;o++)if(!e[o].test(t))return!1;if(t.prerelease.length&&!n.includePrerelease){for(o=0;o<e.length;o++)if(r(e[o].semver),e[o].semver!==oe&&e[o].semver.prerelease.length>0){var i=e[o].semver;if(i.major===t.major&&i.minor===t.minor&&i.patch===t.patch)return!0}return!1}return!0}function ue(e,t,r){try{t=new ie(t,r)}catch(e){return!1}return t.test(e)}function fe(e,t,r,n){var o,i,a,s,c;switch(e=new F(e,n),t=new ie(t,n),r){case">":o=Z,i=te,a=Y,s=">",c=">=";break;case"<":o=Y,i=ee,a=Z,s="<",c="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(ue(e,t,n))return!1;for(var u=0;u<t.set.length;++u){var f=t.set[u],p=null,d=null;if(f.forEach((function(e){e.semver===oe&&(e=new ne(">=0.0.0")),p=p||e,d=d||e,o(e.semver,p.semver,n)?p=e:a(e.semver,d.semver,n)&&(d=e)})),p.operator===s||p.operator===c)return!1;if((!d.operator||d.operator===s)&&i(e,d.semver))return!1;if(d.operator===c&&a(e,d.semver))return!1}return!0}ne.prototype.parse=function(e){var t=this.options.loose?o[M]:o[V],r=e.match(t);if(!r)throw new TypeError("Invalid comparator: "+e);this.operator=r[1],"="===this.operator&&(this.operator=""),r[2]?this.semver=new F(r[2],this.options.loose):this.semver=oe},ne.prototype.toString=function(){return this.value},ne.prototype.test=function(e){return r("Comparator.test",e,this.options.loose),this.semver===oe||("string"==typeof e&&(e=new F(e,this.options)),re(e,this.operator,this.semver,this.options))},ne.prototype.intersects=function(e,t){if(!(e instanceof ne))throw new TypeError("a Comparator is required");var r;if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),""===this.operator)return r=new ie(e.value,t),ue(this.value,r,t);if(""===e.operator)return r=new ie(this.value,t),ue(e.semver,r,t);var n=!(">="!==this.operator&&">"!==this.operator||">="!==e.operator&&">"!==e.operator),o=!("<="!==this.operator&&"<"!==this.operator||"<="!==e.operator&&"<"!==e.operator),i=this.semver.version===e.semver.version,a=!(">="!==this.operator&&"<="!==this.operator||">="!==e.operator&&"<="!==e.operator),s=re(this.semver,"<",e.semver,t)&&(">="===this.operator||">"===this.operator)&&("<="===e.operator||"<"===e.operator),c=re(this.semver,">",e.semver,t)&&("<="===this.operator||"<"===this.operator)&&(">="===e.operator||">"===e.operator);return n||o||i&&a||s||c},t.Range=ie,ie.prototype.format=function(){return this.range=this.set.map((function(e){return e.join(" ").trim()})).join("||").trim(),this.range},ie.prototype.toString=function(){return this.range},ie.prototype.parseRange=function(e){var t=this.options.loose;e=e.trim();var n=t?o[q]:o[L];e=e.replace(n,se),r("hyphen replace",e),e=e.replace(o[K],"$1$2$3"),r("comparator trim",e,o[K]),e=(e=(e=e.replace(o[A],"$1~")).replace(o[N],"$1^")).split(/\s+/).join(" ");var i=t?o[M]:o[V],a=e.split(" ").map((function(e){return function(e,t){return r("comp",e,t),e=function(e,t){return e.trim().split(/\s+/).map((function(e){return function(e,t){r("caret",e,t);var n=t.loose?o[D]:o[B];return e.replace(n,(function(t,n,o,i,a){var s;return r("caret",e,t,n,o,i,a),ae(n)?s="":ae(o)?s=">="+n+".0.0 <"+(+n+1)+".0.0":ae(i)?s="0"===n?">="+n+"."+o+".0 <"+n+"."+(+o+1)+".0":">="+n+"."+o+".0 <"+(+n+1)+".0.0":a?(r("replaceCaret pr",a),s="0"===n?"0"===o?">="+n+"."+o+"."+i+"-"+a+" <"+n+"."+o+"."+(+i+1):">="+n+"."+o+"."+i+"-"+a+" <"+n+"."+(+o+1)+".0":">="+n+"."+o+"."+i+"-"+a+" <"+(+n+1)+".0.0"):(r("no pr"),s="0"===n?"0"===o?">="+n+"."+o+"."+i+" <"+n+"."+o+"."+(+i+1):">="+n+"."+o+"."+i+" <"+n+"."+(+o+1)+".0":">="+n+"."+o+"."+i+" <"+(+n+1)+".0.0"),r("caret return",s),s}))}(e,t)})).join(" ")}(e,t),r("caret",e),e=function(e,t){return e.trim().split(/\s+/).map((function(e){return function(e,t){var n=t.loose?o[C]:o[P];return e.replace(n,(function(t,n,o,i,a){var s;return r("tilde",e,t,n,o,i,a),ae(n)?s="":ae(o)?s=">="+n+".0.0 <"+(+n+1)+".0.0":ae(i)?s=">="+n+"."+o+".0 <"+n+"."+(+o+1)+".0":a?(r("replaceTilde pr",a),s=">="+n+"."+o+"."+i+"-"+a+" <"+n+"."+(+o+1)+".0"):s=">="+n+"."+o+"."+i+" <"+n+"."+(+o+1)+".0",r("tilde return",s),s}))}(e,t)})).join(" ")}(e,t),r("tildes",e),e=function(e,t){return r("replaceXRanges",e,t),e.split(/\s+/).map((function(e){return function(e,t){e=e.trim();var n=t.loose?o[O]:o[T];return e.replace(n,(function(t,n,o,i,a,s){r("xRange",e,t,n,o,i,a,s);var c=ae(o),u=c||ae(i),f=u||ae(a);return"="===n&&f&&(n=""),c?t=">"===n||"<"===n?"<0.0.0":"*":n&&f?(u&&(i=0),a=0,">"===n?(n=">=",u?(o=+o+1,i=0,a=0):(i=+i+1,a=0)):"<="===n&&(n="<",u?o=+o+1:i=+i+1),t=n+o+"."+i+"."+a):u?t=">="+o+".0.0 <"+(+o+1)+".0.0":f&&(t=">="+o+"."+i+".0 <"+o+"."+(+i+1)+".0"),r("xRange return",t),t}))}(e,t)})).join(" ")}(e,t),r("xrange",e),e=function(e,t){return r("replaceStars",e,t),e.trim().replace(o[H],"")}(e,t),r("stars",e),e}(e,this.options)}),this).join(" ").split(/\s+/);return this.options.loose&&(a=a.filter((function(e){return!!e.match(i)}))),a=a.map((function(e){return new ne(e,this.options)}),this)},ie.prototype.intersects=function(e,t){if(!(e instanceof ie))throw new TypeError("a Range is required");return this.set.some((function(r){return r.every((function(r){return e.set.some((function(e){return e.every((function(e){return r.intersects(e,t)}))}))}))}))},t.toComparators=function(e,t){return new ie(e,t).set.map((function(e){return e.map((function(e){return e.value})).join(" ").trim().split(" ")}))},ie.prototype.test=function(e){if(!e)return!1;"string"==typeof e&&(e=new F(e,this.options));for(var t=0;t<this.set.length;t++)if(ce(this.set[t],e,this.options))return!0;return!1},t.satisfies=ue,t.maxSatisfying=function(e,t,r){var n=null,o=null;try{var i=new ie(t,r)}catch(e){return null}return e.forEach((function(e){i.test(e)&&(n&&-1!==o.compare(e)||(o=new F(n=e,r)))})),n},t.minSatisfying=function(e,t,r){var n=null,o=null;try{var i=new ie(t,r)}catch(e){return null}return e.forEach((function(e){i.test(e)&&(n&&1!==o.compare(e)||(o=new F(n=e,r)))})),n},t.minVersion=function(e,t){e=new ie(e,t);var r=new F("0.0.0");if(e.test(r))return r;if(r=new F("0.0.0-0"),e.test(r))return r;r=null;for(var n=0;n<e.set.length;++n){e.set[n].forEach((function(e){var t=new F(e.semver.version);switch(e.operator){case">":0===t.prerelease.length?t.patch++:t.prerelease.push(0),t.raw=t.format();case"":case">=":r&&!Z(r,t)||(r=t);break;case"<":case"<=":break;default:throw new Error("Unexpected operation: "+e.operator)}}))}if(r&&e.test(r))return r;return null},t.validRange=function(e,t){try{return new ie(e,t).range||"*"}catch(e){return null}},t.ltr=function(e,t,r){return fe(e,t,"<",r)},t.gtr=function(e,t,r){return fe(e,t,">",r)},t.outside=fe,t.prerelease=function(e,t){var r=J(e,t);return r&&r.prerelease.length?r.prerelease:null},t.intersects=function(e,t,r){return e=new ie(e,r),t=new ie(t,r),e.intersects(t)},t.coerce=function(e){if(e instanceof F)return e;if("string"!=typeof e)return null;var t=e.match(o[I]);if(null==t)return null;return J(t[1]+"."+(t[2]||"0")+"."+(t[3]||"0"))}})),Ze=(We.SEMVER_SPEC_VERSION,We.re,We.src,We.parse,We.valid,We.clean,We.SemVer,We.inc,We.diff,We.compareIdentifiers,We.rcompareIdentifiers,We.major,We.minor,We.patch,We.compare,We.compareLoose,We.rcompare,We.sort,We.rsort,We.gt,We.lt,We.eq,We.neq,We.gte,We.lte,We.cmp,We.Comparator,We.Range,We.toComparators,We.satisfies,We.maxSatisfying,We.minSatisfying,We.minVersion,We.validRange,We.ltr,We.gtr,We.outside,We.prerelease,We.intersects,We.coerce,We.satisfies(process.version,"^6.12.0 || >=8.0.0")),Ye=["RS256","RS384","RS512","ES256","ES384","ES512"],Xe=["RS256","RS384","RS512"],Qe=["HS256","HS384","HS512"];Ze&&(Ye.splice(3,0,"PS256","PS384","PS512"),Xe.splice(3,0,"PS256","PS384","PS512"));var et=/^\s+|\s+$/g,tt=/^[-+]0x[0-9a-f]+$/i,rt=/^0b[01]+$/i,nt=/^0o[0-7]+$/i,ot=/^(?:0|[1-9]\d*)$/,it=parseInt;function at(e){return e!=e}function st(e,t){return function(e,t){for(var r=-1,n=e?e.length:0,o=Array(n);++r<n;)o[r]=t(e[r],r,e);return o}(t,(function(t){return e[t]}))}var ct,ut,ft=Object.prototype,pt=ft.hasOwnProperty,dt=ft.toString,lt=ft.propertyIsEnumerable,ht=(ct=Object.keys,ut=Object,function(e){return ct(ut(e))}),mt=Math.max;function gt(e,t){var r=vt(e)||function(e){return function(e){return St(e)&&bt(e)}(e)&&pt.call(e,"callee")&&(!lt.call(e,"callee")||"[object Arguments]"==dt.call(e))}(e)?function(e,t){for(var r=-1,n=Array(e);++r<e;)n[r]=t(r);return n}(e.length,String):[],n=r.length,o=!!n;for(var i in e)!t&&!pt.call(e,i)||o&&("length"==i||wt(i,n))||r.push(i);return r}function yt(e){if(r=(t=e)&&t.constructor,n="function"==typeof r&&r.prototype||ft,t!==n)return ht(e);var t,r,n,o=[];for(var i in Object(e))pt.call(e,i)&&"constructor"!=i&&o.push(i);return o}function wt(e,t){return!!(t=null==t?9007199254740991:t)&&("number"==typeof e||ot.test(e))&&e>-1&&e%1==0&&e<t}var vt=Array.isArray;function bt(e){return null!=e&&function(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}(e.length)&&!function(e){var t=_t(e)?dt.call(e):"";return"[object Function]"==t||"[object GeneratorFunction]"==t}(e)}function _t(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function St(e){return!!e&&"object"==typeof e}var Et=function(e,t,r,n){var o;e=bt(e)?e:(o=e)?st(o,function(e){return bt(e)?gt(e):yt(e)}(o)):[],r=r&&!n?function(e){var t=function(e){if(!e)return 0===e?e:0;if((e=function(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||St(e)&&"[object Symbol]"==dt.call(e)}(e))return NaN;if(_t(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=_t(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(et,"");var r=rt.test(e);return r||nt.test(e)?it(e.slice(2),r?2:8):tt.test(e)?NaN:+e}(e))===1/0||e===-1/0){return 17976931348623157e292*(e<0?-1:1)}return e==e?e:0}(e),r=t%1;return t==t?r?t-r:t:0}(r):0;var i=e.length;return r<0&&(r=mt(i+r,0)),function(e){return"string"==typeof e||!vt(e)&&St(e)&&"[object String]"==dt.call(e)}(e)?r<=i&&e.indexOf(t,r)>-1:!!i&&function(e,t,r){if(t!=t)return function(e,t,r,n){for(var o=e.length,i=r+(n?1:-1);n?i--:++i<o;)if(t(e[i],i,e))return i;return-1}(e,at,r);for(var n=r-1,o=e.length;++n<o;)if(e[n]===t)return n;return-1}(e,t,r)>-1},kt=Object.prototype.toString;var xt=function(e){return!0===e||!1===e||function(e){return!!e&&"object"==typeof e}(e)&&"[object Boolean]"==kt.call(e)},jt=/^\s+|\s+$/g,Tt=/^[-+]0x[0-9a-f]+$/i,Ot=/^0b[01]+$/i,It=/^0o[0-7]+$/i,Rt=parseInt,At=Object.prototype.toString;function Pt(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}var Ct=function(e){return"number"==typeof e&&e==function(e){var t=function(e){if(!e)return 0===e?e:0;if((e=function(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&"[object Symbol]"==At.call(e)}(e))return NaN;if(Pt(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Pt(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(jt,"");var r=Ot.test(e);return r||It.test(e)?Rt(e.slice(2),r?2:8):Tt.test(e)?NaN:+e}(e))===1/0||e===-1/0){return 17976931348623157e292*(e<0?-1:1)}return e==e?e:0}(e),r=t%1;return t==t?r?t-r:t:0}(e)},$t=Object.prototype.toString;var Nt=function(e){return"number"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&"[object Number]"==$t.call(e)};var Bt=Function.prototype,Dt=Object.prototype,Mt=Bt.toString,Vt=Dt.hasOwnProperty,Kt=Mt.call(Object),Lt=Dt.toString,qt=function(e,t){return function(r){return e(t(r))}}(Object.getPrototypeOf,Object);var Ht=function(e){if(!function(e){return!!e&&"object"==typeof e}(e)||"[object Object]"!=Lt.call(e)||function(e){var t=!1;if(null!=e&&"function"!=typeof e.toString)try{t=!!(e+"")}catch(e){}return t}(e))return!1;var t=qt(e);if(null===t)return!0;var r=Vt.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&&Mt.call(r)==Kt},Ut=Object.prototype.toString,Jt=Array.isArray;var Ft=function(e){return"string"==typeof e||!Jt(e)&&function(e){return!!e&&"object"==typeof e}(e)&&"[object String]"==Ut.call(e)},Gt=/^\s+|\s+$/g,zt=/^[-+]0x[0-9a-f]+$/i,Wt=/^0b[01]+$/i,Zt=/^0o[0-7]+$/i,Yt=parseInt,Xt=Object.prototype.toString;function Qt(e,t){var r;if("function"!=typeof t)throw new TypeError("Expected a function");return e=function(e){var t=function(e){if(!e)return 0===e?e:0;if((e=function(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&"[object Symbol]"==Xt.call(e)}(e))return NaN;if(er(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=er(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(Gt,"");var r=Wt.test(e);return r||Zt.test(e)?Yt(e.slice(2),r?2:8):zt.test(e)?NaN:+e}(e))===1/0||e===-1/0){return 17976931348623157e292*(e<0?-1:1)}return e==e?e:0}(e),r=t%1;return t==t?r?t-r:t:0}(e),function(){return--e>0&&(r=t.apply(this,arguments)),e<=1&&(t=void 0),r}}function er(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}var tr=function(e){return Qt(2,e)},rr=["RS256","RS384","RS512","ES256","ES384","ES512","HS256","HS384","HS512","none"];Ze&&rr.splice(3,0,"PS256","PS384","PS512");var nr={expiresIn:{isValid:function(e){return Ct(e)||Ft(e)&&e},message:'"expiresIn" should be a number of seconds or string representing a timespan'},notBefore:{isValid:function(e){return Ct(e)||Ft(e)&&e},message:'"notBefore" should be a number of seconds or string representing a timespan'},audience:{isValid:function(e){return Ft(e)||Array.isArray(e)},message:'"audience" must be a string or array'},algorithm:{isValid:Et.bind(null,rr),message:'"algorithm" must be a valid string enum value'},header:{isValid:Ht,message:'"header" must be an object'},encoding:{isValid:Ft,message:'"encoding" must be a string'},issuer:{isValid:Ft,message:'"issuer" must be a string'},subject:{isValid:Ft,message:'"subject" must be a string'},jwtid:{isValid:Ft,message:'"jwtid" must be a string'},noTimestamp:{isValid:xt,message:'"noTimestamp" must be a boolean'},keyid:{isValid:Ft,message:'"keyid" must be a string'},mutatePayload:{isValid:xt,message:'"mutatePayload" must be a boolean'}},or={iat:{isValid:Nt,message:'"iat" should be a number of seconds'},exp:{isValid:Nt,message:'"exp" should be a number of seconds'},nbf:{isValid:Nt,message:'"nbf" should be a number of seconds'}};function ir(e,t,r,n){if(!Ht(r))throw new Error('Expected "'+n+'" to be a plain object.');Object.keys(r).forEach((function(o){var i=e[o];if(i){if(!i.isValid(r[o]))throw new Error(i.message)}else if(!t)throw new Error('"'+o+'" is not allowed in "'+n+'"')}))}var ar={audience:"aud",issuer:"iss",subject:"sub",jwtid:"jti"},sr=["expiresIn","notBefore","noTimestamp","audience","issuer","subject","jwtid"],cr=function(e,t,r,n){var o;if("function"!=typeof r||n||(n=r,r={}),r||(r={}),r=Object.assign({},r),o=n||function(e,t){if(e)throw e;return t},r.clockTimestamp&&"number"!=typeof r.clockTimestamp)return o(new De("clockTimestamp must be a number"));if(void 0!==r.nonce&&("string"!=typeof r.nonce||""===r.nonce.trim()))return o(new De("nonce must be a non-empty string"));var i=r.clockTimestamp||Math.floor(Date.now()/1e3);if(!e)return o(new De("jwt must be provided"));if("string"!=typeof e)return o(new De("jwt must be a string"));var a,s=e.split(".");if(3!==s.length)return o(new De("jwt malformed"));try{a=Ne(e,{complete:!0})}catch(e){return o(e)}if(!a)return o(new De("invalid token"));var c,u=a.header;if("function"==typeof t){if(!n)return o(new De("verify must be called asynchronous if secret or public key is provided as a callback"));c=t}else c=function(e,r){return r(null,t)};return c(u,(function(t,n){if(t)return o(new De("error in secret or public key callback: "+t.message));var c,f=""!==s[2].trim();if(!f&&n)return o(new De("jwt signature is required"));if(f&&!n)return o(new De("secret or public key must be provided"));if(f||r.algorithms||(r.algorithms=["none"]),r.algorithms||(r.algorithms=~n.toString().indexOf("BEGIN CERTIFICATE")||~n.toString().indexOf("BEGIN PUBLIC KEY")?Ye:~n.toString().indexOf("BEGIN RSA PUBLIC KEY")?Xe:Qe),!~r.algorithms.indexOf(a.header.alg))return o(new De("invalid algorithm"));try{c=$e.verify(e,a.header.alg,n)}catch(e){return o(e)}if(!c)return o(new De("invalid signature"));var p=a.payload;if(void 0!==p.nbf&&!r.ignoreNotBefore){if("number"!=typeof p.nbf)return o(new De("invalid nbf value"));if(p.nbf>i+(r.clockTolerance||0))return o(new Ve("jwt not active",new Date(1e3*p.nbf)))}if(void 0!==p.exp&&!r.ignoreExpiration){if("number"!=typeof p.exp)return o(new De("invalid exp value"));if(i>=p.exp+(r.clockTolerance||0))return o(new Le("jwt expired",new Date(1e3*p.exp)))}if(r.audience){var d=Array.isArray(r.audience)?r.audience:[r.audience];if(!(Array.isArray(p.aud)?p.aud:[p.aud]).some((function(e){return d.some((function(t){return t instanceof RegExp?t.test(e):t===e}))})))return o(new De("jwt audience invalid. expected: "+d.join(" or ")))}if(r.issuer&&("string"==typeof r.issuer&&p.iss!==r.issuer||Array.isArray(r.issuer)&&-1===r.issuer.indexOf(p.iss)))return o(new De("jwt issuer invalid. expected: "+r.issuer));if(r.subject&&p.sub!==r.subject)return o(new De("jwt subject invalid. expected: "+r.subject));if(r.jwtid&&p.jti!==r.jwtid)return o(new De("jwt jwtid invalid. expected: "+r.jwtid));if(r.nonce&&p.nonce!==r.nonce)return o(new De("jwt nonce invalid. expected: "+r.nonce));if(r.maxAge){if("number"!=typeof p.iat)return o(new De("iat required when maxAge is specified"));var l=ze(r.maxAge,p.iat);if(void 0===l)return o(new De('"maxAge" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'));if(i>=l+(r.clockTolerance||0))return o(new Le("maxAge exceeded",new Date(1e3*l)))}if(!0===r.complete){var h=a.signature;return o(null,{header:u,payload:p,signature:h})}return o(null,p)}))},ur=function(e,t,r,n){"function"==typeof r?(n=r,r={}):r=r||{};var o="object"==typeof e&&!Buffer.isBuffer(e),i=Object.assign({alg:r.algorithm||"HS256",typ:o?"JWT":void 0,kid:r.keyid},r.header);function a(e){if(n)return n(e);throw e}if(!t&&"none"!==r.algorithm)return a(new Error("secretOrPrivateKey must have a value"));if(void 0===e)return a(new Error("payload is required"));if(o){try{!function(e){ir(or,!0,e,"payload")}(e)}catch(e){return a(e)}r.mutatePayload||(e=Object.assign({},e))}else{var s=sr.filter((function(e){return void 0!==r[e]}));if(s.length>0)return a(new Error("invalid "+s.join(",")+" option for "+typeof e+" payload"))}if(void 0!==e.exp&&void 0!==r.expiresIn)return a(new Error('Bad "options.expiresIn" option the payload already has an "exp" property.'));if(void 0!==e.nbf&&void 0!==r.notBefore)return a(new Error('Bad "options.notBefore" option the payload already has an "nbf" property.'));try{!function(e){ir(nr,!1,e,"options")}(r)}catch(e){return a(e)}var c=e.iat||Math.floor(Date.now()/1e3);if(r.noTimestamp?delete e.iat:o&&(e.iat=c),void 0!==r.notBefore){try{e.nbf=ze(r.notBefore,c)}catch(e){return a(e)}if(void 0===e.nbf)return a(new Error('"notBefore" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'))}if(void 0!==r.expiresIn&&"object"==typeof e){try{e.exp=ze(r.expiresIn,c)}catch(e){return a(e)}if(void 0===e.exp)return a(new Error('"expiresIn" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'))}Object.keys(ar).forEach((function(t){var n=ar[t];if(void 0!==r[t]){if(void 0!==e[n])return a(new Error('Bad "options.'+t+'" option. The payload already has an "'+n+'" property.'));e[n]=r[t]}}));var u=r.encoding||"utf8";if("function"!=typeof n)return $e.sign({header:i,payload:e,secret:t,encoding:u});n=n&&tr(n),$e.createSign({header:i,privateKey:t,payload:e,encoding:u}).once("error",n).once("done",(function(e){n(null,e)}))};function fr(){const e=t.createHash("md5"),r=/MicroMessenger/i.test(__ctx__.CLIENTUA)?__ctx__.CLIENTUA.split(" Process/appbrand")[0]:__ctx__.CLIENTUA;return e.update(r),e.digest("hex")}const pr={createToken:function(e){const t=I(),r={uid:e._id};t.bindTokenToDevice&&(r.clientId=fr());return{token:ur(r,t.tokenSecret,{expiresIn:t.tokenExpiresIn}),tokenExpired:Date.now()+1e3*t.tokenExpiresIn}},refreshToken:function(){},checkToken:async function(e){const t=I();try{const r=cr(e,t.tokenSecret);if(t.bindTokenToDevice&&r.clientId!==fr())return{code:30201,msg:"token不合法,请重新登录"};const n=await j.doc(r.uid).get();if(!n.data||0===n.data.length||!n.data[0].token)return{code:30202,msg:"token不合法,请重新登录"};const o=n.data[0];if(1===o.status)return{code:10001,msg:"账号已禁用"};let i=o.token;return"string"==typeof i&&(i=[i]),-1===i.indexOf(e)?{code:30202,msg:"token不合法,请重新登录"}:(S("checkToken payload",r),{code:0,msg:"token校验通过",...r,userInfo:o})}catch(e){return"TokenExpiredError"===e.name?{code:30203,msg:"token已过期,请重新登录",err:e}:{code:30204,msg:"非法token",err:e}}},getExpiredToken(e){const t=I(),r=[];return e.forEach(e=>{try{cr(e,t.tokenSecret)}catch(t){r.push(e)}}),r}},dr=uniCloud.database();async function lr(e){if(1===e.status)return{code:10001,msg:"账号已禁用"};S("过期token清理");let t=e.token||[];"string"==typeof t&&(t=[t]);const r=pr.getExpiredToken(t);return t=t.filter(e=>-1===r.indexOf(e)),e.token=t,{code:0,user:e}}const hr=uniCloud.database();async function mr({name:e,url:t,data:r,options:n,defaultOptions:o}){let i={};const a=b(Object.assign({},r));a&&a.access_token&&delete a.access_token;try{n=Object.assign({},o,n,{data:a}),i=await uniCloud.httpclient.request(t,n)}catch(t){return function(e,t){throw new c({code:t.code||-2,message:t.message||e+" fail"})}(e,t)}let s=i.data;const u=i.headers["content-type"];if(!Buffer.isBuffer(s)||0!==u.indexOf("text/plain")&&0!==u.indexOf("application/json"))Buffer.isBuffer(s)&&(s={buffer:s,contentType:u});else try{s=JSON.parse(s.toString())}catch(e){s=s.toString()}return v(function(e,t){if(t.errcode)throw new c({code:t.errcode||-2,message:t.errmsg||e+" fail"});return delete t.errcode,delete t.errmsg,{...t,errMsg:e+" ok",errCode:0}}(e,s||{errCode:-2,errMsg:"Request failed"}))}function gr(e,t){let r="";if(t&&t.accessToken){r=`${e.indexOf("?")>-1?"&":"?"}access_token=${t.accessToken}`}return`${e}${r}`}class yr{constructor(e){this.options=Object.assign({baseUrl:"https://api.weixin.qq.com",timeout:5e3},e)}async _requestWxOpenapi({name:e,url:t,data:r,options:n}){const o={method:"GET",dataType:"json",dataAsQueryString:!0,timeout:this.options.timeout};return await mr({name:"auth."+e,url:`${this.options.baseUrl}${gr(t,r)}`,data:r,options:n,defaultOptions:o})}async code2Session(e){return await this._requestWxOpenapi({name:"code2Session",url:"/sns/jscode2session",data:{grant_type:"authorization_code",appid:this.options.appId,secret:this.options.secret,js_code:e}})}async getOauthAccessToken(e){return await this._requestWxOpenapi({name:"getOauthAccessToken",url:"/sns/oauth2/access_token",data:{grant_type:"authorization_code",appid:this.options.appId,secret:this.options.secret,code:e}})}}const wr={RSA:"RSA-SHA1",RSA2:"RSA-SHA256"};var vr={code2Session:{returnValue:{openid:"userId"}}};class br extends class{constructor(e={}){if(!e.appId)throw new Error("appId required");if(!e.privateKey)throw new Error("privateKey required");const t={gateway:"https://openapi.alipay.com/gateway.do",timeout:5e3,charset:"utf-8",version:"1.0",signType:"RSA2",timeOffset:-(new Date).getTimezoneOffset()/60,keyType:"PKCS8"};e.sandbox&&(e.gateway="https://openapi.alipaydev.com/gateway.do"),this.options=Object.assign({},t,e);const r="PKCS8"===this.options.keyType?"PRIVATE KEY":"RSA PRIVATE KEY";this.options.privateKey=this._formatKey(this.options.privateKey,r),this.options.alipayPublicKey&&(this.options.alipayPublicKey=this._formatKey(this.options.alipayPublicKey,"PUBLIC KEY"))}_formatKey(e,t){return`-----BEGIN ${t}-----\n${e}\n-----END ${t}-----`}_formatUrl(e,t){let r=e;const n=["app_id","method","format","charset","sign_type","sign","timestamp","version","notify_url","return_url","auth_token","app_auth_token"];for(const e in t)if(n.indexOf(e)>-1){const n=encodeURIComponent(t[e]);r=`${r}${r.includes("?")?"&":"?"}${e}=${n}`,delete t[e]}return{execParams:t,url:r}}_getSign(e,r){const n=r.bizContent||null;delete r.bizContent;const o=Object.assign({method:e,appId:this.options.appId,charset:this.options.charset,version:this.options.version,signType:this.options.signType,timestamp:_((i=this.options.timeOffset,new Date(Date.now()+6e4*((new Date).getTimezoneOffset()+60*(i||0)))))},r);var i;n&&(o.bizContent=JSON.stringify(b(n)));const a=b(o),s=Object.keys(a).sort().map(e=>{let t=a[e];return"[object String]"!==Array.prototype.toString.call(t)&&(t=JSON.stringify(t)),`${e}=${t}`}).join("&"),c=t.createSign(wr[this.options.signType]).update(s,"utf8").sign(this.options.privateKey,"base64");return Object.assign(a,{sign:c})}async _exec(e,t={},r={}){const n=this._getSign(e,t),{url:o,execParams:i}=this._formatUrl(this.options.gateway,n),{status:a,data:s}=await uniCloud.httpclient.request(o,{method:"POST",data:i,dataType:"text",timeout:this.options.timeout});if(200!==a)throw new Error("request fail");const c=JSON.parse(s),u=e.replace(/\./g,"_")+"_response",f=c[u],p=c.error_response;if(f){if(!r.validateSign||this._checkResponseSign(s,u)){if(!f.code||"10000"===f.code){return{errCode:0,errMsg:f.msg||"",...v(f)}}const e=f.sub_code?`${f.sub_code} ${f.sub_msg}`:""+(f.msg||"unkonwn error");throw new Error(e)}throw new Error("返回结果签名错误")}if(p)throw new Error(p.sub_msg||p.msg||"接口返回错误");throw new Error("request fail")}_checkResponseSign(e,r){if(!this.options.alipayPublicKey||""===this.options.alipayPublicKey)return console.warn("options.alipayPublicKey is empty"),!0;if(!e)return!1;const n=this._getSignStr(e,r),o=JSON.parse(e).sign,i=t.createVerify(wr[this.options.signType]);return i.update(n,"utf8"),i.verify(this.options.alipayPublicKey,o,"base64")}_getSignStr(e,t){let r=e.trim();const n=e.indexOf(t+'"'),o=e.lastIndexOf('"sign"');return r=r.substr(n+t.length+1),r=r.substr(0,o),r=r.replace(/^[^{]*{/g,"{"),r=r.replace(/\}([^}]*)$/g,"}"),r}_notifyRSACheck(e,r,n){const o=Object.keys(e).sort().filter(e=>e).map(t=>{let r=e[t];return"[object String]"!==Array.prototype.toString.call(r)&&(r=JSON.stringify(r)),`${t}=${decodeURIComponent(r)}`}).join("&");return t.createVerify(wr[n]).update(o,"utf8").verify(this.options.alipayPublicKey,r,"base64")}_checkNotifySign(e){const t=e.sign;if(!this.options.alipayPublicKey||!t)return!1;const r=e.sign_type||this.options.signType||"RSA2",n={...e};delete n.sign,n.sign_type=r;return!!this._notifyRSACheck(n,t,r)||(delete n.sign_type,this._notifyRSACheck(n,t,r))}_verifyNotify(e){if(!e.headers)throw new Error("通知格式不正确");let t;for(const r in e.headers)"content-type"===r.toLowerCase()&&(t=e.headers[r]);if(!1!==e.isBase64Encoded&&-1===t.indexOf("application/x-www-form-urlencoded"))throw new Error("通知格式不正确");const r=s.parse(e.body);if(this._checkNotifySign(r))return v(r);throw new Error("通知验签未通过")}}{constructor(e){super(e),this._protocols=vr}async code2Session(e){return await this._exec("alipay.system.oauth.token",{grantType:"authorization_code",code:e})}}var _r=function(e={}){return e.clientType=e.clientType||__ctx__.PLATFORM,e.appId=e.appid,e.secret=e.appsecret,k(yr,e)},Sr=function(e={}){return e.clientType=e.clientType||__ctx__.PLATFORM,e.appId=e.appid,k(br,e)};function Er(){const e=I(),t=__ctx__.PLATFORM;if(!e.oauth||!e.oauth.weixin)throw new Error(`请在公用模块uni-id的config.json或init方法中添加${t}平台微信登录配置项`);["appid","appsecret"].forEach(r=>{if(!e.oauth.weixin[r])throw new Error(`请在公用模块uni-id的config.json或init方法中添加配置项:${t}.oauth.weixin.${r}`)});return _r(e.oauth.weixin)}const kr=uniCloud.database();const xr=uniCloud.database();const jr=uniCloud.database();function Tr(){const e=I(),t=__ctx__.PLATFORM;if(!e.oauth||!e.oauth.alipay)throw new Error(`请在公用模块uni-id的config.json或init方法中添加${t}平台支付宝登录配置项`);["appid","privateKey"].forEach(r=>{if(!e.oauth.alipay[r])throw new Error(`请在公用模块uni-id的config.json或init方法中添加配置项:${t}.oauth.alipay.${r}`)});return Sr(e.oauth.alipay)}const Or=uniCloud.database();const Ir=uniCloud.database();const Rr=uniCloud.database();async function Ar({mobile:e,email:t,code:r,expiresIn:n,type:o}){if(!e&&!t||e&&t)return{code:50101,msg:"手机号和邮箱必须且只能给定其中一个"};n||(n=180);const i=Date.now(),a={mobile:e,email:t,type:o,code:r,state:0,ip:__ctx__.CLIENTIP,created_at:i,expired_at:i+1e3*n};try{return S("addRes",await T.add(a)),{code:0,mobile:e,email:t}}catch(e){return{code:90001,msg:"记录验证信息失败"}}}async function Pr({mobile:e,email:t,code:r,type:n}){if(!e&&!t||e&&t)return{code:50201,msg:"手机号和邮箱必须且只能给定其中一个"};const o=Rr.command,i=Date.now(),a={mobile:e,email:t,type:n,code:r,state:0,expired_at:o.gt(i)};try{const e=await T.where(a).orderBy("created_at","desc").limit(1).get();if(S("verifyRecord:",e),e&&e.data&&e.data.length>0){const t=e.data[0];return S("upRes",await T.doc(t._id).update({state:1})),{code:0,msg:"验证通过"}}return{code:50202,msg:"验证码错误或已失效"}}catch(e){return{code:90001,msg:"验证码校验失败"}}}const Cr=uniCloud.database();const $r=uniCloud.database();var Nr={init:function(e){O=e},register:async function(e){const t=[],r=[{name:"username",desc:"用户名"},{name:"email",desc:"邮箱",extraCond:{email_confirmed:1}},{name:"mobile",desc:"手机号",extraCond:{mobile_confirmed:1}}];if(r.forEach(r=>{const n=r.name;e[n]&&e[n].trim()&&t.push({[n]:e[n],...r.extraCond})}),0===t.length)return{code:20101,msg:"用户名、邮箱、手机号不可同时为空"};const{username:n,email:o,mobile:i}=e,a=dr.command;try{const s=await j.where(a.or(...t)).get();if(S("userInDB:",s),s&&s.data.length>0){const t=s.data[0];for(let n=0;n<r.length;n++){const o=r[n];let i=!0;if(o.extraCond&&(i=Object.keys(o.extraCond).every(e=>t[e]===o.extraCond[e])),t[o.name]===e[o.name]&&i)return{code:20102,msg:o.desc+"已存在"}}}e.password=A(e.password),e.register_date=(new Date).getTime(),e.register_ip=__ctx__.CLIENTIP;const c=await j.add(e);S("addRes",c);const u=c.id,{token:f,tokenExpired:p}=pr.createToken({_id:u});return await j.doc(u).update({token:[f]}),{code:0,uid:u,username:n,email:o,mobile:i,msg:"注册成功",token:f,tokenExpired:p}}catch(e){return{code:90001,msg:"数据库写入异常"}}},login:async function({username:e,password:t,queryField:r=[]}){const n=hr.command,o=[];r&&r.length||(r=["username"]);const i={email:{email_confirmed:1},mobile:{mobile_confirmed:1}};r.forEach(t=>{o.push({[t]:e,...i[t]})});const a=await j.where(n.or(...o)).limit(1).get(),s=__ctx__.CLIENTIP,{passwordErrorLimit:c,passwordErrorRetryTime:u}=I();if(S("userInDB:",a),!(a&&a.data&&a.data.length>0))return{code:10101,msg:"用户不存在"};{const r=a.data[0],n=r.password;let o=r.login_ip_limit||[];o=o.filter(e=>e.last_error_time>Date.now()-1e3*u);let i=o.find(e=>e.ip===s);if(i&&i.error_times>=c)return{code:10103,msg:`密码错误次数过多,请${R(i.last_error_time+1e3*u)}再试。`};if(A(t)!==n)return i?(i.error_times++,i.last_error_time=Date.now()):(i={ip:s,error_times:1,last_error_time:Date.now()},o.push(i)),await j.doc(r._id).update({login_ip_limit:o}),{code:10102,msg:"密码错误"};try{const t=await lr(r);if(0!==t.code)return t;const n=t.user.token;S("开始修改最后登录时间");const{token:i,tokenExpired:a}=pr.createToken(r);S("token",i),n.push(i);return S("upRes",await j.doc(r._id).update({last_login_date:(new Date).getTime(),last_login_ip:s,token:n,login_ip_limit:o})),{code:0,token:i,uid:r._id,username:e,msg:"登录成功",tokenExpired:a}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}}},loginByWeixin:async function(e){const t=__ctx__.PLATFORM,{openid:r,unionid:n}=await Er()["mp-weixin"===t?"code2Session":"getOauthAccessToken"](e);if(!r)return{code:10401,msg:"获取openid失败"};const o=kr.command,i=[{wx_openid:{[t]:r}}];n&&i.push({wx_unionid:n});const a=await j.where(o.or(...i)).get();if(a&&a.data&&a.data.length>0){const e=a.data[0];try{const o=await lr(e);if(0!==o.code)return o;const i=o.user.token;S("开始修改最后登录时间,写入unionid(可能不存在)和openid");const{token:a,tokenExpired:s}=pr.createToken(e);S("token",a),i.push(a);const c={last_login_date:(new Date).getTime(),last_login_ip:__ctx__.CLIENTIP,token:i,wx_openid:{[t]:r}};n&&(c.wx_unionid=n);return S("upRes",await j.doc(e._id).update(c)),{code:0,token:a,uid:e._id,username:e.username,msg:"登录成功",tokenExpired:s}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}}else try{const e=await j.add({register_date:(new Date).getTime(),register_ip:__ctx__.CLIENTIP,wx_openid:{[t]:r},wx_unionid:n}),o=e.id,{token:i,tokenExpired:a}=pr.createToken({_id:o});return await j.doc(o).update({token:[i]}),{code:0,token:i,uid:e.id,msg:"登录成功",tokenExpired:a}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}},bindWeixin:async function({uid:e,code:t}){const r=__ctx__.PLATFORM,{openid:n,unionid:o}=await Er()["mp-weixin"===r?"code2Session":"getOauthAccessToken"](t);if(!n)return{code:60301,msg:"获取openid失败"};const i=xr.command,a=[{wx_openid:{[r]:n}}];o&&a.push({wx_unionid:o});const s=await j.where(i.or(...a)).get();if(s&&s.data&&s.data.length>0)return{code:60302,msg:"微信绑定失败,此微信账号已被绑定"};try{const t={wx_openid:{[r]:n}};return o&&(t.wx_unionid=o),await j.doc(e).update(t),{code:0,msg:"绑定成功"}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}},unbindWeixin:async function(e){try{const t=jr.command,r=await j.doc(e).update({wx_openid:t.remove(),wx_unionid:t.remove()});return S("upRes:",r),1===r.updated?{code:0,msg:"微信解绑成功"}:{code:70301,msg:"微信解绑失败,请稍后再试"}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}},loginByAlipay:async function(e){const{openid:t}=await Tr().code2Session(e);if(!t)return{code:10501,msg:"获取openid失败"};const r=await j.where({ali_openid:t}).get();if(r&&r.data&&r.data.length>0){const e=r.data[0];try{const t=await lr(e);if(0!==t.code)return t;const r=t.user.token;S("开始修改最后登录时间,写入openid");const{token:n,tokenExpired:o}=pr.createToken(e);S("token",n),r.push(n);return S("upRes",await j.doc(e._id).update({last_login_date:(new Date).getTime(),last_login_ip:__ctx__.CLIENTIP,token:r})),{code:0,token:n,uid:e._id,username:e.username,msg:"登录成功",tokenExpired:o}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}}else try{const e=await j.add({register_date:(new Date).getTime(),register_ip:__ctx__.CLIENTIP,ali_openid:t}),r=e.id,{token:n,tokenExpired:o}=pr.createToken({_id:r});return await j.doc(r).update({token:[n]}),{code:0,token:n,uid:e.id,msg:"登录成功",tokenExpired:o}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}},bindAlipay:async function({uid:e,code:t}){const{openid:r}=await Tr().code2Session(t);if(!r)return{code:60401,msg:"获取openid失败"};const n=await j.where({ali_openid:r}).get();if(n&&n.data&&n.data.length>0)return{code:60402,msg:"支付宝绑定失败,此账号已被绑定"};try{return await j.doc(e).update({ali_openid:r}),{code:0,msg:"绑定成功"}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}},unbindAlipay:async function(e){try{const t=Or.command,r=await j.doc(e).update({ali_openid:t.remove()});return S("upRes:",r),1===r.updated?{code:0,msg:"支付宝解绑成功"}:{code:70401,msg:"支付宝解绑失败,请稍后再试"}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}},logout:async function(e){const t=await pr.checkToken(e);if(t.code&&t.code>0)return t;try{const r=Ir.command;return await j.doc(t.uid).update({token:r.pull(e)}),{code:0,msg:"退出成功"}}catch(e){return{code:90001,msg:"数据库写入异常"}}},updatePwd:async function(e){const t=await j.doc(e.uid).get();if(!(t&&t.data&&t.data.length>0))return{code:40201,msg:"用户不存在"};{const r=t.data[0].password;if(A(e.oldPassword)!==r)return{code:40202,msg:"旧密码错误"};try{return S("upRes",await j.doc(t.data[0]._id).update({password:A(e.newPassword),token:[]})),{code:0,msg:"修改成功"}}catch(e){return S("发生异常",e),{code:90001,msg:"数据库写入异常"}}}},updateUser:async function(e){const t=e.uid;if(!t)return{code:80101,msg:"缺少uid参数"};delete e.uid;try{return S("update -> upRes",await j.doc(t).update(e)),{code:0,msg:"修改成功"}}catch(e){return S("发生异常",e),{code:90001,msg:"数据库写入异常"}}},setAvatar:async function(e){try{return S("setAvatar -> upRes",await j.doc(e.uid).update({avatar:e.avatar})),{code:0,msg:"头像设置成功"}}catch(e){return S("发生异常",e),{code:90001,msg:"数据库写入异常"}}},bindMobile:async function({uid:e,mobile:t,code:r}){try{const n=await j.where({mobile:t,mobile_confirmed:1}).count();if(n&&n.total>0)return{code:60101,msg:"此手机号已被绑定"};if(r){const e=await Pr({mobile:t,code:r,type:"bind"});if(0!==e.code)return e}return S("bindMobile -> upRes",await j.doc(e).update({mobile:t,mobile_confirmed:1})),{code:0,msg:"手机号码绑定成功"}}catch(e){return S("发生异常",e),{code:90001,msg:"数据库写入异常"}}},bindEmail:async function({uid:e,email:t,code:r}){try{const n=await j.where({email:t,email_confirmed:1}).count();if(n&&n.total>0)return{code:60201,msg:"此邮箱已被绑定"};if(r){const e=await Pr({email:t,code:r,type:"bind"});if(0!==e.code)return e}return S("bindEmail -> upRes",await j.doc(e).update({email:t,email_confirmed:1})),{code:0,msg:"邮箱绑定成功"}}catch(e){return S("发生异常",e),{code:90001,msg:"数据库写入异常"}}},checkToken:pr.checkToken,encryptPwd:A,resetPwd:async function({uid:e,password:t}){try{return S("upRes",await j.doc(e).update({password:A(t),token:[]})),{code:0,msg:"密码重置成功"}}catch(e){return S("发生异常",e),{code:90001,msg:"数据库写入异常"}}},unbindMobile:async function({uid:e,mobile:t,code:r}){try{if(r){const e=await Pr({mobile:t,code:r,type:"unbind"});if(0!==e.code)return e}const n=Cr.command;return 1===(await j.where({_id:e,mobile:t}).update({mobile:n.remove(),mobile_confirmed:n.remove()})).updated?{code:0,msg:"手机号解绑成功"}:{code:70101,msg:"手机号解绑失败,请稍后再试"}}catch(e){return S("发生异常",e),{code:90001,msg:"数据库写入异常"}}},setVerifyCode:Ar,verifyCode:Pr,sendSmsCode:async function({mobile:e,code:t,type:r}){if(!e)throw new Error("手机号码不可为空");if(!t)throw new Error("验证码不可为空");if(!r)throw new Error("验证码类型不可为空");const n=I();let o=n&&n.service&&n.service.sms;if(!o)throw new Error("请在config.json或init方法中配置service.sms下短信相关参数");o=Object.assign({codeExpiresIn:180},o);const i=["name","smsKey","smsSecret"];for(let e=0,t=i.length;e<t;e++){const t=i[e];if(!o[t])throw new Error("请在config.json或init方法中service.sms下配置"+t)}const{name:a,smsKey:s,smsSecret:c,codeExpiresIn:u}=o;let f;switch(r){case"login":f="登录";break;default:f="验证手机号"}try{await uniCloud.sendSms({smsKey:s,smsSecret:c,phone:e,templateId:"uniID_code",data:{name:a,code:t,action:f,expMinute:""+Math.round(u/60)}});const n=await Ar({mobile:e,code:t,expiresIn:u,type:r});return n.code>=0?n:{code:0,msg:"验证码发送成功"}}catch(e){return{code:50301,msg:"验证码发送失败, "+e.message}}},loginBySms:async function({mobile:e,code:t}){const r=await Pr({mobile:e,code:t,type:"login"});if(0!==r.code)return r;const n={mobile:e,mobile_confirmed:1},o=await j.where(n).get();if(S("userInDB:",o),!(o&&o.data&&o.data.length>0)){const t={mobile:e,mobile_confirmed:1,register_ip:__ctx__.CLIENTIP,register_date:Date.now()},r=await j.add(t);S("addRes",r);const n=r.id;if(r.id){const{token:t,tokenExpired:r}=pr.createToken({_id:n});return await j.doc(n).update({token:[t]}),{code:0,uid:n,mobile:e,msg:"注册成功",token:t,tokenExpired:r}}return{code:90001,msg:"数据库写入失败"}}{const t=o.data[0];try{const r=await lr(t);if(0!==r.code)return r;const n=r.user.token;S("开始修改最后登录时间");const{token:o,tokenExpired:i}=pr.createToken(t);S("token",o),n.push(o);return S("upRes",await j.doc(t._id).update({last_login_date:(new Date).getTime(),last_login_ip:__ctx__.CLIENTIP,token:n})),{code:0,token:o,uid:t._id,username:t.username,mobile:e,msg:"登录成功",tokenExpired:i}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}}},loginByEmail:async function({email:e,code:t}){const r=await Pr({email:e,code:t,type:"login"});if(0!==r.code)return r;const n={email:e,email_confirmed:1},o=await j.where(n).get();if(S("userInDB:",o),!(o&&o.data&&o.data.length>0)){const t={email:e,email_confirmed:1,register_ip:__ctx__.CLIENTIP,register_date:Date.now()},r=await j.add(t);S("addRes",r);const n=r.id;if(r.id){const{token:t,tokenExpired:r}=pr.createToken({_id:n});return await j.doc(n).update({token:[t]}),{code:0,uid:n,email:e,msg:"注册成功",token:t,tokenExpired:r}}return{code:90001,msg:"数据库写入失败"}}{const t=o.data[0];try{const r=await lr(t);if(0!==r.code)return r;const n=r.user.token;S("开始修改最后登录时间");const{token:o,tokenExpired:i}=pr.createToken(t);S("token",o),n.push(o);return S("upRes",await j.doc(t._id).update({last_login_date:(new Date).getTime(),last_login_ip:__ctx__.CLIENTIP,token:n})),{code:0,token:o,uid:t._id,username:t.username,email:e,msg:"登录成功",tokenExpired:i}}catch(e){return S("写入异常:",e),{code:90001,msg:"数据库写入异常"}}}},unbindEmail:async function({uid:e,email:t,code:r}){try{if(r){const e=await Pr({email:t,code:r,type:"unbind"});if(0!==e.code)return e}const n=$r.command;return 1===(await j.where({_id:e,email:t}).update({email:n.remove(),email_confirmed:n.remove()})).updated?{code:0,msg:"邮箱解绑成功"}:{code:70201,msg:"邮箱解绑失败,请稍后再试"}}catch(e){return S("发生异常",e),{code:90001,msg:"数据库写入异常"}}}};module.exports=Nr;
{
"name": "uni-id",
"version": "1.1.1",
"description": "uni-id for uniCloud",
"main": "index.js",
"scripts": {},
"keywords": [],
"author": "",
"license": "Apache-2.0"
}
// 在本文件中可配置云数据库初始化,数据格式见:https://uniapp.dcloud.io/uniCloud/cf-database?id=db_init
// 编写完毕后对本文件点右键,可按配置规则创建表和添加数据
{
"uni-id-users": {
"data": [],
"index": [{
"IndexName": "username",
"MgoKeySchema": {
"MgoIndexKeys": [{
"Name": "username",
"Direction": "1"
}],
"MgoIsUnique": false
}
}, {
"IndexName": "mobile",
"MgoKeySchema": {
"MgoIndexKeys": [{
"Name": "mobile",
"Direction": "1"
}],
"MgoIsUnique": false
}
}, {
"IndexName": "email",
"MgoKeySchema": {
"MgoIndexKeys": [{
"Name": "email",
"Direction": "1"
}],
"MgoIsUnique": false
}
}]
},
"uni-verify": {
"data": [],
"index": [{
"IndexName": "mobile",
"MgoKeySchema": {
"MgoIndexKeys": [{
"Name": "mobile",
"Direction": "1"
}],
"MgoIsUnique": false
}
}, {
"IndexName": "email",
"MgoKeySchema": {
"MgoIndexKeys": [{
"Name": "email",
"Direction": "1"
}],
"MgoIsUnique": false
}
}]
}
}
'use strict';
const uniID = require('uni-id')
const db = uniCloud.database()
const dbCmd = db.command
exports.main = async (event, context) => {
//event为客户端上传的参数
console.log('event : ' + event)
let params = event.params
let res = {}
let payload = {}
switch (event.action) {
case 'register':
res = uniID.register(params);
break;
case 'login':
res = uniID.login(params);
break;
case 'checkToken':
res = uniID.checkToken(event.uniIdToken);
break;
case 'logout':
res = await uniID.logout(event.uniIdToken)
break;
case 'sendSmsCode':
// 简单限制一下客户端调用频率
const ipLimit = await db.collection('uni-verify').where({
ip: context.CLIENTIP,
created_at: dbCmd.gt(Date.now() - 60000)
}).get()
if(ipLimit.data.length > 0) {
return {
code: 429,
msg: '请求过于频繁'
}
}
const randomStr = '00000' + Math.floor(Math.random() * 1000000)
const code = randomStr.substring(randomStr.length - 6)
res = await uniID.sendSmsCode({
mobile: params.mobile,
code,
type: 'login'
})
break;
case 'loginBySms':
res = await uniID.loginBySms(params)
break;
default:
res = {
code: 403,
msg: '非法访问'
}
break;
}
//返回数据给客户端
return res
};
../../common/uni-id
\ No newline at end of file
{
"name": "user-center",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"uni-id": {
"version": "file:../common/uni-id"
}
}
}
{
"name": "user-center",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"uni-id": "file:../common/uni-id"
}
}
// 本文件中的json内容将在云函数【运行】时作为参数传给云函数。
// 配置教程参考:https://uniapp.dcloud.net.cn/uniCloud/quickstart?id=runparam
{
"action": "sendSmsCode",
"params": {
"mobile": "18810505803"
}
}
\ No newline at end of file
page{
display: flex;
flex-direction: column;
width:100%;
}
.flex{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
}
.flex-ac{
/*align-items兼容写法开始*/
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
-webkit-box-align:center;
/*align-items兼容写法开始*/
}
.flex-jc{
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
.flex-dc{
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.flex-jb{
/*justify-content:space-between;兼容写法开始*/
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
/*align-items兼容写法开始*/
}
.flex-col-b{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
/*justify-content:space-between;兼容写法开始*/
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
/*align-items兼容写法开始*/
}
.flex-a-c{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
/*align-items兼容写法开始*/
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
-webkit-box-align:center;
/*align-items兼容写法开始*/
}
.flex-ac-jc{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
/*align-items兼容写法开始*/
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
-webkit-box-align:center;
/*align-items兼容写法开始*/
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
.flex-ac-jb{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
/*align-items兼容写法开始*/
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
-webkit-box-align:center;
/*align-items兼容写法开始*/
/*justify-content:space-between;兼容写法开始*/
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
/*align-items兼容
写法开始*/
}
.flex1{
-prefix-box-flex: 1;
-webkit-box-flex: 1;
-webkit-flex: 1;
-moz-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.ellipsis2{
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:2;
overflow:hidden;
}
.flex-wrap{
-webkit-flex-wrap: wrap;
-moz-flex-wrap: wrap;
-ms-flex-wrap: wrap;
-o-flex-wrap: wrap;
flex-wrap: wrap;
}
checkbox .wx-checkbox-input {
width: 35rpx;
height: 35rpx;
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked {
border: none;
background: #38B0A5;
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked::before {
border-radius: 50%;
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
font-size: 30rpx;
color: #fff;
}
button{
border:none;
border-radius:0;
}
button::after{
border: none;
border-radius: 0;
}
.flex-bt{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
/*justify-content:space-between;兼容写法开始*/
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
/*align-items兼容*/
}
checkbox .wx-checkbox-input {
border-radius: 50%;
width: 40rpx;
height: 40rpx;
}
\ No newline at end of file
@font-face {
font-family: uniicons;
font-weight: normal;
font-style: normal;
src: url('https://img-cdn-qiniu.dcloud.net.cn/fonts/uni.ttf?t=1536565627510') format('truetype');
}
.m-icon {
font-family: uniicons;
font-size: 24px;
font-weight: normal;
font-style: normal;
line-height: 1;
display: inline-block;
text-decoration: none;
-webkit-font-smoothing: antialiased;
}
.m-icon.uni-active {
color: #007aff;
}
.m-icon-contact:before {
content: '\e100';
}
.m-icon-person:before {
content: '\e101';
}
.m-icon-personadd:before {
content: '\e102';
}
.m-icon-contact-filled:before {
content: '\e130';
}
.m-icon-person-filled:before {
content: '\e131';
}
.m-icon-personadd-filled:before {
content: '\e132';
}
.m-icon-phone:before {
content: '\e200';
}
.m-icon-email:before {
content: '\e201';
}
.m-icon-chatbubble:before {
content: '\e202';
}
.m-icon-chatboxes:before {
content: '\e203';
}
.m-icon-phone-filled:before {
content: '\e230';
}
.m-icon-email-filled:before {
content: '\e231';
}
.m-icon-chatbubble-filled:before {
content: '\e232';
}
.m-icon-chatboxes-filled:before {
content: '\e233';
}
.m-icon-weibo:before {
content: '\e260';
}
.m-icon-weixin:before {
content: '\e261';
}
.m-icon-pengyouquan:before {
content: '\e262';
}
.m-icon-chat:before {
content: '\e263';
}
.m-icon-qq:before {
content: '\e264';
}
.m-icon-videocam:before {
content: '\e300';
}
.m-icon-camera:before {
content: '\e301';
}
.m-icon-mic:before {
content: '\e302';
}
.m-icon-location:before {
content: '\e303';
}
.m-icon-mic-filled:before,
.m-icon-speech:before {
content: '\e332';
}
.m-icon-location-filled:before {
content: '\e333';
}
.m-icon-micoff:before {
content: '\e360';
}
.m-icon-image:before {
content: '\e363';
}
.m-icon-map:before {
content: '\e364';
}
.m-icon-compose:before {
content: '\e400';
}
.m-icon-trash:before {
content: '\e401';
}
.m-icon-upload:before {
content: '\e402';
}
.m-icon-download:before {
content: '\e403';
}
.m-icon-close:before {
content: '\e404';
}
.m-icon-redo:before {
content: '\e405';
}
.m-icon-undo:before {
content: '\e406';
}
.m-icon-refresh:before {
content: '\e407';
}
.m-icon-star:before {
content: '\e408';
}
.m-icon-plus:before {
content: '\e409';
}
.m-icon-minus:before {
content: '\e410';
}
.m-icon-circle:before,
.m-icon-checkbox:before {
content: '\e411';
}
.m-icon-close-filled:before,
.m-icon-clear:before {
content: '\e434';
}
.m-icon-refresh-filled:before {
content: '\e437';
}
.m-icon-star-filled:before {
content: '\e438';
}
.m-icon-plus-filled:before {
content: '\e439';
}
.m-icon-minus-filled:before {
content: '\e440';
}
.m-icon-circle-filled:before {
content: '\e441';
}
.m-icon-checkbox-filled:before {
content: '\e442';
}
.m-icon-closeempty:before {
content: '\e460';
}
.m-icon-refreshempty:before {
content: '\e461';
}
.m-icon-reload:before {
content: '\e462';
}
.m-icon-starhalf:before {
content: '\e463';
}
.m-icon-spinner:before {
content: '\e464';
}
.m-icon-spinner-cycle:before {
content: '\e465';
}
.m-icon-search:before {
content: '\e466';
}
.m-icon-plusempty:before {
content: '\e468';
}
.m-icon-forward:before {
content: '\e470';
}
.m-icon-back:before,
.m-icon-left-nav:before {
content: '\e471';
}
.m-icon-checkmarkempty:before {
content: '\e472';
}
.m-icon-home:before {
content: '\e500';
}
.m-icon-navigate:before {
content: '\e501';
}
.m-icon-gear:before {
content: '\e502';
}
.m-icon-paperplane:before {
content: '\e503';
}
.m-icon-info:before {
content: '\e504';
}
.m-icon-help:before {
content: '\e505';
}
.m-icon-locked:before {
content: '\e506';
}
.m-icon-more:before {
content: '\e507';
}
.m-icon-flag:before {
content: '\e508';
}
.m-icon-home-filled:before {
content: '\e530';
}
.m-icon-gear-filled:before {
content: '\e532';
}
.m-icon-info-filled:before {
content: '\e534';
}
.m-icon-help-filled:before {
content: '\e535';
}
.m-icon-more-filled:before {
content: '\e537';
}
.m-icon-settings:before {
content: '\e560';
}
.m-icon-list:before {
content: '\e562';
}
.m-icon-bars:before {
content: '\e563';
}
.m-icon-loop:before {
content: '\e565';
}
.m-icon-paperclip:before {
content: '\e567';
}
.m-icon-eye:before {
content: '\e568';
}
.m-icon-arrowup:before {
content: '\e580';
}
.m-icon-arrowdown:before {
content: '\e581';
}
.m-icon-arrowleft:before {
content: '\e582';
}
.m-icon-arrowright:before {
content: '\e583';
}
.m-icon-arrowthinup:before {
content: '\e584';
}
.m-icon-arrowthindown:before {
content: '\e585';
}
.m-icon-arrowthinleft:before {
content: '\e586';
}
.m-icon-arrowthinright:before {
content: '\e587';
}
.m-icon-pulldown:before {
content: '\e588';
}
.m-icon-scan:before {
content: "\e612";
}
<template>
<view class="m-icon" :class="['m-icon-'+type]" @click="onClick()"></view>
</template>
<script>
export default {
props: {
/**
* 图标类型
*/
type: String
},
methods: {
onClick() {
this.$emit('click')
}
}
}
</script>
<style>
@import "./m-icon.css";
</style>
<template>
<view class="m-input-view">
<input :focus="focus" :type="inputType" :value="value" @input="onInput" class="m-input-input" :placeholder="placeholder"
:password="type==='password'&&!showPassword" @focus="onFocus" @blur="onBlur" />
<!-- 优先显示密码可见按钮 -->
<view v-if="clearable&&!displayable&&value.length" class="m-input-icon">
<m-icon color="#666666" type="clear" @click="clear"></m-icon>
</view>
<view v-if="displayable" class="m-input-icon">
<m-icon :style="{color:showPassword?'#666666':'#cccccc'}" type="eye" @click="display"></m-icon>
</view>
</view>
</template>
<script>
import mIcon from './m-icon/m-icon.vue'
export default {
components: {
mIcon
},
props: {
/**
* 输入类型
*/
type: String,
/**
* 值
*/
value: String,
/**
* 占位符
*/
placeholder: String,
/**
* 是否显示清除按钮
*/
clearable: {
type: [Boolean, String],
default: false
},
/**
* 是否显示密码可见按钮
*/
displayable: {
type: [Boolean, String],
default: false
},
/**
* 自动获取焦点
*/
focus: {
type: [Boolean, String],
default: false
}
},
model: {
prop: 'value',
event: 'input'
},
data() {
return {
/**
* 显示密码明文
*/
showPassword: false,
/**
* 是否获取焦点
*/
isFocus: false
}
},
computed: {
inputType() {
const type = this.type
return type === 'password' ? 'text' : type
}
},
methods: {
clear() {
this.$emit('input', '')
},
display() {
this.showPassword = !this.showPassword
},
onFocus() {
this.isFocus = true
},
onBlur() {
this.$nextTick(() => {
this.isFocus = false
})
},
onInput(e) {
this.$emit('input', e.detail.value)
}
}
}
</script>
<style>
.m-input-view {
display: inline-flex;
flex-direction: row;
align-items: center;
/* width: 100%; */
flex: 1;
padding: 0 10px;
}
.m-input-input {
flex: 1;
width: 100%;
height: 20px;
line-height: 20px;
background-color: rgba(0, 0, 0, 0);
}
.m-input-icon {
width: 20px;
font-size: 20px;
line-height: 20px;
color: #666666;
}
</style>
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
Vue.prototype.$store = store
App.mpType = 'app'
const app = new Vue({
store,
...App
})
app.$mount()
{
"name" : "comment_login",
"appid" : "",
"description" : "登录模板",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
"usingComponents" : true,
"compilerVersion" : 3,
/* 模块配置 */
"modules" : {},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios打包配置 */
"ios" : {},
/* SDK配置 */
"sdkConfigs" : {}
}
},
/* 快应用特有相关 */
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"h5" : {
"router" : {
"base" : ""
}
}
}
{
"pages": [ //pages数组中第一项表示应用启动页,
{
"path": "pages/main/main",
"style": {
"navigationBarTitleText": "登录模板"
}
}, {
"path": "pages/login/login",
"style": {
"navigationBarTitleText": "登录"
}
}, {
"path": "pages/reg/reg",
"style": {
"navigationBarTitleText": "注册"
}
}, {
"path": "pages/pwd/pwd",
"style": {
"navigationBarTitleText": "找回密码"
}
}, {
"path": "pages/user/user",
"style": {
"navigationBarTitleText": "我的"
}
}
,{
"path" : "pages/evaluate/evaluate",
"style" : {
"navigationBarTitleText": "满意度评价"
}
}
,{
"path" : "pages/evaluate-history/evaluate-history",
"style" : {
"navigationBarTitleText": "历史评价"
}
}
,{
"path" : "pages/service-apl/service-apl",
"style" : {
"navigationBarTitleText": "申请服务"
}
}
,{
"path" : "pages/service-apl-history/service-apl-history",
"style" : {
"navigationBarTitleText": "审批记录 "
}
}
],
"tabBar": {
"color": "#7a7e83",
"selectedColor": "#d81e06",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/main/main",
"text": "首页",
"iconPath": "static/bottombar/home.png",
"selectedIconPath": "static/bottombar/selhome.png"
}, {
"pagePath": "pages/user/user",
"text": "我的",
"iconPath": "static/bottombar/my.png",
"selectedIconPath": "./static/bottombar/selmy.png"
}]
},
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#CA0000",
"backgroundColor": "#fbf9fe"
}
}
.m-list{
padding:25upx 10upx;
border-bottom:1upx solid #eee;
}
.ser-name{
width:350upx;margin-right:15rpx;
}
.time{
padding-top:15upx;
color:#ccc;
font-size:30upx;
}
.head-img{
flex-shrink: 0;
margin-right:15upx;
width:100upx;
height:100upx;
border-radius:50%;
}
.img-area{
margin-top:15upx;
}
.img-area .upload-img{
width:150upx;
height:150upx;
margin:5upx 10upx;
}
<template>
<view style="padding:0 35rpx;">
<view class="flex m-list" style="">
<image class="head-img" style="" src="../../static/img/app-icon.png"></image>
<view>
<view class="flex">
<view class="ser-name ellipsis2" style="">服务名称</view>
<view class="time">2020.9.10</view>
</view>
<view>
<text></text>
<text></text>
<text></text>
<text></text>
</view>
<view style="color:#ccc;">
服务好,非常满意
</view>
<view class="img-area" style="margin-top:25upx;">
<image class="upload-img" src="../../static/img/app-icon.png"></image>
<image class="upload-img" src="../../static/img/app-icon.png"></image>
<image class="upload-img" src="../../static/img/app-icon.png"></image>
<image class="upload-img" src="../../static/img/app-icon.png"></image>
</view>
</view>
</view>
<view class="flex m-list" style="">
<image class="head-img" style="" src="../../static/img/app-icon.png"></image>
<view>
<view class="flex">
<view class="ser-name ellipsis2" style="">服务名称官方价格封建割据金凤凰过节费过节费监管局房管局发几个</view>
<view class="time">2020.9.10</view>
</view>
<view>
<text></text>
<text></text>
<text></text>
<text></text>
</view>
<view style="color:#ccc;">
服务好,非常满意寄过来交流交流归根结底开花结果开花结果开花结果看黄金矿工会更好规范化
</view>
<view class="img-area" style="margin-top:25upx;">
<image class="upload-img" src="../../static/img/app-icon.png"></image>
<image class="upload-img" src="../../static/img/app-icon.png"></image>
<image class="upload-img" src="../../static/img/app-icon.png"></image>
<image class="upload-img" src="../../static/img/app-icon.png"></image>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
@import url("evaluate-history.css");
</style>
.category-title {
font-size: 31upx;
font-weight: bold;
padding: 15upx 0;
}
.cate-box {
padding: 15upx 0;
display: flex;
align-items: center;
}
.category-area {
white-space: nowrap;
position: relative;
background-color: #fff;
z-index: 2;
}
.cate-item {
display: inline-block;
/* padding: 8upx 25upx; */
width: 164upx;
height: 74upx;
line-height: 70upx;
text-align: center;
border: 1upx solid #eee;
font-size: 28upx;
border-radius: 10upx;
background-color: #f4f7f8;
color: #2ac096;
margin-right: 30upx;
}
.cate-item .name {
display: inline-block;
vertical-align: middle;
}
.z-cate {
background: linear-gradient(#27c599, #3a9f84); /* 标准的语法 */
color: white;
}
.g-bd {
padding: 35upx 25upx;
font-size: 30upx;
flex:1;
}
.suggest-area {
margin-top: 25upx;
border: 1upx solid #ccc;
padding: 15upx;
font-size: 25upx;
width: 100%;
box-sizing: border-box;
}
.box-title {
margin-top: 25upx;
font-size: 32upx;
}
.title-intro {
color: #999;
font-size: 22upx;
font-weight: normal;
}
.imgs-area {
padding: 25upx 0;
display: flex;
flex-direction:row;
flex-wrap:wrap;
/* border-bottom: 5upx solid #eee; */
}
.imgs-area .img-box {
display: inline-block;
position: relative;
width: 200upx;
height: 200upx;
/* margin-right: 25upx;
margin-bottom: 15upx; */
margin:10upx;
}
.imgs-area .add-box {
/* vertical-align: top; */
box-sizing: border-box;
font-size: 25upx;
/* padding-top: 30upx; */
/* border: 1upx solid #ccc; */
background: #F4F7F8;
width: 200upx;
height: 200upx;
/* display: inline-block; */
text-align: center;
margin:10upx;
}
.imgs-area .img-box .pic {
display: block;
width: 100%;
height: 100%;
}
.imgs-area .img-box .delete-icon {
position: absolute;
top: -15upx;
right: -15upx;
z-index: 2upx;
width: 40upx;
height: 40upx;
}
.imgs-area .add-btn {
display: inline-block;
width: 80upx;
height: 80upx;
}
.btns-area {
display:flex;
position:fixed;
width:100%;
bottom:0;
padding:50upx 0;
left:0;
}
.send-btn {
position: relative;
padding: 0!important;
width: 250upx!important;
height: 74upx;
line-height: 74upx;
text-align: center;
background:#CA0000; /* 标准的语法 */
color: white;
font-size: 25upx;
border-radius:50upx;
}
.right-icon {
position: absolute;
right: 35upx;
top: 13upx;
}
.cancel-btn {
border: 1upx solid #ccc;
background-color: white;
padding: 0;
width: 250upx!important;
height: 74upx;
line-height: 74upx;
text-align: center;
font-size: 25upx;
border-radius:50upx;
}
/*产品缩略 */
.goodsInfo {
display: flex;
align-items: center;
}
.goodsInfo image {
width: 100upx;
height: 100upx;
border-radius: 8upx;
border: 2upx solid #ccc
}
.goodsInfo view {
margin-left: 30upx;
flex: 1;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
/* 服务完成评价星星******************************** */
/* .star-rating {
unicode-bidi: bidi-override;
color: #ddd;
font-size: 30upx;
padding: 0;
}
.star-rating-shop {
color: #ddd;
font-size: 30upx;
height: 150upx;
}
.star-rating text {
padding: 5px;
font-size: 20px;
}
.star-rating-shop text {
padding: 5px;
font-size: 20px;
}
.star-rating-top {
color: #ffd700;
padding: 0;
position: absolute;
z-index: 1;
display: block;
top: 0;
left: 0;
overflow: hidden;
white-space: nowrap;
}
.star-rating-bottom {
padding: 0;
display: block;
z-index: 0;
} */
.v-o-p-img {
display: inline;
position: relative;
top: 35upx;
margin-right: 50upx;
}
.v-o-p-img image{
width:100upx;
height:100upx;
background:white;
}
.v-o-l-face{
color:#eee;
/* display:inline-block; */
margin-left:60upx;
/* position: relative; */
top:18upx;
}
.v-o-l-face image{
width:70upx;
height:70upx;
}
.v-o-l-text{
display:inline-block;
margin-left:20upx;
color:#ccc;
font-size:30rpx;
}
.star{
display: inline-block;
margin:20upx;
font-size:55upx;
}
/***************************************** */
<template>
<view class="g-bd">
<!-- <view class="type-box" >
<view class="category-title">xx信息<text style="color:red;">*</text></view>
<view class="goodsInfo" >
<image src=""></image>
<view>xx</view>
</view>
</view> -->
<view class="type-box">
<view class="category-title">
星级评价 <text style="color:red;">*</text>
</view>
<view class="cate-box">
<!-- <scroll-view scroll-x="true" class="category-area">
<block wx:for="{{ suggestInfo.typeList }}" wx:key="index">
<view bindtap="selectTypeTap" class="cate-item ">
<text class="name" >xx</text>
</view>
</block>
</scroll-view> -->
<view class="star" v-for="(item,index) in starsList" :key="item.id" v-bind:style="{ color: [item.selected ?'red':'#ccc']}"
:data-current="index" @tap="selStar">{{ item.content }}</view>
<view class='flex-a-c v-o-l-face'>
<image :src="starLevel[cur_starLevel].face" />
<view class='v-o-l-text'>{{starLevel[cur_starLevel].name}}</view>
</view>
</view>
</view>
<view class="category-title">
评价内容<text style="color:red;">*</text>
</view>
<textarea class="suggest-area" placeholder="请输入60字以内问题或建议" name="content" maxlength="60"></textarea>
<view class="category-title">
上传图片
<text class="title-intro" style="">(如无图片,可以忽略,最多6张图)</text>
</view>
<view class="imgs-area">
<view class="img-box" v-for="(item,index) in imageList" :key="index">
<image class="pic" :src="item" @tap="previewPictures(item)"/>
<image @click="del(index)" class="delete-icon" src="../../static/comment/delete.png" />
</view>
<view class="flex-ac-jc add-box" @click="uploadPictures">
<image class="add-btn" style='' src='../../static/comment/add-icon.png'></image>
</view>
</view>
<view>
<view class="btns-area">
<button class="send-btn flex-ac-jc">确 定</button>
<button class="cancel-btn flex-ac-jc">取 消</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
imageList: [],
starsList: [{
id: 1,
content: "★",
selected: true
}, {
id: 2,
content: "★",
selected: false
},
{
id: 3,
content: "★",
selected: false
}, {
id: 4,
content: "★",
selected: false
},
{
id: 5,
content: "★",
selected: false
}
],
// orderList: [{
// id: 1,
// content: "★",
// selected: false
// }, {
// id: 2,
// content: "★",
// selected: false
// },
// {
// id: 3,
// content: "★",
// selected: false
// }, {
// id: 4,
// content: "★",
// selected: false
// },
// {
// id: 5,
// content: "★",
// selected: false
// }
// ],
starLevel: [
{
level:1,
name: "不满意",
face: "../../static/comment/level1.png"
},
{
level:2,
name: "较不满意",
face: "../../static/comment/level2.png"
},
{
level:3,
name: "一般",
face: "../../static/comment/level3.png"
},
{
level:4,
name: "较满意",
face: "../../static/comment/level4.png"
},
{
level:5,
name: "很满意",
face: "../../static/comment/praise.png"
},
],
cur_starLevel:0
}
},
methods: {
uploadPictures() {
uni.chooseImage({
count: 6, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], //从相册选择
success: res => {
console.log(res)
// 将选择的本地图片赋值给data中定义的images变量
this.imageList =this.imageList.concat(res.tempFilePaths);
console.log(this.imageList)
}
})
},
/*
图片预览
*/
previewPictures(item) {
uni.previewImage({
current: item,
urls: this.imageList
})
},
del(index){
this.imageList.splice(index, 1)
},
selStar(e) {
let idx = e.target.dataset.current || e.currentTarget.dataset.current; //获取下标值
idx++;
var list = this.starsList;
for (var i in list) {
list[i].selected = i < idx ? true : false;
}
// for (var i in starLevel) {
// starLevel[i].level = idx?this.star_level=idx:this.star_level=1;
// }
this.starsList = list;
this.cur_starLevel=idx-1;
},
chooseImg() {
uni.chooseImage({
count: 6, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], //从相册选择
success: function(res) {
// 预览图片
// uni.previewImage({
// urls: res.tempFilePaths,
// longPressActions: {
// itemList: ['发送给朋友', '保存图片', '收藏'],
// success: function(data) {
// console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
// },
// fail: function(err) {
// console.log(err.errMsg);
// }
// }
// });
// console.log(JSON.stringify(res.tempFilePaths));
// this.imageList = res.tempFilePaths
this.imageList = res.tempFilePaths;
}
});
},
}
}
</script>
<style>
@import url('evaluate.css');
</style>
.head-icon{
display:block;
margin:50upx auto;
width:150upx;
height:150upx;
border-radius:50%;
}
.login-area{
background-color:#fff;
width:95%;
margin:0 auto;
border:1upx solid #eee;
border-radius:15upx;
}
.login-item{
/* background-color:#fff; */
display: flex;
align-items: center;
/* border-radius:15upx; */
}
.login-icon{
width:50upx;
height:50upx;
margin:0 30upx;
}
.login-item-input{
flex:1;
height:120upx;
line-height:120upx;
font-size:30upx;
}
.bt{
border-bottom:1upx solid #eee;
}
.code-btn{
font-size:25rpx;
border:1upx solid #ccc;
padding:15upx;
border-radius:15upx;
margin:0 25upx;
}
.btn-login{
background-color: #CA0000;border-radius:15upx;
}
.mt25{
margin-top:25upx;
}
\ No newline at end of file
<template>
<view class="content">
<!-- <view class="login-type">
<view v-for="(item,index) in loginTypeList" :key="index" @click="loginType = index" :class="{act: loginType === index}"
class="login-type-btn">{{item}}</view>
</view> -->
<!-- <view class="input-group" v-if="loginType === 0">
<view class="input-row border">
<text class="title">账号:</text>
<m-input class="m-input" type="text" clearable focus v-model="username" placeholder="请输入账号"></m-input>
</view>
<view class="input-row">
<text class="title">密码:</text>
<m-input type="password" displayable v-model="password" placeholder="请输入密码"></m-input>
</view>
</view> -->
<!-- <view class="input-group">
<view class="input-row border">
<text class="title">手机:</text>
<m-input class="m-input" type="text" clearable focus v-model="mobile" placeholder="请输入手机号码"></m-input>
</view>
<view class="input-row">
<text class="title">验证码:</text>
<m-input type="text" v-model="code" placeholder="请输入验证码"></m-input>
<view class="send-code-btn" @click="sendSmsCode">{{codeDuration ? codeDuration + 's' : '发送验证码' }}</view>
</view>
</view> -->
<!-- 登录新样式start -->
<view>
<image class="head-icon" style="" src="../../static/login/personal.png"></image>
</view>
<view class="login-area">
<view class="login-item bt">
<image class="login-icon" src="../../static/login/mine.png"></image>
<input class="login-item-input" placeholder="请输入手机号" />
</view>
<view class="login-item bt">
<image class="login-icon" src="../../static/login/password.png"></image>
<input class="login-item-input" placeholder="请输入验证码" />
<view class="code-btn" style="">获取验证码</view>
</view>
<view class="login-item bt">
<image class="login-icon" src="../../static/login/code.png"></image>
<input class="login-item-input" placeholder="请输入密码" />
</view>
</view>
<!-- 登录新样式end -->
<view class="btn-row">
<button type="primary" class="primary btn-login" @tap="bindLogin">登录</button>
</view>
<view class="action-row">
<navigator url="../reg/reg">注册账号</navigator>
</view>
<view class="oauth-row" v-if="hasProvider" v-bind:style="{top: positionTop + 'px'}">
<view class="oauth-image" v-for="provider in providerList" :key="provider.value">
<image :src="provider.image" @tap="oauth(provider.value)"></image>
<!-- #ifdef MP-WEIXIN -->
<button v-if="!isDevtools" open-type="getUserInfo" @getuserinfo="getUserInfo"></button>
<!-- #endif -->
</view>
</view>
</view>
</template>
<script>
import service from '../../service.js';
import {
mapState,
mapMutations
} from 'vuex'
import mInput from '../../components/m-input.vue'
export default {
components: {
mInput
},
data() {
return {
loginType: 0,
loginTypeList: ['密码登录', '免密登录'],
mobile: '',
code: '',
providerList: [],
hasProvider: false,
username: '',
password: '',
positionTop: 0,
isDevtools: false,
codeDuration: 0
}
},
computed: mapState(['forcedLogin']),
methods: {
...mapMutations(['login']),
initProvider() {
const filters = ['weixin', 'qq', 'sinaweibo'];
uni.getProvider({
service: 'oauth',
success: (res) => {
if (res.provider && res.provider.length) {
for (let i = 0; i < res.provider.length; i++) {
if (~filters.indexOf(res.provider[i])) {
this.providerList.push({
value: res.provider[i],
image: '../../static/img/' + res.provider[i] + '.png'
});
}
}
this.hasProvider = true;
}
},
fail: (err) => {
console.error('获取服务供应商失败:' + JSON.stringify(err));
}
});
},
initPosition() {
/**
* 使用 absolute 定位,并且设置 bottom 值进行定位。软键盘弹出时,底部会因为窗口变化而被顶上来。
* 反向使用 top 进行定位,可以避免此问题。
*/
this.positionTop = uni.getSystemInfoSync().windowHeight - 100;
},
sendSmsCode() {
if(this.codeDuration) {
uni.showModal({
content: `请在${this.codeDuration}秒后重试`,
showCancel: false
})
}
if (!/^1\d{10}$/.test(this.mobile)) {
uni.showModal({
content: '手机号码填写错误',
showCancel: false
})
return
}
uniCloud.callFunction({
name: 'user-center',
data: {
action: 'sendSmsCode',
params: {
mobile: this.mobile
}
},
success: (e) => {
if (e.result.code == 0) {
uni.showModal({
content: '验证码发送成功,请注意查收',
showCancel: false
})
this.codeDuration = 60
this.codeInterVal = setInterval(() => {
this.codeDuration--
if (this.codeDuration === 0) {
if (this.codeInterVal) {
clearInterval(this.codeInterVal)
this.codeInterVal = null
}
}
}, 1000)
} else {
uni.showModal({
content: '验证码发送失败:' + e.result.msg,
showCancel: false
})
}
},
fail(e) {
uni.showModal({
content: '验证码发送失败',
showCancel: false
})
}
})
},
loginByPwd() {
/**
* 客户端对账号信息进行一些必要的校验。
* 实际开发中,根据业务需要进行处理,这里仅做示例。
*/
if (this.username.length < 3) {
uni.showToast({
icon: 'none',
title: '账号最短为 3 个字符'
});
return;
}
if (this.password.length < 6) {
uni.showToast({
icon: 'none',
title: '密码最短为 6 个字符'
});
return;
}
const data = {
username: this.username,
password: this.password
};
let _self = this;
uniCloud.callFunction({
name: 'user-center',
data: {
action: 'login',
params: data
},
success: (e) => {
console.log('login success', e);
if (e.result.code == 0) {
uni.setStorageSync('uniIdToken', e.result.token)
uni.setStorageSync('username', e.result.username)
uni.setStorageSync('login_type', 'online')
_self.toMain(_self.username);
} else {
uni.showModal({
content: e.result.msg,
showCancel: false
})
console.log('登录失败', e);
}
},
fail(e) {
uni.showModal({
content: JSON.stringify(e),
showCancel: false
})
}
})
},
loginBySms() {
if (!/^1\d{10}$/.test(this.mobile)) {
uni.showModal({
content: '手机号码填写错误',
showCancel: false
})
return
}
if (!/^\d{6}$/.test(this.code)) {
uni.showModal({
title: '验证码为6位纯数字',
showCancel: false
});
return;
}
let _self = this;
uniCloud.callFunction({
name: 'user-center',
data: {
action: 'loginBySms',
params: {
mobile: this.mobile,
code: this.code
}
},
success: (e) => {
console.log('login success', e);
if (e.result.code == 0) {
const username = e.result.username || '新用户'
uni.setStorageSync('uniIdToken', e.result.token)
uni.setStorageSync('username', username)
uni.setStorageSync('login_type', 'online')
_self.toMain(username);
} else {
uni.showModal({
content: e.result.msg,
showCancel: false
})
console.log('登录失败', e);
}
},
fail(e) {
uni.showModal({
content: JSON.stringify(e),
showCancel: false
})
}
})
},
bindLogin() {
switch (this.loginType) {
case 0:
this.loginByPwd()
break;
case 1:
this.loginBySms()
break;
default:
break;
}
},
oauth(value) {
console.log('三方登录只演示登录api能力,暂未关联云端数据');
uni.login({
provider: value,
success: (res) => {
uni.getUserInfo({
provider: value,
success: (infoRes) => {
/**
* 实际开发中,获取用户信息后,需要将信息上报至服务端。
* 服务端可以用 userInfo.openId 作为用户的唯一标识新增或绑定用户信息。
*/
this.loginLocal(infoRes.userInfo.nickName);
},
fail() {
uni.showToast({
icon: 'none',
title: '登陆失败'
});
}
});
},
fail: (err) => {
console.error('授权登录失败:' + JSON.stringify(err));
}
});
},
getUserInfo({
detail
}) {
console.log('三方登录只演示登录api能力,暂未关联云端数据');
if (detail.userInfo) {
this.loginLocal(detail.userInfo.nickName);
} else {
uni.showToast({
icon: 'none',
title: '登陆失败'
});
}
},
loginLocal(nickName) {
uni.setStorageSync('login_type', 'local')
uni.setStorageSync('username', nickName)
this.toMain(nickName);
},
toMain(userName) {
this.login(userName);
/**
* 强制登录时使用reLaunch方式跳转过来
* 返回首页也使用reLaunch方式
*/
if (this.forcedLogin) {
uni.reLaunch({
url: '../main/main',
});
} else {
uni.navigateBack();
}
}
},
onReady() {
this.initPosition();
this.initProvider();
// #ifdef MP-WEIXIN
this.isDevtools = uni.getSystemInfoSync().platform === 'devtools';
// #endif
}
}
</script>
<style>
@import url("login.css");
.login-type {
display: flex;
justify-content: center;
}
.login-type-btn {
line-height: 30px;
margin: 0px 15px;
}
.login-type-btn.act {
color: #0FAEFF;
border-bottom: solid 1px #0FAEFF;
}
.send-code-btn {
width: 120px;
text-align: center;
background-color: #0FAEFF;
color: #FFFFFF;
}
.action-row {
display: flex;
flex-direction: row;
justify-content: center;
}
.action-row navigator {
color: #007aff;
padding: 0 10px;
}
.oauth-row {
display: flex;
flex-direction: row;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
}
.oauth-image {
position: relative;
width: 50px;
height: 50px;
border: 1px solid #dddddd;
border-radius: 50px;
margin: 0 20px;
background-color: #ffffff;
}
.oauth-image image {
width: 30px;
height: 30px;
margin: 10px;
}
.oauth-image button {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0;
}
</style>
<template>
<view class="content">
<view v-if="hasLogin" class="hello">
<view class="title">
您好 {{userName}},您已成功登录。
</view>
<view class="ul">
<view>这是 uni-app 带登录模板的示例App首页。</view>
<view>在 “我的” 中点击 “退出” 可以 “注销当前账户”</view>
</view>
</view>
<view v-if="!hasLogin" class="hello">
<view class="title">
您好 游客。
</view>
<view class="ul">
<view>这是 uni-app 带登录模板的示例App首页。</view>
<view>在 “我的” 中点击 “登录” 可以 “登录您的账户”</view>
</view>
</view>
</view>
</template>
<script>
import {
mapState,
mapMutations
} from 'vuex'
export default {
computed: mapState(['forcedLogin', 'hasLogin', 'userName']),
onLoad() {
const loginType = uni.getStorageSync('login_type')
if (loginType === 'local') {
this.login(uni.getStorageSync('username'))
return
}
let uniIdToken = uni.getStorageSync('uniIdToken')
if (uniIdToken) {
this.login(uni.getStorageSync('username'))
uniCloud.callFunction({
name: 'user-center',
data: {
action: 'checkToken',
},
success: (e) => {
console.log('checkToken success', e);
if (e.result.code > 0) {
//token过期或token不合法,重新登录
if (this.forcedLogin) {
uni.reLaunch({
url: '../login/login'
});
} else {
uni.navigateTo({
url: '../login/login'
});
}
}
},
fail(e) {
uni.showModal({
content: JSON.stringify(e),
showCancel: false
})
}
})
} else {
this.guideToLogin()
}
},
methods: {
...mapMutations(['login']),
guideToLogin() {
uni.showModal({
title: '未登录',
content: '您未登录,需要登录后才能继续',
/**
* 如果需要强制登录,不显示取消按钮
*/
showCancel: !this.forcedLogin,
success: (res) => {
if (res.confirm) {
/**
* 如果需要强制登录,使用reLaunch方式
*/
if (this.forcedLogin) {
uni.reLaunch({
url: '../login/login'
});
} else {
uni.navigateTo({
url: '../login/login'
});
}
}
}
});
}
}
}
</script>
<style>
.hello {
display: flex;
flex: 1;
flex-direction: column;
}
.title {
color: #8f8f94;
margin-top: 25px;
}
.ul {
font-size: 15px;
color: #8f8f94;
margin-top: 25px;
}
.ul>view {
line-height: 25px;
}
</style>
<template>
<view class="content">
<view class="input-group">
<view class="input-row">
<text class="title">邮箱:</text>
<m-input type="text" focus clearable v-model="email" placeholder="请输入邮箱"></m-input>
</view>
</view>
<view class="btn-row">
<button type="primary" class="primary" @tap="findPassword">提交</button>
</view>
</view>
</template>
<script>
import service from '../../service.js';
import mInput from '../../components/m-input.vue';
export default {
components: {
mInput
},
data() {
return {
email: ''
}
},
methods: {
findPassword() {
/**
* 仅做示例
*/
if (this.email.length < 3 || !~this.email.indexOf('@')) {
uni.showToast({
icon: 'none',
title: '邮箱地址不合法',
});
return;
}
uni.showToast({
icon: 'none',
title: '已发送重置邮件至注册邮箱,请注意查收。',
duration: 3000
});
}
}
}
</script>
<style>
</style>
.head-icon{
display:block;
margin:50upx auto;
width:150upx;
height:150upx;
border-radius:50%;
}
.login-area{
/* background-color:#fff; */
width:95%;
margin:0 auto;
border:1upx solid #eee;
/* border-radius:15upx; */
}
.login-item{
background-color:#fff;
display: flex;
align-items: center;
border-radius:15upx;
}
.login-icon{
width:50upx;
height:50upx;
margin:0 30upx;
}
.login-item-input{
flex:1;
height:90upx;
line-height:90upx;
font-size:30upx;
}
.bt{
border-bottom:1upx solid #eee;
}
.code-btn{
font-size:25rpx;
border:1upx solid #ccc;
padding:15upx;
border-radius:15upx;
margin:0 25upx;
}
.btn-login{
background-color: #CA0000;
border-radius:15upx;
}
.mt25{
margin-top:25upx;
}
.uni-list-cell{
margin:0 50upx;
}
.radio-v{
padding:25upx 30upx;
font-size:30upx;
}
/* .uni-radio-input {
background-color: red!important;
border-color: red!important;
}
.uni-radio-input-checked{
background-color: red!important;
border-color: red!important;
} */
\ No newline at end of file
<template>
<view class="content">
<!-- <view class="input-group">
<view class="input-row border">
<text class="title">账号:</text>
<m-input type="text" focus clearable v-model="username" placeholder="请输入账号"></m-input>
</view>
<view class="input-row border">
<text class="title">密码:</text>
<m-input type="password" displayable v-model="password" placeholder="请输入密码"></m-input>
</view>
<view class="input-row">
<text class="title">确认密码:</text>
<m-input type="password" displayable v-model="confirmPassword" placeholder="请确认密码"></m-input>
</view>
</view> -->
<!-- 登录新样式start -->
<view style="text-align: center;color:#CA0000;font-size:45upx;padding:50upx;">
<!-- <image class="head-icon" style="" src="../../static/login/personal.png"></image> -->
欢迎注册!
</view>
<view class="login-area">
<view class="login-item">
<image class="login-icon" src="../../static/login/mine.png"></image>
<input class="login-item-input" placeholder="请输入身份证号" />
</view>
<view class="login-item radio-v mt25" style="">
<view>是否持证</view>
<radio-group class="flex uni-list" @change="radioChange">
<view class="flex uni-list-cell uni-list-cell-pd" v-for="(item,index) in radioItems" :key="index">
<view>
<radio :id="item.name" :value="item.name" :checked="item.checked"></radio>
</view>
<label class="label-2-text" :for="item.name">
<text>{{item.value}}</text>
</label>
</view>
</radio-group>
</view>
<view class="login-item mt25">
<image class="login-icon" src="../../static/login/phone.png"></image>
<input class="login-item-input" placeholder="请输入手机号码" />
</view>
<view class="login-item mt25">
<image class="login-icon" src="../../static/login/code.png"></image>
<input class="login-item-input" placeholder="请输入验证码" />
<view class="code-btn" style="">获取验证码</view>
</view>
<view class="login-item mt25">
<image class="login-icon" src="../../static/login/password.png"></image>
<input class="login-item-input" placeholder="请输入登录密码" />
</view>
<view class="login-item mt25">
<image class="login-icon" src="../../static/login/password.png"></image>
<input class="login-item-input" placeholder="请再次输入登录密码" />
</view>
</view>
<!-- 登录新样式end -->
<view class="btn-row">
<button type="primary" class="primary btn-login" @tap="register">注册</button>
</view>
</view>
</template>
<script>
import service from '../../service.js';
import mInput from '../../components/m-input.vue';
export default {
components: {
mInput
},
data() {
return {
username: '',
password: '',
confirmPassword: '',
radioItems: [{
name: 'USA',
value: '是'
},
{
name: 'CHN',
value: '否',
checked: 'true'
}
],
}
},
methods: {
register() {
/**
* 客户端对账号信息进行一些必要的校验。
* 实际开发中,根据业务需要进行处理,这里仅做示例。
*/
if (this.username.length < 3) {
uni.showToast({
icon: 'none',
title: '账号最短为 3 个字符'
});
return;
}
if (this.password.length < 6) {
uni.showToast({
icon: 'none',
title: '密码最短为 6 个字符'
});
return;
}
if (this.password !== this.confirmPassword) {
uni.showToast({
icon: 'none',
title: '两次密码输入不一致'
});
return;
}
const data = {
username: this.username,
password: this.password
}
uniCloud.callFunction({
name: 'user-center',
data: {
action: 'register',
params: data
},
success(e) {
console.log("注册成功", e);
if (e.result.code === 0) {
uni.showToast({
title: '注册成功'
});
uni.setStorageSync('uniIdToken', e.result.token)
uni.setStorageSync('username', e.result.username)
uni.reLaunch({
url: '../main/main',
});
} else {
uni.showModal({
content: JSON.stringify(e.result),
showCancel: false
})
}
},
fail(e) {
uni.showModal({
content: JSON.stringify(e),
showCancel: false
})
}
})
}
}
}
</script>
<style>
@import url("reg.css");
</style>
.menu-bar{
text-align: center;
}
.tybe-tab{
display: inline-block;
width:33%;
height:90upx;
line-height:90upx;
text-align: center;
font-size:30upx;
font-weight:bold;
}
.z-active{
/* border-bottom:2upx solid red; */
color:red;
position: relative;
}
.z-active::before{
position: absolute;
bottom:0;
left:30%;
content: '';
height:2upx;
width:100upx;
background-color: red;;
}
.list-area{
padding:0 35upx;
}
.m-his-list{
padding:35upx 0;
border-bottom:1upx solid #eee;
}
.his-item{
font-size:28upx;
color: #ccc;
}
.his-item-result{
font-size:28upx;
color: #ccc;
color:red;
}
.mt10{
margin-top:10upx;
}
\ No newline at end of file
<template>
<view>
<view class="menu-bar">
<block v-for="(tab,index) in StatusList" :key="tab.id">
<view :data-current="index" @click="ontabtap" class="tybe-tab" :class="statusIndex==index ? 'z-active' : ''">{{tab.name}}</view>
</block>
<!-- <view class="tybe-tab">已审批</view>
<view class="tybe-tab">待审批</view> -->
</view>
<block v-if="statusIndex==0">
<view class="list-area">
<view class="m-his-list" style="">
<view class="his-item">申请人:张三</view>
<view class="his-item mt10">伤残等级:一级</view>
<view class="his-item mt10">伤残类别:意外</view>
<view class="his-item mt10">服务类型:特殊服务</view>
<view class="his-item mt10">申请时间:2020.10.1</view>
<view class="his-item-result mt10">审批结果:待审批</view>
</view>
<view class="m-his-list" style="">
<view class="his-item">申请人:张三</view>
<view class="his-item mt10">伤残等级:一级</view>
<view class="his-item mt10">伤残类别:意外</view>
<view class="his-item mt10">服务类型:特殊服务</view>
<view class="his-item mt10">申请时间:2020.10.1</view>
<view class="his-item-result mt10">审批结果:拒绝</view>
<view class="his-item-result mt10">拒绝理由:个叽里呱啦</view>
</view>
</view>
</block>
</view>
</template>
<script>
export default {
data() {
return {
statusIndex:0,
StatusList:[
{
name:'全部'
},
{
name:'已审批'
},
{
name:'待审批'
}
]
}
},
methods: {
ontabtap(e){
let index = e.target.dataset.current || e.currentTarget.dataset.current;
var curIndex=this.statusIndex
if(curIndex==index){
return
}else{
this.statusIndex=index
}
}
}
}
</script>
<style>
@import url("service-apl-history.css");
</style>
page{
padding-bottom:150upx;
background:#F7F7F7;
}
.set-info-title{
font-size:28upx;
color:#999;
background:#F7F7F7;
height:80upx;
line-height:80upx;
padding:0 35upx;
}
.set-info-item {
padding: 0 35upx;
border-bottom: 1upx solid #eee;
}
.set-info-item .item-name {
position: relative;
font-size: 30upx;
margin-right: 25upx;
padding-right: 25upx;
white-space: nowrap;
flex-shrink: 0;
}
.set-info-item .item-name .remind-icon {
position: absolute;
right: -5upx;
top: 5upx;
width: 16upx;
height: 16upx;
}
.set-info-item .item-iput {
font-size: 30upx;
height: 90upx;
line-height: 90upx;
padding: 0 25upx;
}
.set-info-pad {
padding-top: 25upx;
padding-bottom: 25upx;
}
.set-intro-item {
padding: 25upx 35upx;
}
.set-intro-item .item-name {
position: relative;
font-size: 30upx;
margin-right: 25upx;
padding-right: 25upx;
white-space: nowrap;
flex-shrink: 0;
}
.set-intro-item .item-name .remind-icon {
position: absolute;
right: -5upx;
top: 5upx;
width: 16upx;
height: 16upx;
}
.set-intro-item .intro-holder {
font-size: 30upx;
color: #999;
text-align: right;
padding: 0 25upx;
}
.into-num {
font-size: 25upx;
color: #999;
text-align: center;
}
.area-view {
padding: 15upx 35upx;
border-bottom: 1upx solid #eee;
}
.intro-area {
width: 100%;
height: 200upx;
font-size: 30upx;
}
.intro-img {
width: 200upx;
height: 200upx;
background: #ccc;
margin: 0 auto;
}
.img-box {
display: block;
position: relative;
width: 200upx;
height: 200upx;
margin: 0 auto;
}
.add-box {
display: block;
box-sizing: border-box;
font-size: 25upx;
padding-top: 30upx;
border: 1upx solid #ccc;
width: 200upx;
height: 200upx;
text-align: center;
margin: 0 auto;
color:#ccc;
}
.img-box .pic {
display: block;
width: 100%;
height: 100%;
}
.img-box .delete-icon {
position: absolute;
top: 0upx;
right: 0upx;
z-index: 2upx;
width: 40upx;
height: 40upx;
}
.add-btn {
display: inline-block;
width: 80upx;
height: 80upx;
}
.picker-content {
height: 90upx;
line-height: 90upx;
padding: 0 25upx;
font-size: 30upx;
text-align: right;
}
.save-btn {
position: fixed;
width: 100%;
bottom: 0;
left: 0;
height: 100upx;
line-height: 100upx;
text-align: center;
font-size: 32upx;
background-color: #03A9F4;
color:white;
}
/* 提示信息 */
.msg-remind-input{
height:85upx;line-height:85upx;font-size:28upx;
}
.msg-remind-btn{
width:150upx;height:60upx;line-height:60upx;text-align:center;font-size:26upx;border:1upx solid #eee;border-radius:10upx;
}
.trangle{
display:inline-block;
border-top: 15upx solid;
border-right: 8upx solid;
border-left: 8upx solid;
border-color: black transparent transparent transparent;
}
\ No newline at end of file
<template>
<view>
<view style="background:white;">
<!-- <view class="set-info-title">小程序名称设置</view> -->
<view class="flex-a-c set-info-item">
<view class="item-name">
<text>姓名</text>
<text style="color:red;">*</text>
<!-- <image class="remind-icon" mode="aspectFit" style="" src=""></image> -->
</view>
<view class="flex1">
<input name="nickName" value="" class="item-iput"
placeholder="请输入姓名"></input>
</view>
</view>
<view class="flex-a-c set-info-item">
<view class="item-name">
<text>地址</text>
<text style="color:red;">*</text>
<!-- <image class="remind-icon" mode="aspectFit" style="" src=""></image> -->
</view>
<view class="flex1">
<input name="nickName" value="" class="item-iput"
placeholder="请输入居住地址"></input>
</view>
</view>
<view class="flex-a-c set-info-item">
<view class="item-name">
<text>伤残等级</text>
<text style="color:red;">*</text>
<!-- <image class="remind-icon" mode="aspectFit" style="" src=""></image> -->
</view>
<view class="flex1">
<picker @change="bindPickerChange" :value="index" :range="arrayHurt" range-key="name">
<view class="flex-a-c" style="justify-content:flex-end;">
<view class="picker-content" style=''>{{arrayHurt[index].name}}</view>
<view class="trangle"></view>
</view>
</picker>
</view>
</view>
<view class="flex-a-c set-info-item">
<view class="item-name">
<text>伤残类别</text>
<text style="color:red;">*</text>
<!-- <image class="remind-icon" mode="aspectFit" style="" src=""></image> -->
</view>
<view class="flex1">
<picker bindchange="cat1Change" value="" range="" range-key="name">
<view class="flex-a-c" style="justify-content:flex-end;">
<view class="picker-content" style=''>意外</view>
<view class="trangle"></view>
</view>
</picker>
</view>
</view>
<view class="flex-a-c set-info-item">
<view class="item-name">
<text>项目类型</text>
<text style="color:red;">*</text>
<!-- <image class="remind-icon" mode="aspectFit" style="" src=""></image> -->
</view>
<view class="flex1">
<picker bindchange="cat1Change" value="" range="" range-key="name">
<view class="flex-a-c" style="justify-content:flex-end;">
<view class="picker-content" style=''>公益服务</view>
<view class="trangle"></view>
</view>
</picker>
</view>
</view>
<!-- <view class="flex set-info-item set-info-pad">
<view class="item-name">
<text>上传附件</text>
<text style="color:red;">*</text>
</view>
<view class="flex1">
<view class="img-box" style=''>
<image class="pic" style='' src='../../../images/test/banner1.jpg'></image>
<image class="delete-icon" style='' src='../../../images/total/delete.png'></image>
</view>
<block wx:if="{{licImage!=null}}">
<view class="img-box" style=''>
<image class="pic" style='' src=''></image>
<image bindtap='deleteImage' class="delete-icon" style='' src=''></image>
</view>
</block>
<view class="add-box">
<image class="add-btn" style='' src=''></image>
<view>添加</view>
</view>
</view>
</view> -->
<!-- 设置名称 -->
<!-- <view class="flex-a-c" style="padding:0 35rpx;">
<input class="flex1 msg-remind-input" disabled="true" placeholder="小程序名称未设置"></input>
<view class="msg-remind-btn" style="">设置名称</view>
</view>
<view class="set-info-title">小程序介绍设置</view>
<view class="flex set-intro-item">
<view class="item-name">
<text>小程序介绍\n</text>
<text class="into-num">不超过120个字符</text>
<image class="remind-icon" mode="aspectFit" style="" src=""></image>
</view>
<view class="flex1">
<view class="intro-holder">请输入小程序介绍</view>
</view>
</view> -->
<!-- <view class="area-view" style="">
<textarea name="signature" maxlength="120" class="intro-area" placeholder="请输入小程序介绍,不超过120个字符"></textarea>
</view>
<view class="flex-a-c" style="padding:0 35rpx;">
<input class="flex1 msg-remind-input" disabled="true" placeholder="小程序介绍未设置"></input>
<view class="msg-remind-btn" style="">设置介绍</view>
</view> -->
<!-- <view class="set-info-title">小程序图标设置</view>
<view class="flex set-info-item set-info-pad">
<view class="item-name">
<text>小程序图标\n</text>
<text class="into-num">144px*144px</text>
<image class="remind-icon" mode="aspectFit" style="" src=""></image>
</view>
<view class="flex1">
<view class="img-box" style=''>
<image class="pic" style='' src='../../../images/test/banner1.jpg'></image>
<image class="delete-icon" style='' src='../../../images/total/delete.png'></image>
</view>
<view class="add-box">
<image class="add-btn" style='' src=''></image>
<view>添加</view>
</view>
</view>
</view>
<view class="flex-a-c" style="padding:0 35rpx;">
<input class="flex1 msg-remind-input" disabled="true" placeholder="小程序图标未设置"></input>
<view class="msg-remind-btn" style="">设置图标</view>
</view> -->
<!-- <view class="set-info-title">小程序类目设置</view>
<view class="flex-a-c set-info-item">
<view class="item-name">
<text>选择一级类目</text>
<image class="remind-icon" mode="aspectFit" style="" src=""></image>
</view>
<view class="flex1">
<picker bindchange="cat1Change" value="" range="" range-key="name">
<view class="flex-a-c" style="justify-content:flex-end;">
<view class="picker-content" style=''>ggg</view>
<view class="trangle"></view>
</view>
</picker>
</view>
</view>
<view class="flex-a-c set-info-item">
<view class="item-name">
<text>选择二级类目</text>
<image class="remind-icon" mode="aspectFit" style="" src=""></image>
</view>
<view class="flex1">
<picker class="" style='' bindchange="cat2Change" value="" range="" range-key="name">
<view class="flex-a-c" style="justify-content:flex-end;">
<view class="picker-content" style=''>bb</view>
<view class="trangle"></view>
</view>
</picker>
</view>
</view>
<view class="flex-a-c" style="padding:0 35rpx;">
<input class="flex1 msg-remind-input" disabled="true" placeholder="小程序类目未设置"></input>
<view class="msg-remind-btn" style="">设置类目</view>
</view> -->
<!-- <view class="flex set-info-item set-info-pad">
<view class="item-name">
<text>营业执照\n</text>
<text class="into-num">小程序申请单位的营业执照</text>
<image class="remind-icon" mode="aspectFit" style="" src="../../../images/total/star.png"></image>
</view>
<view class="flex1">
<block wx:if="{{licImage!=null}}">
<view class="img-box" style=''>
<image class="pic" style='' src='{{licImage}}'></image>
<image bindtap='deleteImage' class="delete-icon" style='' src='../../../images/total/delete.png'></image>
</view>
</block>
<view class="add-box">
<image bindtap="uploadLic" class="add-btn" style='' src='../../../images/total/add.png'></image>
<view >选择图片</view>
</view>
</view>
</view> -->
<button style="background-color: #CA0000;" class="save-btn">确定</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
arrayHurt: [{name:'一级'},{name: '二级'}, {name:'三级'}, {name:'四级'}],
index: 0,
}
},
methods: {
bindPickerChange: function(e) {
console.log('picker发送选择改变,携带值为:' + e.detail.value)
this.index = e.detail.value
},
}
}
</script>
<style>
@import url("service-apl.css");
</style>
<template>
<view class="">
<view class="center">
<view class="logo" @click="bindLogin" :hover-class="!hasLogin ? 'logo-hover' : ''">
<image class="logo-img" :src="avatarUrl"></image>
<view class="logo-title">
<text class="uer-name">Hi,{{hasLogin ? userName : '您未登录'}}</text>
<text class="go-login navigat-arrow" v-if="!hasLogin">&#xe65e;</text>
</view>
</view>
<view class="center-list" v-for="item in navList" :key="item.id">
<view class="center-list-item border-bottom" v-for="item2 in item.barList" :key="item2.id" @click="goDetailPage(item2)">
<text class="list-icon">&#xe60b;</text>
<text class="list-text">{{item2.name}}</text>
<text class="navigat-arrow">&#xe65e;</text>
</view>
<!-- <view class="center-list-item">
<text class="list-icon">&#xe65f;</text>
<text class="list-text">申请服务</text>
<text class="navigat-arrow">&#xe65e;</text>
</view> -->
</view>
<!-- <view class="center-list">
<view class="center-list-item border-bottom">
<text class="list-icon">&#xe60f;</text>
<text class="list-text">帐号管理</text>
<text class="navigat-arrow">&#xe65e;</text>
</view>
<view class="center-list-item">
<text class="list-icon">&#xe639;</text>
<text class="list-text">新消息通知</text>
<text class="navigat-arrow">&#xe65e;</text>
</view>
</view>
<view class="center-list">
<view class="center-list-item border-bottom">
<text class="list-icon">&#xe60b;</text>
<text class="list-text">帮助与反馈</text>
<text class="navigat-arrow">&#xe65e;</text>
</view>
<view class="center-list-item">
<text class="list-icon">&#xe65f;</text>
<text class="list-text">服务条款及隐私</text>
<text class="navigat-arrow">&#xe65e;</text>
</view>
</view>
<view class="center-list">
<view class="center-list-item">
<text class="list-icon">&#xe614;</text>
<text class="list-text">关于应用</text>
<text class="navigat-arrow">&#xe65e;</text>
</view>
</view> -->
<view class="btn-row">
<button v-if="hasLogin" class="primary" type="primary" @tap="bindLogout">退出登录</button>
</view>
</view>
</view>
</template>
<script>
import {
mapState,
mapMutations
} from 'vuex'
export default {
data() {
return {
avatarUrl: "../../static/img/logo.png",
navList: [
{
id: 1,
barList: [{
id: 1,
name: '满意度评价',
url: '/pages/evaluate/evaluate'
},
{
id: 2,
name: '申请服务',
url: '/pages/service-apl/service-apl'
}
],
},
{
id: 2,
barList: [{
id: 3,
name: '历史评价',
url: '/pages/evaluate-history/evaluate-history'
},
{
id: 4,
name: '服务申请记录',
url: '/pages/service-apl-history/service-apl-history'
}
],
},
]
}
},
computed: {
...mapState(['hasLogin', 'forcedLogin', 'userName'])
},
methods: {
...mapMutations(['logout']),
bindLogin() {
uni.navigateTo({
url: '../login/login',
});
},
bindLogout() {
const loginType = uni.getStorageSync('login_type')
if (loginType === 'local') {
this.logout();
if (this.forcedLogin) {
uni.reLaunch({
url: '../login/login',
});
}
return
}
uniCloud.callFunction({
name: 'user-center',
data: {
action: 'logout'
},
success: (e) => {
console.log('logout success', e);
if (e.result.code == 0) {
this.logout();
uni.removeStorageSync('uniIdToken')
uni.removeStorageSync('username')
/**
* 如果需要强制登录跳转回登录页面
*/
if (this.forcedLogin) {
uni.reLaunch({
url: '../login/login',
});
}
} else {
uni.showModal({
content: e.result.msg,
showCancel: false
})
console.log('登出失败', e);
}
},
fail(e) {
uni.showModal({
content: JSON.stringify(e),
showCancel: false
})
}
})
},
// 路径跳转start
goDetailPage(e) {
let path = e.url;
// let url ='/pages/'+path+'/'+path;
uni.navigateTo({
url: path
});
}
// 路径跳转end
}
}
</script>
<style>
@font-face {
font-family: texticons;
font-weight: normal;
font-style: normal;
src: url('https://at.alicdn.com/t/font_984210_5cs13ndgqsn.ttf') format('truetype');
}
page,
view {
display: flex;
}
page {
background-color: #f8f8f8;
}
button {
width: 100%;
}
.center {
flex-direction: column;
}
.logo {
width: 750rpx;
height: 240rpx;
padding: 20rpx;
box-sizing: border-box;
background-color: #CA0000;
flex-direction: row;
align-items: center;
}
.logo-hover {
opacity: 0.8;
}
.logo-img {
width: 150rpx;
height: 150rpx;
border-radius: 150rpx;
}
.logo-title {
height: 150rpx;
flex: 1;
align-items: center;
justify-content: space-between;
flex-direction: row;
margin-left: 20rpx;
}
.uer-name {
height: 60rpx;
line-height: 60rpx;
font-size: 38rpx;
color: #FFFFFF;
}
.go-login.navigat-arrow {
font-size: 38rpx;
color: #FFFFFF;
}
.login-title {
height: 150rpx;
align-items: self-start;
justify-content: center;
flex-direction: column;
margin-left: 20rpx;
}
.center-list {
background-color: #FFFFFF;
margin-top: 20rpx;
width: 750rpx;
flex-direction: column;
}
.center-list-item {
height: 90rpx;
width: 750rpx;
box-sizing: border-box;
flex-direction: row;
padding: 0rpx 20rpx;
}
.border-bottom {
border-bottom-width: 1rpx;
border-color: #c8c7cc;
border-bottom-style: solid;
}
.list-icon {
width: 40rpx;
height: 90rpx;
line-height: 90rpx;
font-size: 34rpx;
color: red;
text-align: center;
font-family: texticons;
margin-right: 20rpx;
}
.list-text {
height: 90rpx;
line-height: 90rpx;
font-size: 34rpx;
color: #555;
flex: 1;
text-align: left;
}
.navigat-arrow {
height: 90rpx;
width: 40rpx;
line-height: 90rpx;
font-size: 34rpx;
color: #555;
text-align: right;
font-family: texticons;
}
.myicon{
/* height: 90rpx;
width: 40rpx;
line-height: 90rpx; */
font-size: 34rpx;
color:red;
/* text-align: right; */
font-family: myicons;
}
</style>
// 管理账号信息
const USERS_KEY = 'USERS_KEY';
const STATE_KEY = 'STATE_KEY';
const getUsers = function() {
let ret = '';
ret = uni.getStorageSync(USERS_KEY);
if (!ret) {
ret = '[]';
}
return JSON.parse(ret);
}
const addUser = function(userInfo) {
let users = getUsers();
users.push({
account: userInfo.account,
password: userInfo.password
});
uni.setStorageSync(USERS_KEY, JSON.stringify(users));
}
export default {
getUsers,
addUser
}
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
/**
* 是否需要强制登录
*/
forcedLogin: false,
hasLogin: false,
userName: ""
},
mutations: {
login(state, userName) {
state.userName = userName || '新用户';
state.hasLogin = true;
},
logout(state) {
state.userName = "";
state.hasLogin = false;
}
}
})
export default store
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment