index.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. <template>
  2. <view class="container">
  3. <!-- 上半部分:轮播图区域 -->
  4. <view class="top-section">
  5. <swiper class="swiper" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000"
  6. :circular="true" indicator-active-color="#1B64F0" indicator-color="rgba(255, 255, 255, 0.6)"
  7. indicator-class="swiper-indicator" active-class="swiper-indicator-active">
  8. <swiper-item v-for="(item, index) in swiperList" :key="index" @click="handleBannerClick(item)">
  9. <view class="swiper-item">
  10. <image class="swiper-img" :src="item.imageUrl" mode="aspectFill" />
  11. </view>
  12. </swiper-item>
  13. </swiper>
  14. </view>
  15. <view class="search-section">
  16. <view class="search-input-wrapper">
  17. <image class="search-icon" src="@/static/img/search.png" />
  18. <input class="search-input" placeholder="请输入要查询的运单号" placeholder-class="placeholder-style"
  19. @focus="onInputFocus" @blur="onInputBlur" v-model="trackingNumber" />
  20. <view class="search-btn" @click="handleSearch">
  21. 搜索
  22. </view>
  23. </view>
  24. </view>
  25. <view class="btn-container">
  26. <view class="btn-item" @click="handleExpress('1')">
  27. <image class="button-icon" src="/static/img/index-un-time.png" />
  28. <view class="button-right">
  29. <view class="button-title">瑞鲸速达(京东)</view>
  30. <view class="button-desc">下单当日取件</view>
  31. </view>
  32. </view>
  33. <!-- <view class="btn-item" @click="handleExpress('2')">
  34. <image class="button-icon" src="/static/img/index-time.png" />
  35. <view class="button-right">
  36. <view class="button-title">瑞鲸速达(顺丰)</view>
  37. <view class="button-desc">一小时下单取件</view>
  38. </view>
  39. </view> -->
  40. <view class="btn-item" @click="showExpressDialog">
  41. <image class="button-icon" src="/static/img/index-personal.png" />
  42. <view class="button-right">
  43. <view class="button-title">个人寄件</view>
  44. <view class="button-desc">支持顺丰和京东</view>
  45. </view>
  46. </view>
  47. </view>
  48. <!-- 使用 u-popup 弹框组件 -->
  49. <PersonalExpressDialog :visible="showDialog" @update:visible="showDialog = $event"
  50. @select="handleExpressSelect" />
  51. </view>
  52. </template>
  53. <script setup>
  54. import {
  55. ref,
  56. onMounted
  57. } from 'vue'
  58. import {
  59. onShow
  60. } from '@dcloudio/uni-app'
  61. // 导入 u-popup 弹框组件
  62. import PersonalExpressDialog from './components/PersonalExpressDialog.vue'
  63. import {
  64. bannerList
  65. } from '../../api/user'
  66. import {
  67. checkLoginShowModal,
  68. quickLogin
  69. } from "@/utils/util.js";
  70. const showDialog = ref(false)
  71. // 轮播图数据
  72. const swiperList = ref([])
  73. const trackingNumber = ref('')
  74. const isInputFocused = ref(false)
  75. onShow(() => {
  76. getBannerList()
  77. })
  78. const getBannerList = () => {
  79. bannerList().then(res => {
  80. if (res.code == 200) {
  81. swiperList.value = res.data
  82. }
  83. }, {})
  84. }
  85. const showExpressDialog = () => {
  86. console.log('显示个人寄件弹框')
  87. showDialog.value = true
  88. }
  89. const handleExpressSelect = (company) => {
  90. // uni.showToast({
  91. // title: `已选择${company}物流`,
  92. // icon: 'success',
  93. // duration: 1500
  94. // })
  95. }
  96. const handleExpress = async (company) => {
  97. if (!await checkLoginShowModal()) return;
  98. uni.navigateTo({
  99. url: `/pages/order/create_order?product=${company}`
  100. })
  101. }
  102. const handleBannerClick = (item) => {
  103. // if (!item.linkUrl) {
  104. // // uni.showToast({ title: '暂无跳转链接', icon: 'none' });
  105. // return;
  106. // }
  107. // if (item.linkUrl.startsWith('http://') || item.linkUrl.startsWith('https://')) {
  108. // uni.navigateTo({
  109. // url: `/pages/webView/webView?url=${encodeURIComponent(item.linkUrl)}`
  110. // })
  111. // } else {
  112. // uni.showToast({ title: '链接格式不支持', icon: 'none' })
  113. // }
  114. };
  115. const onInputFocus = () => {
  116. isInputFocused.value = true
  117. }
  118. const onInputBlur = () => {
  119. isInputFocused.value = false
  120. }
  121. const handleSearch = async () => {
  122. if (!await checkLoginShowModal()) return;
  123. if (!trackingNumber.value.trim()) {
  124. uni.showToast({
  125. title: '请输入运单号',
  126. icon: 'none'
  127. })
  128. return
  129. }
  130. uni.navigateTo({
  131. url:'/pages/logistics/index?orderNo=' + trackingNumber.value.trim()
  132. })
  133. return
  134. }
  135. </script>
  136. <style lang="scss" scoped>
  137. .container {
  138. display: flex;
  139. flex-direction: column;
  140. height: 100vh;
  141. background-color: #F5F7FA;
  142. }
  143. .top-section {
  144. height: 563rpx;
  145. position: relative;
  146. }
  147. .swiper {
  148. width: 100%;
  149. height: 100%;
  150. position: relative;
  151. }
  152. .swiper-item {
  153. width: 100%;
  154. height: 100%;
  155. position: relative;
  156. }
  157. .swiper-img {
  158. width: 100%;
  159. height: 100%;
  160. object-fit: cover;
  161. }
  162. /* 自定义指示点样式 - 通过定位调整位置 */
  163. /* 方法一:调整整个指示器容器的位置 */
  164. /* 注意:在不同平台可能需要使用不同的选择器 */
  165. /* 微信小程序 */
  166. ::v-deep .wx-swiper-dots {
  167. bottom: 80rpx !important;
  168. /* 调整指示器容器的位置 */
  169. display: flex !important;
  170. justify-content: center !important;
  171. align-items: center !important;
  172. }
  173. /* H5平台 */
  174. ::v-deep .uni-swiper-dots {
  175. bottom: 80rpx !important;
  176. /* 调整指示器容器的位置 */
  177. display: flex !important;
  178. justify-content: center !important;
  179. align-items: center !important;
  180. }
  181. /* 方法二:直接修改指示点样式,通过调整父容器样式 */
  182. .swiper-indicator {
  183. width: 8rpx !important;
  184. height: 8rpx !important;
  185. border-radius: 50% !important;
  186. background: rgba(255, 255, 255, 0.6) !important;
  187. margin: 0 4rpx !important;
  188. }
  189. .swiper-indicator-active {
  190. width: 32rpx !important;
  191. height: 8rpx !important;
  192. background: #1B64F0 !important;
  193. border-radius: 4rpx !important;
  194. }
  195. /* 方法三:如果上述方法都不生效,可以使用绝对定位自定义指示器 */
  196. .custom-indicator {
  197. position: absolute;
  198. left: 0;
  199. right: 0;
  200. bottom: 80rpx;
  201. /* 调整指示器的垂直位置 */
  202. z-index: 10;
  203. display: flex;
  204. justify-content: center;
  205. align-items: center;
  206. }
  207. .custom-indicator-dot {
  208. width: 8rpx;
  209. height: 8rpx;
  210. border-radius: 50%;
  211. background: rgba(255, 255, 255, 0.6);
  212. margin: 0 4rpx;
  213. transition: all 0.3s ease;
  214. }
  215. .custom-indicator-dot.active {
  216. width: 32rpx;
  217. height: 8rpx;
  218. background: #1B64F0;
  219. border-radius: 4rpx;
  220. }
  221. /* 搜索区域 */
  222. .search-section {
  223. position: relative;
  224. top: -40rpx;
  225. width: 100%;
  226. padding: 0 20rpx;
  227. display: flex;
  228. flex-direction: column;
  229. align-items: center;
  230. .search-input-wrapper {
  231. width: 100%;
  232. height: 88rpx;
  233. background: #FFFFFF;
  234. border-radius: 44rpx;
  235. font-size: 28rpx;
  236. color: #333;
  237. border: 4rpx solid #1B64F0;
  238. padding: 6rpx;
  239. display: flex;
  240. justify-content: center;
  241. justify-items: center;
  242. align-items: center;
  243. .search-icon {
  244. width: 40rpx;
  245. height: 40rpx;
  246. margin-left: 18rpx;
  247. }
  248. .search-input {
  249. flex: 1;
  250. margin-left: 8rpx;
  251. margin-right: 8rpx;
  252. }
  253. .placeholder-style {
  254. color: #999999;
  255. }
  256. .search-btn {
  257. width: 160rpx;
  258. height: 76rpx;
  259. background: #1B64F0;
  260. border-radius: 38rpx;
  261. font-weight: 400;
  262. font-size: 32rpx;
  263. color: #FFFFFF;
  264. line-height: 76rpx;
  265. text-align: center;
  266. font-style: normal;
  267. }
  268. }
  269. }
  270. .btn-container {
  271. display: flex;
  272. flex-wrap: wrap;
  273. justify-content: space-between;
  274. padding: 0rpx 20rpx;
  275. .btn-item {
  276. width: 339rpx;
  277. height: 172rpx;
  278. background: #FFFFFF;
  279. box-shadow: 0rpx 4rpx 16rpx 0rpx rgba(27, 100, 240, 0.08), 0rpx 0rpx 8rpx 0rpx rgba(27, 100, 240, 0.08);
  280. border-radius: 32rpx;
  281. border: 2rpx solid #FFFFFF;
  282. display: flex;
  283. justify-content: center;
  284. align-items: center;
  285. padding: 20rpx 0rpx 20rpx 20rpx;
  286. margin-bottom: 32rpx;
  287. .button-icon {
  288. width: 88rpx;
  289. height: 88rpx;
  290. }
  291. .button-right {
  292. display: flex;
  293. flex-direction: column;
  294. flex: 1;
  295. margin-left: 16rpx;
  296. .button-title {
  297. height: 48rpx;
  298. line-height: 48rpx;
  299. font-size: 28rpx;
  300. font-weight: bold;
  301. color: #333;
  302. flex-shrink: 0;
  303. }
  304. .button-desc {
  305. height: 44rpx;
  306. line-height: 44rpx;
  307. font-size: 24rpx;
  308. color: #666;
  309. margin-top: 8rpx;
  310. }
  311. }
  312. }
  313. }
  314. </style>