feat: 音频组件的字段对接

This commit is contained in:
2026-08-06 16:22:04 +08:00
parent cc1615162a
commit 0020c8bb47

View File

@@ -1,7 +1,7 @@
<template>
<view class="discovery-audio-tool-card" hover-class="is-pressed" hover-stay-time="80" @tap="handleSelect">
<view class="audio-visual">
<image v-if="normalizedItem.coverImage" class="audio-cover" :src="normalizedItem.coverImage" mode="aspectFill" />
<image v-if="normalizedItem.coverUrl" class="audio-cover" :src="normalizedItem.coverUrl" mode="aspectFill" />
<view v-else class="audio-cover audio-cover-fallback" />
<view class="audio-play">
<view class="audio-play-triangle" />
@@ -13,12 +13,8 @@
<text class="audio-subtitle block w-full truncate">{{ normalizedItem.subTitle }}</text>
<view class="audio-progress-row w-full min-w-0">
<view class="audio-progress-track">
<view class="audio-progress-fill" :style="{ width: `${normalizedItem.progress}%` }" />
</view>
<text class="audio-time block w-[90px] truncate">
{{ normalizedItem.currentTime }} / {{ normalizedItem.duration }}
</text>
<view class="audio-progress-track" />
<text class="audio-time block w-[90px] truncate">{{ normalizedItem.duration }}</text>
</view>
</view>
</view>
@@ -27,15 +23,6 @@
<script setup>
import { computed } from "vue";
const DEFAULT_ITEM = {
id: "audio-guide",
title: "卧龙潭语音讲解",
subTitle: "解说:响水洞瀑布",
progress: 31,
currentTime: "02:15",
duration: "05:40",
};
const props = defineProps({
item: {
type: Object,
@@ -45,24 +32,36 @@ const props = defineProps({
const emit = defineEmits(["didSelectItem"]);
const clampProgress = (value) => {
const progress = Number(value);
if (Number.isNaN(progress)) return 0;
return Math.min(Math.max(progress, 0), 100);
const formatDuration = (durationMs) => {
if (durationMs === null || durationMs === undefined || durationMs === "") {
return "";
}
const value = Number(durationMs);
if (!Number.isFinite(value) || value < 0) return "";
const totalSeconds = Math.floor(value / 1000);
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
};
const normalizedItem = computed(() => {
const source = Object.keys(props.item).length > 0 ? props.item : DEFAULT_ITEM;
const source = props.item && typeof props.item === "object" ? props.item : {};
const resource = source.resource || {};
const summary = resource.summary || {};
const payload = resource.payload || {};
return {
raw: source,
id: source.id ?? source.tabContentId ?? DEFAULT_ITEM.id,
title: source.title || DEFAULT_ITEM.title,
subTitle: source.subTitle || source.desc || DEFAULT_ITEM.subTitle,
coverImage: source.coverImage || source.image || DEFAULT_ITEM.coverImage || "",
progress: clampProgress(source.progress ?? DEFAULT_ITEM.progress),
currentTime: source.currentTime || DEFAULT_ITEM.currentTime,
duration: source.duration || DEFAULT_ITEM.duration,
code: resource.code || "",
title: summary.title || "",
subTitle: summary.subtitle || "",
coverUrl: summary.coverUrl || "",
url: payload.url || "",
mimeType: payload.mimeType || "",
durationMs: payload.durationMs,
duration: formatDuration(payload.durationMs),
};
});