婚纱摄影管理系统(发送邮箱、腾讯地图API、物流API、webSocket实时聊天、协同过滤算法、Echarts图形化分析)
🎈系统亮点:发送邮箱、腾讯地图API、物流API、webSocket实时聊天、协同过滤算法、Echarts图形化分析;
一.系统开发工具与环境搭建
1.系统设计开发工具
后端使用Java编程语言的Spring boot框架
项目架构:B/S架构
运行环境:win10/win11、jdk17
前端:
技术:框架Vue.js;UI库:ElementUI;
开发工具:Visual Studio Code;
后端:
技术:Java语言、mybatis plus、Spring boot框架;
开发工具:IDEA 2023.3.3版本;
数据库:
数据库:mysql5.7/8.0
数据库工具:Navicat12版本;
二.系统实现(部分截图)
2.1 店铺模块的设计与实现
2.1.1 店铺展示功能的实现
(1)功能设计思路
在首页的主体部分,采用轮播图展示精选摄影作品。轮播图可以自动切换,同时支持用户通过左右箭头手动切换。在轮播图下方,列出婚纱摄影店铺的卡片式布局,每个卡片显示店铺名称、地址、好评率、成交订单数、关注人数。用户点击店铺,前端会调用ToShop的异步函数,传递一个参数店铺Id。使用Vue.js框架中的路由功能将用户导航到一个新的URL路径,即/Front/ShopGood,即可进入该店铺的专属页面。
(2)实现代码
async ToShop(Id) {this.$router.push({path: "/Front/ShopGood",query: {ShopId: Id } }); }
//得到店铺信息
async GetShopApi() {let { Data } = await this.$Post("/Shop/Get", { Id: this.$route.query.ShopId })this.Shop = Data; },
//得到商品分类
async GetGoodTypeApi() {let { Data: { Items } } = await this.$Post("/GoodType/List", { ShopId: this.$route.query.ShopId })this.GoodTypeList = Items; },
//分类选择
async handleClick(e) {this.$refs.Pagination.Reload({ ShopGoodTypeId: e.name }); },
(3)店铺展示界面
当用户进入首页时,首先映入眼帘的是一系列的摄影店铺。在浏览过程中,用户可以根据自己的需求和喜好,参考摄影店铺提供的信息进行筛选。一旦用户对某个店铺产生兴趣,只需轻轻点击,即可进入该店铺的专属页面,查看每个店铺的作品和商品信息。店铺展示界面如图4-1所示。
图4-1 店铺界面展示图
4.1.2 店铺管理功能的实现
(1)功能设计思路
店铺管理属于摄影师角色的权限,当摄影师对店铺信息进行修改时,前端会将输入的文本传递给后面接口/Shop/CreateOrEdit,首先,检查当前用户的角色类型是否为摄影师。如果是摄影师并且审核状态为审核失败,那么将审核状态设置为待审核,同时清除审核用户ID和审核原因。随后,将输入的店铺数据传输对象映射为店铺实体对象。调用saveOrUpdate方法,将店铺实体对象保存到数据库中。最后,将更新后的店铺实体对象映射回店铺数据传输对象,并返回给前端。
(2) 功能实现代码
public ShopDto CreateOrEdit(ShopDto input) {
//如果等于摄影商家并且之前审核失败了,那么就把审核信息都清除等待再次审核
if (BaseContext.getCurrentUserDto().getRoleType() == RoleTypeEnum.摄影师) {if (input.getAuditStatus() == AuditStatus.审核失败.index()) {input.setAuditStatus(AuditStatus.待审核.index());input.setAuditUserId(null);input.setAuditReason(null);}
}
//声明一个店铺实体
Shop Shop = input.MapToEntity();
//调用数据库的增加或者修改方法
saveOrUpdate(Shop);
//把传输模型返回给前端
return Shop.MapToDto();
}
(3) 店铺管理界面
摄影师进入店铺管理界面,店铺的名称、logo、店铺地址、店铺保障和详情信息。这些店铺的信息可以帮助顾客更全面地了解店铺,向顾客保证他们的权益,让他们更加放心地购买商品。店铺管理界面如图4-2所示。
图4-2 店铺管理界面展示图
2.2 摄影作品模块的设计与实现
2.2.1 摄影作品展示功能的实现
(1)功能设计思路
当用户通过店铺的链接进入到店铺的专属界面后,系统会以分页的形式展示该店铺的拍摄标题和作品。将使用Vue.js来创建一个网格布局,每行显示四个作品的缩略图。前端通过接口地址/Opus/List进行调用,获取到作品列表的数据。接下来,我们将这些数据传递给名为OpusListCard的组件进行渲染和显示。为了增加交互性,我们还需要为每个作品的缩略图添加点击事件监听器。当用户点击某个作品时,系统将打开一个新页面,并显示该作品的所有图片。
(2)功能实现代码
public PagedResult<GoodDto> List(GoodPagedInput input) {
//构建where条件+排序
LambdaQueryWrapper<Good> queryWrapper = BuilderQuery(input);
List<Good> goods = _GoodMpper.selectList(queryWrapper);
//把Good实体转换成Good传输模型
List<GoodDto> items = Extension.copyBeanList(goods, GoodDto.class);
//计算表的数据
items = DispatchItem(items);
if (input.getIsHot() == Boolean.TRUE) {
//根据购买人次items.sort(Comparator.comparing(GoodDto::getBuyCount).reversed());
} else {
//根据创建时间从小到达排序
items.sort(Comparator.comparing(GoodDto::getCreationTime));
}
//返回一个分页结构给前端
return Extension.PagedResultBuild(items, input);
}
(3)摄影作品展示界面
用户通过店铺进入店铺的专属界面,会注意到店铺的拍摄标题和主图。如果用户对某个拍摄标题或主图感兴趣,可以点击进去查看这一组的所有图片,以便更全面地了解产品或服务的特点和细节。作品展示界面如图4-3所示。
图4-3 摄影作品界面展示图
2.2.2 摄影作品管理功能的实现
(1)功能设计思路
摄影师角色的功能,摄影作品管理。包括上传作品、浏览已有作品、搜索和筛选作品等功能。使用分页加载更多来处理大量数据。在作品列表中点击某一项,允许摄影师修改作品信息,如名称、封面等。提供“删除”按钮以便快速移除单个作品。实现多选框功能,支持摄影师一次性选择多个作品进行批量删除或修改状态。在作品详情页,所有可编辑字段通过表单呈现,提交后触发后端API更新数据库。提供搜索框和下拉菜单,允许摄影师按名称和拍摄景点快速找到目标作品。
(2)功能实现代码
public PagedResult<OpusDto> List(OpusPagedInput input) {
//构建where条件+排序
LambdaQueryWrapper<Opus> queryWrapper = BuilderQuery(input);
//按创建时间从大到小排序 最新的显示在最前面
queryWrapper=queryWrapper.orderByDesc(Opus::getCreationTime);
//构建一个分页查询的model
Page<Opus> page = new Page<>(input.getPage(), input.getLimit());
//从数据库进行分页查询获取作品数据
IPage<Opus> pageRecords= _OpusMpper.selectPage(page, queryWrapper);
//获取所有满足条件的数据行数
Long totalCount= _OpusMpper.selectCount(queryWrapper);
//把Opus实体转换成Opus传输模型
List<OpusDto> items= Extension.copyBeanList(pageRecords.getRecords(),OpusDto.class);
//计算表的数据
items = DispatchItem(items);
//返回一个分页结构给前端
return PagedResult.GetInstance(items,totalCount);
}
(3)摄影作品管理展示界面
摄影师有权利管理摄影作品,摄影师可以将他们的摄影作品上传到系统中。摄影师可以通过内容浏览功能来查看和管理它们。他们可以浏览已上传的作品列表,并选择要进行修改、删除或批量删除的作品。这样,摄影师可以根据自己的需求对作品进行管理和调整。作品管理界面如图4-4所示。
图4-4 摄影作品管理界面展示图
2.3 摄影服务的设计与实现
2.3.1 摄影服务功能的实现
(1)功能设计思路
每个店铺都设有对应的摄影服务商品,可以通过点击店铺查看专属的商品。也可以在首页的热门推荐查找到推荐的商品。商品列表页面,每个商品以卡片形式展示,包括缩略图、名称、价格等基本信息。点击商品后进入详情页,左侧显示高清图片轮播图,右侧列出商品名称、详细参数、价格、用户评价等信息。提供“立即购买”和“加入购物车”按钮,以及“收藏”功能。下半部分展示商品的图文详情、参数信息以及用户评价。
(2) 功能实现代码
async GetGoodApi() {
let { Data } = await this.$Post("/Good/Get", { Id: this.$route.query.GoodId })
let imgs = FullConvertUrlArray(Data.ImageUrls);
this.ActiveImgUrl = imgs[0].url;
this.ImageList = imgs;
this.Detail = Data; },
async GetGoodPropListApi() {
let { Data: { Items } } = await this.$Post("/GoodProp/List", { GoodId: this.$route.query.GoodId });
this.GoodPropList = Items;},
async ThumbnailMouseOver(url) {
this.ActiveImgUrl = url;
}
(3)摄影服务商品展示界面
用户浏览商品列表时,可以点击每个商品以查看其详细信息。在商品详情页面上,用户可以阅读商品的详细描述、规格、价格等信息。可以选择立即购买该商品、将其添加到购物车或将其收藏。摄影服务商品展示界面如图4-5所示。
图4-5 摄影服务界面展示图
4.3.2 摄影服务管理功能的实现
(1)功能设计思路
在商品列表页顶部添加一个搜索框,允许用户输入商品名称、单位或选择分类进行搜索。提供一个“导出”按钮,点击后将当前搜索结果以Excel格式下载到本地。使用ObjectMapper对象将JSON字符串query转换为GoodPagedInput类型的对象input。从input对象中获取商品列表items。创建一个Excel工作簿workbook。在工作簿中创建一个名为"商品表"的表格sheet。设置表格的列宽度为10个字节。遍历表头数据,为每个表头创建一个单元格,并将表头文本写入单元格,同时应用之前创建的样式。
(2)功能实现代码
ObjectMapper mapper = new ObjectMapper();
GoodPagedInput input = mapper.readValue(query, GoodPagedInput.class);
List<GoodDto> items = List(input).getItems();
//声明一个工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
//生成一个表格,设置表格名称为"商品"
HSSFSheet sheet = workbook.createSheet("商品表");
//设置表格列宽度为10个字节
sheet.setDefaultColumnWidth(30);
//创建标题的显示样式
HSSFCellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//创建第一行表头
HSSFRow headrow = sheet.createRow(0);
//表头数据
String[] header = {"名称", "封面", "主图", "价格", "库存", "详情内容", "店铺名称", "用户名称", "单位", "商品分类名称",};
//遍历添加表头(下面模拟遍历商品,也是同样的操作过程)
for (int i = 0; i < header.length; i++) {
}
(3)摄影服务管理界面
摄影师可以通过名称、单位和分类等条件搜索商品。可以通过导出功能,将搜索结果导出为Excel,方便给用户分享。允许对商品进行修改、删除和新增操作,查看商品属性(摄影包含的服务,比如:相框、相册等)。摄影服务管理界面如图4-6所示。
图4-6 摄影服务管理界面展示图
2.3.3 聊天会话功能的实现
(1)功能设计思路
实时通讯聊天使用了WebSocket技术,sendMessage方法用于向指定的用户发送消息。首先,通过userId从webSocketMap中获取对应的WebSocket对象。如果WebSocket对象存在,就尝试通过session的getBasicRemote()方法发送文本消息。如果发送成功,会打印一条日志信息,表示消息发送成功。如果发送失败,会捕获IOException异常并打印堆栈跟踪信息。如果WebSocket对象不存在,说明对方没有上线,会打印一条日志信息,表示消息发送失败。
(3) 功能实现代码
public static void sendMessage(String message, String userId) {
WebSocket webSocket = webSocketMap.get(userId);
if (webSocket != null) {
try {
webSocket.session.getBasicRemote().sendText(message);
System.out.println("【websocket消息】发送消息成功,目标用户id=" + userId + ",消息内容:" + message);
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("【websocket消息】发送消息失败,用户id=" + userId + "对方没有上线");
}
}
//前端请求时一个websocket时
public void onOpen(Session session, @PathParam("userId") String userId) {
this.userId = userId;
this.session = session;
webSocketMap.put(userId, this);
System.out.println("【websocket消息】有新的连接,连接id=" + userId + ":" + this);
}
(2) 聊天会话展示界面
用户通过聊天界面发送消息时,商家会立刻接收到这些信息。用户询问关于某个产品的详细信息,他们只需要在对话框中输入自己的问题并发送。商家端在接收到这条消息后,会立即进行处理,并给予详尽的答复。聊天展示界面如图4-9所示。
图4-7 聊天会话界面展示图
2.4 旅拍景点模块的设计与实现
2.4.1 旅拍景点功能的实现
(1)功能设计思路
在“旅拍景点”菜单栏下展示全国各地的旅拍景点列表。当用户点击某个景点时,前端页面跳转到该景点的详情页面。在景点详情页面中展示该景点的拍摄作品和详细信息。添加一个“导航去这里”按钮,点击后触发线路规划功能。前端获取电脑的经纬度,它将创建一个地图实例,并将地图的中心设置为给定的经纬度坐标。然后,它检查是否有一个名为beginPosition的属性,如果有,它将使用该属性的经纬度作为路线规划的起点;否则,它将使用默认的经纬度坐标(39.984039, 116.307630307503)作为起点。最后,它将终点设置为与中心相同的经纬度坐标。随后,创建一个驾车路线规划类的实例,设置是否返回多方案以及规划策略。然后调用search方法,传入起点和终点坐标,获取路线规划结果。最后将结果中的路线信息赋值给this.routes,并绘制路径折线。
(2)功能实现代码
let that = this;
if (this.Detail.Latitude && this.Detail.Longitude) {
var center = new TMap.LatLng(this.Detail.Latitude, this.Detail.Longitude) // 初始化地图
let map = new TMap.Map('containerMap', {
zoom: 6, // 设置地图缩放级别
center: center
});
this.map = map;
if (this.beginPosition) {
var startPosition = new TMap.LatLng(this.beginPosition.coords.latitude, this.beginPosition.coords.longitude); // 路线规划起点
}
else {
var startPosition = new TMap.LatLng(39.984039, 116.307630307503); // 路线规划起点
}
var endPosition = new TMap.LatLng(this.Detail.Latitude, this.Detail.Longitude); // 路线规划终点
(3)旅拍景点展示界面
用户点击“旅拍景点”菜单栏,可以看到全国各地的旅拍景点列表。选择想要的景点,前端跳转界面,进入景点详情。显示该景点拍摄的作品,以及景点的详细信息。可以点击“导航去这里”,系统则会自动生成线路规划方案,仅供用户参考。旅拍景点展示界面如图4-8所示。
图4-8 旅拍景点界面展示图
2.4.2 旅拍景点管理功能的实现
(1)功能设计思路
管理员拥有添加、编辑和删除景点的权限。允许管理员输入景点名称、详细地址、介绍等信息并提交。提交后触发后端API将新景点插入数据库。每一列都提供一个“地址选址”按钮,前端会调用地图组件,允许管理员通过地图选择地点。一旦选择了地点,系统会自动获取该地点的经纬度。管理员确认无误后,系统会更新数据库中的经纬度字段。提供“删除”和“编辑”按钮以便快速修改或移除景点。
(2)功能实现代码
Search.searchRectangle({ keyword: this.searchForm.address, bounds: map.getBounds() }) .then((result) => {
console.log("结果", result);
result.data.forEach((item, index) => {
var geometries = markers.getGeometries();
var infoWindow = new TMap.InfoWindow({
map: map, position: item.location, content: `<h3>${item.title}</h3><p>地址:${item.address}</p><p>电话:${item.tel}</p>`,
offset: { x: 0, y: -50 } });
infoWindow.close();
infoWindowList[index] = infoWindow;
geometries.push({
id: String(index), // 点标注数据数组
position: item.location });
markers.updateGeometries(geometries); // 绘制地点标注
markers.on('click', (e) => {
infoWindowList[Number(e.geometry.id)].open();
}); }); });
(3)旅拍景点管理界面
管理员可以进行新增旅拍的景点,为景点设置“地点选址”,获取经纬度。当设置了经纬度,用户在前台就可以通过地址进行导航并为用户规划路线。管理员可以进行删除、修改旅拍景点。旅拍景点管理界面如图4-9所示。
图4-9 旅拍景点管理展示图
2.5 订单模块的设计与实现
2.5.1 订单功能的实现
(1)功能设计思路
订单列表页面,每个订单以列表形式展示,包括订单编号、物流单号、商品概览、下单时间等基本信息,使用分页进行展示。在订单列表页提供一个搜索框,允许用户输入订单编号或物流单号进行搜索。根据输入的条件从数据库中筛选并返回匹配的订单。提供“退款售后”、“查看物流”、“确认收货”等操作按钮。点击后弹出确认对话框,用户确认后触发相应的后端API进行处理。
(2) 功能实现代码
public PagedResult<OrderInfoDto> List(OrderInfoPagedInput input) {
LambdaQueryWrapper<OrderInfo> queryWrapper = BuilderQuery(input);
queryWrapper = queryWrapper.orderByDesc(OrderInfo::getCreationTime);
//构建一个分页查询的model
Page<OrderInfo> page = new Page<>(input.getPage(), input.getLimit());
IPage<OrderInfo> pageRecords = _OrderInfoMpper.selectPage(page, queryWrapper);
Long totalCount = _OrderInfoMpper.selectCount(queryWrapper);
List<OrderInfoDto> items = Extension.copyBeanList(pageRecords.getRecords(), OrderInfoDto.class);
items = DispatchItem(items);
return PagedResult.GetInstance(items, totalCount);
}
(3) 订单展示界面
用户可以在“个人中心”中,查看自己的所有订单。可以通过订单编号、物流单号等查看对应的订单信息。用户可以选择退款售后、查看物流、确认收货操作。订单展示界面如图4-10所示。
图4-10 订单展示图
2.5.2 订单分析功能的实现
(1)功能设计思路
在顶部展示了一个包含多个订单统计信息的列表。每个列表项都有一个标题和一个数量。数据通过后端接口获取的,然后通过JavaScript渲染到页面上。获取热门商品的数据并生成一个柱状图,获取最近30天收入的数据生成折线图。通过调用后端接口获取数据,然后对数据进行处理。接着,设置图表的配置项,包括标题、提示框、网格、x轴和y轴等。最后,使用 ECharts 库初始化图表并设置配置项,将图表渲染到页面上。同时,监听窗口大小变化事件,当窗口大小发生变化时,调整图表的大小以适应新的屏幕尺寸。
(2) 功能实现代码
async GetGoodSalesApi() {
let { Data } = await this.$Post("/OrderInfo/GetGoodSales", { ShopId: this.ShopId })
Data = Data.slice(0, 10);
let option = { title: { text: '热门商品' },
tooltip: { trigger: 'axis',axisPointer: { type: 'shadow' } },
grid: { left: '3%', right: '4%', bottom: '3%',containLabel: true }, xAxis: [{ type: 'category',
data: Data.map(x => x.Good.Name.substring(0, 10)),
axisTick: {
alignWithLabel: true } } ],
yAxis: [ { type: 'value' } ],
series: [ { name: '销量', type: 'bar', barWidth: '10%', data: Data.map(x => x.Qty) } ] };
let myChart = echarts.init(document.getElementById("GoodSalesEchart"));// 图标初始化
myChart.setOption(option);// 渲染页面
window.addEventListener("resize", () => {
myChart.resize();
});
(3) 订单分析界面
管理员登录后台管理系统,找到订单分析模块。在订单分析界面中,你可以看到各种状态的订单数量统计。对于“最近30天收入”、“热门商品”分别使用折现图、柱状图进行展示。订单分析界面图如图4-11所示。
图4-11 订单分析展示图
三.系统功能需求
1.用户
2.摄影师
3.管理员
四、系统代码结构截图
1.后端
2.前端
3.数据库
四、源码获取
1.系统非商用,非开源,非无偿。
2.由本人开发,如需源码,请联系以下方式,koimibuff。
3.项目有很多,并未全部上传,如果未找到想要的,可直接咨询。