基于Springboot+Vue的电子博物馆系统

基于Springboot+Vue的电子博物馆系统

前言:随着信息技术的不断发展,传统博物馆的参观方式逐渐向数字化、在线化转型。电子博物馆作为这一转型的重要组成部分,能够通过信息化手段为用户提供更丰富、更便捷的博物馆参观体验。本文基于Spring Boot和Vue.js框架,设计并实现了一个简单的电子博物馆系统,旨在展示数字化博物馆建设的技术架构及开发过程。

前言

项目功能及技术

用户端主要有首页、文创展示、浏览记录、网站公告、我的收藏、个人中心等模块。
管理端主要有用户管理、博物馆管理、文创管理、公告管理,博物馆视频管理。

vue.js+layui+html+js:用户端界面。
SpringBoot框架+Java程序语言:用户端及后台管理系统API的实现。
Layui前端框架:web后台管理界面样式及数据渲染框架。
MySQL数据库:数据存储。

用户端

管理端

API

SpringBoot框架搭建

1.创建maven project,先创建一个名为SpringBootDemo的项目,选择【New Project】

在这里插入图片描述

然后在弹出的下图窗口中,选择左侧菜单的【New Project】

在这里插入图片描述
在这里插入图片描述

在project下创建module,点击右键选择【new】—【Module…】

在这里插入图片描述

左侧选择【Spring initializr】,通过idea中集成的Spring initializr工具进行spring boot项目的快速创建。窗口右侧:name可根据自己喜好设置,group和artifact和上面一样的规则,其他选项保持默认值即可,【next】

在这里插入图片描述

Developer Tools模块勾选【Spring Boot DevTools】,web模块勾选【Spring Web】,此时,一个Springboot项目已经搭建完成,可开发后续功能

在这里插入图片描述

实体映射创建Mapper

创建一个entity实体类文件夹,并在该文件夹下创建项目用到的实体类

在这里插入图片描述

package com.example.demo.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Data
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;

    private String account;

    private String pwd;

    private String userDesc;

    private String userHead;

    private LocalDateTime createTime;

    private Long role;

    private String nickname;

    private String email;

    private String tags;
}

接口封装

由于我们使用mybatis-plus,所以简单的增删改查不用自己写,框架自带了,只需要实现或者继承他的Mapper、Service

在这里插入图片描述

创建控制器Controller

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

整合Swagger

添加依赖

先导入spring boot的web包

<!--swagger依赖-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

配置Swagger

创建一个swagger的配置类,命名为SwaggerConfig.java

/*
     *用于定义API主界面的信息,比如可以声明所有的API的总标题、描述、版本
     */
    private ApiInfo apiDemo() {
        return new ApiInfoBuilder()
                //用来自定义API的标题
                .title("SpringBoot项目SwaggerAPIAPI标题测试")
                //用来描述整体的API
                .description("SpringBoot项目SwaggerAPI描述测试")
                //创建人信息
                .contact(new Contact("测试员张三","http://localhost:8080/springboot/swagger-ui.html","xxxxxxxx@163.com"))
                //用于定义服务的域名
                //.termsOfServiceUrl("")
                .version("1.0") //可以用来定义版本
                .build();
    }

接口测试

运行Spring Boot项目,默认端口8080,通过地址栏访问url

在这里插入图片描述

接口组定义

根据不同的业务区分不同的接口组,使用@API来划分

@Api(tags = "用户管理") //  tags:组名称
@RestController
public class RoleController {
}

在这里插入图片描述
接口定义

使用@ApiModel来标注实体类,同时在接口中定义入参为实体类作为参数。

  • @ApiModel:用来标类

  • 常用配置项:value:实体类简称;description:实体类说明

  • @ApiModelProperty:用来描述类的字段的含义。

常用字段类型

字段类型所占字节存储范围最大存储值使用场景
TINYINT1-128~127127存储小整数
INT4-2147483648~21474836472147483647存储大整数
BIGINT8-9223372036854775808~92233720368547758079223372036854775807存储极大整数
DECIMAL可变长度存储精度要求高的数值
CHAR固定长度最多255字节255个字符存储长度固定的字符串
VARCHAR可变长度最多65535字节65535个字符存储长度不固定的字符串
DATETIME8‘1000-01-01 00:00:00’~‘9999-12-31 23:59:59’‘9999-12-31 23:59:59’存储日期和时间

