Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
J
jz_Travel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhengke
jz_Travel
Commits
9e3ae0b2
Commit
9e3ae0b2
authored
Jun 23, 2025
by
罗超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改文件
parent
442cdc95
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1208 additions
and
7 deletions
+1208
-7
flex.css
asset/css/flex.css
+13
-1
tffont.css
asset/font/tffont.css
+48
-4
pages.json
pages.json
+7
-0
aiTravelDetail.vue
pages/jiuzhai/aiTravelDetail.vue
+1002
-0
api.js
plugin/api.js
+2
-2
rwRequest.js
plugin/rwRequest.js
+136
-0
No files found.
asset/css/flex.css
View file @
9e3ae0b2
...
@@ -25,11 +25,17 @@
...
@@ -25,11 +25,17 @@
margin-top
:
32
rpx
!important
;
margin-top
:
32
rpx
!important
;
}
}
.q-mb-md
{
.q-mb-md
{
margin-bottom
:
32
rpx
;
margin-bottom
:
32
rpx
;
}
}
.q-mr-sm
{
.q-mr-sm
{
margin-right
:
16
rpx
;
margin-right
:
16
rpx
;
}
}
.q-px-md
{
padding
:
0
32
rpx
;
}
.q-mx-md
{
margin
:
0
32
rpx
;
}
.q-ml-sm
{
.q-ml-sm
{
margin-left
:
16
rpx
;
margin-left
:
16
rpx
;
}
}
...
@@ -626,4 +632,10 @@
...
@@ -626,4 +632,10 @@
}
}
.opacity0
{
.opacity0
{
opacity
:
0
;
opacity
:
0
;
}
.window-height
{
height
:
100vh
;
}
.window-width
{
width
:
100vw
;
}
}
\ No newline at end of file
asset/font/tffont.css
View file @
9e3ae0b2
@font-face
{
@font-face
{
font-family
:
"tffont"
;
/* Project id 4816119 */
font-family
:
"tffont"
;
/* Project id 4816119 */
src
:
url('//at.alicdn.com/t/c/font_4816119_
6zzxojucd79.woff2?t=1740378953818
')
format
(
'woff2'
),
src
:
url('//at.alicdn.com/t/c/font_4816119_
2wse58hij19.woff2?t=1750606991860
')
format
(
'woff2'
),
url('//at.alicdn.com/t/c/font_4816119_
6zzxojucd79.woff?t=1740378953818
')
format
(
'woff'
),
url('//at.alicdn.com/t/c/font_4816119_
2wse58hij19.woff?t=1750606991860
')
format
(
'woff'
),
url('//at.alicdn.com/t/c/font_4816119_
6zzxojucd79.ttf?t=1740378953818
')
format
(
'truetype'
);
url('//at.alicdn.com/t/c/font_4816119_
2wse58hij19.ttf?t=1750606991860
')
format
(
'truetype'
);
}
}
.tffont
{
.tffont
{
...
@@ -13,6 +13,50 @@
...
@@ -13,6 +13,50 @@
-moz-osx-font-smoothing
:
grayscale
;
-moz-osx-font-smoothing
:
grayscale
;
}
}
.tffont-dinner
:before
{
content
:
"\e686"
;
}
.tffont-chuang1
:before
{
content
:
"\e604"
;
}
.tffont-lvxing
:before
{
content
:
"\e603"
;
}
.tffont-yuanquan
:before
{
content
:
"\e63e"
;
}
.tffont-niunai
:before
{
content
:
"\e61e"
;
}
.tffont-moonbyueliang
:before
{
content
:
"\e6a0"
;
}
.tffont-jingdian
:before
{
content
:
"\e88f"
;
}
.tffont-roushi-c
:before
{
content
:
"\e602"
;
}
.tffont-175
:before
{
content
:
"\e6bb"
;
}
.tffont-othertraffic
:before
{
content
:
"\e62a"
;
}
.tffont-Sunny
:before
{
content
:
"\e8c7"
;
}
.tffont-checkmark
:before
{
.tffont-checkmark
:before
{
content
:
"\e611"
;
content
:
"\e611"
;
}
}
...
@@ -103,4 +147,4 @@
...
@@ -103,4 +147,4 @@
.tffont-yongjin2
:before
{
.tffont-yongjin2
:before
{
content
:
"\e600"
;
content
:
"\e600"
;
}
}
\ No newline at end of file
pages.json
View file @
9e3ae0b2
...
@@ -682,6 +682,13 @@
...
@@ -682,6 +682,13 @@
},
},
{
{
"path"
:
"videoinfo"
"path"
:
"videoinfo"
},
{
"path"
:
"aiTravelDetail"
,
"style"
:
{
"navigationStyle"
:
"custom"
}
}
}
]
]
},
},
...
...
pages/jiuzhai/aiTravelDetail.vue
0 → 100644
View file @
9e3ae0b2
<
template
>
<scroll-view
class=
"window-height window-width"
@
scroll=
"handleScroll"
scroll-y
:scroll-top=
"scrollTop"
>
<view
class=
"ai-travel-page"
v-if=
"!loading"
>
<view
class=
"bg-blur-container"
id=
"travel_first"
>
<view
class=
"bg-blur"
></view>
<view
class=
"content"
>
<view
class=
"title"
>
行至天光处,
</view>
<view
class=
"title q-mt-md title-indented"
>
坐看云起时.
</view>
<view
class=
"hero-subtitle"
>
<view>
尊驾光临,不胜荣幸。我们以匠心丈量世界,
</view>
<view
class=
"hero-subtitle-line2"
>
为您定制专属旅程,让每一次出发都成为灵魂的礼遇。
</view>
</view>
</view>
</view>
<view
:style=
"
{ 'height': topHeight + 'px', 'opacity': (currentTop >= (screenHeight * 0.6) - topHeight) ? 1 : 0 }"
style="background-color: #25323c;position: fixed;top: 0;left: 0;right: 0;z-index: 9;">
</view>
<view
class=
"sticky-nav-bar row items-center"
:style=
"
{ 'top': topHeight + 'px' }">
<view
v-for=
"menu in menus"
:key=
"menu.id"
:class=
"
{ 'active': activeMenu === menu.id }"
class="col text-center relative" @click="handleMenuClick(menu)">
{{
menu
.
name
}}
</view>
</view>
<view
class=
"main-content-wrapper q-mt-md"
>
<view
class=
"tag"
>
请您开启:
</view>
<view
class=
"trip-title q-mt-sm"
>
{{
travel
.
title
}}
</view>
<view
class=
"travel-demand-quote"
>
<view
class=
"travel-demand-title"
>
出行需求:
</view>
<view
v-if=
"require && require.summaryArray"
>
<!--
{{
require
.
summary
}}
-->
<view
v-for=
"(item, i) in require.summaryArray"
:key=
"i"
>
{{
item
}}
</view>
</view>
</view>
</view>
<view
class=
"travel-ai-title q-mx-md"
>
设计特色
</view>
<view
class=
"feature-list q-px-md q-mt-md text-sm"
>
<template
v-if=
"travel.recommendReason"
>
<view
v-for=
"(item, i) in travel.recommendReason.split('\n')"
:key=
"i"
>
{{
item
}}
</view>
</
template
>
</view>
<view
class=
"section-container q-px-md"
id=
"travel_second"
>
<view
class=
"section-title"
>
<span>
02
</span>
<span
class=
"q-ml-md"
>
行程
</span>
<span
class=
"text-gold"
>
规划
</span>
</view>
<view
class=
"section-subtitle"
>
Trip Agenda
</view>
<view
class=
"trip-agenda-box"
>
<view
class=
"sample-day row items-center"
v-for=
"(item, i) in travel.days"
:key=
"i"
>
<view
class=
"day-num"
>
D{{ item.orderNum }}
</view>
<view
class=
"col q-ml-md"
>
<view
class=
"detail-title"
>
<text
class=
"q-mr-sm"
v-for=
"(city, j) in item.cities"
:key=
"j"
>
{{ city }}
</text>
</view>
<view
class=
"detail-list"
>
<block
v-for=
"(attraction, j) in item.attractions"
:key=
"j"
>
<text>
{{ attraction.name }}
</text>
<u-icon
name=
"arrow"
size=
"20"
color=
"#12121299"
class=
"detail-arrow"
v-if=
"j < item.attractions.length - 1"
></u-icon>
</block>
</view>
</view>
</view>
</view>
</view>
<view
class=
"section-container q-px-md"
id=
"travel_third"
>
<view
class=
"section-title"
>
<span>
03
</span>
<span
class=
"q-ml-md"
>
每日
</span>
<span
class=
"text-gold"
>
行程
</span>
</view>
<view
class=
"section-subtitle"
>
Daily Itinerary
</view>
<view
class=
"daily-itinerary-box"
style=
"padding-top: 30px;"
>
<view
class=
"daily-itinerary-item"
v-for=
"(item, i) in travel.days"
:key=
"i"
>
<view
class=
"row items-center"
style=
"background-color: #121212;border-radius: 20rpx;padding:20rpx;"
>
<view
class=
"title-num q-mr-md"
>
D{{ item.orderNum }}
</view>
<view
class=
"title-content col"
>
<view
class=
""
>
{{ item.title }}
</view>
<view
style=
"opacity: .8; font-size:26rpx ;"
>
<text
class=
"q-mr-sm"
v-for=
"(city, j) in item.cities"
:key=
"j"
>
{{ city }}
</text>
</view>
</view>
</view>
<view
style=
"height: 40px;"
></view>
<!-- <view class="traff">
<view class="icon-box">
<u-icon name='othertraffic' custom-prefix="tffont" color="#fff" size="40"
style="display: inline-block;"></u-icon>
</view>
<view class="row items-center">
<view style="width: 30px; text-align: center;">
<u-icon name='yuanquan' custom-prefix="tffont" color="#12121266" size="40"
style="display: inline-block;"></u-icon>
</view>
<view class="col q-ml-md">
<view class="text-gold">
成都
</view>
<view style="font-size: 18px;color: #121212;line-height: 1;padding: 10rpx 0;">
成都天府国际机场
</view>
<view style="font-size: 12px;color: #12121266;">
出发时间:08:23
</view>
</view>
</view>
<view class="row items-center">
<view style="height: 86px;">
<view class="relative"
style="height: 100%; width: 30px;text-align: center;line-height: 86px;">
<u-icon name='qianwang' custom-prefix="tffont" color="#12121266" size="16"
style="transform: rotate(90deg) scaleY(-1);margin-left: -8px;"></u-icon>
<view
style="background:#FFF;width: 30px;height: 30px;border:3px solid #12121266;border-radius: 30px;position: absolute;top: 50%;left: 0;transform: translateY(-50%);line-height: 30px;text-align: center;">
<u-icon name='lvxing' custom-prefix="tffont" color="#12121266" size="32"
style="transform: scaleY(-1);display: inline-block;margin-top: -12px;"></u-icon>
</view>
</view>
</view>
<view class="col q-ml-md">
<view style="font-size: 18px;color: #121212;line-height: 1;padding: 10rpx 0;">
CA2351
</view>
<view style="font-size: 12px;color: #12121266;">
用时: 3小时58分
</view>
</view>
</view>
<view class="row items-center">
<view style="width: 30px; text-align: center;">
<u-icon name='dingwei' custom-prefix="tffont" color="#12121266" size="40"
style="display: inline-block;"></u-icon>
</view>
<view class="col q-ml-md">
<view class="text-gold">
成都
</view>
<view style="font-size: 18px;color: #121212;line-height: 1;padding: 10rpx 0;">
成都天府国际机场
</view>
<view style="font-size: 12px;color: #12121266;">
出发时间:08:23
</view>
</view>
</view>
</view> -->
<!-- <view class="split-line"></view> -->
<
template
v-if=
"i > 0 && travel.days[i - 1].hotels && travel.days[i - 1].hotels.length > 0"
>
<view
class=
"hotel"
>
<view
class=
"icon-box icon-box-sum"
>
<!--
<u-icon
name=
'moonbyueliang'
custom-prefix=
"tffont"
color=
"#fff"
size=
"40"
style=
"display: inline-block;"
></u-icon>
-->
<u-icon
name=
'Sunny'
custom-prefix=
"tffont"
color=
"#fff"
size=
"40"
style=
"display: inline-block;"
></u-icon>
</view>
<image
:src=
"travel.days[i - 1].hotels[0].images"
class=
"hotel-image"
mode=
"aspectFill"
v-if=
"travel.days[i - 1].hotels[0].images"
></image>
<view
v-else
class=
"hotel-image"
style=
"background-color: #12121266;"
></view>
<view
class=
"hotel-info"
>
<view
class=
"hotel-name"
>
<u-icon
name=
'chuang1'
custom-prefix=
"tffont"
color=
"#121212CC"
size=
"40"
style=
"display: inline-block;"
></u-icon>
<text
class=
"q-ml-sm"
>
{{
travel
.
days
[
i
-
1
].
hotels
[
0
].
name
}}
</text>
</view>
<view
class=
"hotel-desc"
>
{{
travel
.
days
[
i
-
1
].
hotels
[
0
].
description
}}
</view>
<!--
<view
class=
"text-center"
style=
"margin-top: 20px;"
>
<view
class=
"expense"
@
click=
"handleShowMore(i, travel.days[i - 1].hotels[0].id)"
>
{{
showObject
.
day
==
i
&&
showObject
.
id
==
travel
.
days
[
i
-
1
].
hotels
[
0
].
id
?
'点击收起'
:
'点击展开详情'
}}
</view>
</view>
-->
</view>
</view>
<view
class=
"split-line"
></view>
</
template
>
<
template
v-for=
"(scenicspot, scenIndex) in item.attractions"
>
<view
class=
"scenicspot"
:key=
"scenIndex"
>
<view
class=
"icon-box"
>
{{
scenIndex
+
1
}}
</view>
<image
:src=
"scenicspot.images"
class=
"scenicspot-image"
mode=
"aspectFill"
v-if=
"scenicspot.images"
>
</image>
<view
v-else
class=
"scenicspot-image"
style=
"background-color: #12121266;"
></view>
<view
class=
"scenicspot-info"
>
<view
class=
"scenicspot-name"
>
<u-icon
name=
'jingdian'
custom-prefix=
"tffont"
color=
"#C5A33E"
size=
"40"
style=
"display: inline-block;"
></u-icon>
<text
class=
"q-ml-sm"
>
{{
scenicspot
.
name
}}
</text>
</view>
<view
class=
"scenicspot-desc"
>
{{
scenicspot
.
description
}}
</view>
<!--
<view
class=
"text-center"
style=
"margin-top: 20px;"
>
<view
class=
"expense"
@
click=
"handleShowMore(i,scenIndex)"
>
{{
showObject
.
day
==
i
&&
showObject
.
id
==
scenIndex
?
'点击收起'
:
'点击展开详情'
}}
</view>
</view>
-->
</view>
</view>
<view
class=
"split-line"
></view>
</
template
>
<
template
v-if=
"item.hotels && item.hotels.length > 0"
>
<view
class=
"hotel"
>
<view
class=
"icon-box"
>
<u-icon
name=
'moonbyueliang'
custom-prefix=
"tffont"
color=
"#fff"
size=
"40"
style=
"display: inline-block;"
></u-icon>
</view>
<image
:src=
"item.hotels[0].images"
class=
"hotel-image"
mode=
"aspectFill"
v-if=
"item.hotels[0].images"
></image>
<view
v-else
class=
"hotel-image"
style=
"background-color: #12121266;"
></view>
<view
class=
"hotel-info"
>
<view
class=
"hotel-name"
>
<u-icon
name=
'chuang1'
custom-prefix=
"tffont"
color=
"#121212CC"
size=
"40"
style=
"display: inline-block;"
></u-icon>
<text
class=
"q-ml-sm"
>
{{
item
.
hotels
[
0
].
name
}}
</text>
</view>
<view
class=
"hotel-desc"
>
{{
item
.
hotels
[
0
].
description
}}
</view>
<!--
<view
class=
"text-center"
style=
"margin-top: 20px;"
>
<view
class=
"expense"
@
click=
"handleShowMore(i, item.hotels[0].id)"
>
{{
showObject
.
day
==
i
&&
showObject
.
id
==
item
.
hotels
[
0
].
id
?
'点击收起'
:
'点击展开详情'
}}
</view>
</view>
-->
</view>
</view>
</
template
>
<view
class=
"split-line"
></view>
<view
class=
"dinner"
>
<view
class=
"icon-box"
>
<u-icon
name=
'dinner'
custom-prefix=
"tffont"
color=
"#fff"
size=
"40"
style=
"display: inline-block;"
></u-icon>
</view>
<view
class=
"dinner-info row items-center"
>
<u-icon
name=
'niunai'
custom-prefix=
"tffont"
color=
"#12121266"
size=
"30"
></u-icon>
<text
style=
"margin:0 10rpx;"
>
早餐
</text>
<view
class=
"dinner-name"
>
{{ item.caterings.find(x=>x.type=='早餐')?item.caterings.find(x=>x.type=='早餐').name:'敬请自理' }}
</view>
</view>
<view
class=
"dinner-info row items-center"
>
<u-icon
name=
'roushi-c'
custom-prefix=
"tffont"
color=
"#12121266"
size=
"30"
></u-icon>
<text
style=
"margin:0 10rpx;"
>
午餐
</text>
<view
class=
"dinner-name"
>
{{ item.caterings.find(x=>x.type=='午餐')?item.caterings.find(x=>x.type=='午餐').name:'敬请自理' }}
</view>
</view>
<view
class=
"dinner-info row items-center"
>
<u-icon
name=
'175'
custom-prefix=
"tffont"
color=
"#12121266"
size=
"30"
></u-icon>
<text
style=
"margin:0 10rpx;"
>
晚餐
</text>
<view
class=
"dinner-name"
>
{{ item.caterings.find(x=>x.type=='晚餐')?item.caterings.find(x=>x.type=='晚餐').name:'敬请自理' }}
</view>
</view>
</view>
</view>
</view>
</view>
<view
class=
"section-container q-px-md"
id=
"travel_fourth"
>
<view
class=
"section-title"
>
<span>
04
</span>
<span
class=
"q-ml-md"
>
费用
</span>
<span
class=
"text-gold"
>
说明
</span>
</view>
<view
class=
"section-subtitle"
>
Cost Breakdown
</view>
<view
class=
"travel-ai-title"
>
费用包含
</view>
<view
class=
"include"
>
<view
class=
"include-content"
>
<view
v-for=
"(item,index) in travel.include.split('\n')"
:key=
"index"
>
{{ item }}
</view>
</view>
</view>
<view
class=
"travel-ai-title"
>
费用不含
</view>
<view
class=
"include"
>
<view
class=
"include-content"
>
<view
v-for=
"(item,index) in travel.notInclude.split('\n')"
:key=
"index"
>
{{ item }}
</view>
</view>
</view>
</view>
<view
class=
"spacer"
></view>
</view>
<view
class=
"bg-blur-container"
style=
"height: 100vh;"
v-else
>
<view
class=
"bg-blur"
></view>
<view
class=
"content"
>
<view
class=
"title"
>
行至天光处,
</view>
<view
class=
"title q-mt-md title-indented"
>
坐看云起时.
</view>
<view
class=
"hero-subtitle"
>
<view>
尊驾光临,不胜荣幸。我们以匠心丈量世界,
</view>
<view
class=
"hero-subtitle-line2"
>
为您定制专属旅程,让每一次出发都成为灵魂的礼遇。
</view>
</view>
</view>
</view>
</scroll-view>
</template>
<
script
>
import
http
from
'@/plugin/rwRequest'
export
default
{
data
()
{
return
{
topHeight
:
0
,
screenHeight
:
0
,
currentTop
:
0
,
menus
:
[
{
id
:
1
,
name
:
'行程亮点'
,
scrollId
:
'travel_first'
},
{
id
:
2
,
name
:
'行程规划'
,
scrollId
:
'travel_second'
},
{
id
:
3
,
name
:
'每日行程'
,
scrollId
:
'travel_third'
},
{
id
:
4
,
name
:
'费用说明'
,
scrollId
:
'travel_fourth'
}
],
activeMenu
:
1
,
scrollId
:
''
,
sectionTops
:
[],
isClickScrolling
:
false
,
scrollTimeout
:
null
,
scrollTop
:
0
,
travelId
:
''
,
travel
:
{},
require
:
null
,
cities
:
[],
showObject
:
{
day
:
0
,
id
:
''
},
loading
:
true
}
},
onLoad
(
options
)
{
const
systemInfo
=
uni
.
getSystemInfoSync
()
this
.
topHeight
=
this
.
getTopSafeArea
(
systemInfo
)
this
.
screenHeight
=
systemInfo
.
screenHeight
if
(
options
.
id
)
{
this
.
travelId
=
options
.
id
this
.
getTravelDetail
()
}
},
onReady
()
{
},
methods
:
{
handleShowMore
(
day
,
id
)
{
if
(
day
==
this
.
showObject
.
day
&&
id
==
this
.
showObject
.
id
)
{
this
.
showObject
.
day
=
-
1
this
.
showObject
.
id
=
''
}
else
{
this
.
showObject
.
day
=
day
this
.
showObject
.
id
=
id
}
},
getTravelDetail
()
{
http
.
get
(
'/travel/'
+
this
.
travelId
,
{},
{
loading
:
true
}).
then
(
res
=>
{
this
.
travel
=
res
this
.
resolveCitiesHandler
()
this
.
getTravelRequire
()
this
.
loading
=
false
console
.
log
(
this
.
cities
)
this
.
$nextTick
(()
=>
{
this
.
calculateSectionTops
();
})
})
},
getTravelRequire
()
{
http
.
get
(
'/requirement/'
+
this
.
travel
.
requireId
,
{},
{
loading
:
true
}).
then
(
res
=>
{
console
.
log
(
res
)
this
.
require
=
res
this
.
require
.
summaryArray
=
this
.
require
.
summary
.
split
(
'
\
n'
)
//console.log(this.require.summary.split('\n'))
})
},
getTopSafeArea
(
systemInfo
)
{
const
isIOS
=
systemInfo
.
platform
===
'ios'
let
menuButtonInfo
=
{}
try
{
menuButtonInfo
=
uni
.
getMenuButtonBoundingClientRect
()
}
catch
(
e
)
{
console
.
warn
(
'非微信小程序环境,使用默认状态栏高度'
)
}
let
navBarHeight
=
0
if
(
menuButtonInfo
.
top
)
{
navBarHeight
=
menuButtonInfo
.
top
+
menuButtonInfo
.
height
+
(
menuButtonInfo
.
top
-
systemInfo
.
statusBarHeight
)
}
else
{
navBarHeight
=
isIOS
?
44
:
48
}
return
systemInfo
.
statusBarHeight
+
(
isIOS
?
40
:
44
)
// + navBarHeight
},
handleScroll
(
e
)
{
this
.
currentTop
=
e
.
detail
.
scrollTop
if
(
this
.
isClickScrolling
)
{
return
;
}
const
buffer
=
this
.
topHeight
+
20
;
let
currentActiveMenu
=
this
.
activeMenu
;
for
(
let
i
=
this
.
sectionTops
.
length
-
1
;
i
>=
0
;
i
--
)
{
const
section
=
this
.
sectionTops
[
i
];
if
(
this
.
currentTop
>=
section
.
top
-
buffer
)
{
currentActiveMenu
=
section
.
id
;
break
;
}
}
if
(
this
.
activeMenu
!==
currentActiveMenu
)
{
this
.
activeMenu
=
currentActiveMenu
;
}
},
handleMenuClick
(
menu
)
{
this
.
activeMenu
=
menu
.
id
this
.
isClickScrolling
=
true
;
this
.
scrollTop
=
this
.
sectionTops
.
find
(
s
=>
s
.
id
===
menu
.
id
).
top
clearTimeout
(
this
.
scrollTimeout
);
this
.
scrollTimeout
=
setTimeout
(()
=>
{
this
.
isClickScrolling
=
false
;
},
400
);
},
calculateSectionTops
()
{
const
that
=
this
const
query
=
uni
.
createSelectorQuery
().
in
(
this
);
this
.
menus
.
forEach
(
menu
=>
{
query
.
select
(
'#'
+
menu
.
scrollId
).
boundingClientRect
();
});
query
.
exec
(
res
=>
{
if
(
Array
.
isArray
(
res
)
&&
res
.
every
(
item
=>
item
))
{
this
.
sectionTops
=
res
.
map
((
rect
,
index
)
=>
({
id
:
this
.
menus
[
index
].
id
,
top
:
rect
.
top
-
50
-
that
.
topHeight
}));
}
});
},
resolveCitiesHandler
()
{
this
.
travel
.
days
=
this
.
travel
.
days
.
sort
((
a
,
b
)
=>
a
.
orderNum
-
b
.
orderNum
)
this
.
cities
=
[];
this
.
travel
.
days
.
forEach
(
x
=>
{
x
.
cities
=
[];
const
departures
=
x
.
traffics
.
map
(
y
=>
y
.
departure
)
const
destinations
=
x
.
traffics
.
map
(
y
=>
y
.
destination
)
const
attractionsCities
=
x
.
attractions
.
map
(
y
=>
y
.
city
)
const
cateringsCities
=
x
.
caterings
.
map
(
y
=>
y
.
city
)
const
hotelsCities
=
x
.
hotels
.
map
(
y
=>
y
.
city
)
let
temp
=
[...
new
Set
([...
departures
,
...
destinations
,
...
attractionsCities
,
...
cateringsCities
,
...
hotelsCities
])]
temp
=
temp
.
filter
(
y
=>
y
!==
null
&&
y
!==
undefined
&&
y
!==
''
&&
!
y
.
includes
(
'实际'
)
&&
!
y
.
includes
(
'周边'
)
&&
!
y
.
includes
(
'或'
))
temp
=
temp
.
map
(
y
=>
{
y
=
y
.
replace
(
'省'
,
''
).
replace
(
'市'
,
''
).
replace
(
'区'
,
''
).
replace
(
'县'
,
''
)
return
y
})
x
.
cities
=
[...
new
Set
(
temp
)]
this
.
cities
=
[...
new
Set
([...
this
.
cities
,
...
x
.
cities
])]
});
},
}
}
</
script
>
<
style
lang=
"scss"
>
@import
url("@/asset/css/flex.css")
;
@font-face
{
font-family
:
'SJhuazhaozhong'
;
src
:
url('https://im.oytour.com/tripfont/687060f51259482db1ca519ef285541d.woff')
format
(
'woff'
);
}
.ai-travel-page
{
background-color
:
#f5f5f5
;
}
.bg-blur-container
{
position
:
relative
;
height
:
60vh
;
width
:
100vw
;
overflow
:
hidden
;
margin
:
0
;
padding
:
0
;
box-sizing
:
border-box
;
}
.bg-blur
{
position
:
absolute
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
0
;
width
:
100%
;
height
:
100%
;
background-image
:
url('https://viitto-1301420277.cos.ap-chengdu.myqcloud.com/Upload/Goods/638861400391621664.jpeg')
;
background-size
:
cover
;
background-position
:
center
;
z-index
:
1
;
margin
:
0
;
padding
:
0
;
box-sizing
:
border-box
;
}
.content
{
position
:
relative
;
z-index
:
2
;
margin-top
:
70%
;
padding
:
0
40rpx
;
opacity
:
0
.8
;
height
:
30%
;
}
.content
.title
{
font-size
:
60rpx
;
font-weight
:
bold
;
background
:
linear-gradient
(
0deg
,
rgb
(
255
,
243
,
183
)
0%
,
14%
,
rgb
(
253
,
223
,
153
)
28%
,
45%
,
rgb
(
247
,
205
,
131
)
62%
,
81%
,
rgb
(
253
,
251
,
213
))
center
center
no-repeat
fixed
rgb
(
255
,
255
,
255
);
opacity
:
1
;
line-height
:
1
;
letter-spacing
:
0px
;
color
:
rgb
(
247
,
205
,
131
);
writing-mode
:
horizontal-tb
;
background-clip
:
text
!
important
;
font-family
:
SJhuazhaozhong
;
text-shadow
:
0
0
10rpx
#000
;
}
.title-indented
{
text-indent
:
110rpx
;
}
.hero-subtitle
{
font-size
:
28rpx
;
color
:
#fff
;
text-shadow
:
0
0
10rpx
#000
;
margin-top
:
40rpx
;
}
.hero-subtitle-line2
{
margin-top
:
20rpx
;
line-height
:
52rpx
;
}
.sticky-nav-bar
{
background-color
:
#25323c
;
color
:
#b8c1c8
;
padding
:
30rpx
0
;
position
:
sticky
;
left
:
0
;
right
:
0
;
z-index
:
9
;
}
.main-content-wrapper
{
padding
:
0
32rpx
;
}
.tag
{
display
:
inline-block
;
border-radius
:
10rpx
;
padding
:
6rpx
12rpx
;
font-size
:
24rpx
;
background-color
:
#121212
;
color
:
#C5A33E
;
}
.trip-title
{
font-size
:
36rpx
;
font-weight
:
800
;
color
:
#232323
;
}
.travel-demand-quote
{
position
:
relative
;
font-size
:
28rpx
;
color
:
#333
;
line-height
:
1
.7
;
padding
:
20rpx
;
padding-left
:
60rpx
;
margin
:
40rpx
0
;
background
:
#eee
;
border-radius
:
20rpx
;
box-shadow
:
none
;
}
.travel-ai-title
{
padding-left
:
40rpx
;
font-size
:
32rpx
;
font-weight
:
bold
;
position
:
relative
;
margin-top
:
40px
;
}
.text-gold
{
color
:
#C5A33E
!
important
;
}
.
travel-ai-title
:
:
before
{
display
:
block
;
content
:
" "
;
width
:
8rpx
;
top
:
0
;
left
:
0
;
bottom
:
0
;
background-color
:
#C5A33E
;
border-radius
:
4rpx
;
position
:
absolute
;
}
.
travel-demand-quote
:
:
before
{
content
:
"“"
;
position
:
absolute
;
left
:
0
;
top
:
-10rpx
;
font-size
:
80rpx
;
color
:
#d0d0d0
;
font-family
:
serif
;
line-height
:
1
;
z-index
:
1
;
}
.travel-demand-title
{
font-weight
:
bold
;
margin-bottom
:
10rpx
;
font-size
:
30rpx
;
color
:
#222
;
}
.feature-list
{
line-height
:
1
.8
;
}
.section-container
{
margin-top
:
160rpx
;
}
.section-title
{
font-size
:
48rpx
;
color
:
#121212
;
font-weight
:
bold
;
}
.section-subtitle
{
padding-left
:
48px
;
font-size
:
12px
;
color
:
#121212
66
;
}
.trip-agenda-box
{
margin-top
:
80rpx
;
background-color
:
#FFF
;
box-shadow
:
0
0
10px
#000000
11
;
border-radius
:
20rpx
;
}
.sample-day
{
padding
:
45rpx
30rpx
;
border-bottom
:
1px
solid
#121212
11
;
}
.sample-day
:last-child
{
border-bottom
:
none
;
}
.sample-day
.day-num
{
width
:
60rpx
;
height
:
60rpx
;
border-radius
:
60rpx
;
line-height
:
60rpx
;
background-color
:
#C5A33E
66
;
color
:
#C5A33E
;
font-size
:
30rpx
;
font-weight
:
bold
;
text-align
:
center
!
important
;
}
.sample-day
.detail-title
{
font-size
:
28rpx
;
line-height
:
1
;
color
:
#121212
;
margin-bottom
:
10rpx
;
}
.sample-day
.detail-list
{
font-size
:
24rpx
;
color
:
#121212
99
;
flex-wrap
:
wrap
;
}
.detail-arrow
{
margin
:
0
10rpx
;
display
:
inline-block
;
}
.spacer
{
height
:
40px
;
}
.sticky-nav-bar
.active
{
color
:
#C5A33E
!
important
;
}
.relative
{
position
:
relative
;
}
.
sticky-nav-bar
.
active
:
:
after
{
content
:
" "
;
display
:
block
;
width
:
8px
;
height
:
8px
;
background-color
:
#C5A33E
;
position
:
absolute
;
bottom
:
-15px
;
left
:
50%
;
transform
:
translateX
(
-50%
);
border-radius
:
8px
;
}
.
sticky-nav-bar
.
active
:
:
before
{
content
:
" "
;
display
:
block
;
height
:
4px
;
background-color
:
#C5A33E
;
position
:
absolute
;
bottom
:
-15px
;
left
:
30%
;
right
:
30%
;
}
.daily-itinerary-item
{
margin-top
:
40rpx
;
padding-bottom
:
40px
;
.title-num
{
font-size
:
40rpx
;
color
:
#C5A33E
;
}
.title-content
{
margin-left
:
15px
;
color
:
#fff
!
important
;
font-size
:
28rpx
;
}
.traff
{
padding
:
30rpx
;
border-radius
:
20rpx
;
border
:
1px
solid
#121212
11
;
position
:
relative
;
padding-top
:
50rpx
;
.icon-box
{
width
:
80rpx
;
height
:
80rpx
;
border-radius
:
80rpx
;
position
:
absolute
;
top
:
-20px
;
left
:
10px
;
background-color
:
#121212
;
color
:
#fff
;
text-align
:
center
;
line-height
:
80rpx
;
}
}
.hotel
{
border-radius
:
20rpx
;
position
:
relative
;
.icon-box
{
width
:
80rpx
;
height
:
80rpx
;
border-radius
:
80rpx
;
position
:
absolute
;
top
:
-20px
;
left
:
10px
;
background-color
:
#121212
;
color
:
#fff
;
text-align
:
center
;
line-height
:
80rpx
;
z-index
:
3
;
}
.icon-box-sum
{
background-color
:
#C5A33E
!
important
;
}
.hotel-image
{
width
:
100%
;
height
:
150px
;
border-top-left-radius
:
20rpx
;
border-top-right-radius
:
20rpx
;
}
.hotel-info
{
padding
:
20rpx
;
background-color
:
#FFF
;
border-bottom-left-radius
:
20rpx
;
border-bottom-right-radius
:
20rpx
;
border
:
1px
solid
#121212
11
;
border-top
:
none
;
.hotel-name
{
color
:
#121212
CC
;
font-weight
:
bold
;
font-size
:
22px
;
}
.hotel-desc
{
font-size
:
12px
;
color
:
#121212
66
;
margin-top
:
5px
;
}
.hotel-desc-overflow
{
text-overflow
:
ellipsis
;
overflow
:
hidden
;
-webkit-line-clamp
:
3
;
-webkit-box-orient
:
vertical
;
display
:
-
webkit-box
;
}
}
}
.scenicspot
{
border-radius
:
20rpx
;
position
:
relative
;
.icon-box
{
width
:
80rpx
;
height
:
80rpx
;
border-radius
:
80rpx
;
position
:
absolute
;
top
:
-20px
;
left
:
10px
;
background-color
:
#C5A33E
;
color
:
#fff
;
text-align
:
center
;
line-height
:
80rpx
;
z-index
:
3
;
font-size
:
40rpx
;
}
.scenicspot-image
{
width
:
100%
;
height
:
150px
;
border-top-left-radius
:
20rpx
;
border-top-right-radius
:
20rpx
;
}
.scenicspot-info
{
padding
:
20rpx
;
background-color
:
#FFF
;
border-bottom-left-radius
:
20rpx
;
border-bottom-right-radius
:
20rpx
;
border
:
1px
solid
#121212
11
;
border-top
:
none
;
.scenicspot-name
{
color
:
#121212
CC
;
font-weight
:
bold
;
font-size
:
22px
;
color
:
#C5A33E
;
}
.scenicspot-desc
{
font-size
:
12px
;
color
:
#121212
66
;
margin-top
:
5px
;
}
.scenicspot-desc-overflow
{
text-overflow
:
ellipsis
;
overflow
:
hidden
;
-webkit-line-clamp
:
3
;
-webkit-box-orient
:
vertical
;
display
:
-
webkit-box
;
}
}
}
.dinner
{
border-radius
:
20rpx
;
position
:
relative
;
background-color
:
#121212
12
;
padding
:
20px
;
.icon-box
{
width
:
80rpx
;
height
:
80rpx
;
border-radius
:
80rpx
;
position
:
absolute
;
top
:
-20px
;
left
:
10px
;
background-color
:
#121212
;
color
:
#fff
;
text-align
:
center
;
line-height
:
80rpx
;
}
.dinner-info
{
font-size
:
24rpx
;
color
:
#121212
66
;
margin-top
:
15px
;
.dinner-name
{
font-size
:
24rpx
;
color
:
#121212
;
}
}
}
.expense
{
padding
:
10rpx
20rpx
;
border-radius
:
10rpx
;
border
:
1px
solid
#C5A33E
;
color
:
#C5A33E
;
font-size
:
24rpx
;
display
:
inline-block
;
}
.split-line
{
height
:
40px
;
border-left
:
3px
dashed
#121212
22
;
margin
:
10rpx
29px
;
}
}
.include
{
background-color
:
#121212
05
;
border-radius
:
20rpx
;
padding
:
20rpx
;
margin-top
:
20rpx
;
font-size
:
28rpx
;
color
:
#121212
;
line-height
:
1
.5
;
.include-title
{
// font-weight: bold;
font-size
:
18px
;
margin-bottom
:
10rpx
;
color
:
#C5A33E
;
}
}
</
style
>
\ No newline at end of file
plugin/api.js
View file @
9e3ae0b2
...
@@ -23,8 +23,8 @@ export default {
...
@@ -23,8 +23,8 @@ export default {
install
(
Vue
,
options
)
{
install
(
Vue
,
options
)
{
Vue
.
prototype
.
host
=
"https://wx.weibaoge.cn/web/index.php?_mall_id=1285"
Vue
.
prototype
.
host
=
"https://wx.weibaoge.cn/web/index.php?_mall_id=1285"
// "http://192.168.5.204:8030"
// "http://192.168.5.204:8030"
Vue
.
prototype
.
host2
=
process
.
env
.
NODE_ENV
==
"development"
?
"http
://192.168.5.214:8033
"
:
"https://erpmallapi.oytour.com"
Vue
.
prototype
.
host2
=
process
.
env
.
NODE_ENV
==
"development"
?
"http
s://erpmallapi.oytour.com
"
:
"https://erpmallapi.oytour.com"
Vue
.
prototype
.
host3
=
process
.
env
.
NODE_ENV
==
"development"
?
"http
://192.168.5.214
"
:
"https://reborn.oytour.com"
Vue
.
prototype
.
host3
=
process
.
env
.
NODE_ENV
==
"development"
?
"http
s://reborn.oytour.com
"
:
"https://reborn.oytour.com"
// Vue.prototype.host2 = "https://erpmallapi.oytour.com"
// Vue.prototype.host2 = "https://erpmallapi.oytour.com"
// Vue.prototype.host3 = "https://reborn.oytour.com"
// Vue.prototype.host3 = "https://reborn.oytour.com"
// "http://192.168.5.204:8030":
// "http://192.168.5.204:8030":
...
...
plugin/rwRequest.js
0 → 100644
View file @
9e3ae0b2
// utils/request.js
const
BASE_URL
=
process
.
env
.
NODE_ENV
===
'production'
?
'https://rw.oytour.com/api/app'
:
'https://rw.oytour.com/api/app'
;
const
request
=
(
method
,
url
,
data
=
{},
config
=
{})
=>
{
// 获取用户信息
let
header
=
{
'Accept'
:
'application/json'
,
...
config
.
header
};
try
{
const
userInfoStr
=
uni
.
getStorageSync
(
'userInfo'
);
if
(
userInfoStr
)
{
const
userInfo
=
JSON
.
parse
(
userInfoStr
);
header
[
'Authorization'
]
=
`Bearer
${
userInfo
.
token
}
`
;
}
}
catch
(
e
)
{
console
.
error
(
'获取用户信息失败'
,
e
);
}
return
new
Promise
((
resolve
,
reject
)
=>
{
uni
.
request
({
url
:
BASE_URL
+
url
,
method
:
method
.
toUpperCase
(),
data
,
header
,
timeout
:
config
.
timeout
||
10000
,
success
:
(
res
)
=>
{
if
(
res
.
statusCode
>=
200
&&
res
.
statusCode
<
300
)
{
resolve
(
res
.
data
);
}
else
{
// 处理错误状态码
let
errorMessage
=
'请求失败'
;
switch
(
res
.
statusCode
)
{
case
401
:
errorMessage
=
'未授权,请登录'
;
break
;
case
403
:
errorMessage
=
'拒绝访问'
;
break
;
case
404
:
errorMessage
=
'请求地址不存在'
;
break
;
case
500
:
errorMessage
=
'服务器内部错误'
;
break
;
default
:
errorMessage
=
`请求错误:
${
res
.
statusCode
}
`
;
}
uni
.
showToast
({
title
:
errorMessage
,
icon
:
'none'
,
duration
:
2000
});
reject
(
res
.
data
);
}
},
fail
:
(
err
)
=>
{
let
errorMessage
=
'网络错误'
;
if
(
err
.
errMsg
.
includes
(
'timeout'
))
{
errorMessage
=
'请求超时'
;
}
uni
.
showToast
({
title
:
errorMessage
,
icon
:
'none'
,
duration
:
2000
});
reject
(
err
);
}
});
});
};
// 封装常用方法
const
http
=
{
get
(
url
,
params
=
{},
config
=
{})
{
return
request
(
'GET'
,
url
,
params
,
config
);
},
post
(
url
,
data
=
{},
config
=
{})
{
return
request
(
'POST'
,
url
,
data
,
config
);
},
put
(
url
,
data
=
{},
config
=
{})
{
return
request
(
'PUT'
,
url
,
data
,
config
);
},
delete
(
url
,
data
=
{},
config
=
{})
{
return
request
(
'DELETE'
,
url
,
data
,
config
);
},
// 文件上传
upload
(
url
,
filePath
,
name
=
'file'
,
formData
=
{},
config
=
{})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
// 获取token
let
header
=
{};
try
{
const
userInfoStr
=
uni
.
getStorageSync
(
'userInfo'
);
if
(
userInfoStr
)
{
const
userInfo
=
JSON
.
parse
(
userInfoStr
);
header
[
'Authorization'
]
=
`Bearer
${
userInfo
.
token
}
`
;
}
}
catch
(
e
)
{
console
.
error
(
'获取用户信息失败'
,
e
);
}
uni
.
uploadFile
({
url
:
BASE_URL
+
url
,
filePath
,
name
,
formData
,
header
,
success
:
(
res
)
=>
{
if
(
res
.
statusCode
===
200
)
{
try
{
const
data
=
JSON
.
parse
(
res
.
data
);
resolve
(
data
);
}
catch
(
e
)
{
resolve
(
res
.
data
);
}
}
else
{
reject
(
res
);
}
},
fail
:
(
err
)
=>
{
reject
(
err
);
}
});
});
}
};
export
default
http
;
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment