提交 3b80dd1a 编写于 作者: DCloud_JSON's avatar DCloud_JSON

Merge branch 'dev' into 'master'

Dev

See merge request !4
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
}
......@@ -39,7 +39,7 @@
{
"path": "uni_modules/uni-id-pages/pages/login/login-withpwd",
"style": {
"navigationBarTitleText": ""
"navigationBarTitleText": ""
}
},
{
......@@ -54,46 +54,61 @@
"navigationBarTitleText": "注册"
}
},
{
"path": "uni_modules/uni-id-pages/pages/register/register-admin",
"style": {
"navigationBarTitleText": "注册管理员账号",
"enablePullDownRefresh": false
}
},
{
"path": "uni_modules/uni-id-pages/pages/register/register-by-email",
"style": {
"navigationBarTitleText": "邮箱验证码注册"
}
},
{
"path": "uni_modules/uni-id-pages/pages/retrieve/retrieve",
"style": {
"navigationBarTitleText": "重置密码"
}
}, {
},
{
"path": "uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email",
"style": {
"navigationBarTitleText": "通过邮箱重置密码"
}
},
{
"path": "uni_modules/uni-id-pages/pages/common/webview/webview",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}, {
"path": "uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd",
"style": {
"navigationBarTitleText": "修改密码",
"enablePullDownRefresh": false
}
}
,{
"path" : "uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd",
"style" :
{
"navigationBarTitleText": "修改密码",
"enablePullDownRefresh": false
}
}
],
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#FFF",
"backgroundColor": "#F8F8F8"
/* #ifdef H5 */
,"navigationStyle": "custom"
/* #endif */
}
,"condition" : { //模式配置,仅开发期间生效
"backgroundColor": "#F8F8F8"
/* #ifdef H5 */
,"navigationStyle": "custom"
/* #endif */
},
"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [
{
"name": "", //模式名称
"path": "", //启动页面,必选
"query": "" //启动参数,在页面的onLoad函数里面得到
}
]
"list": [{
"name": "", //模式名称
"path": "", //启动页面,必选
"query": "" //启动参数,在页面的onLoad函数里面得到
}]
},
"uniIdRouter": {
"loginPage": "uni_modules/uni-id-pages/pages/login/login-withoutpwd",
......@@ -102,4 +117,4 @@
],
"resToLogin": true
}
}
\ No newline at end of file
}
......@@ -46,7 +46,7 @@
},
toUserInfoPage() {
uni.navigateTo({
url: "/uni_modules/uni-id-pages/pages/userinfo/userinfo"
url: "/uni_modules/uni-id-pages/pages/userinfo/userinfo?showLoginManage=true"
})
}
}
......
## 1.0.15(2022-09-19)
- 更新表结构,解决在uni-admin中部分clientDB操作没有权限的问题
## 1.0.14(2022-09-16)
- 修改 配置项`isAdmin`默认值为`false`
## 1.0.13(2022-09-16)
- 新增 管理员注册页面
- 新增 配置项`isAdmin`区分是否为管理端
- 新增 登录成功后自动跳转;跳转优先级:路由携带(`uniIdRedirectUrl`参数) > 返回上一路由 > 跳转首页
- uni-id-co 优化 注册管理员时管理员存在提示文案
## 1.0.12(2022-09-07)
- 修复 getSupportedLoginType判断是否支持微信公众号、PC网页微信扫码登录方式报错的Bug
- 优化 适配pc端样式
- 新增 邮箱验证码注册
- 新增 邮箱验证码找回密码
- 新增 退出登录(全局)回调事件:`uni-id-pages-logout`,支持通过[uni.$on](https://uniapp.dcloud.net.cn/api/window/communication.html#on)监听;
- 调整 抽离退出登录方法至`/uni_modules/uni-id-pages/common/common.js`中,方便在项目其他页面中调用
- 调整 用户中心(路径:`/uni_modules/uni-id-pages/pages/userinfo/userinfo`)默认不再显示退出登录按钮。支持页面传参数`showLoginManage=true`恢复显示
## 1.0.11(2022-09-01)
- 修复 iOS端,一键登录功能卡在showLoading的问题
- 更新 合并密码强度与长度配置 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#config)
- uni-id-co 修复 调用 removeAuthorizedApp 接口报错的Bug
- uni-id-co 新增 管理端接口 updateUser [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#update-user)
- uni-id-co 调整 为兼容旧版本,未配置密码强度时提供最简单的密码规则校验(长度大于6即可)
- uni-id-co 调整 注册、登录时如果携带了token则尝试对此token进行登出操作
- uni-id-co 调整 管理端接口 addUser 增加 mobile、email等参数 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#add-user)
## 1.0.10(2022-08-25)
- 修复 导入uni-id-pages插件时未自动导入uni-open-bridge-common的Bug
## 1.0.9(2022-08-23)
......
import config from '../config'
const uniIdCo = uniCloud.importObject("uni-id-co")
export default {
async logout() {
await uniIdCo.logout()
uni.removeStorageSync('uni_id_token');
uni.setStorageSync('uni_id_token_expired', 0)
uni.redirectTo({
url: config.isAdmin ? '/uni_modules/uni-id-pages/pages/login/login-withpwd': '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
});
// uniIdRouter -> loginPage
uni.$emit('uni-id-pages-logout')
},
}
......@@ -4,6 +4,7 @@ let mixin = {
data() {
return {
config,
uniIdRedirectUrl: '',
isMounted: false
}
},
......@@ -16,28 +17,32 @@ let mixin = {
this.isMounted = true;
},
onLoad(e) {
if (e.is_weixin_redirect) {
uni.showLoading({
mask: true
})
if( window.location.href.includes('#') ){
// 将url通过 ? 分割获取后面的参数字符串 再通过 & 将每一个参数单独分割出来
let paramsArr = window.location.href.split('?')[1].split('&')
paramsArr.forEach(item=>{
let arr = item.split('=')
if(arr[0] == 'code'){
e.code = arr[1]
}
})
}
if (e.is_weixin_redirect) {
uni.showLoading({
mask: true
})
if( window.location.href.includes('#') ){
// 将url通过 ? 分割获取后面的参数字符串 再通过 & 将每一个参数单独分割出来
let paramsArr = window.location.href.split('?')[1].split('&')
paramsArr.forEach(item=>{
let arr = item.split('=')
if(arr[0] == 'code'){
e.code = arr[1]
}
})
}
this.$nextTick(n => {
console.log(this.$refs.uniFabLogin);
console.log(this.$refs.uniFabLogin);
this.$refs.uniFabLogin.login({
code:e.code
}, 'weixin')
})
}
if (e.uniIdRedirectUrl) {
this.uniIdRedirectUrl = decodeURIComponent(e.uniIdRedirectUrl)
}
},
computed: {
needAgreements() {
......@@ -70,8 +75,11 @@ let mixin = {
},
methods: {
loginSuccess(e) {
loginSuccess(e)
loginSuccess({
...e,
uniIdRedirectUrl: this.uniIdRedirectUrl
})
}
}
}
export default mixin
export default mixin
......@@ -2,20 +2,54 @@
padding: 0 60rpx;
}
.login-logo {
display: none;
}
/* #ifndef APP-NVUE */
@media screen and (min-width: 690px) {
.uni-content {
padding: 0;
max-width: 400px;
margin-left: calc(50% - 200px);
/* #ifndef H5 */
padding: 0;
max-width: 300px;
margin-left: calc(50% - 200px);
/* #endif */
/* #ifdef H5 */
margin: 0 auto;
position: relative;
top: 100px;
padding: 30px 40px 80px 40px;
max-width: 450px;
max-height: 450px;
border-radius: 10px;
box-shadow: 0 0 20px #efefef;
background-color: #FFF;
/* #endif */
}
/* #ifdef H5 */
.login-logo {
display: flex;
justify-content: center;
}
.login-logo image {
width: 60px;
height: 60px;
}
.register-back{
display: none;
}
/* #endif */
}
.uni-content view {
box-sizing: border-box;
}
/* #endif */
.title {
/* #ifndef APP-NVUE */
display: flex;
......@@ -61,12 +95,9 @@
margin: 15px 0 0 0;
color: #FFF !important;
border-radius: 5px;
}
/*
.uni-btn::after{
display: none;
}
.uni-btn[disabled]{
background-color: $uni-color-primary !important;
opacity: 0.3;
}*/
\ No newline at end of file
}
.uni-body.uni_modules-uni-id-pages-pages-login-login-withoutpwd{
height: auto !important;
}
\ No newline at end of file
import pagesJson from '@/pages.json'
export default function(e = {}) {
const {
showToast = true, toastText = '登录成功', autoBack = true
showToast = true, toastText = '登录成功', autoBack = true, uniIdRedirectUrl = ''
} = e
console.log({
toastText,
......@@ -14,24 +16,36 @@ export default function(e = {}) {
}
if (autoBack) {
let delta = 0; //判断需要返回几层
let pages = getCurrentPages();
let pages = getCurrentPages();
uni.$emit('uni-id-pages-login-success',pages)
console.log(pages);
console.log(pages);
pages.forEach((page, index) => {
if (pages[pages.length - index - 1].route.split('/')[3] == 'login') {
delta++
}
})
console.log('判断需要返回几层:',pages, delta);
// #ifdef H5
if(e.loginType == 'weixin'){
console.log('window.history',window.history);
return window.history.go(-3)
}
// #endif
})
console.log('判断需要返回几层:',pages, delta);
if (uniIdRedirectUrl) {
return uni.reLaunch({
url: uniIdRedirectUrl
})
}
// #ifdef H5
if(e.loginType == 'weixin'){
console.log('window.history',window.history);
return window.history.go(-3)
}
// #endif
if (delta) {
const page = pagesJson.pages[0]
return uni.reLaunch({
url: `/${page.path}`
})
}
uni.navigateBack({
delta
})
}
}
}
// 导入配置
import config from '@/uni_modules/uni-id-pages/config.js'
const passwordLength = config.password.length
const passwordStrength = config.password.strength
const {passwordStrength} = config
let minPasswordLength = 6
let maxPasswordLength = 20
if (passwordLength) {
if (passwordLength[0]) {
minPasswordLength = passwordLength[0]
}
if (passwordLength[1]) {
maxPasswordLength = passwordLength[1]
}
}
// 密码强度表达式
const passwordRules = {
// 密码必须包含大小写字母、数字和特殊符号
......@@ -37,11 +26,6 @@ const ERROR = {
strong: '密码必须包含字母、数字和特殊符号,密码长度必须在8-16位之间',
medium: '密码必须为字母、数字和特殊符号任意两种的组合,密码长度必须在8-16位之间',
weak: '密码必须包含字母,密码长度必须在6-16位之间'
},
passwordLengthError: {
normal: '密码长度必须在' + minPasswordLength + '-' + maxPasswordLength + '位之间',
minLimit: '密码长度不得少于' + minPasswordLength + '',
maxLimit: '密码长度不得超过' + maxPasswordLength + ''
}
}
......@@ -52,16 +36,6 @@ function validPwd(password) {
return ERROR.passwordStrengthError[passwordStrength]
}
}
//长度校验
if (passwordLength) {
if (passwordLength[0] && password.length < passwordLength[0]) {
return ERROR.passwordLengthError.minLimit
}
if (passwordLength[1] && password.length > passwordLength[1]) {
return ERROR.passwordLengthError.maxLimit
}
}
return true
}
......@@ -106,8 +80,6 @@ function getPwdRules(pwdName = 'password', rePwdName = 'password2') {
export default {
ERROR,
minPasswordLength,
maxPasswordLength,
validPwd,
getPwdRules
}
<template>
<view>
<uni-captcha :focus="focusCaptchaInput" ref="captcha" scene="send-email-code" v-model="captcha" />
<view class="box">
<uni-easyinput :focus="focusEmailCodeInput" @blur="focusEmailCodeInput = false" type="number" class="input-box" :inputBorder="false" v-model="modelValue" maxlength="6"
placeholder="请输入邮箱验证码">
</uni-easyinput>
<view class="short-code-btn" hover-class="hover" @click="start">
<text class="inner-text" :class="reverseNumber==0?'inner-text-active':''">{{innerText}}</text>
</view>
</view>
</view>
</template>
<script>
function debounce(func, wait) {
let timer;
wait = wait || 500;
return function() {
let context = this;
let args = arguments;
if (timer) clearTimeout(timer);
let callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait)
if (callNow) func.apply(context, args);
}
}
/**
* email-code-form
* @description 获取邮箱验证码组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=
* @property {Number} count 倒计时时长 s
* @property {String} email 邮箱
* @property {String} type = [login-by-email-code|reset-pwd-by-email-code|bind-email] 验证码类型,用于防止不同功能的验证码混用,目前支持的类型login登录、register注册、bind绑定邮箱、unbind解绑邮箱
* @property {false} focusCaptchaInput = [true|false] 验证码输入框是否默认获取焦点
*/
export default {
name: "uni-email-code-form",
model: {
prop: 'modelValue',
event: 'update:modelValue'
},
props: {
event: ['update:modelValue'],
/**
* 倒计时时长 s
*/
count: {
type: [String, Number],
default: 60
},
/**
* 邮箱
*/
email: {
type: [String],
default: ''
},
/*
验证码类型,用于防止不同功能的验证码混用,目前支持的类型login登录、register注册、bind绑定邮箱、unbind解绑邮箱
*/
type: {
type: String,
default () {
return 'register'
}
},
/*
验证码输入框是否默认获取焦点
*/
focusCaptchaInput: {
type: Boolean,
default () {
return false
}
},
},
data() {
return {
captcha: "",
reverseNumber: 0,
reverseTimer: null,
modelValue: "",
focusEmailCodeInput:false
};
},
watch: {
captcha(value, oldValue) {
if (value.length == 4 && oldValue.length != 4) {
this.start()
}
},
modelValue(value) {
// TODO 兼容 vue2
this.$emit('input', value);
// TODO 兼容 vue3
this.$emit('update:modelValue', value)
}
},
computed: {
innerText() {
if (this.reverseNumber == 0) return "获取邮箱验证码";
return "重新发送" + '(' + this.reverseNumber + 's)';
}
},
created() {
this.initClick();
},
methods: {
getImageCaptcha(focus) {
this.$refs.captcha.getImageCaptcha(focus)
},
initClick() {
this.start = debounce(() => {
if (this.reverseNumber != 0) return;
this.sendMsg();
})
},
sendMsg() {
if (this.captcha.length != 4) {
this.$refs.captcha.focusCaptchaInput = true
return uni.showToast({
title: '请先输入图形验证码',
icon: 'none'
});
}
if(!this.email) return uni.showToast({
title: "请输入邮箱",
icon: 'none'
});
let reg_email = /@/;
if (!reg_email.test(this.email)) return uni.showToast({
title: "邮箱格式错误",
icon: 'none'
});
const uniIdCo = uniCloud.importObject("uni-id-co", {
customUI: true
})
console.log('uniIdCo', uniIdCo)
console.log('sendEmailCode',{
"email": this.email,
"scene": this.type,
"captcha": this.captcha
});
uniIdCo.sendEmailCode({
"email": this.email,
"scene": this.type,
"captcha": this.captcha
}).then(result => {
console.log(result.code);
uni.showToast({
title: "邮箱验证码发送成功",
icon: 'none'
});
this.reverseNumber = Number(this.count);
this.getCode();
}).catch(e => {
console.log(JSON.stringify(e));
if (e.code == "uni-id-invalid-mail-template") {
this.modelValue = "123456"
uni.showToast({
title: '已启动测试模式,详情【控制台信息】',
icon: 'none',
duration: 3000
});
console.warn(e.message);
} else {
this.getImageCaptcha()
this.captcha = ""
uni.showToast({
title: e.message,
icon: 'none'
});
}
})
},
getCode() {
if (this.reverseNumber == 0) {
clearTimeout(this.reverseTimer);
this.reverseTimer = null;
return;
}
this.reverseNumber--;
this.reverseTimer = setTimeout(() => {
this.getCode();
}, 1000)
}
}
}
</script>
<style lang="scss" scoped>
.box {
position: relative;
margin-top: 10px;
}
.short-code-btn {
padding: 0;
position: absolute;
top: 0;
right: 8px;
width: 260rpx;
max-width: 130px;
height: 44px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
}
.inner-text {
font-size: 14px;
color: #AAAAAA;
}
.inner-text-active {
color: #04498c;
}
.captcha {
width: 350rpx;
}
.input-box {
margin: 0;
padding: 4px;
background-color: #F8F8F8;
font-size: 14px;
}
.box ::v-deep .content-clear-icon {
margin-right: 100px;
}
.box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
</style>
......@@ -15,12 +15,12 @@
<script>
import config from '@/uni_modules/uni-id-pages/config.js'
//前一个窗口的页面地址。控制点击切换快捷登录方式是创建还是返回
import loginSuccess from '../../common/loginSuccess.js';
import loginSuccess from '../../common/loginSuccess.js';
const db = uniCloud.database();
const usersTable = db.collection('uni-id-users')
let allServicesList = []
let allServicesList = []
export default {
computed: {
agreements() {
......@@ -42,17 +42,17 @@
]
},
agree: {
get() {
get() {
return this.getParentComponent().agree
},
set(agree) {
console.log('setAgree', agree);
set(agree) {
console.log('setAgree', agree);
return this.getParentComponent().agree = agree
}
}
},
data() {
return {
data() {
return {
servicesList: [{
"id": "username",
"text": "账号登录",
......@@ -232,7 +232,7 @@
}
},
async login_before(type, navigateBack = true) {
console.log(type);
console.log(type);
//提示空实现
if (["qq",
"xiaomi",
......@@ -288,46 +288,46 @@
}
//判断是否需要弹出隐私协议授权框
console.log(type, this.agree);
let needAgreements = (config?.agreements?.scope || []).includes('register')
console.log(type, this.agree);
let needAgreements = (config?.agreements?.scope || []).includes('register')
console.log({
needAgreements
});
if (type != 'univerify' && needAgreements && !this.agree) {
if (type != 'univerify' && needAgreements && !this.agree) {
let agreementsRef = this.getParentComponent().$refs.agreements
return agreementsRef.popup(() => {
return agreementsRef.popup(() => {
console.log(type, navigateBack);
this.login_before(type, navigateBack)
})
}
// #ifdef H5
if(type == 'weixin'){
// console.log('开始微信网页登录');
let redirectUrl = location.protocol +'//'+
document.domain +
(window.location.href.includes('#')?'/#':'') +
'/uni_modules/uni-id-pages/pages/login/login-withoutpwd?is_weixin_redirect=true&type=weixin'
console.log('redirectUrl----',redirectUrl);
let ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger'){
// console.log('在微信公众号内');
return window.open(`https://open.weixin.qq.com/connect/oauth2/authorize?
appid=${config.appid.weixin.h5}
&redirect_uri=${encodeURIComponent(redirectUrl)}
&response_type=code
&scope=snsapi_userinfo
&state=STATE&connect_redirect=1#wechat_redirect`);
}else{
// console.log('非微信公众号内');
return location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=${config.appid.weixin.web}
&redirect_uri=${encodeURIComponent(redirectUrl)}
&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect`
}
}
// #endif
}
// #ifdef H5
if(type == 'weixin'){
// console.log('开始微信网页登录');
let redirectUrl = location.protocol +'//'+
document.domain +
(window.location.href.includes('#')?'/#':'') +
'/uni_modules/uni-id-pages/pages/login/login-withoutpwd?is_weixin_redirect=true&type=weixin'
console.log('redirectUrl----',redirectUrl);
let ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger'){
// console.log('在微信公众号内');
return window.open(`https://open.weixin.qq.com/connect/oauth2/authorize?
appid=${config.appid.weixin.h5}
&redirect_uri=${encodeURIComponent(redirectUrl)}
&response_type=code
&scope=snsapi_userinfo
&state=STATE&connect_redirect=1#wechat_redirect`);
}else{
// console.log('非微信公众号内');
return location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=${config.appid.weixin.web}
&redirect_uri=${encodeURIComponent(redirectUrl)}
&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect`
}
}
// #endif
uni.showLoading({
mask: true
......@@ -419,7 +419,7 @@
}
})
},
login(params, type) { //联网验证登录
login(params, type) { //联网验证登录
console.log('执行登录开始----');
console.log({
params,
......@@ -446,9 +446,9 @@
})
return this.$refs.userProfile.open(result.uid)
}
// #endif
// #ifdef H5
result.loginType = type
// #endif
// #ifdef H5
result.loginType = type
// #endif
loginSuccess(result)
})
......@@ -511,10 +511,17 @@
flex-wrap: wrap;
width: 750rpx;
justify-content: space-around;
position: fixed;
bottom: 10rpx;
position: fixed;
left: 0;
}
.item {
flex-direction: column;
justify-content: center;
align-items: center;
height: 200rpx;
cursor: pointer;
}
/* #ifndef APP-NVUE */
@media screen and (min-width: 690px) {
......@@ -522,17 +529,20 @@
max-width: 500px;
margin-left: calc(50% - 250px);
}
.item {
height: 160rpx;
}
}
@media screen and (max-width: 690px) {
.fab-login-box {
bottom: 10rpx;
}
}
/* #endif */
.item {
flex-direction: column;
justify-content: center;
align-items: center;
height: 200rpx;
cursor: pointer;
}
.logo {
width: 60rpx;
......
export default {
//调试模式
"debug": true,
"debug": false,
/*
登录类型 未列举到的或运行环境不支持的,将被自动隐藏。
如果需要在不同平台有不同的配置,直接用条件编译即可
*/
"isAdmin": false, // 区分管理端与用户端
"loginTypes": [
// "qq",
// "xiaomi",
......@@ -44,15 +45,12 @@ export default {
}
},
/**
* 密码强度
* super(超强:密码必须包含大小写字母、数字和特殊符号
* strong(强: 密码必须包含字母、数字和特殊符号)
* medium (中:密码必须为字母、数字和特殊符号任意两种的组合)
* weak(弱:密码必须包含字母)
* 密码强度
* super(超强:密码必须包含大小写字母、数字和特殊符号,长度范围:8-16位之间)
* strong(强: 密密码必须包含字母、数字和特殊符号,长度范围:8-16位之间)
* medium (中:密码必须为字母、数字和特殊符号任意两种的组合,长度范围:8-16位之间)
* weak(弱:密码必须包含字母和数字,长度范围:6-16位之间
* 为空或false则不验证密码强度
*/
"password": {
"strength": "medium",
"length": [6, 20] //密码长度,默认在6-20位之间
}
}
"passwordStrength":"medium"
}
{
"id": "uni-id-pages",
"displayName": "uni-id-pages",
"version": "1.0.10",
"version": "1.0.15",
"description": "云端一体简单、统一、可扩展的用户中心页面模版",
"keywords": [
"用户管理",
......@@ -48,7 +48,7 @@
"uni-popup",
"uni-scss",
"uni-transition",
"uni-open-bridge-common"
"uni-open-bridge-common"
],
"encrypt": [],
"platforms": {
......
<!-- 短信验证码登录页 -->
<template>
<view class="uni-content">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title">请输入验证码</text>
<text class="tip">先输入图形验证码,再获取短信验证码</text>
......@@ -21,6 +24,7 @@
"code": "",
"phone": "",
"captcha": "",
"logo": "/static/logo.png"
}
},
computed: {
......
<!-- 免密登录页 -->
<template>
<view class="uni-content">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title">请选择登录方式</text>
<!-- 快捷登录框 当url带参数时有效 -->
......@@ -36,7 +39,8 @@
return {
type: "", //快捷登录方式
phone: "", //手机号码
focusPhone:false
focusPhone:false,
logo: "/static/logo.png"
}
},
computed: {
......@@ -177,7 +181,7 @@
}
.quickLogin {
width: 650rpx;
// width: 650rpx;
height: 350px;
align-items: center;
justify-content: center;
......@@ -186,6 +190,9 @@
.quickLoginBtn {
margin: 20px 0;
width: 450rpx;
/* #ifndef APP-NVUE */
max-width: 230px;
/* #endif */
height: 82rpx;
}
......@@ -193,4 +200,10 @@
margin-top: -15px;
margin-bottom: 20px;
}
@media screen and (min-width: 690px) {
.quickLogin{
height: auto;
}
}
</style>
<!-- 账号密码登录页 -->
<template>
<view class="uni-content">
<!-- 顶部文字 -->
<text class="title title-box">账号密码登录</text>
<uni-forms>
<uni-forms-item name="username">
<uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box" :inputBorder="false" v-model="username" placeholder="请输入手机号/用户名" />
</uni-forms-item>
<uni-forms-item name="password">
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable type="password" :inputBorder="false" v-model="password"
placeholder="请输入密码" />
</uni-forms-item>
</uni-forms>
<uni-captcha v-if="needCaptcha" focus ref="captcha" scene="login-by-pwd" v-model="captcha" />
<!-- 带选择框的隐私政策协议组件 -->
<uni-id-pages-agreements scope="login" ref="agreements" ></uni-id-pages-agreements>
<button class="uni-btn" type="primary" @click="pwdLogin">登录</button>
<!-- 忘记密码 -->
<view class="link-box">
<view>
<text class="forget">忘记了?</text>
<text class="link" @click="toRetrievePwd">找回密码</text>
</view>
<text class="link" @click="toRegister">注册账号</text>
</view>
<!-- 悬浮登录方式组件 -->
<uni-id-pages-fab-login ref="uniFabLogin"></uni-id-pages-fab-login>
</view>
<view class="uni-content">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title title-box">账号密码登录</text>
<uni-forms>
<uni-forms-item name="username">
<uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box" :inputBorder="false" v-model="username" placeholder="请输入手机号/用户名/邮箱" />
</uni-forms-item>
<uni-forms-item name="password">
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable type="password" :inputBorder="false" v-model="password"
placeholder="请输入密码" />
</uni-forms-item>
</uni-forms>
<uni-captcha v-if="needCaptcha" focus ref="captcha" scene="login-by-pwd" v-model="captcha" />
<!-- 带选择框的隐私政策协议组件 -->
<uni-id-pages-agreements scope="login" ref="agreements" ></uni-id-pages-agreements>
<button class="uni-btn" type="primary" @click="pwdLogin">登录</button>
<!-- 忘记密码 -->
<view class="link-box">
<view v-if="!config.isAdmin">
<text class="forget">忘记了?</text>
<text class="link" @click="toRetrievePwd">找回密码</text>
</view>
<text class="link" @click="toRegister">{{config.isAdmin ? '注册管理员账号': '注册账号'}}</text>
<!-- <text class="link" @click="toRegister" v-if="!config.isAdmin">注册账号</text> -->
</view>
<!-- 悬浮登录方式组件 -->
<uni-id-pages-fab-login ref="uniFabLogin"></uni-id-pages-fab-login>
</view>
</template>
<script>
import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js';
const uniIdCo = uniCloud.importObject("uni-id-co",{
errorOptions:{
type:'toast'
}
})
export default {
mixins: [mixin],
data() {
return {
"password": "",
"username": "",
"captcha": "",
"needCaptcha": false,
"focusUsername":false,
"focusPassword":false
}
},
onShow() {
// #ifdef H5
document.onkeydown = event => {
var e = event || window.event;
if (e && e.keyCode == 13) { //回车键的键值为13
this.pwdLogin()
}
};
// #endif
},
methods: {
// 页面跳转,找回密码
toRetrievePwd() {
let url = '/uni_modules/uni-id-pages/pages/retrieve/retrieve'
//如果刚好用户名输入框的值为手机号码,就把它传到retrieve页面,根据该手机号找回密码
if (/^1\d{10}$/.test(this.username)) {
url += `?phoneNumber=${this.username}`
}
uni.navigateTo({
url
})
},
/**
* 密码登录
*/
pwdLogin() {
if(!this.password.length){
this.focusPassword = true
return uni.showToast({
title: '请输入密码',
icon: 'none'
});
}
if(!this.username.length){
this.focusUsername = true
return uni.showToast({
title: '请输入手机号/用户名',
icon: 'none'
});
}
if(this.needCaptcha && this.captcha.length!=4){
this.$refs.captcha.getImageCaptcha()
return uni.showToast({
title: '请输入验证码',
icon: 'none'
});
}
if (this.needAgreements && !this.agree) {
return this.$refs.agreements.popup(this.pwdLogin)
}
let data = {
"password": this.password,
"captcha": this.captcha
}
if (/^1\d{10}$/.test(this.username)) {
data.mobile = this.username
}else{
data.username = this.username
}
uniIdCo.login(data).then(e => {
this.loginSuccess(e)
}).catch(e => {
if(e.errCode == 'uni-id-captcha-required'){
this.needCaptcha = true
}else if(this.needCaptcha){
//登录失败,自动重新获取验证码
this.$refs.captcha.getImageCaptcha()
}
})
},
/* 前往注册 */
toRegister(e) {
console.log(e);
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/register/register'
})
}
import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js';
const uniIdCo = uniCloud.importObject("uni-id-co",{
errorOptions:{
type:'toast'
}
})
export default {
mixins: [mixin],
data() {
return {
"password": "",
"username": "",
"captcha": "",
"needCaptcha": false,
"focusUsername":false,
"focusPassword":false,
"logo": "/static/logo.png"
}
},
onShow() {
// #ifdef H5
document.onkeydown = event => {
var e = event || window.event;
if (e && e.keyCode == 13) { //回车键的键值为13
this.pwdLogin()
}
};
// #endif
},
methods: {
// 页面跳转,找回密码
toRetrievePwd() {
let url = '/uni_modules/uni-id-pages/pages/retrieve/retrieve'
//如果刚好用户名输入框的值为手机号码,就把它传到retrieve页面,根据该手机号找回密码
if (/^1\d{10}$/.test(this.username)) {
url += `?phoneNumber=${this.username}`
}
uni.navigateTo({
url
})
},
/**
* 密码登录
*/
pwdLogin() {
if(!this.password.length){
this.focusPassword = true
return uni.showToast({
title: '请输入密码',
icon: 'none'
});
}
if(!this.username.length){
this.focusUsername = true
return uni.showToast({
title: '请输入手机号/用户名/邮箱',
icon: 'none'
});
}
if(this.needCaptcha && this.captcha.length!=4){
this.$refs.captcha.getImageCaptcha()
return uni.showToast({
title: '请输入验证码',
icon: 'none'
});
}
if (this.needAgreements && !this.agree) {
return this.$refs.agreements.popup(this.pwdLogin)
}
let data = {
"password": this.password,
"captcha": this.captcha
}
if (/^1\d{10}$/.test(this.username)) {
data.mobile = this.username
}else if(/@/.test(this.username)) {
data.email = this.username
}else{
data.username = this.username
}
uniIdCo.login(data).then(e => {
this.loginSuccess(e)
}).catch(e => {
if(e.errCode == 'uni-id-captcha-required'){
this.needCaptcha = true
}else if(this.needCaptcha){
//登录失败,自动重新获取验证码
this.$refs.captcha.getImageCaptcha()
}
})
},
/* 前往注册 */
toRegister() {
uni.navigateTo({
url: this.config.isAdmin ? '/uni_modules/uni-id-pages/pages/register/register-admin': '/uni_modules/uni-id-pages/pages/register/register',
fail(e) {
console.error(e);
}
}
})
}
}
}
</script>
<style lang="scss" scoped>
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
@media screen and (min-width: 690px) {
.forget{
font-size: 12px;
color: #8a8f8b;
}
}
.forget{
font-size: 12px;
color: #8a8f8b;
}
.link-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
margin-top: 20px;
}
.link-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
margin-top: 20px;
}
.link {
font-size: 12px;
}
.link {
font-size: 12px;
}
</style>
<!-- 创建超级管理员 -->
<template>
<view class="uni-content">
<match-media :min-width="690">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title title-box">创建超级管理员</text>
</match-media>
<uni-forms ref="form" :value="formData" :rules="rules" validate-trigger="submit" err-show-type="toast">
<uni-forms-item name="username" required>
<uni-easyinput :inputBorder="false" :focus="focusUsername" @blur="focusUsername = false"
class="input-box" placeholder="请输入用户名" v-model="formData.username" trim="both" />
</uni-forms-item>
<uni-forms-item name="nickname">
<uni-easyinput :inputBorder="false" :focus="focusNickname" @blur="focusNickname = false" class="input-box" placeholder="请输入用户昵称" v-model="formData.nickname"
trim="both" />
</uni-forms-item>
<uni-forms-item name="password" v-model="formData.password" required>
<uni-easyinput :inputBorder="false" :focus="focusPassword" @blur="focusPassword = false"
class="input-box" maxlength="20" :placeholder="'请输入' + (config.passwordStrength == 'weak'?'6':'8') + '-16位密码'" type="password"
v-model="formData.password" trim="both" />
</uni-forms-item>
<uni-forms-item name="password2" v-model="formData.password2" required>
<uni-easyinput :inputBorder="false" :focus="focusPassword2" @blur="focusPassword2 =false"
class="input-box" placeholder="再次输入密码" maxlength="20" type="password" v-model="formData.password2"
trim="both" />
</uni-forms-item>
<uni-forms-item>
<uni-captcha ref="captcha" scene="register" v-model="formData.captcha" />
</uni-forms-item>
<uni-id-pages-agreements scope="register" ref="agreements" ></uni-id-pages-agreements>
<button class="uni-btn" type="primary" @click="submit">注册</button>
<button @click="navigateBack" class="register-back">返回</button>
<match-media :min-width="690">
<view class="link-box">
<text class="link" @click="toLogin">已有账号?点此登录</text>
</view>
</match-media>
</uni-forms>
</view>
</template>
<script>
import rules from './validator.js';
import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js';
import config from '@/uni_modules/uni-id-pages/config.js'
const uniIdCo = uniCloud.importObject("uni-id-co", {customUI: true})
export default {
mixins: [mixin],
data() {
return {
formData: {
username: "",
nickname: "",
password: "",
password2: "",
captcha: ""
},
rules,
focusUsername:false,
focusNickname:false,
focusPassword:false,
focusPassword2:false,
logo: "/static/logo.png"
}
},
onReady() {
this.$refs.form.setRules(this.rules)
},
onShow() {
// #ifdef H5
document.onkeydown = event => {
var e = event || window.event;
if (e && e.keyCode == 13) { //回车键的键值为13
this.submit()
}
};
// #endif
},
methods: {
/**
* 触发表单提交
*/
submit() {
this.$refs.form.validate().then((res) => {
if(this.formData.captcha.length != 4){
this.$refs.captcha.focusCaptchaInput = true
return uni.showToast({
title: '请输入验证码',
icon: 'none'
});
}
if (this.needAgreements && !this.agree) {
return this.$refs.agreements.popup(()=>{
this.submitForm(res)
})
}
this.submitForm(res)
}).catch((errors) => {
let key = errors[0].key
key = key.replace(key[0], key[0].toUpperCase())
console.log(key);
this['focus'+key] = true
})
},
submitForm(params) {
uniIdCo.registerAdmin(this.formData).then(e => {
console.log(e);
uni.navigateBack()
})
.catch(e => {
console.log(e);
console.log(e.message);
//更好的体验:登录错误,直接刷新验证码
this.$refs.captcha.getImageCaptcha()
uni.showModal({
title: '提示',
content: e.errMsg || `创建失败: ${e.errCode}`,
showCancel: false
})
})
},
navigateBack() {
uni.navigateBack()
},
toLogin() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withpwd'
})
},
registerByEmail() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/register/register-by-email'
})
}
}
}
</script>
<style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
@media screen and (max-width: 690px) {
.uni-content{
margin-top: 15px;
height: 100%;
background-color: #fff;
}
}
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px 60px;
}
.link-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
}
.link {
font-size: 12px;
}
}
.uni-content ::v-deep .uni-forms-item__label {
position: absolute;
left: -15px;
}
button {
margin-top: 15px;
}
</style>
<!-- 邮箱验证码注册 -->
<template>
<view class="uni-content">
<match-media :min-width="690">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title title-box">邮箱验证码注册</text>
</match-media>
<uni-forms ref="form" :value="formData" :rules="rules" validate-trigger="submit" err-show-type="toast">
<uni-forms-item name="email" required>
<uni-easyinput :inputBorder="false" :focus="focusEmail" @blur="focusEmail = false"
class="input-box" placeholder="请输入邮箱" v-model="formData.email" trim="both" />
</uni-forms-item>
<uni-forms-item name="nickname">
<uni-easyinput :inputBorder="false" :focus="focusNickname" @blur="focusNickname = false" class="input-box" placeholder="请输入用户昵称"
v-model="formData.nickname" trim="both" />
</uni-forms-item>
<uni-forms-item name="password" v-model="formData.password" required>
<uni-easyinput :inputBorder="false" :focus="focusPassword" @blur="focusPassword = false"
class="input-box" maxlength="20" :placeholder="'请输入' + (config.passwordStrength == 'weak'?'6':'8') + '-16位密码'" type="password"
v-model="formData.password" trim="both" />
</uni-forms-item>
<uni-forms-item name="password2" v-model="formData.password2" required>
<uni-easyinput :inputBorder="false" :focus="focusPassword2" @blur="focusPassword2 =false"
class="input-box" placeholder="再次输入密码" maxlength="20" type="password" v-model="formData.password2"
trim="both" />
</uni-forms-item>
<uni-forms-item name="code" >
<uni-id-pages-email-form ref="shortCode" :email="formData.email" type="register" v-model="formData.code">
</uni-id-pages-email-form>
</uni-forms-item>
<uni-id-pages-agreements scope="register" ref="agreements" ></uni-id-pages-agreements>
<button class="uni-btn" type="primary" @click="submit">注册</button>
<button @click="navigateBack" class="register-back">返回</button>
<match-media :min-width="690">
<view class="link-box">
<text class="link" @click="registerByUserName">用户名密码注册</text>
<text class="link" @click="toLogin">已有账号?点此登录</text>
</view>
</match-media>
</uni-forms>
</view>
</template>
<script>
import rules from './validator.js';
import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js';
import config from '@/uni_modules/uni-id-pages/config.js'
import passwordMod from '@/uni_modules/uni-id-pages/common/password.js'
const uniIdCo = uniCloud.importObject("uni-id-co")
export default {
mixins: [mixin],
data() {
return {
formData: {
email: "",
nickname: "",
password: "",
password2: "",
code: ""
},
rules: {
email: {
rules: [{
required: true,
errorMessage: '请输入邮箱',
},{
format:'email',
errorMessage: '邮箱格式不正确',
}
]
},
nickname: {
rules: [{
minLength: 3,
maxLength: 32,
errorMessage: '昵称长度在 {minLength} 到 {maxLength} 个字符',
},
{
validateFunction: function(rule, value, data, callback) {
// console.log(value);
if (/^1\d{10}$/.test(value) || /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(value)) {
callback('昵称不能是:手机号或邮箱')
};
if (/^\d+$/.test(value)) {
callback('昵称不能为纯数字')
};
if(/[\u4E00-\u9FA5\uF900-\uFA2D]{1,}/.test(value)){
callback('昵称不能包含中文')
}
return true
}
}
],
label: "昵称"
},
...passwordMod.getPwdRules(),
code: {
rules: [{
required: true,
errorMessage: '请输入邮箱验证码',
},
{
pattern: /^.{6}$/,
errorMessage: '邮箱验证码不正确',
}
]
}
},
focusEmail:false,
focusNickname:false,
focusPassword:false,
focusPassword2:false,
logo: "/static/logo.png"
}
},
onReady() {
this.$refs.form.setRules(this.rules)
},
onShow() {
// #ifdef H5
document.onkeydown = event => {
var e = event || window.event;
if (e && e.keyCode == 13) { //回车键的键值为13
this.submit()
}
};
// #endif
},
methods: {
/**
* 触发表单提交
*/
submit() {
this.$refs.form.validate().then((res) => {
if (this.needAgreements && !this.agree) {
return this.$refs.agreements.popup(()=>{
this.submitForm(res)
})
}
this.submitForm(res)
}).catch((errors) => {
let key = errors[0].key
key = key.replace(key[0], key[0].toUpperCase())
console.log(key);
this['focus'+key] = true
})
},
submitForm(params) {
uniIdCo.registerUserByEmail(this.formData).then(e => {
console.log(e);
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withpwd',
complete: (e) => {
console.log(e);
}
})
})
.catch(e => {
console.log(e);
console.log(e.message);
})
},
navigateBack() {
uni.navigateBack()
},
toLogin() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withpwd'
})
},
registerByUserName() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/register/register'
})
}
}
}
</script>
<style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
@media screen and (max-width: 690px) {
.uni-content{
margin-top: 15px;
}
}
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px;
max-height: 550px;
}
.link-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
}
.link {
font-size: 12px;
}
}
.uni-content ::v-deep .uni-forms-item__label {
position: absolute;
left: -15px;
}
button {
margin-top: 15px;
}
</style>
<!-- 账号注册页 -->
<template>
<view class="uni-content">
<match-media :min-width="690">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title title-box">用户名密码注册</text>
</match-media>
<uni-forms ref="form" :value="formData" :rules="rules" validate-trigger="submit" err-show-type="toast">
<uni-forms-item name="username" required>
<uni-easyinput :inputBorder="false" :focus="focusUsername" @blur="focusUsername = false"
......@@ -12,7 +19,7 @@
</uni-forms-item>
<uni-forms-item name="password" v-model="formData.password" required>
<uni-easyinput :inputBorder="false" :focus="focusPassword" @blur="focusPassword = false"
class="input-box" maxlength="20" :placeholder="'请输入' + passwordLength[0] + '-' + passwordLength[1] + '位密码'" type="password"
class="input-box" maxlength="20" :placeholder="'请输入' + (config.passwordStrength == 'weak'?'6':'8') + '-16位密码'" type="password"
v-model="formData.password" trim="both" />
</uni-forms-item>
<uni-forms-item name="password2" v-model="formData.password2" required>
......@@ -25,7 +32,13 @@
</uni-forms-item>
<uni-id-pages-agreements scope="register" ref="agreements" ></uni-id-pages-agreements>
<button class="uni-btn" type="primary" @click="submit">注册</button>
<button @click="navigateBack">返回</button>
<button @click="navigateBack" class="register-back">返回</button>
<match-media :min-width="690">
<view class="link-box">
<text class="link" @click="registerByEmail">邮箱验证码注册</text>
<text class="link" @click="toLogin">已有账号?点此登录</text>
</view>
</match-media>
</uni-forms>
</view>
</template>
......@@ -50,12 +63,8 @@
focusUsername:false,
focusNickname:false,
focusPassword:false,
focusPassword2:false
}
},
computed:{
passwordLength(){
return config.password.length
focusPassword2:false,
logo: "/static/logo.png"
}
},
onReady() {
......@@ -111,6 +120,16 @@
},
navigateBack() {
uni.navigateBack()
},
toLogin() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withpwd'
})
},
registerByEmail() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/register/register-by-email'
})
}
}
}
......@@ -118,9 +137,33 @@
<style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
.uni-content{
margin-top: 15px;
@media screen and (max-width: 690px) {
.uni-content{
margin-top: 15px;
height: 100%;
background-color: #fff;
}
}
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px 60px;
}
.link-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
}
.link {
font-size: 12px;
}
}
.uni-content ::v-deep .uni-forms-item__label {
position: absolute;
left: -15px;
......
<!-- 找回密码页 -->
<template>
<view class="uni-content">
<match-media :min-width="690">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title title-box">通过邮箱验证码找回密码</text>
</match-media>
<uni-forms ref="form" :value="formData" err-show-type="toast">
<uni-forms-item name="email">
<uni-easyinput :focus="focusEmail" @blur="focusEmail = false" class="input-box" :disabled="lock" :inputBorder="false"
v-model="formData.email" placeholder="请输入邮箱">
</uni-easyinput>
</uni-forms-item>
<uni-forms-item name="code">
<uni-id-pages-email-form ref="shortCode" :email="formData.email" type="reset-pwd-by-email" v-model="formData.code">
</uni-id-pages-email-form>
</uni-forms-item>
<uni-forms-item name="password">
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password"
placeholder="请输入新密码"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="password2">
<uni-easyinput :focus="focusPassword2" @blur="focusPassword2 = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password2"
placeholder="请再次输入新密码"></uni-easyinput>
</uni-forms-item>
<button class="uni-btn send-btn-box" type="primary" @click="submit">提交</button>
<match-media :min-width="690">
<view class="link-box">
<text class="link" @click="retrieveByPhone">通过手机验证码找回密码</text>
<view></view>
</view>
</match-media>
</uni-forms>
<uni-popup-captcha @confirm="submit" v-model="formData.captcha" scene="reset-pwd-by-sms" ref="popup"></uni-popup-captcha>
</view>
</template>
<script>
import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js';
import passwordMod from '@/uni_modules/uni-id-pages/common/password.js'
const uniIdCo = uniCloud.importObject("uni-id-co",{
errorOptions:{
type:'toast'
}
})
export default {
mixins: [mixin],
data() {
return {
lock: false,
focusEmail:true,
focusPassword:false,
focusPassword2:false,
formData: {
"email": "",
"code": "",
'password': '',
'password2': '',
"captcha": ""
},
rules: {
email: {
rules: [{
required: true,
errorMessage: '请输入邮箱',
},
{
format:'email',
errorMessage: '邮箱格式不正确',
}
]
},
code: {
rules: [{
required: true,
errorMessage: '请输入邮箱验证码',
},
{
pattern: /^.{6}$/,
errorMessage: '请输入6位验证码',
}
]
},
...passwordMod.getPwdRules()
},
logo: "/static/logo.png"
}
},
computed: {
isEmail() {
let reg_email = /@/;
let isEmail = reg_email.test(this.formData.email);
return isEmail;
},
isPwd() {
let reg_pwd = /^.{6,20}$/;
let isPwd = reg_pwd.test(this.formData.password);
return isPwd;
},
isCode() {
let reg_code = /^\d{6}$/;
let isCode = reg_code.test(this.formData.code);
return isCode;
}
},
onLoad(event) {
if (event && event.emailNumber) {
this.formData.email = event.emailNumber;
if(event.lock){
this.lock = event.lock //如果是已经登录的账号,点击找回密码就锁定指定的账号绑定的邮箱码
this.focusEmail = true
}
}
},
onReady() {
if (this.formData.email) {
this.$refs.shortCode.start();
}
this.$refs.form.setRules(this.rules)
},
onShow() {
// #ifdef H5
document.onkeydown = event => {
var e = event || window.event;
if (e && e.keyCode == 13) { //回车键的键值为13
this.submit()
}
};
// #endif
},
methods: {
/**
* 完成并提交
*/
submit() {
console.log("formData", this.formData);
console.log('rules', this.rules);
this.$refs.form.validate()
.then(res => {
let {
email,
password: password,
captcha,
code
} = this.formData
uniIdCo.resetPwdByEmail({
email,
code,
password,
captcha
}).then(e => {
console.log(e);
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withpwd',
complete: (e) => {
console.log(e);
}
})
})
.catch(e => {
if (e.errCode == 'uni-id-captcha-required') {
this.$refs.popup.open()
}
}).finally(e => {
this.formData.captcha = ""
})
}).catch(errors=>{
let key = errors[0].key
if(key == 'code'){
console.log(this.$refs.shortCode);
return this.$refs.shortCode.focusSmsCodeInput = true
}
key = key.replace(key[0], key[0].toUpperCase())
console.log(key,'focus'+key);
this['focus'+key] = true
})
},
retrieveByPhone() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/retrieve/retrieve'
})
}
}
}
</script>
<style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
@media screen and (max-width: 690px) {
.uni-content{
margin-top: 15px;
}
}
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px 40px;
}
.link-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
}
.link {
font-size: 12px;
}
}
</style>
<!-- 找回密码页 -->
<template>
<view class="uni-content">
<match-media :min-width="690">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title title-box">通过手机验证码找回密码</text>
</match-media>
<uni-forms ref="form" :value="formData" err-show-type="toast">
<uni-forms-item name="phone">
<uni-easyinput :focus="focusPhone" @blur="focusPhone = false" class="input-box" :disabled="lock" type="number" :inputBorder="false"
......@@ -20,6 +27,12 @@
placeholder="请再次输入新密码"></uni-easyinput>
</uni-forms-item>
<button class="uni-btn send-btn-box" type="primary" @click="submit">提交</button>
<match-media :min-width="690">
<view class="link-box">
<text class="link" @click="retrieveByEmail">通过邮箱验证码找回密码</text>
<view></view>
</view>
</match-media>
</uni-forms>
<uni-popup-captcha @confirm="submit" v-model="formData.captcha" scene="reset-pwd-by-sms" ref="popup"></uni-popup-captcha>
</view>
......@@ -101,7 +114,8 @@
}
]
}
}
},
logo: "/static/logo.png"
}
},
computed: {
......@@ -187,6 +201,11 @@
console.log(key,'focus'+key);
this['focus'+key] = true
})
},
retrieveByEmail() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email'
})
}
}
}
......@@ -195,7 +214,26 @@
<style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
.uni-content {
margin-top: 15px;
@media screen and (max-width: 690px) {
.uni-content{
margin-top: 15px;
}
}
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px 40px;
}
.link-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
}
.link {
font-size: 12px;
}
}
</style>
<!-- 绑定手机号码页 -->
<template>
<view class="uni-content">
<match-media :min-width="690">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title title-box">绑定手机号</text>
</match-media>
<!-- 登录框 (选择手机号所属国家和地区需要另行实现) -->
<uni-easyinput clearable :focus="focusMobile" @blur="focusMobile = false" type="number" class="input-box" :inputBorder="false" v-model="formData.mobile"
maxlength="11" placeholder="请输入手机号"></uni-easyinput>
......@@ -20,7 +27,8 @@
code: "",
captcha: ""
},
focusMobile:true
focusMobile:true,
logo: "/static/logo.png"
}
},
computed: {
......@@ -90,6 +98,13 @@
padding: 50rpx;
padding-top: 10px;
}
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px 40px;
}
}
/* #ifndef APP-NVUE || VUE3 */
.uni-content ::v-deep .uni-easyinput__content {}
......
<!-- 修改密码 -->
<template>
<view class="uni-content">
<match-media :min-width="690">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 -->
<text class="title title-box">修改密码</text>
</match-media>
<uni-forms ref="form" :value="formData" err-show-type="toast">
<uni-forms-item name="oldPassword">
<uni-easyinput :focus="focusOldPassword" @blur="focusOldPassword = false" class="input-box"
......@@ -81,7 +88,8 @@
}
]
}
}
},
logo: "/static/logo.png"
}
},
onReady() {
......@@ -140,7 +148,15 @@
<style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
.uni-content {
margin-top: 15px;
@media screen and (max-width: 690px) {
.uni-content{
margin-top: 15px;
}
}
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px 40px;
}
}
</style>
<!-- 注销(销毁)账号 -->
<template>
<view class="content">
<view class="uni-content">
<text class="words" space="emsp">
一、注销是不可逆操作,注销后:\n
1.帐号将无法登录、无法找回。\n
......@@ -64,7 +64,7 @@
</script>
<style>
.content {
.uni-content {
display: flex;
flex-direction: column;
font-size: 28rpx;
......@@ -77,20 +77,6 @@
margin-bottom: 80px;
}
.button-group {
display: flex;
flex-direction: row;
position: fixed;
height: 50px;
bottom: 10px;
width: 750rpx;
justify-content: center;
align-items: center;
border-top: solid 1px #e4e6ec;
padding-top: 10px;
background-color: #FFFFFF;
}
.button-group button {
border-radius: 100px;
border: none;
......@@ -108,4 +94,26 @@
color: #e64340;
border: solid 1px #e64340;
}
.button-group {
display: flex;
flex-direction: row;
position: fixed;
height: 50px;
bottom: 10px;
width: 750rpx;
justify-content: center;
align-items: center;
border-top: solid 1px #e4e6ec;
padding-top: 10px;
background-color: #FFFFFF;
max-width: 690px;
}
@media screen and (min-width: 690px) {
.uni-content{
max-width: 690px;
margin-left: calc(50% - 345px);
}
}
</style>
<!-- 用户资料页 -->
<template>
<view class="uni-content">
<view class="avatar">
<uni-id-pages-avatar width="260rpx" height="260rpx"></uni-id-pages-avatar>
</view>
<uni-list>
<uni-list-item class="item" @click="setNickname('')" title="昵称" :rightText="userInfo.nickname||'未设置'" link>
</uni-list-item>
<template>
<view class="uni-content">
<view class="avatar">
<uni-id-pages-avatar width="260rpx" height="260rpx"></uni-id-pages-avatar>
</view>
<uni-list>
<uni-list-item class="item" @click="setNickname('')" title="昵称" :rightText="userInfo.nickname||'未设置'" link>
</uni-list-item>
<uni-list-item class="item" @click="bindMobile" title="手机号" :rightText="userInfo.mobile||'未绑定'" link>
</uni-list-item>
<uni-list-item v-if="userInfo.email" class="item" title="电子邮箱" :rightText="userInfo.email">
</uni-list-item>
<uni-list-item v-if="hasPwd" class="item" @click="changePassword" title="修改密码" link>
</uni-list-item>
</uni-list>
<uni-list class="mt10">
<uni-list-item @click="deactivate" title="注销账号" link="navigateTo"></uni-list-item>
</uni-list>
<uni-popup ref="dialog" type="dialog">
<uni-popup-dialog mode="input" :value="userInfo.nickname" @confirm="setNickname" title="设置昵称"
placeholder="请输入要设置的昵称">
</uni-popup-dialog>
</uni-popup>
<uni-id-pages-bind-mobile ref="bind-mobile-by-sms" @success="getUserInfo"></uni-id-pages-bind-mobile>
<button v-if="hasLogin" @click="logout">退出登录</button>
<button v-else @click="login">去登录</button>
</view>
</template>
<script>
const db = uniCloud.database();
const usersTable = db.collection('uni-id-users')
const uniIdCo = uniCloud.importObject("uni-id-co")
export default {
data() {
return {
univerifyStyle: {
authButton: {
"title": "本机号码一键绑定", // 授权按钮文案
},
otherLoginButton: {
"title": "其他号码绑定",
}
},
userInfo: {
mobile:'',
nickname:''
},
</uni-list-item>
</uni-list>
<uni-list class="mt10">
<uni-list-item @click="deactivate" title="注销账号" link="navigateTo"></uni-list-item>
</uni-list>
<uni-popup ref="dialog" type="dialog">
<uni-popup-dialog mode="input" :value="userInfo.nickname" @confirm="setNickname" title="设置昵称"
placeholder="请输入要设置的昵称">
</uni-popup-dialog>
</uni-popup>
<uni-id-pages-bind-mobile ref="bind-mobile-by-sms" @success="getUserInfo"></uni-id-pages-bind-mobile>
<template v-if="showLoginManage">
<button v-if="hasLogin" @click="logout">退出登录</button>
<button v-else @click="login">去登录</button>
</template>
</view>
</template>
<script>
const db = uniCloud.database();
const usersTable = db.collection('uni-id-users')
const uniIdCo = uniCloud.importObject("uni-id-co")
import common from '@/uni_modules/uni-id-pages/common/common.js';
export default {
data() {
return {
univerifyStyle: {
authButton: {
"title": "本机号码一键绑定", // 授权按钮文案
},
otherLoginButton: {
"title": "其他号码绑定",
}
},
userInfo: {
mobile:'',
nickname:''
},
hasLogin: false,
hasPwd:false
}
},
async onShow() {
this.univerifyStyle.authButton.title = "本机号码一键绑定"
this.univerifyStyle.otherLoginButton.title = "其他号码绑定"
},
async onLoad() {
hasPwd:false,
showLoginManage:false//通过页面传参隐藏登录&退出登录按钮
}
},
async onShow() {
this.univerifyStyle.authButton.title = "本机号码一键绑定"
this.univerifyStyle.otherLoginButton.title = "其他号码绑定"
},
async onLoad(e) {
if(e.showLoginManage){
this.showLoginManage = true//通过页面传参隐藏登录&退出登录按钮
}
this.getUserInfo()
//判断当前用户是否有密码,否则就不显示密码修改功能
let res = await uniIdCo.getAccountInfo()
this.hasPwd = res.isPasswordSet
},
methods: {
login() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
complete: (e) => {
console.log(e);
}
})
},
async logout() {
await uniIdCo.logout()
uni.removeStorageSync('uni_id_token');
uni.setStorageSync('uni_id_token_expired', 0)
uni.redirectTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
});
this.hasPwd = res.isPasswordSet
},
methods: {
login() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
complete: (e) => {
console.log(e);
}
})
},
logout:common.logout,
changePassword(){
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd',
......@@ -82,155 +84,165 @@
console.log(e);
}
})
},
getUserInfo(e) {
uni.showLoading({
mask: true
});
usersTable.where("'_id' == $cloudEnv_uid").field('mobile,nickname').get().then(res => {
console.log({res});
this.userInfo = res.result.data[0]
console.log('this.userInfo', this.userInfo);
this.hasLogin = true
}).catch(e => {
this.userInfo = {}
this.hasLogin = false
console.log(e.message, e.errCode);
}).finally(e => {
// console.log(e);
uni.hideLoading()
})
},
bindMobile() {
// #ifdef APP-PLUS
uni.preLogin({
provider: 'univerify',
success: this.univerify(), //预登录成功
fail: (res) => { // 预登录失败
// 不显示一键登录选项(或置灰)
console.log(res)
this.bindMobileBySmsCode()
}
})
// #endif
// #ifdef MP-WEIXIN
this.$refs['bind-mobile'].open()
// #endif
// #ifdef H5
//...去用验证码绑定
this.bindMobileBySmsCode()
// #endif
},
univerify() {
uni.login({
"provider": 'univerify',
"univerifyStyle": this.univerifyStyle,
success: async e => {
console.log(e.authResult);
uniIdCo.bindMobileByUniverify(e.authResult).then(res => {
console.log(res);
this.getUserInfo()
}).catch(e => {
console.log(e);
}).finally(e=>{
console.log(e);
uni.closeAuthView()
})
},
fail: (err) => {
console.log(err);
if (err.code == '30002' || err.code == '30001') {
this.bindMobileBySmsCode()
}
}
})
},
bindMobileBySmsCode() {
uni.navigateTo({
url: './bind-mobile/bind-mobile',
events: {
getUserInfo: () => {
this.getUserInfo()
}
},
complete(e) {
console.log(e);
}
})
},
setNickname(nickname) {
console.log(nickname);
if (nickname) {
usersTable.where('_id==$env.uid').update({
nickname
}).then(e => {
console.log(e);
if (e.result.updated) {
uni.showToast({
title: "更新成功",
icon: 'none'
});
this.userInfo.nickname = nickname
} else {
uni.showToast({
title: "没有改变",
icon: 'none'
});
}
})
this.$refs.dialog.close()
} else {
this.$refs.dialog.open()
}
},
deactivate(){
uni.navigateTo({
url:"/uni_modules/uni-id-pages/pages/userinfo/deactivate/deactivate"
})
}
}
}
</script>
<style lang="scss" scoped>
@import url("/uni_modules/uni-id-pages/common/login-page.scss");
.uni-content {
padding: 0;
}
/* #ifndef APP-NVUE */
view {
display: flex;
box-sizing: border-box;
flex-direction: column;
}
/* #endif */
.avatar {
align-items: center;
justify-content: center;
margin: 22px 0;
width: 100%;
}
.item {
flex: 1;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
button {
margin: 10%;
margin-top: 40px;
border-radius: 0;
background-color: #FFFFFF;
width: 80%;
}
.mt10{
margin-top: 10px;
}
</style>
},
getUserInfo(e) {
uni.showLoading({
mask: true
});
usersTable.where("'_id' == $cloudEnv_uid").field('mobile,nickname,email').get().then(res => {
console.log({res});
this.userInfo = res.result.data[0]
console.log('this.userInfo', this.userInfo);
this.hasLogin = true
}).catch(e => {
this.userInfo = {}
this.hasLogin = false
console.log(e.message, e.errCode);
}).finally(e => {
// console.log(e);
uni.hideLoading()
})
},
bindMobile() {
// #ifdef APP-PLUS
uni.preLogin({
provider: 'univerify',
success: this.univerify(), //预登录成功
fail: (res) => { // 预登录失败
// 不显示一键登录选项(或置灰)
console.log(res)
this.bindMobileBySmsCode()
}
})
// #endif
// #ifdef MP-WEIXIN
this.$refs['bind-mobile-by-sms'].open()
// #endif
// #ifdef H5
//...去用验证码绑定
this.bindMobileBySmsCode()
// #endif
},
univerify() {
uni.login({
"provider": 'univerify',
"univerifyStyle": this.univerifyStyle,
success: async e => {
console.log(e.authResult);
uniIdCo.bindMobileByUniverify(e.authResult).then(res => {
console.log(res);
this.getUserInfo()
}).catch(e => {
console.log(e);
}).finally(e=>{
console.log(e);
uni.closeAuthView()
})
},
fail: (err) => {
console.log(err);
if (err.code == '30002' || err.code == '30001') {
this.bindMobileBySmsCode()
}
}
})
},
bindMobileBySmsCode() {
uni.navigateTo({
url: './bind-mobile/bind-mobile',
events: {
getUserInfo: () => {
this.getUserInfo()
}
},
complete(e) {
console.log(e);
}
})
},
setNickname(nickname) {
console.log(nickname);
if (nickname) {
usersTable.where('_id==$env.uid').update({
nickname
}).then(e => {
console.log(e);
if (e.result.updated) {
uni.showToast({
title: "更新成功",
icon: 'none'
});
this.userInfo.nickname = nickname
} else {
uni.showToast({
title: "没有改变",
icon: 'none'
});
}
})
this.$refs.dialog.close()
} else {
this.$refs.dialog.open()
}
},
deactivate(){
uni.navigateTo({
url:"/uni_modules/uni-id-pages/pages/userinfo/deactivate/deactivate"
})
}
}
}
</script>
<style lang="scss" scoped>
@import url("/uni_modules/uni-id-pages/common/login-page.scss");
.uni-content {
padding: 0;
}
/* #ifndef APP-NVUE */
view {
display: flex;
box-sizing: border-box;
flex-direction: column;
}
@media screen and (min-width: 690px) {
.uni-content {
padding: 0;
max-width: 690px;
margin-left: calc(50% - 345px);
border: none;
max-height: none;
border-radius: 0;
box-shadow: none;
}
}
/* #endif */
.avatar {
align-items: center;
justify-content: center;
margin: 22px 0;
width: 100%;
}
.item {
flex: 1;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
button {
margin: 10%;
margin-top: 40px;
border-radius: 0;
background-color: #FFFFFF;
width: 80%;
}
.mt10{
margin-top: 10px;
}
</style>
......@@ -49,26 +49,45 @@
"navigationBarTitleText": "注册"
}
},
{
"path": "uni_modules/uni-id-pages/pages/register/register-by-email",
"style": {
"navigationBarTitleText": "邮箱验证码注册"
}
},
{
"path": "uni_modules/uni-id-pages/pages/retrieve/retrieve",
"style": {
"navigationBarTitleText": "重置密码"
}
}, {
},
{
"path": "uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email",
"style": {
"navigationBarTitleText": "通过邮箱重置密码"
}
},
{
"path": "uni_modules/uni-id-pages/pages/common/webview/webview",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
,{
"path" : "uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd",
"style" :
{
"navigationBarTitleText": "修改密码",
"enablePullDownRefresh": false
}
}
,{
"path" : "uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd",
"style" :
{
"navigationBarTitleText": "修改密码",
"enablePullDownRefresh": false
}
},{
"path": "uni_modules/uni-id-pages/pages/register/register-admin",
"style": {
"navigationBarTitleText": "注册管理员账号",
"enablePullDownRefresh": false
}
}
]
}
\ No newline at end of file
module.exports = {
env: {
browser: true,
commonjs: true,
es2021: true
},
extends: [
'standard'
],
parserOptions: {
ecmaVersion: 'latest'
},
rules: {
'no-throw-literal': 0
},
globals: {
uniCloud: 'readonly'
}
}
......@@ -36,7 +36,9 @@ const CAPTCHA_SCENE = {
LOGIN_BY_PWD: 'login-by-pwd',
LOGIN_BY_SMS: 'login-by-sms',
RESET_PWD_BY_SMS: 'reset-pwd-by-sms',
RESET_PWD_BY_EMAIL: 'reset-pwd-by-email',
SEND_SMS_CODE: 'send-sms-code',
SEND_EMAIL_CODE: 'send-email-code',
BIND_MOBILE_BY_SMS: 'bind-mobile-by-sms'
}
......@@ -45,6 +47,7 @@ const LOG_TYPE = {
LOGIN: 'login',
REGISTER: 'register',
RESET_PWD_BY_SMS: 'reset-pwd',
RESET_PWD_BY_EMAIL: 'reset-pwd',
BIND_MOBILE: 'bind-mobile',
BIND_WEIXIN: 'bind-weixin',
BIND_QQ: 'bind-qq',
......@@ -58,6 +61,13 @@ const SMS_SCENE = {
BIND_MOBILE_BY_SMS: 'bind-mobile-by-sms'
}
const EMAIL_SCENE = {
REGISTER: 'register',
LOGIN_BY_EMAIL: 'login-by-email',
RESET_PWD_BY_EMAIL: 'reset-pwd-by-email',
BIND_EMAIL: 'bind-email'
}
module.exports = {
db,
dbCmd,
......@@ -68,5 +78,6 @@ module.exports = {
USER_STATUS,
CAPTCHA_SCENE,
LOG_TYPE,
SMS_SCENE
SMS_SCENE,
EMAIL_SCENE
}
......@@ -15,7 +15,8 @@ const middleware = require('./middleware/index')
const {
registerAdmin,
registerUser
registerUser,
registerUserByEmail
} = require('./module/register/index')
const {
addUser,
......@@ -45,13 +46,15 @@ const {
const {
updatePwd,
resetPwdBySms,
resetPwdByEmail,
closeAccount,
getAccountInfo
} = require('./module/account/index')
const {
createCaptcha,
refreshCaptcha,
sendSmsCode
sendSmsCode,
sendEmailCode
} = require('./module/verify/index')
const {
refreshToken,
......@@ -273,6 +276,17 @@ module.exports = {
* @returns
*/
registerUser,
/**
* 通过邮箱+验证码注册用户
* @param {Object} params
* @param {String} params.email 邮箱
* @param {String} params.password 密码
* @param {String} params.nickname 昵称
* @param {String} params.code 邮箱验证码
* @param {String} params.inviteCode 邀请码
* @returns
*/
registerUserByEmail,
/**
* 用户名密码登录
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login
......@@ -433,6 +447,16 @@ module.exports = {
* @returns {object}
*/
resetPwdBySms,
/**
* 通过邮箱验证码重置密码
* @param {object} params
* @param {string} params.email 邮箱
* @param {string} params.code 邮箱验证码
* @param {string} params.password 密码
* @param {string} params.captcha 图形验证码
* @returns {object}
*/
resetPwdByEmail,
/**
* 注销账户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#close-account
......@@ -470,6 +494,16 @@ module.exports = {
* @returns
*/
sendSmsCode,
/**
* 发送邮箱验证码
* @tutorial 需自行实现功能
* @param {Object} params
* @param {String} params.email 邮箱
* @param {String} params.captcha 图形验证码
* @param {String} params.scene 短信验证码使用场景
* @returns
*/
sendEmailCode,
/**
* 刷新token
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#refresh-token
......
......@@ -4,8 +4,8 @@ const {
const createConfig = require('uni-config-center')
const requiredConfig = {
'web.h5-weixin': ['appid', 'appsecret'],
'web.web-weixin': ['appid', 'appsecret'],
'web.weixin-h5': ['appid', 'appsecret'],
'web.weixin-web': ['appid', 'appsecret'],
'app.weixin': ['appid', 'appsecret'],
'mp-weixin.weixin': ['appid', 'appsecret'],
'app.qq': ['appid', 'appsecret'],
......
......@@ -5,7 +5,7 @@ const {
ERROR
} = require('../../common/error')
function getQQPlatform () {
function getQQPlatform() {
const platform = this.clientPlatform
switch (platform) {
case 'app':
......@@ -18,7 +18,7 @@ function getQQPlatform () {
}
}
async function saveQQUserKey ({
async function saveQQUserKey({
openid,
sessionKey, // QQ小程序用户sessionKey
accessToken, // App端QQ用户accessToken
......@@ -45,14 +45,17 @@ async function saveQQUserKey ({
await this.uniOpenBridge.setUserAccessToken(keyObj, {
access_token: accessToken,
access_token_expired: accessTokenExpired
}, Math.floor((accessTokenExpired - Date.now()) / 1000))
}, accessTokenExpired ?
Math.floor((accessTokenExpired - Date.now()) / 1000) :
30 * 24 * 60 * 60
)
break
default:
break
}
}
function generateQQCache ({
function generateQQCache({
sessionKey, // QQ小程序用户sessionKey
accessToken, // App端QQ用户accessToken
accessTokenExpired // App端QQ用户accessToken过期时间
......@@ -81,7 +84,7 @@ function generateQQCache ({
}
}
function getQQOpenid ({
function getQQOpenid({
userRecord
} = {}) {
const qqPlatform = getQQPlatform.call(this)
......@@ -93,7 +96,7 @@ function getQQOpenid ({
return qqOpenidObj[`${qqPlatform}_${appId}`] || qqOpenidObj[qqPlatform]
}
async function getQQCacheFallback ({
async function getQQCacheFallback({
userRecord,
key
} = {}) {
......@@ -106,7 +109,7 @@ async function getQQCacheFallback ({
return qqCache && qqCache[key]
}
async function getQQCache ({
async function getQQCache({
uid,
userRecord,
key
......
......@@ -78,7 +78,7 @@ async function saveWeixinUserKey ({
access_token: accessToken,
refresh_token: refreshToken,
access_token_expired: accessTokenExpired
}, 30 * 24 * 3600)
}, 30 * 24 * 60 * 60)
break
default:
break
......
module.exports = {
updatePwd: require('./update-pwd'),
resetPwdBySms: require('./reset-pwd-by-sms'),
resetPwdByEmail: require('./reset-pwd-by-email'),
closeAccount: require('./close-account'),
getAccountInfo: require('./get-account-info')
}
const {
ERROR
} = require('../../common/error')
const {
getNeedCaptcha,
verifyCaptcha
} = require('../../lib/utils/captcha')
const {
verifyEmailCode
} = require('../../lib/utils/verify-code')
const {
userCollection,
EMAIL_SCENE,
CAPTCHA_SCENE,
LOG_TYPE
} = require('../../common/constants')
const {
findUser
} = require('../../lib/utils/account')
const PasswordUtils = require('../../lib/utils/password')
/**
* 通过邮箱验证码重置密码
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#reset-pwd-by-email
* @param {object} params
* @param {string} params.email 邮箱
* @param {string} params.code 邮箱验证码
* @param {string} params.password 密码
* @param {string} params.captcha 图形验证码
* @returns {object}
*/
module.exports = async function (params = {}) {
const schema = {
email: 'email',
code: 'string',
password: 'password',
captcha: {
required: false,
type: 'string'
}
}
this.middleware.validate(params, schema)
const {
email,
code,
password,
captcha
} = params
const needCaptcha = await getNeedCaptcha.call(this, {
email,
type: LOG_TYPE.RESET_PWD_BY_EMAIL
})
if (needCaptcha) {
await verifyCaptcha.call(this, {
captcha,
scene: CAPTCHA_SCENE.RESET_PWD_BY_EMAIL
})
}
try {
// 验证手机号验证码,验证不通过时写入失败日志
await verifyEmailCode({
email,
code,
scene: EMAIL_SCENE.RESET_PWD_BY_EMAIL
})
} catch (error) {
await this.middleware.uniIdLog({
data: {
email
},
type: LOG_TYPE.RESET_PWD_BY_EMAIL,
success: false
})
throw error
}
// 根据手机号查找匹配的用户
const userMatched = await findUser.call(this, {
userQuery: {
email
},
authorizedApp: [this.getClientInfo().appId]
})
if (userMatched.length === 0) {
throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS
}
} else if (userMatched.length > 1) {
throw {
errCode: ERROR.ACCOUNT_CONFLICT
}
}
const { _id: uid } = userMatched[0]
const {
passwordHash,
version
} = new PasswordUtils({
passwordSecret: this.config.passwordSecret
}).generatePasswordHash({
password
})
// 更新用户密码
await userCollection.doc(uid).update({
password: passwordHash,
password_secret_version: version,
valid_token_date: Date.now()
})
// 写入成功日志
await this.middleware.uniIdLog({
data: {
email
},
type: LOG_TYPE.RESET_PWD_BY_SMS
})
return {
errCode: 0
}
}
module.exports = {
registerUser: require('./register-user'),
registerAdmin: require('./register-admin')
registerAdmin: require('./register-admin'),
registerUserByEmail: require('./register-user-by-email')
}
......@@ -38,7 +38,8 @@ module.exports = async function (params = {}) {
}).limit(1).get()
if (getAdminRes.data.length > 0) {
return {
errCode: ERROR.ADMIN_EXISTS
errCode: ERROR.ADMIN_EXISTS,
errMsg: this.t('uni-id-admin-exists')
}
}
const {
......
const {
postRegister,
preRegisterWithPassword
} = require('../../lib/utils/register')
const {
verifyCaptcha
} = require('../../lib/utils/captcha')
const {
CAPTCHA_SCENE,
EMAIL_SCENE,
LOG_TYPE
} = require('../../common/constants')
const {
verifyEmailCode
} = require('../../lib/utils/verify-code')
/**
* 通过邮箱+验证码注册普通用户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#register-user-by-email
* @param {Object} params
* @param {String} params.email 邮箱
* @param {String} params.password 密码
* @param {String} params.nickname 昵称
* @param {String} params.code 邮箱验证码
* @param {String} params.inviteCode 邀请码
* @returns
*/
module.exports = async function (params = {}) {
const schema = {
email: 'email',
password: 'password',
nickname: {
required: false,
type: 'nickname'
},
code: 'string',
inviteCode: {
required: false,
type: 'string'
}
}
this.middleware.validate(params, schema)
const {
email,
password,
nickname,
code,
inviteCode
} = params
try {
// 验证邮箱验证码,验证不通过时写入失败日志
await verifyEmailCode({
email,
code,
scene: EMAIL_SCENE.REGISTER
})
} catch (error) {
await this.middleware.uniIdLog({
data: {
email
},
type: LOG_TYPE.REGISTER,
success: false
})
throw error
}
const {
user,
extraData
} = await preRegisterWithPassword.call(this, {
user: {
email
},
password
})
return postRegister.call(this, {
user,
extraData: {
...extraData,
nickname,
email_confirmed: 1
},
inviteCode
})
}
const {
verifyCaptcha
} = require('../../lib/utils/captcha')
const {
EMAIL_SCENE
} = require('../../common/constants')
const {
ERROR
} = require('../../common/error')
/**
* 发送邮箱验证码,可用于登录、注册、绑定邮箱、修改密码等操作
* @tutorial
* @param {Object} params
* @param {String} params.email 邮箱
* @param {String} params.captcha 图形验证码
* @param {String} params.scene 使用场景
* @returns
*/
module.exports = async function (params = {}) {
// 此接口暂未实现,欢迎向我们提交pr
throw new Error('api[sendEmailCode] is not yet implemented')
const schema = {
email: 'email',
captcha: 'string',
scene: 'string'
}
this.middleware.validate(params, schema)
const {
email,
captcha,
scene
} = params
if (!(Object.values(EMAIL_SCENE).includes(scene))) {
throw {
errCode: ERROR.INVALID_PARAM
}
}
await verifyCaptcha.call(this, {
scene: 'send-email-code',
captcha
})
// -- 测试代码
require('../../lib/utils/verify-code')
.setEmailVerifyCode.call(this, {
email,
code: '123456',
expiresIn: 180,
scene
})
return {
errCode: 'uni-id-invalid-mail-template',
errMsg: `已启动测试模式,直接使用:123456作为邮箱验证码即可。\n如果是正式项目,需自行实现发送邮件的相关功能`
}
// -- 测试代码
//发送邮件--需自行实现
}
{
"name": "uni-id-co",
"version": "1.0.9",
"version": "1.0.15",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "uni-id-co",
"version": "1.0.9",
"version": "1.0.12",
"dependencies": {
"jsonwebtoken": "8.5.1",
"lodash.merge": "^4.6.2",
......@@ -43,18 +43,21 @@
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"license": "BSD-3-Clause"
"resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"license": "Apache-2.0",
"resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/jsonwebtoken": {
"version": "8.5.1",
"license": "MIT",
"resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
......@@ -74,7 +77,8 @@
},
"node_modules/jwa": {
"version": "1.4.1",
"license": "MIT",
"resolved": "https://registry.npmmirror.com/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
......@@ -83,7 +87,8 @@
},
"node_modules/jws": {
"version": "3.2.2",
"license": "MIT",
"resolved": "https://registry.npmmirror.com/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
......@@ -91,61 +96,58 @@
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"node_modules/lodash.once": {
"version": "4.1.1",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
},
"node_modules/ms": {
"version": "2.1.3",
"license": "MIT"
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
"resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"node_modules/semver": {
"version": "5.7.1",
"license": "ISC",
"resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"bin": {
"semver": "bin/semver"
}
......@@ -169,16 +171,22 @@
},
"dependencies": {
"buffer-equal-constant-time": {
"version": "1.0.1"
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"requires": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
......@@ -194,6 +202,8 @@
},
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
......@@ -202,43 +212,67 @@
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"lodash.includes": {
"version": "4.3.0"
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
},
"lodash.isboolean": {
"version": "3.0.3"
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
},
"lodash.isinteger": {
"version": "4.0.4"
"version": "4.0.4",
"resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
},
"lodash.isnumber": {
"version": "3.0.3"
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
},
"lodash.isplainobject": {
"version": "4.0.6"
"version": "4.0.6",
"resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"lodash.isstring": {
"version": "4.0.1"
"version": "4.0.1",
"resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
},
"lodash.merge": {
"version": "4.6.2"
"version": "4.6.2",
"resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"lodash.once": {
"version": "4.1.1"
"version": "4.1.1",
"resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
},
"ms": {
"version": "2.1.3"
"version": "2.1.3",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"safe-buffer": {
"version": "5.2.1"
"version": "5.2.1",
"resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"semver": {
"version": "5.7.1"
"version": "5.7.1",
"resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"uni-captcha": {
"version": "file:../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
......
{
"name": "uni-id-co",
"version": "1.0.11",
"version": "1.0.15",
"description": "",
"main": "index.js",
"keywords": [],
......@@ -14,4 +14,4 @@
"uni-open-bridge-common": "file:../../../../uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common"
},
"extensions": {}
}
\ No newline at end of file
}
......@@ -77,7 +77,7 @@
},
"network_model": {
"bsonType": "string",
"description": "设备网络型号wifi/3G/4G/"
"description": "设备网络型号wifi\/3G\/4G\/"
},
"window_width": {
"bsonType": "string",
......
{
"bsonType": "object",
"required": ["user_id"],
"permission": {
"read": "'READ_UNI_ID_LOG' in auth.permission"
},
"properties": {
"_id": {
"description": "ID,系统自动生成"
......@@ -44,6 +48,7 @@
},
"user_id": {
"bsonType": "string",
"foreignKey": "uni-id-users._id",
"description": "用户id,参考uni-id-users表"
},
"username": {
......@@ -62,6 +67,5 @@
"bsonType": "string",
"description": "客户端DCloud AppId"
}
},
"required": []
}
}
{
"bsonType": "object",
"required": ["permission_id", "permission_name"],
"permission": {
"read": "'READ_UNI_ID_PERMISSIONS' in auth.permission",
"create": "'CREATE_UNI_ID_PERMISSIONS' in auth.permission",
"update": "'UPDATE_UNI_ID_PERMISSIONS' in auth.permission",
"delete": "'DELETE_UNI_ID_PERMISSIONS' in auth.permission"
},
"properties": {
"_id": {
"description": "存储文档 ID,系统自动生成"
......@@ -41,9 +48,5 @@
"title": "权限名称",
"trim": "both"
}
},
"required": [
"permission_id",
"permission_name"
]
}
\ No newline at end of file
}
}
{
"bsonType": "object",
"required": ["role_id", "role_name"],
"permission": {
"create": false,
"delete": false,
"read": false,
"update": false
"read": "'READ_UNI_ID_ROLES' in auth.permission",
"create": "'CREATE_UNI_ID_ROLES' in auth.permission",
"update": "'UPDATE_UNI_ID_ROLES' in auth.permission",
"delete": "'DELETE_UNI_ID_ROLES' in auth.permission"
},
"properties": {
"_id": {
"description": "存储文档 ID,系统自动生成"
},
"comment": {
"title": "备注",
"bsonType": "string",
"description": "备注",
"title": "备注",
"trim": "both"
},
"create_date": {
......@@ -24,25 +25,26 @@
}
},
"permission": {
"title": "权限",
"bsonType": "array",
"description": "角色拥有的权限列表",
"foreignKey": "uni-id-permissions.permission_id",
"title": "权限"
"description": "角色拥有的权限列表",
"enum": {
"collection": "uni-id-permissions",
"field": "permission_name as text, permission_id as value"
}
},
"role_id": {
"title": "唯一ID",
"bsonType": "string",
"description": "角色唯一标识,不可修改,不允许重复",
"title": "唯一ID",
"trim": "both"
},
"role_name": {
"title": "名称",
"bsonType": "string",
"description": "角色名称",
"title": "名称",
"trim": "both"
}
},
"required": [
"role_id"
]
}
\ No newline at end of file
}
}
{
"bsonType": "object",
"permission": {
"update": "doc._id == auth.uid",
"read": "doc._id == auth.uid"
},
"properties": {
"_id": {
"description": "存储文档 ID(用户 ID),系统自动生成"
},
"ali_openid": {
"bsonType": "string",
"description": "支付宝平台openid",
"permission": {
"write": false
}
},
"apple_openid": {
"bsonType": "string",
"description": "苹果登录openid",
"permission": {
"write": false
}
},
"avatar": {
"bsonType": "string",
"description": "头像地址",
"title": "头像地址",
"trim": "both"
},
"avatar_file": {
"bsonType": "file",
"description": "用file类型方便使用uni-file-picker组件",
"title": "头像文件"
},
"comment": {
"bsonType": "string",
"description": "备注",
"title": "备注",
"trim": "both",
"permission": {
"write": false
}
},
"dcloud_appid": {
"bsonType": "array",
"description": "允许登录的客户端的appid列表",
"foreignKey": "opendb-app-list.appid",
"permission": {
"write": false
}
},
"department_id": {
"bsonType": "array",
"description": "部门ID",
"enum": {
"collection": "opendb-department",
"field": "_id as value, name as text",
"orderby": "name asc"
},
"enumType": "tree",
"title": "部门",
"permission": {
"write": false
}
},
"email": {
"bsonType": "string",
"description": "邮箱地址",
"format": "email",
"title": "邮箱",
"trim": "both",
"permission": {
"write": false
}
},
"email_confirmed": {
"bsonType": "int",
"defaultValue": 0,
"description": "邮箱验证状态:0 未验证 1 已验证",
"enum": [{
"text": "未验证",
"value": 0
},
{
"text": "已验证",
"value": 1
}
],
"title": "邮箱验证状态",
"permission": {
"write": false
}
},
"gender": {
"bsonType": "int",
"defaultValue": 0,
"description": "用户性别:0 未知 1 男性 2 女性",
"enum": [{
"text": "未知",
"value": 0
},
{
"text": "男",
"value": 1
},
{
"text": "女",
"value": 2
}
],
"title": "性别",
"permission": {
"write": false
}
},
"invite_time": {
"bsonType": "timestamp",
"description": "受邀时间",
"permission": {
"write": false
}
},
"inviter_uid": {
"bsonType": "array",
"description": "用户全部上级邀请者",
"trim": "both",
"permission": {
"write": false
}
},
"last_login_date": {
"bsonType": "timestamp",
"description": "最后登录时间",
"permission": {
"write": false
}
},
"last_login_ip": {
"bsonType": "string",
"description": "最后登录时 IP 地址",
"permission": {
"write": false
}
},
"mobile": {
"bsonType": "string",
"description": "手机号码",
"pattern": "^\\+?[0-9-]{3,20}$",
"title": "手机号码",
"trim": "both",
"permission": {
"write": false
}
},
"mobile_confirmed": {
"bsonType": "int",
"defaultValue": 0,
"description": "手机号验证状态:0 未验证 1 已验证",
"enum": [{
"text": "未验证",
"value": 0
},
{
"text": "已验证",
"value": 1
}
],
"title": "手机号验证状态",
"permission": {
"write": false
}
},
"my_invite_code": {
"bsonType": "string",
"description": "用户自身邀请码",
"permission": {
"write": false
}
},
"nickname": {
"bsonType": "string",
"description": "用户昵称",
"title": "昵称",
"trim": "both"
},
"password": {
"bsonType": "password",
"description": "密码,加密存储",
"title": "密码",
"trim": "both",
"permission": {
"write": false,
"read": false
}
},
"password_secret_version": {
"bsonType": "int",
"description": "密码使用的passwordSecret版本",
"title": "passwordSecret",
"permission": {
"write": false,
"read": false
}
},
"realname_auth": {
"bsonType": "object",
"description": "实名认证信息",
"permission": {
"write": false
},
"properties": {
"auth_date": {
"bsonType": "timestamp",
"description": "认证通过时间"
},
"auth_status": {
"bsonType": "int",
"description": "认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败",
"maximum": 3,
"minimum": 0
},
"contact_email": {
"bsonType": "string",
"description": "联系人邮箱"
},
"contact_mobile": {
"bsonType": "string",
"description": "联系人手机号码"
},
"contact_person": {
"bsonType": "string",
"description": "联系人姓名"
},
"id_card_back": {
"bsonType": "string",
"description": "身份证反面照 URL"
},
"id_card_front": {
"bsonType": "string",
"description": "身份证正面照 URL"
},
"identity": {
"bsonType": "string",
"description": "身份证号码/营业执照号码"
},
"in_hand": {
"bsonType": "string",
"description": "手持身份证照片 URL"
},
"license": {
"bsonType": "string",
"description": "营业执照 URL"
},
"real_name": {
"bsonType": "string",
"description": "真实姓名/企业名称"
},
"type": {
"bsonType": "int",
"description": "用户类型:0 个人用户 1 企业用户",
"maximum": 1,
"minimum": 0
}
},
"required": [
"type",
"auth_status"
]
},
"register_date": {
"bsonType": "timestamp",
"description": "注册时间",
"forceDefaultValue": {
"$env": "now"
}
},
"register_ip": {
"bsonType": "string",
"description": "注册时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP"
}
},
"role": {
"bsonType": "array",
"description": "用户角色",
"enum": {
"collection": "uni-id-roles",
"field": "role_id as value, role_name as text"
},
"foreignKey": "uni-id-roles.role_id",
"permission": {
"write": false
},
"title": "角色"
},
"score": {
"bsonType": "int",
"description": "用户积分,积分变更记录可参考:uni-id-scores表定义",
"permission": {
"write": false
}
},
"status": {
"bsonType": "int",
"defaultValue": 0,
"description": "用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝",
"permission": {
"write": false
},
"enum": [{
"text": "正常",
"value": 0
},
{
"text": "禁用",
"value": 1
},
{
"text": "审核中",
"value": 2
},
{
"text": "审核拒绝",
"value": 3
}
],
"title": "用户状态"
},
"token": {
"bsonType": "array",
"description": "用户token"
},
"username": {
"bsonType": "string",
"description": "用户名,不允许重复",
"title": "用户名",
"trim": "both",
"permission": {
"write": false
}
},
"wx_openid": {
"bsonType": "object",
"description": "微信各个平台openid",
"properties": {
"app": {
"bsonType": "string",
"description": "app平台微信openid"
},
"mp": {
"bsonType": "string",
"description": "微信小程序平台openid"
},
"h5": {
"bsonType": "string",
"description": "微信公众号登录openid"
},
"web": {
"bsonType": "string",
"description": "PC页面扫码登录openid"
}
},
"permission": {
"write": false
}
},
"wx_unionid": {
"bsonType": "string",
"description": "微信unionid",
"permission": {
"write": false
}
},
"qq_openid": {
"bsonType": "object",
"description": "QQ各个平台openid",
"properties": {
"app": {
"bsonType": "string",
"description": "app平台QQ openid"
},
"mp": {
"bsonType": "string",
"description": "QQ小程序平台openid"
}
},
"permission": {
"write": false
}
},
"qq_unionid": {
"bsonType": "string",
"description": "QQ unionid",
"permission": {
"write": false
}
}
},
"required": []
{
"bsonType": "object",
"required": ["username", "password"],
"permission": {
"read": true,
"create": "'CREATE_UNI_ID_USERS' in auth.permission",
"update": "doc._id == auth.uid || 'UPDATE_UNI_ID_USERS' in auth.permission",
"delete": "'DELETE_UNI_ID_USERS' in auth.permission"
},
"properties": {
"_id": {
"description": "存储文档 ID(用户 ID),系统自动生成"
},
"ali_openid": {
"bsonType": "string",
"description": "支付宝平台openid",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"apple_openid": {
"bsonType": "string",
"description": "苹果登录openid",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"avatar": {
"bsonType": "string",
"description": "头像地址",
"title": "头像地址",
"trim": "both"
},
"avatar_file": {
"bsonType": "file",
"description": "用file类型方便使用uni-file-picker组件",
"title": "头像文件"
},
"comment": {
"bsonType": "string",
"description": "备注",
"title": "备注",
"trim": "both",
"permission": {
"write": false,
"read": false
}
},
"dcloud_appid": {
"bsonType": "array",
"description": "允许登录的客户端的appid列表",
"foreignKey": "opendb-app-list.appid",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"department_id": {
"bsonType": "array",
"description": "部门ID",
"enum": {
"collection": "opendb-department",
"field": "_id as value, name as text",
"orderby": "name asc"
},
"enumType": "tree",
"title": "部门",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"email": {
"bsonType": "string",
"description": "邮箱地址",
"format": "email",
"title": "邮箱",
"trim": "both",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"email_confirmed": {
"bsonType": "int",
"defaultValue": 0,
"description": "邮箱验证状态:0 未验证 1 已验证",
"enum": [{
"text": "未验证",
"value": 0
},
{
"text": "已验证",
"value": 1
}
],
"title": "邮箱验证状态",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"gender": {
"bsonType": "int",
"defaultValue": 0,
"description": "用户性别:0 未知 1 男性 2 女性",
"enum": [{
"text": "未知",
"value": 0
},
{
"text": "男",
"value": 1
},
{
"text": "女",
"value": 2
}
],
"title": "性别",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"invite_time": {
"bsonType": "timestamp",
"description": "受邀时间",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"inviter_uid": {
"bsonType": "array",
"description": "用户全部上级邀请者",
"trim": "both",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"last_login_date": {
"bsonType": "timestamp",
"description": "最后登录时间",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"last_login_ip": {
"bsonType": "string",
"description": "最后登录时 IP 地址",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"mobile": {
"bsonType": "string",
"description": "手机号码",
"pattern": "^\\+?[0-9-]{3,20}$",
"title": "手机号码",
"trim": "both",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"mobile_confirmed": {
"bsonType": "int",
"defaultValue": 0,
"description": "手机号验证状态:0 未验证 1 已验证",
"enum": [{
"text": "未验证",
"value": 0
},
{
"text": "已验证",
"value": 1
}
],
"title": "手机号验证状态",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"my_invite_code": {
"bsonType": "string",
"description": "用户自身邀请码",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"nickname": {
"bsonType": "string",
"description": "用户昵称",
"title": "昵称",
"trim": "both"
},
"password": {
"bsonType": "password",
"description": "密码,加密存储",
"title": "密码",
"trim": "both",
"permission": {
"write": false,
"read": false
}
},
"password_secret_version": {
"bsonType": "int",
"description": "密码使用的passwordSecret版本",
"title": "passwordSecret",
"permission": {
"write": false,
"read": false
}
},
"realname_auth": {
"bsonType": "object",
"description": "实名认证信息",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
},
"properties": {
"auth_date": {
"bsonType": "timestamp",
"description": "认证通过时间"
},
"auth_status": {
"bsonType": "int",
"description": "认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败",
"maximum": 3,
"minimum": 0
},
"contact_email": {
"bsonType": "string",
"description": "联系人邮箱"
},
"contact_mobile": {
"bsonType": "string",
"description": "联系人手机号码"
},
"contact_person": {
"bsonType": "string",
"description": "联系人姓名"
},
"id_card_back": {
"bsonType": "string",
"description": "身份证反面照 URL"
},
"id_card_front": {
"bsonType": "string",
"description": "身份证正面照 URL"
},
"identity": {
"bsonType": "string",
"description": "身份证号码/营业执照号码"
},
"in_hand": {
"bsonType": "string",
"description": "手持身份证照片 URL"
},
"license": {
"bsonType": "string",
"description": "营业执照 URL"
},
"real_name": {
"bsonType": "string",
"description": "真实姓名/企业名称"
},
"type": {
"bsonType": "int",
"description": "用户类型:0 个人用户 1 企业用户",
"maximum": 1,
"minimum": 0
}
},
"required": [
"type",
"auth_status"
]
},
"register_date": {
"bsonType": "timestamp",
"description": "注册时间",
"forceDefaultValue": {
"$env": "now",
"read": "doc._id == auth.uid"
}
},
"register_ip": {
"bsonType": "string",
"description": "注册时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP",
"read": "doc._id == auth.uid"
}
},
"role": {
"bsonType": "array",
"description": "用户角色",
"enum": {
"collection": "uni-id-roles",
"field": "role_id as value, role_name as text"
},
"foreignKey": "uni-id-roles.role_id",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
},
"title": "角色"
},
"score": {
"bsonType": "int",
"description": "用户积分,积分变更记录可参考:uni-id-scores表定义",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"status": {
"bsonType": "int",
"defaultValue": 0,
"description": "用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
},
"enum": [{
"text": "正常",
"value": 0
},
{
"text": "禁用",
"value": 1
},
{
"text": "审核中",
"value": 2
},
{
"text": "审核拒绝",
"value": 3
}
],
"title": "用户状态"
},
"token": {
"bsonType": "array",
"description": "用户token",
"permission": {
"read": "doc._id == auth.uid"
}
},
"username": {
"bsonType": "string",
"description": "用户名,不允许重复",
"title": "用户名",
"trim": "both",
"permission": {
"write": false
}
},
"wx_openid": {
"bsonType": "object",
"description": "微信各个平台openid",
"properties": {
"app": {
"bsonType": "string",
"description": "app平台微信openid"
},
"mp": {
"bsonType": "string",
"description": "微信小程序平台openid"
},
"h5": {
"bsonType": "string",
"description": "微信公众号登录openid"
},
"web": {
"bsonType": "string",
"description": "PC页面扫码登录openid"
}
},
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"wx_unionid": {
"bsonType": "string",
"description": "微信unionid",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"qq_openid": {
"bsonType": "object",
"description": "QQ各个平台openid",
"properties": {
"app": {
"bsonType": "string",
"description": "app平台QQ openid"
},
"mp": {
"bsonType": "string",
"description": "QQ小程序平台openid"
}
},
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
},
"qq_unionid": {
"bsonType": "string",
"description": "QQ unionid",
"permission": {
"write": false,
"read": "doc._id == auth.uid"
}
}
}
}
## 1.0.2(2022-09-02)
- 新增 依赖数据表schema opendb-open-data
## 1.0.0(2022-08-22)
- 首次发布
{
"id": "uni-open-bridge-common",
"displayName": "uni-open-bridge-common",
"version": "1.0.0",
"version": "1.0.2",
"description": "统一接管微信等三方平台认证凭据",
"keywords": [
"uni-open-bridge-common",
......
'use strict';
const TAG = "UNI_OPEN_BRIDGE"
const HTTP_STATUS = {
SUCCESS: 200
}
......@@ -13,7 +15,12 @@ const PlatformType = {
QQ_APP: 'qq-app'
}
const ErrorCodeType = {
SYSTEM_ERROR: TAG + "_SYSTEM_ERROR"
}
module.exports = {
HTTP_STATUS,
PlatformType
PlatformType,
ErrorCodeType
}
'use strict';
const {
PlatformType
PlatformType,
ErrorCodeType
} = require('./consts.js')
const {
......@@ -31,8 +32,15 @@ class AccessToken extends Storage {
async fallback(parameters) {
const oauthConfig = appConfig.get(parameters.dcloudAppid, parameters.platform)
const methodName = (parameters.platform === PlatformType.WEIXIN_MP) ? 'GetMPAccessTokenData' :
'GetH5AccessTokenData'
let methodName
if (parameters.platform === PlatformType.WEIXIN_MP) {
methodName = 'GetMPAccessTokenData'
} else if (parameters.platform === PlatformType.WEIXIN_H5) {
methodName = 'GetH5AccessTokenData'
} else {
throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, "platform invalid")
}
const responseData = await WeixinServer[methodName](oauthConfig)
const duration = responseData.expires_in
......@@ -206,5 +214,6 @@ module.exports = {
setTicket,
removeTicket,
PlatformType,
WeixinServer
WeixinServer,
ErrorCodeType
}
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": ["_id", "value"],
"properties": {
"_id": {
"bsonType": "string",
"description": "key,格式:uni-id:[dcloudAppid]:[platform]:[openid]:[access-token|user-access-token|session-key|encrypt-key-version|ticket]"
},
"value": {
"bsonType": "object",
"description": "字段_id对应的值"
},
"expired": {
"bsonType": "date",
"description": "过期时间"
}
}
}
......@@ -39,6 +39,18 @@
"bundleId": "苹果开发者后台获取的bundleId"
}
}
},
"web": {
"oauth": {
"h5-weixin": {
"appid": "微信浏览器内微信登录,所用的微信公众号appid",
"appsecret": "微信公众号后台获取的appsecret"
},
"web-weixin": {
"appid": "手机微信扫码登录,所用的微信开放平台(https://open.weixin.qq.com/)-网站应用的appid",
"appsecret": "微信开放平台-网站应用的appsecret"
}
}
},
"mp-weixin": {
"oauth": {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册