Merge branch 'master' of http://gitea.zianxin.com/zianxin-tec/biz-mobile-react-cloud
# Conflicts: # .env
This commit is contained in:
commit
fbfb31b4a4
14 files changed
+471
-496
No files matched your search
@@ -17,31 +17,32 @@ VITE_PWD_ENC_KEY='pigxpigxpigxpigx'
|
||||
VITE_OAUTH2_APP_CLIENT='mini:mini'
|
||||
|
||||
# 图片访问基础地址
|
||||
VITE_IMAGE_BASE_PATH = http://localhost:9999
|
||||
#VITE_IMAGE_BASE_PATH = http://localhost:9999
|
||||
# VITE_IMAGE_BASE_PATH = http://192.168.101.29:9999 # 邓-本地
|
||||
# VITE_IMAGE_BASE_PATH = http://192.168.101.37:9999 # 邓-本地
|
||||
# VITE_IMAGE_BASE_PATH = https://123.156.230.15:8089/api # 线上
|
||||
#VITE_IMAGE_BASE_PATH = http://220.191.229.171:8090/api # 线上
|
||||
# VITE_IMAGE_BASE_PATH = http://220.191.229.171:8090/api # 线上
|
||||
# VITE_IMAGE_BASE_PATH = https://stgl.pj.gov.cn/api # 线上
|
||||
# VITE_IMAGE_BASE_PATH = http://pjcloud.center.takin.cc # 张
|
||||
# VITE_IMAGE_BASE_PATH = http://59.202.170.152:81/api # 信创线上
|
||||
VITE_IMAGE_BASE_PATH = http://59.202.170.152:81/api # 信创线上
|
||||
|
||||
# ******************** start 开发环境 start ********************
|
||||
# VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
|
||||
VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
|
||||
# VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/app-api
|
||||
# VITE_APP_DEV_SERVICE = http://192.168.101.29:9999 # 邓-本地
|
||||
# VITE_APP_DEV_SERVICE = http://192.168.101.37:9999 # 邓-本地
|
||||
# VITE_APP_DEV_SERVICE = http://192.168.101.50:9999 # 邓-本地
|
||||
# VITE_APP_DEV_SERVICE = http://127.0.0.1:9999
|
||||
# VITE_APP_DEV_SERVICE = http://123.156.230.15:8089/api/ # 线上
|
||||
#VITE_APP_DEV_SERVICE = http://220.191.229.171:8090/api # 线上
|
||||
VITE_APP_DEV_SERVICE = http://localhost:9999
|
||||
# VITE_APP_DEV_SERVICE = http://220.191.229.171:8090/api # 线上
|
||||
# VITE_APP_DEV_SERVICE = http://localhost:9999
|
||||
# ******************** end 开发环境 end ********************
|
||||
|
||||
# ******************** start 生产环境 start ****************
|
||||
#VITE_APP_PROD_SERVICE = http://123.156.228.134:48080/app-api
|
||||
#VITE_APP_PROD_SERVICE = http://59.202.170.152:81/api
|
||||
# VITE_APP_PROD_SERVICE = https://stgl.pj.gov.cn/api
|
||||
VITE_APP_PROD_SERVICE = http://220.191.229.171:8090/api
|
||||
# VITE_APP_PROD_SERVICE = http://220.191.229.171:8090/api
|
||||
VITE_APP_PROD_SERVICE = http://59.202.170.152:81/api # 信创线上
|
||||
# ******************** end 生产环境 end ********************
|
||||
|
||||
# VITE_DEV_ENV = dev
|
||||
VITE_DEV_ENV = prod
|
||||
VITE_DEV_ENV = prod
|
||||
+7
-7
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": true,
|
||||
"trailingComma": "all",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"printWidth": 120
|
||||
}
|
||||
"tabWidth": 2,
|
||||
"useTabs": true,
|
||||
"trailingComma": "all",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"printWidth": 140
|
||||
}
|
||||
+13
-13
@@ -16,13 +16,13 @@
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/tabbar/shop",
|
||||
"style": {
|
||||
"navigationBarTitleText": "超市",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
// {
|
||||
// "path": "pages/tabbar/shop",
|
||||
// "style": {
|
||||
// "navigationBarTitleText": "超市",
|
||||
// "disableScroll": true
|
||||
// }
|
||||
// },
|
||||
{
|
||||
"path": "pages/tabbar/order",
|
||||
"style": {
|
||||
@@ -273,12 +273,12 @@
|
||||
"iconPath": "static/tabbar/home.png",
|
||||
"selectedIconPath": "static/tabbar/home-select.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/tabbar/shop",
|
||||
"text": "超市",
|
||||
"iconPath": "static/tabbar/shop.png",
|
||||
"selectedIconPath": "static/tabbar/shop-select.png"
|
||||
},
|
||||
// {
|
||||
// "pagePath": "pages/tabbar/shop",
|
||||
// "text": "超市",
|
||||
// "iconPath": "static/tabbar/shop.png",
|
||||
// "selectedIconPath": "static/tabbar/shop-select.png"
|
||||
// },
|
||||
{
|
||||
"pagePath": "pages/tabbar/order",
|
||||
"text": "订单",
|
||||
|
||||
+78
-72
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { ref, reactive } from "vue"
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app"
|
||||
import { isEmpty } from "radash"
|
||||
|
||||
import { hooks, router } from "@@/index"
|
||||
@@ -10,96 +10,102 @@ import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
|
||||
import CustomWaterfallsFlow from "@@/components/other/custom-waterfalls-flow/custom-waterfalls-flow.vue"
|
||||
|
||||
const data = {
|
||||
tabs: [
|
||||
{ id: null, name: '全部', disabled: false },
|
||||
{ id: 0, name: '空闲', disabled: false },
|
||||
{ id: 1, name: '部分空闲', disabled: false },
|
||||
{ id: 2, name: '已满', disabled: false },
|
||||
],
|
||||
tabs: [
|
||||
{ id: null, name: "全部", disabled: false },
|
||||
{ id: 0, name: "空闲", disabled: false },
|
||||
{ id: 1, name: "部分空闲", disabled: false },
|
||||
{ id: 2, name: "已满", disabled: false },
|
||||
],
|
||||
}
|
||||
|
||||
const state = reactive<any>({
|
||||
detailId: null,
|
||||
pa: {
|
||||
status: data.tabs[0].id,
|
||||
},
|
||||
detailId: null,
|
||||
pa: {
|
||||
status: data.tabs[0].id,
|
||||
},
|
||||
})
|
||||
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(pageRef, boxesApi.page, null, 'data.records')
|
||||
const pageHook = hooks.usePage(pageRef, boxesApi.page, null, "data.records")
|
||||
const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
pageHook.startPage(page, pagesize, false, state.pa)
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
if (!isEmpty(options.id)) {
|
||||
state.detailId = options.id
|
||||
state.pa.merchantId = options.id
|
||||
}
|
||||
});
|
||||
if (!isEmpty(options.id)) {
|
||||
state.detailId = options.id
|
||||
state.pa.merchantId = options.id
|
||||
}
|
||||
})
|
||||
onShow(() => {
|
||||
if (pageRef.value) {
|
||||
pageRef.value.reload(false)
|
||||
}
|
||||
if (pageRef.value) {
|
||||
pageRef.value.reload(false)
|
||||
}
|
||||
})
|
||||
|
||||
const doTab = (e: any) => {
|
||||
const target = data.tabs[e];
|
||||
state.pa.status = target.id
|
||||
pageRef.value.reload(true)
|
||||
const target = data.tabs[e]
|
||||
state.pa.status = target.id
|
||||
pageRef.value.reload(true)
|
||||
}
|
||||
|
||||
const doCard = (v: any) => {
|
||||
router.jump('/pages/boxes/detail', { id: v.id })
|
||||
router.jump("/pages/boxes/detail", { id: v.id })
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<crud-layout title="包厢预定" bg="/static/page/blue-bg.png">
|
||||
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="5"
|
||||
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
|
||||
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
|
||||
<template #top>
|
||||
<view class="bg-white rounded-16rpx px-20rpx m-x-10rpx m-t-15rpx">
|
||||
<z-tabs :list="data.tabs" @change="doTab" />
|
||||
</view>
|
||||
</template>
|
||||
<view class="h-20rpx" />
|
||||
<custom-waterfalls-flow v-model="pageHook.list" imageKey="images" :columnSpace="1" @wapperClick="doCard"
|
||||
@imageClick="doCard">
|
||||
<template v-slot:default="v">
|
||||
<view class="p-x-15rpx p-t-10rpx p-b-20rpx">
|
||||
<view class="sub-text-28 show-line">{{ v.name }}</view>
|
||||
<view class="m-t-10rpx flex-row items-center">
|
||||
<view class="second-text-32 color-#f63a36!">
|
||||
¥{{ v.price }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-row items-center m-t-10rpx">
|
||||
<view class="second-text-26">可容纳{{ v.capacity }}人</view>
|
||||
<view class="w-1px h-20rpx m-x-5rpx bg-#999" />
|
||||
<view class="flex-row-center">
|
||||
<tm-tag v-if="v.status == 0" size="xs" color="success">
|
||||
{{ hooks.useEnum("boxesBxStatusEnum", v.status.toString()) }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.status == 1" size="xs">
|
||||
{{ hooks.useEnum("boxesBxStatusEnum", v.status) }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.status == 2" size="xs" color="error">
|
||||
{{ hooks.useEnum("boxesBxStatusEnum", v.status) }}
|
||||
</tm-tag>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-row items-center m-t-10rpx">
|
||||
<view class="second-text-26">{{ v.address }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</custom-waterfalls-flow>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
<crud-layout title="包厢预定" bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
:fixed="false"
|
||||
v-model="pageHook.list"
|
||||
:default-page-size="5"
|
||||
safe-area-inset-bottom
|
||||
:loading-more-enabled="true"
|
||||
:show-scrollbar="false"
|
||||
@query="query"
|
||||
:auto-clean-list-when-reload="false"
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
@scroll="pageHook.scroll"
|
||||
>
|
||||
<template #top>
|
||||
<view class="bg-white rounded-16rpx px-20rpx m-x-10rpx m-t-20rpx">
|
||||
<z-tabs :list="data.tabs" @change="doTab" />
|
||||
</view>
|
||||
</template>
|
||||
<view class="h-20rpx" />
|
||||
<custom-waterfalls-flow v-model="pageHook.list" imageKey="images" :columnSpace="1" @wapperClick="doCard" @imageClick="doCard">
|
||||
<template v-slot:default="v">
|
||||
<view class="p-x-15rpx p-t-10rpx p-b-20rpx">
|
||||
<view class="sub-text-28 show-line">{{ v.name }}</view>
|
||||
<view class="m-t-10rpx flex-row items-center">
|
||||
<view class="second-text-32 color-#f63a36!"> ¥{{ v.price }} </view>
|
||||
</view>
|
||||
<view class="flex-row items-center m-t-10rpx">
|
||||
<view class="second-text-26">可容纳{{ v.capacity }}人</view>
|
||||
<view class="w-1px h-20rpx m-x-5rpx bg-#999" />
|
||||
<view class="flex-row-center">
|
||||
<tm-tag v-if="v.status == 0" size="xs" color="success">
|
||||
{{ hooks.useEnum("boxesBxStatusEnum", v.status.toString()) }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.status == 1" size="xs">
|
||||
{{ hooks.useEnum("boxesBxStatusEnum", v.status) }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.status == 2" size="xs" color="error">
|
||||
{{ hooks.useEnum("boxesBxStatusEnum", v.status) }}
|
||||
</tm-tag>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-row items-center m-t-10rpx">
|
||||
<view class="second-text-26">{{ v.address }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</custom-waterfalls-flow>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -107,7 +107,7 @@ const doProduct = (v: any) => {
|
||||
@scroll="pageHook.scroll"
|
||||
>
|
||||
<template #top>
|
||||
<view class="bg-#1777FF p-15rpx">
|
||||
<view class="bg-#1777FF p-15rpx pt-10">
|
||||
<scroll-view scroll-x class="whitespace-nowrap">
|
||||
<view class="flex-row items-center space-x-15rpx">
|
||||
<view
|
||||
@@ -129,13 +129,7 @@ const doProduct = (v: any) => {
|
||||
</template>
|
||||
<view class="h-20rpx" />
|
||||
<view class="m-x-10rpx">
|
||||
<custom-waterfalls-flow
|
||||
v-model="foodList"
|
||||
imageKey="picUrl"
|
||||
:columnSpace="1"
|
||||
@wapperClick="doProduct"
|
||||
@imageClick="doProduct"
|
||||
>
|
||||
<custom-waterfalls-flow v-model="foodList" imageKey="picUrl" :columnSpace="1" @wapperClick="doProduct" @imageClick="doProduct">
|
||||
<template v-slot:default="v">
|
||||
<view class="p-x-15rpx p-y-25rpx">
|
||||
<view class="sub-text-28 show-line">{{ v.name }}</view>
|
||||
|
||||
@@ -50,13 +50,13 @@ const toDetail = async (v: any) => {
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
@scroll="pageHook.scroll"
|
||||
>
|
||||
<template #top> </template>
|
||||
<view class="h-20rpx" />
|
||||
<view class="flex-row card p-20rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i" @tap="toDetail(v)">
|
||||
<image class="w-160rpx h-160rpx rounded-12rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
|
||||
<view class="flex-1 flex-col m-l-20rpx">
|
||||
<view class="flex-row items-center justify-between">
|
||||
<view class="flex-row-center sub-text-34">
|
||||
<text> {{ v.name }}</text>
|
||||
<text>{{ v.name }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<tm-tag size="s">{{ v.deptName }}</tm-tag>
|
||||
@@ -79,5 +79,3 @@ const toDetail = async (v: any) => {
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
+149
-170
@@ -1,47 +1,85 @@
|
||||
<template>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<view class="h-20rpx" />
|
||||
<view class="flex-row items-center">
|
||||
<image
|
||||
v-if="state.userInfo?.sysUser?.avatar"
|
||||
class="w-100rpx h-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="m-l-30rpx" v-if="state.userInfo?.sysUser?.userId">
|
||||
<view class="flex-row items-center">
|
||||
<text class="sub-text-30">{{ state.userInfo?.sysUser?.name }}</text>
|
||||
<text class="iconfont icon-youjiantou color-#666666 m-l-20rpx"></text>
|
||||
</view>
|
||||
<text class="sub-text-26">ID {{ state.userInfo?.sysUser?.userId }}</text>
|
||||
</view>
|
||||
<view v-else class="flex-row items-center m-l-30rpx" @tap="onTabLogin">
|
||||
<text class="sub-text-32">请先登录</text>
|
||||
<text class="iconfont icon-youjiantou" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="m-t-20rpx rounded-20rpx shadow-main p-30rpx p-b-40rpx bg-white!">
|
||||
<view class="service_item flex-row items-center justify-between" v-for="(v, i) in state.menuList" :key="i" @tap="onTabMenu(v, i)">
|
||||
<view class="flex-row-center">
|
||||
<image class="w-40rpx h-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 m-t-40rpx m-x-30rpx">
|
||||
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff" @tap="doLogout">
|
||||
退出登录
|
||||
</view>
|
||||
</view>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from "vue"
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app"
|
||||
import { isEmpty } from "radash"
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
|
||||
import { hooks, router, constant } from "@@/index"
|
||||
import { merchantApi, userApi, walletApi } from "@@/api"
|
||||
import { userApi } from "@@/api"
|
||||
import isDevEnv from "@/sheep/utils/isDevEnv"
|
||||
|
||||
// 定义类型
|
||||
interface ServiceItem {
|
||||
interface MenuItem {
|
||||
text: string
|
||||
icon: string
|
||||
router: string
|
||||
}
|
||||
|
||||
// 服务列表配置
|
||||
const DEFAULT_SERVICES: ServiceItem[] = [
|
||||
{ text: "钱包管理", icon: "/static/icon/service_3.png", router: "/pages/wallet/list" },
|
||||
{ text: "包厢预定", icon: "/static/icon/service_4.png", router: "/pages/boxes/apply-list" },
|
||||
{ text: "外来人员就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/foreign-list" },
|
||||
{ text: "跨单位就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/stride-list" },
|
||||
{ text: "人脸管理", icon: "/static/icon/service_5.png", router: "/pages/human-face/list" },
|
||||
]
|
||||
|
||||
// 状态管理
|
||||
const state = reactive<any>({
|
||||
const state = reactive<{ wallet: any; userInfo: any; menuList: MenuItem[] }>({
|
||||
wallet: [],
|
||||
userInfo: {},
|
||||
serviceList: [...DEFAULT_SERVICES],
|
||||
menuList: [
|
||||
{ text: "钱包管理", icon: "/static/icon/service_3.png", router: "/pages/wallet/list" },
|
||||
// { text: "包厢预定", icon: "/static/icon/service_4.png", router: "/pages/boxes/apply-list" },
|
||||
// { text: "外来人员就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/foreign-list" },
|
||||
// { text: "跨单位就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/stride-list" },
|
||||
{ text: "人脸管理", icon: "/static/icon/service_5.png", router: "/pages/human-face/list" },
|
||||
],
|
||||
})
|
||||
|
||||
const onTabLogin = () => (isDevEnv() ? router.jump("/pages/test/login") : checkAppInfo())
|
||||
|
||||
// 登录相关方法
|
||||
const loginMethods = {
|
||||
// 诗画环境登录
|
||||
async shihuaLogin() {
|
||||
const appInfo = await (window as any).CP2.getAppInfo()
|
||||
if (appInfo.code !== 1) return false
|
||||
// const appInfo = await (window as any).CP2.getAppInfo()
|
||||
// if (appInfo.code !== 0) return false
|
||||
|
||||
const userInfo = await (window as any).CP2.getUserInfo()
|
||||
const { accountId, sessionId } = userInfo.data
|
||||
return doLogin(1, null, accountId, sessionId)
|
||||
// const userInfo = await (window as any).CP2.getUserInfo()
|
||||
// const { accountId, sessionId } = userInfo.data
|
||||
// return doLogin(1, null, accountId, sessionId)
|
||||
return false
|
||||
},
|
||||
|
||||
// 浙政钉登录
|
||||
@@ -61,115 +99,60 @@ const checkAppInfo = async () => {
|
||||
// 先尝试诗画登录
|
||||
const shihuaResult = await loginMethods.shihuaLogin()
|
||||
if (shihuaResult) return
|
||||
|
||||
// 尝试浙政钉登录
|
||||
const zhengdingResult = await loginMethods.zhengdingLogin()
|
||||
const zhengdingResult = loginMethods.zhengdingLogin()
|
||||
if (zhengdingResult) return
|
||||
|
||||
// 开发环境下跳转到测试登录页
|
||||
if (isDevEnv()) {
|
||||
router.jump("/pages/test/login")
|
||||
}
|
||||
uni.showToast({ title: "当前登录环境未知", icon: "none" })
|
||||
} catch (error) {
|
||||
console.error("登录失败:", error)
|
||||
uni.showToast({ title: "登录失败", icon: "none" })
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(() => {
|
||||
if (isDevEnv()) {
|
||||
state.serviceList.push({
|
||||
text: "测试登录",
|
||||
icon: "/static/icon/login.png",
|
||||
router: "/pages/test/login",
|
||||
})
|
||||
}
|
||||
checkAppInfo()
|
||||
})
|
||||
onShow(() => {
|
||||
getUserInfo()
|
||||
})
|
||||
|
||||
const getUserInfo = () => {
|
||||
const userInfoKey = constant.storageConstant.USERINFO
|
||||
const userStorage = uni.getStorageSync(userInfoKey)
|
||||
if (!isEmpty(userStorage)) {
|
||||
state.userInfo = userStorage
|
||||
} else {
|
||||
state.userInfo = {}
|
||||
}
|
||||
}
|
||||
// {
|
||||
// "accessToken": {
|
||||
// "tokenValue": "06d43795-a3ef-4019-a70f-25830e7183a4",
|
||||
// "issuedAt": "2025-01-24T11:10:30.423604599Z",
|
||||
// "expiresAt": "2025-01-25T11:10:30.423604599Z",
|
||||
// "tokenType": {
|
||||
// "value": "Bearer"
|
||||
// },
|
||||
// "scopes": []
|
||||
// },
|
||||
// "refreshToken": {
|
||||
// "tokenValue": "FmRVP4l3d7t3263h9LeKnV8hdU0lPasMuI1wank_EbylRQPNLm7XP4_OtUV-zH9AbMZc9f14Qk2IXhw-33fWMGGKipVY8crbvVyWV5DeAcfeU8fYyQuNDh9rw3Dq0w75",
|
||||
// "issuedAt": "2025-01-24T11:10:30.423699280Z",
|
||||
// "expiresAt": "2025-01-31T11:10:30.423699280Z"
|
||||
// }
|
||||
// }
|
||||
const doLogin = async (loginType, token, accountId, sessionId) => {
|
||||
// loginType 1:诗画登录 2:浙政钉登录
|
||||
const doLogin = async (loginType: number, token: string, accountId: string | null, sessionId: string | null) => {
|
||||
const tokenKey = constant.storageConstant.TOKEN
|
||||
const userInfoKey = constant.storageConstant.USERINFO
|
||||
const tokenStorage = uni.getStorageSync(tokenKey)
|
||||
const userStorage = uni.getStorageSync(userInfoKey)
|
||||
if (isEmpty(tokenStorage) || isEmpty(userStorage)) {
|
||||
uni.showLoading({
|
||||
title: "登录中...",
|
||||
mask: true,
|
||||
})
|
||||
let authData
|
||||
if (loginType == 1) {
|
||||
switch (loginType) {
|
||||
case 1:
|
||||
// 诗画
|
||||
const params = {
|
||||
accountId: accountId,
|
||||
sessionId: sessionId,
|
||||
// const params = {
|
||||
// accountId: accountId,
|
||||
// sessionId: sessionId,
|
||||
// }
|
||||
// const response = await userApi.authsh(params)
|
||||
// authData = response.data
|
||||
break
|
||||
case 2:
|
||||
if (isEmpty(tokenStorage) || isEmpty(userStorage)) {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: "登录中...",
|
||||
mask: true,
|
||||
})
|
||||
const res = await userApi.auth(token)
|
||||
if (res?.code === 0) {
|
||||
uni.setStorageSync(tokenKey, res.data)
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: "登录成功", icon: "none" })
|
||||
const { data: userData } = await userApi.userInfo()
|
||||
uni.setStorageSync(userInfoKey, userData)
|
||||
getStorageUserInfo()
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: "获取浙政钉用户信息失败", icon: "none" })
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: "错误", icon: "none" })
|
||||
}
|
||||
}
|
||||
const response = await userApi.authsh(params)
|
||||
authData = response.data
|
||||
} else if (loginType == 2) {
|
||||
//浙政钉
|
||||
const response: any = await userApi.auth(token)
|
||||
if (!response) return
|
||||
authData = response.data
|
||||
} else {
|
||||
//后期手机号+验证码登录
|
||||
if (isDevEnv()) router.jump("/pages/test/login")
|
||||
uni.hideLoading()
|
||||
return
|
||||
}
|
||||
// const {data: authData} = await userApi.auth(token);
|
||||
console.log("authData", authData)
|
||||
|
||||
uni.setStorageSync(tokenKey, authData)
|
||||
try {
|
||||
const { data: userData } = await userApi.userInfo()
|
||||
uni.setStorageSync(userInfoKey, userData)
|
||||
getUserInfo()
|
||||
uni.hideLoading()
|
||||
// uni.showToast({ title: "登录成功", icon: "none" })
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: "登录失败", icon: "none" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const toService = async (v: any, i: number) => {
|
||||
if (i == state.serviceList.length - 1) {
|
||||
router.jump(v.router)
|
||||
return
|
||||
}
|
||||
const isLogin = await hooks.useCheckLogin()
|
||||
if (isLogin) {
|
||||
router.jump(v.router)
|
||||
break
|
||||
default:
|
||||
uni.showToast({ title: "当前登录环境未知", icon: "none" })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,64 +172,60 @@ const doLogout = async () => {
|
||||
uni.showToast({ title: "退出登录成功", icon: "none" })
|
||||
}
|
||||
|
||||
const onTabLogin = () => {
|
||||
if (isDevEnv()) {
|
||||
router.jump("/pages/test/login")
|
||||
} else {
|
||||
checkAppInfo()
|
||||
const onTabMenu = async (v: MenuItem, i: number) => {
|
||||
if (i == state.menuList.length - 1) {
|
||||
router.jump(v.router)
|
||||
return
|
||||
}
|
||||
const isLogin = await hooks.useCheckLogin()
|
||||
if (isLogin) {
|
||||
router.jump(v.router)
|
||||
}
|
||||
}
|
||||
|
||||
const getStorageUserInfo = () => {
|
||||
const tokenKey = constant.storageConstant.TOKEN
|
||||
const userInfoKey = constant.storageConstant.USERINFO
|
||||
const tokenStorage = uni.getStorageSync(tokenKey)
|
||||
const userStorage = uni.getStorageSync(userInfoKey)
|
||||
if (!isEmpty(userStorage) && !isEmpty(tokenStorage)) {
|
||||
state.userInfo = userStorage
|
||||
} else {
|
||||
state.userInfo = {}
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(() => {
|
||||
isDevEnv()
|
||||
? state.menuList.push({
|
||||
text: "测试登录",
|
||||
icon: "/static/icon/login.png",
|
||||
router: "/pages/test/login",
|
||||
})
|
||||
: checkAppInfo()
|
||||
})
|
||||
onShow(() => {
|
||||
getStorageUserInfo()
|
||||
})
|
||||
|
||||
// {
|
||||
// "accessToken": {
|
||||
// "tokenValue": "06d43795-a3ef-4019-a70f-25830e7183a4",
|
||||
// "issuedAt": "2025-01-24T11:10:30.423604599Z",
|
||||
// "expiresAt": "2025-01-25T11:10:30.423604599Z",
|
||||
// "tokenType": {
|
||||
// "value": "Bearer"
|
||||
// },
|
||||
// "scopes": []
|
||||
// },
|
||||
// "refreshToken": {
|
||||
// "tokenValue": "FmRVP4l3d7t3263h9LeKnV8hdU0lPasMuI1wank_EbylRQPNLm7XP4_OtUV-zH9AbMZc9f14Qk2IXhw-33fWMGGKipVY8crbvVyWV5DeAcfeU8fYyQuNDh9rw3Dq0w75",
|
||||
// "issuedAt": "2025-01-24T11:10:30.423699280Z",
|
||||
// "expiresAt": "2025-01-31T11:10:30.423699280Z"
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<crud-layout title="我的" bg="/static/page/blue-bg.png">
|
||||
<view class="flex-row items-center">
|
||||
<image
|
||||
class="w-100rpx h-100rpx rounded-full"
|
||||
v-if="state.userInfo?.sysUser?.avatar"
|
||||
:src="filePath(state.userInfo.sysUser.avatar)"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<image class="w-100rpx h-100rpx rounded-full" v-else src="/static/icon/default-avatar.png" mode="aspectFill" />
|
||||
<view class="m-l-30rpx" v-if="state.userInfo?.sysUser?.userId">
|
||||
<view class="flex-row items-center">
|
||||
<text class="sub-text-30">{{ state.userInfo?.sysUser?.name }}</text>
|
||||
<text class="iconfont icon-youjiantou color-#666666 m-l-20rpx"></text>
|
||||
</view>
|
||||
<text class="sub-text-26">ID {{ state.userInfo?.sysUser?.userId }}</text>
|
||||
</view>
|
||||
<view v-else class="flex-row items-center m-l-30rpx" @tap="onTabLogin">
|
||||
<text class="sub-text-32">请先登录</text>
|
||||
<text class="iconfont icon-youjiantou"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="m-t-40rpx rounded-20rpx shadow-main p-30rpx p-b-40rpx bg-white!">
|
||||
<view
|
||||
class="service_item flex-row items-center justify-between"
|
||||
v-for="(v, i) in state.serviceList"
|
||||
:key="i"
|
||||
@tap="toService(v, i)"
|
||||
>
|
||||
<view class="flex-row-center">
|
||||
<image class="w-40rpx h-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>
|
||||
|
||||
<view v-if="isDevEnv()" class="flex-col-center m-t-40rpx m-x-30rpx">
|
||||
<view
|
||||
class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff"
|
||||
@tap="doLogout"
|
||||
>
|
||||
退出登录
|
||||
</view>
|
||||
</view>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.service_item:not(:last-child) {
|
||||
padding-bottom: 40rpx;
|
||||
|
||||
@@ -60,7 +60,7 @@ const doRefund = (v: any) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<crud-layout title="订单" bg="/static/page/blue-bg.png">
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
@@ -139,18 +139,14 @@ const doRefund = (v: any) => {
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view
|
||||
class="absolute top-0 right-0 bottom-0 z-10 flex-col items-end w-160rpx p-x-20rpx bg-white bg-opacity-95"
|
||||
>
|
||||
<view class="absolute top-0 right-0 bottom-0 z-10 flex-col items-end w-160rpx p-x-20rpx bg-white bg-opacity-95">
|
||||
<view class="main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
|
||||
<view class="m-t-10rpx second-text-26">共 {{ v.carList.length }} 件</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="['5', '10'].includes(v.orderStatus)" class="flex-row items-center justify-end p-t-20rpx">
|
||||
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="botder_btn" @tap.stop="doRefund(v)">退款 </view>
|
||||
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="m-l-20rpx botder_btn" @tap.stop="doToDetail(v)">
|
||||
核销码
|
||||
</view>
|
||||
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="m-l-20rpx botder_btn" @tap.stop="doToDetail(v)"> 核销码 </view>
|
||||
</view>
|
||||
</view>
|
||||
</z-paging>
|
||||
|
||||
@@ -50,6 +50,7 @@ const toDetail = async (v: any) => {
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
@scroll="pageHook.scroll"
|
||||
>
|
||||
<view class="h-20rpx" />
|
||||
<view class="flex-col card p-20rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i" @tap="toDetail(v)">
|
||||
<view class="flex-row-center">
|
||||
<image class="w-120rpx h-120rpx rounded-12rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
|
||||
|
||||
@@ -122,7 +122,7 @@ const doFreeze = async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<crud-layout title="钱包" bg="/static/page/blue-bg.png">
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
@@ -172,14 +172,8 @@ const doFreeze = async () => {
|
||||
<text class="sub-text-40 color-red!"> ¥{{ hooks.useMoney(v.balance) }} </text>
|
||||
</view>
|
||||
<view class="flex-row items-center justify-end space-x-20rpx m-t-10rpx">
|
||||
<view v-if="v.walletTypeUniqueCode == 1 && !v.cardNumber" class="botder_btn" @tap.stop="openBindDialog(v)">
|
||||
绑定
|
||||
</view>
|
||||
<view
|
||||
v-if="v.walletTypeUniqueCode == 1 && v.cardNumber && v.isFreeze != 1"
|
||||
class="botder_btn"
|
||||
@tap.stop="openFreezeDialog(v)"
|
||||
>
|
||||
<view v-if="v.walletTypeUniqueCode == 1 && !v.cardNumber" class="botder_btn" @tap.stop="openBindDialog(v)"> 绑定 </view>
|
||||
<view v-if="v.walletTypeUniqueCode == 1 && v.cardNumber && v.isFreeze != 1" class="botder_btn" @tap.stop="openFreezeDialog(v)">
|
||||
申请冻结
|
||||
</view>
|
||||
<view class="botder_btn" @tap.stop="router.jump('/pages/wallet/recharge', { id: v.id })"> 去充值 </view>
|
||||
|
||||
@@ -16,7 +16,7 @@ interface LoginParams {
|
||||
|
||||
export default {
|
||||
// 获取用户信息
|
||||
userInfo: () =>
|
||||
userInfo: (): Promise<any> =>
|
||||
request({
|
||||
url: "/admin/user/info",
|
||||
method: "GET",
|
||||
@@ -27,7 +27,7 @@ export default {
|
||||
}),
|
||||
|
||||
// 浙政钉授权
|
||||
auth: (token: string) =>
|
||||
auth: (token: string): Promise<any> =>
|
||||
request({
|
||||
url: `/thirdparty/thirdPartyOAth2/zzdsso/${token}`,
|
||||
method: "GET",
|
||||
|
||||
@@ -1,165 +1,165 @@
|
||||
<script setup lang="ts">
|
||||
import { defineProps, withDefaults, watch, ref, reactive, onMounted } from "vue";
|
||||
import { defineProps, withDefaults, watch, ref, reactive, onMounted } from "vue"
|
||||
import { router } from "@@/index"
|
||||
|
||||
|
||||
|
||||
export type Props = {
|
||||
tabBarType: "default" | "just-flot-back"
|
||||
title: string
|
||||
scrollHideTabbar: boolean
|
||||
navBgColor: string
|
||||
navBgTitleColor: string
|
||||
mainIsScroll: boolean
|
||||
bg: string
|
||||
tabBarType: "default" | "just-flot-back"
|
||||
title: string
|
||||
scrollHideTabbar: boolean
|
||||
navBgColor: string
|
||||
navBgTitleColor: string
|
||||
mainIsScroll: boolean
|
||||
bg: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
tabBarType: "default",
|
||||
title: "",
|
||||
scrollHideTabbar: true,
|
||||
navBgColor: "transparent",
|
||||
navBgTitleColor: "#333",
|
||||
mainIsScroll: false,
|
||||
bg: "",
|
||||
});
|
||||
|
||||
tabBarType: "default",
|
||||
title: "",
|
||||
scrollHideTabbar: true,
|
||||
navBgColor: "transparent",
|
||||
navBgTitleColor: "#333",
|
||||
mainIsScroll: false,
|
||||
bg: "",
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
navBgTitleColor_: props.navBgTitleColor,
|
||||
visble: {
|
||||
topNav: true,
|
||||
topSafe: true
|
||||
}
|
||||
navBgTitleColor_: props.navBgTitleColor,
|
||||
visble: {
|
||||
topNav: false,
|
||||
topSafe: true,
|
||||
},
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.navBgTitleColor,
|
||||
(newVal) => {
|
||||
if (!newVal) return
|
||||
state.navBgTitleColor_ = newVal
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
() => props.navBgTitleColor,
|
||||
(newVal) => {
|
||||
if (!newVal) return
|
||||
state.navBgTitleColor_ = newVal
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
initBackStyle()
|
||||
initBackStyle()
|
||||
})
|
||||
|
||||
|
||||
function scroll(e) {
|
||||
if (!router.hasTabbar()) return
|
||||
if (!props.scrollHideTabbar) return
|
||||
const offset = 50
|
||||
const top = e.target.scrollTop;
|
||||
if (!router.hasTabbar()) return
|
||||
if (!props.scrollHideTabbar) return
|
||||
const offset = 50
|
||||
const top = e.target.scrollTop
|
||||
}
|
||||
|
||||
function defaultPage() {
|
||||
const { route } = router.getCurrentPage() as any
|
||||
const page = __ROUTES__.find(it => it.path == `/${route}`)
|
||||
if (page && page.name) {
|
||||
return page.name;
|
||||
}
|
||||
return ""
|
||||
const { route } = router.getCurrentPage() as any
|
||||
const page = __ROUTES__.find((it) => it.path == `/${route}`)
|
||||
if (page && page.name) {
|
||||
return page.name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
function initBackStyle() {
|
||||
switch (props.tabBarType) {
|
||||
case "default":
|
||||
break;
|
||||
case "just-flot-back":
|
||||
state.visble.topSafe = true
|
||||
state.visble.topNav = false
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (props.tabBarType) {
|
||||
case "default":
|
||||
break
|
||||
case "just-flot-back":
|
||||
state.visble.topSafe = true
|
||||
state.visble.topNav = false
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="layout">
|
||||
<image class="layout_bg" v-if="props.bg" :src="props.bg" mode="aspectFill" />
|
||||
<view class="layout_header">
|
||||
<base-safe-height :bgColor="props.navBgColor" v-if="state.visble.topSafe" type="top" />
|
||||
<base-nav v-if="state.visble.topNav" :titleColor="props.navBgTitleColor" :bgColor="props.navBgColor"
|
||||
:title="props.title || defaultPage()" />
|
||||
<base-just-flot-nav :bgColor="props.navBgColor" :titleColor="props.navBgTitleColor"
|
||||
v-if="!state.visble.topNav"></base-just-flot-nav>
|
||||
</view>
|
||||
<view class="layout_main">
|
||||
<view class="layout_main_top">
|
||||
<slot name="main-top"></slot>
|
||||
</view>
|
||||
<scroll-view :scroll-y="mainIsScroll" @scroll="scroll">
|
||||
<slot></slot>
|
||||
</scroll-view>
|
||||
<view class="layout_main_bottom">
|
||||
<slot name="main-bottom"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="layout">
|
||||
<image class="layout_bg" v-if="props.bg" :src="props.bg" mode="aspectFill" />
|
||||
<view class="layout_header">
|
||||
<base-safe-height :bgColor="props.navBgColor" v-if="state.visble.topSafe" type="top" />
|
||||
<base-nav
|
||||
v-if="state.visble.topNav"
|
||||
:titleColor="props.navBgTitleColor"
|
||||
:bgColor="props.navBgColor"
|
||||
:title="props.title || defaultPage()"
|
||||
/>
|
||||
<base-just-flot-nav :bgColor="props.navBgColor" :titleColor="props.navBgTitleColor" v-if="!state.visble.topNav"></base-just-flot-nav>
|
||||
</view>
|
||||
<view class="layout_main">
|
||||
<view class="layout_main_top">
|
||||
<slot name="main-top"></slot>
|
||||
</view>
|
||||
<scroll-view :scroll-y="mainIsScroll" @scroll="scroll">
|
||||
<slot></slot>
|
||||
</scroll-view>
|
||||
<view class="layout_main_bottom">
|
||||
<slot name="main-bottom"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// #ifdef H5
|
||||
page {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
.layout {
|
||||
width: 100%;
|
||||
// #ifndef H5
|
||||
height: 100vh;
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
height: 100%;
|
||||
// #endif
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
// #ifndef H5
|
||||
height: 100vh;
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
height: 100%;
|
||||
// #endif
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&_bg {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
&_bg {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&_header {
|
||||
z-index: 100;
|
||||
}
|
||||
&_header {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
&_main {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 99;
|
||||
&_main {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 99;
|
||||
|
||||
&_top {}
|
||||
&_top {
|
||||
}
|
||||
|
||||
scroll-view {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
padding: 0 30rpx;
|
||||
// background: #ecf4f9;
|
||||
}
|
||||
scroll-view {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
padding: 0 30rpx;
|
||||
// background: #ecf4f9;
|
||||
}
|
||||
|
||||
&_bottom {
|
||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
&_bottom {
|
||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
&_foot {}
|
||||
&_foot {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1 +1,2 @@
|
||||
export default () => import.meta.env.VITE_DEV_ENV === "dev"
|
||||
// export default () => process.env.NODE_ENV === "development"
|
||||
+81
-76
@@ -1,40 +1,15 @@
|
||||
import Request from "luch-request"
|
||||
import { isEmpty } from "radash"
|
||||
|
||||
import { userApi } from "@@/api"
|
||||
import { router, constant } from "@@/index"
|
||||
import isDevEnv from "./isDevEnv"
|
||||
import { router, constant } from "@@/index"
|
||||
import { userApi } from "../api"
|
||||
|
||||
// 定义常量
|
||||
const TOKEN_KEY = constant.storageConstant.TOKEN
|
||||
const USER_INFO_KEY = constant.storageConstant.USERINFO
|
||||
const REFRESH_TOKEN_URL = "/auth/oauth2/token?grant_type=refresh_token"
|
||||
|
||||
// 定义类型
|
||||
interface LoadingInstance {
|
||||
target: any
|
||||
count: number
|
||||
}
|
||||
|
||||
// 默认请求配置
|
||||
const defaultOptions = {
|
||||
showSuccess: false,
|
||||
// 成功提醒 默认使用后端返回值
|
||||
successMsg: "",
|
||||
// 显示失败消息 默认显示
|
||||
showError: true,
|
||||
// 失败提醒 默认使用后端返回信息
|
||||
errorMsg: "",
|
||||
// 显示请求时loading模态框 默认显示
|
||||
showLoading: true,
|
||||
// loading提醒文字
|
||||
loadingMsg: "加载中",
|
||||
// 需要授权才能请求 默认放开
|
||||
auth: false,
|
||||
}
|
||||
|
||||
// Loading 管理
|
||||
const LoadingInstance: LoadingInstance = {
|
||||
const LoadingInstance: { target: any; count: number } = {
|
||||
target: null,
|
||||
count: 0,
|
||||
}
|
||||
@@ -55,7 +30,21 @@ const http = new Request({
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
withCredentials: true,
|
||||
custom: defaultOptions,
|
||||
custom: {
|
||||
showSuccess: false,
|
||||
// 成功提醒 默认使用后端返回值
|
||||
successMsg: "",
|
||||
// 显示失败消息 默认显示
|
||||
showError: true,
|
||||
// 失败提醒 默认使用后端返回信息
|
||||
errorMsg: "",
|
||||
// 显示请求时loading模态框 默认显示
|
||||
showLoading: true,
|
||||
// loading提醒文字
|
||||
loadingMsg: "加载中",
|
||||
// 需要授权才能请求 默认放开
|
||||
auth: false,
|
||||
},
|
||||
})
|
||||
|
||||
// 处理请求头 Authorization
|
||||
@@ -71,14 +60,14 @@ http.interceptors.request.use((config) => {
|
||||
const tokenStorage = uni.getStorageSync(TOKEN_KEY)
|
||||
const config_header: any = config?.header || {}
|
||||
|
||||
// 设置通用请求头
|
||||
// 设置租户请求头
|
||||
config_header["TENANT-ID"] = "1"
|
||||
if (import.meta.env.VITE_IS_TOC === "true") {
|
||||
config_header["CLIENT-TOC"] = "Y"
|
||||
}
|
||||
|
||||
// 设置认证头
|
||||
if (config.url !== "/sys/auth/refresh-token") {
|
||||
if (config.url !== "/sys/auth/refresh-token" && config.url !== "/auth/oauth2/token") {
|
||||
const authHeader = getAuthHeader(tokenStorage)
|
||||
if (authHeader) {
|
||||
config_header.Authorization = authHeader
|
||||
@@ -131,7 +120,7 @@ const responseHelpers = {
|
||||
// 处理成功提示
|
||||
handleSuccessMessage(response: any) {
|
||||
const { data, config } = response
|
||||
if (data.code === 200 && data.message && config?.custom?.showSuccess) {
|
||||
if (data.code === 0 && data.message && config?.custom?.showSuccess) {
|
||||
uni.showToast({
|
||||
title: config.custom.successMsg || data.message,
|
||||
icon: "none",
|
||||
@@ -142,21 +131,67 @@ const responseHelpers = {
|
||||
// 处理登录过期
|
||||
handleLoginExpired() {
|
||||
uni.removeStorageSync(TOKEN_KEY)
|
||||
uni.removeStorageSync(USER_INFO_KEY)
|
||||
uni.showToast({ title: "登录已过期,请重新登录", icon: "none" })
|
||||
router.jump("/pages/test/login")
|
||||
isDevEnv() ? router.jump("/pages/test/login") : router.jump("/pages/tabbar/my")
|
||||
},
|
||||
|
||||
// 检查并刷新token
|
||||
async checkAndRefreshToken(tokenStorage: any) {
|
||||
const { refresh_token, expiresTime } = tokenStorage
|
||||
if (!refresh_token || !expiresTime) return
|
||||
checkAndRefreshToken(tokenStorage: any) {
|
||||
const { accessToken } = tokenStorage
|
||||
if (!accessToken) return
|
||||
|
||||
const now = new Date().getTime()
|
||||
const remain = expiresTime - now
|
||||
if (remain <= 1000 * 60 * 20) {
|
||||
const refreshData = await userApi.refreshToken({ refreshToken: refresh_token })
|
||||
if (!isEmpty(refreshData.data)) {
|
||||
uni.setStorageSync(TOKEN_KEY, refreshData.data)
|
||||
const issuedDate = new Date(accessToken.issuedAt).getTime()
|
||||
console.log(new Date().getTime() - issuedDate)
|
||||
|
||||
if (new Date().getTime() - issuedDate >= 1000 * 60 * 20) {
|
||||
// try {
|
||||
// const refreshData: any = await request({
|
||||
// url: "/auth/oauth2/token",
|
||||
// method: "POST",
|
||||
// params: { grant_type: "refresh_token" },
|
||||
// data: JSON.stringify({
|
||||
// scope: "server",
|
||||
// refresh_token: tokenStorage.refreshToken.tokenValue,
|
||||
// }),
|
||||
// header: {
|
||||
// skipToken: true,
|
||||
// Authorization: "Basic " + window.btoa(import.meta.env.VITE_OAUTH2_APP_CLIENT),
|
||||
// "content-type": "application/x-www-form-urlencoded",
|
||||
// },
|
||||
// })
|
||||
|
||||
// if (refreshData.code === 0 && !isEmpty(refreshData.data)) {
|
||||
// console.log("refreshData.data", refreshData.data)
|
||||
|
||||
// // 刷新成功,更新token并重试请求
|
||||
// uni.setStorageSync(TOKEN_KEY, refreshData.data)
|
||||
// }
|
||||
// } catch (refreshError) {
|
||||
// console.error("Token refresh failed:", refreshError)
|
||||
// }
|
||||
try {
|
||||
const params = new URL(window.location.href).searchParams
|
||||
const token = params.get("uabaseToken")
|
||||
if (token) {
|
||||
userApi.auth(token).then((res) => {
|
||||
if (res?.code === 0) {
|
||||
uni.setStorageSync(TOKEN_KEY, res.data)
|
||||
} else {
|
||||
uni.removeStorageSync(TOKEN_KEY)
|
||||
uni.removeStorageSync(USER_INFO_KEY)
|
||||
// uni.showToast({ title: "登录已过期", icon: "none" })
|
||||
return Promise.resolve({
|
||||
code: 1,
|
||||
data: "登录已过期",
|
||||
msg: "登录已过期",
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: "错误", icon: "none" })
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -165,6 +200,8 @@ const responseHelpers = {
|
||||
// 响应拦截器
|
||||
http.interceptors.response.use(
|
||||
async (response) => {
|
||||
console.log("response", response)
|
||||
|
||||
// 关闭loading
|
||||
if (response.config?.custom?.showLoading) {
|
||||
closeLoading()
|
||||
@@ -195,19 +232,15 @@ http.interceptors.response.use(
|
||||
|
||||
// Token 刷新检查
|
||||
const tokenStorage = uni.getStorageSync(TOKEN_KEY)
|
||||
if (!isEmpty(tokenStorage) && response.config.url !== "/sys/auth/refresh-token") {
|
||||
if (!isEmpty(tokenStorage) && !response.config.url?.startsWith("/thirdparty/thirdPartyOAth2/zzdsso")) {
|
||||
await responseHelpers.checkAndRefreshToken(tokenStorage)
|
||||
}
|
||||
|
||||
return Promise.resolve(response.data)
|
||||
},
|
||||
|
||||
// 错误拦截器
|
||||
async (error) => {
|
||||
(error) => {
|
||||
// 处理 424 错误(token过期)
|
||||
if (error.statusCode === 424) {
|
||||
const tokenStorage = uni.getStorageSync(TOKEN_KEY)
|
||||
|
||||
if (isDevEnv()) {
|
||||
// 开发环境直接清除token并跳转登录
|
||||
uni.removeStorageSync(TOKEN_KEY)
|
||||
@@ -216,34 +249,6 @@ http.interceptors.response.use(
|
||||
router.jump("/pages/test/login")
|
||||
return false
|
||||
}
|
||||
|
||||
// 生产环境尝试刷新token
|
||||
if (tokenStorage?.refreshToken?.tokenValue) {
|
||||
try {
|
||||
const refreshData = await request({
|
||||
url: REFRESH_TOKEN_URL,
|
||||
method: "POST",
|
||||
data: JSON.stringify({
|
||||
scope: "server",
|
||||
refresh_token: tokenStorage.refreshToken.tokenValue,
|
||||
}),
|
||||
header: {
|
||||
Authorization: "Basic " + window.btoa(import.meta.env.VITE_OAUTH2_APP_CLIENT),
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
})
|
||||
|
||||
if (refreshData.code === 0) {
|
||||
// 刷新成功,更新token并重试请求
|
||||
uni.setStorageSync(TOKEN_KEY, refreshData.data)
|
||||
const config = error.config
|
||||
config.header!.Authorization = `Bearer ${refreshData.data.accessToken.tokenValue}`
|
||||
return http.request(config)
|
||||
}
|
||||
} catch (refreshError) {
|
||||
console.error("Token refresh failed:", refreshError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 显示错误信息
|
||||
|
||||
Reference in new issue
Block a user