当前位置: 首页 > news >正文

基于Java技术的选课管理系统设计与实现

末尾获取源码
开发语言:Java
Java开发工具:JDK1.8
后端框架:SSM
前端:采用JSP技术开发
数据库:MySQL5.7和Navicat管理工具结合
服务器:Tomcat8.5
开发软件:IDEA / Eclipse
是否Maven项目:是


目录

一、项目简介

二、系统功能

三、系统项目截图

个人中心

管理员管理

教师管理

学生管理

基础数据管理

课程信息管理

公告信息管理

学生成绩管理

学生选课管理

四、核心代码

登录相关

文件上传

封装


一、项目简介

如今,科学技术的力量越来越强大,通过结合较为成熟的计算机技术,促进了学校、医疗、商城等许多行业领域的发展。为了顺应时代的变化,各行业结合互联网、人工智能等技术,纷纷开展了管理信息化建设。传统的学校信息管理模式,主要以人工记录的方式统计和存储学生选课信息,这种管理模式容易丢失信息,并且不方便管理人员更新和查询相关数据。相比于传统管理模式,信息化管理模式主要使用计算机存储和管理相关信息记录,操作简单便捷,并且具体较强的灵活性,容易对数据实现查询和更新操作,有利于相关人员在同等时间内,完成更多的工作,并且能够尽可能的减少工作人员发生失误的概率。在idea集成开发平台上,选课管理系统采用了B/S开发结构模式,并且通过使用Java语言编写相关代码,设计系统功能模块,MySQL数据库设计数据表格,存储学生选课信息,Tomcat服务器发布系统网址,处理请求和响应消息。本系统的开发,改进学校管理人员的工作模式,有利于简化工作流程,加快工作进度,提高信息处理效率。


二、系统功能

本系统的整体开发过程是采用B/S结构模式而开展的,通过使用Java语言、MySQL数据库等技术设计系统相关的功能,功能设计完成后,可以通过使用浏览器,运行和使用系统。通过需求分析的相关内容,可以基本上确定系统的主要功能设计。基于JSP的选课管理系统的使用对象主要分为管理员角色和用户角色,主要的功能需求包括用户管理、课程信息管理、学生选课管理等。



三、系统项目截图

个人中心

个人中心模块设计的主要目的是方便用户对密码等个人信息进行管理,用户可以根据自己的实际需求,选择每隔一段时间,更新个人账户的用户名和密码

 

管理员管理

管理员管理模块设计的主要目的是方便管理用户对相关的管理员用户信息进行管理,管理用户可以选择查看管理员用户的密码,修改用户名 

 

教师管理

教师管理模块设计的主要目的是方便管理用户对相关的教师用户信息进行管理,管理用户可以选择查看教师用户的联系方式,修改教师用户的真实姓名

 

学生管理

学生管理模块设计的主要目的是方便管理用户对相关的学生用户信息进行管理,管理用户可以选择查看学生用户的联系方式,修改学生用户的头像

 

基础数据管理

基础数据管理模块设计的主要目的是方便管理用户对相关的班级、课程类型、公告类型信息进行管理,管理用户可以选择查看班级、课程类型、公告类型信息的名称,修改班级、课程类型、公告类型信息记录,删除失效的班级、课程类型、公告类型信息记录

 

 

课程信息管理

课程信息管理模块设计的主要目的是方便管理用户对相关的课程信息进行管理,管理用户可以选择查看课程信息的课程文件,修改课程信息的封面,删除失效的课程信息记录

 

公告信息管理

公告信息管理模块设计的主要目的是方便管理用户对相关的公告信息进行管理,管理用户可以选择查看公告信息的详细内容,修改公告信息的类型,删除失效的公告信息记录

 

学生成绩管理

学生成绩管理模块设计的主要目的是方便管理用户对相关的学生成绩进行管理,管理用户可以选择查看学生的成绩信息,修改学生成绩的课程名称,删除失效的学生成绩信息记录

 

学生选课管理

学生选课管理模块设计的主要目的是方便管理用户对相关的学生选课进行管理,管理用户可以选择查看学生选课的课程名称信息,修改学生选课的课程文件,删除失效的学生选课信息记录

 


四、核心代码

登录相关


