feat: 临时改造讲解页方案 B 链路
接入展厅列表、展厅讲解点分组生成临时业务单元,并迁移讲解详情播放正文到新接口链路。
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
<text class="header-back-icon">‹</text>
|
||||
<text class="header-back-text">返回</text>
|
||||
</view>
|
||||
<text class="header-title">讲解</text>
|
||||
<text class="header-title">{{ headerTitle }}</text>
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
@@ -14,8 +14,8 @@
|
||||
:show-scrollbar="false"
|
||||
>
|
||||
<view v-if="loading" class="state-block">
|
||||
<text class="state-title">正在加载展厅讲解</text>
|
||||
<text class="state-desc">稍后将展示可选择的展厅。</text>
|
||||
<text class="state-title">{{ loadingTitle }}</text>
|
||||
<text class="state-desc">{{ loadingDescription }}</text>
|
||||
</view>
|
||||
|
||||
<view v-else-if="error" class="state-block error">
|
||||
@@ -24,7 +24,7 @@
|
||||
</view>
|
||||
|
||||
<template v-else>
|
||||
<view v-if="filteredHalls.length" class="hall-list">
|
||||
<view v-if="stage === 'hall' && filteredHalls.length" class="hall-list">
|
||||
<view
|
||||
v-for="hall in filteredHalls"
|
||||
:key="hall.id"
|
||||
@@ -55,9 +55,66 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else-if="stage === 'unit' && businessUnits.length" class="hall-list">
|
||||
<view
|
||||
v-for="unit in businessUnits"
|
||||
:key="unit.id"
|
||||
class="hall-card unit-card"
|
||||
@tap="handleBusinessUnitClick(unit.id)"
|
||||
>
|
||||
<view class="unit-mark">
|
||||
<text class="unit-mark-text">{{ unit.name.slice(0, 1) || '讲' }}</text>
|
||||
</view>
|
||||
|
||||
<view class="hall-main">
|
||||
<text class="hall-name">{{ unit.name }}</text>
|
||||
<view class="hall-meta-row">
|
||||
<view class="floor-badge">
|
||||
<text class="floor-badge-text">业务单元</text>
|
||||
</view>
|
||||
<text class="hall-meta-text">{{ unit.guideStopCount }} 个讲解点</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<text class="hall-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else-if="stage === 'stop' && guideStops.length" class="hall-list">
|
||||
<view
|
||||
v-for="stop in guideStops"
|
||||
:key="stop.id"
|
||||
class="hall-card stop-card"
|
||||
@tap="handleGuideStopClick(stop.id)"
|
||||
>
|
||||
<image
|
||||
v-if="stop.coverImageUrl"
|
||||
class="hall-thumb"
|
||||
:src="stop.coverImageUrl"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-else class="hall-thumb placeholder">
|
||||
<text class="hall-thumb-text">{{ hallIconText(stop.name) }}</text>
|
||||
</view>
|
||||
|
||||
<view class="hall-main">
|
||||
<text class="hall-name">{{ stop.name }}</text>
|
||||
<text v-if="stop.description" class="stop-desc">{{ stop.description }}</text>
|
||||
<view class="hall-meta-row">
|
||||
<view class="floor-badge">
|
||||
<text class="floor-badge-text">{{ stop.hasAudio ? '可讲解' : '图文' }}</text>
|
||||
</view>
|
||||
<text class="hall-meta-text">{{ stop.floorId || selectedHallName || '楼层待补充' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<text class="hall-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else class="state-block empty">
|
||||
<text class="state-title">未找到相关展厅</text>
|
||||
<text class="state-desc">暂无可选择的展厅讲解。</text>
|
||||
<text class="state-title">{{ emptyTitle }}</text>
|
||||
<text class="state-desc">{{ emptyDescription }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</scroll-view>
|
||||
@@ -76,18 +133,50 @@ export interface ExplainHallSelectItem {
|
||||
searchText: string
|
||||
}
|
||||
|
||||
export interface ExplainBusinessUnitSelectItem {
|
||||
id: string
|
||||
name: string
|
||||
hallId: string
|
||||
guideStopCount: number
|
||||
}
|
||||
|
||||
export interface ExplainGuideStopSelectItem {
|
||||
id: string
|
||||
name: string
|
||||
hallId?: string
|
||||
hallName?: string
|
||||
floorId?: string
|
||||
coverImageUrl?: string
|
||||
description?: string
|
||||
hasAudio?: boolean
|
||||
}
|
||||
|
||||
export type ExplainSelectStage = 'hall' | 'unit' | 'stop'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
halls?: ExplainHallSelectItem[]
|
||||
businessUnits?: ExplainBusinessUnitSelectItem[]
|
||||
guideStops?: ExplainGuideStopSelectItem[]
|
||||
stage?: ExplainSelectStage
|
||||
selectedHallName?: string
|
||||
selectedBusinessUnitName?: string
|
||||
loading?: boolean
|
||||
error?: string
|
||||
}>(), {
|
||||
halls: () => [],
|
||||
businessUnits: () => [],
|
||||
guideStops: () => [],
|
||||
stage: 'hall',
|
||||
selectedHallName: '',
|
||||
selectedBusinessUnitName: '',
|
||||
loading: false,
|
||||
error: ''
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
hallClick: [hallId: string]
|
||||
businessUnitClick: [unitId: string]
|
||||
guideStopClick: [stopId: string]
|
||||
back: []
|
||||
}>()
|
||||
|
||||
@@ -106,6 +195,31 @@ const hallIconMap: Record<string, string> = {
|
||||
}
|
||||
|
||||
const filteredHalls = computed(() => props.halls)
|
||||
const headerTitle = computed(() => {
|
||||
if (props.stage === 'unit') return props.selectedHallName || '选择业务单元'
|
||||
if (props.stage === 'stop') return props.selectedBusinessUnitName || '选择讲解点'
|
||||
return '讲解'
|
||||
})
|
||||
const loadingTitle = computed(() => {
|
||||
if (props.stage === 'unit') return '正在加载业务单元'
|
||||
if (props.stage === 'stop') return '正在加载讲解点'
|
||||
return '正在加载展厅讲解'
|
||||
})
|
||||
const loadingDescription = computed(() => {
|
||||
if (props.stage === 'unit') return '正在按讲解点所属 outline 分组生成临时业务单元。'
|
||||
if (props.stage === 'stop') return '稍后将展示该业务单元下的讲解点。'
|
||||
return '稍后将展示可选择的展厅。'
|
||||
})
|
||||
const emptyTitle = computed(() => {
|
||||
if (props.stage === 'unit') return '该展厅暂无已标定讲解点'
|
||||
if (props.stage === 'stop') return '该业务单元暂无讲解点'
|
||||
return '未找到相关展厅'
|
||||
})
|
||||
const emptyDescription = computed(() => {
|
||||
if (props.stage === 'unit') return '方案 B 只展示已在地图上标定的讲解点。'
|
||||
if (props.stage === 'stop') return '可返回选择其他业务单元。'
|
||||
return '暂无可选择的展厅讲解。'
|
||||
})
|
||||
|
||||
const hallIconUrl = (hall: ExplainHallSelectItem) => {
|
||||
return hallIconMap[hall.name.trim()] || hall.image || ''
|
||||
@@ -117,6 +231,14 @@ const handleHallClick = (hallId: string) => {
|
||||
emit('hallClick', hallId)
|
||||
}
|
||||
|
||||
const handleBusinessUnitClick = (unitId: string) => {
|
||||
emit('businessUnitClick', unitId)
|
||||
}
|
||||
|
||||
const handleGuideStopClick = (stopId: string) => {
|
||||
emit('guideStopClick', stopId)
|
||||
}
|
||||
|
||||
const handleBack = () => {
|
||||
emit('back')
|
||||
}
|
||||
@@ -165,10 +287,11 @@ const handleBack = () => {
|
||||
left: 12px;
|
||||
top: 0;
|
||||
height: 56px;
|
||||
min-width: 74px;
|
||||
width: 82px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.header-back-icon {
|
||||
@@ -185,10 +308,17 @@ const handleBack = () => {
|
||||
}
|
||||
|
||||
.header-title {
|
||||
max-width: calc(100% - 188px);
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
font-size: 18px;
|
||||
line-height: 25px;
|
||||
font-weight: 800;
|
||||
color: #151713;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hall-list {
|
||||
@@ -238,11 +368,40 @@ const handleBack = () => {
|
||||
color: #83927a;
|
||||
}
|
||||
|
||||
.unit-mark {
|
||||
flex-shrink: 0;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
background: #151713;
|
||||
}
|
||||
|
||||
.unit-mark-text {
|
||||
font-size: 22px;
|
||||
line-height: 30px;
|
||||
font-weight: 800;
|
||||
color: var(--museum-accent);
|
||||
}
|
||||
|
||||
.hall-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.stop-desc {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
color: #68725d;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hall-name {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
|
||||
Reference in New Issue
Block a user