火车票app首页

This commit is contained in:
tangxinyue 2026-03-03 15:45:32 +08:00
parent e233f84b4d
commit cfce21f87e
2 changed files with 905 additions and 866 deletions

View File

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

View File

@ -1,9 +1,11 @@
<template>
<view class="container">
<NavBar title="选择机票" bgColor="#F0F4F9" isBack></NavBar>
<NavBar :title="`选择${type=='airTicket'?'机票':'火车票'}`" bgColor="#F0F4F9" isBack></NavBar>
<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 -->
<image class="watermark" :src="item.bgImage" mode="heightFix"></image>
@ -22,52 +24,72 @@
<uni-icons type="right" size="18" color="#CCCCCC"></uni-icons>
</view>
</template>
</view>
</view>
</template>
<script setup>
import NavBar from '@/components/nav-bar/nav-bar.vue';
import { reactive, toRefs, getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { util } from '@/utils/common.js'; // Assuming util exists for navigation, similar to previous tasks
const {
import NavBar from '@/components/nav-bar/nav-bar.vue';
import {
reactive,
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 {
appContext,
proxy
} = getCurrentInstance();
} = getCurrentInstance();
const appList = [
{
let type = ref('airTicket')
const appList = [{
name: '去哪儿APP',
logo: '/static/image/other/tickets-app/qvnar-logo.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
},
{
name: '飞猪APP',
logo: '/static/image/other/tickets-app/fliggy-logo.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
},
{
name: '携程APP',
logo: '/static/image/other/tickets-app/trip-com-logo.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: "",
isHot: false
},
// {
// name: '12306',
// logo: '/static/image/other/tickets-app/12306-logo.png',
// bgImage: '/static/image/other/tickets-app/12306-bg.png',
// path: '/pages/other/train-tickets/12306-tickets/12306-tickets',
// isHot: false
// }
]
{
name: '铁路12306',
logo: '/static/image/other/tickets-app/12306-logo.png',
bgImage: '/static/image/other/tickets-app/12306-bg.png',
airPath: '',
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', {
type: 'event',
@ -75,31 +97,48 @@ onLoad((option) => {
prefix: '.uni.other.',
value: "机票"
})
})
}
const handleItemClick = (item) => {
if (item.path) {
util.goPage(item.path)
})
/**
* 跳转火车票/飞机票页面
*/
const handleItemClick = (item) => {
if (type.value == 'trainTicket') {
if (item.trainPath) {
util.goPage(item.trainPath)
} else {
uni.showToast({
title: '开发中',
icon: 'none'
})
}
}
} else {
if (item.airPath) {
util.goPage(item.airPath)
} else {
uni.showToast({
title: '开发中',
icon: 'none'
})
}
}
}
</script>
<style lang="less" scoped>
.container {
.container {
min-height: 100vh;
background-color: #F0F4F9;
}
}
.content {
.content {
padding: 24rpx;
}
}
.app-card {
.app-card {
position: relative;
background-color: #FFFFFF;
border-radius: 20rpx;
@ -149,5 +188,5 @@ const handleItemClick = (item) => {
font-weight: 500;
}
}
}
}
</style>