尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
校园网上店铺系统:SpringBoot+Vue前后端分离完整实战
很多人做校园项目第一反应就是做个管理系统但说实话管理系统练不到什么真东西无非就是增删改查。我这次做的是校园网上店铺系统前后端分离后端 SpringBoot MyBatis MySQL前端 Vue 生态把注册登录、商品发布、购物车、下单交易、订单管理、后台审核这些真实电商场景全部走了一遍。对想拿来做毕业设计、或者简历里需要一个完整项目的人来说这套东西的价值在于它不只是一个 CRUD demo而是一套能跑通的完整业务流。这个系统以校园为场景商品以二手书、闲置电子产品、生活用品为主用户角色划分为买家、卖家和平台管理员。买家可以逛店、搜索商品、加购物车、下单付款模拟支付卖家可以发布商品、处理订单管理员负责审核商品和维护用户。整个流程覆盖了真实电商平台最核心的状态流转订单状态、库存扣减、权限区分每一个环节都有实际业务逻辑要处理而不是简单查个表。适合谁我建议两类人参考。第一类是正在做毕业设计或课程项目、需要一个完整可演示系统的人第二类是初级 Java 开发或转正人员想系统走一遍前后端分离开发流程的人。当然如果只是为了应付作业这套代码也能直接拿去改改用但我更推荐跟着文章把关键模块自己敲一遍收获会大得多。1. 项目概述与需求拆解1.1 这个项目解决的是什么问题校园里其实有天然的闲置交易需求大四离校要处理教材毕业生淘汰键盘显示器换宿舍翻出各种用不上但扔了可惜的东西。校园论坛、微信群是主要渠道但信息太散没有统一的商品展示、搜索和交易流程交易基本靠私聊约时间没有平台做约束和管理。这个系统的定位就是给校园场景做一个轻量级的网上店铺平台。注意它不等同于闲鱼那种 C2C 全开放平台而是有平台审核机制、有固定用户群体、有简化交易流程的校内闭环。卖家发布商品之后商品要先经过管理员审核才能上架这就解决了校园交易里“不知道卖东西的人靠不靠谱”的核心痛点买家下单后订单状态全程可见不用再靠微信聊天记录回忆交易进度。从业务架构上讲主要拆成几个模块用户模块负责注册登录和个人信息维护商品模块负责发布、审核、浏览、搜索和上下架交易模块负责购物车、下单、支付模拟和交易状态流转后台模块负责用户管理、分类管理和数据统计。每个模块内部都有独立的 service 层和数据库表相互之间的依赖通过接口完成这也为后面做前后端分离打好了基础。1.2 核心角色与业务闭环整个系统有三个角色权限由 user 表的 role 字段区分。普通用户买家浏览商品、关键词搜索、分类筛选、加入购物车、提交订单、模拟支付、查看订单列表、管理收货地址。卖家在普通用户的基础上增加商品发布、图片上传、商品编辑、上下架操作、订单发货、查看自己的商品列表和简单销售统计。管理员登录独立后台可以审核卖家发布的商品支持通过或驳回可以禁用违规用户可以管理商品分类查看平台维度的交易数据概览。核心业务闭环是这样的注册登录 - 浏览搜索商品 - 加入购物车 - 提交订单 - 模拟支付 - 卖家发货 - 买家家确认收货 - 订单完成。这个闭环听起来简单但每一步拆开后都有细节。比如购物车勾选和库存校验、下单时的地址选择、订单状态的流转记录、支付回调的幂等性处理这些才是项目真正有含金量的地方。当时我把这个业务闭环写在设计文档里的第一页因为后面所有表设计、接口设计、前端页面都是围绕这个闭环展开的。先想清楚流程再写代码比边写边想省事得多。2. 技术选型为什么是这套组合2.1 前后端分离到底带来什么好处传统做法是后端用 Thymeleaf 渲染页面页面和接口在一个工程里开发调试都会互相影响。前后端分离之后前端工程和后端工程完全独立可以并行开发只要定好接口文档前端用 mock 数据先开发页面后端专注写接口最后联调时统一对接效率会高很多。部署上分离也更灵活。后端打包成 jar 包前端打包成静态文件可以放在同一台服务器的不同目录也可以把静态文件放到 Nginx后端只提供 API哪边出问题就单独处理哪边不用把整个项目重新打包。对校园项目的服务器配置来说这种解耦也意味着前端静态资源能走 Nginx 的高性能静态文件服务后端 Tomcat 只处理动态请求压力可以分摊。但分离也带来一个绕不开的问题跨域。前端 dev 服务器默认在 8080 端口跑后端接口在 9090 端口跑浏览器会拦截跨域请求。处理方式有两种开发环境用 Vite 的 proxy 把/api路径转发到后端生产环境用 Nginx 反向代理或者直接把前端 dist 目录交给后端托管。这两种方式后面部署章节我都会讲到尤其是后者很多新手容易在这里卡壳。2.2 每个技术组件选型的理由后端选择 SpringBoot核心原因是“约定大于配置”。我们要在短时间内搭建一个结构清晰的 Web 项目如果从零手写 SSM 的 XML 配置光是 spring、springmvc、mybatis 三个框架的配置文件就要写一大堆还没有任何业务价值。SpringBoot 帮我自动装配了内嵌 Tomcat、自动配置了数据源我只需要写自己的业务代码。要注意的是 SpringBoot 版本别选太老2.7.x 或 3.x 都比较稳这里我用的 2.7.x兼容性友好网上资料也多。持久层是 MyBatis 而不是 JPA核心原因是 SQL 可控。校园店铺这种业务商品列表的分页搜索、订单统计报表多表关联查询非常频繁SQL 稍微复杂一点JPA 的自动生成 SQL 就不好控制了排错很麻烦。MyBatis 把 SQL 直接写在 Mapper XML 里性能瓶颈在哪一眼能看出来。加上它支持动态 SQL用if标签就能拼出灵活的分页搜索条件不用为每一种查询条件单独写方法。MySQL 是关系型数据库里最主流的选择没有悬念。校园项目的数据量级通常不会到百万级别单机 MySQL 性能完全够用生态工具也成熟Navicat、DataGrip 都可以直接连上来调试 SQL。MySQL 8.0 的窗口函数、通用表达式在统计场景很好用不过这个项目里用到的不多主要用的是索引优化和事务隔离。前端选择 Vue理由更简单组件化开发体验好生态成熟上手门槛低。搭配 Element UI 组件库后台管理页面几乎不用手写样式表格、表单、弹窗、分页都是现成组件。Vue 的响应式机制让购物车、订单这种频繁变更状态的页面写起来非常舒服数据一变视图自动更新。3. 数据库设计从表结构看业务3.1 核心表结构与字段说明数据库设计是项目的基础表结构没定好后面写接口和页面都会很别扭。我这套系统一共设计了 6 张核心表用户表、分类表、商品表、购物车表、订单表、订单明细表外加一张收货地址表。用户表user主要字段id、username、password、nickname、avatar、phone、role、status、create_time。password 存的是 BCrypt 加密后的密文不是明文role 用 0 表示普通用户1 表示卖家2 表示管理员status 用 0 表示正常1 表示禁用。商品表goods的字段要重点关注id、seller_id、category_id、name、description、price、original_price、stock、cover、images、status、view_count、create_time、update_time。这里有两个设计细节容易被忽略。一个是 images 字段我用逗号分隔的字符串存多张图片的路径因为校园项目图片量不大没必要单独建一张图片表另一个是 status 字段我用 0 表示待审核、1 表示在售、2 表示下架、3 表示驳回后续上架操作只能从 0 或 2 状态转成 1避免商品在售状态下被随意修改。订单表orders和订单明细表order_item是典型的一对多关系也最见基本功。订单表存订单编号、用户 id、卖家 id、总金额、收货人姓名、电话、地址、订单状态、下单时间、支付时间、发货时间、完成时间。订单明细表存 goods_id、商品名称、商品价格、购买数量、小计金额。注意明细表里必须冗余存储一份商品名称和价格的快照因为商品信息可能被卖家修改下单时的价格和名称要锁定下来否则后续订单详情会出现价格对不上的情况。3.2 关键索引、状态机与数据一致性索引这块我把三个字段设置了索引goods 表的 category_id 和 seller_id、orders 表的 user_id 和 seller_id、order_item 表的 goods_id。为什么这么设计因为业务查询场景基本就是“按分类逛商品”“查某卖家的商品”“查某用户的订单”这些查询都是高频操作不加索引全表扫描必然慢。但要注意索引不是越多越好每个额外索引都会拖慢写入速度所以只给真正高频的查询字段建索引。订单状态我用整数状态码来管理不要用字符串。0 待付款、1 待发货、2 待收货、3 已完成、4 已取消。状态流转是有约束的待付款只能取消或支付变成待发货待发货只能发货变成待收货待收货只能确认收货变成已完成。这些约束在后端 service 层判断比如取消订单前必须检查 status 是否为 0避免用户支付后还能取消订单。数据一致性最经典的问题是库存超卖。下单时直接 UPDATE goods SET stock stock - #{quantity} WHERE id #{id} AND stock #{quantity}这样利用数据库原子更新和条件判断天然防止了并发下的超卖。处理购物车的下单事务时我会在 service 方法上加 Transactional扣库存、创建订单、创建订单明细三个操作在同一个事务里任何一个失败都能回滚不会出现订单失败但库存被扣掉的情况。4. 后端核心实现SpringBoot 与 MyBatis 实战4.1 分层架构与统一接口规范后端工程我按标准分包controller、service、mapper、entity、dto、vo、config、common。实体类直接对应数据库表DTO 接收前端参数VO 返回前端数据避免把数据库实体直接暴露给前端比如密码字段绝对不能出现在 VO 里。接口规范方面我写了一个统一的返回包装类 Result结构是{ code: 200, message: success, data: ... }。所有接口都返回这个包装类前端 axios 拦截器只需要判断 code 是否为 200其他情况统一弹错误提示。再配合 RestControllerAdvice 全局异常处理器业务异常直接抛自定义 BizException系统会自动转成统一的错误返回不用每个接口都手写 try-catch。代码上是这样的Data public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(success); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } }登录接口发一个 token后续请求在 header 里携带拦截器解析 token 后把用户信息放到 ThreadLocal 里业务代码随时可以取当前登录用户。这个方案比传统的 Session 更适合前后端分离因为后端不依赖 Cookie前端不管用 Web 还是 App只要在请求头里加一个字段就行。4.2 MyBatis 动态 SQL 与分页查询商品列表是项目里最复杂的查询接口我把它单独拿出来讲。它要支持关键词模糊搜索、分类筛选、价格区间筛选、综合/销量/价格排序还要分页。如果用传统的 DAO一个接口配一个 SQL 模板每个条件都要判断是否为空代码会非常冗余但 MyBatis 动态 SQL 能优雅解决这个问题。下面这段是商品查询 Mapper XML 的核心结构select idselectGoodsList resultTypecom.demo.vo.GoodsVO SELECT g.id, g.name, g.price, g.cover, g.stock, g.view_count, c.name AS category_name, u.nickname AS seller_name FROM goods g LEFT JOIN category c ON g.category_id c.id LEFT JOIN user u ON g.seller_id u.id where g.status 1 if testkeyword ! null and keyword ! AND g.name LIKE CONCAT(%, #{keyword}, %) /if if testcategoryId ! null AND g.category_id #{categoryId} /if if testminPrice ! null AND g.price gt; #{minPrice} /if if testmaxPrice ! null AND g.price lt; #{maxPrice} /if /where choose when testsort price_ascORDER BY g.price ASC/when when testsort price_descORDER BY g.price DESC/when when testsort salesORDER BY g.sales_count DESC/when otherwiseORDER BY g.create_time DESC/otherwise /choose LIMIT #{offset}, #{pageSize} /select注意几个细节。where标签会自动处理首个 AND 关键字不需要手动拼 11gt;和lt;是 XML 转义直接写会报错分页我用手写 LIMIT 而不是 PageHelper是因为项目体量不大手写更容易控制也避免多一条 count 查询的开销。4.3 登录鉴权与权限控制登录鉴权我用 JWT 实现流程是用户提交用户名密码 - 后端校验 - 生成 token 返回前端 - 前端存 localStorage - 后续请求在 header 带 token。生成 token 用 jjwt 库两行代码就行。String token Jwts.builder() .setSubject(userId.toString()) .claim(role, user.getRole()) .setExpiration(new Date(System.currentTimeMillis() 86400000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact();权限控制我用拦截器加自定义注解。比如卖家发布商品接口标上RequireRole(1)管理员审核接口标上RequireRole(2)拦截器里解析 token 后取 role 字段对比不匹配直接返回 403。这样业务代码不用每次判断“当前用户是不是卖家”权限逻辑全部收敛到拦截器里维护起来很清爽。有一类代码我会单独提示所有涉及订单、金额的操作必须做“当前用户与数据归属者一致”的校验。比如买家取消订单要校验订单里的 user_id 是不是当前登录用户的 id卖家发货要校验订单里的 seller_id 是不是当前登录用户的 id。跨权限操作是这类项目最常见的安全漏洞如果不检验随便一个买家传一个 orderId 就能操作别人的订单。5. 前端实现Vue 应用与接口对接5.1 前端工程化结构与路由设计前端我用的 Vue 3 Vite Vue Router Pinia Element Plus 这套组合工程结构按功能模块划分而不是按文件类型堆在一起。src/ ├── api/ # 接口请求模块 ├── assets/ # 静态资源 ├── components/ # 通用组件 ├── router/ # 路由配置 ├── stores/ # 全局状态管理 ├── views/ # 页面组件 │ ├── home/ # 首页 │ ├── goods/ # 商品详情 │ ├── cart/ # 购物车 │ ├── order/ # 订单 │ ├── seller/ # 卖家中心 │ └── admin/ # 管理后台 └── utils/ # 工具函数路由配置用了懒加载component: () import(...)这样首屏不会把所有页面一次性全加载首页加载速度提升明显。路由守卫里做了权限控制需要登录的路由加meta: { requiresAuth: true }需要卖家或管理员权限的路由加meta: { role: 1 }在全局前置守卫里判断 token 和用户角色不满足条件的跳转到登录页。5.2 axios 封装与跨域联调axios 封装是前端联调最关键的一环。我在 utils 目录下建了一个 request.js先创建 axios 实例设置 baseURL 为/api然后在请求拦截器里带上 token响应拦截器里统一处理错误码。const service axios.create({ baseURL: /api, timeout: 10000 }); service.interceptors.request.use(config { const token localStorage.getItem(token); if (token) { config.headers[Authorization] Bearer token; } return config; }); service.interceptors.response.use( response { const res response.data; if (res.code ! 200) { ElMessage.error(res.message); return Promise.reject(new Error(res.message)); } return res.data; }, error { if (error.response error.response.status 401) { localStorage.removeItem(token); router.push(/login); } ElMessage.error(请求失败); return Promise.reject(error); } );跨域问题在开发环境通过 Vite 的 proxy 配置解决。vite.config.js 里配置server: { proxy: { /api: { target: http://localhost:9090, changeOrigin: true } } }这个配置的原理是前端请求路径是/api/goods/listVite dev server 收到后转发到http://localhost:9090/api/goods/list浏览器认为请求是同源的跨域问题直接消失。后端接口路径统一以/api开头生产环境 Nginx 就继续沿用这个规则做反向代理前后端环境切换时不需要改前端代码。5.3 核心业务页面的数据流购物车页面是 Vue 响应式数据流的典型场景。数据结构是购物车行数组每行包含商品信息、数量、选中状态计算属性实时算出总价。用户勾选、修改数量、删除商品页面通过事件驱动更新数据不需要手动操作 DOM。订单提交的流程是这样的购物车勾选商品后点击结算进入确认订单页前端把勾选的购物车 id 列表传给后端后端在事务里批量创建订单和明细。这样做的好处是订单按卖家拆单而不是把整个购物车内容合成一个订单。一个校园店铺里可能有多个卖家的商品合并成一个订单会导致卖家发货逻辑混乱拆单后每个卖家只处理自己的商品逻辑清晰很多。商品列表页的筛选和搜索是另一个难点。我用的方案是 searchParams 对象作为响应式状态分类、关键词、价格区间、排序方式都在这个对象里维护每次变化后重新请求接口页面用骨架屏过渡。为了避免每次输入关键词都触发请求防抖函数设置 500 毫秒延迟用户停止输入后才发请求实测下来请求量减少了好几倍。6. 前后端联调与部署上线6.1 本地联调和启动顺序本地跑起来不是直接把前端后端分别启动就行有几个前置条件。首先是数据库初始化我准备了一个 init.sql 脚本包含建库建表和初始数据管理员账号、分类数据都在里面导入即可。然后启动顺序建议是先启动 MySQL - 启动后端 - 启动前端因为前端首次页面加载需要调用后端接口获取分类数据如果后端没起来页面会报错。后端启动用 IDEA 直接运行 main 方法或者命令行mvn spring-boot:run。配置文件 application.yml 里要注意数据库连接串的时区问题MySQL 8 连接时一定要加serverTimezoneAsia/Shanghai否则会报时区错误。前端启动npm run dev看到 Local 地址后打开浏览器访问即可。联调阶段的 debug 技巧打开浏览器 F12 Network 面板看接口请求和响应确认请求路径、方法、参数、返回值是否符合预期。关于后端日志我在 application.yml 里开启了 MyBatis SQL 打印这样每个 SQL 语句和参数都能在控制台看到排错效率会高很多。logging: level: com.example.mapper: debug6.2 生产部署两种方案对比生产部署我给两个方案按项目情况选择。方案一是完全交给 SpringBoot 托管。前端执行npm run build生成 dist 目录然后把 dist 下的文件复制到 SpringBoot 的 src/main/resources/static 目录重新打包 jar。启动 jar 后静态资源和接口都在同一个端口不需要额外配置 Nginx。这个方案最简单但有个缺点前端每次改动都要重新打包整个后端版本管理上不够灵活。方案二是 Nginx 托管静态文件加反向代理。dist 目录放在 Nginx 的 html 目录Nginx 配置/指向 dist 的 index.html/api/路径反向代理到后端应用的 9090 端口。产品上线我推荐这个方案因为前端资源由 Nginx 高效托管后端挂掉也不会影响页面加载后续前端更新只需要替换 dist 目录文件。方案二的关键配置server { listen 80; server_name your-domain.com; location / { root /usr/share/nginx/html/dist; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:9090; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }配置里try_files $uri $uri/ /index.html这一行特别重要。Vue Router 如果用的 history 模式直接访问/goods/1这类路径刷新时Nginx 默认会返回 404因为服务器找不到这个文件。只有配置了 try_files 回退到 index.html前端路由才能正常工作。这就是很多 Vue 项目部署后刷新页面就 404 的根本原因。7. 常见问题与踩坑记录7.1 高频报错排查表我在整个开发过程中整理了 8 个高频遇到的问题每个都查了很久才找到原因整理成了一份排查表。问题现象根本原因解决方案前端请求接口报跨域前后端端口不同浏览器拦截devServer 配置 proxy 或后端配置 CORS数据库连接报错 CommunicationsExceptionMySQL 8 要求显式指定时区连接串加 serverTimezoneAsia/ShanghaiVue history 路由刷新 404Nginx 找不到对应文件路径配置 try_files $uri $uri/ /index.html商品图片上传后访问 404SpringBoot 静态资源路径未映射到上传目录WebMvcConfigurer 添加资源映射列表查询返回所有字段都为 nullJava 实体驼峰命名与数据库下划线未映射开启 map-underscore-to-camel-case下单后库存不减但订单创建成功事务未生效或方法在同类中调用Transactional 加在 public 方法类外用代理调用SpringBoot 3 与旧教程配置不兼容jakarta 命名空间替换 javax使用 2.7.x 版本或按 3.x API 调整前端请求接口一直 404未配置 proxy 或接口前缀不匹配确认 /api 前缀与后端 context-path 一致7.2 我的一些实操心得最后说几个我个人项目中感触最深的经验。第一接口文档一定要提前定。我用的是 postman 的接口集合或者直接在 Notion 里维护一个接口清单表字段名、类型、状态码都列出来。前后端分离开发最大的坑不是技术而是沟通接口字段临时变更是家常便饭只有文档提前定好效率才能上去。第二关于图片上传。我用的最简单方案后端接收 MultipartFile存到服务器本地的一个 upload 目录然后返回访问路径。但注意SpringBoot 默认只暴露 static 目录下的文件upload 目录要手动加一个资源映射否则前端拿到路径也访问不到图片。具体配置是Configuration public class WebMvcConfig implements WebMvcConfigurer { Value(${upload.path}) private String uploadPath; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadPath /); } }第三购物车数据到底放前端还是后端我的答案是购物车基础数据放后端只会在用户进入购物车页面时通过接口拉取。为什么不用 localStorage因为购物车里的商品库存和价格是以数据库实时为准的商品可能被人买光可能被卖家下架前端本地存的商品信息可能已经过时直接从后端重新加载才能保证数据准确。第四遇到 Bug 先别急着改代码。把复现步骤记录下来把日志打印出来先判断是前端问题还是后端问题再缩小范围。比如商品列表不显示先看 Network 面板接口是否报错接口正常再看 SQL 是否查询到数据SQL 正常再看字段映射是否正确。层层递进大多数问题都能快速定位。最后这个项目我整体下来最大的收获不是把功能做出来了而是建立了一个完整的业务闭环思维。一个用户从进入页面到下单完成中间涉及多少状态流转、多少数据校验在之前单纯写增删改查时根本体会不到。等到你真正独立把这样的项目跑通一次再去看真实的电商系统架构很多设计理念就会觉得非常熟悉这就是这个项目的最大价值。
RELATED

