Commit a861b594 by lijiabin

【需求 17679】 perf: 继续优化 上传视频页面 、审核页面等

parent 0aea8f16
...@@ -9,6 +9,8 @@ declare global { ...@@ -9,6 +9,8 @@ declare global {
const EffectScope: typeof import('vue').EffectScope const EffectScope: typeof import('vue').EffectScope
const ElMessage: typeof import('element-plus/es').ElMessage const ElMessage: typeof import('element-plus/es').ElMessage
const ElMessageBox: typeof import('element-plus/es').ElMessageBox const ElMessageBox: typeof import('element-plus/es').ElMessageBox
const ElRadio: typeof import('element-plus/es').ElRadio
const ElRadioGroup: typeof import('element-plus/es').ElRadioGroup
const ElSwitch: typeof import('element-plus/es').ElSwitch const ElSwitch: typeof import('element-plus/es').ElSwitch
const computed: typeof import('vue').computed const computed: typeof import('vue').computed
const createApp: typeof import('vue').createApp const createApp: typeof import('vue').createApp
......
...@@ -21,6 +21,7 @@ declare module 'vue' { ...@@ -21,6 +21,7 @@ declare module 'vue' {
ElCard: typeof import('element-plus/es')['ElCard'] ElCard: typeof import('element-plus/es')['ElCard']
ElCarousel: typeof import('element-plus/es')['ElCarousel'] ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem'] ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElColorPicker: typeof import('element-plus/es')['ElColorPicker'] ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
...@@ -86,6 +87,7 @@ declare global { ...@@ -86,6 +87,7 @@ declare global {
const ElCard: typeof import('element-plus/es')['ElCard'] const ElCard: typeof import('element-plus/es')['ElCard']
const ElCarousel: typeof import('element-plus/es')['ElCarousel'] const ElCarousel: typeof import('element-plus/es')['ElCarousel']
const ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem'] const ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
const ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
const ElColorPicker: typeof import('element-plus/es')['ElColorPicker'] const ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
const ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] const ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
const ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] const ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
......
...@@ -10,6 +10,7 @@ import type { ...@@ -10,6 +10,7 @@ import type {
CommentSearchParams, CommentSearchParams,
InterviewItemDto, InterviewItemDto,
ColumnItemDto, ColumnItemDto,
VideoOptionDto,
} from './types' } from './types'
import type { BackendServicePageResult, PageSearchParams } from '@/utils/request/types' import type { BackendServicePageResult, PageSearchParams } from '@/utils/request/types'
...@@ -82,6 +83,16 @@ export const getColumnOptions = () => { ...@@ -82,6 +83,16 @@ export const getColumnOptions = () => {
} }
/** /**
* 获取视频栏目列表 --不分页 用户新增的时候传
*/
export const getVideoOptions = () => {
return service.request<VideoOptionDto[]>({
url: '/api/cultureColumn/listNoPage?type=video',
method: 'POST',
})
}
/**
* 获取首页专栏列表list —— 分页 * 获取首页专栏列表list —— 分页
*/ */
export const getColumnList = (data: PageSearchParams) => { export const getColumnList = (data: PageSearchParams) => {
......
...@@ -107,6 +107,7 @@ export interface AddOrUpdateVideoDto { ...@@ -107,6 +107,7 @@ export interface AddOrUpdateVideoDto {
isRecommend?: BooleanFlag isRecommend?: BooleanFlag
mainTagId: string | number mainTagId: string | number
tagList: { tagId: number; sort: number }[] | number[] tagList: { tagId: number; sort: number }[] | number[]
relateColumnId?: number
} }
/** /**
...@@ -144,6 +145,7 @@ export interface ArticleItemDto { ...@@ -144,6 +145,7 @@ export interface ArticleItemDto {
showName: string showName: string
videoDuration: string videoDuration: string
showComment?: boolean showComment?: boolean
relateColumn?: string
} }
/** /**
...@@ -199,6 +201,21 @@ export interface InterviewOptionDto { ...@@ -199,6 +201,21 @@ export interface InterviewOptionDto {
title: string title: string
type: 'column' type: 'column'
} }
/**
* 视频选项
*/
export interface VideoOptionDto {
color: string
createTime: number
createUserId: number
id: number
isDelete: BooleanFlag
sort: number
status: BooleanFlag
title: string
type: 'video'
}
/** /**
* 专访列表Item * 专访列表Item
...@@ -223,6 +240,10 @@ export interface InterviewItemDto { ...@@ -223,6 +240,10 @@ export interface InterviewItemDto {
viewCount: number viewCount: number
}[] }[]
} }
/**
* 视频选项
*/
/** /**
* 评论列表 * 评论列表
*/ */
......
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
· {{ articleDetail?.viewCount || 0 }} 阅读 · {{ articleDetail?.viewCount || 0 }} 阅读
</p> </p>
</div> </div>
<el-button v-if="articleDetail.relateColumn" type="primary" link>{{
articleDetail.relateColumn
}}</el-button>
<el-button type="primary" link>{{ articleType }}</el-button> <el-button type="primary" link>{{ articleType }}</el-button>
</div> </div>
</div> </div>
......
...@@ -112,7 +112,6 @@ const handleExceed: UploadProps['onExceed'] = (uploadFiles) => { ...@@ -112,7 +112,6 @@ const handleExceed: UploadProps['onExceed'] = (uploadFiles) => {
const handleChange: UploadProps['onChange'] = async (uploadFile, uploadFiles) => { const handleChange: UploadProps['onChange'] = async (uploadFile, uploadFiles) => {
console.log('uploadFiles', uploadFiles) console.log('uploadFiles', uploadFiles)
if (uploadFiles.length > props.limit) { if (uploadFiles.length > props.limit) {
debugger
ElMessage.error(`最多上传 ${props.limit} 个文件`) ElMessage.error(`最多上传 ${props.limit} 个文件`)
const index = fileList.value.findIndex((file) => file.uid === uploadFile.uid) const index = fileList.value.findIndex((file) => file.uid === uploadFile.uid)
if (index !== -1) { if (index !== -1) {
......
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
export * from './user' export * from './user'
export * from './tags' export * from './tags'
export * from './column' export * from './column'
export * from './interview'
export * from './video'
import { defineStore } from 'pinia'
import { getVideoOptions } from '@/api'
import type { VideoOptionDto } from '@/api/article/types'
/**
* 关于专访的相关数据 --不分页
*/
export const useVideoStore = defineStore('video', () => {
const videoList = ref<VideoOptionDto[]>([])
let isLoading = false
const fetchVideoList = async () => {
if (isLoading) return
if (videoList.value.length > 0) return
isLoading = true
try {
const { data } = await getVideoOptions()
videoList.value = data
console.log(videoList.value, 'videoList')
} catch (error) {
console.error(error)
} finally {
isLoading = false
}
}
fetchVideoList()
return { videoList, fetchVideoList }
})
...@@ -2,33 +2,52 @@ ...@@ -2,33 +2,52 @@
<div> <div>
<div v-loading="loading" v-if="list.length"> <div v-loading="loading" v-if="list.length">
<div class="w-full max-w-6xl mx-auto"> <div class="w-full max-w-6xl mx-auto">
<div v-for="(item, index) in list" :key="index" class="bg-white rounded-lg shadow-sm mb-6 overflow-hidden" <div
:style="{ '--dynamic-color': item.color }"> v-for="(item, index) in list"
<div class="flex items-center justify-between pr-4 pl-4 pt-2 pb-2 bg-green-50 border-b border-green-100" :key="index"
:style="{ backgroundColor: item.color, '--dynamic-color': item.color }"> class="bg-white rounded-lg shadow-sm mb-6 overflow-hidden"
:style="{ '--dynamic-color': item.color }"
>
<div
class="flex items-center justify-between pr-4 pl-4 pt-2 pb-2 bg-green-50 border-b border-green-100"
:style="{ backgroundColor: item.color, '--dynamic-color': item.color }"
>
<h3 class="text-lg font-medium text-gray-800 flex items-center"> <h3 class="text-lg font-medium text-gray-800 flex items-center">
<span class="w-1 h-5 mr-2 bg-#444"></span> <span class="w-1 h-5 mr-2 bg-#444"></span>
{{ item.title }} {{ item.title }}
</h3> </h3>
<div class="flex items-center cursor-pointer" @click="router.push({ <div
class="flex items-center cursor-pointer"
@click="
router.push({
path: '/searchPage', path: '/searchPage',
query: { query: {
type: ArticleTypeEnum.VIDEO type: ArticleTypeEnum.VIDEO,
} },
})"> })
"
>
<span class="mr-1 text-14px color-#606266">查看更多 >></span> <span class="mr-1 text-14px color-#606266">查看更多 >></span>
</div> </div>
</div> </div>
<div class="p-4"> <div class="p-4">
<div v-if="item.yaColumnVoList.length" class="grid grid-cols-1 md:grid-cols-3 gap-4"> <div v-if="item.yaColumnVoList.length" class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div v-for="i in item.yaColumnVoList" :key="i.articleId" class="group cursor-pointer" <div
@click="router.push(`/articleDetail/${i.articleId}`)"> v-for="i in item.yaColumnVoList"
:key="i.articleId"
class="group cursor-pointer"
@click="router.push(`/videoDetail/${i.articleId}`)"
>
<div class="relative mb-3 overflow-hidden rounded-lg"> <div class="relative mb-3 overflow-hidden rounded-lg">
<img :src="i.faceUrl" <img
class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300" /> :src="i.faceUrl"
<div v-if="i.isRecommend" class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300"
class="absolute top--1 left--1 w-15 h-7 z-1000 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"> />
<div
v-if="i.isRecommend"
class="absolute top--1 left--1 w-15 h-7 z-1000 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
>
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" /> <img class="w-6" src="@/assets/img/culture/recommend.png" alt="" />
<div class="text-12px text-#000 line-height-12px">推荐</div> <div class="text-12px text-#000 line-height-12px">推荐</div>
</div> </div>
...@@ -79,14 +98,23 @@ ...@@ -79,14 +98,23 @@
</div> </div>
<!-- 右侧:分页器 --> <!-- 右侧:分页器 -->
<div class="right"> <div class="right">
<div class="pagination-wrapper bg-white rounded-lg shadow-sm border border-gray-100 p-3"> <div
<el-pagination v-model:current-page="searchParams.current" v-model:page-size="searchParams.size" class="pagination-wrapper bg-white rounded-lg shadow-sm border border-gray-100 p-3"
:page-sizes="[15, 30, 45, 60]" layout="prev, pager, next, jumper, total" :total="total" >
class="custom-pagination" @current-change=" <el-pagination
v-model:current-page="searchParams.current"
v-model:page-size="searchParams.size"
:page-sizes="[15, 30, 45, 60]"
layout="prev, pager, next, jumper, total"
:total="total"
class="custom-pagination"
@current-change="
(e) => { (e) => {
; (handleBackTop(), goToPage(e)) ;(handleBackTop(), goToPage(e))
} }
" @size-change="changePageSize" /> "
@size-change="changePageSize"
/>
</div> </div>
</div> </div>
</div> </div>
......
<template> <template>
<div class="min-h-screen"> <div class="min-h-screen">
<el-form :model="form" :rules="rules" ref="formRef" label-position="top"> <el-form :model="form" :rules="rules" ref="formRef" label-position="top">
<div class="max-w-6xl mx-auto p-6 grid gap-6"> <div class="max-w-6xl mx-auto grid gap-6">
<!-- 左侧主要内容 --> <!-- 左侧主要内容 -->
<div class="col-span-8 space-y-6"> <div class="col-span-8 space-y-6">
<!-- 视频上传区域 --> <!-- 视频上传区域 -->
...@@ -120,6 +120,20 @@ ...@@ -120,6 +120,20 @@
/> />
</el-form-item> </el-form-item>
</div> </div>
<div class="mb-8">
<el-form-item prop="relateColumnId">
<label class="block text-sm font-semibold text-gray-700 mb-3"> 视频栏目选择 </label>
<el-select v-model="form.relateColumnId" placeholder="请选择视频栏目">
<el-option
v-for="item in videoList"
:key="item.id"
:label="item.title"
:value="item.id"
/>
</el-select>
</el-form-item>
</div>
</div> </div>
<div <div
...@@ -256,6 +270,11 @@ import { addOrUpdateArticle, uploadFile } from '@/api' ...@@ -256,6 +270,11 @@ import { addOrUpdateArticle, uploadFile } from '@/api'
import SelectTags from '@/components/common/SelectTags/index.vue' import SelectTags from '@/components/common/SelectTags/index.vue'
import type { TagItemDto, AddOrUpdateVideoDto } from '@/api' import type { TagItemDto, AddOrUpdateVideoDto } from '@/api'
import { Camera, Picture } from '@element-plus/icons-vue' import { Camera, Picture } from '@element-plus/icons-vue'
import { useVideoStore } from '@/stores'
import { storeToRefs } from 'pinia'
const videoStore = useVideoStore()
const { videoList } = storeToRefs(videoStore)
const router = useRouter() const router = useRouter()
...@@ -273,6 +292,7 @@ const [form, resetData] = useResetData<AddOrUpdateVideoDto>({ ...@@ -273,6 +292,7 @@ const [form, resetData] = useResetData<AddOrUpdateVideoDto>({
releaseStatus: ReleaseStatusTypeEnum.PUBLISH, releaseStatus: ReleaseStatusTypeEnum.PUBLISH,
faceUrl: '', // 封面URL faceUrl: '', // 封面URL
videoDuration: '', videoDuration: '',
relateColumnId: undefined,
}) })
// 封面选择相关 // 封面选择相关
...@@ -364,6 +384,7 @@ const rules = { ...@@ -364,6 +384,7 @@ const rules = {
content: [{ required: true, message: '请输入视频简介', trigger: 'blur' }], content: [{ required: true, message: '请输入视频简介', trigger: 'blur' }],
mainTagId: [{ required: true, message: '请选择主标签', trigger: 'change' }], mainTagId: [{ required: true, message: '请选择主标签', trigger: 'change' }],
faceUrl: [{ required: true, message: '请选择视频封面', trigger: 'change' }], faceUrl: [{ required: true, message: '请选择视频封面', trigger: 'change' }],
relateColumnId: [{ required: true, message: '请选择视频栏目', trigger: 'change' }],
} }
const tansformData = () => { const tansformData = () => {
......
...@@ -262,7 +262,6 @@ const handleSwitchAccount = async () => { ...@@ -262,7 +262,6 @@ const handleSwitchAccount = async () => {
isCodeLogin: 1, isCodeLogin: 1,
cutEmail: selectedEmail.value, cutEmail: selectedEmail.value,
}) })
debugger
done() done()
window.location.reload() window.location.reload()
} catch (error) { } catch (error) {
......
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