Commit 741b36b7 by lijiabin

【需求 17679】 feat: 完成帖子(除视频外)二次编辑功能

parent a25a5702
......@@ -24,6 +24,7 @@
8
</div> -->
</div>
<div class="flex-1">
<div class="flex items-center gap-2">
<h3 class="font-semibold text-gray-800">{{ articleDetail?.createUserName }}</h3>
......@@ -38,7 +39,16 @@
· {{ articleDetail?.viewCount || 0 }} 阅读
</p>
</div>
<!-- 再次编辑按钮 -->
<el-link
v-if="isAuthor"
type="primary"
:underline="false"
@click="router.push(`/publishLongArticle/${articleDetail.type}?id=${articleDetail.id}`)"
class="text-sm"
>
编辑
</el-link>
<!-- 优化后的右侧内容 -->
<div class="flex items-center gap-3">
<span
......@@ -112,15 +122,30 @@ import type { ArticleItemDto } from '@/api'
import { articleTypeListOptions, ArticleTypeEnum } from '@/constants'
import ActionMore from '@/components/common/ActionMore/index.vue'
import { jumpToUserHomePage } from '@/utils'
import { useUserStore } from '@/stores/user'
import { storeToRefs } from 'pinia'
const userStore = useUserStore()
const { userInfo } = storeToRefs(userStore)
const router = useRouter()
const { articleDetail } = defineProps<{
articleDetail: ArticleItemDto
isAudit: boolean // 是否是审核页面
}>()
const articleType = computed(() => {
return articleTypeListOptions.find((item) => item.value === articleDetail.type)?.label
})
// 是否是作者
const isAuthor = computed(() => {
return articleDetail.createUserId === userInfo.value.userId
})
// 如果类型是帖子 专栏 和 专访 就是html
const isHtml = computed(() => {
return articleDetail.content?.includes('<') || articleDetail.content?.includes('</')
return (
articleDetail.type === ArticleTypeEnum.POST ||
articleDetail.type === ArticleTypeEnum.COLUMN ||
articleDetail.type === ArticleTypeEnum.INTERVIEW
)
})
</script>
......@@ -17,8 +17,6 @@
</template>
<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import { onBeforeUnmount, ref, shallowRef, onMounted } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { uploadFile } from '@/api'
const mode = 'default'
......@@ -29,15 +27,14 @@ const editorRef = shallowRef()
// 内容 HTML
const valueHtml = defineModel<string>()
// 模拟 ajax 异步获取内容
onMounted(() => {
setTimeout(() => {
valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>'
}, 1500)
})
// 去掉上传视频的功能
const toolbarConfig = {}
const editorConfig = { placeholder: '请输入内容...', MENU_CONF: {} }
toolbarConfig.excludeKeys = ['group-video', 'group-more-video', 'group-more-video']
// 去掉上传视频
const editorConfig = {
placeholder: '请输入内容...',
MENU_CONF: {},
}
// 修改 uploadImage 菜单配置
......
......@@ -88,7 +88,6 @@
>专访</el-dropdown-item
>
</el-dropdown-menu>
<el-dropdown-item :command="ArticleTypeEnum.LONG_ARTICLE">长文章</el-dropdown-item>
</template>
</el-dropdown>
</div>
......@@ -143,23 +142,27 @@ const getSecondLevelKey = (route: RouteLocationNormalizedLoadedGeneric) => {
const key = Object.keys(route.params).length
? pathSegments.slice(0, 2).join('/')
: pathSegments.slice(0, 1).join('/')
console.log(key, '*********************')
// console.log(key, '*********************')
return key
}
const notShowPath = ['/videoDetail', '/articleDetail', '/questionDetail']
const showOnlineTime = computed(() => {
return !route.path.includes('/videoDetail') && !route.path.includes('/articleDetail')
return notShowPath.every((path) => !route.path.includes(path))
})
const handlePost = async (type: ArticleTypeEnum) => {
if (type === ArticleTypeEnum.VIDEO) {
router.push('/publishVideo')
} else if (type === ArticleTypeEnum.QUESTION) {
router.push(`/homePage/askTab#tabsRef?t=${Date.now()}`)
} else if (type === ArticleTypeEnum.LONG_ARTICLE) {
router.push('/publishLongArticle')
// router.push(`/homePage/askTab#tabsRef?t=${Date.now()}`)
router.push(`/publishLongArticle/${type}`)
} else if (type === ArticleTypeEnum.PRACTICE) {
router.push(`/publishLongArticle/${type}`)
// PublishDialogRef.value?.open(type)
} else {
PublishDialogRef.value?.open(type)
router.push(`/publishLongArticle/${type}`)
}
}
const isDropdownHover = ref(false)
......
......@@ -7,7 +7,7 @@
></ActionButtons>
<div class="lg:col-span-3">
<!-- 帖子主体 -->
<ArticleContent :articleDetail="articleDetail" />
<ArticleContent :articleDetail="articleDetail" :isAudit="false" />
<!-- 评论区 -->
<Comment
......@@ -29,7 +29,7 @@ import { ArticleTypeEnum } from '@/constants'
const commentRef = useTemplateRef<typeof Comment | null>('commentRef')
const route = useRoute()
const id = route.params.id as string
const id = Number(route.params.id)
const isReal = computed(() => {
return +(
......
<template>
<div v-loading="loading" class="px-20">
<div v-loading="loading">
<div class="lg:col-span-3 mb-20">
<ArticleContent :articleDetail="articleDetail" />
<ArticleContent :articleDetail="articleDetail" :isAudit="true" />
</div>
<!-- 底部fixed -->
<div class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 shadow-lg">
......
<template>
<div class="min-h-screen bg-[#fff] font-sans">
<div class="max-w-7xl mx-auto">
<!-- 顶部面包屑或标题(可选) -->
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-position="top"
class="grid grid-cols-12 gap-6 items-start"
>
<!-- 左侧:沉浸式创作区 (占 9 列) -->
<div class="col-span-12 lg:col-span-9 space-y-6">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-8 min-h-[80vh]">
<!-- 标题输入:模拟大标题风格,去掉边框 -->
<el-form-item prop="title" class="!border-b !border-gray-100">
<div class="min-h-screen bg-gradient-to-br pb-10">
<!-- 主编辑区域 -->
<div class="bg-white rounded-lg shadow-lg border border-gray-100/50 overflow-hidden">
<div class="px-10 py-5">
<!-- 标题输入 -->
<el-form-item prop="title" class="mb-8">
<el-input
v-model="form.title"
:placeholder="`在这里输入你的${text}标题...`"
class="title-input text-3xl font-bold"
show-word-limit
type="textarea"
:autosize="{ minRows: 1, maxRows: 3 }"
resize="none"
/>
</el-form-item>
<!-- 富文本编辑器 -->
<div>
<el-form-item prop="content">
<!-- 问吧和实践不是富文本 -->
<template
v-if="
form.type === ArticleTypeEnum.PRACTICE || form.type === ArticleTypeEnum.QUESTION
"
>
<el-input
v-model="form.title"
placeholder="请输入文章标题..."
class="title-input"
show-word-limit
:placeholder="`请输入${text}内容`"
v-model="form.content"
type="textarea"
resize="none"
:rows="30"
:maxlength="2000"
show-word-limit
/>
</el-form-item>
</template>
<template v-else>
<!-- 回显回来可能会有bug 所以需要key 重新渲染一下-->
<WangEditor :key v-model="form.content" class="min-h[90vh]" />
</template>
</el-form-item>
</div>
</div>
</div>
<!-- 富文本编辑器 -->
<div class="editor-container">
<el-form-item prop="content" class="!border-b !border-gray-100">
<WangEditor v-model="form.content" style="height: 800px" />
</el-form-item>
</div>
</div>
<!-- 底部固定按钮栏 -->
<div class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 shadow-lg">
<div class="max-w-[1200px] mx-auto px-4 py-4">
<div class="flex justify-center gap-4">
<el-button @click="handleClosed" class="rounded-lg min-w[120px]"> 取消 </el-button>
<el-button
type="primary"
:disabled="!canPublish"
@click="openDrawer"
class="px-6 py-2 bg-blue-500 hover:bg-blue-600 rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200 min-w[120px]"
>
{{ isEdit ? '编辑' : '发布' }}
</el-button>
</div>
</div>
</div>
<!-- 右侧:配置侧边栏 (占 3 列,吸顶) -->
<div class="col-span-12 lg:col-span-3 space-y-4">
<!-- 卡片1:基础设置 -->
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="font-bold text-gray-800 mb-4 flex items-center gap-2">
<div class="w-1 h-4 bg-blue-500 rounded-full"></div>
基础设置
</div>
<!-- 文章类型 -->
<el-form-item label="文章类型" prop="type">
<el-radio-group
v-model="form.type"
class="w-full grid grid-cols-3 gap-2"
fill="#3b82f6"
>
<el-radio-button :value="ArticleTypeEnum.POST">{{
articleTypeListOptions.find((item) => item.value === type)?.label
}}</el-radio-button>
</el-radio-group>
<!-- 右侧抽屉:发布配置 -->
<el-drawer
v-model="drawerVisible"
title="文章信息"
direction="rtl"
size="500px"
:before-close="handleDrawerClose"
>
<el-form ref="formRef" :model="form" :rules="rules" label-position="top" class="px-4">
<!-- 基础设置 -->
<div class="mb-6">
<!-- 文章类型 -->
<el-form-item label="文章类型" prop="type">
<el-button
type="primary"
class="px-6 py-2 bg-blue-500 hover:bg-blue-600 rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200 min-w[120px]"
>
{{ text }}
</el-button>
</el-form-item>
<!-- 内容图片 实践和问吧需要上传内容图片 然后默认第一张是封面图 -->
<template
v-if="form.type === ArticleTypeEnum.PRACTICE || form.type === ArticleTypeEnum.QUESTION"
>
<el-form-item label="图片">
<UploadFile v-model="form.imgUrl" :limit="1" class="w-full" />
</el-form-item>
</template>
<!-- 封面图 -->
<!-- 帖子 专栏专访 是富文本 需要上传封面图 封面图 -->
<template v-else>
<el-form-item label="封面图" prop="faceUrl">
<div class="w-full">
<UploadFile v-model="form.faceUrl" :limit="1" class="w-full" />
<div class="text-xs text-gray-400 mt-2">建议尺寸 16:9,支持 jpg/png</div>
</div>
<UploadFile v-model="form.faceUrl" :limit="1" class="w-full" />
</el-form-item>
</div>
</template>
<!-- 卡片2:高级配置 (专栏/专访特有) -->
<template
v-if="form.type === ArticleTypeEnum.COLUMN || form.type === ArticleTypeEnum.INTERVIEW"
>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="font-bold text-gray-800 mb-4 flex items-center gap-2">
<div class="w-1 h-4 bg-purple-500 rounded-full"></div>
专栏配置
</div>
<el-form-item label="所属栏目" prop="relateColumnId">
<el-select
v-model="form.relateColumnId"
placeholder="请选择专栏栏目"
class="w-full"
>
<el-option
v-for="item in columnList"
:key="item.id"
:value="item.id"
:label="item.title"
/>
</el-select>
</el-form-item>
<el-form-item label="主标签" prop="mainTagId">
<SelectTags v-model="form.mainTagId" class="w-full" />
</el-form-item>
<el-form-item label="副标签">
<SelectTags
v-model="form.tagList"
:filter-tags-fn="filterTagsFn"
:max-selected-tags="3"
class="w-full"
/>
</el-form-item>
<el-form-item label="推荐设置">
<div class="flex items-center justify-between w-full">
<span class="text-gray-600 text-sm">是否推荐</span>
<el-switch
v-model="form.isRecommend"
:active-value="BooleanFlag.YES"
:inactive-value="BooleanFlag.NO"
/>
</div>
</el-form-item>
<el-form-item v-if="form.type === ArticleTypeEnum.COLUMN">
<div class="flex items-center justify-between w-full">
<span class="text-gray-600 text-sm">同步同事吧</span>
<el-switch
v-model="form.isRelateColleague"
:active-value="BooleanFlag.YES"
:inactive-value="BooleanFlag.NO"
/>
</div>
</el-form-item>
</div>
<!-- 标签和主标签 除了帖子 都需要上传 -->
<template v-if="form.type !== ArticleTypeEnum.POST">
<el-form-item label="主标签" prop="mainTagId">
<SelectTags v-model="form.mainTagId" class="w-full" />
</el-form-item>
<el-form-item label="副标签 (最多3个)">
<SelectTags
v-model="form.tagList"
:filter-tags-fn="filterTagsFn"
:max-selected-tags="3"
class="w-full"
/>
</el-form-item>
</template>
</div>
<!-- 专栏配置 (条件显示) -->
<template
v-if="form.type === ArticleTypeEnum.COLUMN || form.type === ArticleTypeEnum.INTERVIEW"
>
<div class="mb-6">
<el-form-item label="所属栏目" prop="relateColumnId">
<el-select
v-model="form.relateColumnId"
:placeholder="`请选择${text}栏目`"
class="w-full"
>
<el-option
v-for="item in relateColumnList"
:key="item.id"
:value="item.id"
:label="item.title"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="主标签" prop="mainTagId">
<SelectTags v-model="form.mainTagId" class="w-full" />
</el-form-item>
<el-form-item label="副标签 (最多3个)">
<SelectTags
v-model="form.tagList"
:filter-tags-fn="filterTagsFn"
:max-selected-tags="3"
class="w-full"
/>
</el-form-item> -->
<!-- 卡片3:发布设置 -->
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="font-bold text-gray-800 mb-4 flex items-center gap-2">
<div class="w-1 h-4 bg-orange-500 rounded-full"></div>
发布设置
</div>
<el-form-item prop="sendType" class="!mb-2">
<el-radio-group v-model="form.sendType" class="flex flex-col gap-3 w-full">
<div
class="flex items-center p-3 rounded-lg border cursor-pointer transition-all"
:class="
form.sendType === SendTypeEnum.IMMEDIATE
? 'border-blue-500 bg-blue-50'
: 'border-gray-200 hover:border-blue-300'
"
@click="form.sendType = SendTypeEnum.IMMEDIATE"
>
<el-radio :value="SendTypeEnum.IMMEDIATE" class="!mr-2">立即发布</el-radio>
<span class="text-xs text-gray-400 ml-auto">当前时间</span>
</div>
<div
class="flex flex-col p-3 rounded-lg border cursor-pointer transition-all"
:class="
form.sendType === SendTypeEnum.SCHEDULED
? 'border-blue-500 bg-blue-50'
: 'border-gray-200 hover:border-blue-300'
"
@click="form.sendType = SendTypeEnum.SCHEDULED"
>
<div class="flex items-center mb-2">
<el-radio :value="SendTypeEnum.SCHEDULED" class="!mr-2">定时发布</el-radio>
</div>
<el-date-picker
v-if="form.sendType === SendTypeEnum.SCHEDULED"
v-model="form.sendTime"
type="datetime"
placeholder="选择时间"
class="!w-full"
:disabled-date="
(time: Date) => time.getTime() < Date.now() - 1000 * 60 * 60 * 24
"
value-format="X"
size="small"
/>
</div>
<el-form-item label="是否推荐" prop="isRecommend">
<!-- 改为radio单选框 -->
<el-radio-group v-model="form.isRecommend">
<el-radio :value="BooleanFlag.YES"></el-radio>
<el-radio :value="BooleanFlag.NO"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label="同步同事吧"
prop="isRelateColleague"
v-if="form.type === ArticleTypeEnum.COLUMN"
>
<el-radio-group v-model="form.isRelateColleague">
<el-radio :value="BooleanFlag.YES"></el-radio>
<el-radio :value="BooleanFlag.NO"></el-radio>
</el-radio-group>
</el-form-item>
</div>
<div class="mb-6 flex items-center justify-end w-full">
<div class="flex gap-3">
<el-button class="rounded-lg" @click="handleClosed">取消</el-button>
<el-button class="rounded-lg" @click="handleSubmit(ReleaseStatusTypeEnum.DRAFT)">
存草稿
</el-button>
<el-button
type="primary"
@click="handleSubmit(ReleaseStatusTypeEnum.PUBLISH)"
class="px-6 py-2 bg-blue-500 hover:bg-blue-600 rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200"
>
发布
</el-button>
</div>
</div>
</template>
<!-- 发布设置 -->
<div class="mb-6">
<el-form-item label="发布时间" prop="sendType">
<el-radio-group v-model="form.sendType">
<el-radio :value="SendTypeEnum.IMMEDIATE">立即发布</el-radio>
<el-radio :value="SendTypeEnum.SCHEDULED">定时发布</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.sendType === SendTypeEnum.SCHEDULED" prop="sendTime">
<el-date-picker
v-model="form.sendTime"
type="datetime"
placeholder="选择发布时间"
:disabled-date="(time: Date) => time.getTime() < Date.now() - 1000 * 60 * 60 * 24"
value-format="X"
/>
</el-form-item>
</div>
</el-form>
</div>
<!-- 抽屉底部按钮 -->
<template #footer>
<div class="flex gap-3 justify-end">
<el-button @click="handleDrawerClose" class="rounded-lg">取消</el-button>
<el-button @click="handleSubmit(ReleaseStatusTypeEnum.DRAFT)" class="rounded-lg">
存草稿
</el-button>
<el-button
:loading="loading"
type="primary"
@click="handleSubmit(ReleaseStatusTypeEnum.PUBLISH)"
class="px-6 py-2 bg-blue-500 hover:bg-blue-600 rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200 min-w[120px]"
>
确认{{ isEdit ? '编辑' : '发布' }}
</el-button>
</div>
</template>
</el-drawer>
</div>
</template>
......@@ -212,22 +222,41 @@ import {
import UploadFile from '@/components/common/UploadFile/index.vue'
import { useResetData } from '@/hooks'
import { useColumnStore } from '@/stores/column'
import { useInterviewStore } from '@/stores/interview'
import { storeToRefs } from 'pinia'
import { addOrUpdateArticle } from '@/api'
// ... (逻辑部分保持不变,直接复用您的即可)
import { addOrUpdateArticle, addOrUpdatePractice, getArticleDetail } from '@/api'
import { useRouter, useRoute } from 'vue-router'
const columnStore = useColumnStore()
const { columnList } = storeToRefs(columnStore)
const interviewStore = useInterviewStore()
const { interviewList } = storeToRefs(interviewStore)
const loading = ref(false)
const router = useRouter()
const route = useRoute()
const type = route.params.type as ArticleTypeEnum
const text = articleTypeListOptions.find((item) => item.value === type)?.label
const canPublish = computed(() => {
return form.value.title && form.value.content
})
const relateColumnList = computed(() =>
type === ArticleTypeEnum.COLUMN ? columnList.value : interviewList.value,
)
// 抽屉控制
const drawerVisible = ref(false)
const formRef = useTemplateRef<FormInstance>('formRef')
const [form, resetForm] = useResetData({
type: type,
type,
title: '',
content: '',
faceUrl: '',
relateColumnId: null, // 建议初始值设为null或undefined,配合placeholder
imgUrl: '',
relateColumnId: null,
mainTagId: '',
tagList: [],
isRelateColleague: BooleanFlag.NO,
......@@ -242,64 +271,179 @@ const rules = {
content: [{ required: true, message: '请输入文章内容', trigger: 'blur' }],
type: [{ required: true, message: '请选择文章类型', trigger: 'blur' }],
faceUrl: [{ required: true, message: '请上传封面图', trigger: 'blur' }],
imgUrl: [{ required: true, message: '请上传内容图片', trigger: 'blur' }],
sendType: [{ required: true, message: '请选择发布类型', trigger: 'blur' }],
sendTime: [{ required: true, message: '请选择发布时间', trigger: 'blur' }],
sendTime: [{ required: true, message: '请选择发布时间', trigger: 'trigger' }],
releaseStatus: [{ required: true, message: '请选择发布状态', trigger: 'blur' }],
mainTagId: [{ required: true, message: '请选择主标签', trigger: 'blur' }],
isRecommend: [{ required: true, message: '是否推荐', trigger: 'trigger' }],
isRelateColleague: [{ required: true, message: '是否同步同事吧', trigger: 'trigger' }],
relateColumnId: [{ required: true, message: '请选择对应的栏目', trigger: 'trigger' }],
}
const filterTagsFn = (allTags: any[]) => {
return allTags.filter((tag) => tag.id !== Number(form.value.mainTagId))
}
const handleSubmit = async () => {
const transFormData = (releaseStatus: ReleaseStatusTypeEnum) => {
const { tagList, ...data } = form.value
data.tagList = [data.mainTagId, ...tagList].map((item, index) => ({
tagId: Number(item),
sort: index,
}))
data.releaseStatus = releaseStatus
if (data.type === ArticleTypeEnum.PRACTICE || data.type === ArticleTypeEnum.QUESTION) {
// 手动设置一下封面图
if (data.imgUrl) {
data.faceUrl = data.imgUrl.split(',')[0]
}
}
return data
}
// 打开抽屉
const openDrawer = () => {
drawerVisible.value = true
}
// 关闭抽屉
const handleDrawerClose = () => {
drawerVisible.value = false
}
// 取消按钮
const handleClosed = () => {
resetForm()
router.back()
}
// 提交表单
const handleSubmit = async (releaseStatus: ReleaseStatusTypeEnum) => {
try {
await formRef.value.validate()
const res = await addOrUpdateArticle(form.value)
await formRef.value?.validate()
loading.value = true
const res =
form.value.type === ArticleTypeEnum.PRACTICE
? await addOrUpdatePractice(transFormData(releaseStatus))
: await addOrUpdateArticle(transFormData(releaseStatus))
console.log(res)
drawerVisible.value = false
resetForm()
router.back()
// 发布成功后的逻辑...
} catch (error) {
console.log(error)
} finally {
loading.value = false
}
}
const key = ref(0)
const isEdit = computed(() => !!route.query.id)
onActivated(async () => {
key.value++
resetForm()
await nextTick()
if (isEdit.value) {
console.log(route.query.id, '编辑')
// 要编辑回显
const { data } = await getArticleDetail(route.query.id)
// 首先回显基础的信息
// 标题 内容 主标签 副标签 所属栏目 是否推荐 是否同步同事吧 发布时间 发布状态
const {
id,
title,
content,
relateColumnId,
isRecommend,
isRelateColleague,
sendType,
sendTime,
tagIdList,
} = data
form.value = {
...form.value,
title,
content,
relateColumnId,
isRecommend,
isRelateColleague,
sendType,
sendTime,
}
// 回显主副标签
form.value.mainTagId = String(tagIdList[0]) || ''
form.value.tagList = tagIdList.slice(1) || []
const { imgUrl, faceUrl } = data
if (type === ArticleTypeEnum.QUESTION || type === ArticleTypeEnum.PRACTICE) {
form.value.imgUrl = imgUrl
} else {
form.value.faceUrl = faceUrl
}
}
})
</script>
<style scoped lang="scss">
/* 覆盖 Element Plus 默认样式,使其更符合大标题风格 */
<style scoped>
/* 标题输入框样式 */
:deep(.title-input .el-textarea__inner) {
font-size: 24px;
font-weight: bold;
color: #333;
padding: 0;
border: none;
box-shadow: none;
padding: 0;
font-size: 2rem;
font-weight: 700;
line-height: 1.3;
color: #1f2937;
background: transparent;
&::placeholder {
color: #a8abb2;
}
box-shadow: none !important;
}
/* 隐藏 Radio Button 的圆点,改用卡片选择样式时需要 */
:deep(.el-radio-button__inner) {
border-radius: 8px !important;
border: 1px solid #dcdfe6;
border-left: 1px solid #dcdfe6 !important;
:deep(.title-input .el-textarea__inner:focus) {
outline: none;
box-shadow: none !important;
padding: 8px 16px;
width: 100%;
}
:deep(.el-radio-button:first-child .el-radio-button__inner) {
border-left: 1px solid #dcdfe6;
}
:deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) {
background-color: #ecf5ff;
border-color: #409eff;
color: #409eff;
box-shadow: none;
:deep(.title-input .el-textarea__inner::placeholder) {
color: #d1d5db;
font-weight: 600;
}
/* 让侧边栏标签文字稍微小一点 */
/* 表单项标签样式 */
:deep(.el-form-item__label) {
font-weight: 500;
color: #4b5563;
color: #374151;
font-size: 0.875rem;
}
/* 抽屉内容滚动 */
:deep(.el-drawer__body) {
padding: 20px 0;
}
/* 滚动条美化 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #f1f5f9;
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #94a3b8;
}
</style>
......@@ -6,7 +6,7 @@
class="bg-white rounded-lg p-6 shadow-[0_1px_3px_rgba(0,0,0,0.02)] border border-slate-100"
>
<!-- 顶部标签行 -->
<div class="flex flex-wrap gap-2 mb-4">
<div class="flex flex-wrap gap-2 mb-4 justify-between">
<span
v-for="tag in questionDetail.tagNameList"
:key="tag"
......@@ -14,6 +14,18 @@
>
#{{ tag }}
</span>
<!-- 后面加一个编辑 -->
<el-link
v-if="isAuthor"
type="primary"
:underline="false"
@click="
router.push(`/publishLongArticle/${questionDetail.type}?id=${questionDetail.id}`)
"
class="text-sm"
>
编辑
</el-link>
</div>
<!-- 标题:主要信息,黑重粗 -->
......@@ -78,6 +90,18 @@
</span>
</div>
</div>
<!-- 展示图片相关 -->
<div v-if="questionDetail.imgUrl" class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6">
<el-image
v-for="item in questionDetail.imgUrl.split(',')"
:key="item"
:src="item"
fit="cover"
class="rounded-lg w-full h-64 hover:scale-105 transition-transform cursor-pointer"
:preview-src-list="questionDetail.imgUrl.split(',')"
:preview-teleported="true"
/>
</div>
</div>
<!-- 2. 列表控制栏 -->
......@@ -241,14 +265,23 @@ import { usePageSearch } from '@/hooks'
import Comment from '@/components/common/Comment/index.vue'
import CommentDialog from '@/components/common/CommentDialog/index.vue'
import dayjs from 'dayjs'
import { useUserStore } from '@/stores/user'
import { storeToRefs } from 'pinia'
const userStore = useUserStore()
const { userInfo } = storeToRefs(userStore)
const route = useRoute()
const questionId = Number(route.params.id)
const router = useRouter()
const questionId = Number(route.params.id)
const commentRefList = ref<InstanceType<typeof Comment>[]>([])
const questionDetail = ref<ArticleItemDto>({} as ArticleItemDto)
const commentDialogRef = useTemplateRef<typeof CommentDialog>('commentDialogRef')
const isAuthor = computed(() => {
return questionDetail.value.createUserId === userInfo.value.userId
})
const questionContentRef = useTemplateRef<HTMLElement>('questionContentRef')
const isExpand = ref(false)
......
......@@ -53,6 +53,13 @@
@click="jumpToArticleDetailPage({ type: item.type, id: item.id })"
>查看</el-button
>
<el-button
v-if="item.type !== ArticleTypeEnum.VIDEO"
type="primary"
link
@click="jumpToEditPage({ type: item.type, id: item.id })"
>编辑</el-button
>
<el-button type="danger" link @click="handleDelete(item.id)">删除</el-button>
</div>
</div>
......@@ -93,6 +100,8 @@ import type { TabPaneName } from 'element-plus'
import { IS_REAL_KEY } from '@/constants/symbolKey'
import { jumpToArticleDetailPage } from '@/utils'
const router = useRouter()
const isReal = inject(IS_REAL_KEY)
const filterArticleType = computed(() => {
if (isReal?.value === 1) {
......@@ -131,6 +140,14 @@ const handleDelete = async (articleId: number) => {
ElMessage.success('删除成功')
}
const jumpToEditPage = (item: { type: ArticleTypeEnum; id: number }) => {
if (item.type === ArticleTypeEnum.VIDEO) {
router.push(`/publishVideo?id=${item.id}`)
} else {
router.push(`/publishLongArticle/${item.type}?id=${item.id}`)
}
}
defineExpose({
refresh: () => {
searchParams.value.type = filterArticleType.value[0]!.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