This commit is contained in:
WanP
2025-10-27 15:03:40 +08:00
parent 45ceb9c77d
commit 5eb5c59e4b
18 changed files with 1340 additions and 636 deletions

View File

@@ -1,5 +1,5 @@
<template>
<view class="page">
<view v-if="loading" class="page">
<Head></Head>
<!-- 内容区 -->
@@ -8,8 +8,10 @@
<view class="moment">
<!-- 用户栏 -->
<view class="userbar">
<image :src="post.userImg" mode="aspectFill" class="userimg" alt="用户头像" />
<text class="username">{{ post.userName }}</text>
<image v-if="post.user && post.user.userImg" :src="post.user.userImg" mode="aspectFill" class="userimg"
alt="用户头像" />
<image v-else src="/static/imgs/default-avatar.png" mode="aspectFill" class="userimg" alt="默认头像" />
<text class="username">{{ post.user ? post.user.nickName : '未知用户' }}</text>
<button class="follow" @tap="common.openapp">
<uni-icons v-if="post.isfollow" type="checkmarkempty" size="20" color="#333"></uni-icons>
<text v-else>关注</text>
@@ -17,15 +19,28 @@
</view>
<!-- 轮播图 -->
<swiper v-if="post.imgs && post.imgs.length" :indicator-dots="false" :autoplay="false" :interval="3000"
<swiper v-if="post.imgs && post.imgs.length > 0" :indicator-dots="false" :autoplay="false" :interval="3000"
:duration="1000" :circular="true" class="swiper-banner" @change="onChange">
<swiper-item v-for="(item, i) in post.imgs" :key="i">
<view class="swiper-center">
<image v-if="item.type === 'img'" :src="item.src" class="swiper-item" mode="aspectFit" alt="动态图片内容" />
<video v-else :src="item.src" class="swiper-item" object-fit="contain" muted style="pointer-events:none;"
alt="动态视频内容" />
<cover-view class="swiper-mask" @tap="common.openapp">
</cover-view>
<image v-if="item.type === 'img'" :src="item.src" class="swiper-item" mode="aspectFit" alt="动态图片内容"
@load="onImageLoad(i)" @error="onImageError(i)" />
<video v-else-if="item.type === 'video'" id="videoid" :src="item.src" class="swiper-item"
:controls="false" @tap="pausevideo" object-fit="contain" alt="动态视频内容" />
<!-- 播放按钮 - 使用浏览器复制的样式 -->
<view v-if="!isPlaying" class="uni-video-cover" @tap="pausevideo">
<view class="uni-video-cover-play-button uni-video-icon"></view>
</view>
<!-- <cover-view class="swiper-mask" @tap="common.openapp">
</cover-view> -->
<!-- 图片加载状态 -->
<!-- <view v-if="item.loading" class="image-loading">
<text>图片加载中...</text>
</view>
<view v-if="item.error" class="image-error">
<text>图片加载失败</text>
</view> -->
</view>
</swiper-item>
</swiper>
@@ -47,21 +62,30 @@
</view>
<!-- 评论区域 + 互动区域 -->
<Comments :comments="post.comments" :showInteraction="true" :collectsum="post.collectsum" :likesum="post.likesum" />
<Comments :postid="post.id" />
<!-- 互动区域 -->
<!-- <Intereact :collectsum="post.collectsum" :likesum="post.likesum" /> -->
<!-- Findmore -->
<Findmore />
</view>
<view v-else class="loading-container">
<text>页面加载中...</text>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { ref, getCurrentInstance } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useCommonStore } from '@/stores/common.js'
import Head from '@/pages/head/head.vue'
import Comments from '@/pages/comments/comments.vue'
import Findmore from '@/pages/findmore/findmore.vue'
import { getPostList, getPostLImage, getPostVideo, getUserImg } from '../api/api.js'
const common = useCommonStore()
// 当前 dot
@@ -70,102 +94,203 @@ const onChange = e => current.value = e.detail.current
// 动态数据
const post = ref({})
// 播放状态
const isPlaying = ref(true) // 默认播放状态
// 资源加载状态
const loading = ref(false)
// 模拟获取数据函数
const fetchPostData = async () => {
try {
// 使用uni.request替代axios
const response = await new Promise((resolve, reject) => {
uni.request({
url: '', // 这里可以填写实际API地址
method: 'GET',
timeout: 1000,
success: resolve,
fail: reject
})
})
// 图片加载成功处理
const onImageLoad = (index) => {
if (post.value.imgs && post.value.imgs[index]) {
post.value.imgs[index].loading = false
post.value.imgs[index].error = false
}
}
// 处理数据...
const mockData = {
userId: 1000011,
userName: 'Kun Chang-Min',
userImg: '/static/logo.png',
date: '2024-12-03',
copywriting: '智能体是人类智慧的延伸,它们将成为我们最强大的工具,也是最亲密的朋友。',
isfollow: false,
collectsum: 114514,
likesum: 114514,
imgs: [
{ type: 'img', src: '/static/logo.png' },
{ type: 'video', src: '/static/videos/beauty.mp4' },
{ type: 'img', src: '/static/imgs/comment.webp' },
{ type: 'img', src: '/static/imgs/image-138.webp' }
],
comments: [
{
id: 101,
userName: 'Brad Lewin',
atUsers: ['JackyLove'],
content: '今天天气真不错~',
date: '2024-12-01',
likeCount: 99999,
showChild: false,
children: [
{ id: 201, userName: 'Alice', content: '快智能体是人类智慧的延伸,它们将成为我们最强大的工具,也是最亲密的朋友。智能体是人类智慧的延伸', atUsers: ['Brad Lewin', 'JackyLove'], date: '2024-12-01', likeCount: 2 },
{ id: 202, userName: 'Bob', content: '我同意你的观点。我记得喜欢这个版本。这个新版本对我来说Nothing好处', atUsers: [], date: '2024-12-01', likeCount: 1 }
]
},
{
id: 102,
userName: 'Leanne Simpson',
atUsers: ['Theshy'],
content: '有人一起开黑吗?',
date: '2024-12-02',
likeCount: 1145140,
showChild: false,
children: [
{ id: 203, userName: 'Carol', content: '带我一个', atUsers: [], date: '2024-12-02', likeCount: 3 }
]
},
{
id: 103,
userName: 'Tom Hardy',
atUsers: [],
content: '主评论3分享一张今晚的月亮。',
date: '2024-12-03',
likeCount: 999,
showChild: false,
children: []
}
]
}
// 图片加载失败处理
const onImageError = (index) => {
if (post.value.imgs && post.value.imgs[index]) {
post.value.imgs[index].loading = false
post.value.imgs[index].error = true
console.warn(`图片加载失败: index ${index}`)
}
}
// 将模拟数据赋值给post
post.value = mockData
} catch (error) {
console.error('获取数据失败:', error)
// 如果获取失败,使用默认数据
post.value = {
userId: 1000011,
userName: 'Kun Chang-Min',
userImg: '/static/logo.png',
date: '2024-12-03',
copywriting: '智能体是人类智慧的延伸,它们将成为我们最强大的工具,也是最亲密的朋友。',
isfollow: false,
collectsum: 114514,
likesum: 114514,
imgs: [
{ type: 'img', src: '/static/logo.png' }
],
comments: []
//暂停/播放
const pausevideo = () => {
// 获取VideoContext实例
const videoCtx = uni.createVideoContext('videoid', getCurrentInstance());
// 检查视频状态并切换播放/暂停
if (videoCtx) {
// 使用一个状态变量来跟踪播放状态
if (isPlaying.value) {
videoCtx.pause()
isPlaying.value = false
} else {
videoCtx.play()
isPlaying.value = true
}
}
}
// 组件挂载时获取数据
onLoad(() => {
fetchPostData()
const params = ''
getPostList(params).then(res => {
try {
// console.log(res.data.data)
const data = res.data.data
// 处理帖子相关字段 - 根据实际API返回字段优化
data.id = data.id || ''
data.title = data.newsTitle || data.title || ''
data.source = data.newsSource || data.source || ''
data.copywriting = data.textContent || data.newsContent || ''
data.date = data.time || data.date || ''
data.countLike = data.likeCount || data.countLike || 0
data.collectsum = data.collectsum || 0
// data.user.nickName = data.user.nickName || ''
// data.user.userImg = data.user.avatar || data.userImg || ''
// data.comments = data.comments || []
const mediaPromises = []
// 处理图片资源
if (data.imgs && Array.isArray(data.imgs)) {
data.imgs.forEach(image => {
mediaPromises.push(getPostLImage(image.original_url).then(imageRes => {
if (imageRes.statusCode === 200 && imageRes.data) {
// 将arraybuffer转换为base64
const base64 = uni.arrayBufferToBase64(imageRes.data)
const imageUrl = 'data:image/webp;base64,' + base64
return {
type: 'img',
src: imageUrl,
original_url: image.original_url,
loading: true, // 初始加载状态
error: false // 错误状态
}
}
return null
}).catch(error => {
uni.showToast({
title: error.message,
icon: 'error'
})
return null
}))
})
}
//处理视频资源
if (data.videos && Array.isArray(data.videos)) {
data.videos.forEach(video => {
mediaPromises.push(getPostVideo(video.original_url).then(videoRes => {
if (videoRes.statusCode === 200 && videoRes.data) {
// 将arraybuffer转换为base64
const base64 = uni.arrayBufferToBase64(videoRes.data)
const videoUrl = 'data:video/mp4;base64,' + base64
return {
type: 'video',
src: videoUrl,
original_url: video.original_url,
loading: true, // 初始加载状态
error: false // 错误状态
}
}
return null
}).catch(error => {
uni.showToast({
title: error.message,
icon: 'error'
})
return null
}))
})
}
//处理用户信息
if (data.user && data.user.constructor === Object) {
// 如果有头像路径,则获取头像资源
const avatarPath = data.user.avatar || data.userImg
if (avatarPath) {
mediaPromises.push(getUserImg(avatarPath).then(userImgRes => {
if (userImgRes.statusCode === 200 && userImgRes.data) {
// 将arraybuffer转换为base64
const base64 = uni.arrayBufferToBase64(userImgRes.data)
const userImgUrl = 'data:image/webp;base64,' + base64
return {
type: 'userImg',
src: userImgUrl,
original_url: avatarPath
}
}
return null
}).catch(error => {
console.warn('用户头像加载失败:', error)
return null
}))
}
data.user = {
nickName: data.user.nickName || '',
userImg: avatarPath || '' // 先使用原始路径后续会替换为base64
}
}
// 统一等待所有媒体资源加载完成
if (mediaPromises.length > 0) {
Promise.all(mediaPromises).then(mediaItems => {
// 过滤掉null值将有效的媒体资源合并到imgs数组中
const validMediaItems = mediaItems.filter(item => item !== null)
// 分离用户头像和其他媒体资源
const userImgItem = validMediaItems.find(item => item.type === 'userImg')
const otherMediaItems = validMediaItems.filter(item => item.type !== 'userImg')
// 如果有用户头像资源,更新用户头像
if (userImgItem) {
data.user.userImg = userImgItem.src
}
// 设置其他媒体资源
data.imgs = otherMediaItems
// post.value = data
console.log(data)
Object.assign(post.value, data)
loading.value = true
})
} else {
// 如果没有媒体资源,设置空数组
data.imgs = []
post.value = data
}
} catch (error) {
handleError('数据处理错误:', error, '数据加载失败', '抱歉,新闻内容加载失败,请稍后重试')
}
}).catch(error => {
handleError('网络请求错误:', error, '网络错误', '网络连接异常,请检查网络设置')
})
// 统一的错误处理函数
const handleError = (errorType, error, title, message) => {
console.error(errorType, error)
post.value = {
title: title,
source: '系统',
copywriting: message,
date: new Date().toISOString(),
countLike: 0,
collectsum: 0,
comments: [],
imgs: []
}
}
})
</script>
@@ -253,7 +378,8 @@ swiper-item {
height: 100%;
display: flex;
align-items: center;
justify-content: center
justify-content: center;
position: relative;
}
.swiper-item {
@@ -261,17 +387,63 @@ swiper-item {
height: 100%
}
.swiper-center {
position: relative;
::v-deep .uni-video-cover {
background-color: transparent;
}
.swiper-mask {
::v-deep .uni-video-cover-play-button {
width: 100% !important;
height: 100% !important;
display: flex;
align-items: center;
justify-content: center;
}
.uni-video-cover {
position: absolute;
left: 0;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: transparent;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1;
}
.uni-video-icon {
font-family: 'uni-video-icon';
text-align: center;
}
.uni-video-cover-play-button {
width: 100% !important;
height: 100% !important;
display: flex;
align-items: center;
justify-content: center;
line-height: 75px;
font-size: 56px;
color: rgba(255, 255, 255, 0.5);
cursor: pointer;
}
.uni-video-cover-play-button::after {
content: '\ea24';
}
.uni-video-cover {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1;
}
.dots-bar {
@@ -319,4 +491,11 @@ swiper-item {
font-size: 12px;
color: #b1aeb2;
}
.loading-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
</style>