news 2026/9/29 21:24:20

智慧通讯业务3D可视化平台:SpringBoot+Three.js实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
智慧通讯业务3D可视化平台:SpringBoot+Three.js实战

这个项目是我带学生做毕业设计时一眼相中的题目:基于Java+SpringBoot的智慧通讯业务办理3D可视化平台。先别被“智慧通讯”四个字唬住,拆开来看就是两件事:一是用SpringBoot做一套能跑通的通讯业务办理后台,二是用Three.js这类3D渲染技术把业务数据、网点设备状态变成可视化大屏。市面上很多课程设计还停留在“表格增删改查”,而3D可视化能明显拉开档次,不管是答辩演示还是写进简历,都更有说服力。

如果你正在找Java课程设计选题,或者毕业设计想做一个“既有业务功能又有视觉效果”的项目,这篇内容可以给你一个完整的落地思路。我会从技术选型、数据库设计、后端接口、3D场景实现、部署排坑几个维度逐个拆,所有代码都是真实项目中写过的,直接踩过的坑也会一并标出来。

开门见山地说:这套平台的定位是“一个能展示的完整闭环系统”,不是单纯的大屏demo,也不只是一个CRUD报表。业务端要支持客户信息管理、业务办理状态流转、订单追踪;展示端要能用一个3D营业厅场景实时反映设备在线状态、业务办理量、工单分布。两者通过SpringBoot接口串起来,数据库用MySQL,前端可视化为单独静态页面,最终也可以打包进SpringBoot统一部署。

1. 项目定位与技术选型:为什么是 SpringBoot + Three.js

1.1 课程设计/毕业设计需求拆解

很多同学拿到“智慧通讯业务办理3D可视化平台”这个题第一反应是:又要做管理系统又要做3D,是不是太大了?其实题目本身已经暗示了层次:“智慧通讯业务办理”是业务底座,“3D可视化”是表达形式。所以设计的时候不能把两者割裂,更不能偏科——只做后台管理没有可视化,题目后半句不达标;只画一个3D场景不给操作入口,前半句又不达标。

我通常建议把项目拆成三个模块来规划:

  • 用户与权限模块:登录认证、角色区分(管理员/业务员/普通用户),这是SpringBoot项目的基本盘。
  • 业务办理模块:客户档案维护、通讯业务类型定义(开户、过户、改套餐、缴费、停机等)、办理单提交、状态流转。
  • 可视化展示模块:通过3D场景展示网点分布、设备状态、今日办理量、工单进度等,数据来源于后端接口。

这样拆完以后,工作量分配就很清晰:前两个模块是“能跑通的业务系统”,第三个模块是“能出彩的亮点”。毕业设计答辩时,老师最常问的也是“你这个可视化数据从哪来”,如果你能答出“后端统计接口返回的JSON前端渲染”,再配合数据库表结构说明,基本就能稳过。

1.2 后端技术选型:SpringBoot + MyBatis-Plus + MySQL 的理由

后端我选的是SpringBoot 2.7.x + MyBatis-Plus + MySQL 8.0,没有用微服务那套。原因很简单:课程设计阶段,单体应用完全够用,代码少、部署简单、排错容易。SpringBoot的核心价值在于自动配置和生态成熟,写一个Controller再加一个Service,不需要繁琐的XML配置就能跑起来,对不熟悉底层原理的同学非常友好。

MyBatis-Plus和Spring Data JPA之间我推荐前者。JPA虽然封装程度高,但写复杂统计查询时反而要绕弯子;MyBatis-Plus的BaseMapper自带增删改查,需要自定义SQL时又保留了SQL的可控性,同时它还有分页插件、代码生成器,能大幅缩短开发时间。课程设计时间紧张,代码生成器直接把实体类、Mapper、Service、Controller都生成好,你只需要改业务逻辑,效率能翻一倍。

MySQL 8.0目前是主流选择,支持窗口函数,写排名、环比统计这类SQL比较方便。这里顺便建议:连接池用Druid或者HikariCP都行,SpringBoot默认HikariCP其实很稳定,没必要额外引入。我实际用下来,Druid的监控页面在答辩时也是一个可展示的小亮点,所以选了Druid,加了druid-spring-boot-starter依赖。

1.3 3D可视化选型:Three.js 与 ECharts GL 的取舍

