Files
template-10490/pages/detail/[id].vue
赵忠林 f3b88d48c5 fix(request): 解决reactive对象导致重复请求问题
- 修改detail页面标题字体大小样式
- 更新自定义组件中的报名链接地址
- 在request工具中导入vue的isProxy和toRaw方法
- 添加proxy对象检测避免useFetch监听变更重复发送请求
- 修复post和put方法中的数据传递逻辑
2026-03-17 16:47:39 +08:00

269 lines
7.3 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 文章详情 -->
<template>
<!-- 主体部分 -->
<div class="xl:w-screen-xl m-auto py-4 mt-12 px-4 sm:px-0 sm:mt-[220px]">
<el-page-header :icon="ArrowLeft" @back="goBack">
<template #content>
<span class="font-600 mr-3"> 文章详情 </span>
</template>
<el-card shadow="hover" class="my-5 sm:my-10 sm:px-2">
<!-- 新闻详细 -->
<div class=" bg-white">
<h1 class="pt-5 text-3xl text-center">{{ form.title }}</h1>
<div class="flex items-center justify-center py-4">
<el-space size="large" class="text-gray-400" style="font-size: 16px">
<span v-if="form.author">作者{{ form.author }}</span>
<span>{{ $t('createTime') }}{{ dayjs(form.createTime).format('YYYY-MM-DD HH:mm') }}</span>
<span v-if="form.source">来源{{ form.source }}</span>
<span>{{ $t('click') }}{{ getViews(form) }}</span>
</el-space>
<!-- Baidu Button BEGIN -->
<el-space class="flex items-center">
<!-- <a href="#" class="bds_more" data-cmd="more">朋友圈</a>-->
<!-- <a href="#" class="bds_qzone" data-cmd="qzone">QQ空间</a>-->
<!-- <a href="#" class="bds_tsina" data-cmd="tsina">新浪</a>-->
<!-- <a href="#" class="bds_tqq" data-cmd="tqq">腾讯</a>-->
<!-- <a href="#" class="bds_weixin" data-cmd="weixin">微信</a>-->
</el-space>
</div>
<!-- 文章摘要 -->
<div v-if="form.comments" class="screen-item bg-orange-50 text-gray-600 p-3 text-lg">
{{ form.comments }}
</div>
<!-- 文章附件 -->
<div class="screen-item" v-if="form.files">
<div class="text-gray-400 py-3 text-sm">图片附件</div>
<el-scrollbar>
<div class="flex">
<el-image
v-for="(item,index) in JSON.parse(form.files)"
:key="index"
class="scrollbar-item w-[240px] max-h-[180px] mr-4 mb-4"
:src="item"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
:preview-src-list="srcList"
:initial-index="4"
fit="contain"
/>
</div>
</el-scrollbar>
</div>
<!-- 内容组件 -->
<Content class="content text-lg py-5" :editor="form?.editor" :data="form.content" />
<NextArticle :articleId="articleId" />
<h3 class="tag">{{ $t('articleUrl') }}{{ locationUrl() }} </h3>
<Tags :data="form.tags" />
</div>
</el-card>
<!-- 最近浏览 -->
<!-- <CmsArticleRecently :data="form" type="article" />-->
<!-- 相关产品和相关新闻 -->
<!-- <div class="relate_list">-->
<!-- <CmsProductRelated :data="form" />-->
<!-- <CmsArticleRelated :data="form" />-->
<!-- </div>-->
</el-page-header>
</div>
</template>
<script setup lang="ts">
import { ArrowLeft,View,Search } from '@element-plus/icons-vue'
import type {BreadcrumbItem} from "~/types/global";
import type {CmsNavigation} from "~/api/cms/cmsNavigation/model";
import {getNavIdByParamsId, getViews, locationUrl, navTo, paramsId} from "~/utils/common";
import type {CmsArticle, CmsArticleParam} from "~/api/cms/cmsArticle/model";
import useFormData from "~/utils/use-form-data";
import dayjs from "dayjs";
import type {Layout} from "~/api/layout/model";
import {
getCmsArticle
} from "~/api/cms/cmsArticle";
import {listCmsNavigation} from "~/api/cms/cmsNavigation";
import CmsArticleRecently from "~/components/CmsRecently.vue";
import Tags from "~/components/Tags.vue";
import Content from "~/components/Content.vue";
import {FILE_SERVER} from "~/config";
// 引入状态管理
const route = useRoute();
const router = useRouter();
const layout = ref<Layout>({});
const articleId = ref();
const i18n = useI18n();
const breadcrumb = ref<BreadcrumbItem>();
const showPassword = ref<boolean>();
const category = ref<CmsNavigation[]>([]);
const srcList = ref<any[]>([]);
// 配置信息
const {form, assignFields} = useFormData<CmsArticle>({
// 文章id
articleId: undefined,
// 文章模型
model: undefined,
// 文章标题
title: undefined,
// 分类类型
type: undefined,
// 展现方式
showType: undefined,
// 文章类型
categoryId: undefined,
// 文章分类
categoryName: undefined,
parentId: undefined,
// 封面图
image: undefined,
// 附件
files: undefined,
// 附件
fileList: [],
// 缩列图
thumbnail: undefined,
// 视频地址
video: undefined,
// 上传的文件类型
accept: undefined,
// 来源
source: undefined,
// 标签
tags: undefined,
// 文章内容
content: undefined,
// 文章编辑器
editor: undefined,
// 虚拟阅读量
virtualViews: undefined,
// 实际阅读量
actualViews: undefined,
// 访问权限
permission: undefined,
// 访问密码
password: undefined,
password2: undefined,
// 用户ID
userId: undefined,
// 用户昵称
nickname: undefined,
// 账号
username: undefined,
// 用户头像
// userAvatar: undefined,
author: undefined,
// 所属门店ID
shopId: undefined,
//
likes: undefined,
// 排序
sortNumber: undefined,
// 备注
comments: undefined,
// 状态
status: undefined,
// 创建时间
createTime: undefined,
// 更新时间
updateTime: undefined,
// 租户ID
tenantId: undefined,
// 租户名称
tenantName: undefined,
// 租户logo
logo: undefined,
// 详情页路径
detail: undefined
});
// 搜索表单
const where = reactive<CmsArticleParam>({
keywords: '',
page: 1,
limit: 20,
status: 0,
parentId: undefined,
categoryId: undefined,
lang: i18n.locale.value
});
const goBack = () => {
router.back(); // 返回上一页
// window.history.back();
}
// 请求数据
const reload = async () => {
await getCmsArticle(articleId.value).then(data => {
assignFields(data)
layout.value.banner = data?.banner;
// 应用截图
if(data.files){
const imgArr = JSON.parse(data.files);
imgArr.map((item: any) => {
srcList.value.push(item)
})
}
// 二级栏目分类
if (data.parentId) {
listCmsNavigation({parentId: data.parentId}).then(list => {
category.value = list;
})
}
// 拼接图片路径
// if(data.content){
// form.content = form.content?.replace(/src="\//g, 'src="' + FILE_SERVER + '/');
// }
if(form.permission === 1){
console.log('登录可见')
return;
}
if(form.permission === 2){
console.log('需要密码')
showPassword.value = true;
return;
}
}).catch(() => {
navigateTo('/404');
})
// seo
useSeoMeta({
description: form?.comments,
keywords: form.title,
titleTemplate: `${form?.title}` + ' - %s',
})
// 面包屑
breadcrumb.value = form
}
watch(
() => route.params.id,
(id) => {
articleId.value = getNavIdByParamsId(id);
reload();
},
{ immediate: true }
);
</script>
<style lang="scss">
.scrollbar-flex-content {
display: flex;
}
.scrollbar-item {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
</style>