公众号登录

This commit is contained in:
Jason 2022-09-15 10:53:31 +08:00
parent de81fd983a
commit c3462df82c
14 changed files with 2761 additions and 2346 deletions

View File

@ -18,7 +18,7 @@
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
"build:app": "uni build -p app",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5": "node scripts/build.h5.mjs",
"build:h5:ssr": "uni build --ssr",
"build:mp-alipay": "uni build -p mp-alipay",
"build:mp-baidu": "uni build -p mp-baidu",
@ -50,6 +50,7 @@
"vconsole": "^3.14.6",
"vue": "^3.2.37",
"vue-i18n": "^9.2.2",
"weixin-js-sdk": "^1.6.0",
"z-paging": "^2.3.8"
},
"devDependencies": {
@ -66,6 +67,8 @@
"autoprefixer": "^10.4.8",
"eslint": "^8.22.0",
"eslint-plugin-vue": "^9.4.0",
"execa": "^6.1.0",
"fs-extra": "^10.1.0",
"postcss": "^8.4.16",
"postcss-rem-to-responsive-pixel": "^5.1.3",
"prettier": "^2.7.1",

37
app/scripts/build.h5.mjs Normal file
View File

@ -0,0 +1,37 @@
import { execaCommand } from 'execa'
import path from 'path'
import fsExtra from 'fs-extra'
const { existsSync, remove, copy } = fsExtra
const cwd = process.cwd()
//打包发布路径,谨慎改动
const releaseRelativePath = '../h5'
const distPath = path.resolve(cwd, 'dist/build/h5')
const releasePath = path.resolve(cwd, releaseRelativePath)
async function build() {
await execaCommand('uni build', { stdio: 'inherit', encoding: 'utf-8', cwd })
if (existsSync(releasePath)) {
await remove(releasePath)
}
console.log(`文件正在复制 ==> ${releaseRelativePath}`)
try {
await copyFile(distPath, releasePath)
} catch (error) {
console.log(`\n ${error}`)
}
console.log(`文件已复制 ==> ${releaseRelativePath}`)
}
function copyFile(sourceDir, targetDir) {
return new Promise((resolve, reject) => {
copy(sourceDir, targetDir, (err) => {
if (err) {
reject(err)
} else {
resolve()
}
})
})
}
build()

View File

@ -2,10 +2,17 @@
import { onLaunch } from '@dcloudio/uni-app'
import { useAppStore } from './stores/app'
import { useUserStore } from './stores/user'
const { getConfig } = useAppStore()
const appStore = useAppStore()
const { getUser } = useUserStore()
onLaunch(async () => {
await getConfig()
await appStore.getConfig()
// #ifdef H5
const { status, close, url } = appStore.getH5Config
if (status == 0) {
if (close == 1) return (location.href = url)
uni.reLaunch({ url: '/pages/empty/empty' })
}
// #endif
await getUser()
})
</script>

View File

@ -15,3 +15,12 @@ export function register(data: Record<string, any>) {
export function forgotPassword(data: Record<string, any>) {
return request.post({ url: '/login/forgotPassword', data })
}
//向微信请求code的链接
export function getWxCodeUrl() {
return request.get({ url: '/login/codeUrl', data: { url: location.href } })
}
export function OALogin(data: Record<string, any>) {
return request.get({ url: '/login/oaLogin', data })
}

View File

@ -68,5 +68,12 @@
"uniStatistics": {
"enable": false
},
"vueVersion": "3"
"vueVersion": "3",
"h5": {
"router": {
"mode": "history",
"base": "/mobile"
},
"title": "加载中"
}
}

View File

@ -103,6 +103,12 @@
"navigationBarTitleText": "绑定手机号"
}
},
{
"path": "pages/empty/empty",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "uni_modules/vk-uview-ui/components/u-avatar-cropper/u-avatar-cropper",
"style": {

View File

@ -0,0 +1,7 @@
<template>
<div></div>
</template>
<script setup lang="ts"></script>
<style></style>

View File

@ -132,7 +132,7 @@
<navigator url="/pages/register/register" hover-class="none">注册账号</navigator>
</view>
<!-- #ifdef MP-WEIXIN -->
<!-- #ifdef MP-WEIXIN || H5 -->
<view class="mt-[80rpx]" v-if="isOpenOtherAuth">
<u-divider>第三方登录</u-divider>
<div class="flex justify-center mt-[40rpx]">
@ -141,7 +141,7 @@
class="flex flex-col items-center"
@click="wxLogin"
>
<u-icon name="/static/images/icon/icon_wx.png" size="80" />
<img src="@/static/images/icon/icon_wx.png" class="w-[80rpx] h-[80rpx]" />
<div class="text-sm mt-[10px]">微信登录</div>
</div>
</div>
@ -158,8 +158,12 @@ import { SMSEnum } from '@/enums/appEnums'
import { useLockFn } from '@/hooks/useLockFn'
import { useAppStore } from '@/stores/app'
import { useUserStore } from '@/stores/user'
import { isWeixinClient } from '@/utils/client'
import { currentPage } from '@/utils/util'
import { onShow } from '@dcloudio/uni-app'
// #ifdef H5
import wechatOa from '@/utils/wechat'
// #endif
import { onLoad, onShow } from '@dcloudio/uni-app'
import { computed, reactive, ref, shallowRef, watch } from 'vue'
enum LoginTypeEnum {
MOBILE = 'mobile',
@ -176,6 +180,10 @@ enum LoginAuthEnum {
WX = 1,
QQ = 2
}
const isWeixin = ref(true)
// #ifdef H5
// isWeixin.value = isWeixinClient()
// #endif
const userStore = useUserStore()
const appStore = useAppStore()
@ -248,40 +256,51 @@ const loginFun = async (scene: LoginTypeEnum, code?: string) => {
})
try {
const data = await login(params)
const { token, isBindMobile } = data
if (!isBindMobile && isForceBindMobile.value) {
userStore.temToken = token
uni.navigateTo({
url: '/pages/bind_mobile/bind_mobile'
})
uni.hideLoading()
return
}
userStore.login(data.token)
await userStore.getUser()
uni.$u.toast('登录成功')
uni.hideLoading()
uni.navigateBack({
success: () => {
// @ts-ignore
const { onLoad, options } = currentPage()
//
onLoad && onLoad(options)
}
})
loginHandle(data)
} catch (error: any) {
uni.hideLoading()
throw new Error(error)
}
}
const loginHandle = async (data: any) => {
const { token, isBindMobile } = data
if (!isBindMobile && isForceBindMobile.value) {
userStore.temToken = token
uni.navigateTo({
url: '/pages/bind_mobile/bind_mobile'
})
uni.hideLoading()
return
}
userStore.login(data.token)
await userStore.getUser()
uni.$u.toast('登录成功')
uni.hideLoading()
uni.navigateBack({
success: () => {
// @ts-ignore
const { onLoad, options } = currentPage()
//
onLoad && onLoad(options)
}
})
}
const { lockFn: handleLogin } = useLockFn(loginFun)
const wxLogin = async () => {
// #ifdef MP-WEIXIN
const data: any = await uni.login({
provider: 'weixin'
})
handleLogin(LoginTypeEnum.MNP, data.code)
// #endif
// #ifdef H5
if (isWeixin.value) {
wechatOa.getUrl()
}
// #endif
}
watch(
@ -312,6 +331,32 @@ onShow(async () => {
uni.hideLoading()
}
})
onLoad(async (options) => {
if (userStore.isLogin) {
// =>
uni.reLaunch({
url: '/pages/index/index'
})
return
}
const { code } = options
if (code) {
uni.showLoading({
title: '请稍后...'
})
// #ifdef H5
try {
const data = await wechatOa.authLogin(code)
loginHandle(data)
} catch (error: any) {
uni.hideLoading()
throw new Error(error)
}
// #endif
}
})
</script>
<style lang="scss">

View File

@ -7,18 +7,14 @@ interface AppSate {
export const useAppStore = defineStore({
id: 'appStore',
state: (): AppSate => ({
config: {
website: {},
login: {},
tabbar: [],
style: {}
}
config: {}
}),
getters: {
getWebsiteConfig: (state) => state.config.website,
getLoginConfig: (state) => state.config.login,
getTabbarConfig: (state) => state.config.tabbar,
getStyleConfig: (state) => state.config.style
getWebsiteConfig: (state) => state.config.website || {},
getLoginConfig: (state) => state.config.login || {},
getTabbarConfig: (state) => state.config.tabbar || [],
getStyleConfig: (state) => state.config.style || {},
getH5Config: (state) => state.config.h5 || {}
},
actions: {
getImageUrl(url: string) {

View File

@ -1,3 +1,4 @@
page {
background-color: $u-bg-color;
font-size: 28rpx;
}

View File

@ -10,6 +10,15 @@ export const isWeixinClient = () => {
// #endif
}
/**
* @description
* @return { Boolean }
*/
export function isAndroid() {
const u = navigator.userAgent
return u.indexOf('Android') > -1 || u.indexOf('Adr') > -1
}
/**
* @description
* @return { Object }

112
app/src/utils/wechat.ts Normal file
View File

@ -0,0 +1,112 @@
import weixin from 'weixin-js-sdk'
import { getWxCodeUrl, OALogin } from '@/api/account'
import { useUserStore } from '@/stores/user'
import { isAndroid } from './client'
const wechatOa = {
getSignLink() {
if (typeof window.signLink === 'undefined' || window.signLink === '') {
window.signLink = location.href.split('#')[0]
}
return isAndroid() ? location.href.split('#')[0] : window.signLink
},
getUrl() {
getWxCodeUrl().then((res) => {
location.href = res.url
})
},
authLogin(code: string) {
return new Promise((resolve, reject) => {
OALogin({
code
}).then((res) => {
const userStore = useUserStore()
userStore.login(res.token)
resolve(res)
})
})
},
ready() {
return new Promise((resolve, reject) => {
weixin.ready(() => {
resolve('success')
})
})
},
share(options: Record<any, any>) {
this.ready().then(() => {
const { shareTitle, shareLink, shareImage, shareDesc } = options
weixin.updateTimelineShareData({
title: shareTitle, // 分享标题
link: shareLink, // 分享链接该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImage // 分享图标
})
// 发送给好友
weixin.updateAppMessageShareData({
title: shareTitle, // 分享标题
link: shareLink, // 分享链接该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImage, // 分享图标
desc: shareDesc
})
// 发送到tx微博
weixin.onMenuShareWeibo({
title: shareTitle, // 分享标题
link: shareLink, // 分享链接该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImage, // 分享图标
desc: shareDesc
})
})
},
getAddress() {
return new Promise((reslove, reject) => {
this.ready().then(() => {
weixin.openAddress({
success: (res: any) => {
reslove(res)
},
fail: (res: any) => {
reject(res)
}
})
})
})
},
getLocation() {
return new Promise((reslove, reject) => {
this.ready().then(() => {
weixin.getLocation({
type: 'gcj02',
success: (res: any) => {
reslove(res)
},
fail: (res: any) => {
reject(res)
}
})
})
})
}
}
export default wechatOa
// export function wxOaConfig() {
// return new Promise((resolve, reject) => {
// apiJsConfig().then((res) => {
// console.log(res) //微信配置
// weixin.config({
// debug: false, // 开启调试模式
// appId: res.appId, // 必填,公众号的唯一标识
// timestamp: res.timestamp, // 必填,生成签名的时间戳
// nonceStr: res.nonceStr, // 必填,生成签名的随机串
// signature: res.signature, // 必填,签名
// jsApiList: res.jsApiList, // 必填需要使用的JS接口列表
// success: () => {
// resolve('success')
// },
// fail: (res: any) => {
// reject('weixin config is fail')
// }
// })
// })
// })
// }

View File

@ -7,4 +7,9 @@ declare module '*.vue' {
export default component
}
declare interface Window {
signLink: string
}
declare module 'uview-plus'
declare module 'weixin-js-sdk'

File diff suppressed because it is too large Load Diff