diff --git a/.claude/settings.local.json b/.claude/settings.local.json index a180b1a..2467b05 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -21,7 +21,8 @@ "Bash(mkdir -p \"E:\\code\\智柜宝\\wx\\src\\pages\\rental\")", "Bash(cat /E/code/智柜宝/wx/README.md)", "Bash(cat /E/code/智柜宝/wx/package.json)", - "Bash(cat /E/code/智柜宝/wx/manifest.config.ts)" + "Bash(cat /E/code/智柜宝/wx/manifest.config.ts)", + "Bash(tree:*)" ], "deny": [], "ask": [] diff --git a/src/api/users/index.ts b/src/api/users/index.ts index b93044e..4d10939 100644 --- a/src/api/users/index.ts +++ b/src/api/users/index.ts @@ -17,4 +17,9 @@ export async function getWxUserByOpenid(openid: string) { /** 根据openid获取动态码 */ export async function generateDynamicCode(openid: string) { return await http.get("wx/generateDynamicCode", { openid }); +} + +/** 根据openid更新用户昵称和头像 */ +export async function updateUserByOpenid(openid: string, nickName?: string, avatar?: string) { + return await http.get("wx/updateUserByOpenid", { openid, nickName, avatar }); } \ No newline at end of file diff --git a/src/api/users/types.ts b/src/api/users/types.ts index e07319b..7f59907 100644 --- a/src/api/users/types.ts +++ b/src/api/users/types.ts @@ -16,6 +16,8 @@ export interface WxUserDTO { nickName?: string; /** 头像 */ avatar?: string; + /** 是否完成个人信息填写 */ + profileDone?: boolean; /** 手机号码 */ tel?: string; /** 余额(分) */ @@ -32,6 +34,7 @@ export interface WxUserDTO { ab98Name?: string; /** 汇邦云用户头像 */ ab98FaceImg?: string; + /** 企业用户信息 */ qyUser?: { /** 企业用户ID */ diff --git a/src/pages.json b/src/pages.json index 1212177..ec30dcc 100644 --- a/src/pages.json +++ b/src/pages.json @@ -128,6 +128,13 @@ "navigationBarTitleText": "支付成功" } }, + { + "path": "pages/profile/index", + "type": "page", + "style": { + "navigationBarTitleText": "设置头像昵称" + } + }, { "path": "pages/QrScanner/index", "type": "page", diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index 7decf1d..95f30b1 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -3,11 +3,11 @@ import { ref, onMounted } from 'vue' import { useWxStore } from '@/pinia/stores/wx' import { useProductStore } from '@/pinia/stores/product' import { useCartStore } from '@/pinia/stores/cart' -import { getCorpidById, getShopListApi } from '@/api/shop' +import { getShopListApi } from '@/api/shop' import type { ShopEntity } from '@/api/shop/types' import ProductContainer from './components/product-container.vue'; import { generateDynamicCode, getWxUserByOpenid, mpCodeToOpenId } from '@/api/users' -import { toHttpsUrl } from '@/utils' +import { toHttpsUrl, uniLogin } from '@/utils' import { useAb98UserStore } from '@/pinia/stores/ab98-user' import { storeToRefs } from 'pinia' import { useWxParamsStore } from '@/pinia/stores/wx-params' @@ -29,6 +29,8 @@ const showShopList = ref(true) const shopList = ref([]) const shopId = ref(0) + + // 页面加载 onMounted(async () => { }) @@ -67,75 +69,75 @@ function handleCheckout() { onLoad(async (query) => { const wxParamsStore = useWxParamsStore(); + const { wxUserDTO } = storeToRefs(wxStore); console.log('page index onLoad query: ', query); - // scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene + + // 解析scene参数 if (query && query.scene) { const scene = decodeURIComponent(query.scene); wxParamsStore.parseScene(scene); } - - const cid = wxParamsStore.getNumberParam('cid', -1); - let corpid = uni.getStorageSync('local_corpid'); - // 企业ID获取逻辑:根据不同的条件获取企业ID并缓存到本地 - if (cid > 0) { - // 如果存在有效的企业ID参数(cid > 0),则通过API获取对应的企业ID - corpid = (await getCorpidById(cid)).data; - // 将获取到的企业ID存储到本地缓存中 - uni.setStorageSync('local_corpid', corpid || ''); - } else if (corpid) { - // 如果本地已存在企业ID,则直接使用,无需重新获取 - // 空语句块,表示保持现有的corpid值不变 - } else { - // 如果既没有有效的cid参数,也没有本地缓存的corpid,则获取默认企业ID(cid=0) - corpid = (await getCorpidById(0)).data; - // 将默认企业ID存储到本地缓存中 - uni.setStorageSync('local_corpid', corpid || ''); - } - + // 获取企业ID + const cid = wxParamsStore.getNumberParam('cid', -1); + const corpid = await wxStore.getCorpid(cid); + + // 用户登录处理 let openid = uni.getStorageSync('local_openid'); - if (!openid) { - uni.login({ - provider: 'weixin', //使用微信登录 - success: function (loginRes) { - mpCodeToOpenId(loginRes.code).then((wxUser) => { - console.log('wxUser:', wxUser); - wxStore.wxMpCallback(wxUser.data, corpid); - uni.setStorageSync('local_openid', wxUser.data.openid || ''); - if (wxUser.data.ab98UserId) { - ab98UserStore.setAb98UserName(wxUser.data.ab98Name || wxUser.data.nickName || '') - ab98UserStore.setAb98UserFaceImg(wxUser.data.ab98FaceImg || '') - } - }).catch((e) => { - console.error('mpCodeToOpenId error:', e) - }) - }, - }); - } else { - // 从本地缓存中获取用户信息 - const wxUser = await getWxUserByOpenid(openid); - console.log('wxUser:', wxUser); - wxStore.wxMpCallback(wxUser.data, corpid); - uni.setStorageSync('local_openid', wxUser.data.openid || ''); - if (wxUser.data.ab98UserId) { - ab98UserStore.setAb98UserName(wxUser.data.ab98Name || wxUser.data.nickName || '') - ab98UserStore.setAb98UserFaceImg(wxUser.data.ab98FaceImg || '') + try { + if (!openid) { + // 首次登录 + const loginRes = await uniLogin({ provider: 'weixin' }); + const wxUser = await mpCodeToOpenId(loginRes.code); + console.log('wxUser:', wxUser); + await wxStore.processUserInfo(wxUser.data, corpid); + } else { + // 已有本地缓存 + const wxUser = await getWxUserByOpenid(openid); + console.log('wxUser:', wxUser); + await wxStore.processUserInfo(wxUser.data, corpid); } + } catch (error) { + console.error('用户登录处理失败:', error); } - + + // 检查是否需要跳转到个人资料设置页面 + // 条件:未绑定 ab98UserId 且 profileDone 不为真 + if (wxUserDTO.value && !wxUserDTO.value.ab98UserId && wxUserDTO.value.profileDone !== true) { + console.log('用户需要完善资料,跳转到个人资料设置页面'); + uni.navigateTo({ + url: '/pages/profile/index' + }); + return; // 跳转后不执行后续逻辑 + } + + // 获取店铺列表 if (showShopList.value) { try { - // 等待 handleWxCallback 完成 await wxStore.waitForHandleWxCallbackComplete(); const res = await getShopListApi(wxStore.corpid || ''); - console.log('获取店铺列表:', res) + console.log('获取店铺列表:', res); if (res?.code === 0 && res?.data?.length > 0) { shopList.value = res.data; - - // shopList.value = [...shopList.value, ...res.data, ...res.data, ...res.data]; } } catch (error) { - console.error('获取店铺列表失败:', error) + console.error('获取店铺列表失败:', error); + } + } +}); + +onShow(async () => { + // 获取店铺列表 + if (showShopList.value) { + try { + await wxStore.waitForHandleWxCallbackComplete(); + const res = await getShopListApi(wxStore.corpid || ''); + console.log('获取店铺列表:', res); + if (res?.code === 0 && res?.data?.length > 0) { + shopList.value = res.data; + } + } catch (error) { + console.error('获取店铺列表失败:', error); } } }) diff --git a/src/pages/me/index.vue b/src/pages/me/index.vue index cdfe7b9..bb6b7f4 100644 --- a/src/pages/me/index.vue +++ b/src/pages/me/index.vue @@ -5,7 +5,7 @@ import { useAb98UserStore } from '@/pinia/stores/ab98-user' import { useWxParamsStore } from '@/pinia/stores/wx-params' import { storeToRefs } from 'pinia' import { toHttpsUrl } from '@/utils' -import { generateDynamicCode } from '@/api/users' +import { generateDynamicCode, getWxUserByOpenid } from '@/api/users' import { DynamicCodeResponse } from '@/api/users/types' import { useToast } from 'wot-design-uni' @@ -30,7 +30,8 @@ const name = computed(() => { return userName.value || qyName.value || '未知用户' }) -const userAvatar = computed(() => face_img.value ? toHttpsUrl(face_img.value) : '/static/favicon.ico') +const userAvatar = computed(() => face_img.value ? toHttpsUrl(face_img.value) : + wxUserDTO.value?.avatar ? toHttpsUrl(wxUserDTO.value.avatar) : '/static/favicon.ico') // 动态码相关 const dynamicCodeActionSheet = ref(false) @@ -80,8 +81,10 @@ onMounted(() => { wxStore.refreshBalance() }); -onShow(() => { - wxStore.refreshBalance() +onShow(async () => { + const wxUser = await getWxUserByOpenid(wxStore.openid); + console.log('wxUser:', wxUser); + await wxStore.processUserInfo(wxUser.data, wxStore.corpid); }); // 生成动态码 @@ -114,7 +117,7 @@ const handleGenerateDynamicCode = async () => { diff --git a/src/pages/profile/index.vue b/src/pages/profile/index.vue new file mode 100644 index 0000000..883352b --- /dev/null +++ b/src/pages/profile/index.vue @@ -0,0 +1,429 @@ + + + + + \ No newline at end of file diff --git a/src/pinia/stores/wx.ts b/src/pinia/stores/wx.ts index d0a3e72..3445fb8 100644 --- a/src/pinia/stores/wx.ts +++ b/src/pinia/stores/wx.ts @@ -1,5 +1,5 @@ import { pinia } from "@/pinia" -import { getOpenIdApi, getBalanceApi, qyLogin, getBalanceByQyUserid, fakeQyLoginApi, getUserBalance } from "@/api/shop" +import { getOpenIdApi, getBalanceApi, qyLogin, getBalanceByQyUserid, fakeQyLoginApi, getUserBalance, getCorpidById } from "@/api/shop" import { ab98UserDTO, GetBalanceResponse } from "@/api/shop/types" import { useAb98UserStore } from "./ab98-user" import { defineStore } from "pinia" @@ -199,10 +199,39 @@ export const useWxStore = defineStore("wx", () => { refreshBalance(); } + // 处理用户信息的通用函数 + const processUserInfo = async (userData: any, corpid_: string) => { + wxMpCallback(userData, corpid_) + uni.setStorageSync('local_openid', userData.openid || '') + if (userData.ab98UserId) { + const ab98UserStore = useAb98UserStore(); + ab98UserStore.setAb98UserName(userData.ab98Name || userData.nickName || '') + ab98UserStore.setAb98UserFaceImg(userData.ab98FaceImg || '') + } + } + + // 获取企业ID + const getCorpid = async (cidParam: number): Promise => { + let corpid = uni.getStorageSync('local_corpid') + const cid = cidParam + + if (cid > 0) { + corpid = (await getCorpidById(cid)).data + } else if (!corpid) { + corpid = (await getCorpidById(0)).data + } + // 如果 corpid 有值,缓存它 + if (corpid) { + uni.setStorageSync('local_corpid', corpid) + } + return corpid || '' + } + return { code, state, openid, corpid, userid, balance, useBalance, balanceLimit, isCabinetAdmin, corpidLogin, name, ab98User, qyUserId, isFakeQyLogin, isHandleWxCallbackComplete, wxUserDTO, ab98UserId, setOpenid, setBalance, setIsCabinetAdmin, - refreshBalance, setAb98User, waitForHandleWxCallbackComplete, wxMpCallback, setAb98UserId } + refreshBalance, setAb98User, waitForHandleWxCallbackComplete, wxMpCallback, setAb98UserId, + processUserInfo, getCorpid } }) /** diff --git a/src/utils/index.ts b/src/utils/index.ts index 13c0b7a..2f05361 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -194,3 +194,22 @@ export const isDoubleTokenMode = import.meta.env.VITE_AUTH_MODE === 'double' * 通常为 /pages/index/index */ export const HOME_PAGE = `/${pages.find(page => page.type === 'home')?.path || pages[0].path}` + +/** + * uni.login 的 Promise 封装,使其能够使用 await 进行等待 + * @param options - uni.login 的配置选项 + * @returns Promise + */ +export function uniLogin(options?: UniApp.LoginOptions): Promise { + return new Promise((resolve, reject) => { + uni.login({ + ...options, + success: (res) => { + resolve(res) + }, + fail: (err) => { + reject(err) + } + }) + }) +}