当前位置: 首页 > news >正文

企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 8)

内容安全与广告位完善

前言

第七天完成了横幅海报模块动态化和一键启动脚本。第八天的开发工作将重点关注内容安全防护(文章防复制功能)、数据字典优化(横幅类型下拉选择)、各广告位的完整实现以及数据库字段优化,进一步完善门户系统的功能和安全性。

一、富文本内容存储优化

1.1 问题分析

文章内容使用富文本编辑器录入,但数据库yucms_article表的content字段使用TEXT类型,最大存储 64KB,无法满足长文章的存储需求。

1.2 解决方案

content字段类型从TEXT改为LONGTEXT(最大支持 4GB):

ALTER TABLE yucms_article MODIFY COLUMN content LONGTEXT;

1.3 字段类型对比

字段类型

最大容量

适用场景

TEXT

64KB

短文本、摘要

LONGTEXT

4GB

长文章、富文本内容

二、文章正文防复制功能

2.1 需求分析

为保护原创内容,需要实现文章正文的防复制功能,并在用户尝试复制时弹出提示框。

2.2 实现方案

ArticleDetail.vue中添加防复制事件监听:

<div ref="articleContentRef" class="anti-copy" @copy="preventCopy" @contextmenu="preventContextMenu" @selectstart="preventSelectStart" > <div v-html="article.content"></div> </div>

2.3 事件处理函数

// 阻止复制 function preventCopy(e) { e.preventDefault(); showCopyAlert(); } // 阻止右键菜单 function preventContextMenu(e) { e.preventDefault(); } // 阻止文字选中 function preventSelectStart(e) { e.preventDefault(); }

2.4 自定义提示弹窗

创建美观的提示弹窗组件,与网站整体风格协调:

<Transition name="fade"> <div v-if="showAlert" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50"> <div class="bg-white rounded-2xl shadow-2xl p-6 max-w-md w-full mx-4 transform"> <div class="text-center"> <div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-full flex items-center justify-center mx-auto mb-4"> <svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"></path> </svg> </div> <h3 class="text-lg font-semibold text-slate-800 mb-2">关注公众号获取资料</h3> <p class="text-slate-600 mb-4">为保护原创内容,文章正文无法直接复制</p> <div class="bg-slate-50 rounded-lg p-4 mb-4"> <p class="text-sm text-slate-500 mb-1">公众号名称</p> <p class="text-lg font-bold text-bank-primary">Fintech.Ren</p> </div> <button @click="showAlert = false" class="w-full py-3 bg-bank-primary text-white font-medium rounded-xl hover:bg-bank-primary/90 transition-colors" > 我知道了 </button> </div> </div> </div> </Transition>

2.5 CSS 样式

.anti-copy { user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; } .fade-enter-active, .fade-leave-active { transition: opacity 0.3s ease; } .fade-enter-from, .fade-leave-to { opacity: 0; }

三、横幅类型下拉选择优化

3.1 问题分析

横幅管理页面中,横幅类型使用单选按钮展示,不够美观且占用空间较大。需要改为下拉菜单形式。

3.2 修改 YucmsBanner.data.ts

将横幅类型字段从radio改为select

{ label: '横幅类型', field: 'type', defaultValue: "1", component: 'JDictSelectTag', componentProps:{ dictCode:"yucms_banner_type", type: "select", refresh: true, }, dynamicRules: ({model,schema}) => { return [{ required: true, message: '请选择横幅类型!' }]; }, }

3.3 数据字典刷新问题

3.3.1 问题描述

数据字典修改后,前端不会自动更新,因为initDictOptions函数优先读取缓存。

3.3.2 解决方案

jeecgboot-vue3/src/utils/dict/index.ts中添加refresh参数:

export const initDictOptions = (code, refresh = false) => { if (!refresh && getDictItemsByCode(code)) { return new Promise((resolve) => resolve(getDictItemsByCode(code))); } // 从后端获取最新数据... };

JDictSelectTag.vue组件中传递refresh属性:

props: { refresh: propTypes.bool.def(false), }, async function initDictData() { const dictData = await initDictOptions(dictCode, refresh); // 处理数据逻辑 }

四、各广告位动态获取实现

4.1 广告位类型定义

Type 值

广告位名称

尺寸

位置

1

首页轮播

-

首页顶部

2

首页横条

728×90

轮播下方

3

首页960×670

960×670

中间区域

4

首页320×790

320×790

侧边栏

5

首页300×250

300×250

侧边栏下方

6

List页640×360

640×360

文章列表页

4.2 Banner API 封装

src/api/banner.ts中创建各广告位的 API 函数:

// 获取首页轮播(type=1,取3条) export const getBannerList = (params?: any) => { const now = new Date().toISOString().slice(0, 19).replace('T', ' '); return defHttp.get({ url: Api.GetBannerList, params: { ...params, bannerStatus: '1', type: '1', pageSize: 3, column: 'updateTime', order: 'desc', startTime_lte: now, endTime_gte: now } }); }; // 获取顶部横幅(type=2,取1条) export const getTopBanner = () => { /* ... */ }; // 获取中间横幅(type=3,取1条) export const getMiddleBanner = () => { /* ... */ }; // 获取侧边栏横幅(type=4,取1条) export const getSideBanner = () => { /* ... */ }; // 获取小横幅(type=5,取1条) export const getSmallBanner = () => { /* ... */ }; // 获取List页横幅(type=6,取1条) export const getListBanner = () => { /* ... */ };

4.3 数据获取逻辑

各广告位的数据获取逻辑统一遵循以下规则:

  1. 状态过滤bannerStatus = 1(启用状态)

  2. 时间区间:当前时间在start_timeend_time之间

  3. 类型过滤:根据广告位类型设置type参数

  4. 排序规则:按update_time降序排列

  5. 数量限制:轮播取前3条,其他广告位取前1条

4.4 Home.vue 集成

在首页中集成各广告位组件:

// 响应式变量 const topBanner = ref(null); const sideBanner = ref(null); const middleBanner = ref(null); const smallBanner = ref(null); // 数据获取函数 async function fetchTopBanner() { /* ... */ } async function fetchSideBanner() { /* ... */ } async function fetchMiddleBanner() { /* ... */ } async function fetchSmallBanner() { /* ... */ } // 组件挂载时执行 onMounted(() => { fetchTopBanner(); fetchSideBanner(); fetchMiddleBanner(); fetchSmallBanner(); });

4.5 模板渲染

使用v-if/v-else实现广告位的条件渲染:

<!-- 中间横幅 --> <div v-if="middleBanner" class="ad-container overflow-hidden"> <a :href="middleBanner.linkUrl" :target="middleBanner.izBlank === '1' ? '_blank' : '_self'"> <img :src="getImageUrl(middleBanner.imageUrl)" :alt="middleBanner.title" /> </a> </div> <div v-else class="ad-container flex items-center justify-center"> <div class="text-center"> <p class="text-sm text-slate-400">广告位 960 × 670</p> <p class="text-xs text-slate-300 mt-1">联盟广告位</p> </div> </div>

五、图片路径问题修复

5.1 问题描述

ArticleList.vue中的getImageUrl函数使用了错误的路径前缀/jeecg-boot,导致图片无法加载。

5.2 统一修复

确保所有页面的getImageUrl函数使用正确的前缀/jeecgboot(与 Vite 代理配置一致):

function getImageUrl(imagePath) { if (!imagePath) return null; // 完整URL直接返回 if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) { return imagePath; } // 添加正确的代理前缀 if (imagePath.startsWith('/')) { return `/jeecgboot${imagePath}`; } else { return `/jeecgboot/${imagePath}`; } }

5.3 Vite 代理配置

server: { port: 3001, proxy: { '/jeecgboot': { target: 'http://localhost:8080/jeecg-boot', changeOrigin: true, rewrite: (path) => path.replace(/^\/jeecgboot/, '') } } }

六、广告位尺寸规范

6.1 各广告位实际尺寸

广告位

容器宽度

推荐图片尺寸

比例

首页轮播

全屏

1920×600

16:5

首页横条

960px

728×90

~8:1

首页960×670

960px

960×670

~1.43:1

首页320×790

300px

320×790

~0.41:1

首页300×250

300px

300×250

6:5

List页640×360

自适应

640×360

16:9

6.2 图片适配策略

  • 使用object-cover确保图片填满容器

  • 设置固定高度,宽度自适应

  • 添加loading="lazy"实现懒加载

七、总结

第八天的开发工作主要完成了以下内容:

  1. 富文本内容存储优化:将content字段类型从TEXT改为LONGTEXT,支持大文本存储

  2. 文章防复制功能:实现文章正文的防复制保护,自定义美观的提示弹窗

  3. 横幅类型下拉选择:将单选按钮改为下拉菜单,优化用户体验

  4. 数据字典刷新机制:添加refresh参数支持强制刷新字典数据

  5. 各广告位完整实现:首页轮播、横条、中间横幅、侧边栏横幅、小横幅及 List 页横幅的动态获取

  6. 图片路径问题修复:统一所有页面的getImageUrl函数路径前缀

这些改进完善了门户系统的内容安全防护和广告位管理功能,为后续的功能扩展和性能优化奠定了基础。

http://www.jsqmd.com/news/724205/

相关文章:

  • 如何用WarcraftHelper彻底解决魔兽争霸III兼容性问题:完整实战指南
  • 厦门园博苑花灯乐园演绎厦门夜色,一场看见文化,一场点燃热爱 - 资讯焦点
  • 从零构建个人化CLI工具:基于Node.js的脚手架与工作流自动化实践
  • 从调色到抠图:手把手教你用OpenCV cvtColor玩转5个图像处理小项目(C++版)
  • 2026有实力的聚美健牛磺酸葡萄糖饮厂家靠谱吗,看看这些厂家表现 - 工业推荐榜
  • video-subtitle-extractor:本地AI字幕提取终极方案深度解析
  • Masa API统一搜索功能解析与实战指南
  • 从零部署VideoChat2:多模态视频理解模型实战指南
  • .NET 9云原生落地实践(2024年Q3最新Gartner验证架构):Service Mesh集成+自动扩缩容+可观测性闭环
  • 从零构建AI应用:LangChain、RAG与多智能体实战指南
  • SQL数据库如何同步更新多个关联表_使用存储过程与事务一致性
  • 告别单行复制!在SAP ABAP SALV中实现多选(行/单元格)的完整配置指南
  • 终极指南:WechatDecrypt微信聊天记录解密实战教程
  • 2026 黔西市黄金回收TOP5排名|正规备案门店优选 - 资讯焦点
  • 游戏加速新境界:OpenSpeedy如何让你的游戏体验提升300%
  • 探讨2026年聚美健清洗液 聚美健多用途清洗液费用怎么算 - 工业推荐榜
  • PaddlePaddle模型部署实战:从原理到生产级服务搭建
  • pp储罐采购避坑指南:如何挑选质量好、性能优的生产厂家? - 品牌推荐大师
  • Sunshine游戏串流完整指南:如何打造你的个人云端游戏主机?
  • AI赋能编译优化:从智能诊断到自动化构建
  • 1000字降AI免费试用怎么用?嘎嘎降AI让毕业生付费决策风险压到零!
  • Avalonia 无头模式在 Docker 容器中的运行方法
  • 物理约束下的生成艺术:从断裂力学到音乐创作
  • 2026年成都聚美健0.85%纯净生理盐水排名,十大厂家哪家好 - 工业推荐榜
  • ncmdumpGUI实战指南:3分钟解锁网易云音乐NCM文件,实现音乐跨平台自由播放
  • 从手机到监控:拆解CMOS图像传感器里那些‘看不见’的设计(微透镜、CFA、IR-CUT)
  • LangChain框架-数据检索
  • 小红书数据采集神器:xhs工具完全实战指南
  • 解锁网易云音乐:3步完成NCM加密文件转换
  • 采购能考的证?采购从业者必备权威证书全解析(中供国培官方招生) - 中供国培