基于 Spring Boot + Vue3 的博物馆藏品管理系统设计与实现

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系名片!

一、项目背景与意义

博物馆作为文化遗产的重要保存与展示机构,日常需要管理大量藏品信息,包括藏品的基本属性、入藏时间、来源、保存状态、展览记录等。传统依靠纸质台账或 Excel 表格的管理方式,存在信息分散、检索困难、数据易丢失、多人协作冲突等问题,难以满足现代博物馆数字化管理的需求。

基于 Spring Boot + Vue3 构建的博物馆藏品管理系统,采用前后端分离架构,能够实现藏品信息的集中化、结构化与可视化管理,提升藏品登记、查询、统计和借展管理的效率,同时为后续的数字化展陈、藏品研究提供可靠的数据基础。

二、系统需求分析

2.1 功能需求

  • 用户与权限管理:支持管理员、藏品管理员、普通查询用户等角色,基于角色进行菜单与接口权限控制。
  • 藏品信息管理:藏品的增删改查,支持编号、名称、类别、年代、材质、尺寸、来源、入藏时间、保存状态、图片等字段。
  • 分类与年代管理:维护藏品类别(陶瓷、书画、青铜器、玉器等)与年代字典,便于统一规范录入。
  • 藏品检索与统计:支持按名称、类别、年代、状态等多条件组合查询,并提供分类数量、状态分布等统计图表。
  • 出入库与借展管理:记录藏品出库、入库、外借展览的申请与审批流程,保留完整操作日志。
  • 图片与附件管理:支持藏品多图上传、预览与压缩存储。

2.2 非功能需求

  • 系统响应时间控制在秒级,列表查询支持分页。
  • 接口需具备鉴权与参数校验,防止越权访问与非法数据写入。
  • 关键操作需记录日志,便于追溯。
  • 前端界面简洁易用,适配常见桌面浏览器分辨率。

三、技术选型

层次 技术 说明
后端框架 Spring Boot 3.x 快速构建 RESTful 服务,内置 Tomcat
持久层 MyBatis-Plus 简化 CRUD,支持分页与条件构造器
数据库 MySQL 8.0 存储藏品、用户、日志等业务数据
鉴权 Spring Security + JWT 无状态登录认证与接口权限控制
前端框架 Vue 3 + Vite 组合式 API,构建速度快
UI 组件库 Element Plus 表格、表单、弹窗等常用组件
状态与路由 Pinia + Vue Router 全局状态管理与前端路由守卫
图表 ECharts 藏品分类与状态统计可视化

四、系统架构设计

系统采用前后端分离架构,前端通过 Axios 调用后端 RESTful 接口,后端按 Controller、Service、Mapper 分层组织代码,数据库负责持久化存储。

flowchart LR A[Vue3 前端] -->|HTTP/JSON| B[Spring Boot 后端] B --> C[Controller 层] C --> D[Service 层] D --> E[Mapper 层] E --> F[(MySQL 数据库)] B --> G[文件存储] A --> H[ECharts 统计展示]

4.1 后端分层说明

  • Controller:接收请求、参数校验、返回统一响应体。
  • Service:业务逻辑编排,如借展审批、状态流转。
  • Mapper:基于 MyBatis-Plus 完成数据访问。
  • Common:统一返回结果、异常处理、JWT 工具类等公共组件。

五、数据库设计

核心表包括用户表、角色表、藏品表、藏品分类表、出入库记录表与操作日志表。以下为藏品表的主要字段设计。

sql 复制代码
CREATE TABLE collection_item (
    id            BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
    item_no       VARCHAR(32)  NOT NULL UNIQUE COMMENT '藏品编号',
    name          VARCHAR(128) NOT NULL COMMENT '藏品名称',
    category_id   BIGINT       NOT NULL COMMENT '分类ID',
    era           VARCHAR(64)  COMMENT '年代',
    material      VARCHAR(64)  COMMENT '材质',
    size_desc     VARCHAR(128) COMMENT '尺寸描述',
    origin        VARCHAR(128) COMMENT '来源',
    entry_date    DATE         COMMENT '入藏日期',
    status        TINYINT      DEFAULT 1 COMMENT '状态:1在库 2展出 3修复 4外借',
    cover_url     VARCHAR(255) COMMENT '封面图地址',
    description   TEXT         COMMENT '详细描述',
    create_time   DATETIME     DEFAULT CURRENT_TIMESTAMP,
    update_time   DATETIME     DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted       TINYINT      DEFAULT 0 COMMENT '逻辑删除标记'
) COMMENT '藏品信息表';

六、后端核心实现

6.1 统一响应与全局异常处理

java 复制代码
@Data
public class Result<T> {
    private Integer code;
    private String message;
    private T data;

    public static <T> Result<T> success(T data) {
        Result<T> r = new Result<>();
        r.setCode(200);
        r.setMessage("success");
        r.setData(data);
        return r;
    }

    public static <T> Result<T> fail(String message) {
        Result<T> r = new Result<>();
        r.setCode(500);
        r.setMessage(message);
        return r;
    }
}

6.2 藏品分页查询接口

java 复制代码
@RestController
@RequestMapping("/api/collections")
@RequiredArgsConstructor
public class CollectionController {

    private final CollectionService collectionService;