package com.controller;import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.TokenEntity;
import com.entity.UserEntity;
import com.service.TokenService;
import com.service.UserService;
import com.utils.CommonUtil;
import com.utils.MD5Util;
import com.utils.MPUtil;
import com.utils.PageUtils;
import com.utils.R;
import com.utils.ValidatorUtils;/*** 登录相关*/
@RequestMapping("users")
@RestController
public class UserController{@Autowiredprivate UserService userService;@Autowiredprivate TokenService tokenService;/*** 登录*/@IgnoreAuth@PostMapping(value = "/login")public R login(String username, String password, String captcha, HttpServletRequest request) {UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));if(user==null || !user.getPassword().equals(password)) {return R.error("账号或密码不正确");}String token = tokenService.generateToken(user.getId(),username, "users", user.getRole());return R.ok().put("token", token);}/*** 注册*/@IgnoreAuth@PostMapping(value = "/register")public R register(@RequestBody UserEntity user){
//    	ValidatorUtils.validateEntity(user);if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {return R.error("用户已存在");}userService.insert(user);return R.ok();}/*** 退出*/@GetMapping(value = "logout")public R logout(HttpServletRequest request) {request.getSession().invalidate();return R.ok("退出成功");}/*** 密码重置*/@IgnoreAuth@RequestMapping(value = "/resetPass")public R resetPass(String username, HttpServletRequest request){UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));if(user==null) {return R.error("账号不存在");}user.setPassword("123456");userService.update(user,null);return R.ok("密码已重置为:123456");}/*** 列表*/@RequestMapping("/page")public R page(@RequestParam Map<String, Object> params,UserEntity user){EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params));return R.ok().put("data", page);}/*** 列表*/@RequestMapping("/list")public R list( UserEntity user){EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();ew.allEq(MPUtil.allEQMapPre( user, "user")); return R.ok().put("data", userService.selectListView(ew));}/*** 信息*/@RequestMapping("/info/{id}")public R info(@PathVariable("id") String id){UserEntity user = userService.selectById(id);return R.ok().put("data", user);}/*** 获取用户的session用户信息*/@RequestMapping("/session")public R getCurrUser(HttpServletRequest request){Long id = (Long)request.getSession().getAttribute("userId");UserEntity user = userService.selectById(id);return R.ok().put("data", user);}/*** 保存*/@PostMapping("/save")public R save(@RequestBody UserEntity user){
//    	ValidatorUtils.validateEntity(user);if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {return R.error("用户已存在");}userService.insert(user);return R.ok();}/*** 修改*/@RequestMapping("/update")public R update(@RequestBody UserEntity user){
//        ValidatorUtils.validateEntity(user);userService.updateById(user);//全部更新return R.ok();}/*** 删除*/@RequestMapping("/delete")public R delete(@RequestBody Long[] ids){userService.deleteBatchIds(Arrays.asList(ids));return R.ok();}
}

文件上传

package com.controller;import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ResourceUtils;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.ConfigEntity;
import com.entity.EIException;
import com.service.ConfigService;
import com.utils.R;/*** 上传文件映射表*/
@RestController
@RequestMapping("file")
@SuppressWarnings({"unchecked","rawtypes"})
public class FileController{@Autowiredprivate ConfigService configService;/*** 上传文件*/@RequestMapping("/upload")public R upload(@RequestParam("file") MultipartFile file,String type) throws Exception {if (file.isEmpty()) {throw new EIException("上传文件不能为空");}String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);File path = new File(ResourceUtils.getURL("classpath:static").getPath());if(!path.exists()) {path = new File("");}File upload = new File(path.getAbsolutePath(),"/upload/");if(!upload.exists()) {upload.mkdirs();}String fileName = new Date().getTime()+"."+fileExt;File dest = new File(upload.getAbsolutePath()+"/"+fileName);file.transferTo(dest);FileUtils.copyFile(dest, new File("C:\\Users\\Desktop\\jiadian\\springbootl7own\\src\\main\\resources\\static\\upload"+"/"+fileName));if(StringUtils.isNotBlank(type) && type.equals("1")) {ConfigEntity configEntity = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "faceFile"));if(configEntity==null) {configEntity = new ConfigEntity();configEntity.setName("faceFile");configEntity.setValue(fileName);} else {configEntity.setValue(fileName);}configService.insertOrUpdate(configEntity);}return R.ok().put("file", fileName);}/*** 下载文件*/@IgnoreAuth@RequestMapping("/download")public ResponseEntity<byte[]> download(@RequestParam String fileName) {try {File path = new File(ResourceUtils.getURL("classpath:static").getPath());if(!path.exists()) {path = new File("");}File upload = new File(path.getAbsolutePath(),"/upload/");if(!upload.exists()) {upload.mkdirs();}File file = new File(upload.getAbsolutePath()+"/"+fileName);if(file.exists()){/*if(!fileService.canRead(file, SessionManager.getSessionUser())){getResponse().sendError(403);}*/HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);    headers.setContentDispositionFormData("attachment", fileName);    return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);}} catch (IOException e) {e.printStackTrace();}return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR);}}

