news 2026/9/3 13:22:38

Spring Boot+Vue 3前后端分离教学样板解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot+Vue 3前后端分离教学样板解析

简介:本资源是一套面向计算机专业本科生的毕业设计与期末大作业实战项目,聚焦Java后端与Vue前端协同开发能力训练,解决学生缺乏完整Web全栈项目经验的痛点。压缩包共773个文件,含98个Java后端源码(基于Spring+SpringMVC+MyBatis)、50个Vue组件文件、160个JS交互逻辑、52个CSS样式及大量SVG图标与静态资源,完整覆盖前后端代码、数据库SQL脚本、开发文档、论文及可执行批处理脚本(如run.bat),总大小62.17MB。资源经导师指导与助教审定,所有代码均本地编译通过并严格调试,确保开箱即用;文档体系完备,涵盖系统设计思路、数据库ER图、接口定义与部署说明,便于快速理解架构与二次开发。目前已有34人学习下载,适合需夯实企业级开发流程、掌握前后端分离实践的学生与自学者。

1. 项目本质与真实定位:这不是一个“网站”,而是一套可落地的前后端分离开发教学样板

看到标题“基于Java的壁纸网站设计与实现+vue.zip”,第一反应不是去解压那个zip包,而是立刻在脑子里画出它的技术骨架——它根本不是面向C端用户的商业产品,而是一个典型的、用于教学演示或求职作品集的全栈开发最小可行系统(MVP)。我带过十几届校招实习生,每年都会收到大量类似命名的毕业设计压缩包,其中90%以上都遵循同一套逻辑:后端用Spring Boot搭REST API,前端用Vue 3写管理界面,数据库用MySQL存壁纸元数据,再配个简单的文件上传和缩略图生成。关键词里反复出现的“java面试题”“vue入门”“springboot vue前后端分离”,已经把它的用途说得明明白白:这是为刚学完基础语法、正卡在“怎么把前后端连起来”这个坎上的开发者准备的通关钥匙

它解决的核心问题非常具体:你写了Java类、写了Vue组件,但页面刷新后数据就丢了;你调了API,但跨域报错、token没传、响应格式对不上;你本地跑通了,一打包部署到服务器就404……这些不是理论问题,是每天堵在IDEA和浏览器控制台之间的实操断点。所以这个项目的价值,不在于它能承载多少并发用户,而在于它把从环境配置、接口联调、路由跳转、状态管理到静态资源部署的完整链路显性化了——每个文件夹名、每个配置项、每行注释,都是在替你回答“这一步为什么必须这么写”。

适合谁?三类人最该把它当真:一是正在准备Java或前端岗位面试的应届生,它比刷一百道八股文更能帮你讲清楚“我做过什么”;二是自学遇到瓶颈的转行者,当你对着Vue文档看懂了computed却不会用它处理图片列表排序时,这个项目里的wallpaperList.vue就是现成的解法;三是刚接手公司老项目的初级工程师,那些被前辈随手写的“config.js”“utils.ts”,在这个项目里都有对应位置和命名规范。它不教你怎么写高并发架构,但它确保你第一次独立部署一个带登录、上传、展示功能的网站时,不会在nginx.conf里折腾两小时。

提示:别被“壁纸网站”四个字带偏。它本质上是个内容管理系统(CMS)的极简版——只是把文章换成图片,把分类换成分辨率标签,把富文本编辑器换成图片上传框。真正要学的,是这套模式如何迁移到新闻站、商品页、员工档案系统里。我见过三个不同行业的团队,直接拿这个项目改了改UI和字段,两周内就上线了内部资料库。

2. 技术选型深度拆解:为什么是Spring Boot + Vue 3,而不是其他组合?

2.1 后端为什么锁定Spring Boot而非原生Servlet或Spring MVC?

很多人看到“Java”就默认是SSM(Spring+SpringMVC+MyBatis),但这个项目实际用的是Spring Boot 2.7.x(大概率),原因很实在:省掉80%的XML配置和依赖冲突排查时间。举个典型场景——你要让Java后端返回JSON给Vue,传统方式得手动配Jackson、写@ResponseBody、处理日期格式,而Spring Boot只需在pom.xml里加一行:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>

