提交 3140e005 编写于 作者: DCloud_JSON's avatar DCloud_JSON 提交者: study夏羽

修复已知问题

上级 e56037a4
...@@ -87,12 +87,6 @@ console.log(` ...@@ -87,12 +87,6 @@ console.log(`
}) })
}) })
},1) },1)
//更新 uni-starter.config agreements
let agreementsTitle = $i18n('agreementsTitle').split(',')
let agreements = uniStarterConfig.about.agreements
agreements[0].title = agreementsTitle[0]
agreements[1].title = agreementsTitle[1]
uniStarterConfig.about.agreements = agreements
} }
initLanguageAfter() initLanguageAfter()
uni.$on('changeLanguage', e => { uni.$on('changeLanguage', e => {
......
...@@ -108,7 +108,7 @@ export default { ...@@ -108,7 +108,7 @@ export default {
}, },
settings:{ settings:{
navigationBarTitle:"设置", navigationBarTitle:"设置",
userInfo: "个人资料", userInfo: "账号资料",
changePassword: "修改密码", changePassword: "修改密码",
clearTmp: "清理缓存", clearTmp: "清理缓存",
pushServer: "推送功能", pushServer: "推送功能",
......
...@@ -122,12 +122,13 @@ ...@@ -122,12 +122,13 @@
"style": { "style": {
"navigationBarTitleText": "注销账号" "navigationBarTitleText": "注销账号"
} }
}, { },
{
"path": "uni_modules/uni-id-pages/pages/userinfo/userinfo", "path": "uni_modules/uni-id-pages/pages/userinfo/userinfo",
"style": { "style": {
"navigationBarTitleText": "个人资料" "navigationBarTitleText": "个人资料"
} }
}, { },{
"path": "uni_modules/uni-id-pages/pages/userinfo/bind-mobile/bind-mobile", "path": "uni_modules/uni-id-pages/pages/userinfo/bind-mobile/bind-mobile",
"style": { "style": {
"navigationBarTitleText": "绑定手机号码" "navigationBarTitleText": "绑定手机号码"
......
...@@ -18,12 +18,8 @@ ...@@ -18,12 +18,8 @@
<uni-list-item v-if="i18nEnable" :title="$t('settings.changeLanguage')" @click="changeLanguage" :rightText="currentLanguage" link></uni-list-item> <uni-list-item v-if="i18nEnable" :title="$t('settings.changeLanguage')" @click="changeLanguage" :rightText="currentLanguage" link></uni-list-item>
</uni-list> </uni-list>
<uni-list class="mt10" :border="false">
<uni-list-item @click="deactivate" :title="$t('settings.deactivate')" link="navigateTo"></uni-list-item>
</uni-list>
<!-- 退出/登录 按钮 --> <!-- 退出/登录 按钮 -->
<view class="bottom-back" @click="clickLogout"> <view class="bottom-back" @click="changeLoginState">
<text class="bottom-back-text" v-if="hasLogin">{{$t('settings.logOut')}}</text> <text class="bottom-back-text" v-if="hasLogin">{{$t('settings.logOut')}}</text>
<text class="bottom-back-text" v-else>{{$t('settings.login')}}</text> <text class="bottom-back-text" v-else>{{$t('settings.login')}}</text>
</view> </view>
...@@ -32,6 +28,7 @@ ...@@ -32,6 +28,7 @@
<script> <script>
import pushServer from './dc-push/push.js'; import pushServer from './dc-push/push.js';
import common from '@/uni_modules/uni-id-pages/common/common.js';
export default { export default {
data() { data() {
return { return {
...@@ -79,15 +76,14 @@ ...@@ -79,15 +76,14 @@
//#endif //#endif
}, },
methods: { methods: {
toEdit() { async changeLoginState(){
uni.navigateTo({ if(this.hasLogin){
url: '/pages/ucenter/userinfo/userinfo' await common.logout()
}else{
uni.redirectTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
}); });
}, }
deactivate(){
uni.navigateTo({
url:"/uni_modules/uni-id-pages/pages/userinfo/deactivate/deactivate"
})
}, },
/** /**
* 开始生物认证 * 开始生物认证
...@@ -165,36 +161,6 @@ ...@@ -165,36 +161,6 @@
}) })
}) })
}, },
clickLogout() {
console.log("this.hasLogin: ",this.hasLogin);
if (this.hasLogin) {
this.logout()
uni.navigateBack();
/* uni.showModal({
title: this.$t('settings.tips'),
content: this.$t('settings.exitLogin'),
cancelText: this.$t('settings.cancelText'),
confirmText: this.$t('settings.confirmText'),
success: res => {
console.log("res: ",res);
if (res.confirm) {
uni.removeStorageSync('uni_id_token');
uni.setStorageSync('uni_id_token_expired', 0)
uni.redirectTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
});
}
}
});
} else {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
complete: (e) => {
console.log(6369696,e);
}
});
}
},
clearTmp() { clearTmp() {
uni.showLoading({ uni.showLoading({
title: this.$t('settings.clearing'), title: this.$t('settings.clearing'),
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<view class="center"> <view class="center">
<uni-sign-in ref="signIn"></uni-sign-in> <uni-sign-in ref="signIn"></uni-sign-in>
<view class="userInfo" @click.capture="toUserInfo"> <view class="userInfo" @click.capture="toUserInfo">
<cloud-image width="150rpx" height="150rpx" v-if="userInfo.avatar_file&&userInfo.avatar_file.url" :src="userInfo.avatar_file.url"></cloud-image> <cloud-image width="150rpx" height="150rpx" v-if="hasLogin&&userInfo.avatar_file&&userInfo.avatar_file.url" :src="userInfo.avatar_file.url"></cloud-image>
<image v-else class="logo-img" src="@/static/uni-center/defaultAvatarUrl.png"></image> <image v-else class="logo-img" src="@/static/uni-center/defaultAvatarUrl.png"></image>
<view class="logo-title"> <view class="logo-title">
<text class="uer-name" v-if="hasLogin">{{userInfo.nickname||userInfo.username||userInfo.mobile}}</text> <text class="uer-name" v-if="hasLogin">{{userInfo.nickname||userInfo.username||userInfo.mobile}}</text>
...@@ -133,7 +133,8 @@ ...@@ -133,7 +133,8 @@
"radius": "100%" // 边框圆角,支持百分比 "radius": "100%" // 边框圆角,支持百分比
} }
}, },
userInfo:{} userInfo:{},
hasLogin:false
} }
}, },
onLoad() { onLoad() {
...@@ -148,12 +149,22 @@ ...@@ -148,12 +149,22 @@
//#endif //#endif
}, },
onShow() { onShow() {
console.log('this.hasLogin',this.hasLogin); this.hasLogin = uniCloud.getCurrentUserInfo().tokenExpired > Date.now()
if(this.hasLogin){ if(this.hasLogin){
this.getUserInfo() this.getUserInfo()
} }
}, },
computed: { computed: {
test:{
get(){
console.log(this._test,Date.now());
this._test = Date.now()
return ''
},
set(){
}
},
// #ifdef APP-PLUS // #ifdef APP-PLUS
appVersion() { appVersion() {
return getApp().appVersion return getApp().appVersion
...@@ -161,19 +172,10 @@ ...@@ -161,19 +172,10 @@
// #endif // #endif
appConfig() { appConfig() {
return getApp().globalData.config return getApp().globalData.config
},
hasLogin(){
return uniCloud.getCurrentUserInfo().tokenExpired > Date.now()
} }
}, },
methods: { methods: {
setUserInfo(data){
},
getUserInfo(e) { getUserInfo(e) {
uni.showLoading({
mask: true
});
const db = uniCloud.database(); const db = uniCloud.database();
db.collection('uni-id-users').where("'_id' == $cloudEnv_uid").field('mobile,nickname,avatar_file').get().then(res => { db.collection('uni-id-users').where("'_id' == $cloudEnv_uid").field('mobile,nickname,avatar_file').get().then(res => {
console.log({res}); console.log({res});
...@@ -184,7 +186,6 @@ ...@@ -184,7 +186,6 @@
console.log(e.message, e.errCode); console.log(e.message, e.errCode);
}).finally(e => { }).finally(e => {
// console.log(e); // console.log(e);
uni.hideLoading()
}) })
}, },
toSettings() { toSettings() {
......
{
"schedule": {
"__UNI__xxxxxx": {
"enable": true,
"h5-weixin": {
"enable": false,
"tasks": ["ticket"]
}
}
},
"ipWhitelist": ["0.0.0.0"]
}
\ No newline at end of file
## 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) ## 1.0.10(2022-08-25)
- 修复 导入uni-id-pages插件时未自动导入uni-open-bridge-common的Bug - 修复 导入uni-id-pages插件时未自动导入uni-open-bridge-common的Bug
## 1.0.9(2022-08-23) ## 1.0.9(2022-08-23)
......
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: '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
});
uni.$emit('uni-id-pages-logout')
},
}
\ No newline at end of file
...@@ -2,20 +2,54 @@ ...@@ -2,20 +2,54 @@
padding: 0 60rpx; padding: 0 60rpx;
} }
.login-logo {
display: none;
}
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
@media screen and (min-width: 690px) { @media screen and (min-width: 690px) {
.uni-content { .uni-content {
/* #ifndef H5 */
padding: 0; padding: 0;
max-width: 400px; max-width: 300px;
margin-left: calc(50% - 200px); 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 { .uni-content view {
box-sizing: border-box; box-sizing: border-box;
} }
/* #endif */ /* #endif */
.title { .title {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
...@@ -62,11 +96,8 @@ ...@@ -62,11 +96,8 @@
color: #FFF !important; color: #FFF !important;
border-radius: 5px; border-radius: 5px;
} }
/*
.uni-btn::after{ .uni-body.uni_modules-uni-id-pages-pages-login-login-withoutpwd{
display: none; height: auto !important;
} }
.uni-btn[disabled]{
background-color: $uni-color-primary !important; \ No newline at end of file
opacity: 0.3;
}*/
\ No newline at end of file
// 导入配置 // 导入配置
import config from '@/uni_modules/uni-id-pages/config.js' import config from '@/uni_modules/uni-id-pages/config.js'
const passwordLength = config.password.length const {passwordStrength} = config
const passwordStrength = config.password.strength
let minPasswordLength = 6
let maxPasswordLength = 20
if (passwordLength) {
if (passwordLength[0]) {
minPasswordLength = passwordLength[0]
}
if (passwordLength[1]) {
maxPasswordLength = passwordLength[1]
}
}
// 密码强度表达式 // 密码强度表达式
const passwordRules = { const passwordRules = {
// 密码必须包含大小写字母、数字和特殊符号 // 密码必须包含大小写字母、数字和特殊符号
...@@ -33,15 +22,10 @@ const ERROR = { ...@@ -33,15 +22,10 @@ const ERROR = {
rePwdErr: '两次输入密码不一致' rePwdErr: '两次输入密码不一致'
}, },
passwordStrengthError: { passwordStrengthError: {
superstrong: '密码必须包含大小写字母、数字和特殊符号', super: '密码必须包含大小写字母、数字和特殊符号,密码长度必须在8-16位之间',
strong: '密码必须包含字母、数字和特殊符号', strong: '密码必须包含字母、数字和特殊符号,密码长度必须在8-16位之间',
medium: '密码必须为字母、数字和特殊符号任意两种的组合', medium: '密码必须为字母、数字和特殊符号任意两种的组合,密码长度必须在8-16位之间',
weak: '密码必须包含字母' weak: '密码必须包含字母,密码长度必须在6-16位之间'
},
passwordLengthError: {
normal: '密码长度必须在' + minPasswordLength + '-' + maxPasswordLength + '位之间',
minLimit: '密码长度不得少于' + minPasswordLength + '',
maxLimit: '密码长度不得超过' + maxPasswordLength + ''
} }
} }
...@@ -52,16 +36,6 @@ function validPwd(password) { ...@@ -52,16 +36,6 @@ function validPwd(password) {
return ERROR.passwordStrengthError[passwordStrength] 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 return true
} }
...@@ -106,8 +80,6 @@ function getPwdRules(pwdName = 'password', rePwdName = 'password2') { ...@@ -106,8 +80,6 @@ function getPwdRules(pwdName = 'password', rePwdName = 'password2') {
export default { export default {
ERROR, ERROR,
minPasswordLength,
maxPasswordLength,
validPwd, validPwd,
getPwdRules getPwdRules
} }
...@@ -46,8 +46,8 @@ ...@@ -46,8 +46,8 @@
watch: { watch: {
src:{ src:{
handler(src) { handler(src) {
// console.log(src); console.log(src);
// console.log(src.substring(0, 8)); console.log(src.substring(0, 8));
if (src&&src.substring(0, 8) == "cloud://") { if (src&&src.substring(0, 8) == "cloud://") {
uniCloud.getTempFileURL({ uniCloud.getTempFileURL({
fileList: [src] fileList: [src]
......
<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>
...@@ -512,27 +512,37 @@ ...@@ -512,27 +512,37 @@
width: 750rpx; width: 750rpx;
justify-content: space-around; justify-content: space-around;
position: fixed; position: fixed;
bottom: 10rpx;
left: 0; left: 0;
} }
.item {
flex-direction: column;
justify-content: center;
align-items: center;
height: 200rpx;
cursor: pointer;
}
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
@media screen and (min-width: 690px) { @media screen and (min-width: 690px) {
.fab-login-box { .fab-login-box {
max-width: 500px; max-width: 500px;
margin-left: calc(50% - 250px); margin-left: calc(50% - 250px);
} }
.item {
height: 160rpx;
}
}
@media screen and (max-width: 690px) {
.fab-login-box {
bottom: 10rpx;
}
} }
/* #endif */ /* #endif */
.item {
flex-direction: column;
justify-content: center;
align-items: center;
height: 200rpx;
cursor: pointer;
}
.logo { .logo {
width: 60rpx; width: 60rpx;
......
export default { export default {
//调试模式 //调试模式
"debug": true, "debug": false,
/* /*
登录类型 未列举到的或运行环境不支持的,将被自动隐藏。 登录类型 未列举到的或运行环境不支持的,将被自动隐藏。
如果需要在不同平台有不同的配置,直接用条件编译即可 如果需要在不同平台有不同的配置,直接用条件编译即可
...@@ -45,14 +45,11 @@ export default { ...@@ -45,14 +45,11 @@ export default {
}, },
/** /**
* 密码强度 * 密码强度
* superstrong(超强:密码必须包含大小写字母、数字和特殊符号) * super(超强:密码必须包含大小写字母、数字和特殊符号,长度范围:8-16位之间)
* strong(强: 密码必须包含字母、数字和特殊符号) * strong(强: 密密码必须包含字母、数字和特殊符号,长度范围:8-16位之间)
* medium (中:密码必须为字母、数字和特殊符号任意两种的组合) * medium (中:密码必须为字母、数字和特殊符号任意两种的组合,长度范围:8-16位之间)
* weak(弱:密码必须包含字母 * weak(弱:密码必须包含字母和数字,长度范围:6-16位之间)
* 为空或false则不验证密码强度 * 为空或false则不验证密码强度
*/ */
"password": { "passwordStrength":"medium"
// "strength": "strong",
"length": [6, 20] //密码长度,默认在6-20位之间
}
} }
<!-- 短信验证码登录页 --> <!-- 短信验证码登录页 -->
<template> <template>
<view class="uni-content"> <view class="uni-content">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 --> <!-- 顶部文字 -->
<text class="title">请输入验证码</text> <text class="title">请输入验证码</text>
<text class="tip">先输入图形验证码,再获取短信验证码</text> <text class="tip">先输入图形验证码,再获取短信验证码</text>
...@@ -21,6 +24,7 @@ ...@@ -21,6 +24,7 @@
"code": "", "code": "",
"phone": "", "phone": "",
"captcha": "", "captcha": "",
"logo": "/static/logo.png"
} }
}, },
computed: { computed: {
......
<!-- 免密登录页 --> <!-- 免密登录页 -->
<template> <template>
<view class="uni-content"> <view class="uni-content">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 --> <!-- 顶部文字 -->
<text class="title">请选择登录方式</text> <text class="title">请选择登录方式</text>
<!-- 快捷登录框 当url带参数时有效 --> <!-- 快捷登录框 当url带参数时有效 -->
...@@ -36,7 +39,8 @@ ...@@ -36,7 +39,8 @@
return { return {
type: "", //快捷登录方式 type: "", //快捷登录方式
phone: "", //手机号码 phone: "", //手机号码
focusPhone:false focusPhone:false,
logo: "/static/logo.png"
} }
}, },
computed: { computed: {
...@@ -177,7 +181,7 @@ ...@@ -177,7 +181,7 @@
} }
.quickLogin { .quickLogin {
width: 650rpx; // width: 650rpx;
height: 350px; height: 350px;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
...@@ -186,6 +190,9 @@ ...@@ -186,6 +190,9 @@
.quickLoginBtn { .quickLoginBtn {
margin: 20px 0; margin: 20px 0;
width: 450rpx; width: 450rpx;
/* #ifndef APP-NVUE */
max-width: 230px;
/* #endif */
height: 82rpx; height: 82rpx;
} }
...@@ -193,4 +200,10 @@ ...@@ -193,4 +200,10 @@
margin-top: -15px; margin-top: -15px;
margin-bottom: 20px; margin-bottom: 20px;
} }
@media screen and (min-width: 690px) {
.quickLogin{
height: auto;
}
}
</style> </style>
<!-- 账号密码登录页 --> <!-- 账号密码登录页 -->
<template> <template>
<view class="uni-content"> <view class="uni-content">
<view class="login-logo">
<image :src="logo"></image>
</view>
<!-- 顶部文字 --> <!-- 顶部文字 -->
<text class="title title-box">账号密码登录</text> <text class="title title-box">账号密码登录</text>
<uni-forms> <uni-forms>
<uni-forms-item name="username"> <uni-forms-item name="username">
<uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box" :inputBorder="false" v-model="username" placeholder="请输入手机号/用户名" /> <uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box" :inputBorder="false" v-model="username" placeholder="请输入手机号/用户名/邮箱" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="password"> <uni-forms-item name="password">
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable type="password" :inputBorder="false" v-model="password" <uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable type="password" :inputBorder="false" v-model="password"
...@@ -45,7 +48,8 @@ ...@@ -45,7 +48,8 @@
"captcha": "", "captcha": "",
"needCaptcha": false, "needCaptcha": false,
"focusUsername":false, "focusUsername":false,
"focusPassword":false "focusPassword":false,
"logo": "/static/logo.png"
} }
}, },
onShow() { onShow() {
...@@ -84,7 +88,7 @@ ...@@ -84,7 +88,7 @@
if(!this.username.length){ if(!this.username.length){
this.focusUsername = true this.focusUsername = true
return uni.showToast({ return uni.showToast({
title: '请输入手机号/用户名', title: '请输入手机号/用户名/邮箱',
icon: 'none' icon: 'none'
}); });
} }
...@@ -107,6 +111,8 @@ ...@@ -107,6 +111,8 @@
if (/^1\d{10}$/.test(this.username)) { if (/^1\d{10}$/.test(this.username)) {
data.mobile = this.username data.mobile = this.username
}else if(/@/.test(this.username)) {
data.email = this.username
}else{ }else{
data.username = this.username data.username = this.username
} }
...@@ -135,7 +141,9 @@ ...@@ -135,7 +141,9 @@
<style lang="scss" scoped> <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{ .forget{
font-size: 12px; font-size: 12px;
color: #8a8f8b; color: #8a8f8b;
......
<!-- 邮箱验证码注册 -->
<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> <template>
<view class="uni-content"> <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 ref="form" :value="formData" :rules="rules" validate-trigger="submit" err-show-type="toast">
<uni-forms-item name="username" required> <uni-forms-item name="username" required>
<uni-easyinput :inputBorder="false" :focus="focusUsername" @blur="focusUsername = false" <uni-easyinput :inputBorder="false" :focus="focusUsername" @blur="focusUsername = false"
...@@ -12,7 +19,7 @@ ...@@ -12,7 +19,7 @@
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="password" v-model="formData.password" required> <uni-forms-item name="password" v-model="formData.password" required>
<uni-easyinput :inputBorder="false" :focus="focusPassword" @blur="focusPassword = false" <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" /> v-model="formData.password" trim="both" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="password2" v-model="formData.password2" required> <uni-forms-item name="password2" v-model="formData.password2" required>
...@@ -25,7 +32,13 @@ ...@@ -25,7 +32,13 @@
</uni-forms-item> </uni-forms-item>
<uni-id-pages-agreements scope="register" ref="agreements" ></uni-id-pages-agreements> <uni-id-pages-agreements scope="register" ref="agreements" ></uni-id-pages-agreements>
<button class="uni-btn" type="primary" @click="submit">注册</button> <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> </uni-forms>
</view> </view>
</template> </template>
...@@ -50,12 +63,8 @@ ...@@ -50,12 +63,8 @@
focusUsername:false, focusUsername:false,
focusNickname:false, focusNickname:false,
focusPassword:false, focusPassword:false,
focusPassword2:false focusPassword2:false,
} logo: "/static/logo.png"
},
computed:{
passwordLength(){
return config.password.length
} }
}, },
onReady() { onReady() {
...@@ -111,6 +120,16 @@ ...@@ -111,6 +120,16 @@
}, },
navigateBack() { navigateBack() {
uni.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 @@ ...@@ -118,9 +137,33 @@
<style lang="scss"> <style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss"; @import "@/uni_modules/uni-id-pages/common/login-page.scss";
@media screen and (max-width: 690px) {
.uni-content{ .uni-content{
margin-top: 15px; 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 { .uni-content ::v-deep .uni-forms-item__label {
position: absolute; position: absolute;
left: -15px; 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> <template>
<view class="uni-content"> <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 ref="form" :value="formData" err-show-type="toast">
<uni-forms-item name="phone"> <uni-forms-item name="phone">
<uni-easyinput :focus="focusPhone" @blur="focusPhone = false" class="input-box" :disabled="lock" type="number" :inputBorder="false" <uni-easyinput :focus="focusPhone" @blur="focusPhone = false" class="input-box" :disabled="lock" type="number" :inputBorder="false"
...@@ -20,6 +27,12 @@ ...@@ -20,6 +27,12 @@
placeholder="请再次输入新密码"></uni-easyinput> placeholder="请再次输入新密码"></uni-easyinput>
</uni-forms-item> </uni-forms-item>
<button class="uni-btn send-btn-box" type="primary" @click="submit">提交</button> <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-forms>
<uni-popup-captcha @confirm="submit" v-model="formData.captcha" scene="reset-pwd-by-sms" ref="popup"></uni-popup-captcha> <uni-popup-captcha @confirm="submit" v-model="formData.captcha" scene="reset-pwd-by-sms" ref="popup"></uni-popup-captcha>
</view> </view>
...@@ -101,7 +114,8 @@ ...@@ -101,7 +114,8 @@
} }
] ]
} }
} },
logo: "/static/logo.png"
} }
}, },
computed: { computed: {
...@@ -187,6 +201,11 @@ ...@@ -187,6 +201,11 @@
console.log(key,'focus'+key); console.log(key,'focus'+key);
this['focus'+key] = true this['focus'+key] = true
}) })
},
retrieveByEmail() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email'
})
} }
} }
} }
...@@ -195,7 +214,26 @@ ...@@ -195,7 +214,26 @@
<style lang="scss"> <style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss"; @import "@/uni_modules/uni-id-pages/common/login-page.scss";
.uni-content { @media screen and (max-width: 690px) {
.uni-content{
margin-top: 15px; 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> </style>
<!-- 绑定手机号码页 --> <!-- 绑定手机号码页 -->
<template> <template>
<view class="uni-content"> <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" <uni-easyinput clearable :focus="focusMobile" @blur="focusMobile = false" type="number" class="input-box" :inputBorder="false" v-model="formData.mobile"
maxlength="11" placeholder="请输入手机号"></uni-easyinput> maxlength="11" placeholder="请输入手机号"></uni-easyinput>
...@@ -20,7 +27,8 @@ ...@@ -20,7 +27,8 @@
code: "", code: "",
captcha: "" captcha: ""
}, },
focusMobile:true focusMobile:true,
logo: "/static/logo.png"
} }
}, },
computed: { computed: {
...@@ -91,6 +99,13 @@ ...@@ -91,6 +99,13 @@
padding-top: 10px; padding-top: 10px;
} }
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px 40px;
}
}
/* #ifndef APP-NVUE || VUE3 */ /* #ifndef APP-NVUE || VUE3 */
.uni-content ::v-deep .uni-easyinput__content {} .uni-content ::v-deep .uni-easyinput__content {}
......
<!-- 修改密码 --> <!-- 修改密码 -->
<template> <template>
<view class="uni-content"> <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 ref="form" :value="formData" err-show-type="toast">
<uni-forms-item name="oldPassword"> <uni-forms-item name="oldPassword">
<uni-easyinput :focus="focusOldPassword" @blur="focusOldPassword = false" class="input-box" <uni-easyinput :focus="focusOldPassword" @blur="focusOldPassword = false" class="input-box"
...@@ -81,7 +88,8 @@ ...@@ -81,7 +88,8 @@
} }
] ]
} }
} },
logo: "/static/logo.png"
} }
}, },
onReady() { onReady() {
...@@ -140,7 +148,15 @@ ...@@ -140,7 +148,15 @@
<style lang="scss"> <style lang="scss">
@import "@/uni_modules/uni-id-pages/common/login-page.scss"; @import "@/uni_modules/uni-id-pages/common/login-page.scss";
.uni-content { @media screen and (max-width: 690px) {
.uni-content{
margin-top: 15px; margin-top: 15px;
} }
}
@media screen and (min-width: 690px) {
.uni-content{
padding: 30px 40px 40px;
}
}
</style> </style>
<!-- 注销(销毁)账号 --> <!-- 注销(销毁)账号 -->
<template> <template>
<view class="content"> <view class="uni-content">
<text class="words" space="emsp"> <text class="words" space="emsp">
一、注销是不可逆操作,注销后:\n 一、注销是不可逆操作,注销后:\n
1.帐号将无法登录、无法找回。\n 1.帐号将无法登录、无法找回。\n
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
</script> </script>
<style> <style>
.content { .uni-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
font-size: 28rpx; font-size: 28rpx;
...@@ -77,20 +77,6 @@ ...@@ -77,20 +77,6 @@
margin-bottom: 80px; 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 { .button-group button {
border-radius: 100px; border-radius: 100px;
border: none; border: none;
...@@ -108,4 +94,26 @@ ...@@ -108,4 +94,26 @@
color: #e64340; color: #e64340;
border: solid 1px #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> </style>
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: ''
},
hasLogin: false,
hasPwd: false
}
},
async onShow() {
this.univerifyStyle.authButton.title = "本机号码一键绑定"
this.univerifyStyle.otherLoginButton.title = "其他号码绑定"
},
async onLoad() {
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',
});
},
changePassword() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd',
complete: (e) => {
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"
})
}
}
}
...@@ -21,14 +21,17 @@ ...@@ -21,14 +21,17 @@
</uni-popup-dialog> </uni-popup-dialog>
</uni-popup> </uni-popup>
<uni-id-pages-bind-mobile ref="bind-mobile-by-sms" @success="getUserInfo"></uni-id-pages-bind-mobile> <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-if="hasLogin" @click="logout">退出登录</button>
<button v-else @click="login">去登录</button> <button v-else @click="login">去登录</button>
</template>
</view> </view>
</template> </template>
<script> <script>
const db = uniCloud.database(); const db = uniCloud.database();
const usersTable = db.collection('uni-id-users') const usersTable = db.collection('uni-id-users')
const uniIdCo = uniCloud.importObject("uni-id-co") const uniIdCo = uniCloud.importObject("uni-id-co")
import common from '@/uni_modules/uni-id-pages/common/common.js';
export default { export default {
data() { data() {
return { return {
...@@ -45,14 +48,18 @@ ...@@ -45,14 +48,18 @@
nickname:'' nickname:''
}, },
hasLogin: false, hasLogin: false,
hasPwd:false hasPwd:false,
showLoginManage:false//通过页面传参隐藏登录&退出登录按钮
} }
}, },
async onShow() { async onShow() {
this.univerifyStyle.authButton.title = "本机号码一键绑定" this.univerifyStyle.authButton.title = "本机号码一键绑定"
this.univerifyStyle.otherLoginButton.title = "其他号码绑定" this.univerifyStyle.otherLoginButton.title = "其他号码绑定"
}, },
async onLoad() { async onLoad(e) {
if(e.showLoginManage){
this.showLoginManage = true//通过页面传参隐藏登录&退出登录按钮
}
this.getUserInfo() this.getUserInfo()
//判断当前用户是否有密码,否则就不显示密码修改功能 //判断当前用户是否有密码,否则就不显示密码修改功能
let res = await uniIdCo.getAccountInfo() let res = await uniIdCo.getAccountInfo()
...@@ -67,14 +74,7 @@ ...@@ -67,14 +74,7 @@
} }
}) })
}, },
async logout() { logout:common.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',
});
},
changePassword(){ changePassword(){
uni.navigateTo({ uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd', url: '/uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd',
...@@ -206,7 +206,17 @@ ...@@ -206,7 +206,17 @@
box-sizing: border-box; box-sizing: border-box;
flex-direction: column; 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 */ /* #endif */
.avatar { .avatar {
align-items: center; align-items: center;
......
{
"pages": [
{
"path": "uni_modules/uni-id-pages/pages/userinfo/deactivate/deactivate",
"style": {
"navigationBarTitleText": "注销账号"
}
},
{
"path": "uni_modules/uni-id-pages/pages/userinfo/userinfo",
"style": {
"navigationBarTitleText": "个人资料"
}
},
{
"path": "uni_modules/uni-id-pages/pages/userinfo/bind-mobile/bind-mobile",
"style": {
"navigationBarTitleText": "绑定手机号码"
}
},
{
"path": "uni_modules/uni-id-pages/pages/userinfo/cropImage/cropImage",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "uni_modules/uni-id-pages/pages/login/login-withoutpwd",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "uni_modules/uni-id-pages/pages/login/login-withpwd",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "uni_modules/uni-id-pages/pages/login/login-smscode",
"style": {
"navigationBarTitleText": "手机验证码登录"
}
},
{
"path": "uni_modules/uni-id-pages/pages/register/register",
"style": {
"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
}
}
]
}
\ No newline at end of file
...@@ -29,6 +29,21 @@ baseValidator.username = function (username) { ...@@ -29,6 +29,21 @@ baseValidator.username = function (username) {
} }
} }
baseValidator.password = function (password) {
const errCode = ERROR.INVALID_PASSWORD
if (!isValidString(password)) {
return {
errCode
}
}
if (password.length < 6) {
// 密码长度不能小于6
return {
errCode
}
}
}
baseValidator.mobile = function (mobile) { baseValidator.mobile = function (mobile) {
const errCode = ERROR.INVALID_MOBILE const errCode = ERROR.INVALID_MOBILE
if (!isValidString(mobile)) { if (!isValidString(mobile)) {
...@@ -92,7 +107,7 @@ baseType.forEach((type) => { ...@@ -92,7 +107,7 @@ baseType.forEach((type) => {
} }
}) })
function tokenize (name) { function tokenize(name) {
let i = 0 let i = 0
const result = [] const result = []
let token = '' let token = ''
...@@ -122,7 +137,7 @@ function tokenize (name) { ...@@ -122,7 +137,7 @@ function tokenize (name) {
* 处理validator名 * 处理validator名
* @param {string} name * @param {string} name
*/ */
function parseValidatorName (name) { function parseValidatorName(name) {
const tokenList = tokenize(name) const tokenList = tokenize(name)
let i = 0 let i = 0
let currentToken = tokenList[i] let currentToken = tokenList[i]
...@@ -172,7 +187,7 @@ function parseValidatorName (name) { ...@@ -172,7 +187,7 @@ function parseValidatorName (name) {
return result return result
} }
function getRuleCategory (rule) { function getRuleCategory(rule) {
switch (rule.type) { switch (rule.type) {
case 'array': case 'array':
return 'array' return 'array'
...@@ -183,7 +198,7 @@ function getRuleCategory (rule) { ...@@ -183,7 +198,7 @@ function getRuleCategory (rule) {
} }
} }
function isMatchUnionType (val, rule) { function isMatchUnionType(val, rule) {
if (!rule.children || rule.children.length === 0) { if (!rule.children || rule.children.length === 0) {
return true return true
} }
...@@ -209,7 +224,7 @@ function isMatchUnionType (val, rule) { ...@@ -209,7 +224,7 @@ function isMatchUnionType (val, rule) {
return false return false
} }
function isMatchBaseType (val, rule) { function isMatchBaseType(val, rule) {
if (typeof baseValidator[rule.type] !== 'function') { if (typeof baseValidator[rule.type] !== 'function') {
throw new Error(`invalid schema type: ${rule.type}`) throw new Error(`invalid schema type: ${rule.type}`)
} }
...@@ -220,7 +235,7 @@ function isMatchBaseType (val, rule) { ...@@ -220,7 +235,7 @@ function isMatchBaseType (val, rule) {
return true return true
} }
function isMatchArrayType (arr, rule) { function isMatchArrayType(arr, rule) {
if (getType(arr) !== 'array') { if (getType(arr) !== 'array') {
return false return false
} }
...@@ -249,11 +264,12 @@ const passwordRules = { ...@@ -249,11 +264,12 @@ const passwordRules = {
// 密码必须为字母、数字和特殊符号任意两种的组合 // 密码必须为字母、数字和特殊符号任意两种的组合
medium: /^(?![0-9]+$)(?![a-zA-Z]+$)(?![~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]+$)[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/, medium: /^(?![0-9]+$)(?![a-zA-Z]+$)(?![~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]+$)[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/,
// 密码必须包含字母和数字 // 密码必须包含字母和数字
weak: /^(?=.*[0-9])(?=.*[a-zA-Z])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{6,16}$/ weak: /^(?=.*[0-9])(?=.*[a-zA-Z])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{6,16}$/,
} }
function createPasswordVerifier ({ function createPasswordVerifier({
passwordStrength = 'medium' passwordStrength = ''
} = {}) { } = {}) {
return function (password) { return function (password) {
const passwordRegExp = passwordRules[passwordStrength] const passwordRegExp = passwordRules[passwordStrength]
...@@ -275,11 +291,12 @@ function createPasswordVerifier ({ ...@@ -275,11 +291,12 @@ function createPasswordVerifier ({
} }
class Validator { class Validator {
constructor ({ constructor({
passwordStrength = 'medium' passwordStrength = ''
} = {}) { } = {}) {
this.baseValidator = baseValidator this.baseValidator = baseValidator
this.customValidator = Object.create(null) this.customValidator = Object.create(null)
if (passwordStrength) {
this.mixin( this.mixin(
'password', 'password',
createPasswordVerifier({ createPasswordVerifier({
...@@ -287,16 +304,17 @@ class Validator { ...@@ -287,16 +304,17 @@ class Validator {
}) })
) )
} }
}
mixin (type, handler) { mixin(type, handler) {
this.customValidator[type] = handler this.customValidator[type] = handler
} }
getRealBaseValidator (type) { getRealBaseValidator(type) {
return this.customValidator[type] || this.baseValidator[type] return this.customValidator[type] || this.baseValidator[type]
} }
get validator () { get validator() {
return new Proxy({}, { return new Proxy({}, {
get: (_, prop) => { get: (_, prop) => {
if (typeof prop !== 'string') { if (typeof prop !== 'string') {
...@@ -318,7 +336,7 @@ class Validator { ...@@ -318,7 +336,7 @@ class Validator {
}) })
} }
validate (value = {}, schema = {}) { validate(value = {}, schema = {}) {
for (const schemaKey in schema) { for (const schemaKey in schema) {
let schemaValue = schema[schemaKey] let schemaValue = schema[schemaKey]
if (getType(schemaValue) === 'string') { if (getType(schemaValue) === 'string') {
...@@ -358,7 +376,7 @@ class Validator { ...@@ -358,7 +376,7 @@ class Validator {
} }
} }
function checkClientInfo (clientInfo) { function checkClientInfo(clientInfo) {
const stringNotRequired = { const stringNotRequired = {
required: false, required: false,
type: 'string' type: 'string'
......
const assert = require('assert')
const {
Validator
} = require('./validator')
const {
ERROR
} = require('./error')
const {
getType
} = require('./utils')
const testCaseList = [{
value: {
username: 'uname'
},
schema: {
username: 'username'
},
expected: undefined
}, {
value: {
username: '123456'
},
schema: {
username: 'username'
},
expected: {
errCode: ERROR.INVALID_USERNAME
}
}, {
value: {
username: '数字天堂'
},
schema: {
username: 'username'
},
expected: {
errCode: ERROR.INVALID_USERNAME
}
}, {
value: {
password: '123456abc'
},
schema: {
password: 'password'
}
}, {
value: {
password: '123456def'
},
schema: {
password: 'password'
},
mixin: [{
type: 'password',
handler: function (password) {
if (typeof password !== 'string' || password.length < 10) {
return {
errCode: ERROR.INVALID_PASSWORD
}
}
}
}],
expected: {
errCode: ERROR.INVALID_PASSWORD
}
}, {
value: {
numberOrString: '123456'
},
schema: {
numberOrString: 'number|string'
}
}, {
value: {
numberOrString: 123456
},
schema: {
numberOrString: 'number|string'
}
}, {
value: {
numberOrString: '123456'
},
schema: {
numberOrString: 'string|number'
}
}, {
value: {
numberOrString: 123456
},
schema: {
numberOrString: 'string|number'
}
}, {
value: {
numberOrString: ['123456']
},
schema: {
numberOrString: 'array<number|string>'
}
}, {
value: {
numberOrString: [123456]
},
schema: {
numberOrString: 'array<number|string>'
}
}, {
value: {
numberOrString: [123456, '123456']
},
schema: {
numberOrString: 'array<number|string>'
}
}, {
value: {
numberOrString: ['123456']
},
schema: {
numberOrString: 'array<string|number>'
}
}, {
value: {
numberOrString: [123456]
},
schema: {
numberOrString: 'array<string|number>'
}
}, {
value: {
numberOrString: [123456, '123456']
},
schema: {
numberOrString: 'array<string|number>'
}
}, {
value: {
numberOrString: ['123456']
},
mixin: [{
type: '1to6',
handler: function (val) {
if (val !== '123456') {
return {
errCode: ERROR.INVALID_PARAM
}
}
}
}],
schema: {
numberOrString: 'array<number|1to6>'
}
}]
function execTestCase ({
value = {},
schema = {},
mixin = [],
expected = undefined,
error = ''
} = {}) {
const validator = new Validator()
for (let i = 0; i < mixin.length; i++) {
const {
type,
handler
} = mixin[i]
validator.mixin(type, handler)
}
let validateResult,
validateError
try {
validateResult = validator.validate(value, schema)
} catch (err) {
validateError = err
}
const tag = JSON.stringify({ value, schema })
if (error) {
if (typeof error === 'string') {
assert.strictEqual(validateError.message.indexOf(error) > -1, true, `[${tag}] error message error`)
} else if (getType(error) === 'regexp') {
assert.strictEqual(error.test(validateError), true, `[${tag}] error message error`)
} else {
throw new Error(`[${tag}] invalid test case`)
}
return
}
if (expected === undefined) {
assert.strictEqual(validateResult, undefined, `[${tag}] validate result error`)
return
}
const expectedKeys = Object.keys(expected)
let passResultCheck = true
for (let i = 0; i < expectedKeys.length; i++) {
const key = expectedKeys[i]
if (expected[key] !== validateResult[key]) {
passResultCheck = false
break
}
}
assert.strictEqual(passResultCheck, true, `[${tag}] validate result error`)
}
for (let i = 0; i < testCaseList.length; i++) {
console.log(`test case: ${i}`)
execTestCase(testCaseList[i])
console.log(`test case: ${i}, pass`)
}
...@@ -7,6 +7,9 @@ module.exports = { ...@@ -7,6 +7,9 @@ module.exports = {
// permission: [] // 允许进行此操作的权限,包含任一权限均可操作。 // permission: [] // 允许进行此操作的权限,包含任一权限均可操作。
// 权限角色均配置时,用户拥有任一权限或任一角色均可操作 // 权限角色均配置时,用户拥有任一权限或任一角色均可操作
}, },
updateUser: {
role: ['admin']
},
authorizeAppLogin: { authorizeAppLogin: {
role: ['admin'] role: ['admin']
}, },
......
...@@ -18,7 +18,8 @@ const { ...@@ -18,7 +18,8 @@ const {
registerUser registerUser
} = require('./module/register/index') } = require('./module/register/index')
const { const {
addUser addUser,
updateUser
} = require('./module/admin/index') } = require('./module/admin/index')
const { const {
login, login,
...@@ -109,7 +110,7 @@ module.exports = { ...@@ -109,7 +110,7 @@ module.exports = {
this.hooks = this.configUtils.getHooks() this.hooks = this.configUtils.getHooks()
this.validator = new Validator({ this.validator = new Validator({
passwordStrength: this.config.passwordStrength || 'medium' passwordStrength: this.config.passwordStrength
}) })
/** /**
* 示例:覆盖密码验证规则 * 示例:覆盖密码验证规则
...@@ -216,6 +217,23 @@ module.exports = { ...@@ -216,6 +217,23 @@ module.exports = {
* @returns * @returns
*/ */
addUser, addUser,
/**
* 修改用户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#update-user
* @param {Object} params
* @param {String} params.id 要更新的用户id
* @param {String} params.username 用户名
* @param {String} params.password 密码
* @param {String} params.nickname 昵称
* @param {Array} params.authorizedApp 允许登录的AppID列表
* @param {Array} params.role 用户角色列表
* @param {String} params.mobile 手机号
* @param {String} params.email 邮箱
* @param {Array} params.tags 用户标签
* @param {Number} params.status 用户状态
* @returns
*/
updateUser,
/** /**
* 授权用户登录应用 * 授权用户登录应用
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#authorize-app-login * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#authorize-app-login
......
...@@ -4,8 +4,8 @@ const { ...@@ -4,8 +4,8 @@ const {
const createConfig = require('uni-config-center') const createConfig = require('uni-config-center')
const requiredConfig = { const requiredConfig = {
'web.h5-weixin': ['appid', 'appsecret'], 'web.weixin-h5': ['appid', 'appsecret'],
'web.web-weixin': ['appid', 'appsecret'], 'web.weixin-web': ['appid', 'appsecret'],
'app.weixin': ['appid', 'appsecret'], 'app.weixin': ['appid', 'appsecret'],
'mp-weixin.weixin': ['appid', 'appsecret'], 'mp-weixin.weixin': ['appid', 'appsecret'],
'app.qq': ['appid', 'appsecret'], 'app.qq': ['appid', 'appsecret'],
......
...@@ -8,6 +8,9 @@ const { ...@@ -8,6 +8,9 @@ const {
const { const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
const {
logout
} = require('./logout')
const PasswordUtils = require('./password') const PasswordUtils = require('./password')
async function realPreLogin (params = {}) { async function realPreLogin (params = {}) {
...@@ -173,10 +176,14 @@ async function postLogin (params = {}) { ...@@ -173,10 +176,14 @@ async function postLogin (params = {}) {
extraData, extraData,
isThirdParty = false isThirdParty = false
} = params } = params
const {
clientIP,
uniIdToken
} = this.getClientInfo()
const uid = user._id const uid = user._id
const updateData = { const updateData = {
last_login_date: Date.now(), last_login_date: Date.now(),
last_login_ip: this.getClientInfo().clientIP, last_login_ip: clientIP,
...extraData ...extraData
} }
const { const {
...@@ -185,6 +192,13 @@ async function postLogin (params = {}) { ...@@ -185,6 +192,13 @@ async function postLogin (params = {}) {
} = await this.uniIdCommon.createToken({ } = await this.uniIdCommon.createToken({
uid uid
}) })
if (uniIdToken) {
try {
await logout.call(this)
} catch (error) {}
}
await userCollection.doc(uid).update(updateData) await userCollection.doc(uid).update(updateData)
await this.middleware.uniIdLog({ await this.middleware.uniIdLog({
data: { data: {
......
const {
dbCmd,
LOG_TYPE,
deviceCollection,
userCollection
} = require('../../common/constants')
async function logout() {
const {
uniIdToken,
deviceId
} = this.getClientInfo()
const {
uid
} = await this.uniIdCommon.checkToken(
uniIdToken,
{
autoRefresh: false
}
)
// 删除token
await userCollection.doc(uid).update({
token: dbCmd.pull(uniIdToken)
})
// 仅当device表的device_id和user_id均对应时才进行更新
await deviceCollection.where({
device_id: deviceId,
user_id: uid
}).update({
token_expired: 0
})
await this.middleware.uniIdLog({
data: {
user_id: uid
},
type: LOG_TYPE.LOGOUT
})
return {
errCode: 0
}
}
module.exports = {
logout
}
\ No newline at end of file
...@@ -5,7 +5,7 @@ const { ...@@ -5,7 +5,7 @@ const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
function getQQPlatform () { function getQQPlatform() {
const platform = this.clientPlatform const platform = this.clientPlatform
switch (platform) { switch (platform) {
case 'app': case 'app':
...@@ -18,7 +18,7 @@ function getQQPlatform () { ...@@ -18,7 +18,7 @@ function getQQPlatform () {
} }
} }
async function saveQQUserKey ({ async function saveQQUserKey({
openid, openid,
sessionKey, // QQ小程序用户sessionKey sessionKey, // QQ小程序用户sessionKey
accessToken, // App端QQ用户accessToken accessToken, // App端QQ用户accessToken
...@@ -45,14 +45,17 @@ async function saveQQUserKey ({ ...@@ -45,14 +45,17 @@ async function saveQQUserKey ({
await this.uniOpenBridge.setUserAccessToken(keyObj, { await this.uniOpenBridge.setUserAccessToken(keyObj, {
access_token: accessToken, access_token: accessToken,
access_token_expired: accessTokenExpired access_token_expired: accessTokenExpired
}, Math.floor((accessTokenExpired - Date.now()) / 1000)) }, accessTokenExpired ?
Math.floor((accessTokenExpired - Date.now()) / 1000) :
30 * 24 * 60 * 60
)
break break
default: default:
break break
} }
} }
function generateQQCache ({ function generateQQCache({
sessionKey, // QQ小程序用户sessionKey sessionKey, // QQ小程序用户sessionKey
accessToken, // App端QQ用户accessToken accessToken, // App端QQ用户accessToken
accessTokenExpired // App端QQ用户accessToken过期时间 accessTokenExpired // App端QQ用户accessToken过期时间
...@@ -81,7 +84,7 @@ function generateQQCache ({ ...@@ -81,7 +84,7 @@ function generateQQCache ({
} }
} }
function getQQOpenid ({ function getQQOpenid({
userRecord userRecord
} = {}) { } = {}) {
const qqPlatform = getQQPlatform.call(this) const qqPlatform = getQQPlatform.call(this)
...@@ -93,7 +96,7 @@ function getQQOpenid ({ ...@@ -93,7 +96,7 @@ function getQQOpenid ({
return qqOpenidObj[`${qqPlatform}_${appId}`] || qqOpenidObj[qqPlatform] return qqOpenidObj[`${qqPlatform}_${appId}`] || qqOpenidObj[qqPlatform]
} }
async function getQQCacheFallback ({ async function getQQCacheFallback({
userRecord, userRecord,
key key
} = {}) { } = {}) {
...@@ -106,7 +109,7 @@ async function getQQCacheFallback ({ ...@@ -106,7 +109,7 @@ async function getQQCacheFallback ({
return qqCache && qqCache[key] return qqCache && qqCache[key]
} }
async function getQQCache ({ async function getQQCache({
uid, uid,
userRecord, userRecord,
key key
......
...@@ -12,10 +12,13 @@ const { ...@@ -12,10 +12,13 @@ const {
getValidInviteCode, getValidInviteCode,
generateInviteInfo generateInviteInfo
} = require('./fission') } = require('./fission')
const {
logout
} = require('./logout')
const PasswordUtils = require('./password') const PasswordUtils = require('./password')
const merge = require('lodash.merge') const merge = require('lodash.merge')
async function realPreRegister (params = {}) { async function realPreRegister(params = {}) {
const { const {
user user
} = params } = params
...@@ -30,7 +33,7 @@ async function realPreRegister (params = {}) { ...@@ -30,7 +33,7 @@ async function realPreRegister (params = {}) {
} }
} }
async function preRegister (params = {}) { async function preRegister(params = {}) {
try { try {
await realPreRegister.call(this, params) await realPreRegister.call(this, params)
} catch (error) { } catch (error) {
...@@ -42,7 +45,7 @@ async function preRegister (params = {}) { ...@@ -42,7 +45,7 @@ async function preRegister (params = {}) {
} }
} }
async function preRegisterWithPassword (params = {}) { async function preRegisterWithPassword(params = {}) {
const { const {
user, user,
password password
...@@ -69,7 +72,7 @@ async function preRegisterWithPassword (params = {}) { ...@@ -69,7 +72,7 @@ async function preRegisterWithPassword (params = {}) {
} }
} }
async function thirdPartyRegister ({ async function thirdPartyRegister({
user = {} user = {}
} = {}) { } = {}) {
return { return {
...@@ -78,7 +81,7 @@ async function thirdPartyRegister ({ ...@@ -78,7 +81,7 @@ async function thirdPartyRegister ({
} }
} }
async function postRegister (params = {}) { async function postRegister(params = {}) {
const { const {
user, user,
extraData = {}, extraData = {},
...@@ -93,7 +96,8 @@ async function postRegister (params = {}) { ...@@ -93,7 +96,8 @@ async function postRegister (params = {}) {
channel, channel,
scene, scene,
clientIP, clientIP,
osName osName,
uniIdToken
} = this.getClientInfo() } = this.getClientInfo()
merge(user, extraData) merge(user, extraData)
...@@ -147,6 +151,12 @@ async function postRegister (params = {}) { ...@@ -147,6 +151,12 @@ async function postRegister (params = {}) {
user.invite_time = inviteTime user.invite_time = inviteTime
} }
if (uniIdToken) {
try {
await logout.call(this)
} catch (error) {}
}
const beforeRegister = this.hooks.beforeRegister const beforeRegister = this.hooks.beforeRegister
let userRecord = user let userRecord = user
if (beforeRegister) { if (beforeRegister) {
......
...@@ -78,7 +78,7 @@ async function saveWeixinUserKey ({ ...@@ -78,7 +78,7 @@ async function saveWeixinUserKey ({
access_token: accessToken, access_token: accessToken,
refresh_token: refreshToken, refresh_token: refreshToken,
access_token_expired: accessTokenExpired access_token_expired: accessTokenExpired
}, 30 * 24 * 3600) }, 30 * 24 * 60 * 60)
break break
default: default:
break break
......
...@@ -18,6 +18,10 @@ const PasswordUtils = require('../../lib/utils/password') ...@@ -18,6 +18,10 @@ const PasswordUtils = require('../../lib/utils/password')
* @param {String} params.nickname 昵称 * @param {String} params.nickname 昵称
* @param {Array} params.authorizedApp 允许登录的AppID列表 * @param {Array} params.authorizedApp 允许登录的AppID列表
* @param {Array} params.role 用户角色列表 * @param {Array} params.role 用户角色列表
* @param {String} params.mobile 手机号
* @param {String} params.email 邮箱
* @param {Array} params.tags 用户标签
* @param {Number} params.status 用户状态
* @returns * @returns
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
...@@ -35,6 +39,22 @@ module.exports = async function (params = {}) { ...@@ -35,6 +39,22 @@ module.exports = async function (params = {}) {
role: { role: {
require: false, require: false,
type: 'array<string>' type: 'array<string>'
},
mobile: {
required: false,
type: 'mobile'
},
email: {
required: false,
type: 'email'
},
tags: {
required: false,
type: 'array<string>'
},
status: {
required: false,
type: 'number'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
...@@ -43,11 +63,17 @@ module.exports = async function (params = {}) { ...@@ -43,11 +63,17 @@ module.exports = async function (params = {}) {
password, password,
authorizedApp, authorizedApp,
nickname, nickname,
role role,
mobile,
email,
tags,
status
} = params } = params
const userMatched = await findUser({ const userMatched = await findUser({
userQuery: { userQuery: {
username username,
mobile,
email
}, },
authorizedApp authorizedApp
}) })
...@@ -65,17 +91,28 @@ module.exports = async function (params = {}) { ...@@ -65,17 +91,28 @@ module.exports = async function (params = {}) {
} = passwordUtils.generatePasswordHash({ } = passwordUtils.generatePasswordHash({
password password
}) })
const data = {
await userCollection.add({
username, username,
password: passwordHash, password: passwordHash,
password_secret_version: version, password_secret_version: version,
dcloud_appid: authorizedApp || [], dcloud_appid: authorizedApp || [],
nickname, nickname,
role: role || [] role: role || [],
}) mobile,
email,
tags: tags || [],
status
}
if (email) {
data.email_confirmed = 1
}
if (mobile) {
data.mobile_confirmed = 1
}
await userCollection.add(data)
return { return {
errCode: 0 errCode: 0,
errMsg: ''
} }
} }
module.exports = { module.exports = {
addUser: require('./add-user') addUser: require('./add-user'),
updateUser: require('./update-user')
} }
const {
findUser
} = require('../../lib/utils/account')
const {
ERROR
} = require('../../common/error')
const {
userCollection
} = require('../../common/constants')
const PasswordUtils = require('../../lib/utils/password')
/**
* 修改用户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#update-user
* @param {Object} params
* @param {String} params.uid 要更新的用户id
* @param {String} params.username 用户名
* @param {String} params.password 密码
* @param {String} params.nickname 昵称
* @param {Array} params.authorizedApp 允许登录的AppID列表
* @param {Array} params.role 用户角色列表
* @param {String} params.mobile 手机号
* @param {String} params.email 邮箱
* @param {Array} params.tags 用户标签
* @param {Number} params.status 用户状态
* @returns
*/
module.exports = async function (params = {}) {
const schema = {
uid: 'string',
username: 'username',
password: {
required: false,
type: 'password'
},
authorizedApp: {
required: false,
type: 'array<string>'
}, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录
nickname: {
required: false,
type: 'nickname'
},
role: {
require: false,
type: 'array<string>'
},
mobile: {
required: false,
type: 'mobile'
},
email: {
required: false,
type: 'email'
},
tags: {
required: false,
type: 'array<string>'
},
status: {
required: false,
type: 'number'
}
}
this.middleware.validate(params, schema)
const {
uid,
username,
password,
authorizedApp,
nickname,
role,
mobile,
email,
tags,
status
} = params
// 更新的用户数据字段
const data = {
username,
dcloud_appid: authorizedApp || [],
nickname,
role: role || [],
mobile,
email,
tags: tags || [],
status
}
// 更新用户名时验证用户名是否重新
if (username) {
const userMatched = await findUser({
userQuery: {
username
},
authorizedApp
})
if (userMatched.filter(user => user._id !== uid).length) {
throw {
errCode: ERROR.ACCOUNT_EXISTS
}
}
}
if (password) {
const passwordUtils = new PasswordUtils({
passwordSecret: this.config.passwordSecret
})
const {
passwordHash,
version
} = passwordUtils.generatePasswordHash({
password
})
data.password = passwordHash
data.password_secret_version = version
}
await userCollection.doc(uid).update(data)
return {
errCode: 0
}
}
const { const {
dbCmd, logout
LOG_TYPE, } = require('../../lib/utils/logout')
deviceCollection,
userCollection
} = require('../../common/constants')
/** /**
* 用户退出登录 * 用户退出登录
...@@ -11,37 +8,7 @@ const { ...@@ -11,37 +8,7 @@ const {
* @returns * @returns
*/ */
module.exports = async function () { module.exports = async function () {
const { await logout.call(this)
uniIdToken,
deviceId
} = this.getClientInfo()
const {
uid
} = await this.uniIdCommon.checkToken(
uniIdToken,
{
autoRefresh: false
}
)
// 删除token
await userCollection.doc(uid).update({
token: dbCmd.pull(uniIdToken)
})
// 仅当device表的device_id和user_id均对应时才进行更新
await deviceCollection.where({
device_id: deviceId,
user_id: uid
}).update({
token_expired: 0
})
await this.middleware.uniIdLog({
data: {
user_id: uid
},
type: LOG_TYPE.LOGOUT
})
return { return {
errCode: 0 errCode: 0
} }
......
...@@ -16,7 +16,7 @@ module.exports = async function (params = {}) { ...@@ -16,7 +16,7 @@ module.exports = async function (params = {}) {
uid: 'string', uid: 'string',
appId: 'string' appId: 'string'
} }
this.moddleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
uid, uid,
appId appId
......
{ {
"name": "uni-id-co", "name": "uni-id-co",
"version": "1.0.10", "version": "1.0.12",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"keywords": [], "keywords": [],
......
'use strict'; 'use strict';
const TAG = "UNI_OPEN_BRIDGE"
const HTTP_STATUS = { const HTTP_STATUS = {
SUCCESS: 200 SUCCESS: 200
} }
...@@ -13,7 +15,12 @@ const PlatformType = { ...@@ -13,7 +15,12 @@ const PlatformType = {
QQ_APP: 'qq-app' QQ_APP: 'qq-app'
} }
const ErrorCodeType = {
SYSTEM_ERROR: TAG + "_SYSTEM_ERROR"
}
module.exports = { module.exports = {
HTTP_STATUS, HTTP_STATUS,
PlatformType PlatformType,
ErrorCodeType
} }
'use strict'; 'use strict';
const { const {
PlatformType PlatformType,
ErrorCodeType
} = require('./consts.js') } = require('./consts.js')
const { const {
...@@ -31,8 +32,15 @@ class AccessToken extends Storage { ...@@ -31,8 +32,15 @@ class AccessToken extends Storage {
async fallback(parameters) { async fallback(parameters) {
const oauthConfig = appConfig.get(parameters.dcloudAppid, parameters.platform) const oauthConfig = appConfig.get(parameters.dcloudAppid, parameters.platform)
const methodName = (parameters.platform === PlatformType.WEIXIN_MP) ? 'GetMPAccessTokenData' : let methodName
'GetH5AccessTokenData' 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 responseData = await WeixinServer[methodName](oauthConfig)
const duration = responseData.expires_in const duration = responseData.expires_in
...@@ -206,5 +214,6 @@ module.exports = { ...@@ -206,5 +214,6 @@ module.exports = {
setTicket, setTicket,
removeTicket, removeTicket,
PlatformType, PlatformType,
WeixinServer WeixinServer,
ErrorCodeType
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册