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

0 阅读4分钟

横幅海报

前言

前六天的开发工作完成了项目的基础架构、首页开发、文章列表页面、文章详情页面、公共组件抽离、交互优化和数据动态化。第七天的开发工作将重点关注横幅海报模块的动态化实现,进一步提升开发效率和完善功能模块。

​编辑

一、横幅海报模块动态化

1.1 需求分析

横幅海报模块需要从 yucms_banner 表中动态获取数据,而不是使用静态数据。具体需求如下:

  • 获取 banner_status 为 1 的横幅(启用状态)
  • update_time 降序排序,取前 3 条
  • 图片地址从 image_url 字段获取
  • 标题从 title 字段获取
  • 链接地址从 link_url 字段获取
  • 根据 iz_blank 字段判断跳转方式(0=当前窗口,1=新窗口)

1.2 创建 Banner API 文件

src/api/banner.ts 中创建 Banner 相关的 API 函数:

import { defHttp } from '../utils/http/axios';
import { Api } from '../utils/http/axios';

export const getBannerList = (params?: any) => {
  return defHttp.get({
    url: Api.GetArticleList,
    params: {
      ...params,
      bannerStatus: '1',
      pageSize: 3,
      column: 'updateTime',
      order: 'desc'
    }
  });
};

1.3 修改 Home.vue 横幅模块

在 Home.vue 中导入 API 函数并添加数据获取逻辑:

import { getBannerList } from '../api/banner';

// 横幅数据
const banners = ref([]);

// 获取横幅数据
async function fetchBanners() {
  try {
    const response = await getBannerList();
    if (response.success && response.result) {
      banners.value = response.result.records || [];
    } else {
      banners.value = [];
    }
  } catch (error) {
    console.error('获取横幅数据失败:', error);
    banners.value = [];
  }
}

// 组件挂载时执行
onMounted(() => {
  fetchBanners();
});

1.4 动态渲染横幅模板

使用 v-for 指令动态渲染横幅数据:

<div v-for="(banner, index) in banners" :key="banner.id" :class="['banner-slide', index === 0 ? 'active' : '']" :data-slide="index">
  <div class="absolute inset-0">
    <img :src="getImageUrl(banner.imageUrl)" :alt="banner.title" class="w-full h-full object-cover" />
    <div class="absolute inset-0 bg-gradient-to-r from-black/70 via-black/40 to-transparent"></div>
  </div>
  <div class="relative h-full flex items-end pb-8">
    <div class="container mx-auto px-8 md:px-16 lg:px-20">
      <a :href="banner.linkUrl" :target="banner.izBlank === '1' ? '_blank' : '_self'" ...>
        {{ banner.title }}
      </a>
    </div>
  </div>
</div>

1.5 数据字段映射

数据库字段前端使用说明
image_urlbanner.imageUrl图片地址
titlebanner.title标题
link_urlbanner.linkUrl跳转链接
iz_blankbanner.izBlank是否新窗口打开
banner_status过滤条件状态(1启用)
update_time排序字段更新时间降序

二、内部链接路由处理

2.1 问题分析

横幅海报模块使用普通的 <a> 标签作为链接,当 iz_blank 为 0 时在当前窗口打开。但这种方式会导致页面刷新,丢失 Vue 组件状态,Header 和 Footer 也会重新渲染。

2.2 解决方案

使用 Vue Router 的 router-link 组件实现内部链接的客户端导航:

<!-- 内部链接使用 router-link -->
<router-link
  v-if="banner.linkUrl && banner.linkUrl.startsWith('/') && banner.izBlank !== '1'"
  :to="banner.linkUrl"
  class="inline-flex items-center gap-2 px-6 py-2.5 text-sm font-semibold rounded-lg shadow-lg transition-all duration-300 hover:scale-105 hover:shadow-xl"
  style="background-color: #3b82f6; color: #0f172a;">
  {{ banner.title }}
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path></svg>查看详情
</router-link>

<!-- 新窗口打开或外部链接使用普通 a 标签 -->
<a
  v-else
  :href="banner.linkUrl"
  :target="banner.izBlank === '1' ? '_blank' : '_self'"
  ...>
  {{ banner.title }}
</a>

2.3 逻辑说明

条件使用组件行为
linkUrl/ 开头且 izBlank !== '1'router-link客户端导航,保留 Header/Footer
izBlank === '1' 或外部链接<a> 标签新窗口打开或页面跳转

三、图片路径统一修复

3.1 问题描述

Home.vue 和 ArticleDetail.vue 中的 getImageUrl 函数使用了不同的路径前缀:

  • Home.vue 使用 /jeecgboot(不带横杠)
  • ArticleDetail.vue 使用 /jeecg-boot(带横杠)

由于项目的 Vite 代理配置使用的是 /jeecgboot,导致 ArticleDetail.vue 中的图片无法正确加载。

3.2 解决方案

统一所有页面中 getImageUrl 函数的路径前缀为 /jeecgboot

function getImageUrl(imagePath) {
  if (!imagePath) return null;

  // 检查是否已经是完整URL
  if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
    return imagePath;
  }

  // 检查是否以/开头
  if (imagePath.startsWith('/')) {
    // 对于以/开头的路径,添加 /jeecgboot 前缀(与代理配置保持一致)
    return `/jeecgboot${imagePath}`;
  } else {
    // 对于相对路径(如 temp/xxx.png 或 uploads/2024/03/xxx.jpg)
    // 直接添加 /jeecgboot 前缀(与代理配置保持一致)
    return `/jeecgboot/${imagePath}`;
  }
}

3.3 Vite 代理配置

确保 vite.config.js 中的代理配置与图片路径处理保持一致:

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

四、总结

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

  1. 横幅海报模块动态化:从 yucms_banner 表动态获取数据,支持启用状态过滤和排序
  2. 内部链接路由处理:使用 router-link 替代 <a> 标签实现客户端导航,保留页面状态
  3. UI 细节优化:横幅海报按钮位置调整、热门文章阅读数量显示

这些改进进一步提升了项目的开发效率和用户体验,为后续的功能完善奠定了基础。