3D可视化是个容易踩坑的环节。市面上可视化方案很多,最常见的是ECharts和ECharts GL,它擅长画3D柱状图、3D地图、3D散点这类“数据图表”。但如果要展示一个营业厅内部空间,里面有柜台、机柜设备、用户轨迹,ECharts就显得力不从心了。

我最终选择的是Three.js。Three.js是基于WebGL的3D渲染引擎,可以创建一个完整的3D场景:地面、墙壁、设备模型、标签、光效、动画。它学习门槛比ECharts高,但只做“简模+状态映射+点击交互”其实并不难。用立方体模拟机柜,用球体模拟设备节点,用CSS2DRenderer显示标签,这些在Three.js官网都有现成例子可参考。而且Three.js做出来的效果“很3D”,答辩时视觉冲击力明显更强。

如果你时间实在不够,也可以考虑折中:用ECharts GL做3D地图/柱状图,配合普通ECharts做趋势曲线,这样也能满足“3D可视化”的字眼要求。但既然题目写的是“3D可视化平台”,我个人建议上Three.js,至少做一个小场景,价值感瞬间不一样。

2. 数据库设计与业务模型

2.1 核心表结构设计

数据库是整个平台的基座,设计的好坏直接影响开发进度。我不建议一上来就建表,先画一张简单的ER图,明确实体关系:用户属于角色,角色有权限;客户有多个业务办理单;业务办理单引用业务类型;网点包含设备;设备与状态记录关联。基于这些关系,我的核心表设计如下:

表名用途关键字段
sys_user用户表id, username, password, real_name, role_id, branch_id, status
sys_role角色表id, role_name, role_code, description
customer客户表id, customer_no, name, phone, id_card, address, created_time
biz_type业务类型表id, type_name, type_code, fee, need_audit, status
biz_order业务办理单表id, order_no, customer_id, biz_type_id, user_id, branch_id, status, handle_time, remark
order_status_log订单状态日志表id, order_id, from_status, to_status, change_time, operator_id
branch网点表id, branch_name, address, longitude, latitude, manager_id
device设备表id, device_no, device_name, device_type, branch_id, status, last_online_time
device_status_log设备状态日志表id, device_id, status, report_time

每个表都建议加上create_time和update_time字段,后面做可视化统计时非常有用。比如要统计“今日各网点办理量”,只需要按biz_order.create_time和branch_id分组汇总。设备状态表用status字段区分在线/离线/故障,3D大屏上不同颜色就是从这里来。

2.2 业务办理流程的状态机设计

业务办理模块最容易被做成“一个表一个状态字段,update一下就完事”。但如果只是这样,答辩时老师追问“一个单子从提交到完成经历了哪些环节”你就很难解释清楚。所以我建议引入状态机+日志表:

  • biz_order.status记录当前状态:0待受理、1办理中、2已完成、3已取消、4异常。
  • order_status_log记录每一次状态变化:从什么状态变成什么状态,谁操作的,什么时候变的。

这样做有两个好处:第一,业务可追溯,任何一张单子的历史流程都能查出来;第二,可视化大屏上可以展示“各状态订单占比”,还能画漏斗图。SpringBoot里使用@Transactional保证状态更新的原子性,先更新biz_order.status,再插入order_status_log,一旦插入失败要回滚,否则状态和日志对不上。

状态流转的规则也要写在Service层里,比如“已取消”和“已完成”不能跳到“办理中”,前端下拉框根据当前状态动态过滤。这样逻辑集中在后端,前端展示和交互就不会乱。

2.3 可视化数据从哪来:统计查询与缓存设计

3D大屏上的数据不是凭空生成的,来源就是数据库里的业务表。但你不能让前端直接查表,必须提供后端接口,返回聚合好的JSON。以“当日业务办理量按网点分布”为例,SQL可以写成:

SELECT b.branch_name, COUNT(o.id) AS total FROM biz_order o LEFT JOIN branch b ON o.branch_id = b.id WHERE o.create_time >= CURDATE() GROUP BY o.branch_id, b.branch_name;

