完善登录、收藏、分享

This commit is contained in:
wangxiaowei
2025-10-20 17:34:50 +08:00
parent c3ffadfded
commit 820b445e9c
12 changed files with 228 additions and 78 deletions

View File

@ -17,7 +17,7 @@
}
// 微信静默授权
await snsapiBaseAuthorize()
// await snsapiBaseAuthorize()
// await initJweixinSDK()
})
onShow((options) => {

View File

@ -8,6 +8,7 @@ export interface ITeaSpecialistDetailsParams {
id: number
longitude: number
latitude: number
user_id: number
}
export function getTeaSpecialistDetails(data: ITeaSpecialistDetailsParams) {
@ -24,7 +25,6 @@ export function getTeaSpecialistDetails(data: ITeaSpecialistDetailsParams) {
*/
export interface ICollectTeaSpecialistParams {
id: number
user_id: number
status: number
}

View File

@ -11,3 +11,13 @@ export interface IJweiXin {
timestamp: number
url: string
}
/**
* JSSDK 分享参数
*/
export interface IJweiXinShareParams {
title: '' | string
desc: '' | string
link: '' | string
imgUrl: '' | string
}

View File

@ -11,6 +11,7 @@ export interface ITeaSpecialistDetailsResult {
export interface ITeaSpecialistDetailsFields {
name: string
star: number
image: string
reservation_num: number
distance: number
speed: number
@ -25,4 +26,5 @@ export interface ITeaSpecialistDetailsFields {
teamasterLevel: Array<any>
price: number
fare_price: number
collect: number
}

View File

@ -1,11 +1,13 @@
import {wxSnsapiBaseLogin} from '@/api/login'
import { useUserStore } from '@/store'
import type { IUserInfoVo } from '@/api/types/login'
import { jump, NAVIGATE_TO } from '@/utils/tools'
import { toast } from '@/utils/toast'
/**
* 微信静默授权
*/
const getUrlCode = (): { [key: string]: string | undefined } => {
export const getUrlCode = (): { [key: string]: string | undefined } => {
// 截取url中的code方法
const url = location.search
// this.winUrl = url;
@ -25,34 +27,23 @@ const getUrlCode = (): { [key: string]: string | undefined } => {
*/
export async function snsapiBaseAuthorize() {
// TODO 测试代码
// wxSnsapiBaseLogin({code: '051wM51w3488N53ThD3w3obLDm2wM51r'}).then((res: IUserInfoVo) => {
// console.log("登录成功 ~ snsapiBaseAuthorize ~ res:", res)
// // 映射 IUserLogin 到 IUserInfoVo
// useUserStore().setUserInfo(res)
// }).catch(err => {
// // 失败就重新授权
// uni.setStorageSync('wechatCode', 0)
// console.log('请求失败', err)
// })
// const res = {
// account: "u39317465",
// avatar: "https://cz.stnav.com/uploads/user/avatar/c2b3c5f94e3f20c8a989bd302519b4c7.jpeg",
// channel:2,
// is_new_user: 1,
// id: 4,
// sn:"39317465",
// token: "013f5128f0208f2f9d9285af5070ae7b",
// nickname: '微信用户',
// mobile: '15005837859'
// }
// useUserStore().setUserInfo(res)
// console.log(useUserStore().userInfo)
// wxSnsapiBaseLogin({code: '001Vgi0w3dwIP538nE1w32v6j83Vgi0X'}).then((res: IUserInfoVo) => {
// console.log("登录成功 ~ snsapiBaseAuthorize ~ res:", res)
// // 映射 IUserLogin 到 IUserInfoVo
// useUserStore().setUserInfo(res)
// }).catch(err => {
// // 失败就重新授权
// uni.setStorageSync('wechatCode', 0)
// console.log('请求失败', err)
// })
// return
let local = window.location.href // 获取页面url
let appid = import.meta.env.VITE_WX_SERVICE_ACCOUNT_APPID // 公众号的APPID
console.log("🚀 ~ snsapiBaseAuthorize ~ appid:", appid)
let code = getUrlCode().code // 截取code
console.log("🚀 ~ snsapiBaseAuthorize ~ code:", code)
// 获取之前的code
let oldCode = uni.getStorageSync('wechatCode')
@ -63,7 +54,7 @@ export async function snsapiBaseAuthorize() {
// 设置旧的code为0避免死循环
uni.setStorageSync('wechatCode',0)
window.location.href =
`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${uri}&response_type=code&scope=snsapi_base&state=123#wechat_redirect`
`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${uri}&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect`
} else {
// 保存最新code
uni.setStorageSync('wechatCode',code)
@ -72,6 +63,13 @@ export async function snsapiBaseAuthorize() {
const res: IUserInfoVo = await wxSnsapiBaseLogin({code})
console.log("登录成功 ~ snsapiBaseAuthorize ~ res:", res)
useUserStore().setUserInfo(res)
if (!res.mobile) {
// 如果没有绑定手机号的话需要去绑定手机号
toast.info('请先绑定手机号')
jump('/pages/login/mobile', NAVIGATE_TO, 500)
} else {
uni.$emit('loginSuccess')
}
} catch (err) {
uni.setStorageSync('wechatCode', 0)
console.log('请求失败', err)

View File

@ -7,6 +7,7 @@ import VueHook from 'alova/vue'
import { toast } from '@/utils/toast'
import { ContentTypeEnum, ResultEnum, ShowMessage } from './tools/enum'
import { useUserStore } from '@/store'
import { jump, SWITCH_TAB, NAVIGATE_TO } from '@/utils/tools'
// 配置动态Tag
export const API_DOMAINS = {
@ -67,14 +68,20 @@ const alovaInstance = createAlova({
// method.config.headers.token = token;
const userStore = useUserStore()
const { token } = userStore.userInfo as unknown as IUserInfo
const { token, mobile } = userStore.userInfo as unknown as IUserInfo
if (!token) {
toast.info('请先登录')
setTimeout(() => {
uni.switchTab({ url: '/pages/my/my' })
}, 500)
jump('/pages/my/my', SWITCH_TAB, 500)
throw new Error('[请求错误]:未登录')
}
if (!mobile) {
toast.info('请先绑定手机号')
jump('/pages/login/mobile', NAVIGATE_TO, 500)
throw new Error('[请求错误]:未绑定手机号')
}
method.config.headers.token = token;
}
@ -124,6 +131,12 @@ const alovaInstance = createAlova({
// throw new Error(`登录超时[${code}]${msg}`)
// }
if (code === ResultEnum.Success) {
if (config.meta?.toast !== false && msg) {
toast.info(msg)
}
}
if (code !== ResultEnum.Success) {
if (config.meta?.toast !== false) {
toast.warning(msg)

View File

@ -72,8 +72,12 @@
<template #right>
<view class="flex items-center ml-114rpx">
<view class="mr-16rpx flex items-center" @click="Detail.handleCollect">
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_sc.png`"></wd-img>
<!-- <wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_sc_s.png`"></wd-img> -->
<template v-if="userInfo.token && info.collect > 0">
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_sc_s.png`"></wd-img>
</template>
<template v-else>
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_sc.png`"></wd-img>
</template>
</view>
<view @click="Detail.handleShare" class="flex items-center">
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_share.png`"></wd-img>
@ -272,16 +276,24 @@
import { useMessage } from 'wot-design-uni'
import { getTeaSpecialistDetails, collectTeaSpecialist } from '@/api/tea'
import { ITeaSpecialistDetailsFields } from '@/api/types/tea'
import {toast} from '@/utils/toast'
import {TeaSpecialistLevelValue} from '@/utils/teaSpecialist'
import { toast } from '@/utils/toast'
import { TeaSpecialistLevelValue } from '@/utils/teaSpecialist'
import { jump, NAVIGATE_TO } from '@/utils/tools'
import { useUserStore } from '@/store'
import type {IUserInfoVo} from '@/api/types/login'
import { wxShare } from '@/utils/jwexin'
const OSS = inject('OSS')
// 用户信息
const userInfo = ref<IUserInfoVo>(null)
// 茶艺师
const id = ref<number>(0)
const info = reactive<ITeaSpecialistDetailsFields>({
name: '',
star: 0,
image: '',
reservation_num: 0,
distance: 0,
speed: 0,
@ -290,6 +302,7 @@
teamasterLevel: [],
price: 0,
fare_price: 0,
collect: 0
})
const latitude = ref<number>(0) // 纬度
const longitude = ref<number>(0) // 经度
@ -324,6 +337,10 @@
const tipMoney = ref<Number>(0) // 其他打赏金额
onLoad(async (args) => {
const userStore = useUserStore()
userInfo.value = userStore.userInfo
console.log("🚀 ~ userInfo.value :",userInfo.value)
id.value = args.id || 0
latitude.value = args.lat || 0
longitude.value = args.lng || 0
@ -332,7 +349,8 @@
const res = await getTeaSpecialistDetails({
id: args.id,
latitude: latitude.value,
longitude: longitude.value
longitude: longitude.value,
user_id: userInfo.value.id || 0
})
// 将返回的数据合并到 reactive 对象中
Object.assign(info, res.teamaster || {})
@ -350,24 +368,31 @@
const Detail = {
// 处理收藏
handleCollect: async () => {
const res = await collectTeaSpecialist({
user_id: 1,
id: 1,
status: 1
let status = info.collect == 0 ? 1 : 0
await collectTeaSpecialist({
id: id.value,
status
})
console.log('收藏=', res)
info.collect = info.collect == 0 ? 1 : 0
},
// 处理分享
handleShare: () => {
console.log('处理分享')
const url = window.location.href
const { name, real, image} = info
const params = {
title: name,
desc: real?.interests,
imgUrl: image,
link: url
}
wxShare(params)
},
// 预约茶室
handleReserveTeaRoom: () => {
uni.navigateTo({
url: '/pages/reserve/tea-room'
})
jump('/pages/reserve/tea-room', NAVIGATE_TO)
},
// 立即邀约

View File

@ -155,7 +155,7 @@
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js"
import TeaSpecialistLevel from '@/components/TeaSpecialistLevel.vue'
import {getLocation} from '@/utils/jwexin'
import {wxGetLocation} from '@/utils/jwexin'
import {TeaSpecialistLevelValue} from '@/utils/teaSpecialist'
import {getDecorate, getTeaSpecialistLevels, getTeaSpecialist} from '@/api/home'
import {getCity} from '@/api/city'
@ -186,7 +186,7 @@
onLoad(async () => {
// 授权获取地址
await getLocation((res) => {
await wxGetLocation((res) => {
latitude.value = res.latitude
longitude.value = res.longitude
Index.handleSearch()

View File

@ -178,10 +178,11 @@
</template>
<script lang="ts" setup>
import {OrderStatus} from '@/utils/order'
import {toast} from '@/utils/toast'
import { OrderStatus } from '@/utils/order'
import { toast } from '@/utils/toast'
import { useUserStore } from '@/store'
import {snsapiBaseAuthorize} from '@/hooks/useWeiXin'
import { getUrlCode, snsapiBaseAuthorize } from '@/hooks/useWeiXin'
import { jump, NAVIGATE_TO } from '@/utils/tools'
const OSS = inject('OSS')
const navbarHeight = inject('navbarHeight')
@ -212,15 +213,33 @@
const isClaimCoupon = ref<boolean>(false)
onShow(() => {
const code = getUrlCode().code // 截取code
const userStore = useUserStore()
console.log("🚀 ~ userStore:", userStore.userInfo)
if (userStore.userInfo.mobile) {
userInfo.value = userStore.userInfo
isLogin.value = true
} else if (code && !userStore.userInfo.token) {
// 这里是微信授权之后跳转回到本页面获取到code但是没有登录状态的话需要进行登录操作
snsapiBaseAuthorize()
}
})
onLoad(() => {
uni.$on('loginSuccess', () => {
// 刷新用户信息
console.log("🚀 ~ 刷新用户信息:")
const userStore = useUserStore()
if (userStore.userInfo.mobile) {
userInfo.value = userStore.userInfo
isLogin.value = true
}
// 你可以在这里做跳转或弹窗提示
})
})
onUnload(() => {
uni.$off('loginSuccess')
})
const My = {
@ -254,16 +273,13 @@
},
// 跳转到个人信息
handleToProfile: () => {
handleToProfile: async () => {
if (isLogin.value) {
uni.navigateTo({
url: '/bundle/profile/profile'
})
} else {
// 登录操作
uni.navigateTo({
url: '/bundle/vip/benefits'
})
await snsapiBaseAuthorize()
}
},

43
src/typings.d.ts vendored
View File

@ -1,28 +1,29 @@
// 全局要用的类型放到这里
declare global {
interface IResData<T> {
code: number
msg: string
data: T
}
interface IResData<T> {
code: number
msg: string
data: T
}
// uni.uploadFile文件上传参数
interface IUniUploadFileOptions {
file?: File
files?: UniApp.UploadFileOptionFiles[]
filePath?: string
name?: string
formData?: any
}
// uni.uploadFile文件上传参数
interface IUniUploadFileOptions {
file?: File
files?: UniApp.UploadFileOptionFiles[]
filePath?: string
name?: string
formData?: any
}
interface IUserInfo {
nickname?: string
avatar?: string
/** 微信的 openid非微信没有这个字段 */
openid?: string
token?: string
}
interface IUserInfo {
nickname?: string
avatar?: string
/** 微信的 openid非微信没有这个字段 */
openid?: string
token?: string
mobile?: string
}
}
export {} // 防止模块污染
export { } // 防止模块污染

View File

@ -1,5 +1,6 @@
import wx from 'jweixin-1.6.0'
import {wxSignature} from '@/api/jwexin'
import { wxSignature } from '@/api/jwexin'
import { IJweiXinShareParams } from '@/api/types/jwexin'
declare global {
interface Window {
@ -45,7 +46,7 @@ export async function initJweixinSDK(): Promise<any> {
}
// 获取经纬度
export async function getLocation(callback: (res: any) => void ) {
export async function wxGetLocation(callback: (res: any) => void ) {
if (!isWechat()) {
console.log('不是微信客户端')
return
@ -68,3 +69,31 @@ export async function getLocation(callback: (res: any) => void ) {
});
});
}
// 分享
export async function wxShare(data:IJweiXinShareParams) {
if (!isWechat()) {
console.log('不是微信客户端')
return
}
await initJweixinSDK()
const params = {
title: data.title || '茶址',
desc: data.desc || '茶艺师分享',
link: data.link || window.location.href,
imgUrl: data.imgUrl || 'https://shchazhi.oss-cn-hangzhou.aliyuncs.com/fronted/images/logo.png',
success: function(res) {
console.log('设置成功')
},
cancel: function(res) {}
}
wx.ready(function() {
wx.updateAppMessageShareData(params)
wx.updateTimelineShareData(params)
});
console.log("🚀 ~ wxShare ~ params:", params)
}

56
src/utils/tools.ts Normal file
View File

@ -0,0 +1,56 @@
/**
* 页面跳转方法
* @param url 跳转地址
* @param type 跳转类型 1: switchTab 2: navigateTo 3: navigateBack 4: reLaunch 5: redirectTo
* @param time 延迟时间(毫秒)默认0
*/
export const SWITCH_TAB = 1
export const NAVIGATE_TO = 2
export const NAVIGATE_BACK = 3
export const RE_LAUNCH = 4
export const REDIRECT_TO = 5
export function jump(url: string, type: number, time: number = 0) {
switch (type) {
case SWITCH_TAB:
//跳转至 table
setTimeout(function() {
uni.switchTab({
url
})
}, time);
break;
case NAVIGATE_TO:
//跳转至非table页面
setTimeout(function() {
uni.navigateTo({
url
})
}, time);
break;
case NAVIGATE_BACK:
//返回上页面
setTimeout(function() {
uni.navigateBack({
delta: parseInt(url),
})
}, time);
break;
case RE_LAUNCH:
//关闭当前所有页面跳转至非table页面
setTimeout(function() {
uni.reLaunch({
url,
})
}, time);
break;
case REDIRECT_TO:
//关闭当前页面跳转至非table页面
setTimeout(function() {
uni.redirectTo({
url
})
}, time);
break;
}
}