优化导览预览与讲解展示层
This commit is contained in:
@@ -2,147 +2,73 @@
|
||||
<GuidePageFrame
|
||||
:active-tab="activeTopTab"
|
||||
variant="static"
|
||||
:show-top-tabs="false"
|
||||
show-back
|
||||
@tab-change="handleTopTabChange"
|
||||
@back="handleBack"
|
||||
>
|
||||
<view class="detail-page" :class="{ 'with-audio-player': showAudioPlayer }">
|
||||
<scroll-view class="content" scroll-y>
|
||||
<view class="detail-hero">
|
||||
<image
|
||||
v-if="heroImage"
|
||||
class="hero-image"
|
||||
:src="heroImage"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-else class="hero-placeholder">
|
||||
<text class="hero-placeholder-text">讲解</text>
|
||||
</view>
|
||||
<view
|
||||
v-if="exhibit.audio.status === 'playable'"
|
||||
class="audio-control"
|
||||
@tap="handlePlayAudio"
|
||||
>
|
||||
<svg v-if="!isPlaying" width="28" height="28" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M8 5V19L19 12L8 5Z" fill="currentColor"/>
|
||||
</svg>
|
||||
<svg v-else width="28" height="28" viewBox="0 0 24 24" fill="none">
|
||||
<rect x="6" y="5" width="4" height="14" rx="1" fill="currentColor"/>
|
||||
<rect x="14" y="5" width="4" height="14" rx="1" fill="currentColor"/>
|
||||
</svg>
|
||||
</view>
|
||||
<view v-else class="audio-status">
|
||||
<text class="audio-status-text">{{ audioStatusText }}</text>
|
||||
</view>
|
||||
<view class="explain-detail-page" :class="{ 'with-audio-player': showAudioPlayer }">
|
||||
<scroll-view class="content" scroll-y :show-scrollbar="false">
|
||||
<image
|
||||
v-if="heroImage"
|
||||
class="hero-image"
|
||||
:src="heroImage"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
|
||||
<view v-else class="hero-placeholder">
|
||||
<text class="hero-placeholder-text">讲解</text>
|
||||
</view>
|
||||
|
||||
<view class="detail-info">
|
||||
<text class="content-type">{{ contentTypeText }}</text>
|
||||
<view class="detail-body">
|
||||
<text class="detail-title">{{ exhibit.title }}</text>
|
||||
<text v-if="exhibit.subtitle" class="detail-subtitle">{{ exhibit.subtitle }}</text>
|
||||
<text v-if="detailMeta" class="detail-meta">{{ detailMeta }}</text>
|
||||
|
||||
<view class="meta-grid">
|
||||
<view class="meta-item">
|
||||
<text class="meta-label">内容类型</text>
|
||||
<text class="meta-value">{{ contentTypeText }}</text>
|
||||
<view
|
||||
v-if="exhibit.audio.status === 'playable'"
|
||||
class="audio-panel"
|
||||
@tap="handlePlayAudio"
|
||||
>
|
||||
<view class="audio-play">
|
||||
<svg v-if="!isPlaying" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M8 5V19L19 12L8 5Z" fill="currentColor"/>
|
||||
</svg>
|
||||
<svg v-else width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<rect x="6" y="5" width="4" height="14" rx="1" fill="currentColor"/>
|
||||
<rect x="14" y="5" width="4" height="14" rx="1" fill="currentColor"/>
|
||||
</svg>
|
||||
</view>
|
||||
<view v-if="exhibit.hallName" class="meta-item">
|
||||
<text class="meta-label">所属展厅</text>
|
||||
<text class="meta-value">{{ exhibit.hallName }}</text>
|
||||
</view>
|
||||
<view v-if="exhibit.floorLabel" class="meta-item">
|
||||
<text class="meta-label">所在楼层</text>
|
||||
<text class="meta-value">{{ exhibit.floorLabel }}</text>
|
||||
</view>
|
||||
<view class="meta-item">
|
||||
<text class="meta-label">讲解状态</text>
|
||||
<text class="meta-value">{{ audioStatusText }}</text>
|
||||
<text class="audio-time">00:00</text>
|
||||
<view class="audio-track">
|
||||
<view class="audio-dot"></view>
|
||||
</view>
|
||||
<text class="audio-time">{{ exhibit.audio.durationLabel || '音频讲解' }}</text>
|
||||
</view>
|
||||
|
||||
<view v-if="exhibit.audio.status !== 'playable'" class="audio-note">
|
||||
<text class="audio-note-title">{{ audioNoteTitle }}</text>
|
||||
<text class="audio-note-desc">
|
||||
{{ exhibit.audio.unavailableReason || '当前仅提供图文讲解,正式音频接入后将显示播放入口。' }}
|
||||
<view v-else class="text-status-panel">
|
||||
<text class="text-status-title">图文讲解</text>
|
||||
<text class="text-status-desc">
|
||||
{{ exhibit.audio.unavailableReason || '该讲解暂无已发布音频,当前提供图文讲解。' }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="content-section">
|
||||
<text class="section-title">讲解摘要</text>
|
||||
<text class="section-text">{{ exhibit.summary }}</text>
|
||||
</view>
|
||||
|
||||
<view class="content-section">
|
||||
<text class="section-title">讲解介绍</text>
|
||||
<text class="section-text">{{ exhibit.body }}</text>
|
||||
</view>
|
||||
|
||||
<view class="content-section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">章节</text>
|
||||
<text class="section-state">{{ exhibit.chapters.length ? `${exhibit.chapters.length} 段` : '待开放' }}</text>
|
||||
</view>
|
||||
<view v-if="exhibit.chapters.length" class="chapter-list">
|
||||
<view
|
||||
v-for="chapter in exhibit.chapters"
|
||||
:key="chapter.id"
|
||||
class="chapter-item"
|
||||
>
|
||||
<text class="chapter-title">{{ chapter.title }}</text>
|
||||
<text v-if="typeof chapter.startTime === 'number'" class="chapter-time">
|
||||
{{ formatChapterTime(chapter.startTime) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<text v-else class="section-text muted">正式章节数据接入后将在这里展示。</text>
|
||||
</view>
|
||||
|
||||
<view class="content-section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">讲解文稿</text>
|
||||
<text class="section-state">{{ exhibit.transcript ? '已接入' : '待开放' }}</text>
|
||||
</view>
|
||||
<text class="section-text muted">
|
||||
{{ exhibit.transcript || '正式文稿数据接入后将在这里展示。' }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view v-if="exhibit.location" class="location-note">
|
||||
<text class="location-title">位置说明</text>
|
||||
<text class="location-desc">{{ locationDescription }}</text>
|
||||
<text class="section-title">讲解内容</text>
|
||||
<text class="section-text">{{ exhibit.body || exhibit.summary }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="action-bar">
|
||||
<view
|
||||
class="action-btn primary"
|
||||
class="location-btn"
|
||||
:class="{ disabled: !exhibit.location }"
|
||||
@tap="handleNavigate"
|
||||
>
|
||||
<svg class="btn-icon" width="18" height="18" viewBox="0 0 24 24" fill="none">
|
||||
<svg class="location-icon" width="19" height="19" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M12 21C12 21 18 14.9 18 9.8C18 6.5 15.3 4 12 4C8.7 4 6 6.5 6 9.8C6 14.9 12 21 12 21Z" stroke="currentColor" stroke-width="1.7"/>
|
||||
<circle cx="12" cy="10" r="2.2" stroke="currentColor" stroke-width="1.7"/>
|
||||
</svg>
|
||||
<text class="btn-text">{{ exhibit.location?.actionText || '暂无位置' }}</text>
|
||||
</view>
|
||||
<view class="action-btn" @tap="handleCollect">
|
||||
<svg class="btn-icon" width="18" height="18" viewBox="0 0 24 24" fill="none">
|
||||
<path
|
||||
:fill="isCollected ? 'currentColor' : 'none'"
|
||||
d="M12 20.2L10.8 19.1C6.4 15.1 3.5 12.5 3.5 9.2C3.5 6.6 5.6 4.5 8.2 4.5C9.7 4.5 11.1 5.2 12 6.3C12.9 5.2 14.3 4.5 15.8 4.5C18.4 4.5 20.5 6.6 20.5 9.2C20.5 12.5 17.6 15.1 13.2 19.1L12 20.2Z"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.7"
|
||||
/>
|
||||
</svg>
|
||||
<text class="btn-text">收藏</text>
|
||||
</view>
|
||||
<view class="action-btn" @tap="handleShare">
|
||||
<svg class="btn-icon" width="18" height="18" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M8 12H6.8C5.8 12 5 12.8 5 13.8V18.2C5 19.2 5.8 20 6.8 20H17.2C18.2 20 19 19.2 19 18.2V13.8C19 12.8 18.2 12 17.2 12H16" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
|
||||
<path d="M12 15V4M12 4L8.5 7.5M12 4L15.5 7.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
<text class="btn-text">分享</text>
|
||||
<text class="location-text">查看位置</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -174,12 +100,10 @@ import {
|
||||
} from '@/usecases/guideUseCase'
|
||||
import {
|
||||
toExplainDetailPageViewModel,
|
||||
type ExplainContentType,
|
||||
type ExplainDetailPageViewModel
|
||||
} from '@/view-models/explainViewModels'
|
||||
import {
|
||||
isGuideTopTab,
|
||||
navigateToGuideTopTab,
|
||||
type GuideTopTab
|
||||
} from '@/utils/guideTopTabs'
|
||||
|
||||
@@ -188,12 +112,12 @@ const defaultDetail: ExplainDetailPageViewModel = {
|
||||
title: '讲解内容',
|
||||
subtitle: '位置待补充',
|
||||
contentType: 'exhibit',
|
||||
coverImages: ['/static/exhibit-placeholder.jpg'],
|
||||
coverImages: [],
|
||||
summary: '该讲解内容待补充。',
|
||||
body: '该讲解内容待补充。',
|
||||
audio: {
|
||||
status: 'unavailable',
|
||||
unavailableReason: '该展项暂无已发布音频,当前提供图文讲解。'
|
||||
unavailableReason: '该讲解暂无已发布音频,当前提供图文讲解。'
|
||||
},
|
||||
chapters: [],
|
||||
relatedItems: []
|
||||
@@ -209,59 +133,28 @@ const audioPlayerRef = ref<AudioPlayerExpose | null>(null)
|
||||
const showAudioPlayer = ref(false)
|
||||
const currentAudio = ref<AudioItem | null>(null)
|
||||
const isPlaying = ref(false)
|
||||
const isCollected = ref(false)
|
||||
const activeTopTab = ref<GuideTopTab>('guide')
|
||||
const activeTopTab = ref<GuideTopTab>('explain')
|
||||
|
||||
const heroImage = computed(() => exhibit.value.coverImages[0])
|
||||
const audioStatusText = computed(() => {
|
||||
if (exhibit.value.audio.status === 'playable') {
|
||||
return exhibit.value.audio.durationLabel || '可播放'
|
||||
}
|
||||
if (exhibit.value.audio.status === 'none') {
|
||||
return '图文讲解'
|
||||
}
|
||||
return '图文讲解'
|
||||
})
|
||||
|
||||
const audioNoteTitle = computed(() => (
|
||||
exhibit.value.audio.status === 'playable'
|
||||
? '音频讲解'
|
||||
: '图文讲解'
|
||||
))
|
||||
|
||||
const contentTypeText = computed(() => {
|
||||
const map: Record<ExplainContentType, string> = {
|
||||
hall: '空间讲解',
|
||||
zone: '展区讲解',
|
||||
exhibit: '展品讲解',
|
||||
theme: '主题讲解'
|
||||
}
|
||||
return map[exhibit.value.contentType]
|
||||
})
|
||||
|
||||
const locationDescription = computed(() => (
|
||||
exhibit.value.location?.note || '当前支持三维位置预览。'
|
||||
))
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
if (options.id) {
|
||||
const exhibitData = await explainUseCase.getExhibitById(options.id)
|
||||
if (exhibitData) {
|
||||
exhibit.value = toExplainDetailPageViewModel(exhibitData)
|
||||
}
|
||||
}
|
||||
const detailMeta = computed(() => [
|
||||
exhibit.value.hallName,
|
||||
exhibit.value.floorLabel
|
||||
].filter(Boolean).join(' · '))
|
||||
|
||||
onLoad(async (options: any = {}) => {
|
||||
const tab = Array.isArray(options.tab) ? options.tab[0] : options.tab
|
||||
if (isGuideTopTab(tab)) {
|
||||
activeTopTab.value = tab
|
||||
}
|
||||
})
|
||||
|
||||
const formatChapterTime = (seconds: number) => {
|
||||
const minute = Math.floor(seconds / 60)
|
||||
const second = Math.floor(seconds % 60)
|
||||
return `${minute}:${String(second).padStart(2, '0')}`
|
||||
}
|
||||
const exhibitId = Array.isArray(options.id) ? options.id[0] : options.id
|
||||
if (!exhibitId) return
|
||||
|
||||
const exhibitData = await explainUseCase.getExhibitById(exhibitId)
|
||||
if (exhibitData) {
|
||||
exhibit.value = toExplainDetailPageViewModel(exhibitData)
|
||||
}
|
||||
})
|
||||
|
||||
const handlePlayAudio = async () => {
|
||||
if (exhibit.value.audio.url) {
|
||||
@@ -376,22 +269,6 @@ const handleNavigate = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleCollect = () => {
|
||||
isCollected.value = !isCollected.value
|
||||
uni.showToast({
|
||||
title: isCollected.value ? '已加入本地收藏' : '已取消本地收藏',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
const handleShare = () => {
|
||||
uni.showShareMenu()
|
||||
}
|
||||
|
||||
const handleTopTabChange = (tab: GuideTopTab) => {
|
||||
navigateToGuideTopTab(tab)
|
||||
}
|
||||
|
||||
const handleBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
@@ -405,285 +282,208 @@ const handleBack = () => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.detail-page {
|
||||
.explain-detail-page {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--museum-bg-light);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.detail-hero {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
background: #edf0ea;
|
||||
height: 100%;
|
||||
padding: 84px 20px calc(104px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.hero-image,
|
||||
.hero-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: 250px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.hero-image {
|
||||
background: #e9ece5;
|
||||
}
|
||||
|
||||
.hero-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #e6eadf;
|
||||
background: #e9ece5;
|
||||
}
|
||||
|
||||
.hero-placeholder-text {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #67705f;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
font-weight: 800;
|
||||
color: #68725d;
|
||||
}
|
||||
|
||||
.audio-control {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
bottom: 18px;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--museum-accent);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
||||
color: #151713;
|
||||
.detail-body {
|
||||
padding-top: 22px;
|
||||
}
|
||||
|
||||
.audio-status {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
background: rgba(21, 23, 19, 0.86);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.audio-status-text {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.detail-info {
|
||||
padding: 22px 16px 116px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.content-type,
|
||||
.detail-title,
|
||||
.detail-subtitle,
|
||||
.detail-meta,
|
||||
.audio-time,
|
||||
.text-status-title,
|
||||
.text-status-desc,
|
||||
.section-title,
|
||||
.section-text,
|
||||
.audio-note-title,
|
||||
.audio-note-desc,
|
||||
.location-title,
|
||||
.location-desc {
|
||||
.location-text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.content-type {
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #68725d;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
margin-top: 4px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
font-weight: 700;
|
||||
font-size: 29px;
|
||||
line-height: 38px;
|
||||
font-weight: 800;
|
||||
color: #151713;
|
||||
}
|
||||
|
||||
.detail-subtitle {
|
||||
margin-top: 6px;
|
||||
.detail-meta {
|
||||
margin-top: 8px;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
color: #555c51;
|
||||
}
|
||||
|
||||
.audio-panel {
|
||||
height: 76px;
|
||||
margin-top: 24px;
|
||||
padding: 0 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
box-sizing: border-box;
|
||||
background: #0b0c0a;
|
||||
border-radius: 8px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.audio-play {
|
||||
flex-shrink: 0;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
color: #151713;
|
||||
background: #e0df00;
|
||||
}
|
||||
|
||||
.audio-time {
|
||||
flex-shrink: 0;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #68725d;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.meta-grid {
|
||||
margin-top: 18px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
.audio-track {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
height: 3px;
|
||||
background: rgba(255, 255, 255, 0.24);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
min-height: 62px;
|
||||
padding: 10px 12px;
|
||||
.audio-dot {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: #e0df00;
|
||||
border-radius: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.text-status-panel {
|
||||
margin-top: 24px;
|
||||
padding: 14px;
|
||||
box-sizing: border-box;
|
||||
background: #f7f8f3;
|
||||
border: 1px solid #ebece5;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e4e6df;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.meta-label,
|
||||
.meta-value {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.meta-label {
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #818a7a;
|
||||
}
|
||||
|
||||
.meta-value {
|
||||
margin-top: 4px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
.text-status-title {
|
||||
font-size: 15px;
|
||||
line-height: 21px;
|
||||
font-weight: 800;
|
||||
color: #151713;
|
||||
}
|
||||
|
||||
.audio-note,
|
||||
.location-note {
|
||||
margin-top: 14px;
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
background: #f1f4ea;
|
||||
border: 1px solid #e2e7d7;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.audio-note-title,
|
||||
.location-title {
|
||||
font-size: 14px;
|
||||
.text-status-desc {
|
||||
margin-top: 5px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
font-weight: 700;
|
||||
color: #151713;
|
||||
}
|
||||
|
||||
.audio-note-desc,
|
||||
.location-desc {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
color: #5d6656;
|
||||
}
|
||||
|
||||
.content-section {
|
||||
margin-top: 22px;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 700;
|
||||
font-size: 19px;
|
||||
line-height: 27px;
|
||||
font-weight: 800;
|
||||
color: #151713;
|
||||
}
|
||||
|
||||
.section-state {
|
||||
font-size: 12px;
|
||||
color: #818a7a;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
color: #333a2f;
|
||||
}
|
||||
|
||||
.section-text.muted {
|
||||
color: #818a7a;
|
||||
}
|
||||
|
||||
.chapter-list {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.chapter-item {
|
||||
min-height: 44px;
|
||||
padding: 0 12px;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
background: #f7f8f3;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.chapter-title {
|
||||
font-size: 14px;
|
||||
color: #151713;
|
||||
}
|
||||
|
||||
.chapter-time {
|
||||
font-size: 12px;
|
||||
color: #818a7a;
|
||||
margin-top: 13px;
|
||||
font-size: 16px;
|
||||
line-height: 28px;
|
||||
color: #2f352d;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
flex-shrink: 0;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
display: grid;
|
||||
grid-template-columns: 1.4fr 1fr 1fr;
|
||||
gap: 8px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 12px 20px calc(18px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
border-top: 1px solid #e7e9e0;
|
||||
background: rgba(249, 250, 251, 0.96);
|
||||
}
|
||||
|
||||
.detail-page.with-audio-player .action-bar {
|
||||
margin-bottom: 88px;
|
||||
.explain-detail-page.with-audio-player .action-bar {
|
||||
bottom: 88px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
height: 46px;
|
||||
.location-btn {
|
||||
height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
gap: 8px;
|
||||
box-sizing: border-box;
|
||||
background: #f7f8f3;
|
||||
border: 1px solid #e5e8df;
|
||||
background: #ffffff;
|
||||
border: 1px solid #151713;
|
||||
border-radius: 8px;
|
||||
color: #151713;
|
||||
}
|
||||
|
||||
.action-btn.primary {
|
||||
background: #151713;
|
||||
border-color: #151713;
|
||||
color: var(--museum-accent);
|
||||
.location-btn.disabled {
|
||||
color: #8d9488;
|
||||
border-color: #d8dcd3;
|
||||
background: #f2f4ef;
|
||||
}
|
||||
|
||||
.action-btn.disabled {
|
||||
background: #f1f3ed;
|
||||
border-color: #e5e8df;
|
||||
color: #8b9385;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
.location-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
.location-text {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
font-weight: 700;
|
||||
color: currentColor;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user