IT社区|网络社区平台|基于SpringBoot的IT社区平台

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介: IT社区|网络社区平台|基于SpringBoot的IT社区平台

项目编号:BS-PT-098

前言:

随着国家的发展,网络的普及,以及IT行业的高薪就职,导致越来越多的人进入IT行业,分一杯羹,但是由于众多的人数,肯定会存在技术参差不齐的现象,在书写代码上出现了错误,有问题解决不出来时,不知道找谁询问。因此IT社区平台应景而生,不同的IT大神,小白,都可以发布帖子,对帖子进行客观、实在的评价,不同的观点,不同的思想,能够碰发出不一样的火花。本系统的设计目的主要是为了方便同学们在论坛上进行沟通,与网友进行思维碰撞。方便大家在学习生活上有疑难的时候可以询问他人。

本社区平台属于前后端分离的项目,前台包含了首页、文章模块、论贴模块、搜索模块、视频模块、排行模块、筛选模块、个人中心模块(个人资料、我的文章、我的视频、我的帖子、消息通知、收藏、关注、评论、粉丝),后台包含了首页、论贴管理模块、视频管理模块、论贴类型模块、文章管理模块,用户管理,文章标签管理,日志管理。其中每个主模块中又包含多个子模块。

一,项目简介

本社区平台提供了两个可使用的角色:用户、管理员。本平台包含了前台系统和后台管理系统两个系统,前台系统供用户使用,而后台管理系统则供管理员使用。前台系统分为登录注册模块、首页、文章模块、论贴模块、搜索模块、视频模块、排行模块、筛选模块、个人中心模块;后台系统分为首页、论贴管理模块、视频管理模块、论贴类型模块、文章管理模块,用户管理,文章标签管理,日志管理等。

1.前台系统

文章模块:用户可以查看自己感兴趣的文章,可以对文章点赞,收藏,转发,评论等。

论贴模块:用户对其他用户提出的问题进行回答讨论,该模块没限制,用户可以自行发言。

搜索模块:用户可以在前台系统中输入相关信息进行全局查询。

视频模块:用户可以发布教学视频,知识视频等。

排行模块:对论贴类型进行各种排行,评分,点击量,收藏量等等。

个人中心模块:包含各种子模块:个人资料、我的文章、我的视频、我的帖子、消息通知、收藏、关注、评论、粉丝、私信等。

2.后台系统

论贴管理:管理员可以对论贴进行审核,驳回操作。

文章管理:管理员对文章,转发,评论进行管理。

论贴类型模块:管理员对论贴的种类进行管理操作。

用户管理模块:管理员对用户进行认证。

文章标签维护:管理员对前台显示的文章标签进行禁用启动编辑等操作。

日志管理:记录用户的各种操作。

本系统的具体功能分析如下:

  1. 前台系统模块功能

表3-1 前台系统模块描述

功能名称

功能描述

文章模块

该模块中主要功能包括查看文章详情,发布文章,对文章进行评论,转发文章,对文章点赞。发布文章时选择文章标签然后进行发布。

搜索模块

通过输入关键字进行模糊查询,查询的范围包含论贴类型,论贴,文章,视频,用户。一输多查。

论贴模块

发布帖子,通过选择不同的帖子类型进行发布不同的帖子,有面试贴,技术贴,内推贴等等。进入某个帖子专区,可以查看全部属于该专区的帖子,以及属于该专区的视频。

排行模块

排行中包含评分排行,点击量排行,收藏量排行等功能。

视频模块

主要功能有发布视频,观看视频,和类型表关联。可以在专区中查看该专区所属的视频。

个人中心模块

该模块中的功能有:个人资料的修改查看、个人论贴、个人视频、个人文章、个人转发、个人消息(系统消息、动态消息、评论消息、私信消息)、个人收藏、个人评论、个人关注、个人粉丝等若干个功能。

2.后台系统模块功能

表3-2 后台系统模块描述

模块名称

功能描述

文章管理模块

原创文章,转发文章,评论进行删除,重写发布操作。

用户管理模块

对用户进行认证,查询,删除操作。

论贴管理模块

该模块功能对用户发布的帖子进行审核,驳回操作。

视频管理模块

该模块的主要功能是对用户发布的视频进行审核,驳回等操作。

文章标签维护模块

对标签的禁用启用,编辑,彻底删除,查询,添加等操作

日志管理模块

查询用户的日志,删除日志。

二,环境介绍

语言环境:Java:  jdk1.8

数据库:Mysql: mysql5.7

应用服务器:Tomcat:  tomcat8.5.31

开发工具:IDEA或eclipse

后台开发:Springboot+Mybatis-plus

前台开发:VUE

三,系统展示

5.1 登录注册界面的实现

登录界面如图5-1,用户输入用户名和密码进行账号的登录。

注册界面如图5-2,用户输入邮箱等信息,通过服务端发送验证码到用户邮箱中,将验证码同时存入redis缓存中,用户填写验证码以及其他相关信息,将输入的验证码与redis中的验证码进行比对,一致则注册成功。

图5-1 登录主页面

图5-2 注册主页面

5.2文章模块的实现

文章模块界面如图5-3,5-4,该模块具体包含文章列表,文章详情,文章转发,用户发布文章,以及对文章进行的点赞,评论操作都在该模块中进行,展示文章列表,发布文章,文章详情是对文章表的增,删,查操作,另外只有用户本人可以对自己发布的文章进行删除,编辑权限,其他用户无次类权限,所有该功能的实现同时需要用户表的关联,评论需要与评论表关联。

图5-3 文章列表展示页面

图5-4 文章详情页面

5.3搜索模块的实现

检索模块界面如图5-5,用户输入关键词,通过模糊查询,包含多条查询语句,对论贴类型,论贴,文章,视频,用户的模糊查询,前端查询函数同时执行多条查询sql语句,使其达到目的。

图5-5 检索模块界面

5.4 论贴模块的实现

论贴界面如图5-6、5-7。通过对论贴表,用户表进行查询显示全部帖子,及其详细内容,用户登录后才能发布帖子,实现帖子的发布是对论贴表的增操作,内容包含文字和图片,用户发布的帖子数据库表state默认为0,需要管理员审核,当管理员审核通过后,state变为1,才算正在的发布,其他用户才能看见。

图5-6 论贴页面实现

图5-7 发布论贴实现

5.5 排行模块的实现

排行模块如图5-8,该模块通过对数据库话题标(论贴类型表)进行查询,分别对评分,点击量,收藏量进行排序,通过sql语句查询出前10条数据返回页面,进行页面渲染。

图5-8 排行列表实现

5.6 视频模块的实现

    视频模块如图5-9、5-10,该模块通过阿里云第三方视频点播服务来完成,通过获取阿里云oss的endpoint,keyid,keysecret,bucketname进行绑定,获取第三方api来实现具体的功能。用户发布视频后,同样需要管理员来审核。

图5-9 视频列表实现

图5-10 视频播放实现

5.7 个人中心模块的实现

个人中心模块如图5-11、5-12,该模块是用户最重要的模块,里面包含了许多子模块,该模块游客无法访问,只有当用户登录后才能显示,前端判断用户是否登录来实现,表格样式通过用户id来对相应各表的查询显示操作,收藏,私信,消息通知,个人信息都在里面显示,同时可以进行相应的操作。

图5-11 个人中心页面

图5-12 我的文章页面

5.8 文章管理模块实现

文章管理模块如图5-13、5-14,该模块主要是对文章表、评论表进行sql操作,文章显示,逻辑删除,重新发布等操作,包括转发的文章,同时也包括评论语句。该模块是对文章表,评论表的基本sql语句操作。

图5-13文章管理列表页面

图5-14 文章评论管理页面

四,核心代码展示

public Result item(@RequestParam(defaultValue = "0L", name = "userId") Long userId, @RequestParam("thatId") Long thatId) {
        // 保存收藏、关注、粉丝、动态、转发、评论、消息数
        int collectionCount = collectionService.count(new QueryWrapper<Collection>().eq("user_id", thatId));
        int attentionCount = attentionService.count(new QueryWrapper<Attention>().eq("this_id", thatId));
        int fansCount = attentionService.count(new QueryWrapper<Attention>().eq("that_id", thatId));
        int essayCount = essayService.count(new QueryWrapper<Essay>().eq("user_id", thatId));
        int forwardCount = forwardService.count(new QueryWrapper<Forward>().eq("user_id", thatId));
        int commentCount = commentService.count(new QueryWrapper<Comment>().eq("user_id", thatId));
        int messageCount = messageService.count(new QueryWrapper<Message>().eq("this_id", thatId));
        int newsCount = newsService.count(new QueryWrapper<News>().eq("user_id", thatId).eq("zt", MapUtil.YFB));
        int videoCount = videoService.count(new QueryWrapper<Video>().eq("user_id", thatId).eq("zt", MapUtil.VIDEO_YFB));
        final Attention one = attentionService.getOne(new QueryWrapper<Attention>().eq("this_id", userId).eq("that_id", thatId));
        User user;
        Object obj = redisUtils.get(MapUtil.USER_KEY + thatId);
        if (obj != null) {
            user = (User) obj;
        } else {
            user = userService.getById(thatId);
            redisUtils.set(MapUtil.USER_KEY + thatId, user, MapUtil.USER_SXQ);
        }
        Item item = new Item();
        // 是否已关注
        item.setFlagAttention(one == null ? 0 : 1);
        item.setAttentionCount(attentionCount);
        item.setCollectionCount(collectionCount);
        item.setFansCount(fansCount);
        item.setEssayCount(essayCount);
        item.setForwardCount(forwardCount);
        item.setCommentCount(commentCount);
        item.setMessageCount(messageCount);
        item.setNewsCount(newsCount);
        item.setVideoCount(videoCount);
        BeanUtil.copyProperties(user, item);
        return Result.success(item);
    }
