Commit 0aea8f16 by lijiabin

【需求 17679】 perf: 优化个人中心页面相关内容

parent ebc96968
...@@ -11,6 +11,12 @@ import type { ...@@ -11,6 +11,12 @@ import type {
SelfPraiseSearchParams, SelfPraiseSearchParams,
SelfPraiseDetailDto, SelfPraiseDetailDto,
OfficialAccountItemDto, OfficialAccountItemDto,
SelfCaseItemDto,
SelfCommentItemDto,
SelfCommentSearchParams,
SelfDraftSearchParams,
SelfTaskSearchParams,
SelfTaskItemDto,
} from './types' } from './types'
import type { BackendServicePageResult, PageSearchParams } from '@/utils/request/types' import type { BackendServicePageResult, PageSearchParams } from '@/utils/request/types'
...@@ -50,7 +56,7 @@ export const getSelfPublishList = (data: SelfPublishSearchParams) => { ...@@ -50,7 +56,7 @@ export const getSelfPublishList = (data: SelfPublishSearchParams) => {
/** /**
* 获取我的草稿列表 * 获取我的草稿列表
*/ */
export const getSelfDraftList = (data: PageSearchParams) => { export const getSelfDraftList = (data: SelfDraftSearchParams) => {
return service.request<BackendServicePageResult<SelfPublishDetailDto>>({ return service.request<BackendServicePageResult<SelfPublishDetailDto>>({
url: '/api/personalCenter/selfDraft', url: '/api/personalCenter/selfDraft',
method: 'POST', method: 'POST',
...@@ -84,15 +90,7 @@ export const getSelfPraiseList = (data: SelfPraiseSearchParams) => { ...@@ -84,15 +90,7 @@ export const getSelfPraiseList = (data: SelfPraiseSearchParams) => {
* 获取我的案例库列表 * 获取我的案例库列表
*/ */
export const getSelfCaseList = (data: PageSearchParams) => { export const getSelfCaseList = (data: PageSearchParams) => {
return service.request< return service.request<BackendServicePageResult<SelfCaseItemDto>>({
BackendServicePageResult<{
id: number
title: string
content: string
createTime: string
updateTime: string
}>
>({
url: '/api/personalCenter/selfCase', url: '/api/personalCenter/selfCase',
method: 'POST', method: 'POST',
data, data,
...@@ -102,8 +100,8 @@ export const getSelfCaseList = (data: PageSearchParams) => { ...@@ -102,8 +100,8 @@ export const getSelfCaseList = (data: PageSearchParams) => {
/** /**
* 获取我的任务列表 * 获取我的任务列表
*/ */
export const getSelfTaskList = (data: PageSearchParams) => { export const getSelfTaskList = (data: SelfTaskSearchParams) => {
return service.request<BackendServicePageResult<SelfPublishDetailDto>>({ return service.request<BackendServicePageResult<SelfTaskItemDto>>({
url: '/api/personalCenter/selfTaskConfig', url: '/api/personalCenter/selfTaskConfig',
method: 'POST', method: 'POST',
data, data,
...@@ -113,8 +111,8 @@ export const getSelfTaskList = (data: PageSearchParams) => { ...@@ -113,8 +111,8 @@ export const getSelfTaskList = (data: PageSearchParams) => {
/** /**
* 评论回复 * 评论回复
*/ */
export const getSelfCommentList = (data: PageSearchParams) => { export const getSelfCommentList = (data: SelfCommentSearchParams) => {
return service.request({ return service.request<BackendServicePageResult<SelfCommentItemDto>>({
url: '/api/personalCenter/selfComment', url: '/api/personalCenter/selfComment',
method: 'POST', method: 'POST',
data, data,
......
import { ArticleTypeEnum, AuditStatusEnum, BooleanFlag } from '@/constants' import {
ArticleTypeEnum,
AuditStatusEnum,
BooleanFlag,
CommentTypeEnum,
TaskDateLimitTypeEnum,
TaskTypeEnum,
} from '@/constants'
import type { PageSearchParams } from '@/utils/request/types' import type { PageSearchParams } from '@/utils/request/types'
export interface SelfPublishSearchParams extends PageSearchParams { export interface SelfPublishSearchParams extends PageSearchParams {
...@@ -75,6 +82,11 @@ export interface SelfPraiseDetailDto { ...@@ -75,6 +82,11 @@ export interface SelfPraiseDetailDto {
viewCount: number viewCount: number
} }
//草稿搜索
export interface SelfDraftSearchParams extends PageSearchParams {
type: ArticleTypeEnum
}
// 我的草稿 详情 // 我的草稿 详情
export interface SelfDraftDetailDto { export interface SelfDraftDetailDto {
id: number id: number
...@@ -126,7 +138,7 @@ export interface AuditListItemDto { ...@@ -126,7 +138,7 @@ export interface AuditListItemDto {
*/ */
export interface AuditArticleDto { export interface AuditArticleDto {
articleId: number articleId: number
auditResult: Exclude<AuditStatusEnum, AuditStatusEnum.UNAUDITED> auditResult: AuditStatusEnum
auditRemark?: string auditRemark?: string
} }
...@@ -171,3 +183,98 @@ export interface OfficialAccountItemDto { ...@@ -171,3 +183,98 @@ export interface OfficialAccountItemDto {
userId: number userId: number
version: null version: null
} }
/**
* 我的案例库列表
*/
export interface SelfCaseItemDto {
caseType: string
content: string
createTime: number
createUser: number
cultureKeywordMain: string
cultureKeywordSecond: string
cultureRelation: number
dataSources: number
deptId: string
deptName: string
id: number
integrity: number
isDelete: number
isDispose: number
isUse: number
mainScene: string
minorScene: string
number: string
sceneKeywordMain: string
sceneKeywordSecond: string
sourceProject: string
sourceTime: number
sourceType: string
sourceUser: number
title: string
yearKeywordMain: null
yearKeywordSecond: null
}
/**
* 我的评论列表查询参数
*/
export interface SelfCommentSearchParams extends PageSearchParams {
messageType: CommentTypeEnum
}
/**
* 我的评论列表
*/
export interface SelfCommentItemDto {
articleId: number
avatar: string
children: null
content: string
createTime: number
createUserId: number
description: string
faceUrl: string
hasPraise: boolean
hiddenAvatar: string
hiddenName: string
id: number
isFeatured: boolean
isRecommend: boolean
isTop: boolean
pid: number
postPriseCount: number
region: string
regionHide: boolean
replyId: number
replyName: string
replyUser: string
title: string
type: string
userId: number
viewCount: number
}
// 我的任务
export interface SelfTaskSearchParams extends PageSearchParams {
taskType: TaskTypeEnum
}
export interface SelfTaskItemDto {
completedTasks: number
currentCount: number
description: string
id: number
jumpUrl: string
limitCount: number
limitType: TaskDateLimitTypeEnum
periodKey: string
rewardType: number
rewardValue: number
status: number
svgName: string
taskKey: string
taskType: number
title: string
totalTasks: number
}
...@@ -6,8 +6,20 @@ ...@@ -6,8 +6,20 @@
<!-- 底部fixed --> <!-- 底部fixed -->
<div class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 shadow-lg"> <div class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 shadow-lg">
<div class="max-w-7xl mx-auto px-6 py-4 flex justify-center items-center gap-4"> <div class="max-w-7xl mx-auto px-6 py-4 flex justify-center items-center gap-4">
<el-button type="primary" @click="handleAgree" class="min-w-[120px]"> 通过 </el-button> <el-button
<el-button type="danger" @click="handleReject" class="min-w-[120px]"> 驳回 </el-button> type="primary"
@click="handleAudit(AuditStatusEnum.AGREED)"
class="min-w-[120px]"
>
通过
</el-button>
<el-button
type="danger"
@click="handleAudit(AuditStatusEnum.REJECTED)"
class="min-w-[120px]"
>
驳回
</el-button>
</div> </div>
</div> </div>
</div> </div>
...@@ -18,37 +30,32 @@ import ArticleContent from '@/components/common/ArticleContent/index.vue' ...@@ -18,37 +30,32 @@ import ArticleContent from '@/components/common/ArticleContent/index.vue'
import { type ArticleItemDto } from '@/api' import { type ArticleItemDto } from '@/api'
import { getArticleDetail, auditArticle } from '@/api' import { getArticleDetail, auditArticle } from '@/api'
import { AuditStatusEnum } from '@/constants/enums' import { AuditStatusEnum } from '@/constants/enums'
import type { AuditArticleDto } from '@/api'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const id = route.params.id as string const id = route.params.id as string
const articleDetail = ref({} as ArticleItemDto) const articleDetail = ref({} as ArticleItemDto)
const loading = ref(false) const loading = ref(false)
const handleAgree = async () => {
await auditArticle({ const handleAudit = async (auditStatus: AuditStatusEnum) => {
const auditData: AuditArticleDto = {
articleId: Number(id), articleId: Number(id),
auditResult: AuditStatusEnum.AGREED, auditResult: auditStatus,
}) }
ElMessage.success('审核通过') if (auditStatus === AuditStatusEnum.REJECTED) {
router.push('/') const { value } = await ElMessageBox.prompt('请输入拒绝理由', '提示', {
} confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^\S+$/,
inputErrorMessage: '请输入拒绝理由',
})
const handleReject = async () => { auditData.auditRemark = value
const remark = await ElMessageBox.prompt('请输入审核驳回原因', '审核驳回', {
confirmButtonText: '确定',
cancelButtonText: '取消',
})
if (!remark.value) {
ElMessage.warning('请输入审核驳回原因')
return
} }
await auditArticle({ await auditArticle(auditData)
articleId: Number(id), ElMessage.success('审核成功')
auditResult: AuditStatusEnum.REJECTED, router.replace('/')
auditRemark: remark.value,
})
ElMessage.success('审核驳回')
} }
onMounted(async () => { onMounted(async () => {
......
...@@ -2,21 +2,29 @@ ...@@ -2,21 +2,29 @@
<div class="flex-1 flex flex-col" v-loading="loading"> <div class="flex-1 flex flex-col" v-loading="loading">
<!-- List Container --> <!-- List Container -->
<div class="flex-1 p-4 pt-1"> <div class="flex-1 p-4 pt-1">
<el-tabs v-model="searchParams.isAudit" @tab-change="toggleTab"> <div class="relative">
<el-tab-pane <el-tabs v-model="searchParams.isAudit" @tab-change="toggleTab">
v-for="tab in auditTypeListOptions" <el-tab-pane
:key="tab.value" v-for="tab in auditTypeListOptions"
:label="tab.label" :key="tab.value"
:name="tab.value" :label="tab.label"
/> :name="tab.value"
</el-tabs> />
</el-tabs>
<div class="absolute right-0 top-2.5 z-1000">
<el-icon
size="15"
class="cursor-pointer hover:rotate-180 transition-all duration-300"
@click="refresh"
><Refresh
/></el-icon>
</div>
</div>
<div v-if="!list.length" class="flex flex-col items-center justify-center h-64"> <div v-if="!list.length" class="flex flex-col items-center justify-center h-64">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4"> <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<el-icon class="text-2xl text-gray-300"><Document /></el-icon> <el-icon class="text-2xl text-gray-300"><Document /></el-icon>
</div> </div>
<div class="text-gray-500 text-lg mb-2">暂无内容</div> <div class="text-gray-500 text-lg mb-2">暂无内容</div>
<div class="text-gray-400 text-sm">{{ getEmptyText() }}</div>
</div> </div>
<div v-else class="space-y-4"> <div v-else class="space-y-4">
...@@ -60,6 +68,10 @@ ...@@ -60,6 +68,10 @@
v-if="searchParams.isAudit === AuditStatusEnum.UNAUDITED" v-if="searchParams.isAudit === AuditStatusEnum.UNAUDITED"
class="flex items-center text-gray-400 text-sm ml-4" class="flex items-center text-gray-400 text-sm ml-4"
> >
<el-button type="info" link @click="router.push(`/auditArticle/${item.id}`)"
>去详情页审核</el-button
>
<el-button <el-button
type="primary" type="primary"
link link
...@@ -112,9 +124,12 @@ import { auditTypeListOptions } from '@/constants/options' ...@@ -112,9 +124,12 @@ import { auditTypeListOptions } from '@/constants/options'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { AuditStatusEnum } from '@/constants' import { AuditStatusEnum } from '@/constants'
import type { AuditArticleDto } from '@/api' import type { AuditArticleDto } from '@/api'
import type { TabPaneName } from 'element-plus'
const router = useRouter()
const toggleTab = (key: AuditStatusEnum) => { const toggleTab = (key: TabPaneName) => {
searchParams.value.isAudit = key searchParams.value.isAudit = key as AuditStatusEnum
refresh() refresh()
} }
...@@ -129,20 +144,20 @@ const { list, loading, searchParams, total, refresh, goToPage, changePageSize } ...@@ -129,20 +144,20 @@ const { list, loading, searchParams, total, refresh, goToPage, changePageSize }
) )
const handleAudit = async (data: AuditArticleDto) => { const handleAudit = async (data: AuditArticleDto) => {
if (data.auditResult === AuditStatusEnum.REJECTED) {
const { value } = await ElMessageBox.prompt('请输入拒绝理由', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^\S+$/,
inputErrorMessage: '请输入拒绝理由',
})
data.auditRemark = value
}
await auditArticle(data) await auditArticle(data)
ElMessage.success('审核成功') ElMessage.success('审核成功')
refresh()
}
const getEmptyText = () => { refresh()
const emptyTexts: Record<string, string> = {
posts: '还没有发布任何帖子',
videos: '还没有上传任何视频',
questions: '还没有提出任何问题',
articles: '还没有发表任何专栏文章',
practice: '还没有分享任何实践经验',
interviews: '还没有参与任何专访',
}
return emptyTexts[searchParams.value.isAudit] || '暂无数据'
} }
</script> </script>
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
<el-icon class="text-2xl text-gray-300"><Document /></el-icon> <el-icon class="text-2xl text-gray-300"><Document /></el-icon>
</div> </div>
<div class="text-gray-500 text-lg mb-2">暂无内容</div> <div class="text-gray-500 text-lg mb-2">暂无内容</div>
<div class="text-gray-400 text-sm">{{ getEmptyText() }}</div>
</div> </div>
<div v-else class="space-y-4"> <div v-else class="space-y-4">
...@@ -23,10 +22,10 @@ ...@@ -23,10 +22,10 @@
<span class="mr-2"> <span class="mr-2">
{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }} {{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span> </span>
<span class="mr-2">浏览 {{ item.viewCount }}</span> <!-- <span class="mr-2">浏览 {{ item.viewCount }}</span>
<span class="mr-2">点赞 {{ item.replyCount }}</span> <span class="mr-2">点赞 {{ item.replyCount }}</span>
<span class="mr-2">评论 {{ item.collectionCount }}</span> <span class="mr-2">评论 {{ item.collectionCount }}</span>
<span class="mr-2">收藏 {{ item.praiseCount }}</span> <span class="mr-2">收藏 {{ item.praiseCount }}</span> -->
</div> </div>
</div> </div>
...@@ -64,35 +63,8 @@ import { Document } from '@element-plus/icons-vue' ...@@ -64,35 +63,8 @@ import { Document } from '@element-plus/icons-vue'
import { getSelfCaseList } from '@/api' import { getSelfCaseList } from '@/api'
import { usePageSearch } from '@/hooks' import { usePageSearch } from '@/hooks'
import { articleTypeListOptions } from '@/constants/options'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { ArticleTypeEnum } from '@/constants/enums'
const toggleTab = (key: string) => { const { list, loading, searchParams, total, goToPage, changePageSize } =
searchParams.value.type = key
refresh()
}
// State
const { list, loading, searchParams, total, refresh, goToPage, changePageSize } =
usePageSearch(getSelfCaseList) usePageSearch(getSelfCaseList)
// Computed
const paginatedList = computed(() => {
const start = (searchParams.value.current - 1) * searchParams.value.size
const end = start + searchParams.value.size
return list.value.slice(start, end)
})
const getEmptyText = () => {
const emptyTexts: Record<string, string> = {
posts: '还没有发布任何帖子',
videos: '还没有上传任何视频',
questions: '还没有提出任何问题',
articles: '还没有发表任何专栏文章',
practice: '还没有分享任何实践经验',
interviews: '还没有参与任何专访',
}
return emptyTexts[searchParams.type] || '暂无数据'
}
</script> </script>
<template> <template>
<div class="flex-1 flex flex-col" v-loading="loading"> <div class="flex-1 flex flex-col" v-loading="loading">
<div class="flex-1 p-4 pt-1"> <div class="flex-1 p-4 pt-1">
<el-tabs v-model="searchParams.type" @tab-change="toggleTab"> <div class="relative">
<el-tab-pane <el-tabs v-model="searchParams.type" @tab-change="toggleTab">
v-for="tab in articleTypeListOptions" <el-tab-pane
:key="tab.value" v-for="tab in articleTypeListOptions"
:label="tab.label" :key="tab.value"
:name="tab.value" :label="tab.label"
/> :name="tab.value"
</el-tabs> />
</el-tabs>
<div class="absolute right-0 top-2.5 z-1000">
<el-icon
size="15"
class="cursor-pointer hover:rotate-180 transition-all duration-300"
@click="refresh"
><Refresh
/></el-icon>
</div>
</div>
<div v-if="!list.length" class="flex flex-col items-center justify-center h-64"> <div v-if="!list.length" class="flex flex-col items-center justify-center h-64">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4"> <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
...@@ -64,7 +74,7 @@ ...@@ -64,7 +74,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Document } from '@element-plus/icons-vue' import { Document, Refresh } from '@element-plus/icons-vue'
import { getSelfCollectList } from '@/api' import { getSelfCollectList } from '@/api'
import { usePageSearch } from '@/hooks' import { usePageSearch } from '@/hooks'
......
...@@ -2,14 +2,24 @@ ...@@ -2,14 +2,24 @@
<div class="flex-1 flex flex-col" v-loading="loading"> <div class="flex-1 flex flex-col" v-loading="loading">
<!-- List Container --> <!-- List Container -->
<div class="flex-1 p-4 pt-1"> <div class="flex-1 p-4 pt-1">
<el-tabs v-model="searchParams.messageType" @tab-change="toggleTab"> <div class="relative">
<el-tab-pane <el-tabs v-model="searchParams.messageType" @tab-change="toggleTab">
v-for="tab in commentTypeListOptions" <el-tab-pane
:key="tab.value" v-for="tab in commentTypeListOptions"
:label="tab.label" :key="tab.value"
:name="tab.value" :label="tab.label"
/> :name="tab.value"
</el-tabs> />
</el-tabs>
<div class="absolute right-0 top-2.5 z-1000">
<el-icon
size="15"
class="cursor-pointer hover:rotate-180 transition-all duration-300"
@click="refresh"
><Refresh
/></el-icon>
</div>
</div>
<div v-if="!list.length" class="flex flex-col items-center justify-center h-64"> <div v-if="!list.length" class="flex flex-col items-center justify-center h-64">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4"> <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
...@@ -31,10 +41,10 @@ ...@@ -31,10 +41,10 @@
<span class="mr-2"> <span class="mr-2">
{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }} {{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span> </span>
<span class="mr-2">浏览 {{ item.viewCount }}</span> <!-- <span class="mr-2">浏览 {{ item.viewCount }}</span>
<span class="mr-2">点赞 {{ item.replyCount }}</span> <span class="mr-2">点赞 {{ item.replyCount }}</span>
<span class="mr-2">评论 {{ item.collectionCount }}</span> <span class="mr-2">评论 {{ item.collectionCount }}</span>
<span class="mr-2">收藏 {{ item.praiseCount }}</span> <span class="mr-2">收藏 {{ item.praiseCount }}</span> -->
</div> </div>
</div> </div>
...@@ -68,15 +78,16 @@ ...@@ -68,15 +78,16 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Document } from '@element-plus/icons-vue' import { Document, Refresh } from '@element-plus/icons-vue'
import { getSelfCommentList, deleteComment } from '@/api' import { getSelfCommentList, deleteComment } from '@/api'
import { usePageSearch } from '@/hooks' import { usePageSearch } from '@/hooks'
import { commentTypeListOptions } from '@/constants/options' import { commentTypeListOptions } from '@/constants/options'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { CommentTypeEnum } from '@/constants/enums' import { CommentTypeEnum } from '@/constants/enums'
import type { TabPaneName } from 'element-plus'
const toggleTab = (key: number) => { const toggleTab = (key: TabPaneName) => {
searchParams.value.messageType = key searchParams.value.messageType = key as CommentTypeEnum
refresh() refresh()
} }
......
<template>
<div class="flex-1 flex flex-col" v-loading="loading">
<!-- List Container -->
<div class="flex-1 p-4 pt-1">
<el-tabs v-model="searchParams.type" @tab-change="toggleTab">
<el-tab-pane
v-for="tab in articleTypeListOptions"
:key="tab.value"
:label="tab.label"
:name="tab.value"
/>
</el-tabs>
<div v-if="!list.length" class="flex flex-col items-center justify-center h-64">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<el-icon class="text-2xl text-gray-300"><Document /></el-icon>
</div>
<div class="text-gray-500 text-lg mb-2">暂无内容</div>
<div class="text-gray-400 text-sm">{{ getEmptyText() }}</div>
</div>
<div v-else class="space-y-4">
<div
v-for="item in list"
:key="item.id"
class="flex items-center p-2 rounded-lg hover:bg-gray-100 transition-colors cursor-pointer"
>
<!-- Content -->
<div class="flex-1 min-w-0">
<div class="text-gray-900 font-medium truncate">{{ item.title }}</div>
<div class="text-gray-500 text-sm mt-1 truncate">
<span class="mr-2">
{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span>
<span class="mr-2">浏览 {{ item.viewCount }}</span>
<span class="mr-2">点赞 {{ item.replyCount }}</span>
<span class="mr-2">评论 {{ item.collectionCount }}</span>
<span class="mr-2">收藏 {{ item.praiseCount }}</span>
</div>
</div>
<!-- Meta Info -->
<div class="flex items-center text-gray-400 text-sm ml-4">
<el-button type="primary" link>编辑</el-button>
<el-button type="danger" link>删除</el-button>
</div>
</div>
</div>
</div>
<div
v-if="list.length"
class="flex items-center justify-end px-6 py-4 border-t border-gray-200"
>
<div class="pagination-wrapper bg-white rounded-lg shadow-sm border border-gray-100 p-3">
<el-pagination
v-model:current-page="searchParams.current"
v-model:page-size="searchParams.size"
@size-change="changePageSize"
@current-change="goToPage"
:page-sizes="[10, 20, 30, 40]"
layout="prev, pager, next, jumper, total"
:total="total"
class="custom-pagination"
/>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { Document } from '@element-plus/icons-vue'
import { getSelfDraftList } from '@/api'
import { usePageSearch } from '@/hooks'
import { articleTypeListOptions } from '@/constants/options'
import dayjs from 'dayjs'
import { ArticleTypeEnum } from '@/constants/enums'
const toggleTab = (key: string) => {
searchParams.value.type = key
refresh()
}
// State
const { list, loading, searchParams, total, refresh, goToPage, changePageSize } = usePageSearch(
getSelfDraftList,
{
defaultParams: {
type: ArticleTypeEnum.POST,
},
},
)
// Computed
const paginatedList = computed(() => {
const start = (searchParams.value.current - 1) * searchParams.value.size
const end = start + searchParams.value.size
return list.value.slice(start, end)
})
const getEmptyText = () => {
const emptyTexts: Record<string, string> = {
posts: '还没有发布任何帖子',
videos: '还没有上传任何视频',
questions: '还没有提出任何问题',
articles: '还没有发表任何专栏文章',
practice: '还没有分享任何实践经验',
interviews: '还没有参与任何专访',
}
return emptyTexts[searchParams.type] || '暂无数据'
}
</script>
...@@ -2,21 +2,30 @@ ...@@ -2,21 +2,30 @@
<div class="flex-1 flex flex-col" v-loading="loading"> <div class="flex-1 flex flex-col" v-loading="loading">
<!-- List Container --> <!-- List Container -->
<div class="flex-1 p-4 pt-1"> <div class="flex-1 p-4 pt-1">
<el-tabs v-model="searchParams.type" @tab-change="toggleTab"> <div class="relative">
<el-tab-pane <el-tabs v-model="searchParams.type" @tab-change="toggleTab">
v-for="tab in articleTypeListOptions" <el-tab-pane
:key="tab.value" v-for="tab in articleTypeListOptions"
:label="tab.label" :key="tab.value"
:name="tab.value" :label="tab.label"
/> :name="tab.value"
</el-tabs> />
</el-tabs>
<div class="absolute right-0 top-2.5 z-1000">
<el-icon
size="15"
class="cursor-pointer hover:rotate-180 transition-all duration-300"
@click="refresh"
><Refresh
/></el-icon>
</div>
</div>
<div v-if="!list.length" class="flex flex-col items-center justify-center h-64"> <div v-if="!list.length" class="flex flex-col items-center justify-center h-64">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4"> <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<el-icon class="text-2xl text-gray-300"><Document /></el-icon> <el-icon class="text-2xl text-gray-300"><Document /></el-icon>
</div> </div>
<div class="text-gray-500 text-lg mb-2">暂无内容</div> <div class="text-gray-500 text-lg mb-2">暂无内容</div>
<div class="text-gray-400 text-sm">{{ getEmptyText() }}</div>
</div> </div>
<div v-else class="space-y-4"> <div v-else class="space-y-4">
...@@ -32,10 +41,10 @@ ...@@ -32,10 +41,10 @@
<span class="mr-2"> <span class="mr-2">
{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }} {{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span> </span>
<span class="mr-2">浏览 {{ item.viewCount }}</span> <!-- <span class="mr-2">浏览 {{ item.viewCount }}</span>
<span class="mr-2">点赞 {{ item.replyCount }}</span> <span class="mr-2">点赞 {{ item.replyCount }}</span>
<span class="mr-2">评论 {{ item.collectionCount }}</span> <span class="mr-2">评论 {{ item.collectionCount }}</span>
<span class="mr-2">收藏 {{ item.praiseCount }}</span> <span class="mr-2">收藏 {{ item.praiseCount }}</span> -->
</div> </div>
</div> </div>
...@@ -69,20 +78,20 @@ ...@@ -69,20 +78,20 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Document } from '@element-plus/icons-vue' import { Document, Refresh } from '@element-plus/icons-vue'
import { getSelfDraftList } from '@/api' import { getSelfDraftList } from '@/api'
import { usePageSearch } from '@/hooks' import { usePageSearch } from '@/hooks'
import { articleTypeListOptions } from '@/constants/options' import { articleTypeListOptions } from '@/constants/options'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { ArticleTypeEnum } from '@/constants/enums' import { ArticleTypeEnum } from '@/constants/enums'
import type { TabPaneName } from 'element-plus'
const toggleTab = (key: string) => { const toggleTab = (key: TabPaneName) => {
searchParams.value.type = key searchParams.value.type = key as ArticleTypeEnum
refresh() refresh()
} }
// State
const { list, loading, searchParams, total, refresh, goToPage, changePageSize } = usePageSearch( const { list, loading, searchParams, total, refresh, goToPage, changePageSize } = usePageSearch(
getSelfDraftList, getSelfDraftList,
{ {
...@@ -91,23 +100,4 @@ const { list, loading, searchParams, total, refresh, goToPage, changePageSize } ...@@ -91,23 +100,4 @@ const { list, loading, searchParams, total, refresh, goToPage, changePageSize }
}, },
}, },
) )
// Computed
const paginatedList = computed(() => {
const start = (searchParams.value.current - 1) * searchParams.value.size
const end = start + searchParams.value.size
return list.value.slice(start, end)
})
const getEmptyText = () => {
const emptyTexts: Record<string, string> = {
posts: '还没有发布任何帖子',
videos: '还没有上传任何视频',
questions: '还没有提出任何问题',
articles: '还没有发表任何专栏文章',
practice: '还没有分享任何实践经验',
interviews: '还没有参与任何专访',
}
return emptyTexts[searchParams.type] || '暂无数据'
}
</script> </script>
<template> <template>
<div class="flex-1 flex flex-col" v-loading="loading"> <div class="flex-1 flex flex-col" v-loading="loading">
<div class="flex-1 p-4 pt-1"> <div class="flex-1 p-4 pt-1">
<el-tabs v-model="searchParams.type" @tab-change="toggleTab"> <div class="relative">
<el-tab-pane <el-tabs v-model="searchParams.type" @tab-change="toggleTab">
v-for="tab in articleTypeListOptions" <el-tab-pane
:key="tab.value" v-for="tab in articleTypeListOptions"
:label="tab.label" :key="tab.value"
:name="tab.value" :label="tab.label"
/> :name="tab.value"
</el-tabs> />
</el-tabs>
<div class="absolute right-0 top-2.5 z-1000">
<el-icon
size="15"
class="cursor-pointer hover:rotate-180 transition-all duration-300"
@click="refresh"
><Refresh
/></el-icon>
</div>
</div>
<div v-if="!list.length" class="flex flex-col items-center justify-center h-64"> <div v-if="!list.length" class="flex flex-col items-center justify-center h-64">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4"> <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<el-icon class="text-2xl text-gray-300"><Document /></el-icon> <el-icon class="text-2xl text-gray-300"><Document /></el-icon>
...@@ -29,10 +38,10 @@ ...@@ -29,10 +38,10 @@
<span class="mr-2"> <span class="mr-2">
{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }} {{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span> </span>
<span class="mr-2">浏览 {{ item.viewCount }}</span> <!-- <span class="mr-2">浏览 {{ item.viewCount }}</span>
<span class="mr-2">点赞 {{ item.replyCount }}</span> <span class="mr-2">点赞 {{ item.replyCount }}</span>
<span class="mr-2">评论 {{ item.collectionCount }}</span> <span class="mr-2">评论 {{ item.collectionCount }}</span>
<span class="mr-2">收藏 {{ item.praiseCount }}</span> <span class="mr-2">收藏 {{ item.praiseCount }}</span> -->
</div> </div>
</div> </div>
......
<template> <template>
<div class="flex-1 flex flex-col" v-loading="loading"> <div class="flex-1 flex flex-col" v-loading="loading">
<div class="flex-1 p-4 pt-1"> <div class="flex-1 p-4 pt-1">
<el-tabs v-model="searchParams.type" @tab-change="toggleTab"> <div class="relative">
<el-tab-pane <el-tabs v-model="searchParams.type" @tab-change="toggleTab">
v-for="tab in articleTypeListOptions" <el-tab-pane
:key="tab.value" v-for="tab in articleTypeListOptions"
:label="tab.label" :key="tab.value"
:name="tab.value" :label="tab.label"
/> :name="tab.value"
</el-tabs> />
</el-tabs>
<div class="absolute right-0 top-2.5 z-1000">
<el-icon
size="15"
class="cursor-pointer hover:rotate-180 transition-all duration-300"
@click="refresh"
><Refresh
/></el-icon>
</div>
</div>
<div v-if="!list.length" class="flex flex-col items-center justify-center h-64"> <div v-if="!list.length" class="flex flex-col items-center justify-center h-64">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4"> <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
...@@ -65,7 +75,7 @@ ...@@ -65,7 +75,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Document } from '@element-plus/icons-vue' import { Document, Refresh } from '@element-plus/icons-vue'
import { getSelfPublishList, deleteArticle } from '@/api' import { getSelfPublishList, deleteArticle } from '@/api'
import { usePageSearch } from '@/hooks' import { usePageSearch } from '@/hooks'
import { articleTypeListOptions } from '@/constants/options' import { articleTypeListOptions } from '@/constants/options'
......
...@@ -2,14 +2,24 @@ ...@@ -2,14 +2,24 @@
<div class="flex-1 flex flex-col" v-loading="loading"> <div class="flex-1 flex flex-col" v-loading="loading">
<!-- List Container --> <!-- List Container -->
<div class="flex-1 p-4 pt-1"> <div class="flex-1 p-4 pt-1">
<el-tabs v-model="searchParams.taskType" @tab-change="toggleTab"> <div class="relative">
<el-tab-pane <el-tabs v-model="searchParams.taskType" @tab-change="toggleTab">
v-for="tab in taskTypeListOptions" <el-tab-pane
:key="tab.value" v-for="tab in taskTypeListOptions"
:label="tab.label" :key="tab.value"
:name="tab.value" :label="tab.label"
/> :name="tab.value"
</el-tabs> />
</el-tabs>
<div class="absolute right-0 top-2.5 z-1000">
<el-icon
size="15"
class="cursor-pointer hover:rotate-180 transition-all duration-300"
@click="refresh"
><Refresh
/></el-icon>
</div>
</div>
<div v-if="!list.length" class="flex flex-col items-center justify-center h-64"> <div v-if="!list.length" class="flex flex-col items-center justify-center h-64">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4"> <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
...@@ -71,12 +81,11 @@ ...@@ -71,12 +81,11 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Document } from '@element-plus/icons-vue' import { Document, Refresh } from '@element-plus/icons-vue'
import { getSelfTaskList } from '@/api' import { getSelfTaskList } from '@/api'
import { usePageSearch } from '@/hooks' import { usePageSearch } from '@/hooks'
import { taskTypeListOptions } from '@/constants/options' import { taskTypeListOptions } from '@/constants/options'
import dayjs from 'dayjs'
import { TaskTypeEnum } from '@/constants/enums' import { TaskTypeEnum } from '@/constants/enums'
import type { TabPaneName } from 'element-plus' import type { TabPaneName } from 'element-plus'
import { TaskDateLimitTypeText } from '@/constants' import { TaskDateLimitTypeText } from '@/constants'
......
...@@ -103,7 +103,7 @@ ...@@ -103,7 +103,7 @@
<div class="bg-white rounded-lg shadow-sm min-h-500px"> <div class="bg-white rounded-lg shadow-sm min-h-500px">
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<keep-alive> <keep-alive>
<component :is="currentComponent" /> <component :is="currentComponent" ref="currentComponentRef" />
</keep-alive> </keep-alive>
</transition> </transition>
</div> </div>
...@@ -171,6 +171,7 @@ const menuOfficialItems = [ ...@@ -171,6 +171,7 @@ const menuOfficialItems = [
{ key: 'audit', label: '审核列表', icon: User, component: SelfAudit, tab: '审核列表' }, { key: 'audit', label: '审核列表', icon: User, component: SelfAudit, tab: '审核列表' },
] ]
const currentComponentRef = useTemplateRef<InstanceType<typeof SelfAudit>>('currentComponentRef')
const currentComponent = computed( const currentComponent = computed(
() => () =>
[...menuUserItems, ...menuOfficialItems].find((item) => item.key === activeMenu.value) [...menuUserItems, ...menuOfficialItems].find((item) => item.key === activeMenu.value)
......
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