当前位置: 首页 > 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.cnnetsun.cn/news/2155832.html

相关文章:

  • “PHP不适合工业场景”是最大认知陷阱?看航天某院所如何用PHP 8.2+FFI直驱ARM Cortex-A9实时内核(实测jitter < 8μs)
  • 构建个人技术学习仓库:从Git管理到知识体系化实践
  • 高效小红书数据采集实战指南:xhs工具完全解析
  • BTW:AI开发工作流管理器,统一配置提升编码效率
  • ASPO算法:解决LLM强化学习中IS比率失衡问题
  • 三步深度解析KKManager:Illusion游戏模组管理实战指南
  • Universal x86 Tuning Utility:开源硬件调优引擎的技术深度解析与实践指南
  • 从‘搬运工’到‘魔术师’:用SeaTunnel和Flink CDC玩转实时数据同步与转换(附避坑配置)
  • 逆向工程AI创业公司Magic的长上下文处理技术
  • 基于大语言模型构建个人AI助手:从智能体架构到实战部署
  • 抖音直播数据采集实战:从网页端API到实时弹幕分析
  • 保姆级教程:在Ubuntu20.04 ROS Noetic上,从零配置laser_scan_matcher搭配GMapping建图(解决csm依赖报错)
  • TranslucentTB在Windows 11更新后无法启动?3步排查+5种修复方案
  • GitHub中文插件:3分钟让GitHub界面全面中文化的终极解决方案
  • ChatGPT平替方案:基于LM Z-Image构建私有化智能对话助手
  • 如何快速解锁你的微信聊天记录:WechatDecrypt本地解密完整指南
  • 智能文献助手Zotero GPT:3大核心功能深度解析与实战指南
  • 多智能体任务编排框架:从原理到实践,构建复杂AI工作流
  • 思源宋体CN:开源专业字体如何改变你的设计工作流?
  • Go微服务高可用实战:基于gobreaker的熔断器与自适应限流深度实践
  • SRWE终极指南:5分钟掌握实时窗口分辨率控制技术
  • Fast-GitHub终极指南:一键解决国内GitHub访问慢的免费浏览器插件
  • 如何在Blender中导入MMD模型:MMD Tools插件完整教程
  • YOLO26-seg分割优化:注意力魔改 | SimAM(无参Attention),一种轻量级的自注意力机制,效果秒杀CBAM、SE
  • 协程泄漏、心跳超时、流式响应中断——Swoole+LLM长连接三大报错全解析,附可落地的监控熔断脚本
  • 为什么你的AI Sandbox永远“半隔离”?——深度拆解Linux命名空间缺陷、GPU共享陷阱与3种绕过检测的隐蔽行为
  • 多模态代码生成技术:从设计草图到可执行代码的自动化实践
  • LLaMA-Factory结合DPO实现偏好对齐(RLHF简化方案)-实战落地指南
  • 2026年权威披露:杭州GEO优化源头服务商怎么挑选?亲测对比AI搜索优化公司避坑攻略
  • Downkyi:5步掌握B站视频下载的终极秘籍