参考代码块

    <script type="text/javascript">
			layui.use(['laydate', 'form'], function() {
				var laydate = layui.laydate;
				var form = layui.form;
				// 监听全选
			});
			//轻量级框架
			var dataInfo = new Vue({
				el: "#content-page",
				//Vue的数据对象
				data: {
					timeSort: 'next', //发布时间排序
					viewVolumeSort: 'next', //浏览量排序
					arrayList: [], //数据列表
					title: null,
					dynasty: null,
					typeId: null,
					areaList: [],
					appointment: {},
					swiperSrc: '',
					indexSwiper: [
						'https://photo.16pic.com/00/53/26/16pic_5326792_b.jpg',
						'https://img95.699pic.com/desgin_photo/40113/1735_list.jpg',
						'https://file3.renrendoc.com/fileroot_temp3/2022-5/20/f16ee02b-429f-46ad-806f-f453cfb33b80/f16ee02b-429f-46ad-806f-f453cfb33b801.gif',
					],
					swiperIndexl: 0,
					
					bwgArray:[
					],
				}, //数据对象结束
				//方法
				methods: {
					GetAll: function(desc, desc1) {
						var me = this;
						me.swiperSrc = me.indexSwiper[0];
						let list = me.indexSwiper;
						var swiperIndexl = me.swiperIndexl;
						me.swiperSrc = list[swiperIndexl];
						setInterval(function() {
							me.swiperSrc = list[swiperIndexl];
							swiperIndexl = (swiperIndexl + 1) % list.length;
						}, 3000);
						if (sessionStorage.getItem('user') == null || sessionStorage.getItem('user') == undefined ||
							sessionStorage.getItem('user') == '') {
							location.href = "login/login.html"
						}
						
						
						$.ajax({
							url: "http://127.0.0.1:8085/exhibition/list",
							async: false,
							type: "POST",
							contentType: 'application/json',
							dataType: 'json',
							data: JSON.stringify({
							}),
							success: function(json) {
								me.bwgArray = json.data;
							}
						});
						

					},
					gobwgDetail(e) {
						sessionStorage.setItem("exhibition", JSON.stringify(e));
						window.location.href = "museumDetail.html";
					},
					
					goAreaDetail(item) {
						//console.log(id)
						sessionStorage.setItem("area", JSON.stringify(item));
						window.location.href = "areaDetail.html";
					},

				}, //方法结束
				created: function() {
					var vm = this;
					vm.GetAll('desc', 'desc');
				}, //初始加载方法结束

			}); //vue结束

			function GetQueryString(name) {
				var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
				var r = window.location.search.substr(1).match(reg);
				if (r != null) return unescape(r[2]);
				return null;
			}
		</script>
<body>

		<div class="container-fluid" id="content-page">
		<div class="row top-header">
			<div class="col-md-1">&nbsp;</div>
			<div class="col-md-11">
				<div class="rightMenu">
					<img src="img/logo.png" class="logo" />
					<div class="logoTitle">数字博物馆</div>
					<div class="menuBox">
						<div class="menuTitle">
							<a href="index.html" style="text-decoration: none;">首页</a>
						</div>
						<div class="menuTitle">
							<a href="surroundings.html" style="text-decoration: none;">文创展示</a>
						</div>
						<div class="menuTitle">
							<a href="news.html" style="text-decoration: none;">网站公告</a>
						</div>
						<div class="menuTitle">
							<a href="history.html" style="text-decoration: none;">浏览记录</a>
						</div>
						<div class="menuTitle">
							<a href="center.html" style="text-decoration: none;">个人中心</a>
						</div>
						<div class="menuTitle">
							<a href="./login/login.html" style="text-decoration: none;">退出登录</a>
						</div>
				
					</div>
				</div>
			</div>
		</div>
			<div class="row">
				<div class="col-md-1">&nbsp;</div>
				<div class="col-md-10 paramBox">
					<div class="displayBox">
						<div class="sortBox" >
							当前位置:网站公告
							<img src="img/news.png" class="sortImg" />
						</div>
					</div>
				</div>
				<div class="col-md-1">&nbsp;</div>
			</div>

			<div class="row">
				<div class="col-md-1">&nbsp;</div>
				<div class="col-md-10">
					<div class="iconTitle">
						<div class="iconParent">
							<div class="listIcon">网站公告</div>
						</div>
						<div class="topTitle"></div>
						<div class="newTitle" v-for="item in arrayList" @click="goDetail(item)">· {{item.title}}</div>
					</div>


				</div>
				<div class="col-md-1">&nbsp;</div>
			</div>

			<div class="row">
				<div style="height:100px;"></div>
			</div>

		</div>

		<script src="js/jquery.min.js"></script>
		<script src="js/vue.js"></script>
		<script src="js/utils.js"></script>
		<script type="text/javascript">
			//轻量级框架
			var dataInfo = new Vue({
				el: "#content-page",
				//Vue的数据对象
				data: {
					timeSort: 'on', //发布时间排序
					viewVolumeSort: 'on', //浏览量排序
					arrayList: [
					], //数据列表

				}, //数据对象结束
				//方法
				methods: {
					GetAll: function() {
						var me = this;
						
						$.ajax({
							url: "http://127.0.0.1:8085/announcement/selectPageByUser",
							async: false,
							type: "POST",
							contentType: 'application/json',
							dataType: 'json',
							data: JSON.stringify({}),
							success: function(json) {
								me.arrayList = json.list;
							}
						});

					},
					goDetail(e){
						console.log(e);
						sessionStorage.setItem("ann",JSON.stringify(e));
						window.location.href="newsDetail.html";
					},

				}, //方法结束
				created: function() {
					var vm = this;
					vm.GetAll();
				}, //初始加载方法结束

			}); //vue结束

			function GetQueryString(name) {
				var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
				var r = window.location.search.substr(1).match(reg);
				if (r != null) return unescape(r[2]);
				return null;
			}
		</script>

		<div class="container-fluid" id="content-page">
			<div class="row top-header">
				<div class="col-md-1">&nbsp;</div>
				<div class="col-md-11">
					<div class="rightMenu">
						<img src="img/logo.png" class="logo" />
						<div class="logoTitle">数字博物馆</div>
						<div class="menuBox">
							<div class="menuTitle">
								<a href="index.html" style="text-decoration: none;">首页</a>
							</div>
							<div class="menuTitle">
								<a href="surroundings.html" style="text-decoration: none;">文创展示</a>
							</div>
							<div class="menuTitle">
								<a href="news.html" style="text-decoration: none;">网站公告</a>
							</div>
							<div class="menuTitle">
								<a href="history.html" style="text-decoration: none;">浏览记录</a>
							</div>
							<div class="menuTitle">
								<a href="center.html" style="text-decoration: none;">个人中心</a>
							</div>
							<div class="menuTitle">
								<a href="./login/login.html" style="text-decoration: none;">退出登录</a>
							</div>
			
						</div>
					</div>
				</div>
			</div>

			<div class="row">
				<div class="col-md-3">
					<div class="prevBox">
						<img src="img/prev.png" class="swiperChangeImg" v-on:click="prevImg" />
					</div>
				</div>
				<div class="col-md-6 ">
					<div class="swiperBox">
						<img :src="showSrc" class="swiperItemImg" />
					</div>
				</div>
				<div class="col-md-3">
					<div class="nextBox">
						<img src="img/next.png" class="swiperChangeImg" v-on:click="nextImg"/>
					</div>
				</div>
			</div>
			
			
			<div class="row">
				 <div class="col-md-2">&nbsp;</div>
				 <div class="col-md-8">
					 <div class="borerBox"></div>
				 </div>
				 <div class="col-md-2">&nbsp;</div>
			</div>
			
			<div class="row">
				<div class="col-md-2">&nbsp;</div>
				<div class="col-md-8">
					<div class="wwDetailBox">
						<div class="wwDetailLeft">
							<div class="wwDetailTitle">名称与朝代</div>
							<div class="wwDetailText">{{info.title}},{{info.dynasty}}</div>
							<div class="wwDetailTitle">出土时间和地点</div>
							<div class="wwDetailText">{{info.address}}</div>
							<div class="wwDetailTitle">材质</div>
							<div class="wwDetailText">{{info.materialQuality}}</div>
						</div>
						<div class="wwDetailRight">
							<div class="wwDetailTitle">历史文化背景</div>
							<div class="wwDetailText">{{info.history}}</div>
						</div>
					</div>
				</div>
				<div class="col-md-2">&nbsp;</div>
			</div>
			
			<div class="row">
				 <div class="col-md-2">&nbsp;</div>
				 <div class="col-md-8">
					 <div style="margin: 20px 0 80px 0;">
						 <video width="100%" height="400" controls>
							 <source :src="'http://127.0.0.1:8085/'+info.videoSrc" type="video/mp4"/>
						 </video>
					 </div>
				 </div>
				 <div class="col-md-2">&nbsp;</div>
			</div>
			
			<!-- <div class="row">
				<div class="col-md-3">&nbsp;</div>
				<div class="col-md-6">
					<div class="wcTypeBox">
						<div>
							<div class="wcTypeItem">
								生活用品
							</div>
						</div>
						
					</div>
				</div>
				<div class="col-md-3">&nbsp;</div>
			</div> -->


			<div class="footer">
				<div class="row">
					<div class="col-md-4">&nbsp;</div>
					<div class="col-md-4 ">
						<div class="footerLine1">
							<a href="javascript:void(0);" class="lineA">相关链接</a>
							<a href="javascript:void(0);" class="lineA">影像授权</a>
							<a href="javascript:void(0);" class="lineA">隐私政策</a>
							<a href="javascript:void(0);" class="lineA">版权说明</a>
							<a href="javascript:void(0);" class="lineA">联系我们</a>
							<a href="javascript:void(0);" class="lineA">关于我们</a>
						</div>
						<div class="footerLine2">
							<span class="lineB">京公网安备 11010102004165151号</span>
							<span class="lineB">京ICP备05067311号-1</span>
							<span class="lineB">© 2023-至今</span>
						</div>
					</div>
					<div class="col-md-4">&nbsp;</div>
				</div>
			</div>

		</div>



		<script src="js/jquery.min.js"></script>
		<script src="js/vue.js"></script>
		<script src="js/utils.js"></script>
		<script type="text/javascript">
			//轻量级框架
			var dataInfo = new Vue({
				el: "#content-page",
				//Vue的数据对象
				data: {
					info:{
						id:1,
						//名称与朝代
						name:'越王勾践剑',
						//出土时间和地点
						address:'出土时间是1965年12月,,出土于湖北省荆州市江陵县望山楚墓群1号墓',
						//材质
						materialQuality:'越王勾践剑的材质主要是青铜和锡的合金。这种合金使得剑身既坚硬又富有韧性,能够保持长久的锋利。同时,剑身上还镀有一层含铬的金属,这使得越王勾践剑在历经千年之后仍然能够保持光泽,不生锈蚀。',
						//历史文化背景
						history:'越王勾践剑在历史上的地位十分重要,它不仅是越国强大军事实力的象征,也体现了当时越国工匠的精湛技艺。这把剑见证了越王勾践卧薪尝胆、励精图治的历史故事,也反映了春秋战国时期诸侯争霸、文化交融的时代背景。关于越王勾践,最为人熟知的便是他卧薪尝胆的故事。在吴国战败后,勾践被俘为奴,但他并未放弃复国的信念。他卧薪尝胆,时刻提醒自己不忘国仇家恨,最终成功复仇并重建越国。越王勾践剑作为他的佩剑,见证了这一伟大历程,具有极高的历史价值。',
						//视频
						videoSrc:'http://vjs.zencdn.net/v/oceans.mp4',
						//朝代
						dynasty:'春秋晚期',
						//分类
						typeName:'青铜器',
						//封面图
						images:'https://www.chinakongzi.org/zhwh/tpjj/201708/W020170809353217008926.jpg',
						//轮播图
						bannerList: [
							'https://img.zcool.cn/community/015b76608697f511013e3b7dd2fd0d.jpg@1280w_1l_2o_100sh.jpg',
							'https://img.zcool.cn/community/01f475608697f511013f47209e7be5.jpg@1280w_1l_2o_100sh.jpg',
							'https://img.zcool.cn/community/015b3e608697f611013e3b7d0ca587.jpg@1280w_1l_2o_100sh.jpg',
							'https://img.zcool.cn/community/01139e608697f511013f4720a66170.jpg@1280w_1l_2o_100sh.jpg',
							'https://img.zcool.cn/community/0124cf608697f511013e3b7da76892.jpg@1280w_1l_2o_100sh.jpg'
						],
					},
					
					showSrc: '',
					currentIndex:0,

				}, //数据对象结束
				//方法
				methods: {
					GetAll: function() {
						var vm = this;
						var id=GetQueryString('id');
						
						$.ajax({
							url: "http://127.0.0.1:8085/question/selectById?id="+id,
							async: false,
							type: "POST",
							contentType: 'application/json',
							dataType: 'json',
							success: function(json) {
								vm.info=json.data;
								let list = vm.info.banners;
								var currentIndex = vm.currentIndex;
								vm.showSrc =  "http://127.0.0.1:8085/"+list[currentIndex];
								setInterval(function() {
									vm.showSrc = "http://127.0.0.1:8085/"+list[currentIndex];
									currentIndex = (currentIndex + 1) % list.length;
								}, 3000);
							}
						});
						
					},
					//点击上一页
					prevImg(){
						var vm = this;
						let list = vm.info.banners;
						var currentIndex = vm.currentIndex;
						currentIndex = currentIndex-1;
						if(currentIndex<0){
							currentIndex = list.length-1;
						}
						vm.showSrc = "http://127.0.0.1:8085/"+list[currentIndex];
						vm.currentIndex =currentIndex;
					},
					//点击下一页
					nextImg(){
						var vm = this;
						let list = vm.info.banners;
						var currentIndex = vm.currentIndex;
						currentIndex = currentIndex+1;
						if(currentIndex==list.length){
							currentIndex = 0;
						}
						vm.showSrc = "http://127.0.0.1:8085/"+list[currentIndex];
						vm.currentIndex =currentIndex;
					},
					
					infoDetail(e) {
						window.location.href = "museumDetails.html";
					},

				}, //方法结束
				created: function() {
					var vm = this;
					vm.GetAll();
				}, //初始加载方法结束

			}); //vue结束

			function GetQueryString(name) {
				var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
				var r = window.location.search.substr(1).match(reg);
				if (r != null) return unescape(r[2]);
				return null;
			}
		</script>

### 设计与实现基于Spring BootVue的数字博物馆管理系统 #### 三、系统架构设计 对于构建数字博物馆管理系统而言,采用现代化的技术栈能够有效提升开发效率并保障系统的稳定性扩展性。考虑到这一点,可以借鉴校园疫情防控系统中的经验,即利用Spring Boot作为后端框架负责处理业务逻辑服务接口调用,而前端则选用Vue.js来构建交互界面[^1]。 #### 四、技术选型 - **后端**: 使用Java编程语言配合Spring Boot框架搭建RESTful API服务器; - **数据库**: MySQL用于存储展品信息、用户数据以及其他必要的元数据; - **前端**: Vue.js结合Element UI组件库快速建立响应式的Web页面; - **集成方式**: 实现前后端分离模式下的跨域资源共享(CORS),并通过JSON格式交换数据[^4]。 #### 五、具体实施流程 为了更好地规划整个项目的进度安排,下面给出了一套合理的实施方案: ##### 阶段一:需求调研与分析 (第1~2周) 深入了解客户的具体需求以及现有资源情况,制定详细的项目计划书技术路线图。此期间还需完成团队成员的角色分配及责任界定工作。 ##### 阶段二:环境配置与基础建设(第3~4周) 安装所需的软件包如JDK、Maven等,并设置好IDEA/Eclipse开发环境;初始化Git仓库以便版本控制;创建MySQL数据库实例及其表结构定义文件。 ##### 阶段三:核心功能模块开发(第5~8周) 按照既定的功能列表逐步推进各个子系统的编码作业,包括但不限于藏品录入编辑、展览预约查询等功能点的研发。与此同时也要注重单元测试案例编写以确保代码质量。 ##### 阶段四:联调优化与安全加固(第9~10周) 当所有独立部分都完成后便进入整体调试环节,重点解决可能出现的数据传输错误或者性能瓶颈等问题。另外还需要加强网络安全防护措施防止恶意攻击事件的发生。 ##### 阶段五:试运行反馈修正(第11~12周) 邀请少量真实用户参与Beta版产品的体验活动,收集他们提出的宝贵意见并对发现的问题及时作出改进直至满足上线标准为止。 ##### 阶段六:正式发布部署维护更新迭代(长期持续) 经过充分验证后的最终产品即可对外公开提供服务啦!后续还要定期推出新特性增强用户体验感的同时保持良好的售后支持体系运作状态。 ```python # 示例Python脚本展示如何连接到MySQL数据库 import mysql.connector def connect_to_db(): connection = mysql.connector.connect( host='localhost', user='root', password='password', database='museum_management' ) cursor = connection.cursor() return connection, cursor if __name__ == '__main__': conn, cur = connect_to_db() print("Database connected successfully!") ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无语小咪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值