Merge branch 'master' of https://codeup.aliyun.com/bsdtec/biz-mobile-react-cloud
# Conflicts: # src/pages.json
This commit is contained in:
commit
86467d7298
32 files changed
+396
-583
No files matched your search
@@ -62,7 +62,6 @@
|
||||
"@zebra-ui/swiper": "^2.2.8",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"gdt-jsapi": "^1.9.51",
|
||||
"luch-request": "^3.1.1",
|
||||
"pinia": "^2.2.6",
|
||||
"qrcode": "^1.5.4",
|
||||
|
||||
Generated
-16
@@ -65,9 +65,6 @@ importers:
|
||||
dayjs:
|
||||
specifier: ^1.11.13
|
||||
version: 1.11.13
|
||||
gdt-jsapi:
|
||||
specifier: ^1.9.51
|
||||
version: 1.9.51
|
||||
luch-request:
|
||||
specifier: ^3.1.1
|
||||
version: 3.1.1
|
||||
@@ -1304,9 +1301,6 @@ packages:
|
||||
'@polka/url@1.0.0-next.28':
|
||||
resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==}
|
||||
|
||||
'@remax/mini-types@0.1.0':
|
||||
resolution: {integrity: sha512-bVDcbUrp6p0PZwfS0xGVQS6k9f8B35BtZaYt/W/IGKh7VALYQ+tS2KcytLRmIJ/Vmohaw5ikIRN89I+frPdh4g==}
|
||||
|
||||
'@rollup/pluginutils@5.1.4':
|
||||
resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
@@ -2426,9 +2420,6 @@ packages:
|
||||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
gdt-jsapi@1.9.51:
|
||||
resolution: {integrity: sha512-VN1iIK7kJU2g2oxY/n8waCREhWxcVwR8qHAE1keVnUJHI6mTdgTelICzq++niRRCaLqUVWC1pYvftEVgk4sq8A==}
|
||||
|
||||
generic-names@4.0.0:
|
||||
resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==}
|
||||
|
||||
@@ -6021,8 +6012,6 @@ snapshots:
|
||||
|
||||
'@polka/url@1.0.0-next.28': {}
|
||||
|
||||
'@remax/mini-types@0.1.0': {}
|
||||
|
||||
'@rollup/pluginutils@5.1.4(rollup@4.34.2)':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.6
|
||||
@@ -7275,11 +7264,6 @@ snapshots:
|
||||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
gdt-jsapi@1.9.51:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.7
|
||||
'@remax/mini-types': 0.1.0
|
||||
|
||||
generic-names@4.0.0:
|
||||
dependencies:
|
||||
loader-utils: 3.3.1
|
||||
|
||||
+10
-6
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import isDevEnv from "./sheep/utils/isDevEnv"
|
||||
import { getAppInfo } from "@@/utils/getAppInfo"
|
||||
import getLaunchParam from "@/sheep/utils/getLaunchParam"
|
||||
import { isDevEnv, getLaunchParam } from "@/sheep/utils/app"
|
||||
import { getAppInfo } from "@@/utils/app"
|
||||
|
||||
// import { onLaunch, onShow, onHide } from "@dcloudio/uni-app"
|
||||
// onLaunch(() => {})
|
||||
@@ -153,9 +152,6 @@ export default {
|
||||
case "coopMerchant":
|
||||
uni.switchTab({ url: "/pages/tabbar/coopMerchant" })
|
||||
break
|
||||
case "thirdApp":
|
||||
uni.navigateTo({ url: "/pages/thirdApp/thirdAppList" })
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -163,6 +159,10 @@ export default {
|
||||
// 诗画环境
|
||||
const userRole = uni.getStorageSync("userRole")
|
||||
const launchParam = getLaunchParam()
|
||||
if (launchParam == "thirdApp") {
|
||||
uni.navigateTo({ url: "/pages/thirdApp/thirdAppList" })
|
||||
return
|
||||
}
|
||||
if (launchParam) {
|
||||
switch (userRole) {
|
||||
case "merchant":
|
||||
@@ -206,6 +206,10 @@ export default {
|
||||
} else if (appInfo == "sh") {
|
||||
// 是诗画环境
|
||||
const userRole = uni.getStorageSync("userRole")
|
||||
if (launchParam == "thirdApp") {
|
||||
uni.navigateTo({ url: "/pages/thirdApp/thirdApp" })
|
||||
return
|
||||
}
|
||||
if (launchParam) {
|
||||
switch (userRole) {
|
||||
case "user":
|
||||
|
||||
+10
-15
@@ -246,12 +246,19 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/test",
|
||||
"root": "pages/user",
|
||||
"pages": [
|
||||
{
|
||||
"path": "login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationBarTitleText": "密码登录",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "userRole",
|
||||
"style": {
|
||||
"navigationBarTitleText": "用户身份",
|
||||
"disableScroll": true
|
||||
}
|
||||
}
|
||||
@@ -302,18 +309,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/user",
|
||||
"pages": [
|
||||
{
|
||||
"path": "userRole",
|
||||
"style": {
|
||||
"navigationBarTitleText": "用户身份",
|
||||
"disableScroll": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/pay",
|
||||
"pages": [
|
||||
@@ -462,7 +457,7 @@
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "浦江小程序",
|
||||
"navigationBarTitleText": "浦江智慧后勤h5",
|
||||
"navigationBarBackgroundColor": "#1777FF",
|
||||
"backgroundColor": "#ecf4f9",
|
||||
"navigationStyle": "custom"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, nextTick } from "vue"
|
||||
import { ref, reactive } from "vue"
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app"
|
||||
import { isEmpty } from "radash"
|
||||
|
||||
import { hooks, router, constant } from "@@/index"
|
||||
import { hooks, router } from "@@/index"
|
||||
import { faceApi } from "@@/api"
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<view class="min-h-screen bg-white px-30rpx pb-30rpx">
|
||||
<!-- 顶部导航 -->
|
||||
<view class="flex items-center h-88rpx relative">
|
||||
<view class="absolute left-0 h-88rpx flex items-center pr-20rpx" @tap="goBack">
|
||||
<text class="text-36rpx text-gray-800"><</text>
|
||||
<text class="text-28rpx text-gray-800 ml-4rpx">返回</text>
|
||||
</view>
|
||||
<view class="flex-1 text-center text-34rpx font-500">问题反馈</view>
|
||||
</view>
|
||||
|
||||
<!-- 问题分类 -->
|
||||
<view class="mt-40rpx">
|
||||
<view class="text-32rpx font-500 mb-24rpx">问题分类</view>
|
||||
<view class="flex flex-wrap gap-24rpx">
|
||||
<view
|
||||
v-for="(item, index) in categories"
|
||||
:key="index"
|
||||
:class="[
|
||||
'px-32rpx py-12rpx rounded-20rpx text-28rpx transition-colors duration-200',
|
||||
selectedCategory === item ? 'bg-blue-200 text-blue-600' : 'bg-gray-100',
|
||||
]"
|
||||
@tap="selectedCategory = item"
|
||||
>
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 详细描述 -->
|
||||
<view class="mt-40rpx">
|
||||
<view class="text-32rpx font-500 mb-24rpx">
|
||||
详细描述
|
||||
<text class="text-red-500 ml-8rpx">*</text>
|
||||
</view>
|
||||
<view class="w-full bg-gray-50 rounded-16rpx p-20rpx box-border">
|
||||
<textarea
|
||||
v-model="description"
|
||||
placeholder="您在哪个页面,遇到了什么问题,详细描述有助于帮您快速解决"
|
||||
placeholder-style="color: #999999;"
|
||||
:maxlength="200"
|
||||
class="w-full h-240rpx bg-gray-50 text-28rpx leading-40rpx p-0 box-border"
|
||||
/>
|
||||
<view class="text-right text-gray-400 text-24rpx mt-8rpx">{{ description.length }}/200</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 图片上传 -->
|
||||
<view class="mt-40rpx">
|
||||
<view class="text-32rpx font-500 mb-24rpx">上传图片 ({{ images.length }}/3)</view>
|
||||
<view class="flex flex-wrap gap-24rpx">
|
||||
<view v-for="(img, index) in images" :key="index" class="relative w-160rpx h-160rpx">
|
||||
<image :src="img" mode="aspectFill" class="w-full h-full rounded-16rpx" />
|
||||
<view
|
||||
class="absolute -right-12rpx -top-12rpx w-40rpx h-40rpx bg-black bg-opacity-60 text-white rounded-full flex items-center justify-center active:bg-opacity-80"
|
||||
@tap="deleteImage(index)"
|
||||
>
|
||||
×
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="images.length < 3"
|
||||
class="w-160rpx h-160rpx rounded-16rpx border border-dashed border-gray-200 flex items-center justify-center active:bg-gray-50"
|
||||
@tap="handleUpload"
|
||||
>
|
||||
<view class="text-48rpx text-gray-400">+</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<view class="mt-40rpx">
|
||||
<view class="text-32rpx font-500 mb-24rpx">联系方式</view>
|
||||
<view class="w-full bg-gray-50 rounded-16rpx px-20rpx box-border">
|
||||
<input
|
||||
v-model="contact"
|
||||
placeholder="手机号/邮箱/微信号"
|
||||
placeholder-style="color: #999999;"
|
||||
class="w-full h-88rpx text-28rpx bg-gray-50"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 邮箱联系我们 -->
|
||||
<view class="mt-48rpx flex items-center justify-between text-28rpx">
|
||||
<view class="text-gray-800">邮箱联系我们</view>
|
||||
<view class="flex items-center gap-16rpx">
|
||||
<text class="text-gray-600">user_service@36kr.com</text>
|
||||
<view class="px-24rpx py-8rpx bg-gray-100 rounded-8rpx text-28rpx active:bg-gray-200" @tap="copyEmail"> 复制 </view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view
|
||||
class="my-64rpx h-88rpx bg-blue-500 text-white rounded-20rpx flex items-center justify-center text-32rpx active:bg-blue-600 transition-colors duration-200"
|
||||
@tap="handleSubmit"
|
||||
>
|
||||
提 交
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
|
||||
const categories = ["产品建议", "功能Bug", "内容订正", "其他"]
|
||||
const selectedCategory = ref("产品建议")
|
||||
const description = ref("")
|
||||
const images = ref<string[]>([])
|
||||
const contact = ref("")
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
const handleUpload = () => {
|
||||
uni.chooseImage({
|
||||
count: 3 - images.value.length,
|
||||
success: (res) => {
|
||||
images.value = [...images.value, ...res.tempFilePaths]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const deleteImage = (index: number) => {
|
||||
images.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const copyEmail = () => {
|
||||
uni.setClipboardData({
|
||||
data: "user_service@36kr.com",
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: "复制成功",
|
||||
icon: "none",
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!description.value) {
|
||||
uni.showToast({
|
||||
title: "请填写详细描述",
|
||||
icon: "none",
|
||||
})
|
||||
return
|
||||
}
|
||||
// 实现提交逻辑
|
||||
}
|
||||
</script>
|
||||
@@ -1,337 +0,0 @@
|
||||
<template>
|
||||
<view class="feedback-page">
|
||||
<!-- 顶部导航 -->
|
||||
<view class="header">
|
||||
<view class="back-btn" @tap="goBack">
|
||||
<text class="back-icon"><</text>
|
||||
<text class="back-text">返回</text>
|
||||
</view>
|
||||
<view class="title">其它问题</view>
|
||||
</view>
|
||||
|
||||
<!-- 问题分类 -->
|
||||
<view class="category-section">
|
||||
<view class="section-title">问题分类</view>
|
||||
<view class="category-list">
|
||||
<view
|
||||
v-for="(item, index) in categories"
|
||||
:key="index"
|
||||
:class="['category-item', { active: selectedCategory === item }]"
|
||||
@tap="selectedCategory = item"
|
||||
>
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 详细描述 -->
|
||||
<view class="description-section">
|
||||
<view class="section-title">
|
||||
详细描述
|
||||
<text class="required">*</text>
|
||||
</view>
|
||||
<view class="textarea-wrap">
|
||||
<textarea
|
||||
v-model="description"
|
||||
placeholder="您在哪个页面,遇到了什么问题,详细描述有助于帮您快速解决"
|
||||
placeholder-style="color: #999999;"
|
||||
:maxlength="200"
|
||||
class="feedback-textarea"
|
||||
></textarea>
|
||||
<view class="word-count">{{ description.length }}/200</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 图片上传 -->
|
||||
<view class="upload-section">
|
||||
<view class="section-title">上传图片 ({{ images.length }}/3)</view>
|
||||
<view class="upload-area">
|
||||
<view
|
||||
v-for="(img, index) in images"
|
||||
:key="index"
|
||||
class="image-item"
|
||||
>
|
||||
<image :src="img" mode="aspectFill"/>
|
||||
<view class="delete-btn" @tap="deleteImage(index)">×</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="images.length < 3"
|
||||
class="upload-btn"
|
||||
@tap="handleUpload"
|
||||
>
|
||||
<view class="plus">+</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<!-- <view class="contact-section">-->
|
||||
<!-- <view class="section-title">联系方式</view>-->
|
||||
<!-- <view class="input-wrap">-->
|
||||
<!-- <input -->
|
||||
<!-- v-model="contact"-->
|
||||
<!-- placeholder="手机号/邮箱/微信号"-->
|
||||
<!-- placeholder-style="color: #999999;"-->
|
||||
<!-- class="contact-input"-->
|
||||
<!-- />-->
|
||||
<!-- </view>-->
|
||||
<!-- </view>-->
|
||||
|
||||
<!-- <!– 邮箱联系 –>-->
|
||||
<!-- <view class="email-contact">-->
|
||||
<!-- <view class="contact-text">联系我们</view>-->
|
||||
<!-- <view class="email">-->
|
||||
<!-- user_service@36kr.com-->
|
||||
<!-- <view class="copy-btn" @tap="copyEmail">复制</view>-->
|
||||
<!-- </view>-->
|
||||
<!-- </view>-->
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-btn" @tap="handleSubmit">提交</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
const categories = ['产品建议', '功能Bug', '内容订正', '其他']
|
||||
const selectedCategory = ref('产品建议')
|
||||
const description = ref('')
|
||||
const images = ref([])
|
||||
const contact = ref('')
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
const handleUpload = () => {
|
||||
uni.chooseImage({
|
||||
count: 3 - images.value.length,
|
||||
success: (res) => {
|
||||
images.value = [...images.value, ...res.tempFilePaths]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const deleteImage = (index: number) => {
|
||||
images.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const copyEmail = () => {
|
||||
uni.setClipboardData({
|
||||
data: 'user_service@36kr.com',
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: '复制成功',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!description.value) {
|
||||
uni.showToast({
|
||||
title: '请填写详细描述',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
// 实现提交逻辑
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.feedback-page {
|
||||
padding: 0 30rpx;
|
||||
min-height: 100vh;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 88rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 20rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 36rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.back-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 40rpx 0 24rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.required {
|
||||
color: #ff4d4f;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.category-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.category-item {
|
||||
padding: 12rpx 32rpx;
|
||||
border-radius: 32rpx;
|
||||
background: #f5f5f5;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.category-item.active {
|
||||
background: #e6f4ff;
|
||||
color: #1677ff;
|
||||
}
|
||||
|
||||
.textarea-wrap {
|
||||
width: 100%;
|
||||
background-color: #F8F8F8;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.feedback-textarea {
|
||||
width: 100%;
|
||||
height: 240rpx;
|
||||
background-color: #F8F8F8;
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.word-count {
|
||||
text-align: right;
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.image-item, .upload-btn {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 16rpx;
|
||||
border: 1rpx dashed #e5e5e5;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.image-item image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.upload-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.plus {
|
||||
font-size: 48rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
position: absolute;
|
||||
right: -12rpx;
|
||||
top: -12rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.input-wrap {
|
||||
width: 100%;
|
||||
background-color: #F8F8F8;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.contact-input {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
font-size: 28rpx;
|
||||
background-color: #F8F8F8;
|
||||
}
|
||||
|
||||
.email-contact {
|
||||
margin: 48rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.email {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
padding: 8rpx 24rpx;
|
||||
background: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
margin: 64rpx 0;
|
||||
height: 88rpx;
|
||||
background: #1677ff;
|
||||
color: #fff;
|
||||
border-radius: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
/* 修改输入框的placeholder样式 */
|
||||
::-webkit-input-placeholder {
|
||||
color: #999999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -28,7 +28,7 @@
|
||||
</view>
|
||||
</tm-sheet>
|
||||
|
||||
<tm-button class="mt-1" :block="true" @click="disabled ? '' : handlePay()" :disabled="disabled">支付</tm-button>
|
||||
<tm-button class="mt-1" :block="true" @click="disabled ? '' : handlePay()" :disabled="disabled">支 付</tm-button>
|
||||
|
||||
<numberKeyboard v-model="amount" />
|
||||
</view>
|
||||
@@ -38,15 +38,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, reactive } from "vue"
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app"
|
||||
import { usePayStore } from "@/sheep/stores/pay"
|
||||
import payApi from "@@/api/pay"
|
||||
import { storePrice } from "@/sheep/utils/formatMoney"
|
||||
import { router } from "@/sheep"
|
||||
import { merchantApi, walletApi } from "@/sheep/api"
|
||||
import numberKeyboard from "@/sheep/components/numberKeyboard.vue"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
import { hooks } from "@@/index"
|
||||
import { router } from "@/sheep"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
import { storePrice } from "@/sheep/utils/formatMoney"
|
||||
import { usePayStore } from "@/sheep/stores/pay"
|
||||
import { isEmpty } from "radash"
|
||||
import numberKeyboard from "@/sheep/components/numberKeyboard.vue"
|
||||
|
||||
const scanCodeData = reactive({
|
||||
id: "",
|
||||
@@ -69,8 +69,13 @@ onShow(async () => {
|
||||
uni.showLoading({ title: "加载中...", mask: true })
|
||||
if (scanCodeData.id) {
|
||||
const { data } = await merchantApi.detail({ id: scanCodeData.id })
|
||||
scanCodeData.name = data.name
|
||||
disabled.value = false
|
||||
if (data) {
|
||||
scanCodeData.name = data.name
|
||||
disabled.value = false
|
||||
} else {
|
||||
disabled.value = true
|
||||
return uni.showToast({ title: "商户id错误", icon: "none" })
|
||||
}
|
||||
} else {
|
||||
uni.showToast({ title: "参数不存在", icon: "none" })
|
||||
disabled.value = true
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
<view class="bg-gray-100 flex-col min-h-screen">
|
||||
<view class="bg-white p-4 card mx-3 my-1 mt-2 flex items-center justify-between">
|
||||
<view class="flex items-center">
|
||||
<image class="w-64 h-64 mr-2" :src="filePath(transferMoney.sourceWalletType.walletTypeIcon)" />
|
||||
<view>{{ transferMoney.sourceWalletType.walletTypeName }}</view>
|
||||
<image class="w-64 h-64 mr-2" :src="filePath(payStore.sourceWalletData.walletTypeIcon)" />
|
||||
<view>{{ payStore.sourceWalletData.walletTypeName }}</view>
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<view class="main-text-28">余额:</view>
|
||||
<view class="main-text-28 mr-1">{{ hooks.useMoney(transferMoney.sourceWalletType.balance) + "元" }}</view>
|
||||
<view class="main-text-28 mr-1">{{ hooks.useMoney(payStore.sourceWalletData.balance) + "元" }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg-white p-4 card mx-3 my-1 flex items-center justify-between active:bg-[#f0f0f0]" @click="targetWalletSelect">
|
||||
<view class="bg-white p-4 card mx-3 my-1 flex items-center justify-between active:bg-[#f0f0f0]" @click="show = true">
|
||||
<view class="flex items-center">
|
||||
<image class="w-64 h-64 rounded-full mr-2" src="@/static/page/money-cny-circle-fill.svg" />
|
||||
<view>转入到</view>
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<view class="second-text-28 mr-1">{{ state.targetWalletTypeName }}</view>
|
||||
<view class="second-text-28 mr-1">{{ targetWalletType.name }}</view>
|
||||
<image class="w-38 h-38 rounded-full c-blueGray" src="@/static/page/arrow-right.svg" />
|
||||
</view>
|
||||
</view>
|
||||
@@ -32,26 +32,24 @@
|
||||
</view>
|
||||
<!-- 金额限制提示 -->
|
||||
<view class="h-30rpx">
|
||||
<view v-if="storePrice(amount) > transferMoney.sourceWalletType?.balance" class="text-xs c-red px-8">
|
||||
注:转账金额不能超过钱包余额
|
||||
</view>
|
||||
<view v-if="storePrice(amount) > payStore.sourceWalletData?.balance" class="text-xs c-red px-8">注:转账金额不能超过钱包余额</view>
|
||||
</view>
|
||||
|
||||
<view class="p-4 font-bold mt-1">
|
||||
<tm-button block @click="confirmTransfer" v-if="transferMoney.sourceWalletType.walletTypeId">确定转账</tm-button>
|
||||
<tm-button block @click="confirmTransfer" v-if="payStore.sourceWalletData.walletTypeId">确定转账</tm-button>
|
||||
</view>
|
||||
|
||||
<number-keyboard v-model="amount" />
|
||||
|
||||
<!-- 选择转入方式 -->
|
||||
<tm-drawer v-model:show="show" title="选择钱包" size="50%" bg-color="#efefef" position="bottom" :show-footer="true" :showClose="true">
|
||||
<tm-drawer v-model:show="show" title="选择钱包" size="30%" bg-color="#efefef" position="bottom" :show-footer="false" :showClose="true">
|
||||
<view class="m-4">
|
||||
<view
|
||||
v-for="(v, index) in state.walletList"
|
||||
v-for="(v, index) in wallet.walletList"
|
||||
:key="index"
|
||||
class="card mb-2 overflow-hidden relative border-4 border-solid border-white duration-200 flex justify-between items-center p-4"
|
||||
:class="{ 'border-4 border-solid border-blue!': state.targetWalletTypeId == v.walletTypeId }"
|
||||
@click="state.targetWalletTypeId = v.walletTypeId"
|
||||
:class="{ 'border-4 border-solid border-blue!': targetWalletType.id == v.walletTypeId }"
|
||||
@click="selectTargetWalletType(v)"
|
||||
>
|
||||
<view class="flex items-center">
|
||||
<image class="w-70 h-70 mr-2" :src="filePath(v.walletTypeIcon)" />
|
||||
@@ -63,12 +61,6 @@
|
||||
<view class="main-text-32">余额:{{ hooks.useMoney(v.balance) + "元" }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template #footer>
|
||||
<view class="font-bold px-5">
|
||||
<tm-button block @click="confirmTargetWallet">确 定</tm-button>
|
||||
</view>
|
||||
</template>
|
||||
</tm-drawer>
|
||||
</view>
|
||||
</template>
|
||||
@@ -81,46 +73,44 @@ import { payApi, walletApi } from "@/sheep/api"
|
||||
import { hooks, router } from "@@/index"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
import { storePrice } from "@/sheep/utils/formatMoney"
|
||||
import { useTransferMoney } from "@/sheep/stores/transferMoney"
|
||||
import { usePayStore } from "@/sheep/stores/pay"
|
||||
|
||||
const payStore = usePayStore()
|
||||
|
||||
const transferMoney = useTransferMoney()
|
||||
const amount = ref("")
|
||||
const show = ref(false)
|
||||
const state = reactive<any>({
|
||||
sourceWalletTypeId: "",
|
||||
sourceWalletTypeName: "",
|
||||
walletList: [],
|
||||
targetWalletTypeId: "",
|
||||
targetWalletTypeName: "",
|
||||
const sourceWalletType = reactive({
|
||||
id: "",
|
||||
name: "",
|
||||
})
|
||||
const targetWalletType = reactive({
|
||||
id: "",
|
||||
name: "",
|
||||
})
|
||||
const wallet = reactive<any>({
|
||||
walletList: [],
|
||||
})
|
||||
const curTargetWallet = ref()
|
||||
|
||||
onLoad(async () => {
|
||||
if (!transferMoney.sourceWalletType.walletTypeId) return uni.showToast({ title: "钱包类型id不存在", icon: "none" })
|
||||
state.sourceWalletTypeId = transferMoney.sourceWalletType.walletTypeId
|
||||
state.sourceWalletTypeName = transferMoney.sourceWalletType.walletTypeName
|
||||
uni.setNavigationBarTitle({ title: state.sourceWalletTypeName || "源钱包" })
|
||||
if (!payStore.sourceWalletData.walletTypeId) return uni.showToast({ title: "钱包类型id不存在", icon: "none" })
|
||||
sourceWalletType.id = payStore.sourceWalletData.walletTypeId
|
||||
sourceWalletType.name = payStore.sourceWalletData.walletTypeName
|
||||
uni.setNavigationBarTitle({ title: sourceWalletType.name || "源钱包" })
|
||||
|
||||
const res = await walletApi.all()
|
||||
if (res.code == 0) {
|
||||
state.walletList = res.data.records.filter((item: any) => item.walletTypeId != state.sourceWalletTypeId)
|
||||
wallet.walletList = res.data.records.filter((item: any) => item.walletTypeId != sourceWalletType.id)
|
||||
}
|
||||
if (!curTargetWallet.value) {
|
||||
curTargetWallet.value = state.walletList[0]
|
||||
state.targetWalletTypeId = state.walletList[0]?.walletTypeId
|
||||
state.targetWalletTypeName = state.walletList[0]?.walletTypeName
|
||||
if (wallet.walletList.length) {
|
||||
targetWalletType.id = wallet.walletList[0]?.walletTypeId
|
||||
targetWalletType.name = wallet.walletList[0]?.walletTypeName
|
||||
}
|
||||
})
|
||||
|
||||
// 目标钱包选择
|
||||
const targetWalletSelect = () => {
|
||||
// state.sourceWalletTypeId = ""
|
||||
show.value = true
|
||||
}
|
||||
|
||||
// 确认目标钱包
|
||||
const confirmTargetWallet = () => {
|
||||
// state.sourceWalletTypeName = state.walletList.find((item: any) => item.walletTypeId != state.sourceWalletTypeId).walletTypeName
|
||||
// 选择目标钱包
|
||||
const selectTargetWalletType = (v: any) => {
|
||||
targetWalletType.id = v.walletTypeId
|
||||
targetWalletType.name = v.walletTypeName
|
||||
show.value = false
|
||||
}
|
||||
|
||||
@@ -153,14 +143,10 @@ const confirmTransfer = async () => {
|
||||
if (!amount.value || amount.value === "0" || amount.value === "0." || parseFloat(amount.value) === 0) {
|
||||
return uni.showToast({ title: "金额不能为零", icon: "none" })
|
||||
}
|
||||
if (numAmount.value > transferMoney.sourceWalletType.balance) {
|
||||
if (numAmount.value > payStore.sourceWalletData.balance) {
|
||||
return uni.showToast({ title: "转账金额不能超过钱包余额", icon: "none" })
|
||||
}
|
||||
|
||||
// console.log("state.sourceWalletTypeId", state.sourceWalletTypeId)
|
||||
// console.log("state.targetWalletTypeId", state.targetWalletTypeId)
|
||||
// console.log("金额", numAmount.value)
|
||||
|
||||
uni.showModal({
|
||||
title: "确定转入吗?",
|
||||
success: async (res) => {
|
||||
@@ -170,28 +156,25 @@ const confirmTransfer = async () => {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 二次确认转账
|
||||
const confirmTransferAgain = async () => {
|
||||
try {
|
||||
uni.showLoading({ title: "正在转入...", mask: true })
|
||||
const res = await payApi.transferMoney({
|
||||
sourceWalletTypeId: state.sourceWalletTypeId,
|
||||
targetWalletTypeId: state.targetWalletTypeId,
|
||||
sourceWalletTypeId: sourceWalletType.id,
|
||||
targetWalletTypeId: targetWalletType.id,
|
||||
balance: numAmount.value,
|
||||
})
|
||||
if (res.code == 0) {
|
||||
uni.showToast({ title: "转账成功", icon: "success" })
|
||||
transferMoney.setSourceWalletType({})
|
||||
// router.jump("/pages/wallet/list", {}, 2)
|
||||
payStore.setSourceWalletData({})
|
||||
router.back()
|
||||
} else {
|
||||
uni.showToast({ title: res.msg, icon: "none" })
|
||||
}
|
||||
} catch (error: any) {
|
||||
uni.showToast({
|
||||
title: error.message,
|
||||
icon: "none",
|
||||
})
|
||||
uni.showToast({ title: error.message, icon: "none" })
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
|
||||
@@ -57,11 +57,10 @@ import { reactive } from "vue"
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app"
|
||||
import { isEmpty } from "radash"
|
||||
import { filePath } from "@@/utils/file"
|
||||
import { getAppInfo } from "@@/utils/getAppInfo"
|
||||
import { getAppInfo } from "@@/utils/app"
|
||||
import { hooks, router, constant } from "@@/index"
|
||||
import { userApi } from "@@/api"
|
||||
import isDevEnv from "@/sheep/utils/isDevEnv"
|
||||
// import dd from "gdt-jsapi"
|
||||
import { isDevEnv } from "@/sheep/utils/app"
|
||||
|
||||
const state = reactive<{
|
||||
wallet: any[]
|
||||
@@ -83,7 +82,6 @@ const state = reactive<{
|
||||
// { text: "跨单位就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/stride-list" },
|
||||
{ text: "人脸管理", icon: "/static/icon/service_5.png", router: "/pages/human-face/list" },
|
||||
{ text: "清除缓存", icon: "/static/icon/clear-storage.png", router: "" },
|
||||
// { text: "意见反馈", icon: "/static/icon/service_5.png", router: "/pages/integrated/feedback/index" },
|
||||
],
|
||||
appInfo: "",
|
||||
})
|
||||
@@ -366,7 +364,7 @@ const scanCode = {
|
||||
},
|
||||
}
|
||||
|
||||
const onTabLogin = () => (isDevEnv() ? router.jump("/pages/test/login") : login.checkAppInfo())
|
||||
const onTabLogin = () => (isDevEnv() ? router.jump("/pages/user/login") : login.checkAppInfo())
|
||||
|
||||
const onTabMenu = async (item: any, index: number) => {
|
||||
const isLogin = await hooks.useCheckLogin()
|
||||
@@ -400,13 +398,18 @@ const initMenuConfig = () => {
|
||||
state.menuList.push({
|
||||
text: "测试-登录",
|
||||
icon: "/static/icon/login.png",
|
||||
router: "/pages/test/login",
|
||||
router: "/pages/user/login",
|
||||
})
|
||||
state.menuList.push({
|
||||
text: "测试-角色选择",
|
||||
icon: "/static/icon/login.png",
|
||||
router: "/pages/user/userRole",
|
||||
})
|
||||
state.menuList.push({
|
||||
text: "测试-意见反馈",
|
||||
icon: "/static/icon/service_5.png",
|
||||
router: "/pages/integrated/feedback",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { orderApi } from "@@/api"
|
||||
import { filePath } from "@@/utils/file"
|
||||
|
||||
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
|
||||
import getLaunchParam from "@/sheep/utils/getLaunchParam"
|
||||
import { getLaunchParam } from "@/sheep/utils/app"
|
||||
|
||||
const data = {
|
||||
tabs: [
|
||||
|
||||
@@ -23,7 +23,7 @@ onLoad(() => {
|
||||
app._initTabbar()
|
||||
})
|
||||
onShow(() => {
|
||||
// pageRef.value && pageRef.value.reload(false)
|
||||
pageRef.value && pageRef.value.reload(false)
|
||||
})
|
||||
|
||||
const toDetail = async (v: any) => {
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<view class="flex-1 flex-col m-l-20rpx">
|
||||
<view class="sub-text-34">
|
||||
<text class="mr-2">{{ v.name }}</text>
|
||||
<!-- <tm-tag v-if="v.supType == '10' && Number(v.mchCount) > 0" size="xs" skin="thin">共{{ v.mchCount }}家</tm-tag> -->
|
||||
</view>
|
||||
<view class="m-t-10rpx">
|
||||
<view class="flex justify-between items-center">
|
||||
|
||||
File renamed without changes.
@@ -54,7 +54,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
import { userApi } from "@/sheep/api"
|
||||
import getLaunchParam from "@/sheep/utils/getLaunchParam"
|
||||
import { getLaunchParam } from "@/sheep/utils/app"
|
||||
|
||||
const userRole = ref("user")
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from "vue"
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app"
|
||||
|
||||
import { hooks } from "@@/index"
|
||||
import { foodApi } from "@@/api"
|
||||
|
||||
const data = {}
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
status: 1,
|
||||
},
|
||||
})
|
||||
|
||||
onLoad(() => {})
|
||||
onShow(() => {})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<crud-layout title="订单详情" bg="/static/page/blue-bg.png"> </crud-layout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -85,5 +85,3 @@ const doTab = (e: any) => {
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -7,7 +7,7 @@ import { hooks, router } from "@@/index"
|
||||
import { walletApi } from "@@/api"
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
import { useTransferMoney } from "@/sheep/stores/transferMoney"
|
||||
import { usePayStore } from "@/sheep/stores/pay"
|
||||
|
||||
const state = reactive<any>({
|
||||
showBindDialog: false,
|
||||
@@ -129,7 +129,7 @@ const doFreeze = async () => {
|
||||
// 转账
|
||||
const doTransferMoney = (v: any) => {
|
||||
if (v.walletTypeId) {
|
||||
useTransferMoney().setSourceWalletType(v)
|
||||
usePayStore().setSourceWalletData(v)
|
||||
router.jump("/pages/pay/transferMoney")
|
||||
return
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -7,10 +7,10 @@ const showVerifyDeviceImpModel = (onClose: () => any = () => null) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (VerifyDeviceImpModelInstance) return
|
||||
|
||||
const close = () => {
|
||||
const close = async () => {
|
||||
render(null, document.body)
|
||||
VerifyDeviceImpModelInstance = false
|
||||
onClose()
|
||||
await onClose()
|
||||
}
|
||||
|
||||
const vnode = h(VerifyDeviceImpModel, {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export default {
|
||||
logo: "/static/constant/logo.png"
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
export { default as imgConstant } from "./img-constant";
|
||||
export { default as serviceEnum } from "./service-enum"
|
||||
|
||||
export { default as serviceEnum } from "./service-enum";
|
||||
|
||||
export { default as storageConstant } from "./storage-constant";
|
||||
export { default as storageConstant } from "./storage-constant"
|
||||
@@ -1,6 +1,6 @@
|
||||
import storageConstant from "../constant/storage-constant"
|
||||
import { jump } from "../router/index"
|
||||
import isDevEnv from "../utils/isDevEnv"
|
||||
import { isDevEnv } from "../utils/app"
|
||||
|
||||
export const useToken = () => {
|
||||
const tokenKey = storageConstant.TOKEN
|
||||
@@ -41,7 +41,7 @@ export const useCheckLogin = async (): Promise<boolean> => {
|
||||
confirmText: "去登录",
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
jump("/pages/test/login", {}, 3)
|
||||
jump("/pages/user/login", {}, 3)
|
||||
return
|
||||
}
|
||||
if (!res.confirm) {
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
// https://pinia.vuejs.org/
|
||||
import { createPinia } from "pinia"
|
||||
|
||||
// 创建
|
||||
const pinia = createPinia()
|
||||
|
||||
// 导出
|
||||
export default pinia
|
||||
@@ -1,14 +1,20 @@
|
||||
import { defineStore } from "pinia"
|
||||
|
||||
export const usePayStore = defineStore("pay", {
|
||||
state: (): { payData: { id?: string; name?: string; customPrice?: number } } => {
|
||||
state: (): { payData: { id?: string; name?: string; customPrice?: number }; sourceWalletData: any } => {
|
||||
return {
|
||||
payData: {},
|
||||
sourceWalletData: {},
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
// 支付
|
||||
setPayData(data: any) {
|
||||
this.payData = data
|
||||
},
|
||||
// 转账
|
||||
setSourceWalletData(data: any) {
|
||||
this.sourceWalletData = data
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -1,14 +0,0 @@
|
||||
import { defineStore } from "pinia"
|
||||
|
||||
export const useTransferMoney = defineStore("transferMoney", {
|
||||
state: (): any => {
|
||||
return {
|
||||
sourceWalletType: {},
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setSourceWalletType(data: any) {
|
||||
this.sourceWalletType = data
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,26 @@
|
||||
// app运行环境
|
||||
// export default () => import.meta.env.VITE_DEV_ENV === "dev"
|
||||
export const isDevEnv = (): boolean => process.env.NODE_ENV === "development"
|
||||
|
||||
// 获取启动参数
|
||||
export const getLaunchParam = (): "canteen" | "selfMerchant" | "coopMerchant" | "thirdApp" | null => {
|
||||
return new URL(window.location.href).searchParams.get("launchParam") as "canteen" | "selfMerchant" | "coopMerchant" | "thirdApp" | null
|
||||
}
|
||||
|
||||
// 检测app信息判断运行环境
|
||||
export const getAppInfo = async (): Promise<string> => {
|
||||
try {
|
||||
const res = await (window as any).CP2.getAppInfo()
|
||||
// 浙政钉环境
|
||||
if (res.code === 0) {
|
||||
console.log("环境:zzd")
|
||||
return "zzd"
|
||||
} else {
|
||||
// 诗画环境
|
||||
console.log("环境:sh")
|
||||
return "sh"
|
||||
}
|
||||
} catch (error) {
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import isDevEnv from "./isDevEnv"
|
||||
import { isDevEnv } from "./app"
|
||||
|
||||
export const filePath = (path?: string) => {
|
||||
const imageBaseUrl = isDevEnv() ? import.meta.env.VITE_IMAGE_DEV_PATH : import.meta.env.VITE_APP_PROD_IMAGE
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
// 检测app信息判断运行环境
|
||||
export const getAppInfo = async (): Promise<string> => {
|
||||
try {
|
||||
const res = await (window as any).CP2.getAppInfo()
|
||||
// 浙政钉环境
|
||||
if (res.code === 0) {
|
||||
console.log("环境:zzd")
|
||||
return "zzd"
|
||||
} else {
|
||||
// 诗画环境
|
||||
console.log("环境:sh")
|
||||
return "sh"
|
||||
}
|
||||
} catch (error) {
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
// 获取启动参数
|
||||
const getLaunchParam = (): "canteen" | "selfMerchant" | "coopMerchant" | "thirdApp" | null => {
|
||||
return new URL(window.location.href).searchParams.get("launchParam") as "canteen" | "selfMerchant" | "coopMerchant" | "thirdApp" | null
|
||||
}
|
||||
|
||||
export default getLaunchParam
|
||||
@@ -1,2 +0,0 @@
|
||||
// export default () => import.meta.env.VITE_DEV_ENV === "dev"
|
||||
export default () => process.env.NODE_ENV === "development"
|
||||
+114
-45
@@ -2,12 +2,33 @@ import Request from "luch-request"
|
||||
import { router, constant } from "@@/index"
|
||||
import { userApi } from "../api"
|
||||
import { isEmpty } from "radash"
|
||||
import isDevEnv from "./isDevEnv"
|
||||
import { getAppInfo } from "@@/utils/getAppInfo"
|
||||
import { isDevEnv } from "./app"
|
||||
import { getAppInfo } from "@@/utils/app"
|
||||
import showVerifyDeviceImpModel from "../components/verifyDeviceImpModel/verifyDeviceImpModel"
|
||||
|
||||
const TOKEN_KEY = constant.storageConstant.TOKEN
|
||||
const USER_INFO_KEY = constant.storageConstant.USERINFO
|
||||
const SKIP_AUTH_URLS = ["/thirdparty/thirdPartyOAth2", "/sys/auth/refresh-token", "/auth/oauth2/token"]
|
||||
|
||||
let isRefreshing = false
|
||||
// 队列存储发送失败的请求
|
||||
let failedQueue: any[] = []
|
||||
// 存储刷新token的Promise
|
||||
let refreshTokenPromise: Promise<any> | null = null
|
||||
|
||||
// 处理队列中的请求
|
||||
const processQueue = (error: any, token: any = null) => {
|
||||
failedQueue.forEach((prom) => {
|
||||
if (error) {
|
||||
prom.reject(error)
|
||||
} else {
|
||||
prom.resolve(token)
|
||||
}
|
||||
})
|
||||
if (!error) {
|
||||
failedQueue = []
|
||||
}
|
||||
}
|
||||
|
||||
// 读取token并处理Authorization请求头
|
||||
const getAuthHeader = (tokenStorage: any) => {
|
||||
@@ -20,7 +41,7 @@ const getAuthHeader = (tokenStorage: any) => {
|
||||
// 浙政钉登录 登录成功返回true,否则返回false
|
||||
async function handleZzdLogin(): Promise<boolean> {
|
||||
try {
|
||||
uni.showLoading({ title: "加载中...", mask: true })
|
||||
uni.showLoading({ title: "登录中...", mask: true })
|
||||
const token = new URL(window.location.href).searchParams.get("uabaseToken")
|
||||
|
||||
if (!token) {
|
||||
@@ -57,15 +78,15 @@ async function handleShLogin(): Promise<boolean> {
|
||||
try {
|
||||
uni.showLoading({ title: "登录中...", mask: true })
|
||||
|
||||
// const userInfo = await (window as any).CP2.getUserInfo()
|
||||
// if (userInfo.code == 0 || !userInfo.data.accountId || !userInfo.data.sessionId) {
|
||||
// uni.showToast({ title: "获取诗画用户信息失败", icon: "none" })
|
||||
// return false
|
||||
// }
|
||||
const userInfo = await (window as any).CP2.getUserInfo()
|
||||
if (userInfo.code == 0 || !userInfo.data.accountId || !userInfo.data.sessionId) {
|
||||
uni.showToast({ title: "获取诗画用户信息失败", icon: "none" })
|
||||
return false
|
||||
}
|
||||
|
||||
// const { accountId, sessionId } = userInfo.data
|
||||
// const response = await userApi.authsh({ accountId, sessionId })
|
||||
const response = await userApi.authsh({ accountId: "67e790d6a95d5a7b507e53dd", sessionId: "68215b03a95d5a4899d20cb4" }) // 测试
|
||||
const { accountId, sessionId } = userInfo.data
|
||||
const response = await userApi.authsh({ accountId, sessionId })
|
||||
// const response = await userApi.authsh({ accountId: "67e790d6a95d5a7b507e53dd", sessionId: "68215b03a95d5a4899d20cb4" }) // 测试
|
||||
|
||||
if (response.code == 0) {
|
||||
uni.setStorageSync(TOKEN_KEY, { accessToken: response.data.accessToken })
|
||||
@@ -81,13 +102,9 @@ async function handleShLogin(): Promise<boolean> {
|
||||
return false
|
||||
}
|
||||
|
||||
// 如果是设备未验证,保存响应数据
|
||||
if (response.data == -1) {
|
||||
uni.showToast({ title: "您的设备需要信任验证", icon: "none" })
|
||||
await showVerifyDeviceImpModel(async () => {
|
||||
await autoLogin()
|
||||
uni.reLaunch({ url: window.location.href.split("#")[1] })
|
||||
})
|
||||
return false
|
||||
uni.setStorageSync(TOKEN_KEY, { data: -1 })
|
||||
}
|
||||
|
||||
uni.showToast({ title: response.msg || "登录失败", icon: "none" })
|
||||
@@ -118,6 +135,56 @@ async function autoLogin(): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
// token刷新
|
||||
async function refreshToken(): Promise<any> {
|
||||
if (refreshTokenPromise) {
|
||||
return refreshTokenPromise
|
||||
}
|
||||
|
||||
if (!isRefreshing) {
|
||||
isRefreshing = true
|
||||
refreshTokenPromise = (async () => {
|
||||
try {
|
||||
const loginResult = await autoLogin()
|
||||
if (loginResult) {
|
||||
const newTokenStorage = uni.getStorageSync(TOKEN_KEY)
|
||||
processQueue(null, newTokenStorage)
|
||||
return newTokenStorage
|
||||
} else {
|
||||
// 检查是否需要设备验证
|
||||
const tokenStorage = uni.getStorageSync(TOKEN_KEY)
|
||||
if (tokenStorage?.data == -1) {
|
||||
// 显示设备验证弹窗
|
||||
await showVerifyDeviceImpModel(async () => {
|
||||
// 验证完成后重新登录
|
||||
const newLoginResult = await autoLogin()
|
||||
if (newLoginResult) {
|
||||
const newTokenStorage = uni.getStorageSync(TOKEN_KEY)
|
||||
processQueue(null, newTokenStorage)
|
||||
return newTokenStorage
|
||||
} else {
|
||||
processQueue(new Error("登录失败"), null)
|
||||
throw new Error("登录失败")
|
||||
}
|
||||
})
|
||||
} else {
|
||||
processQueue(new Error("登录失败"), null)
|
||||
throw new Error("登录失败")
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
processQueue(error, null)
|
||||
throw error
|
||||
} finally {
|
||||
isRefreshing = false
|
||||
refreshTokenPromise = null
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
return refreshTokenPromise
|
||||
}
|
||||
|
||||
// token过期刷新检查
|
||||
async function checkAndRefreshToken(tokenStorage: any) {
|
||||
const { accessToken } = tokenStorage
|
||||
@@ -125,13 +192,9 @@ async function checkAndRefreshToken(tokenStorage: any) {
|
||||
|
||||
const expiresDate = new Date(accessToken.expiresAt).getTime()
|
||||
|
||||
// console.log("过期时间", expiresDate)
|
||||
// console.log("现在时间", new Date().getTime())
|
||||
// console.log("现在时间大于过期时间吗", new Date().getTime() >= expiresDate)
|
||||
|
||||
// token已过期,尝试刷新
|
||||
if (new Date().getTime() >= expiresDate) {
|
||||
await autoLogin()
|
||||
return await refreshToken()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,8 +220,6 @@ const http = new Request({
|
||||
|
||||
// 请求拦截器
|
||||
http.interceptors.request.use(async (config) => {
|
||||
// console.log("config", config)
|
||||
|
||||
const tokenStorage = uni.getStorageSync(TOKEN_KEY)
|
||||
const config_header: any = config.header || {}
|
||||
|
||||
@@ -166,25 +227,25 @@ http.interceptors.request.use(async (config) => {
|
||||
config_header["TENANT-ID"] = "1"
|
||||
if (import.meta.env.VITE_IS_TOC === "true") config_header["CLIENT-TOC"] = "Y"
|
||||
|
||||
// 不需要设置认证头的接口路径
|
||||
const skipAuthUrls = ["/thirdparty/thirdPartyOAth2", "/sys/auth/refresh-token", "/auth/oauth2/token"]
|
||||
|
||||
// 判断是否需要设置认证头
|
||||
if (!skipAuthUrls.some((url) => config.url?.startsWith(url))) {
|
||||
if (!SKIP_AUTH_URLS.some((url) => config.url?.startsWith(url))) {
|
||||
if (!isEmpty(tokenStorage)) {
|
||||
// token存在,token过期刷新检查
|
||||
await checkAndRefreshToken(tokenStorage)
|
||||
|
||||
const authHeader = getAuthHeader(tokenStorage)
|
||||
if (authHeader) config_header.Authorization = authHeader
|
||||
const newTokenStorage = await checkAndRefreshToken(tokenStorage)
|
||||
if (newTokenStorage) {
|
||||
const authHeader = getAuthHeader(newTokenStorage)
|
||||
if (authHeader) config_header.Authorization = authHeader
|
||||
} else {
|
||||
const authHeader = getAuthHeader(tokenStorage)
|
||||
if (authHeader) config_header.Authorization = authHeader
|
||||
}
|
||||
} else {
|
||||
// token不存在,则发起登录
|
||||
await autoLogin()
|
||||
|
||||
// 登录后重新获取token
|
||||
const newTokenStorage = uni.getStorageSync(TOKEN_KEY)
|
||||
const authHeader = getAuthHeader(newTokenStorage)
|
||||
if (authHeader) config_header.Authorization = authHeader
|
||||
// token不存在,刷新token
|
||||
const newTokenStorage = await refreshToken()
|
||||
if (newTokenStorage) {
|
||||
const authHeader = getAuthHeader(newTokenStorage)
|
||||
if (authHeader) config_header.Authorization = authHeader
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,8 +255,6 @@ http.interceptors.request.use(async (config) => {
|
||||
// 响应拦截器
|
||||
http.interceptors.response.use(
|
||||
async (response) => {
|
||||
// console.log("response", response)
|
||||
|
||||
// 账号密码登录响应结果特殊处理
|
||||
if (response.config.url === "/auth/oauth2/token") {
|
||||
return Promise.resolve({
|
||||
@@ -208,8 +267,6 @@ http.interceptors.response.use(
|
||||
return Promise.resolve(response.data)
|
||||
},
|
||||
async (error) => {
|
||||
// console.log("error", error)
|
||||
|
||||
// 处理 424 错误(token过期)
|
||||
if (error.statusCode === 424) {
|
||||
if (isDevEnv()) {
|
||||
@@ -217,9 +274,21 @@ http.interceptors.response.use(
|
||||
uni.removeStorageSync(TOKEN_KEY)
|
||||
uni.removeStorageSync(USER_INFO_KEY)
|
||||
uni.showToast({ title: "登录已过期,请重新登录", icon: "none" })
|
||||
router.jump("/pages/test/login")
|
||||
router.jump("/pages/user/login")
|
||||
} else {
|
||||
await autoLogin()
|
||||
try {
|
||||
const newTokenStorage = await refreshToken()
|
||||
if (newTokenStorage) {
|
||||
// 重新发起失败的请求
|
||||
const config = error.config
|
||||
const authHeader = getAuthHeader(newTokenStorage)
|
||||
if (authHeader && config.header) config.header.Authorization = authHeader
|
||||
return http.request(config)
|
||||
}
|
||||
} catch (err) {
|
||||
// 错误已在refreshToken中处理
|
||||
return Promise.reject(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user