try {
            //accessKeyId, accessKeySecret
            //fileName:上传文件原始名称
            String fileName = file.getOriginalFilename();
            //title:上传之后显示名称
            String title = fileName.substring(0, fileName.lastIndexOf("."));
            //inputStream:上传文件输入流
            InputStream inputStream = file.getInputStream();
            UploadStreamRequest request = new UploadStreamRequest(ConstantProperties.ACCESS_KEY_ID, ConstantProperties.ACCESS_KEY_SECRET, title, fileName, inputStream);
            UploadVideoImpl uploader = new UploadVideoImpl();
            UploadStreamResponse response = uploader.uploadStream(request);
            String videoId;
            if (response.isSuccess()) {
                videoId = response.getVideoId();
            } else {
                //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。
                // 其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因
                videoId = response.getVideoId();
            }
            return videoId;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
package com.superb.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.superb.common.MapUtil;
import com.superb.entity.Message;
import com.superb.entity.News;
import com.superb.entity.Record;
import com.superb.entity.Video;
import com.superb.service.MessageService;
import com.superb.service.OssService;
import com.superb.service.RecordAdminService;
import com.superb.service.VideoService;
import com.superb.util.Result;
import com.superb.util.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
/**
 * <p>
 *  前端控制器
 * </p>
 *
 */
@RestController
@RequestMapping("/video")
public class VideoController {
    @Autowired
    private OssService ossService;
    @Autowired
    private VideoService videoService;
    /**
     * 视频列表 已发布
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/list")
    public Result list(@RequestParam(defaultValue = "1", name = "current") Integer current,
                       @RequestParam(defaultValue = "10", name = "size") Integer size){
        Page<Map<String, Object>> page = new Page<>(current, size);
        IPage<Map<String, Object>> mapIPage = videoService.listVideo(page, MapUtil.VIDEO_YFB);
        return Result.success(mapIPage);
    }
    /**
     * 相关视频推荐列表 已发布
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/listVideoByStyleId")
    public Result listVideoByStyleId(@RequestParam(defaultValue = "1", name = "current") Integer current,
                       @RequestParam(defaultValue = "5", name = "size") Integer size, @RequestParam("styleId")Integer styleId){
        Page<Map<String, Object>> page = new Page<>(current, size);
        IPage<Map<String, Object>> mapIPage = videoService.listByStyleId(page, styleId);
        return Result.success(mapIPage);
    }
    /**
     * 查询所有已驳回  video  附加user
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/listAdminYbh")
    public Result listAdminYbh (@RequestParam(defaultValue = "1",value = "current") Integer current,
                                @RequestParam(defaultValue = "10",name = "size") Integer size) {
        Page<Map<String ,Object>> page = new Page<>(current, size);
        IPage<Map<String, Object>> list = videoService.listVideo(page, MapUtil.VIDEO_YBH);
        return Result.success(list);
    }
    /**
     * 查询所有待审核  video  附加user
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/listAdminDsh")
    public Result listAdminDsh (@RequestParam(defaultValue = "1",value = "current") Integer current,
                                @RequestParam(defaultValue = "10",name = "size") Integer size) {
        Page<Map<String ,Object>> page = new Page<>(current, size);
        IPage<Map<String, Object>> list = videoService.listVideo(page, MapUtil.VIDEO_DSH);
        return Result.success(list);
    }
    /**
     * 视频排行
     * @return
     */
    @GetMapping("/itemPh")
    public Result itemPh () {
        return Result.success(videoService.listPh(MapUtil.PHTS, MapUtil.VIDEO_YFB));
    }
    /**
     * 视频详情
     * @param id
     * @return
     */
    @GetMapping("/itemXq")
    public Result itemXq (@RequestParam("id") Integer id) {
        Map<String, Object> map = videoService.videoById(id);
        map.put("count", (Long)map.get("count") + 1L);
        // 访问量+1
        Video video = new Video();
        video.setId(id);
        video.setCount((Long)map.get("count"));
        videoService.updateById(video);
        return Result.success(map);
    }
    /**
     * 个人视频
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/listByUserId")
    public Result listByUserId(@RequestParam(defaultValue = "1", name = "current") Integer current,
                       @RequestParam(defaultValue = "8", name = "size") Integer size,
                       @RequestParam("userId") Long userId){
        Page<Map<String, Object>> page = new Page<>(current, size);
        IPage<Map<String, Object>> mapIPage = videoService.listByUserId(page, userId);
        return Result.success(mapIPage);
    }
    /**
     * 上传视频
     * @param file
     * @return
     */
    @PostMapping("/uploadAlyVideo")
    public Result uploadAlyVideo(MultipartFile file){
        String videoId = ossService.uploadVideoAly(file);
        return Result.success(videoId);
    }
    /**
     * 保存
     * @param video
     * @return
     */
    @PostMapping("/saveVideo")
    public Result saveVideo(@RequestBody Video video){
        video.setZt(MapUtil.VIDEO_DSH);
        // 获取视频url
        String urlById = Utils.getUrlById(video.getVideoId());
        video.setVideoUrl(urlById);
        videoService.save(video);
        return Result.success();
    }
    /**
     * 删除视频
     * @param video
     * @return
     */
    @PostMapping("/delete")
    public Result delete(@RequestBody Video video){
        ossService.removeMoreAlyVideo(video.getVideoId());
        return Result.success();
    }
    @Autowired
    private RecordAdminService recordAdminService;
    @Autowired
    private MessageService messageService;
    /**
     * 驳回视频
     * @param video
     * @return
     */
    @PostMapping("/bhAdmin")
    public Result bhAdmin (@RequestBody Video video) {
        video.setZt(MapUtil.VIDEO_YBH);
        videoService.updateById(video);
        // 发消息
        Message message = new Message();
        message.setMessageTitle(MapUtil.XTTZ);
        message.setMessageText("你的视频《" + video.getVideoTitle() + "》已被驳回");
        message.setMessageType(MapUtil.XXLX_XT);
        message.setThatId(MapUtil.GLYID);
        message.setThisId(video.getUserId());
        // 后台记录
        recordAdminService.xr("驳回视频:" + video.getVideoTitle());
        messageService.save(message);
        return Result.success("已驳回");
    }
    /**
     * 发布
     * @param video
     * @return
     */
    @PostMapping("/fbAdmin")
    public Result fbAdmin (@RequestBody Video video) {
        video.setZt(MapUtil.VIDEO_YFB);
        videoService.updateById(video);
        // 发消息
        Message message = new Message();
        message.setMessageTitle(MapUtil.XTTZ);
        message.setMessageText("你的视频《" + video.getVideoTitle() + "》已通过审核");
        message.setMessageType(MapUtil.XXLX_XT);
        message.setThatId(MapUtil.GLYID);
        message.setThisId(video.getUserId());
        // 后台记录
        recordAdminService.xr("审批通过:" + video.getVideoTitle());
        messageService.save(message);
        return Result.success("已发布");
    }
    /**
     * 模糊查询
     * @param text
     * @return
     */
    @GetMapping("/search")
    public Result search(@RequestParam(defaultValue = "", value = "text") String text,
                         @RequestParam(defaultValue = "1", name = "current") Integer current,
                         @RequestParam(defaultValue = "8", name = "size") Integer size){
        Page<Map<String, Object>> page = new Page<>(current, size);
        IPage<Map<String, Object>> search = videoService.search(page, text);
        return Result.success(search);
    }
}

五,项目总结

首先是论文的摘要部分,对整个项目进行了初步的了解,然后第一部分绪论,对项目的背景和目的内容出发,书写项目的开发目的,第二部分,系统项目所使用的相关技术的介绍,第三部分对系统分析,可行性,需求进行深入分析,第四部分则是系统的具体设计,从架构到功能到数据库,每个模块的具体设计思路,流程等,第五部分是对系统的运行页面功能,和核心代码的具体实现思路的撰写,最后就是总结致谢等。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
机器学习/深度学习 人工智能 运维
企业内训|LLM大模型在服务器和IT网络运维中的应用-某日企IT运维部门
本课程是为某在华日资企业集团的IT运维部门专门定制开发的企业培训课程,本课程旨在深入探讨大型语言模型(LLM)在服务器及IT网络运维中的应用,结合当前技术趋势与行业需求,帮助学员掌握LLM如何为运维工作赋能。通过系统的理论讲解与实践操作,学员将了解LLM的基本知识、模型架构及其在实际运维场景中的应用,如日志分析、故障诊断、网络安全与性能优化等。
92 2
|
7天前
|
NoSQL 关系型数据库 MySQL
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
96 56
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
|
2月前
|
安全 物联网 物联网安全
量子通信网络:安全信息交换的新平台
【10月更文挑战第6天】量子通信网络作为一种全新的安全信息交换平台,正逐步展现出其独特的优势和巨大的潜力。通过深入研究和不断探索,我们有理由相信,量子通信网络将成为未来信息安全领域的重要支柱,为构建更加安全、高效、可靠的信息社会贡献力量。让我们共同期待量子通信网络在未来的广泛应用和美好前景!
|
3月前
|
XML 网络协议 物联网
基于surging的木舟IOT平台如何添加网络组件
【8月更文挑战第30天】在基于 Surging 的木舟 IOT 平台中添加网络组件需经历八个步骤:首先理解 Surging 及平台架构;其次明确组件需求,选择合适技术库;接着创建项目并配置;然后设计实现网络功能;再将组件集成至平台;接着进行详尽测试;最后根据反馈持续优化与维护。具体实施时应参照最新文档调整。
69 10
|
3月前
|
缓存 算法 物联网
基于AODV和leach协议的自组网络平台matlab仿真,对比吞吐量,负荷,丢包率,剩余节点个数,节点消耗能量
本系统基于MATLAB 2017b,对AODV与LEACH自组网进行了升级仿真,新增运动节点路由测试,修正丢包率统计。AODV是一种按需路由协议,结合DSDV和DSR,支持动态路由。程序包含参数设置、消息收发等功能模块,通过GUI界面配置节点数量、仿真时间和路由协议等参数,并计算网络性能指标。 该代码实现了节点能量管理、簇头选举、路由发现等功能,并统计了网络性能指标。
179 73
|
1月前
|
机器学习/深度学习 搜索推荐 安全
深度学习之社交网络中的社区检测
在社交网络分析中,社区检测是一项核心任务,旨在将网络中的节点(用户)划分为具有高内部连接密度且相对独立的子群。基于深度学习的社区检测方法,通过捕获复杂的网络结构信息和节点特征,在传统方法基础上实现了更准确、更具鲁棒性的社区划分。
73 7
|
3月前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
113 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
2月前
|
Java Maven Spring
springboot学习一:idea社区版本创建springboot项目的三种方式(第三种为主)
这篇文章介绍了在IntelliJ IDEA社区版中创建Spring Boot项目的三种方法,特别强调了第三种方法的详细步骤。
976 0
springboot学习一:idea社区版本创建springboot项目的三种方式(第三种为主)
|
3月前
|
机器学习/深度学习 人工智能 算法
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台。果蔬识别系统,本系统使用Python作为主要开发语言,通过收集了12种常见的水果和蔬菜('土豆', '圣女果', '大白菜', '大葱', '梨', '胡萝卜', '芒果', '苹果', '西红柿', '韭菜', '香蕉', '黄瓜'),然后基于TensorFlow库搭建CNN卷积神经网络算法模型,然后对数据集进行训练,最后得到一个识别精度较高的算法模型,然后将其保存为h5格式的本地文件方便后期调用。再使用Django框架搭建Web网页平台操作界面,实现用户上传一张果蔬图片识别其名称。
69 0
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台