封装

package com.utils;import java.util.HashMap;
import java.util.Map;/*** 返回数据*/
public class R extends HashMap<String, Object> {private static final long serialVersionUID = 1L;public R() {put("code", 0);}public static R error() {return error(500, "未知异常,请联系管理员");}public static R error(String msg) {return error(500, msg);}public static R error(int code, String msg) {R r = new R();r.put("code", code);r.put("msg", msg);return r;}public static R ok(String msg) {R r = new R();r.put("msg", msg);return r;}public static R ok(Map<String, Object> map) {R r = new R();r.putAll(map);return r;}public static R ok() {return new R();}public R put(String key, Object value) {super.put(key, value);return this;}
}

相关文章:

基于Java技术的选课管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

在UBUNTU上使用Qemu和systemd-nspawn搭建RISC-V轻量级用户模式开发环境

参考链接 使用Qemu和systemd-nspawn搭建RISC-V轻量级用户模式开发环境 - 知乎 安装Qemu sudo apt updatesudo apt -y install qemu-user-binfmt qemu-user-static systemd-container sudo apt -y install zstd 配置环境 RISCV_FILEarchriscv-2023-10-09.tar.zstwget -c ht…...

JAVA使用POI向doc加入图片

JAVA使用POI向doc加入图片 前言 刚来一个需求需要导出一个word文档&#xff0c;文档内是系统某个界面的各种数据图表&#xff0c;以图片的方式插入后导出。一番查阅资料于是乎着手开始编写简化demo,有关参考poi的文档查阅 Apache POI Word(docx) 入门示例教程 网上大多数是XXX…...

反向传播算法

反向传播算法的数学解释 反向传播算法是深度学习中用于训练神经网络的核心算法。它通过计算损失函数相对于网络权重的梯度来更新权重&#xff0c;从而最小化损失。 反向传播的基本原理 反向传播算法基于链式法则&#xff0c;它按层反向传递误差&#xff0c;从输出层开始&…...

记录 | ubuntu降低内核版本的方法

降低 ubuntu 内核&#xff0c;比如降低到 4.15 版本&#xff0c;下载对应 4.15.0.128 内核离线安装&#xff0c;网址&#xff1a; http://archive.ubuntu.com/ubuntu/pool/main/l/linux/&#xff0c; 根据实际选择下载&#xff0c;我这里选择&#xff0c;安装的话采用 dpkg -i …...

MX6ULL学习笔记 (八) platform 设备驱动实验

前言&#xff1a; 什么是 Linux 下的 platform 设备驱动 Linux下的字符设备驱动一般都比较简单&#xff0c;只是对IO进行简单的读写操作。但是I2C、SPI、LCD、USB等外设的驱动就比较复杂了&#xff0c;需要考虑到驱动的可重用性&#xff0c;以避免内核中存在大量重复代码&…...

初识Linux:权限(2)

目录 权限 用户&#xff08;角色&#xff09; 文件权限属性 文件的权限属性&#xff1a; 有无权限的区别&#xff1a; 身份匹配&#xff1a; 拥有者、所属组的修改&#xff1a; 八进制的转化&#xff1a; 文件的类型&#xff1a; x可执行权限为什么不能执行&#xf…...

测试环境使用问题及其优化对策实践

1 背景及问题 G.J.Myers在<软件测试技巧>中提出&#xff1a;测试是为了寻找错误而运行程序的过程&#xff0c;一个好的测试用例是指很可能找到迄今为止尚未发现的错误的测试&#xff0c; 一个成功的测试是揭示了迄今为止尚未发现的错误的测试。 对于新手来说&#xff0…...

【力扣】206.反转链表

206.反转链表 这道题有两种解法&#xff0c;但不只有两种&#xff0c;嘿嘿。 法一&#xff1a;迭代法 就是按循序遍历将每一个指针的指向都给改了。比如说1——>2——>3改为null<——1<——2<——3这样。那这里以第二个结点为例&#xff0c;想一想。我想要指向…...

Python:核心知识点整理大全7-笔记

目录 4.2.5 遗漏了冒号 4.3 创建数值列表 4.3.1 使用函数 range() 4.3.2 使用 range()创建数字列表 结果如下&#xff1a; 4.3.3 对数字列表执行简单的统计计算 4.3.4 列表解析 4.4 使用列表的一部分 4.4.1 切片 4.4.2 遍历切片 4.4.3 复制列表 4.2.5 遗漏了冒号 fo…...

Hadoop学习笔记(HDP)-Part.15 安装HIVE

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …...

【力扣100】4.移动零

题目链接 我的题解&#xff1a; class Solution:def moveZeroes(self, nums: List[int]) -> None:"""Do not return anything, modify nums in-place instead."""# 思路是先计算共有几个0&#xff0c;然后remove几次&#xff0c;再末位加几个…...

Filebeat使用指南

Filebeat介绍主要优势主要功能配置日志的解析Kibana中设置日志解析安装步骤安装Filebeat安装监控通过prometheus监控 Filebeat和Logstash的主要区别 Filebeat介绍 Filebeat是使用Golang实现的轻量型日志采集器&#xff0c;也是Elasticsearch stack的一员。它可以作为一个agent…...

【Vue2】Vue的介绍与Vue的第一个实例

文章目录 前言一、为什么要学习Vue二、什么是Vue1.什么是构建用户界面2.什么是渐进式Vue的两种开发方式&#xff1a; 3.什么是框架 三、创建Vue实例四、插值表达式 {{}}1.作用&#xff1a;利用表达式进行插值&#xff0c;渲染到页面中2.语法3.错误用法 五、响应式特性1.什么是响…...

十五届蓝桥杯分享会(一)

注&#xff1a;省赛4月&#xff0c;决赛6月 一、蓝桥杯整体介绍 1.十四届蓝桥杯软件电子赛参赛人数&#xff1a;C 8w&#xff0c;java/python 2w&#xff0c;web 4k&#xff0c;单片机 1.8w&#xff0c;嵌入式/EDA5k&#xff0c;物联网 300 1.1设计类参赛人数&#xff1a;平…...

原生video设置控制面板controls显示哪些控件

之前我们学习了如何使用原生video播放视频 今天来一个进阶版的——设置控制面板controls显示哪些控件 先看一下当我们使用原生video时&#xff0c;controls属性为true时&#xff0c;相关代码如下&#xff1a; 正常的控制面板默认显示的控件有&#xff1a;播放、时间线、音量调…...

openlayers地图使用---跟随地图比例尺动态标绘大小的一种方式2

openlayers地图使用—跟随地图比例尺动态标绘大小的一种方式2 预期&#xff1a;随着地图比例尺放大缩小&#xff0c;地图上的标绘随着变化尺寸 思路&#xff1a;通过不断添加地图图层实现标绘的动态缩放 优点&#xff1a;标绘放大缩小非常流畅 缺点&#xff1a;标绘超过1000…...

C语言期末考试复习PTA数据类型及表达式-分支结构程序-循环结构-数组经典选择题

目录 第一章&#xff1a;C语言数据类型和表达式 第一题&#xff1a; 第二题&#xff1a; 第三题&#xff1a; 第四题&#xff1a; 第五题&#xff1a; 第六题&#xff1a; 第七题&#xff1a; 第八题&#xff1a; 第九题&#xff1a; 第二章&#xff1a;分支结构程序…...

RHEL8_Linux访问NFS存储及自动挂载

本章主要介绍NFS客户端的使用 创建FNS服务器并通过NFS共享一个目录在客户端上访问NFS共享的目录自动挂载的配置和使用 1.访问NFS存储 前面介绍了本地存储&#xff0c;本章就来介绍如何使用网络上的存储设备。NFS即网络文件系统&#xff0c;所实现的是 Linux 和 Linux 之间的共…...

python 使用 AppiumService 类启动appium server

一、前置说明 在Appium的1.6.0版本中引入了AppiumService类&#xff0c;可以很方便的通过该类来管理Appium服务器的启动和停止。 二、操作步骤 import osfrom appium.webdriver.appium_service import AppiumService as OriginalServerfrom libs import pathclass AppiumSer…...

OpenClaw小团队协作:Qwen3.5-9B共享模型端点的权限管理

OpenClaw小团队协作&#xff1a;Qwen3.5-9B共享模型端点的权限管理 1. 为什么小团队需要共享OpenClaw实例 去年我们实验室遇到一个典型问题&#xff1a;五个研究员共用三台GPU服务器&#xff0c;每个人都想用OpenClaw做自动化实验&#xff0c;但各自部署不仅浪费资源&#xf…...

Gazebo 11 插件开发避坑实录:从 ModelPlugin 报错到 WorldPlugin 的平滑迁移

Gazebo 11插件开发深度指南&#xff1a;从兼容性陷阱到高效迁移策略 当Gazebo从9版本迭代到11版本时&#xff0c;许多开发者突然发现原本运行良好的插件代码开始报出各种奇怪的错误。这就像你熟悉的咖啡店突然换了所有设备——虽然咖啡豆还是那些咖啡豆&#xff0c;但制作流程…...

公众号流量分成大涨!后公众号时代如何运营?流量商店旗下的互粉平台成增粉利器!

“上个月流量主收入终于突破5000元了&#xff01;”深夜&#xff0c;运营“职场进化论”公众号的小林在朋友圈晒出后台截图。一年前&#xff0c;这个只有几百粉丝的账号月收入还不到100元。而如今&#xff0c;像小林这样依靠公众号流量分成实现可观收入的创作者正越来越多。 20…...

SEO 优化师如何处理网站收录和排名下降的问题

SEO 优化师如何处理网站收录和排名下降的问题 在数字营销中&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;是一个至关重要的环节&#xff0c;尤其是对于那些希望在百度上获得高排名和流量的网站。即使是最优秀的SEO策略&#xff0c;也可能会在某些时候面临网站收录和排…...

基因组调查实战:KMC+GenomeScope2.0多倍体分析全流程解析

1. 为什么需要基因组调查&#xff1f; 当你第一次拿到一个未知物种的测序数据时&#xff0c;最头疼的问题往往是&#xff1a;这个基因组到底有多大&#xff1f;复杂度如何&#xff1f;该投入多少测序量才够用&#xff1f;这就好比装修房子前要先量尺寸&#xff0c;基因组调查就…...

WPS样式与题注的隐藏用法:这样设置,让你的技术文档像专业手册一样清晰

WPS样式与题注的隐藏用法&#xff1a;这样设置&#xff0c;让你的技术文档像专业手册一样清晰 在技术文档撰写领域&#xff0c;格式混乱往往是内容质量的第一杀手。想象一下这样的场景&#xff1a;当你需要修改某个章节标题时&#xff0c;所有交叉引用的图表编号都需要手动更新…...

白噪声的含义

白噪声指的是一种功率谱密度在整个频率范围内均匀分布的随机信号。简单来说&#xff0c;它包含了人耳可听范围内&#xff08;20-20000Hz&#xff09;所有频率的声音&#xff0c;且每个频率的能量都相同。 为什么叫“白”噪声&#xff1f; 这个命名借用了“白光”的概念。白光是…...

手把手教你用RK3588的NPU跑通第一个YOLOv5模型(附环境配置避坑点)

从零部署YOLOv5到RK3588 NPU&#xff1a;完整环境配置与模型转换实战 拿到RK3588开发板的第一时间&#xff0c;许多开发者最迫不及待想验证的就是其NPU的AI推理性能。作为瑞芯微第四代RKNPU架构的旗舰芯片&#xff0c;RK3588的6TOPS算力在边缘计算领域确实令人期待。但在实际部…...

2025届必备的五大AI科研方案推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 使AIGC&#xff08;人工智能生成内容&#xff09;检测率降低的关键之处在于弱化文本所具有的…...

【实测】GitNexus实测:拖入GitHub链接秒出代码知识图谱,今天涨了857星

腾讯10年程序员带你实测GitNexus——一款零服务器、纯浏览器端的代码知识图谱引擎&#xff0c;内置Graph RAG智能问答。今天GitHub Trending单日涨857星。 文章目录前言一、背景与痛点1.1 问题描述1.2 现有方案的不足二、GitNexus核心能力详解2.1 零服务器架构2.2 交互式知识图…...