    @GetMapping
    public Result<Page<CollectionItem>> page(
            @RequestParam(defaultValue = "1") long current,
            @RequestParam(defaultValue = "10") long size,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) Long categoryId) {
        return Result.success(collectionService.pageQuery(current, size, keyword, categoryId));
    }

    @PostMapping
    public Result<Long> create(@RequestBody @Valid CollectionItem item) {
        collectionService.save(item);
        return Result.success(item.getId());
    }
}

6.3 业务层分页实现

java 复制代码
@Service
@RequiredArgsConstructor
public class CollectionServiceImpl extends ServiceImpl<CollectionMapper, CollectionItem>
        implements CollectionService {

    @Override
    public Page<CollectionItem> pageQuery(long current, long size, String keyword, Long categoryId) {
        LambdaQueryWrapper<CollectionItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(keyword), CollectionItem::getName, keyword)
               .eq(categoryId != null, CollectionItem::getCategoryId, categoryId)
               .orderByDesc(CollectionItem::getCreateTime);
        return this.page(new Page<>(current, size), wrapper);
    }
}

七、前端核心实现

7.1 请求封装与拦截器

javascript 复制代码
import axios from 'axios'
import { ElMessage } from 'element-plus'

const request = axios.create({
  baseURL: '/api',
  timeout: 10000
})

request.interceptors.request.use(config => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})

request.interceptors.response.use(
  res => {
    const { code, message, data } = res.data
    if (code === 200) return data
    ElMessage.error(message || '请求失败')
    return Promise.reject(new Error(message))
  },
  err => {
    ElMessage.error(err.response?.data?.message || '网络异常')
    return Promise.reject(err)
  }
)

export default request

7.2 藏品列表页面

vue 复制代码
<template>
  <el-card>
    <el-form :inline="true" :model="query">
      <el-form-item label="关键词">
        <el-input v-model="query.keyword" placeholder="藏品名称" clearable />
      </el-form-item>
      <el-form-item label="分类">
        <el-select v-model="query.categoryId" placeholder="全部" clearable>
          <el-option v-for="c in categories" :key="c.id" :label="c.name" :value="c.id" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="loadData">查询</el-button>
      </el-form-item>
    </el-form>

    <el-table :data="list" v-loading="loading">
      <el-table-column prop="itemNo" label="编号" width="140" />
      <el-table-column prop="name" label="名称" />
      <el-table-column prop="era" label="年代" width="120" />
      <el-table-column prop="status" label="状态" width="100">
        <template #default="{ row }">
          <el-tag :type="statusType(row.status)">{{ statusText(row.status) }}</el-tag>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
      v-model:current-page="query.current"
      v-model:page-size="query.size"
      :total="total"
      layout="total, prev, pager, next"
      @current-change="loadData"
    />
  </el-card>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue'
import request from '@/utils/request'

const list = ref([])
const total = ref(0)
const loading = ref(false)
const categories = ref([])
const query = reactive({ current: 1, size: 10, keyword: '', categoryId: null })

const loadData = async () => {
  loading.value = true
  try {
    const page = await request.get('/collections', { params: query })
    list.value = page.records
    total.value = page.total
  } finally {
    loading.value = false
  }
}

onMounted(loadData)
</script>

八、系统测试与部署

  • 接口测试:使用 Postman 或 Apifox 验证登录、藏品增删改查、分页查询等接口。
  • 权限测试:验证不同角色访问受限接口时返回 403。
  • 部署方式 :前端执行 npm run build 生成静态资源,交由 Nginx 托管;后端打包为 jar,通过 java -jar 运行,数据库使用 MySQL 8.0。
nginx 复制代码
server {
    listen 80;
    server_name museum.example.com;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

九、总结与展望

本文围绕博物馆藏品管理系统,完成了从需求分析、技术选型、架构设计到核心代码实现的完整梳理。系统采用 Spring Boot + Vue3 前后端分离方案,具备良好的可维护性与扩展性。

后续可在此基础上继续扩展:引入 Redis 缓存热点查询、使用 MinIO 或对象存储管理藏品图片、增加藏品二维码标签打印、结合 Elasticsearch 实现全文检索,以及对接数字展厅实现藏品的三维展示。

相关推荐
苍何1 小时前
Codex+Obsidian,多平台同步,一键分发,太香了!
后端
fanruitian1 小时前
python 进程 线程
java·前端·python
\光辉岁月/1 小时前
javaSE8-新特性-Stream&Option
java·stream·option
zzu123zsw1 小时前
把条件校验收敛到枚举接口:Spring Boot 统一断言模式与零污染异常切面工程化
java·spring boot·后端·架构设计
SL_staff1 小时前
计划系统落地难?从开发者视角重构执行入口体验
java·开源·全栈
鬼手点金1 小时前
单轮对话:最简单的 API 调用
java·服务器·前端·javascript·react.js·servlet·tomcat
code_slave(码畜)2 小时前
微服务架构落地:分库分表实战(下) —— 分布式主键、跨分片查询与分页聚合防坑
数据库·spring boot·分布式·spring cloud·微服务·架构·分库分表
牛牛牌蜡笔小新2 小时前
Java-常用类库
java·开发语言
Wang's Blog2 小时前
Java 项目实战: 交友项目 - MongoDB集群:概述
java·mongodb·交友