这种统计接口通常会被前端大屏高频调用,如果每次都实时查全表,数据量一上来MySQL会忙不过来。我的做法是:热点接口加Redis缓存,比如/api/visual/overview,这个接口汇总了总用户数、今日办理量、设备在线率、工单趋势,数据变化没那么频繁,缓存30秒完全够用。SpringBoot里用@Cacheable或者手动RedisTemplate都行,课程设计里手工写RedisTemplate反而更容易讲清楚。

另外要注意:3D大屏展示的空间数据和设备状态,不要在主线程里查询。我写了一个@Scheduled定时任务,每10秒去数据库拉一次设备状态,写入Redis Hash结构,接口再从Redis读取。这样既保证数据时效性,也避免频繁查表。

3. 核心功能实战:从后端接口到3D场景

3.1 SpringBoot 项目搭建与配置

项目骨架我推荐用Spring Initializr生成,依赖选择:Spring Web、MySQL Driver、MyBatis-Plus、Redis、Lombok、Validation。如果你用IDEA,可以直接在New Project里选Spring Initializr,填好Group和Artifact就行。

pom.xml关键依赖示例:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>

application.yml里的几个关键配置注意一下:

spring: datasource: url: jdbc:mysql://localhost:3306/smart_tel?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 mybatis-plus: mapper-locations: classpath*:mapper/**/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

注意serverTimezone必须设置,我因为没加这一项,连接数据库时报过The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized,这是最常见的坑之一。MyBatis-Plus的驼峰映射默认开启,所以数据库字段下划线会自动映射到实体类驼峰属性,命名就按create_time这种方式来。

3.2 业务办理后端接口实现

业务办理的接口设计要遵守“一单一状态”的原则。核心接口如下:

  • POST /api/order/create:提交业务办理单
  • POST /api/order/handle:受理/处理业务
  • POST /api/order/complete:完成业务
  • POST /api/order/cancel:取消业务
  • GET /api/order/page:分页查询办理单
  • GET /api/order/status/{orderNo}:查询办理进度

以创建办理单为例,Service层的关键逻辑是生成唯一订单号、保存客户关联、插入初始状态、写入日志。订单号不要用数据库自增ID,太容易被猜,我用的是“日期+业务类型码+随机数”,比如20250612153000TX0001。生成代码:

String orderNo = "D" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + RandomStringUtils.randomNumeric(4);

提交办理单时,前端提交customerId和bizTypeId,后端校验客户是否存在、业务类型是否启用。校验通过后,用事务插入biz_order和order_status_log:

@Transactional(rollbackFor = Exception.class) public BizOrder createOrder(OrderCreateRequest request) { Customer customer = customerMapper.selectById(request.getCustomerId()); if (customer == null) throw new BusinessException("客户不存在"); BizType bizType = bizTypeMapper.selectById(request.getBizTypeId()); if (bizType == null || bizType.getStatus() != 1) throw new BusinessException("业务类型不可用"); BizOrder order = new BizOrder(); order.setOrderNo(orderNo); order.setCustomerId(customer.getId()); order.setBizTypeId(bizType.getId()); order.setStatus(0); order.setCreateTime(LocalDateTime.now()); orderMapper.insert(order); OrderStatusLog log = new OrderStatusLog(); log.setOrderId(order.getId()); log.setFromStatus(-1); log.setToStatus(0); log.setChangeTime(LocalDateTime.now()); log.setOperatorId(getCurrentUserId()); orderStatusLogMapper.insert(log); return order; }

这里有一个容易忽略的点:@Transactional默认只回滚RuntimeException和Error,你自己定义的BusinessException要继承RuntimeException,否则事务不会生效。如果验证失败还想回滚,就要抛出运行时异常。我学生在这里栽过好几次跟头,数据库里经常出现状态变了但日志没插入的情况。

3.3 3D可视化数据接口设计

为了前端的3D场景能直接使用,接口返回结构要统一且规范。我建议所有接口返回统一包装类:

{ "code": 200, "message": "success", "data": {} }

3D大屏主要用这几个接口:

接口路径返回内容用途
/api/visual/overview总客户数、今日办理量、设备在线率、工单分布大屏顶部统计卡
/api/visual/branches所有网点坐标、名称、实时办理量3D场景中的网点标记
/api/visual/devices设备编号、所属网点、状态、温度3D场景中的机柜设备状态
/api/visual/trend近7日业务办理趋势ECharts折线图
/api/visual/bizTypes各业务类型办理量占比ECharts饼图

/api/visual/devices返回数据示例:

{ "code": 200, "message": "success", "data": [ { "deviceNo": "DEV-001", "deviceName": "服务器A-01", "deviceType": "server", "branchId": 1, "branchName": "中心营业厅", "status": "online", "temperature": 45.6, "lastOnlineTime": "2025-06-12 15:30:00" } ] }

前端拿到这批数据后,根据status字段映射设备材质颜色:online绿色、offline灰色、error红色。这个设计没什么高级技术,但非常实用,可视化大屏的“3D感”就是靠这种颜色映射和几何体位置来体现的。

3.4 前端3D场景搭建:Three.js 实战

前端我不建议上太重的框架,直接用HTML + Three.js + ECharts,通过fetch或axios调用后端接口就行。如果你用Vue,也可以把Three.js封装成组件,但课程设计阶段纯静态页面反而简单。

最简单的Three.js场景至少需要这几步:场景(Scene)、相机(Camera)、渲染器(Renderer)、几何体(Mesh)、光源(Light)。以模拟营业厅机柜设备为例:

const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(20, 15, 20); camera.lookAt(0, 0, 0); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.getElementById('container').appendChild(renderer.domElement); // 地面 const planeGeometry = new THREE.PlaneGeometry(20, 20); const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x1a1a2e }); const plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.rotation.x = -Math.PI / 2; scene.add(plane); // 机柜设备 function createCabinet(x, z, status) { const geometry = new THREE.BoxGeometry(1.2, 2, 1); const material = new THREE.MeshStandardMaterial({ color: status === 'online' ? 0x00d26a : status === 'error' ? 0xff4d4f : 0x999999 }); const cabinet = new THREE.Mesh(geometry, material); cabinet.position.set(x, 1, z); scene.add(cabinet); return cabinet; } // 根据接口数据生建设备 fetch('/api/visual/devices') .then(res => res.json()) .then(data => { data.data.forEach((device, index) => { const x = (index % 5) * 2 - 4; const z = Math.floor(index / 5) * 2 - 2; createCabinet(x, z, device.status); }); });

上面这段是精简版,实际代码还要加入OrbitControls实现鼠标旋转缩放、CSS2DRenderer显示设备名称标签、requestAnimationFrame循环渲染。为了演示设备状态会动态变化,我加了一个定时器:

setInterval(() => { fetch('/api/visual/devices') .then(res => res.json()) .then(data => { // 遍历场景中的机柜物体,根据状态更新颜色 }); }, 10000);

这个轮询方式最简单。如果你想更高级一点,后端用WebSocket推送状态变化,前端监听消息实时更新材质颜色。我两个方案都做过:如果设备和网点数量不多,轮询完全够用;如果刷新频率要求高,再上WebSocket。课程设计用轮询+@Scheduled写演示代码,逻辑更清晰,老师看得懂。

3.5 可视化大屏组合:ECharts 和 Three.js 同屏展示

完整的大屏不能只有3D场景,还得有图表数据支撑。推荐布局:中间是Three.js的3D营业厅场景,两侧或上下放ECharts图表。页面用Flex或Grid布局,背景深色,标题文字用亮色。

ECharts和Three.js之间不存在冲突,它们各自占用一个Canvas或DOM容器。只要注意在页面加载时先初始化Three.js场景,再初始化ECharts图表,不会相互干扰。比如右侧放一个“业务类型占比”饼图:

const chart = echarts.init(document.getElementById('chart1')); fetch('/api/visual/bizTypes') .then(res => res.json()) .then(data => { chart.setOption({ tooltip: { trigger: 'item' }, series: [{ type: 'pie', radius: ['40%', '70%'], data: data.data.map(item => ({ name: item.typeName, value: item.total })) }] }); });

大屏的数据刷新策略要避免整屏重刷。我之前写了个粗糙版本,每10秒重新加载所有图表和Three.js数据,结果页面肉眼可见地闪烁。后来改成:ECharts实例只更新series.data,Three.js只更新材质颜色。这样刷新过程平滑得多。操作很简单的,拿到新的数据后单独调用chart.setOption({ series: [{ data: newData }] }),Three.js则根据设备ID找到对应物体更新材质。

4. 部署、联调与文档整理

4.1 本地联调时经常踩的坑

前后端分离开发时,最典型的问题是跨域。SpringBoot后端接口跑在8080/Vite前端跑在5173,如果不配置跨域,浏览器的fetch请求会被拦截。最简单的跨域配置是在Controller类上加@CrossOrigin,但更标准的做法是配置全局CORS:

@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }

另一个坑是数据库连接池报错。如果MySQL服务没有启动,或者密码不对,SpringBoot启动时就会报Failed to configure a DataSource。这个错误很好排查,但很多同学会把数据库连接串里的时区漏掉,报了错还一脸懵。我建议在application.yml里把driver-class-name显式写出来,MySQL 8一定写com.mysql.cj.jdbc.Driver,别用老版的com.mysql.jdbc.Driver。

4.2 项目打包和统一部署

课程设计要交源码,也要能跑起来演示。如果前端是独立的HTML + JS,没有工程化,你可以直接把前端静态文件放在SpringBoot的src/main/resources/static目录下,然后访问http://localhost:8080/index.html就能看到大屏页面。这样Maven打包后一个jar包就包含了前端,部署非常方便。

打包命令:

mvn clean package -DskipTests

打完的jar包在target目录,运行:

java -jar smart-tel-0.0.1.jar

如果Redis没有启动,而你又强制在启动类里初始化客户端,那么应用可能启动失败。建议代码里对Redis连接做容错,或者演示的时候先启动Redis。很多同学没有装Redis,可视化接口返回不了数据,这就很尴尬。我的经验是演示前先把Redis和MySQL都启动好,并给visualService加一个降级逻辑:如果Redis挂了就去查数据库。

4.3 万字文档怎么写:结构、图和答辩准备

项目附带“万字文档”,最终成果物不只是代码,更是一份能支撑答辩的文档。我的文档结构一般这样安排:

  1. 绪论:背景与意义、国内外现状、论文结构。
  2. 需求分析:功能性需求、非功能性需求、用例图。
  3. 系统设计:总体架构图、功能模块图、数据库ER图、时序图。
  4. 系统实现:核心功能页面截图、核心代码逻辑说明、3D可视化实现原理。
  5. 系统测试:测试用例表、测试结果、异常处理分析。
  6. 总结与展望。

写文档的时候有两个容易让老师加分的点:一是数据库ER图要详细到每个表字段,用PowerDesigner或draw.io画;二是3D可视化的实现要写清楚“数据如何从数据库流到前端渲染”的完整链路,最好配一张自己画的时序图。这块能用文字描述清楚,答辩时基本不会被问倒。

答辩高频问题我也列一下:

  • “3D可视化用的是什么技术?为什么选Three.js?”回答:WebGL渲染引擎,支持真实3D场景,比单纯图表更直观。
  • “状态日志表有什么作用?”回答:记录流转历史,便于追溯和统计分析。
  • “如果设备数量很多,3D场景会不会卡?”回答:会卡,需要优化;我们用了合并几何体、降低粒子数量、按需渲染等方式。
  • “大屏数据是实时更新的吗?”回答:后端定时任务轮询数据库,前端定时拉取接口,属于准实时,也可以改造为WebSocket推送。

5. 完整排坑实录与性能优化建议

5.1 高频问题速查表

问题现象原因解决方法
启动报时区错误jdbc连接串未设置serverTimezone加上serverTimezone=Asia/Shanghai
前端请求接口跨域未配置CORS全局配置WebMvcConfigurer
事务不生效自定义异常未继承RuntimeException继承RuntimeException,或指定rollbackFor
3D场景黑屏未加光源或相机位置不在物体前面添加环境光和方向光,调整相机位置
模型颜色不更新修改了材质的一个副本而未更新材质数组确保通过mesh.material.color.set更新原材质
大屏数据刷新闪烁整个页面重新render只更新材质和图表data,不重建dom
数据库中文乱码连接串未设置characterEncoding加characterEncoding=utf8
Redis连接不上导致启动失败未做容错演示前先启动Redis,或代码降级查库

这串问题基本都是我实际开发中踩过的。特别是Three.js里更新材质颜色,看起来很简单,但其实有个细节:如果你在创建Mesh时给material传了一个数组,或者在多Mesh共用材质时,直接赋值new THREE.MeshStandardMaterial()会导致之前所有Mesh不受影响,必须用mesh.material.color.set(newColor)这种原地修改方法。

5.2 性能优化:让3D场景更顺滑

Three.js绘制大量设备时,每增加一个Mesh就意味着多一次Draw Call。课程设计里设备数量不会太多,但为了让演示不卡顿,可以做几个小优化:

  • 合并静态几何体:地面、墙壁这些不变的元素用BufferGeometryUtils.mergeBufferGeometries合成一个几何体,只保留一个Mesh。
  • 限制光源数量:Scene里不要放十几个点光源。一个AmbientLight加一个DirectionalLight就够了。
  • 开启渲染器性能设置:renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)),避免高DPI屏幕下拉满分辨率导致卡顿。
  • 减少粒子特效:如果做了粒子系统,粒子数量控制在5000以下。

后端性能也有优化空间。统计接口不要动不动SELECT *,只查需要的字段;大屏接口加Redis缓存;定时任务错峰执行,不要所有任务都卡到同一秒启动。这些点不只写在技术文档里,答辩时说出来,老师会觉得你有实战经验。

5.3 一些独门经验:机构和设备怎么建模才“好看”

Three.js项目说到底逃不过“美观”二字。很多同学学了一堆API,做出来的东西还是像“方盒子堆砌”。我的经验是:与其追求复杂模型,不如把灯光和配色做好。

大屏背景用深蓝色渐变,搭配浅蓝色轮廓线,设备用高明度色彩逐个区分状态。地面可以用THREE.GridHelper画网格线,科技感瞬间上来。还可以在场景里加一个THREE.AxesHelper,答辩时说是开发辅助工具,方便理解坐标方向。

设备位置不要手动一个个填坐标,定义一个配置数组,跟后端设备列表一一对应。设备坐标可以用相对坐标,比如机柜按“排、列、层”规则生成,这样后面加设备也方便。我用一个简单函数生成坐标:

function calcDevicePosition(row, column, layer) { return { x: column * 2 - 6, y: layer * 2.5 + 1.5, z: row * 2 - 4 }; }

这个思路是从“真实机房有列、排、层”这个场景里来的,效果比乱摆好很多。

总的来说,这套智慧通讯业务办理3D可视化平台,真正做完之后你会收获三层能力:一是SpringBoot搭建CRUD后端的能力,包括事务、接口、缓存;二是Three.js从零搭建3D场景并动态更新数据的经验;三是把一个综合项目从设计到部署再到写成文档的全过程认知。这些能力对课程设计展示、找工作面试帮忙都很大。如果你正在计划做一个类似的Java毕业设计,可以从业务办理这个模块先开始,等跑通了再加3D场景,千万不要一上来就啃Three.js,容易失去信心。

另外给你一个小建议:从第一天就把SQL脚本和初始数据准备好,每次改表结构都要同步更新init.sql。这样做的好处是后期演示时,直接执行这个脚本就能生成一套能看的数据,不用临时造数。很多项目的文档写得很好,但一运行发现数据库是空的,大屏上啥都看不出来,这种翻车现场我见过太多次了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 21:23:50

用OpenClaw跑通七轴臂控制教学:从pyAgxArm SDK到TaoToken统一Key配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 21:23:21

用了这么久 Claude Code,你可能从来没打开过它最重要的文件夹!——.claude 目录里 settings.json 与 commands 的 TaoToken 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 21:22:25

fabricjs7.4修改默认控制点的样式

默认的修改后的&#xff1a;全局代码&#xff1a;canvas new fa.Canvas(cabox, {backgroundColor: "transparent",selection: true // 保持默认选择功能});fabric.InteractiveFabricObject.ownDefaults {...fabric.InteractiveFabricObject.ownDefaults,// cornerS…

作者头像 李华
网站建设 2026/9/29 21:22:10

Hermes 接入阿里 DashScope 配置指南:TaoToken 统一 Key 通道实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 21:22:07

会编网络:Python生态强大,聊聊少有人知的优质第三方库

熟悉Python的人都知道&#xff0c;Python最大优势之一就是庞大开源第三方库生态。海量开发者持续贡献各类工具库&#xff0c;几乎大部分常见需求&#xff0c;都有现成代码方案。提到Python库&#xff0c;大家最熟悉无非pandas、requests&#xff0c;分别用于数据分析和爬虫。除…

作者头像 李华