微信登录引导头像昵称
This commit is contained in:
parent
e6a92a479b
commit
4617c65581
|
|
@ -26,3 +26,18 @@ export function userMnpMobile(data: any) {
|
||||||
export function userChangePwd(data: any) {
|
export function userChangePwd(data: any) {
|
||||||
return request.post({ url: '/user/changePwd', data }, { isAuth: true })
|
return request.post({ url: '/user/changePwd', data }, { isAuth: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 绑定小程序
|
||||||
|
export function mnpAuthBind(data: any) {
|
||||||
|
return request.post({ url: '/user/bindMnp', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绑定公众号
|
||||||
|
export function oaAuthBind(data: any) {
|
||||||
|
return request.post({ url: '/user/bindOa', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新微信小程序头像昵称
|
||||||
|
export function updateUser(data: Record<string, any>, header: any) {
|
||||||
|
return request.post({ url: '/user/updateUser', data, header })
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
<template>
|
||||||
|
<button
|
||||||
|
class="avatar-upload p-0 m-0 rounded"
|
||||||
|
:style="styles"
|
||||||
|
hover-class="none"
|
||||||
|
open-type="chooseAvatar"
|
||||||
|
@click="chooseAvatar"
|
||||||
|
@chooseavatar="chooseAvatar"
|
||||||
|
>
|
||||||
|
<image class="w-full h-full" mode="heightFix" :src="modelValue" v-if="modelValue" />
|
||||||
|
<slot v-else>
|
||||||
|
<div
|
||||||
|
:style="styles"
|
||||||
|
class="border border-dotted border-light flex w-full h-full flex-col items-center justify-center text-muted text-xs box-border rounded"
|
||||||
|
>
|
||||||
|
<u-icon name="plus" :size="36" />
|
||||||
|
添加图片
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { uploadImage } from '@/api/app'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { addUnit } from '@/utils/util'
|
||||||
|
import { isBoolean } from 'lodash'
|
||||||
|
import { computed, CSSProperties, onUnmounted } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
fileKey: {
|
||||||
|
type: String,
|
||||||
|
default: 'path'
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 120
|
||||||
|
},
|
||||||
|
round: {
|
||||||
|
type: [Boolean, String, Number],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(event: 'update:modelValue', value: string): void
|
||||||
|
}>()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const styles = computed<CSSProperties>(() => {
|
||||||
|
const size = addUnit(props.size)
|
||||||
|
return {
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
borderRadius: isBoolean(props.round) ? (props.round ? '50%' : '') : addUnit(props.round)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const chooseAvatar = (e: any) => {
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/uni_modules/vk-uview-ui/components/u-avatar-cropper/u-avatar-cropper?destWidth=300&rectWidth=200&fileType=jpg'
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
const path = e.detail?.avatarUrl
|
||||||
|
if (path) {
|
||||||
|
uploadImageIng(path)
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadImageIng = async (file: string) => {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '正在上传中...'
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
const res: any = await uploadImage(file, userStore.temToken!)
|
||||||
|
uni.hideLoading()
|
||||||
|
emit('update:modelValue', res[props.fileKey])
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.$u.toast(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 监听从裁剪页发布的事件,获得裁剪结果
|
||||||
|
uni.$on('uAvatarCropper', (path) => {
|
||||||
|
uploadImageIng(path)
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
uni.$off('uAvatarCropper')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.avatar-upload {
|
||||||
|
background: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
&::after {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<u-popup v-model="showPopup" mode="bottom" border-radius="14" :mask-close-able="false">
|
||||||
|
<view class="h-[1000rpx] p-[40rpx]">
|
||||||
|
<view class="flex items-center">
|
||||||
|
<image
|
||||||
|
class="w-[100rpx] h-[100rpx] rounded"
|
||||||
|
mode="heightFix"
|
||||||
|
:src="logo"
|
||||||
|
></image>
|
||||||
|
<text class="text-3xl ml-5 font-bold">{{ title }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="mt-5 text-muted">
|
||||||
|
建议使用您的微信头像和昵称,以便获得更好的体验
|
||||||
|
</view>
|
||||||
|
<view class="mt-[30rpx]">
|
||||||
|
<form @submit="handleSubmit">
|
||||||
|
<u-form-item required label="头像" :labelWidth="120">
|
||||||
|
<view class="flex-1">
|
||||||
|
<avatar-upload v-model="avatar"></avatar-upload>
|
||||||
|
</view>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item required label="昵称" :labelWidth="120">
|
||||||
|
<input
|
||||||
|
class="flex-1 h-[60rpx]"
|
||||||
|
name="nickname"
|
||||||
|
type="nickname"
|
||||||
|
placeholder="请输入昵称"
|
||||||
|
/>
|
||||||
|
</u-form-item>
|
||||||
|
<view class="mt-[80rpx]">
|
||||||
|
<button
|
||||||
|
class="bg-primary rounded-full text-white text-lg h-[80rpx] leading-[80rpx]"
|
||||||
|
hover-class="none"
|
||||||
|
form-type="submit"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex justify-center mt-[60rpx]">
|
||||||
|
<view class="text-muted" @click="showPopup = false">暂不登录</view>
|
||||||
|
</view>
|
||||||
|
</form>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
const props = defineProps({
|
||||||
|
show: {
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
logo: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(event: 'update:show', show: boolean): void
|
||||||
|
(event: 'update', value: any): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const showPopup = computed({
|
||||||
|
get() {
|
||||||
|
return props.show
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
emit('update:show', val)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const avatar = ref()
|
||||||
|
|
||||||
|
const handleSubmit = (e: any) => {
|
||||||
|
const { nickname } = e.detail.value
|
||||||
|
if (!avatar.value)
|
||||||
|
return uni.$u.toast({
|
||||||
|
title: '请添加头像'
|
||||||
|
})
|
||||||
|
if (!nickname)
|
||||||
|
return uni.$u.toast({
|
||||||
|
title: '请输入昵称'
|
||||||
|
})
|
||||||
|
emit('update', {
|
||||||
|
avatar: avatar.value,
|
||||||
|
nickname
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -154,12 +154,19 @@
|
||||||
</view>
|
</view>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
</view>
|
</view>
|
||||||
|
<mplogin-popup
|
||||||
|
v-model:show="showLoginPopup"
|
||||||
|
:logo="websiteConfig.logo"
|
||||||
|
:title="websiteConfig.name"
|
||||||
|
@update="handleUpdateUser"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { mobileLogin, accountLogin, mnpLogin } from '@/api/account'
|
import { mobileLogin, accountLogin, mnpLogin } from '@/api/account'
|
||||||
import { smsSend } from '@/api/app'
|
import { smsSend } from '@/api/app'
|
||||||
|
import { updateUser } from '@/api/user'
|
||||||
import { SMSEnum } from '@/enums/appEnums'
|
import { SMSEnum } from '@/enums/appEnums'
|
||||||
import { BACK_URL } from '@/enums/cacheEnums'
|
import { BACK_URL } from '@/enums/cacheEnums'
|
||||||
import { useLockFn } from '@/hooks/useLockFn'
|
import { useLockFn } from '@/hooks/useLockFn'
|
||||||
|
|
@ -187,6 +194,7 @@ enum LoginAuthEnum {
|
||||||
QQ = 2
|
QQ = 2
|
||||||
}
|
}
|
||||||
const isWeixin = ref(true)
|
const isWeixin = ref(true)
|
||||||
|
const showLoginPopup = ref(false)
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
isWeixin.value = isWeixinClient()
|
isWeixin.value = isWeixinClient()
|
||||||
// #endif
|
// #endif
|
||||||
|
|
@ -194,11 +202,12 @@ isWeixin.value = isWeixinClient()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
const websiteConfig = computed(() => appStore.getWebsiteConfig)
|
||||||
const uCodeRef = shallowRef()
|
const uCodeRef = shallowRef()
|
||||||
const loginWay = ref<LoginWayEnum>()
|
const loginWay = ref<LoginWayEnum>()
|
||||||
const codeTips = ref('')
|
const codeTips = ref('')
|
||||||
const isCheckAgreement = ref(false)
|
const isCheckAgreement = ref(false)
|
||||||
|
const loginData = ref<any>({})
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
scene: '',
|
scene: '',
|
||||||
username: '',
|
username: '',
|
||||||
|
|
@ -329,6 +338,13 @@ const { lockFn: wxLogin } = useLockFn(async () => {
|
||||||
const data = await mnpLogin({
|
const data = await mnpLogin({
|
||||||
code
|
code
|
||||||
})
|
})
|
||||||
|
loginData.value = data
|
||||||
|
if (data.isNew) {
|
||||||
|
uni.hideLoading()
|
||||||
|
userStore.temToken = data.token
|
||||||
|
showLoginPopup.value = true
|
||||||
|
return
|
||||||
|
}
|
||||||
loginHandle(data)
|
loginHandle(data)
|
||||||
// #endif
|
// #endif
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
|
|
@ -341,6 +357,12 @@ const { lockFn: wxLogin } = useLockFn(async () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handleUpdateUser = async (value: any) => {
|
||||||
|
await updateUser(value, { token: userStore.temToken })
|
||||||
|
showLoginPopup.value = false
|
||||||
|
loginHandle(loginData.value)
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => appStore.getLoginConfig,
|
() => appStore.getLoginConfig,
|
||||||
(value) => {
|
(value) => {
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,17 @@
|
||||||
<u-icon name="arrow-right" color="#666"></u-icon>
|
<u-icon name="arrow-right" color="#666"></u-icon>
|
||||||
</view>
|
</view>
|
||||||
<!-- #ifdef MP-WEIXIN || H5 -->
|
<!-- #ifdef MP-WEIXIN || H5 -->
|
||||||
<view class="item bg-white flex flex-1 justify-between" v-if="isWeixin">
|
<view
|
||||||
|
v-if="isWeixin"
|
||||||
|
class="item bg-white flex flex-1 justify-between"
|
||||||
|
@click="bindWechatLock"
|
||||||
|
>
|
||||||
<view class="">绑定微信</view>
|
<view class="">绑定微信</view>
|
||||||
<view class="flex justify-between">
|
<view class="flex justify-between">
|
||||||
<view class="text-muted mr-[20rpx]">
|
<view class="text-muted mr-[20rpx]">
|
||||||
{{ userInfo.isBindMnp ? '已绑定' : '未绑定' }}
|
{{ userInfo.isBindWechat ? '已绑定' : '未绑定' }}
|
||||||
</view>
|
</view>
|
||||||
<!-- <u-icon name="arrow-right" color="#666"></u-icon> -->
|
<u-icon v-if="userInfo.isBindWechat == 0" name="arrow-right" color="#666"></u-icon>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
|
|
@ -68,23 +72,19 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getUserInfo } from '@/api/user'
|
import { mnpAuthBind, oaAuthBind } from '@/api/user'
|
||||||
import { onShow } from '@dcloudio/uni-app'
|
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||||
import { ref } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useAppStore } from '@/stores/app'
|
import { useAppStore } from '@/stores/app'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { AgreementEnum } from '@/enums/agreementEnums'
|
import { AgreementEnum } from '@/enums/agreementEnums'
|
||||||
import { isWeixinClient } from '@/utils/client'
|
import { isWeixinClient } from '@/utils/client'
|
||||||
|
import wechatOa from '@/utils/wechat'
|
||||||
|
import { useLockFn } from '@/hooks/useLockFn'
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const userInfo = ref({
|
const userInfo = computed(() => userStore.userInfo)
|
||||||
avatar: '',
|
|
||||||
nickname: '',
|
|
||||||
username: '',
|
|
||||||
isBindMnp: '',
|
|
||||||
isPassword: ''
|
|
||||||
})
|
|
||||||
const list = ref([
|
const list = ref([
|
||||||
{
|
{
|
||||||
text: '修改密码'
|
text: '修改密码'
|
||||||
|
|
@ -101,12 +101,6 @@ isWeixin.value = isWeixinClient()
|
||||||
|
|
||||||
const show = ref(false)
|
const show = ref(false)
|
||||||
|
|
||||||
// 获取用户信息
|
|
||||||
const getUser = async () => {
|
|
||||||
const res = await getUserInfo()
|
|
||||||
userInfo.value = res
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改/忘记密码
|
// 修改/忘记密码
|
||||||
const handleClick = (index: number) => {
|
const handleClick = (index: number) => {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
|
|
@ -120,7 +114,7 @@ const handleClick = (index: number) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePwd = () => {
|
const handlePwd = () => {
|
||||||
if (!userInfo.value.isPassword)
|
if (!userInfo.value.hasPwd)
|
||||||
return uni.navigateTo({ url: '/pages/change_password/change_password?type=set' })
|
return uni.navigateTo({ url: '/pages/change_password/change_password?type=set' })
|
||||||
show.value = true
|
show.value = true
|
||||||
}
|
}
|
||||||
|
|
@ -138,8 +132,58 @@ const logoutHandle = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bindWechat = async () => {
|
||||||
|
if (userInfo.value.isBindWechat) return
|
||||||
|
try {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '请稍后...'
|
||||||
|
})
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
const { code }: any = await uni.login({
|
||||||
|
provider: 'weixin'
|
||||||
|
})
|
||||||
|
await mnpAuthBind({
|
||||||
|
code: code
|
||||||
|
})
|
||||||
|
//#endif
|
||||||
|
// #ifdef H5
|
||||||
|
if (isWeixin.value) {
|
||||||
|
wechatOa.getUrl()
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
uni.$u.toast('绑定成功')
|
||||||
|
await userStore.getUser()
|
||||||
|
uni.hideLoading()
|
||||||
|
} catch (e) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.$u.toast(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { lockFn: bindWechatLock } = useLockFn(bindWechat)
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
getUser()
|
userStore.getUser()
|
||||||
|
})
|
||||||
|
onLoad(async (options) => {
|
||||||
|
// #ifdef H5
|
||||||
|
const { code } = options
|
||||||
|
if (!isWeixin.value) return
|
||||||
|
if (code) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '请稍后...'
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
await oaAuthBind({ code })
|
||||||
|
uni.$u.toast('绑定成功')
|
||||||
|
await userStore.getUser()
|
||||||
|
} catch (error) {}
|
||||||
|
//用于清空code
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages/user_set/user_set'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endif
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,3 +93,34 @@ export function objectToQuery(params: Record<string, any>): string {
|
||||||
}
|
}
|
||||||
return query.slice(0, -1)
|
return query.slice(0, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 组合异步任务
|
||||||
|
* @param { string } task 异步任务
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function series(...task: Array<(_arg: any) => any>) {
|
||||||
|
return function (): Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const iteratorTask = task.values()
|
||||||
|
const next = (res?: any) => {
|
||||||
|
const nextTask = iteratorTask.next()
|
||||||
|
if (nextTask.done) {
|
||||||
|
resolve(res)
|
||||||
|
} else {
|
||||||
|
Promise.resolve(nextTask.value(res)).then(next).catch(reject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 添加单位
|
||||||
|
* @param {String | Number} value 值 100
|
||||||
|
* @param {String} unit 单位 px em rem
|
||||||
|
*/
|
||||||
|
export const addUnit = (value: string | number, unit = 'rpx') => {
|
||||||
|
return !Object.is(Number(value), NaN) ? `${value}${unit}` : value
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue