网站可以做多少事情菏泽企业做网站
news/
2025/9/28 0:23:05/
文章来源:
网站可以做多少事情,菏泽企业做网站,粤康码小程序,贵州毕节网站建设简介
该项目采用微服务架构#xff0c;实现了前后端分离的系统设计。在前端#xff0c;我们选择了 Vue3 配合 TypeScript 和 ElementUi 框架#xff0c;以提升开发效率和用户体验。而在后端#xff0c;则是运用 SpringBoot 和 Mybatis-plus 进行开发#xff0c;保证了系统…简介
该项目采用微服务架构实现了前后端分离的系统设计。在前端我们选择了 Vue3 配合 TypeScript 和 ElementUi 框架以提升开发效率和用户体验。而在后端则是运用 SpringBoot 和 Mybatis-plus 进行开发保证了系统的高效和稳定。此外我们引入了 ElasticSearch 作为全文检索服务以加快搜索速度和提高检索效率。同时通过 WebSocket 技术实现了实时聊天和消息推送功能增强了用户的互动体验。
代码下载
https://url21.ctfile.com/f/15432821-1020751544-c0e7e4?p8418 (访问密码: 8418) 项目目录
yanhuo-web 前段页面yanhuo-auth 认证服务yanhuo-common 公共模块,存放一些工具类或公用类yanhuo-platform 烟火 app 主要功能模块yanhuo-im 聊天模块yanhuo-search 搜索模块yanhuo-util 第三方服务模块邮箱短信oss 对象存储服务yanhuo-xo 对象存放模块
源码讲解
Controller 源码示例
首先来看 AlbumController 中的代码主要讲解八个容易误解的方面。 RestController这是一个组合注解它表示这个类是一个控制器并且其中的所有方法都会返回数据而不是视图。 RequestMapping(“/album”)这个注解用于将 HTTP 请求映射到 MVC 和 REST 控制器的处理方法上。在这里它将所有的请求映射到以/album 为前缀的 URL。 Autowired这个注解用于自动注入 Spring 容器中的 bean。在这里它注入了一个 AlbumService 的实例这个实例提供了专辑的增删改查操作。 getAlbumPageByUserId 方法这个方法用于根据用户 ID 获取专辑列表并支持分页。它接受三个参数当前页currentPage分页数pageSize和用户 IDuserId。它调用 albumService 的 getAlbumPageByUserId 方法来获取数据并返回一个 Result?对象。 saveAlbumByDTO 方法这个方法用于保存专辑。它接受一个 AlbumDTO 对象作为参数并使用 ValidatorUtils.validateEntity 方法进行数据校验。然后它调用 albumService 的 saveAlbumByDTO 方法来保存专辑并返回一个 Result?对象。 getAlbumById 方法这个方法用于根据专辑 ID 获取专辑。它接受一个 albumId 作为参数并调用 albumService 的 getAlbumById 方法来获取数据并返回一个 Result?对象。 deleteAlbumById 方法这个方法用于根据专辑 ID 删除专辑。它接受一个 albumId 作为参数并调用 albumService 的 deleteAlbumById 方法来删除数据并返回一个 Result?对象。 updateAlbumByDTO 方法这个方法用于更新专辑。它接受一个 AlbumDTO 对象作为参数并使用 ValidatorUtils.validateEntity 方法进行数据校验。然后它调用 albumService 的 updateAlbumByDTO 方法来更新专辑并返回一个 Result?对象。
package com.yanhuo.platform.controller;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yanhuo.common.result.Result;
import com.yanhuo.common.validator.ValidatorUtils;
import com.yanhuo.common.validator.group.AddGroup;
import com.yanhuo.common.validator.group.UpdateGroup;
import com.yanhuo.platform.service.AlbumService;
import com.yanhuo.xo.dto.AlbumDTO;
import com.yanhuo.xo.entity.Album;
import com.yanhuo.xo.vo.AlbumVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RequestMapping(/album)
RestController
public class AlbumController {AutowiredAlbumService albumService;/*** 根据用户id获取专辑* param currentPage 当前页* param pageSize 分页数* param userId 用户id* return 专辑数*/RequestMapping(getAlbumPageByUserId/{currentPage}/{pageSize})public Result? getAlbumPageByUserId(PathVariable long currentPage, PathVariable long pageSize,String userId){PageAlbum page albumService.getAlbumPageByUserId(currentPage,pageSize,userId);return Result.ok(page);}/*** 保存专辑* param albumDTO 专辑实体* return success*/RequestMapping(saveAlbumByDTO)public Result? saveAlbumByDTO(RequestBody AlbumDTO albumDTO) {ValidatorUtils.validateEntity(albumDTO, AddGroup.class);albumService.saveAlbumByDTO(albumDTO);return Result.ok();}/*** 根据专辑id获取专辑* param albumId 专辑id* return 专辑实体*/RequestMapping(getAlbumById)public Result? getAlbumById(String albumId) {AlbumVo albumVo albumService.getAlbumById(albumId);return Result.ok(albumVo);}/*** 根据专辑id删除专辑* param albumId 专辑id* return success*/RequestMapping(deleteAlbumById)public Result? deleteAlbumById(String albumId) {albumService.deleteAlbumById(albumId);return Result.ok();}/*** 更新专辑* param albumDTO 专辑实体* return success*/RequestMapping(updateAlbumByDTO)public Result? updateAlbumByDTO(RequestBody AlbumDTO albumDTO) {ValidatorUtils.validateEntity(albumDTO, UpdateGroup.class);albumService.updateAlbumByDTO(albumDTO);return Result.ok();}
}
Service 源码示例
下面代码是一个服务实现类用于处理与笔记相关的业务逻辑。这个类使用了 MyBatis-Plus 框架来简化数据库操作并使用了 Hutool 工具类库来处理 JSON 数据。下面是这段代码的详细解释 NoteServiceImpl 类继承了 ServiceImplNoteDao, Note这意味着它继承了 MyBatis-Plus 提供的基本 CRUD 操作。NoteDao 是一个接口用于定义与笔记相关的数据库操作方法。Note 是一个实体类用于映射数据库中的笔记表。 类中注入了多个服务包括用户服务、标签服务、分类服务、ES 客户端、关注服务、点赞或收藏服务以及 OSS 客户端。这些服务将在后面的方法中被使用。 getNoteById 方法用于根据笔记 ID 获取笔记详情。该方法首先通过 getById 方法从数据库中获取笔记对象然后将浏览次数加 1 并更新到数据库。接下来通过用户 ID 获取用户对象并将用户名、头像和更新时间设置到 NoteVo 对象中。然后检查当前用户是否关注了该笔记的作者并设置 NoteVo 对象的 isFollow 属性。接着检查当前用户是否点赞或收藏了该笔记并设置 NoteVo 对象的 isLike 和 isCollection 属性。最后通过标签笔记关系服务获取该笔记的所有标签并设置到 NoteVo 对象中。 saveNoteByDTO 方法用于保存新的笔记。该方法首先从当前用户上下文中获取用户 ID然后将传入的 JSON 字符串转换为 NoteDTO 对象并将其转换为 Note 对象。然后将用户 ID 设置到 Note 对象中并保存到数据库。接下来更新用户的动态数量。然后处理标签关系将标签 ID 和笔记 ID 保存到标签笔记关系表中。然后通过 OSS 客户端上传图片并将图片 URL 保存到 Note 对象中。最后将 Note 对象更新到数据库并将笔记信息添加到 ES 搜索引擎中。 deleteNoteByIds、updateNoteByDTO 和 getHotPage 方法目前没有实现具体的业务逻辑。这段代码的主要功能是处理与笔记相关的业务逻辑包括获取笔记详情、保存新的笔记、更新笔记等。代码中使用了 MyBatis-Plus 框架来简化数据库操作并使用了 Hutool 工具类库来处理 JSON 数据。此外代码中还使用了 ES 搜索引擎和 OSS 对象存储服务来处理笔记的搜索和图片存储。
package com.yanhuo.platform.service.impl;import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yanhuo.common.auth.AuthContextHolder;
import com.yanhuo.common.exception.YanHuoException;
import com.yanhuo.common.result.Result;
import com.yanhuo.common.utils.ConvertUtils;
import com.yanhuo.platform.client.EsClient;
import com.yanhuo.platform.client.OssClient;
import com.yanhuo.platform.service.*;
import com.yanhuo.xo.dao.NoteDao;
import com.yanhuo.xo.dto.NoteDTO;
import com.yanhuo.xo.entity.*;
import com.yanhuo.xo.vo.NoteSearchVo;
import com.yanhuo.xo.vo.NoteVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;Service
public class NoteServiceImpl extends ServiceImplNoteDao, Note implements NoteService {AutowiredUserService userService;AutowiredTagNoteRelationService tagNoteRelationService;AutowiredTagService tagService;AutowiredCategoryService categoryService;AutowiredEsClient esClient;AutowiredFollowerService followerService;AutowiredLikeOrCollectionService likeOrCollectionService;AutowiredOssClient ossClient;Overridepublic NoteVo getNoteById(String noteId) {Note note this.getById(noteId);note.setViewCount(note.getViewCount() 1);User user userService.getById(note.getUid());NoteVo noteVo ConvertUtils.sourceToTarget(note, NoteVo.class);noteVo.setUsername(user.getUsername()).setAvatar(user.getAvatar()).setTime(note.getUpdateDate().getTime());boolean follow followerService.isFollow(user.getId());noteVo.setIsFollow(follow);String currentUid AuthContextHolder.getUserId();ListLikeOrCollection likeOrCollectionList likeOrCollectionService.list(new QueryWrapperLikeOrCollection().eq(like_or_collection_id, noteId).eq(uid, currentUid));if(!likeOrCollectionList.isEmpty()) {SetInteger types likeOrCollectionList.stream().map(LikeOrCollection::getType).collect(Collectors.toSet());noteVo.setIsLike(types.contains(1));noteVo.setIsCollection(types.contains(3));}//得到标签ListTagNoteRelation tagNoteRelationList tagNoteRelationService.list(new QueryWrapperTagNoteRelation().eq(nid, noteId));ListString tids tagNoteRelationList.stream().map(TagNoteRelation::getTid).collect(Collectors.toList());if (!tids.isEmpty()) {ListTag tagList tagService.listByIds(tids);noteVo.setTagList(tagList);}this.updateById(note);return noteVo;}Transactional(rollbackFor Exception.class)Overridepublic String saveNoteByDTO(String noteData, MultipartFile[] files) {String currentUid AuthContextHolder.getUserId();NoteDTO noteDTO JSONUtil.toBean(noteData, NoteDTO.class);Note note ConvertUtils.sourceToTarget(noteDTO, Note.class);note.setUid(currentUid);boolean save this.save(note);if(!save){return null;}// TODO 需要往专辑中添加User user userService.getById(currentUid);user.setTrendCount(user.getTrendCount() 1);userService.updateById(user);ListString tids noteDTO.getTagList();ListTagNoteRelation tagNoteRelationList new ArrayList();String tags;if(!tids.isEmpty()){for (String tid : tids) {TagNoteRelation tagNoteRelation new TagNoteRelation();tagNoteRelation.setTid(tid);tagNoteRelation.setNid(note.getId());tagNoteRelationList.add(tagNoteRelation);}tagNoteRelationService.saveBatch(tagNoteRelationList);tags tagService.listByIds(tids).stream().map(Tag::getTitle).collect(Collectors.joining(,));}Category category categoryService.getById(note.getCid());Category parentCategory categoryService.getById(note.getCpid());ListString dataList;try {ResultListString result ossClient.saveBatch(files, 1);dataList result.getData();}catch (Exception e){throw new YanHuoException(添加图片失败);}String[] urlArr dataList.toArray(new String[dataList.size()]);String urls JSONUtil.toJsonStr(urlArr);note.setUrls(urls);note.setNoteCover(urlArr[0]);this.updateById(note);// 往es中添加数据NoteSearchVo noteSearchVo ConvertUtils.sourceToTarget(note, NoteSearchVo.class);noteSearchVo.setUsername(user.getUsername()).setAvatar(user.getAvatar()).setLikeCount(0L).setCategoryName(category.getTitle()).setCategoryParentName(parentCategory.getTitle()).setTags(tags).setTime(note.getUpdateDate().getTime());esClient.addNote(noteSearchVo);return note.getId();}Overridepublic void deleteNoteByIds(ListString noteIds) {}Overridepublic String updateNoteByDTO(NoteDTO noteDTO) {return null;}Overridepublic PageNoteVo getHotPage(long currentPage, long pageSize) {return null;}
}
Vue3 源码示例
这段代码是一个Vue3组件的模板和脚本部分用于展示和加载关注者的动态trends。下面是对代码的详细解释
模板部分Template
template 标签内定义了组件的结构。使用了Vue的v-infinite-scroll指令来实现无限滚动加载更多数据。使用v-for指令循环渲染trendData数组中的每个动态项。每个动态项包含用户头像、用户信息、动态内容、图片和交互按钮点赞、评论等。使用v-if和v-else指令来条件渲染加载中的图片和已加载的图片。事件绑定click用于处理用户交互如跳转到用户页面、点赞、查看动态等。
脚本部分Script
导入了必要的Vue组件和图标。使用Vue 3的Composition APIscript setup定义组件的逻辑。响应式变量如currentPage、pageSize、trendData等用于控制分页和存储数据。handleLoad函数用于处理图片加载完成的事件。toUser函数用于导航到用户页面。getFollowTrends函数用于获取关注者的动态数据。loadMoreData函数用于加载更多动态数据。toMain函数用于显示动态的详细内容。close函数用于关闭动态详细内容的显示。refresh函数用于刷新动态数据。like函数用于处理点赞和取消点赞的操作。 12.initData函数用于初始化动态数据。在组件挂载时调用initData函数。
样式部分Style
使用了Less预处理器编写样式。定义了.container、.trend-container、.trend-item等类用于设置组件的布局和样式。使用了flex布局来排列用户头像、信息和图片。使用了scoped属性确保样式只应用于当前组件。
templatediv classcontainer v-infinite-scrollloadMoreDataul classtrend-containerli classtrend-item v-for(item, index) in trendData :keyindexa classuser-avatarimg classavatar-item :srcitem.avatar clicktoUser(item.uid) //adiv classmaindiv classinfodiv classuser-infoa class{{ item.username }}/a/divdiv classinteraction-hintspan{{ item.time }}/span/divdiv classinteraction-content clicktoMain(item.nid){{ item.content }}/divdiv classinteraction-imgs clicktoMain(item.nid)div classdetails-box v-for(url, index) in item.imgUrls :keyindexel-imagev-if!item.isLoading:srcurlloadhandleLoad(item)styleheight: 230px; width: 100%/el-imageel-imagev-else:srcurlclassnote-img animate__animated animate__fadeIn animate__delay-0.5sfitcover/el-image/div/divdiv classinteraction-footerdiv classicon-itemiclassiconfont icon-follow-fillstylewidth: 1em; height: 1emclicklike(item.nid, item.uid, index, -1)v-ifitem.isLike/iiclassiconfont icon-followstylewidth: 1em; height: 1emclicklike(item.nid, item.uid, index, 1)v-else/ispan classcount{{ item.likeCount }}/span/divdiv classicon-itemChatRound stylewidth: 0.9em; height: 0.9em /span classcount{{item.commentCount}}/span/divdiv classicon-itemMore stylewidth: 1em; height: 1em //div/div/div/div/li/uldiv classfeeds-loadingRefresh stylewidth: 1.2em; height: 1.2em colorrgba(51, 51, 51, 0.8) //divFloatingBtn click-refreshrefresh/FloatingBtnMainv-showmainShow:nidnidclassanimate__animated animate__zoomIn animate__delay-0.5sclick-mainclose/Main/div
/template
script langts setup
import { ChatRound, More, Refresh } from element-plus/icons-vue;
import { ref } from vue;
import { getFollowTrendPage } from /api/follower;
import { formateTime } from /utils/util;
import FloatingBtn from /components/FloatingBtn.vue;
import Main from /pages/main/main.vue;
import type { LikeOrCollectionDTO } from /type/likeOrCollection;
import { likeOrCollectionByDTO } from /api/likeOrCollection;
import { useRouter } from vue-router;const router useRouter();
const currentPage ref(1);
const pageSize ref(5);
const trendData refArrayany([]);
const trendTotal ref(0);
const topLoading ref(false);
const mainShow ref(false);
const nid ref();
const likeOrCollectionDTO refLikeOrCollectionDTO({likeOrCollectionId: ,publishUid: ,type: 0,
});const handleLoad (item: any) {item.isLoading true;
};const toUser (uid: string) {router.push({ name: user, state: { uid: uid } });
};const getFollowTrends () {getFollowTrendPage(currentPage.value, pageSize.value).then((res) {const { records, total } res.data;console.log(records, total);records.forEach((item: any) {item.time formateTime(item.time);trendData.value.push(item);});trendTotal.value total;});
};const loadMoreData () {currentPage.value 1;getFollowTrends();
};const toMain (noteId: string) {nid.value noteId;mainShow.value true;
};const close (nid: string, isLike: boolean) {const index trendData.value.findIndex((item) item.nid nid);trendData.value[index].isLike isLike;mainShow.value false;
};const refresh () {let scrollTop window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;const clientHeight window.innerHeight ||Math.min(document.documentElement.clientHeight, document.body.clientHeight);if (scrollTop clientHeight * 2) {const timeTop setInterval(() {document.documentElement.scrollTop document.body.scrollTop scrollTop - 100;if (scrollTop 0) {clearInterval(timeTop);topLoading.value true;setTimeout(() {currentPage.value 1;trendData.value [];getFollowTrends();topLoading.value false;}, 500);}}, 10); //定时调用函数使其更顺滑} else {document.documentElement.scrollTop 0;topLoading.value true;setTimeout(() {currentPage.value 1;trendData.value [];getFollowTrends();topLoading.value false;}, 500);}
};const like (nid: string, uid: string, index: number, val: number) {likeOrCollectionDTO.value.likeOrCollectionId nid;likeOrCollectionDTO.value.publishUid uid;likeOrCollectionDTO.value.type 1;likeOrCollectionByDTO(likeOrCollectionDTO.value).then(() {trendData.value[index].isLike val 1;trendData.value[index].likeCount val;});
};const initData () {getFollowTrends();
};initData();
/scriptstyle langless scoped
.container {flex: 1;padding: 0 24px;padding-top: 72px;width: 67%;height: 100vh;margin: 0 auto;.feeds-loading {margin: 3vh;text-align: center;}.trend-container {.trend-item {display: flex;flex-direction: row;padding-top: 24px;max-width: 100vw;.user-avatar {margin-right: 24px;flex-shrink: 0;.avatar-item {width: 48px;height: 48px;display: flex;align-items: center;justify-content: center;cursor: pointer;border-radius: 100%;border: 1px solid rgba(0, 0, 0, 0.08);object-fit: cover;}}.main {flex-grow: 1;flex-shrink: 1;display: flex;flex-direction: row;padding-bottom: 12px;border-bottom: 1px solid rgba(0, 0, 0, 0.08);.info {flex-grow: 1;flex-shrink: 1;.user-info {display: flex;flex-direction: row;align-items: center;font-size: 16px;font-weight: 600;margin-bottom: 4px;a {color: #333;}}.interaction-hint {font-size: 14px;color: rgba(51, 51, 51, 0.6);margin-bottom: 8px;}.interaction-content {display: flex;font-size: 14px;color: #333;margin-bottom: 12px;line-height: 140%;cursor: pointer;}.interaction-imgs {display: flex;.details-box {width: 25%;border-radius: 4px;margin: 8px 12px 0 0;cursor: pointer;.note-img {width: 100%;height: 230px;display: flex;border-radius: 4px;align-items: center;justify-content: center;cursor: pointer;object-fit: cover;}}}.interaction-footer {margin: 8px 12px 0 0;padding: 0 12px;display: flex;justify-content: space-between;align-items: center;.icon-item {display: flex;justify-content: left;align-items: center;color: rgba(51, 51, 51, 0.929);.count {margin-left: 3px;}}}}}}}
}
/style
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/920121.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!