Commit 6d62a17d by lijiabin

parent 16dcab51
import { ArticleTypeEnum, ReleaseStatusTypeEnum, BooleanFlag, SendTypeEnum } from '@/constants' import {
ArticleTypeEnum,
ReleaseStatusTypeEnum,
BooleanFlag,
SendTypeEnum,
VideoPositionEnum,
} from '@/constants'
import type { PageSearchParams } from '@/utils/request/types' import type { PageSearchParams } from '@/utils/request/types'
/** /**
...@@ -193,6 +199,8 @@ export interface ArticleItemDto { ...@@ -193,6 +199,8 @@ export interface ArticleItemDto {
sendTime: string sendTime: string
tagIdList: number[] tagIdList: number[]
pushList: { valueId: string; valueType: number; valueName: string }[] pushList: { valueId: string; valueType: number; valueName: string }[]
videoLocation: VideoPositionEnum
articleVideoUrl: string
} }
/** /**
......
...@@ -73,7 +73,15 @@ ...@@ -73,7 +73,15 @@
<h1 class="text-2xl font-bold text-gray-900 mb-4 leading-tight"> <h1 class="text-2xl font-bold text-gray-900 mb-4 leading-tight">
{{ articleDetail?.title }} {{ articleDetail?.title }}
</h1> </h1>
<!-- 顶部添加的视频 剧中固定宽度 -->
<div v-if="showTopVideo" class="flex justify-center">
<video
:src="articleDetail.articleVideoUrl"
controls
class="w-80% aspect-video"
:poster="`${articleDetail.articleVideoUrl}?x-oss-process=video/snapshot,t_1000,f_jpg`"
/>
</div>
<!-- 文章内容 --> <!-- 文章内容 -->
<div v-if="!isHtml" class="prose prose-lg max-w-none"> <div v-if="!isHtml" class="prose prose-lg max-w-none">
<div class="text-gray-700 leading-relaxed space-y-4 whitespace-pre-line text-17px"> <div class="text-gray-700 leading-relaxed space-y-4 whitespace-pre-line text-17px">
...@@ -95,13 +103,23 @@ ...@@ -95,13 +103,23 @@
:preview-teleported="true" :preview-teleported="true"
/> />
</div> </div>
<div v-if="articleDetail.type === ArticleTypeEnum.VIDEO"> <div v-if="articleDetail.type === ArticleTypeEnum.VIDEO" class="flex justify-center">
<video :src="articleDetail.videoUrl" controls /> <video :src="articleDetail.videoUrl" controls class="w-80% aspect-video" />
</div> </div>
</div> </div>
<div v-else v-html="articleDetail.content" class="html-content" v-image-preview="1111" /> <div v-else v-html="articleDetail.content" class="html-content" v-image-preview />
<!-- 底部添加的视频 -->
<div v-if="showBottomVideo" class="flex justify-center">
<!-- 长宽 1/1 -->
<video
:src="articleDetail.articleVideoUrl"
controls
class="w-80% aspect-video"
:poster="`${articleDetail.articleVideoUrl}?x-oss-process=video/snapshot,t_1000,f_jpg`"
/>
</div>
<!-- 标签 --> <!-- 标签 -->
<div class="flex flex-wrap gap-2 mt-6"> <div class="flex flex-wrap gap-2 mt-6">
<span <span
...@@ -128,7 +146,7 @@ ...@@ -128,7 +146,7 @@
<script setup lang="ts"> <script setup lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'
import type { ArticleItemDto } from '@/api' import type { ArticleItemDto } from '@/api'
import { articleTypeListOptions, ArticleTypeEnum } from '@/constants' import { articleTypeListOptions, ArticleTypeEnum, VideoPositionEnum } from '@/constants'
import ActionMore from '@/components/common/ActionMore/index.vue' import ActionMore from '@/components/common/ActionMore/index.vue'
import { jumpToUserHomePage } from '@/utils' import { jumpToUserHomePage } from '@/utils'
import { useUserStore } from '@/stores/user' import { useUserStore } from '@/stores/user'
...@@ -159,6 +177,25 @@ const isHtml = computed(() => { ...@@ -159,6 +177,25 @@ const isHtml = computed(() => {
) )
}) })
const isInterviewOrColumn = computed(
() =>
articleDetail.type === ArticleTypeEnum.INTERVIEW ||
articleDetail.type === ArticleTypeEnum.COLUMN,
)
const showTopVideo = computed(
() =>
isInterviewOrColumn.value &&
articleDetail.videoLocation === VideoPositionEnum.TOP &&
articleDetail.articleVideoUrl,
)
const showBottomVideo = computed(
() =>
isInterviewOrColumn.value &&
articleDetail.videoLocation === VideoPositionEnum.BOTTOM &&
articleDetail.articleVideoUrl,
)
const showPreview = ref(false) const showPreview = ref(false)
const currentPreviewIndex = ref(0) const currentPreviewIndex = ref(0)
const srcList = ref<string[]>([]) const srcList = ref<string[]>([])
......
...@@ -97,3 +97,11 @@ export enum UsageStatusEnum { ...@@ -97,3 +97,11 @@ export enum UsageStatusEnum {
// 已使用 // 已使用
USED = 1, USED = 1,
} }
// 视频位置枚举
export enum VideoPositionEnum {
// 顶部
TOP = 1,
// 底部
BOTTOM = 2,
}
...@@ -18,7 +18,7 @@ export const useUploadImg = (imgList: Ref<string[]> = ref([])) => { ...@@ -18,7 +18,7 @@ export const useUploadImg = (imgList: Ref<string[]> = ref([])) => {
}, },
}) })
const data = await promise const data = await promise
imgList.value.push(data.filePath) imgList.value = [...imgList.value, data.filePath]
} catch (error) { } catch (error) {
console.error('上传失败:', error) console.error('上传失败:', error)
} finally { } finally {
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
> >
<div class="content-wrapper p-6"> <div class="content-wrapper p-6">
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<transition name="fade" mode="out-in"> <transition name="fade-home" mode="out-in">
<keep-alive> <keep-alive>
<component :is="Component" :key="getThirdLevelKey(route)" /> <component :is="Component" :key="getThirdLevelKey(route)" />
</keep-alive> </keep-alive>
...@@ -519,22 +519,22 @@ provide(TABS_REF_KEY, tabsRef) ...@@ -519,22 +519,22 @@ provide(TABS_REF_KEY, tabsRef)
} }
} }
.fade-enter-from, .fade-home-enter-from,
.fade-leave-to { .fade-home-leave-to {
opacity: 0; opacity: 0;
transform: translateX(30px); transform: translateX(30px);
filter: blur(4px); filter: blur(4px);
} }
.fade-enter-to, .fade-home-enter-to,
.fade-leave-from { .fade-home-leave-from {
opacity: 1; opacity: 1;
transform: translateX(0); transform: translateX(0);
filter: blur(0); filter: blur(0);
} }
.fade-enter-active, .fade-home-enter-active,
.fade-leave-active { .fade-home-leave-active {
transition: all 0.3s ease; transition: all 0.3s ease;
} }
</style> </style>
...@@ -190,15 +190,15 @@ ...@@ -190,15 +190,15 @@
</el-form-item> </el-form-item>
<!-- 插入视频 顶部或者底部 radio --> <!-- 插入视频 顶部或者底部 radio -->
<el-form-item label="插入视频" prop="insertVideo"> <el-form-item label="插入视频" prop="videoLocation">
<el-radio-group v-model="form.insertVideo"> <el-radio-group v-model="form.videoLocation">
<el-radio :value="BooleanFlag.YES">顶部</el-radio> <el-radio :value="VideoPositionEnum.TOP">顶部</el-radio>
<el-radio :value="BooleanFlag.NO">底部</el-radio> <el-radio :value="VideoPositionEnum.BOTTOM">底部</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="视频" prop="videoUrl"> <el-form-item label="视频" prop="articleVideoUrl">
<UploadVideo v-model="form.videoUrl" btnClass="flex-col" /> <UploadVideo v-model="form.articleVideoUrl" btnClass="flex-col" />
</el-form-item> </el-form-item>
</template> </template>
</div> </div>
...@@ -254,6 +254,7 @@ import { ...@@ -254,6 +254,7 @@ import {
BooleanFlag, BooleanFlag,
ReleaseStatusTypeEnum, ReleaseStatusTypeEnum,
articleTypeListOptions, articleTypeListOptions,
VideoPositionEnum,
} from '@/constants' } from '@/constants'
import UploadFile from '@/components/common/UploadFile/index.vue' import UploadFile from '@/components/common/UploadFile/index.vue'
import UploadVideo from '@/components/common/UploadVideo/index.vue' import UploadVideo from '@/components/common/UploadVideo/index.vue'
...@@ -314,8 +315,8 @@ const [form, resetForm] = useResetData({ ...@@ -314,8 +315,8 @@ const [form, resetForm] = useResetData({
pushList: [], pushList: [],
// 视频 // 视频
videoUrl: '', videoLocation: VideoPositionEnum.TOP,
insertVideo: BooleanFlag.NO, articleVideoUrl: '',
}) })
const rules: Record<string, FormItemRule[]> = { const rules: Record<string, FormItemRule[]> = {
......
...@@ -236,7 +236,7 @@ ...@@ -236,7 +236,7 @@
> >
<el-icon class="text-base"><IEpChatRound /></el-icon> <el-icon class="text-base"><IEpChatRound /></el-icon>
<span> <span>
{{ answer.childrenNum ? `${answer.childrenNum} 条评论` : '添加评论' }} {{ answer.childrenNum ? `${answer.childrenNum} 条评论` : '回复' }}
</span> </span>
</button> </button>
</div> </div>
......
...@@ -138,7 +138,7 @@ ...@@ -138,7 +138,7 @@
<div class="flex-1 min-w-0"> <div class="flex-1 min-w-0">
<div class="bg-white rounded-lg shadow-sm min-h-500px"> <div class="bg-white rounded-lg shadow-sm min-h-500px">
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<transition name="fade" mode="in-out"> <transition name="fade-user" mode="out-in">
<keep-alive> <keep-alive>
<component :is="Component" :key="getThirdLevelKey(route)" ref="componentRef" /> <component :is="Component" :key="getThirdLevelKey(route)" ref="componentRef" />
</keep-alive> </keep-alive>
...@@ -471,4 +471,20 @@ onMounted(() => { ...@@ -471,4 +471,20 @@ onMounted(() => {
transform: translateY(-20px) rotateY(10deg) translateZ(200px) scale(0.9); transform: translateY(-20px) rotateY(10deg) translateZ(200px) scale(0.9);
filter: blur(6px); filter: blur(6px);
} }
.fade-user-enter-from,
.fade-user-leave-to {
opacity: 0;
transform: translateX(10px);
filter: blur(4px);
}
.fade-user-enter-to,
.fade-user-leave-from {
opacity: 1;
transform: translateX(0);
filter: blur(0);
}
.fade-user-enter-active,
.fade-user-leave-active {
transition: all 0.3s ease;
}
</style> </style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment