Files
pj_h5_cloud/src/pages/tabbar/my.vue
T
2026-08-10 00:40:42 +08:00

437 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<template #main-top>
<view class="flex items-center py-3 px-5">
<view class="flex items-center" v-if="state.userInfo?.sysUser?.userId" @tap="doUserArea">
<image v-if="state.userInfo?.sysUser?.avatar" class="size-100rpx rounded-full"
:src="filePath(state.userInfo.sysUser.avatar)" mode="aspectFill" />
<image v-else class="w-100rpx h-100rpx rounded-full" src="/static/icon/default-avatar.png"
mode="aspectFill" />
<view class="ml-30rpx">
<view class="flex items-center">
<view class="sub-text-30">{{ state.userInfo?.sysUser?.name }}</view>
<view v-if="state.userInfo?.sysUser?.birthday"
class="ml-20rpx flex items-center bg-#FFFFFF px-16rpx py-6rpx rounded-full shadow-sm">
<image class="size-32rpx mr-8rpx" src="/static/icon/birthday.png" mode="aspectFit" />
<text class="text-24rpx color-blue font-bold lh-1">
{{ dayjs(state.userInfo.sysUser.birthday).format("MM-DD") }}
</text>
</view>
</view>
<view class="m-t-5rpx sub-text-26">ID {{ state.userInfo?.sysUser?.userId }}</view>
</view>
</view>
<view v-else class="flex items-center ml-30rpx" @tap="onTabLogin">
<text class="sub-text-32">请先登录</text>
<text class="iconfont icon-youjiantou" />
</view>
</view>
</template>
<view class="mt-10rpx rounded-20rpx shadow-main p-30rpx pb-40rpx bg-white">
<view class="service_item flex items-center justify-between" v-for="(v, i) in state.menuList" :key="i"
@tap="onTabMenu(v)">
<view class="flex-row-center">
<image class="size-40rpx" :src="v.icon" mode="aspectFill" />
<text class="sub-text-28 m-l-20rpx">{{ v.text }}</text>
</view>
<view class="iconfont icon-youjiantou" />
</view>
</view>
<view v-if="isDevEnv()" class="flex-col-center mt-40rpx mx-30rpx">
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff"
@tap="doLogout">
退出登录
</view>
</view>
<view class="h-30rpx" />
<view v-if="state.appInfo == APPENV.SH" class="flex-col-center mt-40rpx mx-30rpx">
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff"
@tap="doChangeRole">
切换角色
</view>
</view>
<view class="second-text-26 text-center mb-2 mt-10">
<text>联系热线:</text>
<text @click="doPhone('18367908152')">18367908152</text>
&nbsp;
<text @click="doPhone('15657370065')">15657370065</text>
</view>
</crud-layout>
<modify-user ref="modifyUserRef" warnText="填写出生日期即可领取生日兑换券" @close="storage.getUserInfo" />
<tm-modal :show="state.actModalShow" :showCancel="false" title="核销活动兑换券" zIndex="999" @confirm="" @cancel=""
@close="">
<view class="text-center text-28">是否核销该活动兑换券?</view>
<view class="text-center text-28">确认核销将自动对用户的 消费钱包 扣费</view>
<template #footer>
<view class="w-full flex justify-center gap-6">
<tm-button skin="thin" @tap="actModalCancel">取 消</tm-button>
<tm-button color="primary" @tap="actModalConfirm">确 认</tm-button>
</view>
</template>
</tm-modal>
</template>
<script setup lang="ts">
import { reactive, ref } from "vue"
import dayjs from "dayjs"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
import { filePath } from "@@/utils/file"
import { getAppInfo } from "@@/utils/app"
import { hooks, router, constant } from "@@/index"
import { actCancel, userApi } from "@@/api"
import { isDevEnv } from "@/sheep/utils/app"
import { APPENV } from "@/sheep/constant"
import { ensureBizLogin } from "@/sheep/utils/request"
import ModifyUser from "@@/components/modify-user.vue"
const modifyUserRef = ref<any>()
const state = reactive<any>({
wallet: [],
userInfo: {},
menuList: [
{ text: "扫一扫", icon: "/static/icon/scan.png", path: "" },
{ text: "我参加的活动", icon: "/static/icon/act.png", path: "/pages/merchant/my-act-list" },
{ text: "我的钱包", icon: "/static/icon/service_3.png", path: "/pages/wallet/list" },
{ text: "我的人脸", icon: "/static/icon/service_5.png", path: "/pages/human-face/list" },
// { text: "车辆管理", icon: "/static/icon/service_6.png", path: "/pages/car/userCar/list" },
{ text: "清除缓存", icon: "/static/icon/clear-storage.png", path: "" },
],
appInfo: "",
actModalShow: false,
actVal: {},
})
// 常量
const STORAGE_KEYS = {
TOKEN: constant.storageConstant.TOKEN,
USER_INFO: constant.storageConstant.USERINFO,
}
const doUserArea = () => {
if (!state.userInfo?.sysUser?.userId) return
modifyUserRef.value?.open()
}
const storage = {
// 获取存储的用户信息
getUserInfo: () => {
const tokenStorage = uni.getStorageSync(STORAGE_KEYS.TOKEN)
const userStorage = uni.getStorageSync(STORAGE_KEYS.USER_INFO)
if (!isEmpty(userStorage) && !isEmpty(tokenStorage)) {
state.userInfo = userStorage
} else {
state.userInfo = {}
}
},
// 保存用户信息到存储
saveUserInfo: (userData: any) => {
uni.setStorageSync(STORAGE_KEYS.USER_INFO, userData)
storage.getUserInfo()
},
// 保存token到存储
saveToken: (tokenData: any) => {
uni.setStorageSync(STORAGE_KEYS.TOKEN, tokenData)
},
// 清除用户登录相关的存储
clearUserStorage: () => {
uni.removeStorageSync(STORAGE_KEYS.TOKEN)
uni.removeStorageSync(STORAGE_KEYS.USER_INFO)
state.userInfo = {}
},
// 清除缓存
clearCache: () => {
uni.showModal({
title: "确定清除缓存吗?",
content: "清除缓存将自动刷新页面",
success: (res) => {
if (res.confirm) {
uni.clearStorageSync()
state.userInfo = {}
uni.reLaunch({ url: "/pages/tabbar/my?reauth=1" })
}
},
})
},
}
const login = {
// 检查应用环境并登录
checkAppInfo: async () => {
try {
// 先尝试诗画登录
const shihuaResult = await login.shihuaLogin()
if (shihuaResult) return
// 尝试浙政钉登录
const zhengdingResult = login.zhengdingLogin()
if (zhengdingResult) return
uni.showToast({ title: "当前登录环境未知", icon: "none" })
} catch (error) {
console.error("登录失败:", error)
uni.showToast({ title: "登录失败", icon: "none" })
}
},
// 诗画环境登录:走统一 ensureBizLogin,避免与请求拦截器各打一遍 /shjnsso
shihuaLogin: async () => {
const appInfo = await (window as any).CP2.getAppInfo()
if (appInfo.code == 0) return false
return await ensureBizLogin()
},
// 浙政钉登录
zhengdingLogin: () => {
const params = new URL(window.location.href).searchParams
const token = params.get("uabaseToken")
if (token) {
return login.doLogin(2, token, "", "")
}
return false
},
// 执行登录操作 - loginType 1:诗画登录 2:浙政钉登录
doLogin: async (loginType: number, token: string, accountId: string, sessionId: string) => {
const tokenStorage = uni.getStorageSync(STORAGE_KEYS.TOKEN)
const userStorage = uni.getStorageSync(STORAGE_KEYS.USER_INFO)
switch (loginType) {
case 1: // 诗画登录
uni.showLoading({ title: "登录中...", mask: true })
const response = await userApi.authsh({ accountId, sessionId })
if (response.code == 0) {
storage.saveToken({ accessToken: response.data.accessToken })
uni.hideLoading()
uni.showToast({ title: "登录成功", icon: "none" })
const { data: userData } = await userApi.userInfo()
storage.saveUserInfo(userData)
} else {
uni.hideLoading()
storage.clearUserStorage()
if (response.msg == "token已失效") {
uni.showToast({ title: "用户凭证已失效,请退出并重新进入智慧后勤应用", icon: "none", duration: 6000 })
} else {
if (response.code == -1) {
storage.saveToken({ data: -1 })
}
uni.showToast({ title: response.msg || "登录失败", icon: "none" })
}
}
break
case 2: // 浙政钉登录
if (isEmpty(tokenStorage) || isEmpty(userStorage)) {
try {
uni.showLoading({ title: "登录中...", mask: true })
const res = await userApi.auth({ token })
if (res.code == 0) {
storage.saveToken(res.data)
uni.hideLoading()
uni.showToast({ title: "登录成功", icon: "none" })
const { data: userData } = await userApi.userInfo()
storage.saveUserInfo(userData)
} else {
storage.clearUserStorage()
if (res.msg == "token已失效") {
uni.showToast({ title: "用户凭证已失效,请退出并重新进入智慧后勤应用", icon: "none", duration: 6000 })
} else {
uni.showToast({ title: res.msg || "登录失败", icon: "none" })
}
}
} catch (error) {
uni.showToast({ title: "登录错误", icon: "none" })
} finally {
uni.hideLoading()
}
}
break
default:
uni.showToast({ title: "当前登录环境未知", icon: "none" })
}
},
// 退出登录
logout: async () => {
const isLogin = await hooks.useCheckLogin()
if (!isLogin) return
uni.showLoading({ title: "退出登录中...", mask: true })
storage.clearUserStorage()
uni.hideLoading()
uni.showToast({ title: "退出登录成功", icon: "none" })
},
// 切换角色
changeRole: () => {
router.jump("/pages/user/userRole")
},
}
// 打开活动核销对话框
const actModalShow = (v) => {
state.actModalShow = true
state.actVal = v
}
// 确认核销
const actModalConfirm = async () => {
try {
uni.showLoading({ title: "核销中...", mask: true })
const { code, msg }: any = await actCancel.appCreateActOrder(state.actVal)
if (code != 0) return uni.showToast({ title: msg || "核销失败", icon: "none", duration: 4000 })
uni.showToast({ title: "核销成功", icon: "success" })
state.actModalShow = false
state.actVal = {}
} catch (error) {
uni.showToast({ title: "核销失败", icon: "none" })
} finally {
uni.hideLoading()
}
}
// 取消核销
const actModalCancel = () => {
state.actModalShow = false
state.actVal = {}
}
const { scanCodeAction, processUrlScanResult, processBase64ScanResult } = hooks.useScanCode(actModalShow)
// 扫一扫
const appScanCode = async () => {
const scanResult = await scanCodeAction()
if (!scanResult) return uni.showToast({ title: "扫码错误", icon: "none" })
// 判断扫码结果
if (scanResult.startsWith("http")) {
// 扫码结果是url链接
processUrlScanResult(scanResult.replace("/#", ""))
} else {
// 扫码结果是base64字符串
processBase64ScanResult(scanResult)
}
}
const onTabLogin = () => (isDevEnv() ? router.jump("/pages/user/login") : login.checkAppInfo())
const onTabMenu = async (item: any) => {
const isLogin = await hooks.useCheckLogin()
if (isLogin) {
if (item.path == "/pages/tabbar/index") return uni.switchTab({ url: item.path })
switch (item.text) {
case "扫一扫":
await appScanCode()
break
case "清除缓存":
storage.clearCache()
break
default:
router.jump(item.path)
}
}
}
// 退出登录
const doLogout = async () => {
await login.logout()
}
// 切换角色
const doChangeRole = () => {
login.changeRole()
}
// 初始化配置菜单
const initMenuConfig = () => {
if (isDevEnv()) {
state.menuList.push(
{ text: "dev-✨导航✨", icon: "/static/icon/service_1.png", path: "/pages/tabbar/index" },
{ text: "dev-外来人员就餐", icon: "/static/icon/service_1.png", path: "/pages/apply/foreign-list" },
{ text: "dev-跨单位就餐", icon: "/static/icon/service_1.png", path: "/pages/apply/stride-list" },
{ text: "dev-包厢预定", icon: "/static/icon/service_4.png", path: "/pages/boxes/apply-list" },
{ text: "dev-第三方应用", icon: "/static/icon/login.png", path: "/pages/thirdApp/happyMall" },
{ text: "dev-登录", icon: "/static/icon/login.png", path: "/pages/user/login" },
{ text: "dev-角色选择", icon: "/static/icon/login.png", path: "/pages/user/userRole" },
)
}
}
onLoad(async (options: Record<string, string | undefined>) => {
const app = getApp()
app._initTabbar()
// 初始化配置菜单
initMenuConfig()
// 获取应用信息
state.appInfo = await getAppInfo()
await userApi.userRole()
await isMallMchUser()
await isMchUser()
// 获取存储中的用户信息
storage.getUserInfo()
if (options?.reauth === "1") {
await login.checkAppInfo()
storage.getUserInfo()
}
// 门户壳「扫一扫」:跳到我的页并自动调起扫码(登录态在本 H5)
if (options?.autoScan === "1") {
const isLogin = await hooks.useCheckLogin()
if (isLogin) {
await appScanCode()
}
}
})
const isMallMchUser = async () => {
const { data } = await userApi.isMallMchUser()
if (data)
state.menuList.unshift({ text: "共富商城商品管理", icon: "/static/icon/service_4.png", path: "/pages/prosperity-shop/goods-manage" })
}
const isMchUser = async () => {
const { data } = await userApi.isMerchant()
// 商家查看优惠券列表
if (data)
state.menuList.unshift({ text: "查看用户领取的优惠券列表", icon: "/static/icon/service_1.png", path: "/pages/merchant/coupon-list" })
}
onShow(() => {
// 获取存储中的用户信息
storage.getUserInfo()
})
// 联系客服
const doPhone = (phone: string) => {
hooks.useMakePhoneCall(phone)
}
</script>
<style lang="scss" scoped>
.service_item:not(:last-child) {
padding-bottom: 40rpx;
border-bottom: 1px solid #fafafa;
margin-bottom: 40rpx;
}
</style>