相关推荐

VDC与BIM的区别及项目落地全解析

VDC与BIM的区别及项目落地全解析

刚入行的时候,我第一次听到“VDC”这个词,是从项目总监嘴里蹦出来的。当时他指着屏幕上的三维模型说:“这个管线调整的方案,VDC那边先跑一遍,没问题再出图。”我下意识把VDC理解成了“三维建模”,后来被现场…

📅 2026/10/8 20:34:52
基于纳什谈判理论的风-光-氢多主体新能源优化运行

基于纳什谈判理论的风-光-氢多主体新能源优化运行

国内做新能源优化运行、尤其是多主体博弈方向的同学,这两年应该都能明显感觉到一个变化:单主体的调度模型越来越难发文章了,大家都在往“多主体协同”“利益分配”这个方向走。而这个方向里,纳什谈判理论几乎是绕不开的一块基石。…

📅 2026/10/8 20:29:51
基于pytest的PTZ与宏系统自动化测试实战

基于pytest的PTZ与宏系统自动化测试实战

1. 为什么说软件测试在PTZ与宏系统场景里是“保命”的1.1 一个未被测试捕获的PTZ细节,会造成什么后果先说一个我真实踩过的坑。之前做一套视频巡检平台,上层有一个宏任务引擎,用来把多台球机的PTZ动作编排成“一键巡航”:预置位A …

📅 2026/10/8 20:29:51
MORE NEWS

更多资讯

📰

十分钟从零开始开发一个自己的MCP server(二):用TaoToken统一Key打通stdio与Claude Desktop

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

📰

openclaw可以控制手机吗?Android 端接入 TaoToken 的可行路径与配置验证

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

📰

Coding Agent的底层运行逻辑是什么?从一次401报错拆解到TaoToken统一Key

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

📰

书霸:把问卷设计从空白变成方案

一份问卷真正难写的地方,往往不是“凑出几道题”,而是把研究主题、调查对象和问题结构连接起来。很多人在开始设计问卷时,会先陷入三个问题:研究目标说不清,题目数量拿不准,题型之间缺少逻辑。结果是问卷看…

📰

从下单到签收,一票货要闯 7 道关:物流管理论文别再写“现状-问题-对策“三段式了

物流管理的毕业论文,十个里有八个是这个结构:某物流现状分析 → 存在问题 → 对策建议。评委看乏了,你也写乏了。 问题出在哪?这种写法没有"研究对象"。物流是一个由无数决策节点串起来的网络,论文的含金量…

📰

2026年AI编程助手如何选:TaoToken统一Key接入与选型评测指南

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

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