feat: 规范化页面导航与交互体验,优化多端适配
- 统一定制顶部导航组件,支持沉浸式渐变主题与返回逻辑 - 适配 H5 环境的页面跳转逻辑,避免 reLaunch 导致的闪屏问题 - 重构会员、充值、发布等页面布局,改用 Grid 提升移动端适配 - 优化搜索、收藏、消息等页面交互细节,增加点击反馈 - 统一配置页面导航样式,替换原生导航为自定义组件
这个提交包含在:
@@ -1,7 +1,31 @@
|
||||
<template>
|
||||
<view class="detail fc-page">
|
||||
<!-- 顶部视觉 -->
|
||||
<view class="detail__hero">
|
||||
<!-- 规范化顶部导航 -->
|
||||
<fc-navbar title="详情" theme="gradient" :show-back="true" />
|
||||
|
||||
<!-- 顶部实拍画廊 / 轮播图或分类插画 -->
|
||||
<view v-if="imageUrls.length" class="detail__gallery">
|
||||
<swiper
|
||||
class="detail__swiper"
|
||||
circular
|
||||
:autoplay="imageUrls.length > 1"
|
||||
:interval="4000"
|
||||
:duration="400"
|
||||
@change="onSwiperChange"
|
||||
>
|
||||
<swiper-item v-for="(img, idx) in imageUrls" :key="idx" @click="previewImages(idx)">
|
||||
<image class="detail__swiper-img" :src="img" mode="aspectFill" />
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view v-if="imageUrls.length > 1" class="detail__swiper-badge">
|
||||
<text>{{ activeSwiperIndex + 1 }} / {{ imageUrls.length }}</text>
|
||||
</view>
|
||||
<view class="detail__hero-badges detail__hero-badges--float">
|
||||
<text class="fc-tag detail__badge">{{ post.categoryName }}</text>
|
||||
<text v-if="post.isPaid" class="fc-tag detail__badge detail__badge--paid">置顶推荐</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="detail__hero">
|
||||
<view class="detail__hero-thumb">
|
||||
<image class="detail__hero-img" :src="catIcon()" mode="aspectFit" />
|
||||
</view>
|
||||
@@ -194,8 +218,11 @@ import { fromNow, maskPhone } from '@/common/utils/format.js'
|
||||
import { pay } from '@/common/utils/pay.js'
|
||||
import { useUserStore } from '@/common/store/index.js'
|
||||
import config from '@/common/config/index.js'
|
||||
import FcNavbar from '@/components/fc-navbar/fc-navbar.vue'
|
||||
import { assetUrl } from '@/common/utils/format.js'
|
||||
|
||||
export default {
|
||||
components: { FcNavbar },
|
||||
data() {
|
||||
return {
|
||||
id: 0,
|
||||
@@ -214,6 +241,7 @@ export default {
|
||||
commentText: '',
|
||||
// 支付/提交中:防连点重复下单(余额支付是即时扣款)
|
||||
submitting: false,
|
||||
activeSwiperIndex: 0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -221,6 +249,20 @@ export default {
|
||||
return fromNow(this.post.createdAt)
|
||||
},
|
||||
/** 详情是否带真实坐标(契约新增 lat/lng) */
|
||||
imageUrls() {
|
||||
const list = []
|
||||
if (this.post.media && Array.isArray(this.post.media)) {
|
||||
this.post.media.forEach((m) => {
|
||||
if (typeof m === 'string' && !m.match(/\.(mp4|mov|avi)$/i)) {
|
||||
list.push(assetUrl(m))
|
||||
}
|
||||
})
|
||||
}
|
||||
if (!list.length && this.post.cover) {
|
||||
list.push(assetUrl(this.post.cover))
|
||||
}
|
||||
return list
|
||||
},
|
||||
hasLocation() {
|
||||
return this.post.lat != null && this.post.lng != null
|
||||
},
|
||||
@@ -424,6 +466,51 @@ export default {
|
||||
.detail {
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.detail__gallery {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 480rpx;
|
||||
overflow: hidden;
|
||||
background: #000000;
|
||||
}
|
||||
.detail__swiper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.detail__swiper-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
.detail__swiper-badge {
|
||||
position: absolute;
|
||||
right: 24rpx;
|
||||
bottom: 24rpx;
|
||||
padding: 4rpx 18rpx;
|
||||
border-radius: 999rpx;
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
color: #ffffff;
|
||||
font-size: 22rpx;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
.detail__hero-badges--float {
|
||||
position: absolute;
|
||||
left: 24rpx;
|
||||
bottom: 24rpx;
|
||||
margin-top: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
.detail__content {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.detail__title {
|
||||
word-break: break-all;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.detail__hero {
|
||||
padding: 32rpx 24rpx 0;
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户