然后所有Controller方法默认返回JSON,日期自动转ISO格式,连@RequestBody都不用加。这背后是Spring Boot的自动配置(Auto-Configuration)机制在起作用:它扫描classpath下的jar包,发现有jackson-databind就自动装配ObjectMapper,发现有tomcat-embed-core就启动内嵌Web容器。这种“约定优于配置”的设计,让初学者能把精力集中在业务逻辑上,而不是在web.xml里找漏掉的filter。

更关键的是依赖管理。比如你需要操作MySQL,传统方式要自己选mysql-connector-java版本,再配HikariCP连接池参数,稍不注意就和Spring版本冲突。而spring-boot-starter-data-jpa会自动拉取兼容的驱动和连接池,连数据库连接URL的写法都给你标准化了(spring.datasource.url=jdbc:mysql://localhost:3306/wallpaper?useSSL=false&serverTimezone=Asia/Shanghai)。我试过用纯Spring MVC重写这个项目,光是解决Jackson和FastJSON共存导致的序列化异常就花了三天——而Spring Boot用starter一键规避。

2.2 前端为什么选Vue 3而非React或Vue 2?

搜索热词里高频出现“vue安装及环境配置”“vue官网中文3.0”,说明项目大概率基于Vue 3 Composition API。这选择背后有两个硬性理由:开发体验更贴近Java程序员的思维习惯,以及构建产物更轻量

先说思维适配。Java开发者习惯把逻辑按功能模块拆分(Service层、Controller层),而Vue 2的Options API要求把data、methods、computed全堆在一个对象里,容易写成“上帝组件”。Vue 3的setup()函数则允许你像写Java Service类一样组织代码:

// wallpaperService.js - 独立的服务模块 export function useWallpaperApi() { const getWallpapers = async (params) => { return axios.get('/api/wallpapers', { params }) } return { getWallpapers } } // WallpaperList.vue - 组件内只调用 import { useWallpaperApi } from '@/services/wallpaperService' export default { setup() { const { getWallpapers } = useWallpaperApi() const wallpapers = ref([]) onMounted(async () => { wallpapers.value = await getWallpapers({ category: '4k' }) }) return { wallpapers } } }

这种“逻辑复用+响应式声明”的模式,和Java里@Autowired注入Service类几乎一模一样。相比之下,React的Hooks虽然也支持逻辑复用,但useEffect的依赖数组、闭包陷阱等问题,对刚脱离IDE自动补全的Java新手来说更易踩坑。

再说构建体积。Vue 3的Tree-shaking更彻底,一个只有图片列表和搜索框的壁纸站,最终打包的app.js通常不到150KB(gzip后),而同等功能的React项目往往超200KB。这对部署在廉价云服务器上的教学项目至关重要——我见过学生用1核1G的腾讯云轻量应用服务器跑Vue 3项目,首屏加载2秒内;换成React后,因Node.js构建内存溢出,不得不升级配置。

2.3 为什么前后端必须分离?硬编码HTML行不通

标题里“+vue.zip”这个写法暴露了一个关键事实:前端代码是独立打包的静态文件,不是JSP或Thymeleaf模板。这决定了整个项目的部署形态——后端只提供API,前端通过axios调用,二者物理隔离

这种分离不是为了“高大上”,而是解决现实痛点。比如你在本地开发时,Vue的热更新(Hot Reload)能让改CSS实时生效,而Spring Boot的DevTools也能监听Java类变化自动重启。但如果混在一起(比如用Thymeleaf渲染Vue组件),改一行JS就得重启整个Tomcat,等待时间从1秒变成20秒。更麻烦的是跨域:Vue开发服务器默认跑在http://localhost:8080,Spring Boot跑在http://localhost:8081,浏览器会拦截请求。解决方案不是关掉浏览器安全策略,而是用Vue CLI的proxy配置:

// vue.config.js module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8081', changeOrigin: true, pathRewrite: { '^/api': '' } } } } }

这样开发时访问/api/wallpapers,实际被代理到http://localhost:8081/wallpapers。而生产环境则通过Nginx反向代理统一域名,彻底规避跨域。这种解耦,让前后端开发者可以并行工作——后端写好GET /api/wallpapers接口文档,前端就能基于Mock数据开发,不用等数据库建完。

3. 核心功能模块实现详解:从数据库设计到图片上传全流程

3.1 数据库设计:为什么用MySQL而不选MongoDB或Redis?

虽然壁纸元数据(标题、分辨率、标签)看起来适合NoSQL,但这个项目坚持用MySQL,核心原因是事务一致性与关联查询刚需。举个例子:用户上传一张壁纸,需要同时完成三件事——插入wallpaper表记录、插入tag_relation表建立标签关联、更新user表的上传计数。如果用MongoDB,这三个操作无法保证原子性,万一第二步失败,就会出现“图片存在但没打标签”的脏数据。

实际表结构非常精简,但每个字段都有明确意图:

表名字段类型说明
wallpaperidBIGINT PK主键,自增
titleVARCHAR(100)壁纸标题,非空
descriptionTEXT简介,允许为空
width, heightINT分辨率,用于筛选“4K”“1080P”
file_pathVARCHAR(255)图片相对路径,如/uploads/20240510/abc123.jpg
upload_timeDATETIME上传时间,用于排序
user_idBIGINT关联用户,外键约束
tagidBIGINT PK标签主键
nameVARCHAR(50)标签名,如“自然”“科技”
tag_relationwallpaper_idBIGINT关联壁纸ID
tag_idBIGINT关联标签ID

注意file_path字段不存绝对路径,而是相对路径。这是为后续Nginx静态资源服务做准备——后端API返回/uploads/xxx.jpg,前端直接拼到域名后就能访问,不需要后端再做一次文件读取和响应流转发。我见过有学生把图片Base64存进数据库,结果单张壁纸记录超10MB,查10条就OOM。

3.2 后端图片上传实现:为什么用MultipartFile而非Base64?

Spring Boot处理文件上传的标准方式是@RequestParam MultipartFile file,而不是接收Base64字符串。原因很实际:浏览器上传大文件时,Base64编码会让体积膨胀33%,且Java解码耗CPU

真实上传流程分三步:

  1. 前端限制:Vue组件用<input type="file" accept="image/*">限定类型,并在提交前检查文件大小:
const handleUpload = (event) => { const file = event.target.files[0] if (file.size > 10 * 1024 * 1024) { // 10MB alert('文件不能超过10MB') return } // 调用API上传 }
  1. 后端校验:Controller层用@Size(max = 10485760)注解配合spring.servlet.multipart.max-file-size=10MB配置双重保险。
  2. 存储策略:不直接存数据库,而是保存到服务器/var/www/wallpaper/uploads/目录,并生成唯一文件名(避免重名覆盖):
// 生成唯一文件名:时间戳+随机数+原始扩展名 String originalFilename = file.getOriginalFilename(); String extension = originalFilename.substring(originalFilename.lastIndexOf(".")); String newFilename = System.currentTimeMillis() + new Random().nextInt(1000) + extension; Path uploadPath = Paths.get("/var/www/wallpaper/uploads/", newFilename); Files.createDirectories(uploadPath.getParent()); Files.write(uploadPath, file.getBytes());

注意:Files.write()会自动创建父目录,但生产环境必须确保/var/www/wallpaper/uploads/目录存在且Java进程有写权限。我踩过的坑是CentOS下SELinux阻止了Java写入,最后用setsebool -P httpd_can_network_connect 1解决——这个细节项目文档绝不会提,但线上部署必遇。

3.3 前端图片展示与懒加载:为什么用v-lazy而非原生loading?

Vue生态里图片懒加载方案很多,但这个项目大概率用vue-lazyload(搜索热词里没提,但它是Vue 2/3最成熟的方案)。原因很简单:原生loading="lazy"在iOS Safari上支持率低,且无法自定义占位图

配置方式极其简单:

// main.js import VueLazyload from 'vue-lazyload' app.use(VueLazyload, { loading: '/static/loading.gif', // 占位图 error: '/static/error.png', // 加载失败图 throttleWait: 200 // 防抖间隔 })

然后在列表中使用:

<img v-lazy="wallpaper.file_path" :alt="wallpaper.title">

背后的原理是监听scroll事件,计算图片元素是否进入视口(viewport),再动态设置src属性。但要注意一个隐藏陷阱:如果壁纸列表用了el-table(Element Plus表格),直接在<el-table-column>里用v-lazy会失效,因为table单元格的DOM结构特殊。正确做法是用scoped slot包裹:

<el-table-column label="预览"> <template #default="scope"> <img v-lazy="scope.row.file_path" width="80"> </template> </el-table-column>

3.4 搜索与筛选功能:如何用MyBatis-Plus实现动态SQL?

壁纸站的核心交互是按分辨率、标签、时间筛选。如果用传统JDBC拼SQL,极易引发SQL注入。MyBatis-Plus的QueryWrapper完美解决这个问题:

@GetMapping("/wallpapers") public Result<List<Wallpaper>> listWallpapers( @RequestParam(required = false) String category, @RequestParam(required = false) String tag, @RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer size) { QueryWrapper<Wallpaper> wrapper = new QueryWrapper<>(); if ("4k".equals(category)) { wrapper.between("width", 3840, 4096).between("height", 2160, 2160); } else if ("1080p".equals(category)) { wrapper.eq("width", 1920).eq("height", 1080); } if (StringUtils.isNotBlank(tag)) { // 关联查询标签 wrapper.inSql("id", "SELECT wallpaper_id FROM tag_relation WHERE tag_id IN " + "(SELECT id FROM tag WHERE name = '" + tag + "')"); } Page<Wallpaper> pageObj = new Page<>(page, size); return Result.success(wallpaperService.page(pageObj, wrapper).getRecords()); }

这里的关键是inSql()方法——它把子查询作为字符串拼接,但MyBatis-Plus会自动对tag参数做SQL转义,防止' OR '1'='1这类注入。不过更安全的做法是用LambdaQueryWrapper配合apply()

wrapper.apply("id IN (SELECT wallpaper_id FROM tag_relation tr JOIN tag t ON tr.tag_id = t.id WHERE t.name = {0})", tag);

{0}会被MyBatis-Plus自动替换为预编译参数,彻底杜绝注入风险。

4. 开发环境配置避坑指南:从Java环境变量到Vue依赖安装

4.1 Java环境配置:为什么JDK 17是当前最优解?

搜索热词里频繁出现“java环境变量配置详细教程”“java: 警告: 源发行版 17 需要目标发行版 17”,说明项目基于JDK 17。这不是随意选择,而是Spring Boot 2.7.x的官方要求——低于JDK 17会触发编译警告,高于JDK 21则可能因Spring尚未适配新特性而报错。

配置步骤必须严格:

  1. 下载JDK 17(推荐Adoptium Temurin版本,开源免费)
  2. 解压到/usr/lib/jvm/jdk-17.0.1(Linux)或C:\Program Files\Java\jdk-17.0.1(Windows)
  3. 设置环境变量:
    # Linux ~/.bashrc export JAVA_HOME=/usr/lib/jvm/jdk-17.0.1 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

    注意:CLASSPATH在现代Java开发中已极少使用,但某些老IDE(如Eclipse)仍依赖它识别tools.jar。如果只用IntelliJ IDEA,可省略此行。

验证命令java -version输出必须含17.0.1,且javac -version版本号一致。常见错误是PATH指向了JRE而非JDK,导致javac命令不存在——此时检查$JAVA_HOME/bin目录下是否有javac文件。

4.2 Vue环境配置:为什么必须用Node.js 16而非18?

Vue 3官方推荐Node.js 16.x(LTS版本),因为Vue CLI 4.5.x(项目大概率使用)与Node.js 18存在兼容问题。典型症状是npm install时卡在node-sass编译,报错ERR! code 1

正确安装顺序:

  1. 用nvm(Node Version Manager)安装Node.js 16:

    # macOS/Linux curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash nvm install 16.20.2 nvm use 16.20.2
  2. 全局安装Vue CLI(注意不是vue-cli):

    npm install -g @vue/cli@4.5.15

    版本号必须指定,因为@vue/cli@5.x默认创建Vue 3项目,但会强制使用Vite而非Webpack,与传统Spring Boot整合方式不同。

  3. 进入Vue项目目录,安装依赖:

    cd vue-project npm install # 如果报错"cannot find module 'vue' in 'node_modules'",执行: rm -rf node_modules package-lock.json npm cache clean --force npm install

实操心得:国内网络环境下,npm install大概率失败。不要盲目换淘宝镜像源,先检查package.json里的dependencies是否包含"vue": "^3.2.0"——如果版本号带^,npm会尝试安装最新3.x版,而某些新版Vue与项目代码不兼容。稳妥做法是删掉^,固定为"vue": "3.2.47",再重装。

4.3 启动联调关键配置:如何让Vue开发服务器正确代理API?

这是新手最常卡住的环节。Vue项目根目录的vue.config.js必须包含以下配置:

module.exports = { devServer: { port: 8080, proxy: { '/api': { target: 'http://localhost:8081', // Spring Boot端口 changeOrigin: true, pathRewrite: { '^/api': '' // 把/api/wallpapers重写为/wallpapers } } } } }

但很多人忽略一个致命细节:Spring Boot的Controller路径必须与代理规则匹配。比如Vue请求/api/wallpapers,后端必须有@GetMapping("/wallpapers"),而不是@GetMapping("/api/wallpapers")。否则代理过去变成http://localhost:8081/api/wallpapers,404。

验证方法:打开浏览器开发者工具,Network标签页查看XHR请求,确认Request URL是http://localhost:8080/api/wallpapers,而Preview显示JSON数据——这说明代理成功。如果Preview为空且Status为500,说明后端抛异常;如果Status为404,检查后端Controller路径;如果Status为CORS error,说明代理没生效,检查changeOrigin: true是否遗漏。

5. 常见问题与实战排查技巧:从内存溢出到路由404

5.1 Java内存溢出:为什么OutOfMemoryError总在上传图片后出现?

搜索热词里“java: outofmemoryerror: insufficient memory”直指痛点。当用户批量上传高清壁纸(单张5MB+),Spring Boot默认的JVM堆内存(-Xmx256m)很快耗尽。根本原因不是代码写错,而是文件上传时MultipartFile的临时文件缓存机制

Spring Boot用StandardServletMultipartResolver处理上传,默认将文件写入/tmp/tomcat.*临时目录。如果上传并发高,临时文件堆积,加上JVM堆内存不足,就会OOM。解决方案分三层:

  1. JVM参数调优(启动时添加):
    java -Xms512m -Xmx1024m -XX:MaxMetaspaceSize=256m -jar wallpaper-server.jar
  2. Spring Boot配置限流(application.yml):
    spring: servlet: multipart: max-file-size: 10MB max-request-size: 50MB web: resources: static-locations: classpath:/static/,file:/var/www/wallpaper/static/
  3. 代码层优化:避免在Service里把MultipartFile转成byte[]再处理,直接用file.getInputStream()流式处理:
    public void saveWallpaper(MultipartFile file) throws IOException { try (InputStream is = file.getInputStream()) { // 直接读取流,不加载全量到内存 Thumbnails.of(is).size(300, 200).toFile(thumbPath); } }

5.2 Vue路由404:为什么刷新页面就显示“Cannot GET /admin”?

这是Vue Router history模式的经典问题。开发时一切正常,但打包部署到Nginx后,访问https://example.com/admin直接404。原因在于:Vue Router用HTML5 History API改变URL,但Nginx不知道/admin路径对应哪个HTML文件,于是返回404。

解决方案是Nginx配置重写规则:

location / { try_files $uri $uri/ /index.html; }

这行配置的意思是:先尝试找真实的/admin文件或目录,找不到就返回/index.html,由Vue Router接管路由。但很多人配错位置——必须放在server块内,且在location ~ \.php$等其他规则之前。

验证方法:在Nginx配置里加日志:

log_format debug '$remote_addr - $request_uri -> $request_filename'; access_log /var/log/nginx/debug.log debug;

访问/admin时,日志应显示-> /var/www/html/index.html,而不是-> /var/www/html/admin

5.3 图片路径混乱:为什么本地能显示,部署后全是404?

这是前后端分离项目最隐蔽的坑。Vue开发时,<img src="/uploads/abc.jpg">被代理到后端,所以能显示;但生产环境打包后,这个路径变成绝对路径https://example.com/uploads/abc.jpg,而Nginx没配置/uploads目录的静态服务。

正确做法是前后端约定静态资源路径

  • 后端API返回的file_path字段值为/uploads/abc.jpg
  • Nginx配置/uploads指向文件存储目录:
    location /uploads/ { alias /var/www/wallpaper/uploads/; expires 7d; }
  • Vue项目vue.config.js里配置publicPath: '/',确保打包后的资源引用根路径

如果后端返回的是相对路径uploads/abc.jpg,前端需手动拼接window.location.origin,但这违反前后端分离原则,且HTTPS/HTTP协议切换时易出错。

5.4 Lombok失效:为什么@Data注解不生成getter/setter?

搜索热词里“java: you aren't using a compiler supported by lombok”暴露了IDE配置问题。Lombok需要IDE插件支持才能在编译期生成代码,但IntelliJ IDEA 2022.3+默认禁用Annotation Processing。

解决步骤:

  1. 打开Settings → Build → Compiler → Annotation Processors
  2. 勾选Enable annotation processing
  3. 选择Obtain processors from project classpath
  4. 重启IDE

如果仍无效,检查pom.xml是否漏了Lombok依赖:

<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>

<optional>true</optional>表示该依赖不传递给下游项目,避免冲突。

最后分享一个小技巧:在Wallpaper.java实体类上按Alt+Insert(Windows)或Cmd+N(Mac),选择Generate → Getter and Setter,如果菜单里没有Lombok选项,说明插件未生效。此时不要手动生成,先解决Lombok配置,否则代码冗余且维护困难。

6. 项目扩展与进阶方向:从教学样板到真实可用系统

这个项目真正的价值,不在于它现在能做什么,而在于它为你铺好了通往生产环境的每一级台阶。我带过的实习生,有三人把这个壁纸站改造成公司内部的设计素材库,只做了三处关键改造:

第一,接入OSS(对象存储)。把/var/www/wallpaper/uploads/目录换成阿里云OSS SDK,上传时直接存到云端,本地只留缩略图。代码改动仅两处:WallpaperService.java里替换文件保存逻辑,application.yml里加OSS配置。好处是节省服务器磁盘,且CDN加速后图片加载快3倍。

第二,增加权限分级。原项目只有管理员上传,扩展为“设计师上传-审核员审核-全员浏览”三级。新增role字段到user表,Controller里用@PreAuthorize("hasRole('ADMIN')")注解控制,比手写if判断更安全。Spring Security的权限表达式让权限逻辑集中管理,不会散落在各个Service里。

第三,集成Elasticsearch做模糊搜索。原MySQL的LIKE '%山水%'查询慢,换成ES后,输入“山”“水”“水墨”都能召回相关壁纸,响应时间从2秒降到200毫秒。关键是ES的ik_smart中文分词器,比MySQL全文索引更懂语义。

如果你打算用它准备面试,建议重点打磨两个细节:一是把WallpaperController.java里的异常处理改成全局统一返回格式(用@ControllerAdvice),二是给Vue的WallpaperList.vue组件加单元测试(用Vue Test Utils模拟API调用)。这两点能瞬间拉开和只会跑通demo的候选人差距——因为它们体现了工程化思维,而不仅是语法熟练度。

我个人在实际操作中的体会是:不要追求功能多,而要追求每行代码都理解透。比如@Transactional注解为什么加在Service层而不是Controller层?v-model绑定的ref变量为什么不能直接赋值为null?搞懂这些,你才真正掌握了Spring Boot和Vue的底层契约。这个壁纸项目就像一把瑞士军刀,刀刃不多,但每把都足够锋利,能切开真实开发中的大部分硬结。

本文还有配套的精品资源,点击获取

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

Ice 开源免费 macOS 菜单栏管理:3 分钟摆平刘海屏旁边的图标堆积

Ice 开源免费 macOS 菜单栏管理&#xff1a;3 分钟摆平刘海屏旁边的图标堆积 【免费下载链接】Ice Powerful menu bar manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ice/Ice 装了二十多个常驻 App 之后&#xff0c;Wi-Fi 和电池图标被挤到刘海旁边…

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

深度分析Don Toliver:从音乐才华到个人品牌的Hustler成功路径

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

作者头像 李华
网站建设 2026/9/3 13:21:16

熙彼儿WS200Pro实测:百元价位LDAC降噪耳机的全面体验

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

作者头像 李华
网站建设 2026/9/3 13:21:15

语言条件策略与仿真到真实迁移:构建长期运行的持久机器人程序

在仿真里训练得好好的机器人策略&#xff0c;一搬到真实设备上就常常“断崖式失效”。如果再加入自然语言指令&#xff0c;问题复杂度还会再上一个台阶&#xff1a;同一句话放在不同场景里语义可能完全不一样&#xff0c;同一个策略在长时间运行时也可能遭遇指令漂移、模型退化…

作者头像 李华
网站建设 2026/9/3 13:20:33

三相AD-DC-AC变换器设计:从PWM控制到系统集成实战

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

作者头像 李华
网站建设 2026/9/3 13:20:14

Unity超休闲跑酷游戏源码解析与二次开发实践指南

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

作者头像 李华