需求:小程序端代码要同时同步到服务器与 git 远程仓库,此前前端仅存在于本地目录(无 remote,从未推送), 服务器与 gitcode 上只有后端。现并入本仓库,复用现有「push 即部署」链路,一次推送双端落地。 - 新增 uniapp/:小程序端源码全量快照(150 文件 / 1.2M) pages(13 页面) · components(fc-navbar/fc-tabbar/fc-post-card/fc-empty) · common(api·utils·mock·assets·store·config) · static(74 图标 + 3 轮播插画 + LOGO) · docs(01-04 交付文档) · tests(零依赖全链路用例) · tools(图标/主题/轮播配图生成脚本) - 明确排除:AGENTS.md(含后台密码、服务器 root 密码、小程序 AppSecret,切勿入库)、 unpackage/(构建产物,由 uniapp/.gitignore 忽略)、node_modules、.DS_Store、*.log - .gitignore 新增 /uniapp/AGENTS.md 兜底(与根 /AGENTS.md、/fluniapp/ 同一约定) - README.md 增补「本项目结构 + 部署链路」章节,说明 uniapp/ 为源码快照、 小程序真正上线仍需微信开发者工具 cli upload 说明:本次为源码快照,未携带前端本地仓库历史——其历史提交中含 AGENTS.md 凭据, 若做 subtree 合并会把密码永久写入本仓库历史,故采用快照方式。
762 行
19 KiB
Vue
762 行
19 KiB
Vue
<template>
|
||
<view class="detail fc-page">
|
||
<!-- 顶部视觉 -->
|
||
<view class="detail__hero">
|
||
<view class="detail__hero-thumb">
|
||
<image class="detail__hero-img" :src="catIcon()" mode="aspectFit" />
|
||
</view>
|
||
<view class="detail__hero-badges">
|
||
<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 class="fc-card detail__head">
|
||
<text class="detail__title">{{ post.title }}</text>
|
||
<view class="detail__price-row">
|
||
<view class="fc-price">
|
||
<text v-if="post.price > 0" class="fc-price__symbol">¥</text>
|
||
<text v-if="post.price > 0" class="detail__amount">{{ post.price }}</text>
|
||
<text v-if="post.price > 0" class="detail__unit">{{ post.priceUnit }}</text>
|
||
<text v-if="!(post.price > 0)" class="detail__neg">面议</text>
|
||
</view>
|
||
<view class="detail__stats">
|
||
<view class="fc-inline">
|
||
<image class="fc-icon fc-icon--sm" :src="iconUrl('eye')" mode="aspectFit" />
|
||
<text class="detail__stat-num">{{ post.views }}</text>
|
||
</view>
|
||
<view class="fc-inline detail__stat-gap">
|
||
<image class="fc-icon fc-icon--sm" :src="iconUrl('comment-gray')" mode="aspectFit" />
|
||
<text class="detail__stat-num">{{ post.commentCount || 0 }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="detail__meta">
|
||
<text>{{ post.area }} · {{ post.address }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 发布者 -->
|
||
<view class="fc-card detail__publisher">
|
||
<view class="detail__avatar">{{ (post.publisher && post.publisher.name || '同').slice(0, 1) }}</view>
|
||
<view class="detail__publisher-info">
|
||
<view class="detail__publisher-name-row">
|
||
<text class="detail__publisher-name">{{ post.publisher && post.publisher.name }}</text>
|
||
<text v-if="post.publisher && post.publisher.verified" class="fc-tag detail__verified">已认证</text>
|
||
</view>
|
||
<text class="detail__publisher-sub">
|
||
{{ post.publisher && post.publisher.isMerchant ? '商家用户' : '个人用户' }} · {{ timeText }}发布
|
||
</text>
|
||
</view>
|
||
<view class="detail__follow" @click="toggleFollow">
|
||
<text>{{ followed ? '已关注' : '+ 关注' }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 内容展示 -->
|
||
<view class="fc-card">
|
||
<text class="detail__section-title">详细描述</text>
|
||
<text class="detail__content">{{ post.content }}</text>
|
||
<view class="detail__tags">
|
||
<text v-for="t in post.tags || []" :key="t" class="fc-tag detail__tag">{{ t }}</text>
|
||
</view>
|
||
<view v-if="post.address" class="detail__map" @click="openMap">
|
||
<view class="detail__map-bg">
|
||
<image class="fc-icon fc-icon--md" :src="iconUrl('home-location')" mode="aspectFit" />
|
||
</view>
|
||
<view class="detail__map-info">
|
||
<text class="detail__map-name">{{ post.address }}</text>
|
||
<text class="detail__map-action">地图导航 ›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 付费查看联系方式 -->
|
||
<view class="fc-card detail__contact">
|
||
<text class="detail__section-title">联系方式</text>
|
||
<view v-if="unlocked" class="detail__contact-inner">
|
||
<view class="detail__contact-row">
|
||
<text class="detail__contact-label">电话</text>
|
||
<text class="detail__contact-value" @click="callPhone">{{ contact.phone }}</text>
|
||
</view>
|
||
<view class="detail__contact-row">
|
||
<text class="detail__contact-label">微信</text>
|
||
<text class="detail__contact-value">{{ contact.wechat }}</text>
|
||
</view>
|
||
<view class="detail__contact-actions">
|
||
<view class="detail__contact-btn" @click="callPhone">
|
||
<image class="fc-icon fc-icon--sm" :src="iconUrl('phone')" mode="aspectFit" />
|
||
<text class="detail__btn-text">拨打电话</text>
|
||
</view>
|
||
<view class="detail__contact-btn detail__contact-btn--ghost" @click="copyWechat">
|
||
<text>复制微信号</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view v-else class="detail__locked">
|
||
<image class="fc-icon fc-icon--xl" :src="iconUrl('lock')" mode="aspectFit" />
|
||
<text class="detail__locked-text">非会员查看完整联系方式需付费或开通会员</text>
|
||
<view class="detail__pay-type">
|
||
<view class="detail__pay-item" :class="{ 'detail__pay-item--active': payType === 'balance' }"
|
||
@click="payType = 'balance'"><text>余额支付</text></view>
|
||
<view class="detail__pay-item" :class="{ 'detail__pay-item--active': payType === 'wxpay' }"
|
||
@click="payType = 'wxpay'"><text>微信支付</text></view>
|
||
</view>
|
||
<view class="detail__locked-actions">
|
||
<view class="detail__locked-btn" @click="payView(payType)"><text>¥2 付费查看</text></view>
|
||
<view class="detail__locked-btn detail__locked-btn--vip" @click="goVip"><text>开通会员免费看</text></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 评价互动 -->
|
||
<view class="fc-card">
|
||
<view class="detail__cmt-head">
|
||
<text class="detail__section-title">用户评价({{ comments.length }})</text>
|
||
<text class="detail__cmt-write" @click="showComment = true">写评价 ›</text>
|
||
</view>
|
||
<view v-for="c in comments" :key="c.id" class="detail__cmt">
|
||
<view class="detail__cmt-top">
|
||
<text class="detail__cmt-user">{{ c.user }}</text>
|
||
<view class="detail__cmt-score">
|
||
<image v-for="n in 5" :key="n" class="fc-icon fc-icon--xs"
|
||
:src="iconUrl(n <= c.score ? 'star' : 'star-o')" mode="aspectFit" />
|
||
</view>
|
||
</view>
|
||
<text class="detail__cmt-content">{{ c.content }}</text>
|
||
<text v-if="c.reply" class="detail__cmt-reply">商家回复:{{ c.reply }}</text>
|
||
</view>
|
||
<text v-if="!comments.length" class="detail__cmt-empty">暂无评价,快来抢沙发~</text>
|
||
</view>
|
||
|
||
<view class="detail__bar-space"></view>
|
||
|
||
<!-- 底部操作栏 -->
|
||
<view class="detail__bar">
|
||
<view class="detail__bar-item" @click="toggleFav">
|
||
<image class="fc-icon fc-icon--md" :src="iconUrl(faved ? 'bar-fav-on' : 'bar-fav')" mode="aspectFit" />
|
||
<text class="detail__bar-text">收藏</text>
|
||
</view>
|
||
<view class="detail__bar-item" @click="onShare">
|
||
<image class="fc-icon fc-icon--md" :src="iconUrl('bar-share')" mode="aspectFit" />
|
||
<text class="detail__bar-text">分享</text>
|
||
</view>
|
||
<view class="detail__bar-item" @click="showPoster = true">
|
||
<image class="fc-icon fc-icon--md" :src="iconUrl('bar-poster')" mode="aspectFit" />
|
||
<text class="detail__bar-text">海报</text>
|
||
</view>
|
||
<view class="detail__bar-main" @click="unlocked ? callPhone() : payView(payType)">
|
||
<text>{{ unlocked ? '立即联系' : '付费查看' }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 写评价弹层 -->
|
||
<view v-if="showComment" class="detail__mask" @click="showComment = false">
|
||
<view class="detail__sheet" @click.stop>
|
||
<text class="detail__sheet-title">发表评价</text>
|
||
<view class="detail__stars">
|
||
<image v-for="n in 5" :key="n" class="detail__star-img"
|
||
:src="iconUrl(n <= score ? 'star' : 'star-o')" mode="aspectFit" @click="score = n" />
|
||
</view>
|
||
<textarea v-model="commentText" class="detail__sheet-input" placeholder="说说你的体验…" maxlength="200" />
|
||
<view class="detail__sheet-btn" @click="submitComment"><text>提交评价</text></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 海报弹层 -->
|
||
<view v-if="showPoster" class="detail__mask" @click="showPoster = false">
|
||
<view class="detail__poster" @click.stop>
|
||
<view class="detail__poster-head">
|
||
<text class="detail__poster-title">{{ post.title }}</text>
|
||
<text class="detail__poster-price">¥{{ post.price > 0 ? post.price : '面议' }}</text>
|
||
</view>
|
||
<text class="detail__poster-tip">长按识别 / 保存海报分享给好友</text>
|
||
<view class="fc-inline detail__poster-qr">
|
||
<image class="fc-icon fc-icon--sm" :src="iconUrl('qrcode')" mode="aspectFit" />
|
||
<text class="detail__poster-qr-text">扫码查看同城详情</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import postApi from '@/common/api/post.js'
|
||
import { iconUrl, categoryIconUrl, loadUiConfig } from '@/common/store/ui.js'
|
||
import { fromNow, maskPhone } from '@/common/utils/format.js'
|
||
import config from '@/common/config/index.js'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
id: 0,
|
||
post: { publisher: {}, tags: [] },
|
||
unlocked: false,
|
||
payType: config.defaultPayType,
|
||
contact: { phone: '', wechat: '' },
|
||
comments: [],
|
||
followed: false,
|
||
faved: false,
|
||
showComment: false,
|
||
showPoster: false,
|
||
score: 5,
|
||
commentText: '',
|
||
}
|
||
},
|
||
computed: {
|
||
timeText() {
|
||
return fromNow(this.post.createdAt)
|
||
},
|
||
},
|
||
onLoad(query) {
|
||
this.id = Number(query.id || 101)
|
||
loadUiConfig()
|
||
this.fetch()
|
||
},
|
||
methods: {
|
||
iconUrl,
|
||
catIcon() {
|
||
return categoryIconUrl(this.post.categoryId)
|
||
},
|
||
async fetch() {
|
||
try {
|
||
const res = await postApi.detail(this.id)
|
||
this.post = res
|
||
this.comments = [
|
||
{ id: 5001, user: '小王同学', score: 5, content: '联系很及时,沟通顺畅。', reply: '' },
|
||
{ id: 5002, user: '果果', score: 4, content: '信息真实,价格合理。', reply: '感谢支持~' },
|
||
]
|
||
this.contact = { phone: maskPhone(res.contact), wechat: '' }
|
||
} catch (e) {
|
||
uni.showToast({ title: '信息加载失败', icon: 'none' })
|
||
}
|
||
},
|
||
async payView(payType) {
|
||
try {
|
||
const res = await postApi.payView(this.id, { payType })
|
||
this.unlocked = true
|
||
this.contact = { phone: res.contact.phone, wechat: res.contact.wechat }
|
||
uni.showToast({ title: '已解锁完整联系方式', icon: 'none' })
|
||
} catch (e) {
|
||
uni.showToast({ title: e.message || '支付失败', icon: 'none' })
|
||
}
|
||
},
|
||
async submitComment() {
|
||
if (!this.commentText.trim()) {
|
||
uni.showToast({ title: '请输入评价内容', icon: 'none' })
|
||
return
|
||
}
|
||
try {
|
||
await postApi.comment(this.id, { score: this.score, content: this.commentText })
|
||
this.comments.unshift({ id: Date.now(), user: '我', score: this.score, content: this.commentText, reply: '' })
|
||
this.commentText = ''
|
||
this.showComment = false
|
||
uni.showToast({ title: '评价成功', icon: 'none' })
|
||
} catch (e) {
|
||
uni.showToast({ title: e.message, icon: 'none' })
|
||
}
|
||
},
|
||
toggleFollow() {
|
||
this.followed = !this.followed
|
||
},
|
||
toggleFav() {
|
||
this.faved = !this.faved
|
||
uni.showToast({ title: this.faved ? '已收藏' : '已取消收藏', icon: 'none' })
|
||
},
|
||
goVip() {
|
||
uni.navigateTo({ url: '/pages/member/index' })
|
||
},
|
||
openMap() {
|
||
uni.openLocation({
|
||
latitude: 26.647,
|
||
longitude: 106.63,
|
||
name: this.post.address,
|
||
address: this.post.area,
|
||
fail: () => uni.showToast({ title: '导航需在小程序内使用', icon: 'none' }),
|
||
})
|
||
},
|
||
callPhone() {
|
||
if (!this.unlocked) return this.payView(this.payType)
|
||
uni.makePhoneCall({ phoneNumber: this.contact.phone })
|
||
},
|
||
copyWechat() {
|
||
uni.setClipboardData({ data: this.contact.wechat })
|
||
uni.showToast({ title: '微信号已复制', icon: 'none' })
|
||
},
|
||
onShare() {
|
||
uni.showToast({ title: '已生成分享链接', icon: 'none' })
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
|
||
|
||
<style lang="scss" scoped>
|
||
.detail {
|
||
padding-bottom: 40rpx;
|
||
}
|
||
.detail__hero {
|
||
padding: 32rpx 24rpx 0;
|
||
}
|
||
.detail__hero-thumb {
|
||
height: 420rpx;
|
||
border-radius: $fc-radius-lg;
|
||
background: $fc-gradient-soft;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
}
|
||
.detail__hero-img {
|
||
width: 240rpx;
|
||
height: 240rpx;
|
||
}
|
||
.detail__hero-badges {
|
||
display: flex;
|
||
margin-top: 20rpx;
|
||
}
|
||
.detail__badge {
|
||
margin-right: 12rpx;
|
||
}
|
||
.detail__badge--paid {
|
||
background: $fc-gradient-warm;
|
||
color: #ffffff;
|
||
}
|
||
.detail__head {
|
||
margin-top: 20rpx;
|
||
}
|
||
.detail__title {
|
||
font-size: $fc-font-title;
|
||
font-weight: 700;
|
||
color: $fc-text;
|
||
line-height: 1.35;
|
||
}
|
||
.detail__price-row {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: space-between;
|
||
margin-top: 20rpx;
|
||
}
|
||
.detail__amount {
|
||
font-size: 48rpx;
|
||
}
|
||
.detail__unit {
|
||
margin-left: 6rpx;
|
||
font-size: $fc-font-xs;
|
||
color: $fc-text-secondary;
|
||
font-weight: 400;
|
||
}
|
||
.detail__neg {
|
||
font-size: 40rpx;
|
||
}
|
||
.detail__stats {
|
||
display: flex;
|
||
font-size: $fc-font-xs;
|
||
color: $fc-text-placeholder;
|
||
}
|
||
.detail__stat-num {
|
||
margin-left: 6rpx;
|
||
font-size: $fc-font-xs;
|
||
color: $fc-text-placeholder;
|
||
}
|
||
.detail__stat-gap {
|
||
margin-left: 18rpx;
|
||
}
|
||
.detail__meta {
|
||
margin-top: 16rpx;
|
||
font-size: $fc-font-sm;
|
||
color: $fc-text-secondary;
|
||
}
|
||
.detail__publisher {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.detail__avatar {
|
||
width: 88rpx;
|
||
height: 88rpx;
|
||
border-radius: 50%;
|
||
background: $fc-gradient-warm;
|
||
color: #ffffff;
|
||
font-size: 36rpx;
|
||
font-weight: 700;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.detail__publisher-info {
|
||
flex: 1;
|
||
margin-left: 20rpx;
|
||
}
|
||
.detail__publisher-name-row {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.detail__publisher-name {
|
||
font-size: $fc-font-lg;
|
||
font-weight: 600;
|
||
color: $fc-text;
|
||
}
|
||
.detail__verified {
|
||
margin-left: 12rpx;
|
||
background: #e9f9ee;
|
||
color: $fc-success;
|
||
}
|
||
.detail__publisher-sub {
|
||
display: block;
|
||
margin-top: 6rpx;
|
||
font-size: $fc-font-xs;
|
||
color: $fc-text-secondary;
|
||
}
|
||
.detail__follow {
|
||
padding: 14rpx 28rpx;
|
||
border-radius: $fc-radius-pill;
|
||
border: 2rpx solid $fc-primary-text;
|
||
color: $fc-primary-text;
|
||
font-size: $fc-font-sm;
|
||
}
|
||
.detail__section-title {
|
||
font-size: $fc-font-lg;
|
||
font-weight: 700;
|
||
color: $fc-text;
|
||
}
|
||
.detail__content {
|
||
display: block;
|
||
margin-top: 18rpx;
|
||
font-size: $fc-font;
|
||
color: $fc-text-regular;
|
||
line-height: 1.7;
|
||
}
|
||
.detail__tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
margin-top: 18rpx;
|
||
}
|
||
.detail__tag {
|
||
margin: 0 12rpx 12rpx 0;
|
||
}
|
||
.detail__map {
|
||
margin-top: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
background: $fc-bg;
|
||
border-radius: $fc-radius;
|
||
padding: 20rpx;
|
||
}
|
||
.detail__map-bg {
|
||
width: 120rpx;
|
||
height: 90rpx;
|
||
border-radius: 12rpx;
|
||
background: linear-gradient(135deg, #d8f1e8, #93d6c2);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.detail__map-pin {
|
||
font-size: 36rpx;
|
||
}
|
||
.detail__map-info {
|
||
flex: 1;
|
||
margin-left: 20rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.detail__map-name {
|
||
font-size: $fc-font;
|
||
color: $fc-text;
|
||
}
|
||
.detail__map-action {
|
||
margin-top: 8rpx;
|
||
font-size: $fc-font-xs;
|
||
color: $fc-primary-text;
|
||
}
|
||
.detail__locked {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 32rpx 0 8rpx;
|
||
}
|
||
.detail__locked-icon {
|
||
font-size: 64rpx;
|
||
}
|
||
.detail__locked-text {
|
||
margin-top: 16rpx;
|
||
font-size: $fc-font-sm;
|
||
color: $fc-text-secondary;
|
||
text-align: center;
|
||
}
|
||
.detail__locked-actions {
|
||
display: flex;
|
||
margin-top: 28rpx;
|
||
}
|
||
/* 支付方式选择(付费查看) */
|
||
.detail__pay-type {
|
||
display: flex;
|
||
margin-top: 24rpx;
|
||
}
|
||
.detail__pay-item {
|
||
min-width: 168rpx;
|
||
height: 66rpx;
|
||
padding: 0 24rpx;
|
||
margin-right: 16rpx;
|
||
border-radius: $fc-radius;
|
||
border: 2rpx solid $fc-border;
|
||
background: $fc-bg;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: $fc-font-sm;
|
||
color: $fc-text-regular;
|
||
&--active {
|
||
border-color: $fc-primary-text;
|
||
background: $fc-primary-lighter;
|
||
color: $fc-primary-text;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
.detail__locked-btn {
|
||
padding: 18rpx 40rpx;
|
||
border-radius: $fc-radius-pill;
|
||
background: $fc-gradient-primary;
|
||
color: $fc-primary-ink;
|
||
font-size: $fc-font-sm;
|
||
font-weight: 600;
|
||
&--vip {
|
||
margin-left: 20rpx;
|
||
background: $fc-gradient-warm;
|
||
}
|
||
}
|
||
.detail__contact-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
height: 80rpx;
|
||
border-bottom: 2rpx solid $fc-border;
|
||
}
|
||
.detail__contact-label {
|
||
font-size: $fc-font;
|
||
color: $fc-text-secondary;
|
||
}
|
||
.detail__contact-value {
|
||
font-size: $fc-font-lg;
|
||
font-weight: 600;
|
||
color: $fc-primary-text;
|
||
}
|
||
.detail__contact-actions {
|
||
display: flex;
|
||
margin-top: 24rpx;
|
||
}
|
||
.detail__contact-btn {
|
||
flex: 1;
|
||
height: 84rpx;
|
||
border-radius: $fc-radius-pill;
|
||
background: $fc-gradient-primary;
|
||
color: $fc-primary-ink;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: $fc-font;
|
||
&--ghost {
|
||
margin-left: 20rpx;
|
||
background: #ffffff;
|
||
border: 2rpx solid $fc-primary-text;
|
||
color: $fc-primary-text;
|
||
}
|
||
}
|
||
.detail__cmt-head {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
.detail__cmt-write {
|
||
font-size: $fc-font-sm;
|
||
color: $fc-primary-text;
|
||
}
|
||
.detail__cmt {
|
||
margin-top: 24rpx;
|
||
padding-top: 20rpx;
|
||
border-top: 2rpx solid $fc-border;
|
||
}
|
||
.detail__cmt-top {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
.detail__cmt-user {
|
||
font-size: $fc-font;
|
||
font-weight: 600;
|
||
color: $fc-text;
|
||
}
|
||
.detail__btn-text {
|
||
margin-left: 10rpx;
|
||
}
|
||
.detail__cmt-score {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.detail__cmt-content {
|
||
display: block;
|
||
margin-top: 12rpx;
|
||
font-size: $fc-font;
|
||
color: $fc-text-regular;
|
||
line-height: 1.6;
|
||
}
|
||
.detail__cmt-reply {
|
||
display: block;
|
||
margin-top: 12rpx;
|
||
padding: 14rpx 20rpx;
|
||
border-radius: $fc-radius-sm;
|
||
background: $fc-bg;
|
||
font-size: $fc-font-sm;
|
||
color: $fc-text-secondary;
|
||
}
|
||
.detail__cmt-empty {
|
||
display: block;
|
||
margin-top: 24rpx;
|
||
text-align: center;
|
||
font-size: $fc-font-sm;
|
||
color: $fc-text-placeholder;
|
||
}
|
||
.detail__bar-space {
|
||
height: 160rpx;
|
||
}
|
||
.detail__bar {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 14rpx 24rpx;
|
||
background: #ffffff;
|
||
border-top: 2rpx solid $fc-border;
|
||
box-shadow: 0 -6rpx 24rpx rgba(4, 48, 30, 0.08);
|
||
}
|
||
.detail__bar-item {
|
||
width: 110rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
.detail__bar-text {
|
||
margin-top: 4rpx;
|
||
font-size: 20rpx;
|
||
color: $fc-text-secondary;
|
||
}
|
||
.detail__bar-main {
|
||
flex: 1;
|
||
height: 88rpx;
|
||
border-radius: $fc-radius-pill;
|
||
background: $fc-gradient-primary;
|
||
color: $fc-primary-ink;
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 8rpx 24rpx rgba(4, 48, 30, 0.3);
|
||
}
|
||
.detail__mask {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
z-index: 200;
|
||
background: rgba(4, 48, 42, 0.5);
|
||
display: flex;
|
||
align-items: flex-end;
|
||
}
|
||
.detail__sheet {
|
||
width: 100%;
|
||
background: #ffffff;
|
||
border-radius: 32rpx 32rpx 0 0;
|
||
padding: 36rpx 32rpx 60rpx;
|
||
}
|
||
.detail__sheet-title {
|
||
display: block;
|
||
text-align: center;
|
||
font-size: $fc-font-lg;
|
||
font-weight: 700;
|
||
}
|
||
.detail__stars {
|
||
display: flex;
|
||
justify-content: center;
|
||
margin: 28rpx 0;
|
||
}
|
||
.detail__star-img {
|
||
width: 56rpx;
|
||
height: 56rpx;
|
||
margin: 0 10rpx;
|
||
}
|
||
.detail__sheet-input {
|
||
width: 100%;
|
||
height: 180rpx;
|
||
background: $fc-bg;
|
||
border-radius: $fc-radius;
|
||
padding: 22rpx 24rpx;
|
||
font-size: $fc-font;
|
||
}
|
||
.detail__sheet-btn {
|
||
margin-top: 28rpx;
|
||
height: 88rpx;
|
||
border-radius: $fc-radius-pill;
|
||
background: $fc-gradient-primary;
|
||
color: $fc-primary-ink;
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.detail__poster {
|
||
width: 100%;
|
||
background: #ffffff;
|
||
border-radius: 32rpx 32rpx 0 0;
|
||
padding: 44rpx 40rpx 60rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
.detail__poster-head {
|
||
width: 100%;
|
||
border-radius: $fc-radius-lg;
|
||
background: $fc-gradient-hero;
|
||
padding: 40rpx 32rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.detail__poster-title {
|
||
color: #ffffff;
|
||
font-size: $fc-font-xl;
|
||
font-weight: 700;
|
||
}
|
||
.detail__poster-price {
|
||
margin-top: 20rpx;
|
||
color: #ffffff;
|
||
font-size: 52rpx;
|
||
font-weight: 700;
|
||
}
|
||
.detail__poster-tip {
|
||
margin-top: 28rpx;
|
||
font-size: $fc-font-sm;
|
||
color: $fc-text-secondary;
|
||
}
|
||
.detail__poster-qr {
|
||
margin-top: 24rpx;
|
||
width: 100%;
|
||
height: 140rpx;
|
||
border-radius: $fc-radius;
|
||
background: $fc-bg;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: $fc-primary-text;
|
||
font-size: $fc-font;
|
||
}
|
||
.detail__poster-qr-text {
|
||
margin-left: 12rpx;
|
||
}
|
||
</style>
|
||
|