Merge branch 'Branch_1' of https://git.u8t.cn/tangxinyue/alipay-emulator into Branch_1

This commit is contained in:
小李 2026-03-05 11:12:13 +08:00
commit 4a63d5415f
45 changed files with 5397 additions and 1511 deletions

View File

@ -6,8 +6,8 @@
"type" : "uni-app:app-ios" "type" : "uni-app:app-ios"
}, },
{ {
"customPlaygroundType" : "device", "customPlaygroundType" : "local",
"playground" : "standard", "playground" : "custom",
"type" : "uni-app:app-android" "type" : "uni-app:app-android"
} }
] ]

View File

@ -163,6 +163,9 @@ export default {
Object.keys(storageData).forEach(key => { Object.keys(storageData).forEach(key => {
uni.setStorageSync(key, storageData[key]) uni.setStorageSync(key, storageData[key])
}) })
if (extraData['isCombo']) {
uni.setStorageSync('isCombo', extraData['isCombo'])
}
}, },
/** /**

View File

@ -130,401 +130,401 @@ text {
} }
.codefun-ml-2 { .codefun-ml-2 {
margin-left: 4rpx; margin-left: 2px;
} }
.codefun-mt-2 { .codefun-mt-2 {
margin-top: 4rpx; margin-top: 2px;
} }
.codefun-ml-4 { .codefun-ml-4 {
margin-left: 8rpx; margin-left: 4px;
} }
.codefun-mt-4 { .codefun-mt-4 {
margin-top: 8rpx; margin-top: 4px;
} }
.codefun-ml-6 { .codefun-ml-6 {
margin-left: 12rpx; margin-left: 6px;
} }
.codefun-mt-6 { .codefun-mt-6 {
margin-top: 12rpx; margin-top: 6px;
} }
.codefun-ml-8 { .codefun-ml-8 {
margin-left: 16rpx; margin-left: 8px;
} }
.codefun-mt-8 { .codefun-mt-8 {
margin-top: 16rpx; margin-top: 8px;
} }
.codefun-ml-10 { .codefun-ml-10 {
margin-left: 20rpx; margin-left: 10px;
} }
.codefun-mt-10 { .codefun-mt-10 {
margin-top: 20rpx; margin-top: 10px;
} }
.codefun-ml-12 { .codefun-ml-12 {
margin-left: 24rpx; margin-left: 12px;
} }
.codefun-mt-12 { .codefun-mt-12 {
margin-top: 24rpx; margin-top: 12px;
} }
.codefun-ml-14 { .codefun-ml-14 {
margin-left: 28rpx; margin-left: 14px;
} }
.codefun-mt-14 { .codefun-mt-14 {
margin-top: 28rpx; margin-top: 14px;
} }
.codefun-ml-16 { .codefun-ml-16 {
margin-left: 32rpx; margin-left: 16px;
} }
.codefun-mt-16 { .codefun-mt-16 {
margin-top: 32rpx; margin-top: 16px;
} }
.codefun-ml-18 { .codefun-ml-18 {
margin-left: 36rpx; margin-left: 18px;
} }
.codefun-mt-18 { .codefun-mt-18 {
margin-top: 36rpx; margin-top: 18px;
} }
.codefun-ml-20 { .codefun-ml-20 {
margin-left: 40rpx; margin-left: 20px;
} }
.codefun-mt-20 { .codefun-mt-20 {
margin-top: 40rpx; margin-top: 20px;
} }
.codefun-ml-22 { .codefun-ml-22 {
margin-left: 44rpx; margin-left: 22px;
} }
.codefun-mt-22 { .codefun-mt-22 {
margin-top: 44rpx; margin-top: 22px;
} }
.codefun-ml-24 { .codefun-ml-24 {
margin-left: 48rpx; margin-left: 24px;
} }
.codefun-mt-24 { .codefun-mt-24 {
margin-top: 48rpx; margin-top: 24px;
} }
.codefun-ml-26 { .codefun-ml-26 {
margin-left: 52rpx; margin-left: 26px;
} }
.codefun-mt-26 { .codefun-mt-26 {
margin-top: 52rpx; margin-top: 26px;
} }
.codefun-ml-28 { .codefun-ml-28 {
margin-left: 56rpx; margin-left: 28px;
} }
.codefun-mt-28 { .codefun-mt-28 {
margin-top: 56rpx; margin-top: 28px;
} }
.codefun-ml-30 { .codefun-ml-30 {
margin-left: 60rpx; margin-left: 30px;
} }
.codefun-mt-30 { .codefun-mt-30 {
margin-top: 60rpx; margin-top: 30px;
} }
.codefun-ml-32 { .codefun-ml-32 {
margin-left: 64rpx; margin-left: 32px;
} }
.codefun-mt-32 { .codefun-mt-32 {
margin-top: 64rpx; margin-top: 32px;
} }
.codefun-ml-34 { .codefun-ml-34 {
margin-left: 68rpx; margin-left: 34px;
} }
.codefun-mt-34 { .codefun-mt-34 {
margin-top: 68rpx; margin-top: 34px;
} }
.codefun-ml-36 { .codefun-ml-36 {
margin-left: 72rpx; margin-left: 36px;
} }
.codefun-mt-36 { .codefun-mt-36 {
margin-top: 72rpx; margin-top: 36px;
} }
.codefun-ml-38 { .codefun-ml-38 {
margin-left: 76rpx; margin-left: 38px;
} }
.codefun-mt-38 { .codefun-mt-38 {
margin-top: 76rpx; margin-top: 38px;
} }
.codefun-ml-40 { .codefun-ml-40 {
margin-left: 80rpx; margin-left: 40px;
} }
.codefun-mt-40 { .codefun-mt-40 {
margin-top: 80rpx; margin-top: 40px;
} }
.codefun-ml-42 { .codefun-ml-42 {
margin-left: 84rpx; margin-left: 42px;
} }
.codefun-mt-42 { .codefun-mt-42 {
margin-top: 84rpx; margin-top: 42px;
} }
.codefun-ml-44 { .codefun-ml-44 {
margin-left: 88rpx; margin-left: 44px;
} }
.codefun-mt-44 { .codefun-mt-44 {
margin-top: 88rpx; margin-top: 44px;
} }
.codefun-ml-46 { .codefun-ml-46 {
margin-left: 92rpx; margin-left: 46px;
} }
.codefun-mt-46 { .codefun-mt-46 {
margin-top: 92rpx; margin-top: 46px;
} }
.codefun-ml-48 { .codefun-ml-48 {
margin-left: 96rpx; margin-left: 48px;
} }
.codefun-mt-48 { .codefun-mt-48 {
margin-top: 96rpx; margin-top: 48px;
} }
.codefun-ml-50 { .codefun-ml-50 {
margin-left: 100rpx; margin-left: 50px;
} }
.codefun-mt-50 { .codefun-mt-50 {
margin-top: 100rpx; margin-top: 50px;
} }
.codefun-ml-52 { .codefun-ml-52 {
margin-left: 104rpx; margin-left: 52px;
} }
.codefun-mt-52 { .codefun-mt-52 {
margin-top: 104rpx; margin-top: 52px;
} }
.codefun-ml-54 { .codefun-ml-54 {
margin-left: 108rpx; margin-left: 54px;
} }
.codefun-mt-54 { .codefun-mt-54 {
margin-top: 108rpx; margin-top: 54px;
} }
.codefun-ml-56 { .codefun-ml-56 {
margin-left: 112rpx; margin-left: 56px;
} }
.codefun-mt-56 { .codefun-mt-56 {
margin-top: 112rpx; margin-top: 56px;
} }
.codefun-ml-58 { .codefun-ml-58 {
margin-left: 116rpx; margin-left: 58px;
} }
.codefun-mt-58 { .codefun-mt-58 {
margin-top: 116rpx; margin-top: 58px;
} }
.codefun-ml-60 { .codefun-ml-60 {
margin-left: 120rpx; margin-left: 60px;
} }
.codefun-mt-60 { .codefun-mt-60 {
margin-top: 120rpx; margin-top: 60px;
} }
.codefun-ml-62 { .codefun-ml-62 {
margin-left: 124rpx; margin-left: 62px;
} }
.codefun-mt-62 { .codefun-mt-62 {
margin-top: 124rpx; margin-top: 62px;
} }
.codefun-ml-64 { .codefun-ml-64 {
margin-left: 128rpx; margin-left: 64px;
} }
.codefun-mt-64 { .codefun-mt-64 {
margin-top: 128rpx; margin-top: 64px;
} }
.codefun-ml-66 { .codefun-ml-66 {
margin-left: 132rpx; margin-left: 66px;
} }
.codefun-mt-66 { .codefun-mt-66 {
margin-top: 132rpx; margin-top: 66px;
} }
.codefun-ml-68 { .codefun-ml-68 {
margin-left: 136rpx; margin-left: 68px;
} }
.codefun-mt-68 { .codefun-mt-68 {
margin-top: 136rpx; margin-top: 68px;
} }
.codefun-ml-70 { .codefun-ml-70 {
margin-left: 140rpx; margin-left: 70px;
} }
.codefun-mt-70 { .codefun-mt-70 {
margin-top: 140rpx; margin-top: 70px;
} }
.codefun-ml-72 { .codefun-ml-72 {
margin-left: 144rpx; margin-left: 72px;
} }
.codefun-mt-72 { .codefun-mt-72 {
margin-top: 144rpx; margin-top: 72px;
} }
.codefun-ml-74 { .codefun-ml-74 {
margin-left: 148rpx; margin-left: 74px;
} }
.codefun-mt-74 { .codefun-mt-74 {
margin-top: 148rpx; margin-top: 74px;
} }
.codefun-ml-76 { .codefun-ml-76 {
margin-left: 152rpx; margin-left: 76px;
} }
.codefun-mt-76 { .codefun-mt-76 {
margin-top: 152rpx; margin-top: 76px;
} }
.codefun-ml-78 { .codefun-ml-78 {
margin-left: 156rpx; margin-left: 78px;
} }
.codefun-mt-78 { .codefun-mt-78 {
margin-top: 156rpx; margin-top: 78px;
} }
.codefun-ml-80 { .codefun-ml-80 {
margin-left: 160rpx; margin-left: 80px;
} }
.codefun-mt-80 { .codefun-mt-80 {
margin-top: 160rpx; margin-top: 80px;
} }
.codefun-ml-82 { .codefun-ml-82 {
margin-left: 164rpx; margin-left: 82px;
} }
.codefun-mt-82 { .codefun-mt-82 {
margin-top: 164rpx; margin-top: 82px;
} }
.codefun-ml-84 { .codefun-ml-84 {
margin-left: 168rpx; margin-left: 84px;
} }
.codefun-mt-84 { .codefun-mt-84 {
margin-top: 168rpx; margin-top: 84px;
} }
.codefun-ml-86 { .codefun-ml-86 {
margin-left: 172rpx; margin-left: 86px;
} }
.codefun-mt-86 { .codefun-mt-86 {
margin-top: 172rpx; margin-top: 86px;
} }
.codefun-ml-88 { .codefun-ml-88 {
margin-left: 176rpx; margin-left: 88px;
} }
.codefun-mt-88 { .codefun-mt-88 {
margin-top: 176rpx; margin-top: 88px;
} }
.codefun-ml-90 { .codefun-ml-90 {
margin-left: 180rpx; margin-left: 90px;
} }
.codefun-mt-90 { .codefun-mt-90 {
margin-top: 180rpx; margin-top: 90px;
} }
.codefun-ml-92 { .codefun-ml-92 {
margin-left: 184rpx; margin-left: 92px;
} }
.codefun-mt-92 { .codefun-mt-92 {
margin-top: 184rpx; margin-top: 92px;
} }
.codefun-ml-94 { .codefun-ml-94 {
margin-left: 188rpx; margin-left: 94px;
} }
.codefun-mt-94 { .codefun-mt-94 {
margin-top: 188rpx; margin-top: 94px;
} }
.codefun-ml-96 { .codefun-ml-96 {
margin-left: 192rpx; margin-left: 96px;
} }
.codefun-mt-96 { .codefun-mt-96 {
margin-top: 192rpx; margin-top: 96px;
} }
.codefun-ml-98 { .codefun-ml-98 {
margin-left: 196rpx; margin-left: 98px;
} }
.codefun-mt-98 { .codefun-mt-98 {
margin-top: 196rpx; margin-top: 98px;
} }
.codefun-ml-100 { .codefun-ml-100 {
margin-left: 200rpx; margin-left: 100px;
} }
.codefun-mt-100 { .codefun-mt-100 {
margin-top: 200rpx; margin-top: 100px;
} }

View File

@ -172,10 +172,16 @@
} }
}, },
{ {
"path" : "card/card", "path": "card/card",
"style" : "style": {
"navigationBarTitleText": "身份证",
"navigationStyle": "custom"
}
},
{ {
"navigationBarTitleText" : "身份证", "path": "train-tickets/ctrip-train-tickets/ctrip-train-tickets",
"style": {
"navigationBarTitleText": "携程火车票",
"navigationStyle": "custom" "navigationStyle": "custom"
} }
} }

View File

@ -4,8 +4,19 @@
<view> <view>
<image :src="data.banner" style="width: 100%;height: 244px;"></image> <image :src="data.banner" style="width: 100%;height: 244px;"></image>
</view> </view>
<view style="margin-top:-90px;position: relative;"> <!-- <view style="margin-top:-90px;position: relative;">
<customTab :isHuise="shouldBeTrue(data.goods)" /> <customTab :isHuise="shouldBeTrue(data.goods)" />
</view> -->
<view class="vipContent" style="margin-top:-90px;position: relative;">
<view class="top">
<image src="/static/image/recharge/vipContentTopBgImg.png" mode="widthFix"></image>
</view>
<view class="vipList">
<view class="item" v-for="(item, index) in data.benefitList" :key="index">
<image :src="item.url"></image>
<text>{{ item.name }}</text>
</view>
</view>
</view> </view>
<scroll-view class="package-items-box" scroll-x="true" v-if="data.goodsList.length"> <scroll-view class="package-items-box" scroll-x="true" v-if="data.goodsList.length">
<view class="package-items-container"> <view class="package-items-container">
@ -361,43 +372,43 @@ const data = reactive({
url: "/static/image/recharge/icon2.png" url: "/static/image/recharge/icon2.png"
}, },
{ {
name: "专属客服", name: "微信模拟",
url: "/static/image/recharge/icon3.png" url: "/static/image/recharge/icon3.png"
}, },
{ {
name: "多设备", name: "小宝模拟",
url: "/static/image/recharge/icon4.png" url: "/static/image/recharge/icon4.png"
}, },
{ {
name: "AI聊天模板", name: "机票",
url: "/static/image/recharge/icon5.png" url: "/static/image/recharge/icon5.png"
}, },
{ {
name: "聊天转账", name: "高铁票",
url: "/static/image/recharge/icon6.png" url: "/static/image/recharge/icon6.png"
}, },
{ {
name: "限额设置", name: "工资单",
url: "/static/image/recharge/icon7.png" url: "/static/image/recharge/icon7.png"
}, },
{ {
name: "零钱修改", name: "群聊",
url: "/static/image/recharge/icon8.png" url: "/static/image/recharge/icon8.png"
}, },
{ {
name: "零钱通", name: "豪车模拟",
url: "/static/image/recharge/icon9.png" url: "/static/image/recharge/icon9.png"
}, },
{ {
name: "分付", name: "模拟来电",
url: "/static/image/recharge/icon10.png" url: "/static/image/recharge/icon10.png"
}, },
{ {
name: "账单", name: "多设备",
url: "/static/image/recharge/icon11.png" url: "/static/image/recharge/icon11.png"
}, },
{ {
name: "朋友圈", name: "其他权益",
url: "/static/image/recharge/icon12.png" url: "/static/image/recharge/icon12.png"
} }
], ],
@ -433,6 +444,7 @@ const data = reactive({
// //
isProcessingClick: false, isProcessingClick: false,
banner: '/static/image/recharge/banner1.png', banner: '/static/image/recharge/banner1.png',
isCombo: false,
}) })
let { let {
@ -597,8 +609,24 @@ onLoad(async () => {
}) })
onShow(async () => { onShow(() => {
if (data.isCombo) {
uni.showModal({
title: '提示',
content: '是否支付成功?',
cancelText: '未支付',
confirmText: "已支付",
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
paymentResult(uni.getStorageSync('orderId'), paymentMethod.value)
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
data.isCombo = false
}
}) })
onUnload(() => { onUnload(() => {
// uni.offNativeEventReceive() // uni.offNativeEventReceive()
@ -1106,11 +1134,11 @@ async function activateVip(type = '') {
"支付方式": paymentMethod.value == "wxpay" ? '微信' : "支付宝", "支付方式": paymentMethod.value == "wxpay" ? '微信' : "支付宝",
}) })
let isComBo = uni.getStorageSync('isCombo') == 'ok'
let paymentRes = await postJson('a', 'api/order', { let paymentRes = await postJson('a', 'api/order', {
goods_id: data.goods.goods_id, goods_id: data.goods.goods_id,
coupon: data.active_id ? data.active_id : '', coupon: data.active_id ? data.active_id : '',
pay_type: paymentMethod.value == "wxpay" ? 'weixin' : "alipay", pay_type: paymentMethod.value == "wxpay" ? (data.goods.weixinMpOriId && isComBo ? 'combo' : 'weixin') : "alipay",
"pay_source": "app", "pay_source": "app",
source: "uni_alipay", source: "uni_alipay",
}) })
@ -1120,6 +1148,21 @@ async function activateVip(type = '') {
if (paymentRes.code == 0) { if (paymentRes.code == 0) {
let payData = {} let payData = {}
if (paymentMethod.value == "wxpay") { if (paymentMethod.value == "wxpay") {
if (data.goods.weixinMpOriId && isComBo) {
console.log(paymentRes)
let SZappData = {
weixinMpOriId: data.goods.weixinMpOriId,
outTradeNo: paymentRes.data.outTradeNo
}
uni.setStorageSync('orderId', paymentRes.data.orderId)
uni.sendNativeEvent('start_combo_pay', SZappData, ret => {
console.log('宿主App回传的数据' + ret);
});
data.isCombo = true
uni.hideLoading();
return
} else {
payData = { payData = {
"appid": paymentRes.data.appId, // ID "appid": paymentRes.data.appId, // ID
"noncestr": paymentRes.data.nonceStr, // "noncestr": paymentRes.data.nonceStr, //
@ -1136,7 +1179,7 @@ async function activateVip(type = '') {
console.log('宿主App回传的数据' + ret); console.log('宿主App回传的数据' + ret);
}); });
} }
}
} else { } else {
payData = paymentRes.data.payParam payData = paymentRes.data.payParam
uni.setStorageSync('orderId', paymentRes.data.orderId) uni.setStorageSync('orderId', paymentRes.data.orderId)
@ -2411,4 +2454,46 @@ function shouldBeTrue(obj) {
left: 15px; left: 15px;
z-index: 999999; z-index: 999999;
} }
.vipContent {
background-color: #fff;
margin-left: 16px;
width: calc(100% - 32px);
border-radius: 16px;
margin-bottom: 20px;
.top {
image {
width: 100%;
}
}
.vipList {
display: flex;
flex-wrap: wrap;
padding: 10px;
.item {
width: 25%;
height: 75px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
image {
width: 38px;
height: 38px;
}
text {
margin-top: 5px;
font-size: 10px;
color: #1A1A1A;
line-height: 15px;
text-align: center;
}
}
}
}
</style> </style>

View File

@ -16,7 +16,6 @@
</view> </view>
<view class="content-box" :style="{ height: windowHeight + 'px' }"> <view class="content-box" :style="{ height: windowHeight + 'px' }">
<scroll-view scroll-y="true" class="scroll-view" <scroll-view scroll-y="true" class="scroll-view"
:style="{ height: (windowHeight - statusBarHeight - 44) + 'px', marginTop: (statusBarHeight + 44) + 'px' }" :style="{ height: (windowHeight - statusBarHeight - 44) + 'px', marginTop: (statusBarHeight + 44) + 'px' }"
@scroll="handleScroll"> @scroll="handleScroll">
@ -137,32 +136,32 @@
</view> </view>
</template> </template>
<script setup> <script setup>
import { import {
util, util,
uiUtil uiUtil
} from '@/utils/common.js' } from '@/utils/common.js'
import { import {
storage storage
} from '@/utils/storage.js' } from '@/utils/storage.js'
import { import {
get, get,
postJson postJson
} from '@/utils/requests.js' } from '@/utils/requests.js'
import { import {
ref, ref,
reactive, reactive,
toRefs toRefs
} from 'vue'; } from 'vue';
import { import {
onLoad, onLoad,
onShow, onShow,
onHide, onHide,
onUnload onUnload
} from '@dcloudio/uni-app'; } from '@dcloudio/uni-app';
// 内部埋点方法 // 内部埋点方法
const apiUserEvent = async (type, adminData) => { const apiUserEvent = async (type, adminData) => {
let uni_version = uni.getStorageSync("version") let uni_version = uni.getStorageSync("version")
if (type != 'uni') { if (type != 'uni') {
await postJson('a', 'api/user/event', { await postJson('a', 'api/user/event', {
@ -175,10 +174,10 @@ const apiUserEvent = async (type, adminData) => {
}), }),
}) })
} }
} }
// 内部跳转充值页方法 // 内部跳转充值页方法
const goRechargePage = () => { const goRechargePage = () => {
// 进入页面 // 进入页面
apiUserEvent('all', { apiUserEvent('all', {
type: "event", type: "event",
@ -191,65 +190,64 @@ const goRechargePage = () => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/common/recharge/index' url: '/pages/common/recharge/index'
}); });
} }
// 菜单列表 // 菜单列表
const menuList = [{ const menuList = [{
icon: "yuemoni", icon: "yuemoni",
name: "余额模拟", name: "余额模拟",
isHot: false, isHot: false,
path: "/pages/balance/index" path: "/pages/balance/index"
}, },
{ {
icon: "zhangdanshencheng", icon: "zhangdanshencheng",
name: "账单生成", name: "账单生成",
isHot: false, isHot: false,
path: "/pages/bill/bill-list/bill-list" path: "/pages/bill/bill-list/bill-list"
}, },
{ {
icon: "licaiheika", icon: "licaiheika",
name: "理财黑卡", name: "理财黑卡",
isHot: true, isHot: true,
path: "/pages/finance-management/index" path: "/pages/finance-management/index"
// path: "" // path: ""
}, },
{ {
icon: "huabei", icon: "huabei",
name: "花呗", name: "花呗",
isHot: false, isHot: false,
path: "/pages/ant-credit-pay/index" path: "/pages/ant-credit-pay/index"
}, },
] ]
const otherList = [{
const otherList = [{
icon: "/static/image/index/qita/jipiao.png", icon: "/static/image/index/qita/jipiao.png",
name: "机票", name: "机票",
path: "/pages/other/tickets-app/index" path: "/pages/other/tickets-app/index?type=airTicket"
}, },
{ {
icon: "/static/image/index/qita/huochepiao.png", icon: "/static/image/index/qita/huochepiao.png",
name: "火车票", name: "火车票",
path: "/pages/other/train-tickets/12306-tickets/12306-tickets" // path: "/pages/other/train-tickets/12306-tickets/12306-tickets"
}, path: "/pages/other/tickets-app/index?type=trainTicket"
{ },
{
icon: "/static/image/index/qita/gongzidan.png", icon: "/static/image/index/qita/gongzidan.png",
name: "工资单", name: "工资单",
path: "/pages/other/splash/splash" path: "/pages/other/splash/splash"
}, },
{ {
icon: "/static/image/index/qita/shipinqunliao.png", icon: "/static/image/index/qita/shipinqunliao.png",
name: "视频群聊", name: "视频群聊",
path: "/pages/other/video-group-chat/video-group-chat" path: "/pages/other/video-group-chat/video-group-chat"
}, },
{ {
icon: "/static/image/index/qita/card.png", icon: "/static/image/index/qita/card.png",
name: "身份证", name: "身份证",
path: "/pages/other/card/card" path: "/pages/other/card/card"
}, },
] ]
const data = reactive({ const data = reactive({
navBarBgColor: 'transparent', navBarBgColor: 'transparent',
statusBarHeight: 0, statusBarHeight: 0,
windowWidth: 0, windowWidth: 0,
@ -260,9 +258,9 @@ const data = reactive({
vision: "", vision: "",
platform: '', // 添加平台信息, platform: '', // 添加平台信息,
qqgroup: {} qqgroup: {}
}) })
const { const {
statusBarHeight, statusBarHeight,
windowWidth, windowWidth,
windowHeight, windowHeight,
@ -272,12 +270,12 @@ const {
vision, vision,
platform, platform,
qqgroup qqgroup
} = toRefs(data); } = toRefs(data);
/** /**
* 处理页面滚动事件 * 处理页面滚动事件
*/ */
const handleScroll = (e) => { const handleScroll = (e) => {
const scrollTop = e.detail.scrollTop const scrollTop = e.detail.scrollTop
// 滚动超过20px时显示蓝色背景否则显示透明背景 // 滚动超过20px时显示蓝色背景否则显示透明背景
if (scrollTop > 20) { if (scrollTop > 20) {
@ -285,16 +283,16 @@ const handleScroll = (e) => {
} else { } else {
data.navBarBgColor = 'transparent' data.navBarBgColor = 'transparent'
} }
} }
onLoad(async () => { onLoad(async () => {
// 获取平台信息 // 获取平台信息
const systemInfo = uni.getSystemInfoSync() const systemInfo = uni.getSystemInfoSync()
data.platform = systemInfo.platform data.platform = systemInfo.platform
data.vision = uni.getStorageSync('version') data.vision = uni.getStorageSync('version')
}) })
onShow(() => { onShow(() => {
// 启动时获取数据 // 启动时获取数据
fetchUserData() fetchUserData()
// 每次显示时刷新数据 // 每次显示时刷新数据
@ -310,12 +308,12 @@ onShow(() => {
plus.navigator.setStatusBarStyle("dark"); plus.navigator.setStatusBarStyle("dark");
}, 500) }, 500)
// #endif // #endif
}) })
/** /**
* 获取用户数据(从服务器) * 获取用户数据(从服务器)
*/ */
const fetchUserData = async () => { const fetchUserData = async () => {
try { try {
// 先设置默认值,避免页面显示异常 // 先设置默认值,避免页面显示异常
setUserData() setUserData()
@ -355,12 +353,12 @@ const fetchUserData = async () => {
} catch (error) { } catch (error) {
console.error('获取用户数据异常:', error) console.error('获取用户数据异常:', error)
} }
} }
/** /**
* 获取用户信息 * 获取用户信息
*/ */
const fetchUserInfo = async () => { const fetchUserInfo = async () => {
const data = await get('', 'api/user', {}) const data = await get('', 'api/user', {})
if (data.code === 0) { if (data.code === 0) {
uni.setStorageSync('userInfo', data.data) uni.setStorageSync('userInfo', data.data)
@ -368,12 +366,12 @@ const fetchUserInfo = async () => {
} else { } else {
throw new Error(data.message || '获取用户信息失败') throw new Error(data.message || '获取用户信息失败')
} }
} }
/** /**
* 获取用户配置 * 获取用户配置
*/ */
const fetchUserConfig = async () => { const fetchUserConfig = async () => {
const data = await get('', 'api/user/config', {}) const data = await get('', 'api/user/config', {})
if (data.code === 0) { if (data.code === 0) {
uni.setStorageSync('config', data.data) uni.setStorageSync('config', data.data)
@ -381,13 +379,13 @@ const fetchUserConfig = async () => {
} else { } else {
throw new Error(data.message || '获取用户配置失败') throw new Error(data.message || '获取用户配置失败')
} }
} }
/** /**
* 设置用户数据(从本地存储读取) * 设置用户数据(从本地存储读取)
*/ */
const setUserData = () => { const setUserData = () => {
// 用户信息 - 提供默认值 // 用户信息 - 提供默认值
const userInfoData = storage.get("userInfo") const userInfoData = storage.get("userInfo")
data.userInfo = userInfoData || { data.userInfo = userInfoData || {
@ -429,9 +427,9 @@ const setUserData = () => {
} }
data.videoHelpList = [] data.videoHelpList = []
} }
} }
const clickMenu = (item) => { const clickMenu = (item) => {
if (!item.path) { if (!item.path) {
uiUtil.showError('开发中') uiUtil.showError('开发中')
} else { } else {
@ -442,61 +440,61 @@ const clickMenu = (item) => {
} }
util.goPage(url) util.goPage(url)
} }
} }
// 开通vip // 开通vip
const openVip = () => { const openVip = () => {
goRechargePage() goRechargePage()
} }
/** /**
* 点击视频教程 * 点击视频教程
* @param item * @param item
*/ */
const clickVideoHelp = (item) => { const clickVideoHelp = (item) => {
const url = item.url const url = item.url
util.goPage(`/pages/common/webview/webview?url=${encodeURIComponent(url)}&title=${item.text}`) util.goPage(`/pages/common/webview/webview?url=${encodeURIComponent(url)}&title=${item.text}`)
} }
/** /**
* 点击公告 * 点击公告
*/ */
const clickNotice = () => { const clickNotice = () => {
console.log("点击公告", noticeInfo.value) console.log("点击公告", noticeInfo.value)
if (!noticeInfo.value.url) return if (!noticeInfo.value.url) return
const url = noticeInfo.value.url + `&uni_id=${userInfo.value.user_id}` const url = noticeInfo.value.url + `&uni_id=${userInfo.value.user_id}`
util.goPage(`/pages/common/webview/webview?url=${encodeURIComponent(url)}&title=${noticeInfo.value.title}`) util.goPage(`/pages/common/webview/webview?url=${encodeURIComponent(url)}&title=${noticeInfo.value.title}`)
} }
/** /**
* 终极兼容版复制函数 * 终极兼容版复制函数
*/ */
const copyNumber = (number) => { const copyNumber = (number) => {
if (!number) return; if (!number) return;
const text = String(number); const text = String(number);
uni.setClipboardData({ uni.setClipboardData({
data: text, data: text,
success: function () { success: function() {
uni.showToast({ uni.showToast({
title: '复制成功', title: '复制成功',
icon: 'none' icon: 'none'
}); });
}, },
fail: function () { fail: function() {
uni.showToast({ uni.showToast({
title: '复制失败', title: '复制失败',
icon: 'none' icon: 'none'
}); });
} }
}); });
} }
/** /**
* 退出模拟器 * 退出模拟器
*/ */
const exit = () => { const exit = () => {
console.log("退出模拟器") console.log("退出模拟器")
// 判断是否为 iOS 环境 // 判断是否为 iOS 环境
if (uni.getSystemInfoSync().platform === 'ios') { if (uni.getSystemInfoSync().platform === 'ios') {
@ -506,25 +504,25 @@ const exit = () => {
} else { } else {
plus.runtime.quit(); plus.runtime.quit();
} }
} }
const noticeContainer = ref(null); const noticeContainer = ref(null);
const noticeInner = ref(null); const noticeInner = ref(null);
const noticeBox = ref(null); const noticeBox = ref(null);
// #ifndef H5 // #ifndef H5
const animation = uni.requireNativePlugin('animation'); const animation = uni.requireNativePlugin('animation');
const dom = uni.requireNativePlugin('dom'); const dom = uni.requireNativePlugin('dom');
// #endif // #endif
let marqueeTimer = null; let marqueeTimer = null;
const currentMarqueeId = ref(0); const currentMarqueeId = ref(0);
const lastMarqueeText = ref(''); const lastMarqueeText = ref('');
/** /**
* 开始走马灯 * 开始走马灯
*/ */
const startMarquee = () => { const startMarquee = () => {
// 避免不必要的重置:如果文本没有变化且正在运行,则忽略 // 避免不必要的重置:如果文本没有变化且正在运行,则忽略
if (lastMarqueeText.value === noticeInfo.value.text && currentMarqueeId.value > 0) { if (lastMarqueeText.value === noticeInfo.value.text && currentMarqueeId.value > 0) {
return; return;
@ -572,12 +570,12 @@ const startMarquee = () => {
}); });
}); });
}, 1000); // 增加延时确保渲染 }, 1000); // 增加延时确保渲染
} }
/** /**
* 执行滚动动画循环 * 执行滚动动画循环
*/ */
const runMarqueeAnimation = (containerWidth, textWidth, myId) => { const runMarqueeAnimation = (containerWidth, textWidth, myId) => {
// ID 校验如果当前ID不匹配说明已被新动画取代停止递归 // ID 校验如果当前ID不匹配说明已被新动画取代停止递归
if (myId !== currentMarqueeId.value) return; if (myId !== currentMarqueeId.value) return;
if (!noticeInner.value) return; if (!noticeInner.value) return;
@ -614,12 +612,12 @@ const runMarqueeAnimation = (containerWidth, textWidth, myId) => {
runMarqueeAnimation(containerWidth, textWidth, myId); runMarqueeAnimation(containerWidth, textWidth, myId);
}); });
}); });
} }
/** /**
* 停止走马灯 * 停止走马灯
*/ */
const stopMarquee = () => { const stopMarquee = () => {
// 清除定时器 // 清除定时器
if (marqueeTimer) { if (marqueeTimer) {
clearTimeout(marqueeTimer); clearTimeout(marqueeTimer);
@ -627,42 +625,42 @@ const stopMarquee = () => {
} }
// 增加ID使其失效 // 增加ID使其失效
currentMarqueeId.value++; currentMarqueeId.value++;
} }
onHide(() => { onHide(() => {
stopMarquee(); stopMarquee();
}) })
onUnload(() => { onUnload(() => {
stopMarquee(); stopMarquee();
}) })
</script> </script>
<style> <style>
.container { .container {
background-color: #F0F4F9; background-color: #F0F4F9;
} }
.margin-l-6 { .margin-l-6 {
margin-left: 6px; margin-left: 6px;
} }
.index-bg-img { .index-bg-img {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
z-index: 0; z-index: 0;
} }
.nav-bar-box { .nav-bar-box {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
z-index: 9999; z-index: 9999;
background-color: transparent; background-color: transparent;
} }
.content-box { .content-box {
position: fixed; position: fixed;
top: 0rpx; top: 0rpx;
left: 0; left: 0;
@ -672,29 +670,29 @@ onUnload(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
} }
::v-deep .uni-scroll-view-content { ::v-deep .uni-scroll-view-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
} }
.status-box { .status-box {
width: 100%; width: 100%;
} }
.nav-box { .nav-box {
height: 44px; height: 44px;
background-color: transparent; background-color: transparent;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
} }
.left-box { .left-box {
width: 60px; width: 60px;
height: 44px; height: 44px;
background-color: transparent; background-color: transparent;
@ -703,9 +701,9 @@ onUnload(() => {
justify-content: center; justify-content: center;
position: relative; position: relative;
z-index: 10; z-index: 10;
} }
.title { .title {
flex: 1; flex: 1;
height: 44px; height: 44px;
font-size: 32rpx; font-size: 32rpx;
@ -716,33 +714,33 @@ onUnload(() => {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.right-box { .right-box {
width: 60px; width: 60px;
height: 44px; height: 44px;
background-color: transparent; background-color: transparent;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.user-box { .user-box {
position: relative; position: relative;
margin: 24rpx 32rpx 0; margin: 24rpx 32rpx 0;
height: 120rpx; height: 120rpx;
z-index: 10; z-index: 10;
} }
.user-bg { .user-bg {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 120rpx; height: 120rpx;
} }
.user-info-box { .user-info-box {
position: absolute; position: absolute;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -754,49 +752,49 @@ onUnload(() => {
width: 100%; width: 100%;
height: 120rpx; height: 120rpx;
z-index: 1; z-index: 1;
} }
.user-info { .user-info {
flex: 1; flex: 1;
} }
.user-avatar { .user-avatar {
width: 72rpx; width: 72rpx;
height: 72rpx; height: 72rpx;
border-radius: 50%; border-radius: 50%;
margin-right: 20rpx; margin-right: 20rpx;
} }
.name-box { .name-box {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
} }
.phone-text { .phone-text {
font-size: 28rpx; font-size: 28rpx;
color: #FFFFFF; color: #FFFFFF;
font-weight: bold; font-weight: bold;
margin-right: 12rpx; margin-right: 12rpx;
} }
.vip-logo { .vip-logo {
width: 60rpx; width: 60rpx;
height: 20rpx; height: 20rpx;
} }
.vip-end-time { .vip-end-time {
font-size: 24rpx; font-size: 24rpx;
color: #FFFFFF; color: #FFFFFF;
margin-top: 8rpx; margin-top: 8rpx;
} }
.open-vip-btn { .open-vip-btn {
height: 40rpx; height: 40rpx;
width: 116rpx; width: 116rpx;
} }
.notice-box { .notice-box {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -806,9 +804,9 @@ onUnload(() => {
padding: 0 16rpx; padding: 0 16rpx;
height: 64rpx; height: 64rpx;
overflow: hidden; overflow: hidden;
} }
.sound-box { .sound-box {
height: 64rpx; height: 64rpx;
width: 50rpx; width: 50rpx;
display: flex; display: flex;
@ -816,35 +814,35 @@ onUnload(() => {
justify-content: center; justify-content: center;
position: relative; position: relative;
z-index: 10; z-index: 10;
} }
.notice-content-wrapper { .notice-content-wrapper {
flex: 1; flex: 1;
flex-direction: row; flex-direction: row;
overflow: hidden; overflow: hidden;
} }
.notice-inner { .notice-inner {
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
} }
.notice-content { .notice-content {
font-size: 24rpx; font-size: 24rpx;
color: #767676; color: #767676;
} }
.group-box { .group-box {
margin: 32rpx; margin: 32rpx;
margin-bottom: 0; margin-bottom: 0;
} }
.title-img { .title-img {
width: 140rpx; width: 140rpx;
height: 44rpx; height: 44rpx;
} }
.video-help-box { .video-help-box {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -855,47 +853,47 @@ onUnload(() => {
margin-top: 16rpx; margin-top: 16rpx;
flex-wrap: wrap; flex-wrap: wrap;
padding-top: 8rpx; padding-top: 8rpx;
} }
.video-help-item { .video-help-item {
margin-top: 16rpx; margin-top: 16rpx;
width: 25%; width: 25%;
text-align: center; text-align: center;
flex-direction: column; flex-direction: column;
display: flex; display: flex;
align-items: center; align-items: center;
} }
.video-help-img { .video-help-img {
width: 96rpx; width: 96rpx;
height: 96rpx; height: 96rpx;
} }
.video-help-title { .video-help-title {
font-size: 24rpx; font-size: 24rpx;
color: #1A1A1A; color: #1A1A1A;
text-align: center; text-align: center;
} }
.menu-box { .menu-box {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; flex-wrap: wrap;
margin-top: 16rpx; margin-top: 16rpx;
} }
.item-box { .item-box {
position: relative; position: relative;
height: 156rpx; height: 156rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-end; justify-content: flex-end;
margin-bottom: 32rpx; margin-bottom: 32rpx;
} }
.menu-item { .menu-item {
display: flex; display: flex;
position: relative; position: relative;
flex-direction: row; flex-direction: row;
@ -905,47 +903,47 @@ onUnload(() => {
border-radius: 16rpx; border-radius: 16rpx;
padding: 16rpx 32rpx; padding: 16rpx 32rpx;
height: 140rpx; height: 140rpx;
} }
.menu-item-name { .menu-item-name {
font-weight: bold; font-weight: bold;
font-size: 32rpx; font-size: 32rpx;
color: #000000; color: #000000;
} }
.name-img { .name-img {
height: 28rpx; height: 28rpx;
} }
.hot-icon { .hot-icon {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 68rpx; width: 68rpx;
height: 30rpx; height: 30rpx;
z-index: 99; z-index: 99;
} }
.activity-box { .activity-box {
margin: 0 32rpx; margin: 0 32rpx;
} }
.footer-box { .footer-box {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-top: 40rpx; margin-top: 40rpx;
margin-bottom: 10rpx; margin-bottom: 10rpx;
} }
.vision-text { .vision-text {
font-size: 24rpx; font-size: 24rpx;
color: #767676; color: #767676;
} }
.ios-padding-bottom { .ios-padding-bottom {
margin-bottom: 50rpx; margin-bottom: 50rpx;
} }
</style> </style>

View File

@ -1,9 +1,12 @@
<template> <template>
<view class="container"> <view class="container">
<NavBar title="选择机票" bgColor="#F0F4F9" isBack></NavBar> <NavBar :title="`选择${type == 'airTicket' ? '机票' : '火车票'}`" bgColor="#F0F4F9" isBack></NavBar>
<view class="content"> <view class="content">
<view class="app-card" v-for="(item, index) in appList" :key="index" @click="handleItemClick(item)"> <template v-for="(item, index) in appList" :key="index">
<view class="app-card"
v-if="(type == 'airTicket' && item.airPath) || (type == 'trainTicket' && item.trainPath)"
@click="handleItemClick(item)">
<!-- Background Watermark --> <!-- Background Watermark -->
<image class="watermark" :src="item.bgImage" mode="heightFix"></image> <image class="watermark" :src="item.bgImage" mode="heightFix"></image>
@ -22,52 +25,72 @@
<uni-icons type="right" size="18" color="#CCCCCC"></uni-icons> <uni-icons type="right" size="18" color="#CCCCCC"></uni-icons>
</view> </view>
</template>
</view> </view>
</view> </view>
</template> </template>
<script setup> <script setup>
import NavBar from '@/components/nav-bar/nav-bar.vue'; import NavBar from '@/components/nav-bar/nav-bar.vue';
import { reactive, toRefs, getCurrentInstance } from 'vue'; import {
import { onLoad } from '@dcloudio/uni-app'; reactive,
import { util } from '@/utils/common.js'; // Assuming util exists for navigation, similar to previous tasks toRefs,
getCurrentInstance,
ref
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import {
util
} from '@/utils/common.js'; // Assuming util exists for navigation, similar to previous tasks
const { const {
appContext, appContext,
proxy proxy
} = getCurrentInstance(); } = getCurrentInstance();
const appList = [ let type = ref('airTicket')
{
const appList = [{
name: '去哪儿APP', name: '去哪儿APP',
logo: '/static/image/other/tickets-app/qvnar-logo.png', logo: '/static/image/other/tickets-app/qvnar-logo.png',
bgImage: '/static/image/other/tickets-app/qvnar-bg.png', bgImage: '/static/image/other/tickets-app/qvnar-bg.png',
path: '/pages/other/air-tickets/qunar-air-tickets/qunar-air-tickets', airPath: '/pages/other/air-tickets/qunar-air-tickets/qunar-air-tickets',
trainPath: "",
isHot: false isHot: false
}, },
{ {
name: '飞猪APP', name: '飞猪APP',
logo: '/static/image/other/tickets-app/fliggy-logo.png', logo: '/static/image/other/tickets-app/fliggy-logo.png',
bgImage: '/static/image/other/tickets-app/fliggy-bg.png', bgImage: '/static/image/other/tickets-app/fliggy-bg.png',
path: '/pages/other/air-tickets/fliggy-air-tickets/fliggy-air-tickets', airPath: '/pages/other/air-tickets/fliggy-air-tickets/fliggy-air-tickets',
trainPath: "",
isHot: true isHot: true
}, },
{ {
name: '携程APP', name: '携程APP',
logo: '/static/image/other/tickets-app/trip-com-logo.png', logo: '/static/image/other/tickets-app/trip-com-logo.png',
bgImage: '/static/image/other/tickets-app/trip-com-bg.png', bgImage: '/static/image/other/tickets-app/trip-com-bg.png',
path: '/pages/other/air-tickets/ctrip-air-tickets/ctrip-air-tickets', airPath: '/pages/other/air-tickets/ctrip-air-tickets/ctrip-air-tickets',
trainPath: "/pages/other/train-tickets/ctrip-train-tickets/ctrip-train-tickets",
isHot: false isHot: false
}, },
// { {
// name: '12306', name: '铁路12306',
// logo: '/static/image/other/tickets-app/12306-logo.png', logo: '/static/image/other/tickets-app/12306-logo.png',
// bgImage: '/static/image/other/tickets-app/12306-bg.png', bgImage: '/static/image/other/tickets-app/12306-bg.png',
// path: '/pages/other/train-tickets/12306-tickets/12306-tickets', airPath: '',
// isHot: false trainPath: "/pages/other/train-tickets/12306-tickets/12306-tickets",
// } isHot: false
}
] ]
onLoad((option) => { onLoad((option) => {
const appType = option.type
if (appType == "trainTicket") {
type.value = "trainTicket"
} else {
type.value = "airTicket"
// //
proxy.$apiUserEvent('all', { proxy.$apiUserEvent('all', {
type: 'event', type: 'event',
@ -75,19 +98,36 @@ onLoad((option) => {
prefix: '.uni.other.', prefix: '.uni.other.',
value: "机票" value: "机票"
}) })
}
}) })
/**
* 跳转火车票/飞机票页面
*/
const handleItemClick = (item) => { const handleItemClick = (item) => {
if (item.path) { if (type.value == 'trainTicket') {
util.goPage(item.path) if (item.trainPath) {
util.goPage(item.trainPath)
} else { } else {
uni.showToast({ uni.showToast({
title: '开发中', title: '开发中',
icon: 'none' icon: 'none'
}) })
} }
} } else {
if (item.airPath) {
util.goPage(item.airPath)
} else {
uni.showToast({
title: '开发中',
icon: 'none'
})
}
}
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.container { .container {

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,17 @@
<text class="label">订单号</text> <text class="label">订单号</text>
<input class="input" v-model="ticketsInfo.orderInfo.orderNo" /> <input class="input" v-model="ticketsInfo.orderInfo.orderNo" />
</view> </view>
<picker mode="date" fields="day" :value="getPickerDate(ticketsInfo.orderInfo.orderTime)" <picker v-if="app == '12306'" mode="date" fields="day"
@change="onOrderTimeChange"> :value="getPickerDate(ticketsInfo.orderInfo.orderTime)" @change="onOrderTimeChange">
<view class="form-item"> <view class="form-item">
<text class="label">下单时间</text> <text class="label">下单时间</text>
<view class="input">{{ ticketsInfo.orderInfo.orderTime }}</view> <view class="input">{{ ticketsInfo.orderInfo.orderTime }}</view>
</view> </view>
</picker> </picker>
<view v-if="app == 'ctrip'" class="form-item">
<text class="label">订单总价</text>
<input class="input" type="number" v-model="ticketsInfo.orderInfo.price" />
</view>
</view> </view>
</view> </view>
@ -75,6 +79,10 @@
<text class="label">历时</text> <text class="label">历时</text>
<input class="input" v-model="ticketsInfo.ticketInfo.duration" /> <input class="input" v-model="ticketsInfo.ticketInfo.duration" />
</view> </view>
<view v-if="app == 'ctrip'" class="form-item">
<text class="label">火车名称</text>
<input class="input" v-model="ticketsInfo.ticketInfo.trainName" />
</view>
</view> </view>
</view> </view>
@ -116,7 +124,11 @@
<view class="form-item"> <view class="form-item">
<text class="label">票价</text> <text class="label">票价</text>
<input class="input" v-model="passenger.price" /> <input class="input" type="number" v-model="passenger.price" @input="onPriceInput" />
</view>
<view class="form-item">
<text class="label">积分</text>
<input class="input" type="number" v-model="passenger.points" />
</view> </view>
<view class="form-item"> <view class="form-item">
<text class="label">证件类型</text> <text class="label">证件类型</text>
@ -136,16 +148,20 @@
</view> </view>
<!-- 酒店广告 --> <!-- 酒店广告 -->
<view class="section-container"> <view v-if="app == '12306' || app == 'ctrip'" class="section-container">
<view class="section-header" @click="toggleSection('hotelInfo')"> <view class="section-header" @click="toggleSection('hotelInfo')">
<text class="section-title">酒店广告</text> <text class="section-title">{{ app == '12306' ? '酒店广告' : '返现任务' }}</text>
<uni-icons :type="collapsed.hotelInfo ? 'bottom' : 'top'" size="16" color="#666"></uni-icons> <uni-icons :type="collapsed.hotelInfo ? 'bottom' : 'top'" size="16" color="#666"></uni-icons>
</view> </view>
<view class="card" v-show="!collapsed.hotelInfo"> <view class="card" v-show="!collapsed.hotelInfo">
<view class="form-item"> <view v-if="app == '12306'" class="form-item">
<text class="label">城市</text> <text class="label">城市</text>
<input class="input" v-model="ticketsInfo.hotelInfo.city" /> <input class="input" v-model="ticketsInfo.hotelInfo.city" />
</view> </view>
<view v-if="app == 'ctrip'" class="form-item">
<text class="label">返现金额</text>
<input class="input" type="number" v-model="ticketsInfo.hotelInfo.cashback" />
</view>
<uni-datetime-picker type="daterange" v-model="hotelDateRange" :border="false"> <uni-datetime-picker type="daterange" v-model="hotelDateRange" :border="false">
<view class="form-item"> <view class="form-item">
<text class="label">入住/离店日期</text> <text class="label">入住/离店日期</text>
@ -162,18 +178,20 @@
</template> </template>
<script setup> <script setup>
import NavBar from '@/components/nav-bar/nav-bar.vue' import NavBar from '@/components/nav-bar/nav-bar.vue'
import { import {
reactive, reactive,
toRefs, toRefs,
onMounted, onMounted,
computed computed
} from 'vue'; } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const defaultData = { const defaultData = {
"orderInfo": { "orderInfo": {
"orderNo": "EJ66223536", "orderNo": "EJ66223536",
"orderTime": "2026.01.01" "orderTime": "2026.01.01",
"price": "4440"
}, },
"ticketInfo": { "ticketInfo": {
"departureTime": "01-01 09:19", "departureTime": "01-01 09:19",
@ -184,7 +202,8 @@
"duration": "4时45分", "duration": "4时45分",
"date": "2026.01.01", "date": "2026.01.01",
"weekDay": "星期四", "weekDay": "星期四",
"gate": "6B" "gate": "6B",
"trainName": "复兴号"
}, },
"passengerList": [{ "passengerList": [{
"name": "张元英", "name": "张元英",
@ -195,62 +214,79 @@
"idType": "外国护照KR", "idType": "外国护照KR",
"price": "2110", "price": "2110",
"status": "已支付", "status": "已支付",
"isMe": true "isMe": true,
"points": 9632
}], }],
"hotelInfo": { "hotelInfo": {
"city": "上海", "city": "上海",
"cashback": "25",
"startDay": "01-01", "startDay": "01-01",
"endDay": "01-02" "endDay": "01-02"
} }
} }
// //
const ticketType = [{ const ticketType = [{
label: '成人票', label: '成人票',
value: '1' value: '1'
}, },
{ {
label: '儿童票', label: '儿童票',
value: '2' value: '2'
}, },
{ {
label: '学生票', label: '学生票',
value: '3' value: '3'
}, },
{ {
label: '残疾军人票', label: '残疾军人票',
value: '4' value: '4'
} }
] ]
const data = reactive({ const data = reactive({
ticketsInfo: JSON.parse(JSON.stringify(defaultData)), ticketsInfo: JSON.parse(JSON.stringify(defaultData)),
collapsed: { collapsed: {
orderInfo: true, orderInfo: true,
ticketInfo: false, // Default open ticket info as it is most likely to be edited ticketInfo: false, // Default open ticket info as it is most likely to be edited
passengerList: false, passengerList: false,
hotelInfo: true hotelInfo: true
} },
}) app: '12306',
STORAGE_KEY: 'ticketsInfo'
})
let { app } = toRefs(data)
const { const {
ticketsInfo, ticketsInfo,
collapsed collapsed
} = toRefs(data) } = toRefs(data)
const ticketYear = computed(() => { onLoad((options) => {
console.log("options", options)
if (options.app) {
data.app = options.app
}
if (options.storageKey) {
data.STORAGE_KEY = options.storageKey
}
})
const ticketYear = computed(() => {
const dateStr = data.ticketsInfo.ticketInfo.date; const dateStr = data.ticketsInfo.ticketInfo.date;
if (dateStr && dateStr.length >= 4) { if (dateStr && dateStr.length >= 4) {
return dateStr.substring(0, 4); return dateStr.substring(0, 4);
} }
return new Date().getFullYear().toString(); return new Date().getFullYear().toString();
}) })
/**
/**
* 获取酒店日期范围 * 获取酒店日期范围
*/ */
const hotelDateRange = computed({ const hotelDateRange = computed({
get() { get() {
const year = ticketYear.value; const year = ticketYear.value;
const start = data.ticketsInfo.hotelInfo.startDay ? const start = data.ticketsInfo.hotelInfo.startDay ?
@ -268,19 +304,33 @@
data.ticketsInfo.hotelInfo.endDay = val[1].substring(5); data.ticketsInfo.hotelInfo.endDay = val[1].substring(5);
} }
} }
}) })
onMounted(() => { onMounted(() => {
const stored = uni.getStorageSync('ticketsInfo') const stored = uni.getStorageSync(data.STORAGE_KEY)
if (stored) { if (stored) {
Object.assign(data.ticketsInfo, stored) Object.assign(data.ticketsInfo, stored)
} }
updateDuration(); updateDuration();
}) })
/** /**
* 更新总价
*/
const onPriceInput = () => {
setTimeout(() => {
let total = 0;
data.ticketsInfo.passengerList.forEach(item => {
const price = Number(item.price) || 0;
total += price;
});
data.ticketsInfo.orderInfo.price = total.toString();
}, 50);
}
/**
* 确认 * 确认
*/ */
const handleRightButtonClick = () => { const handleRightButtonClick = () => {
console.log("handleRightButtonClick", data.ticketsInfo) console.log("handleRightButtonClick", data.ticketsInfo)
const orderTimeStr = data.ticketsInfo.orderInfo.orderTime; const orderTimeStr = data.ticketsInfo.orderInfo.orderTime;
const ticketDateStr = data.ticketsInfo.ticketInfo.date; const ticketDateStr = data.ticketsInfo.ticketInfo.date;
@ -312,38 +362,39 @@
} }
} }
uni.setStorageSync('ticketsInfo', data.ticketsInfo) uni.setStorageSync(data.STORAGE_KEY, data.ticketsInfo)
uni.navigateBack() uni.navigateBack()
} }
/** /**
* 切换折叠状态 * 切换折叠状态
* @param {string} key * @param {string} key
*/ */
const toggleSection = (key) => { const toggleSection = (key) => {
data.collapsed[key] = !data.collapsed[key] data.collapsed[key] = !data.collapsed[key]
} }
/** /**
* 删除乘客 * 删除乘客
* @param {number} index * @param {number} index
*/ */
const removePassenger = (index) => { const removePassenger = (index) => {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '确定要删除该乘客吗?', content: '确定要删除该乘客吗?',
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
data.ticketsInfo.passengerList.splice(index, 1) data.ticketsInfo.passengerList.splice(index, 1);
onPriceInput();
} }
} }
}) })
} }
/** /**
* 添加乘客 * 添加乘客
*/ */
const addPassenger = () => { const addPassenger = () => {
const oldPassenger = data.ticketsInfo.passengerList[data.ticketsInfo.passengerList.length - 1] const oldPassenger = data.ticketsInfo.passengerList[data.ticketsInfo.passengerList.length - 1]
const newPassenger = { const newPassenger = {
name: '新乘客', name: '新乘客',
@ -354,17 +405,19 @@
idType: '中国居民身份证', idType: '中国居民身份证',
price: oldPassenger.price || '0', price: oldPassenger.price || '0',
status: '已支付', status: '已支付',
isMe: false isMe: false,
} points: oldPassenger.points || '2898',
data.ticketsInfo.passengerList.push(newPassenger)
} }
data.ticketsInfo.passengerList.push(newPassenger);
onPriceInput();
}
/** /**
* 获取选择器日期 * 获取选择器日期
* @param {string} dateStr * @param {string} dateStr
* @returns {string} * @returns {string}
*/ */
const getPickerDate = (dateStr) => { const getPickerDate = (dateStr) => {
if (!dateStr) return ''; if (!dateStr) return '';
// Handle YYYY.MM.DD format // Handle YYYY.MM.DD format
if (dateStr.includes('.')) { if (dateStr.includes('.')) {
@ -377,34 +430,34 @@
return `${year}-${dateStr}`; return `${year}-${dateStr}`;
} }
return dateStr; return dateStr;
} }
/** /**
* 切换下单时间 * 切换下单时间
* @param {*} e * @param {*} e
*/ */
const onOrderTimeChange = (e) => { const onOrderTimeChange = (e) => {
const val = e.detail.value; const val = e.detail.value;
if (val) { if (val) {
data.ticketsInfo.orderInfo.orderTime = val.replace(/-/g, '.'); data.ticketsInfo.orderInfo.orderTime = val.replace(/-/g, '.');
} }
} }
/** /**
* 切换乘客类型 * 切换乘客类型
* @param {*} e * @param {*} e
* @param {*} index * @param {*} index
*/ */
const onTicketTypeChange = (e, index) => { const onTicketTypeChange = (e, index) => {
const val = e.detail.value; const val = e.detail.value;
data.ticketsInfo.passengerList[index].type = ticketType[val].label; data.ticketsInfo.passengerList[index].type = ticketType[val].label;
} }
/** /**
* 切换出发日期 * 切换出发日期
* @param {*} e * @param {*} e
*/ */
const onTicketDateChange = (e) => { const onTicketDateChange = (e) => {
const val = e.detail.value; // YYYY-MM-DD const val = e.detail.value; // YYYY-MM-DD
if (val) { if (val) {
// Update Date: YYYY.MM.DD // Update Date: YYYY.MM.DD
@ -415,30 +468,30 @@
const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
data.ticketsInfo.ticketInfo.weekDay = days[dateObj.getDay()]; data.ticketsInfo.ticketInfo.weekDay = days[dateObj.getDay()];
} }
} }
/** /**
* 获取时间 * 获取时间
* @param {string} fullStr * @param {string} fullStr
* @returns {string} * @returns {string}
*/ */
const getTimeHHMM = (fullStr) => { const getTimeHHMM = (fullStr) => {
if (!fullStr) return ''; if (!fullStr) return '';
if (fullStr.length > 5) return fullStr.split(' ')[1]; if (fullStr.length > 5) return fullStr.split(' ')[1];
return fullStr; return fullStr;
} }
/** /**
* 获取出发时间 * 获取出发时间
*/ */
const departureTimeHHMM = computed(() => { const departureTimeHHMM = computed(() => {
return getTimeHHMM(data.ticketsInfo.ticketInfo.departureTime); return getTimeHHMM(data.ticketsInfo.ticketInfo.departureTime);
}) })
/** /**
* 获取出发时间选择器范围 * 获取出发时间选择器范围
*/ */
const departureTimeRange = computed(() => { const departureTimeRange = computed(() => {
const hours = Array.from({ const hours = Array.from({
length: 24 length: 24
}, (_, i) => i < 10 ? '0' + i : '' + i); }, (_, i) => i < 10 ? '0' + i : '' + i);
@ -446,12 +499,12 @@
length: 60 length: 60
}, (_, i) => i < 10 ? '0' + i : '' + i); }, (_, i) => i < 10 ? '0' + i : '' + i);
return [hours, minutes]; return [hours, minutes];
}) })
/** /**
* 获取出发时间索引 * 获取出发时间索引
*/ */
const departureTimeIndex = computed(() => { const departureTimeIndex = computed(() => {
const timeStr = getTimeHHMM(data.ticketsInfo.ticketInfo.departureTime); const timeStr = getTimeHHMM(data.ticketsInfo.ticketInfo.departureTime);
if (!timeStr) return [0, 0]; if (!timeStr) return [0, 0];
const [h, m] = timeStr.split(':'); const [h, m] = timeStr.split(':');
@ -462,12 +515,12 @@
let mIdx = minutes.indexOf(m); let mIdx = minutes.indexOf(m);
if (mIdx === -1) mIdx = 0; if (mIdx === -1) mIdx = 0;
return [hIdx, mIdx]; return [hIdx, mIdx];
}) })
/** /**
* 获取到达时间日期范围 * 获取到达时间日期范围
*/ */
const arrivalRange = computed(() => { const arrivalRange = computed(() => {
const dateStr = data.ticketsInfo.ticketInfo.date; // YYYY.MM.DD const dateStr = data.ticketsInfo.ticketInfo.date; // YYYY.MM.DD
const dates = []; const dates = [];
if (dateStr) { if (dateStr) {
@ -488,12 +541,12 @@
length: 60 length: 60
}, (_, i) => i < 10 ? '0' + i : '' + i); }, (_, i) => i < 10 ? '0' + i : '' + i);
return [dates, hours, minutes]; return [dates, hours, minutes];
}) })
/** /**
* 获取到达时间索引 * 获取到达时间索引
*/ */
const arrivalIndex = computed(() => { const arrivalIndex = computed(() => {
const arrTime = data.ticketsInfo.ticketInfo.arrivalTime; const arrTime = data.ticketsInfo.ticketInfo.arrivalTime;
if (!arrTime || arrTime.length < 5) return [0, 0, 0]; if (!arrTime || arrTime.length < 5) return [0, 0, 0];
// Might be HH:mm or MM-DD HH:mm // Might be HH:mm or MM-DD HH:mm
@ -524,13 +577,13 @@
if (mIdx === -1) mIdx = 0; if (mIdx === -1) mIdx = 0;
return [dateIdx, hIdx, mIdx]; return [dateIdx, hIdx, mIdx];
}) })
/** /**
* 切换到达时间 * 切换到达时间
* @param {*} e * @param {*} e
*/ */
const onArrivalChange = (e) => { const onArrivalChange = (e) => {
const idxs = e.detail.value; const idxs = e.detail.value;
const range = arrivalRange.value; const range = arrivalRange.value;
if (!range[0][idxs[0]]) return; if (!range[0][idxs[0]]) return;
@ -562,17 +615,17 @@
data.ticketsInfo.ticketInfo.arrivalTime = newArrTime; data.ticketsInfo.ticketInfo.arrivalTime = newArrTime;
updateDuration(); updateDuration();
} }
/** /**
* 切换出发时间 * 切换出发时间
* @param e * @param e
*/ */
/** /**
* 切换出发时间 * 切换出发时间
* @param e * @param e
*/ */
const onDepartureTimeChange = (e) => { const onDepartureTimeChange = (e) => {
let val = e.detail.value; // Array [hIdx, mIdx] let val = e.detail.value; // Array [hIdx, mIdx]
// Convert array to HH:mm string // Convert array to HH:mm string
@ -625,12 +678,12 @@
let mmdd = `${dateParts[1]}-${dateParts[2]}`; let mmdd = `${dateParts[1]}-${dateParts[2]}`;
data.ticketsInfo.ticketInfo.departureTime = `${mmdd} ${val}`; data.ticketsInfo.ticketInfo.departureTime = `${mmdd} ${val}`;
updateDuration(); updateDuration();
} }
/** /**
* 更新时长 * 更新时长
*/ */
const updateDuration = () => { const updateDuration = () => {
// Helper to parse MM-DD HH:mm to timestamp (using current year) // Helper to parse MM-DD HH:mm to timestamp (using current year)
// Safer to use "/" for cross-platform compatibility // Safer to use "/" for cross-platform compatibility
const getTs = (str) => { const getTs = (str) => {
@ -649,53 +702,53 @@
const diffMins = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60)); const diffMins = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
data.ticketsInfo.ticketInfo.duration = `${diffHrs}${diffMins}`; data.ticketsInfo.ticketInfo.duration = `${diffHrs}${diffMins}`;
} }
} }
</script> </script>
<style> <style>
@import "@/common/main.css"; @import "@/common/main.css";
page { page {
background-color: #F8F8F8; background-color: #F8F8F8;
height: 100vh; height: 100vh;
overflow: hidden; overflow: hidden;
} }
</style> </style>
<style lang="less" scoped> <style lang="less" scoped>
.container { .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100vh; height: 100vh;
} }
.form-content { .form-content {
flex: 1; flex: 1;
height: 0; height: 0;
padding: 24rpx; padding: 24rpx;
box-sizing: border-box; box-sizing: border-box;
} }
.section-container { .section-container {
margin-bottom: 24rpx; margin-bottom: 24rpx;
} }
.section-header { .section-header {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 24rpx 12rpx 16rpx; padding: 24rpx 12rpx 16rpx;
background-color: transparent; background-color: transparent;
} }
.section-title { .section-title {
font-size: 28rpx; font-size: 28rpx;
color: #666; color: #666;
font-weight: 500; font-weight: 500;
} }
.card { .card {
background-color: #fff; background-color: #fff;
border-radius: 16rpx; border-radius: 16rpx;
padding: 0 24rpx; padding: 0 24rpx;
@ -722,9 +775,9 @@
color: #FF4D4F; color: #FF4D4F;
padding: 4rpx 12rpx; padding: 4rpx 12rpx;
} }
} }
.form-item { .form-item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@ -747,9 +800,9 @@
color: #333; color: #333;
text-align: right; text-align: right;
} }
} }
.add-btn-box { .add-btn-box {
background-color: #fff; background-color: #fff;
border-radius: 16rpx; border-radius: 16rpx;
padding: 24rpx; padding: 24rpx;
@ -764,9 +817,9 @@
font-size: 30rpx; font-size: 30rpx;
margin-left: 8rpx; margin-left: 8rpx;
} }
} }
.placeholder { .placeholder {
height: 60rpx; height: 60rpx;
} }
</style> </style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB