news 2026/9/26 18:01:27

二手交易网站源码全栈解析:从论文到可运行系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二手交易网站源码全栈解析:从论文到可运行系统

简介:这份资源是二手交易网站项目的论文与源码合集,面向电子商务、网络开发方向的学习者与研究者,尤其适合需要完成课程设计、毕业设计或想深入理解二手电商运作机制的中高级开发者。压缩包为zip格式,整体约53.32MB,文件总数与类型明细上游未提供,从描述可知核心内容分为论文与源码两大部分:论文涵盖市场背景与需求分析、用户画像构建、界面设计理念、技术架构选型、开发过程与市场分析、项目总结等;源码则包含前端界面布局与交互逻辑、后端用户与商品订单管理、支付接口对接及数据库设计等模块。目前已有49人学习下载,读者可借助论文理清设计思路与商业逻辑,对照源码掌握前后端协作与数据存储细节,并从中体会用户体验、数据安全、交易公正性与隐私保护等关键问题的落地方式,实现从理论到实践的系统学习。

1. 二手交易网站从论文到可跑源码:一套能落地的全栈方案长什么样

二手交易网站这个题目,几乎每年都出现在毕业设计和课程设计的选题清单里,但真正把它做成一个能跑起来、能演示、能讲清楚技术选型的系统,和只交一份论文加一堆跑不起来的代码,中间差着一条完整的工程链路。我见过太多同学拿到「论文+源码」的压缩包,解压之后发现数据库连不上、依赖装不上、前端页面白屏,最后只能对着论文干瞪眼。这篇笔记要解决的就是这个问题:把二手交易网站从需求分析、数据库设计、后端接口、前端页面到部署运行的每一步拆开讲清楚,让你拿到任何一份二手交易网站的源码都能看懂结构、跑通流程、改出自己想要的功能。

适合读这篇的人有三类:正在做二手交易网站毕业设计、需要把论文和代码对上的同学;想用 Java 或 Python 快速搭一个二手交易平台原型、验证业务逻辑的开发者;以及手上有源码但跑不起来、需要一套系统排查思路的工程师。核心关键词就是二手交易网站和源码,我会围绕这两个词,把技术选型、数据库表结构、核心接口实现、前端交互和部署踩坑全部串一遍。整套方案我一般用 SpringBoot + MyBatis + MySQL + Vue 来做,这也是目前课程设计和中小型项目里最稳的组合,下面按这个技术栈展开,Python 方案会在关键处做对比说明。

2. 二手交易网站的技术选型与数据库设计:先把地基打对

2.1 为什么 SpringBoot + MyBatis + Vue 是二手交易网站的主流组合

二手交易网站的业务本质是「用户发布商品 → 买家浏览搜索 → 下单交易 → 双方评价」,这个链路对后端的要求集中在三点:用户会话管理、商品数据的增删改查、订单状态的流转控制。SpringBoot 在这三件事上都有成熟的 starter 支持,MyBatis 对商品表这种字段多、查询条件灵活的场景比 JPA 更好控制 SQL,Vue 的前端组件化则能让商品列表、详情、发布表单这些重复度高的页面快速复用。

选型时最容易翻车的地方是盲目上微服务。二手交易网站的用户量在课程设计阶段通常只有几十到几百,单体应用完全够用,拆成微服务只会让部署和调试成本翻倍。我一般会建议:如果论文里写了微服务架构,代码里至少要有服务拆分和注册中心的实际配置,否则答辩时被问到「你的服务怎么注册发现的」会很难看。另一个常见误区是前端用 jQuery 一把梭,结果商品列表的分页和筛选逻辑全写在 HTML 里,后期改一个字段要动十几个页面。Vue 的响应式数据绑定在这个场景下能省掉大量 DOM 操作代码。

数据库层面,MySQL 5.7 和 8.0 在二手交易网站这个量级下差异不大,但 8.0 的窗口函数在统计「某用户本月成交额排名」这类需求上会方便很多。如果源码里用的是 5.7,迁移到 8.0 时注意驱动包要从mysql-connector-java换成mysql-connector-j,否则启动时会报驱动类找不到。

2.2 二手交易网站核心表结构设计与字段说明

一套能跑的二手交易网站,最少需要六张核心表:用户表、商品表、商品分类表、订单表、收货地址表、评价表。下面这张表是我在多个项目里沉淀下来的字段设计,直接照着建能覆盖 90% 的课程设计需求。

表名核心字段字段类型说明
userid, username, password, phone, avatar, credit_score, create_timebigint, varchar(50), varchar(100), varchar(20), varchar(255), int, datetimecredit_score 用于信用分,初始 100
productid, user_id, category_id, title, description, price, original_price, images, status, create_timebigint, bigint, bigint, varchar(100), text, decimal(10,2), decimal(10,2), varchar(1000), tinyint, datetimestatus: 0 待审核 1 在售 2 已售 3 下架
categoryid, name, parent_id, sort_orderbigint, varchar(50), bigint, int支持二级分类,parent_id 为 0 表示一级
ordersid, order_no, buyer_id, seller_id, product_id, amount, status, address_id, create_time, finish_timebigint, varchar(64), bigint, bigint, bigint, decimal(10,2), tinyint, bigint, datetime, datetimestatus: 0 待付款 1 已付款 2 已发货 3 已完成 4 已取消
addressid, user_id, receiver, phone, province, city, district, detail, is_defaultbigint, bigint, varchar(50), varchar(20), varchar(50), varchar(50), varchar(50), varchar(255), tinyintis_default: 1 默认地址
commentid, order_id, from_user_id, to_user_id, content, rating, create_timebigint, bigint, bigint, bigint, text, tinyint, datetimerating 1-5 星

建表时有两个字段容易被忽略但后期一定会用到:product 表的images字段建议存 JSON 数组字符串而不是单张图片路径,因为二手商品通常有多张实拍图;orders 表的order_no要用业务编号而不是自增主键,格式可以是「年月日时分秒+随机数」,方便对账和排查。

CREATE TABLE `product` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) NOT NULL COMMENT '发布者ID', `category_id` bigint(20) NOT NULL COMMENT '分类ID', `title` varchar(100) NOT NULL COMMENT '商品标题', `description` text COMMENT '商品描述', `price` decimal(10,2) NOT NULL COMMENT '售价', `original_price` decimal(10,2) DEFAULT NULL COMMENT '原价', `images` varchar(1000) DEFAULT NULL COMMENT '图片JSON数组', `status` tinyint(4) DEFAULT '0' COMMENT '0待审核 1在售 2已售 3下架', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`), KEY `idx_category_status` (`category_id`,`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

这段建表语句里,idx_category_status联合索引是给「按分类筛选在售商品」这个最高频查询准备的。如果只建 category_id 单列索引,当分类下商品很多时,status 的过滤会走回表,分页查询会明显变慢。images用 varchar(1000) 而不是 text,是因为 MySQL 在 varchar 上建前缀索引更方便,而且 1000 字符足够存 5-6 张图片的 URL。

2.3 从论文需求到表字段的映射方法

论文里的需求描述通常是「用户可以发布二手商品,填写标题、描述、价格、上传图片」,对应到表字段就是 title、description、price、images 四个字段。但论文往往不会写「商品需要审核」,而实际系统里如果不加 status 字段,所有发布的商品直接上架,会出现违规内容无法下架的问题。我一般会对照论文的功能模块图,逐个模块问三个问题:这个操作产生什么数据、数据之间什么关系、数据状态会怎么变。把这三个问题的答案填进表结构,基本不会漏字段。

订单表的状态流转是论文里最容易写不清楚的部分。论文可能只写「买家下单后生成订单」,但实际代码里订单状态至少要有待付款、已付款、已发货、已完成、已取消五种。状态之间的流转条件要在代码里用枚举控制,不能直接在数据库里改 status 值,否则会出现「已取消的订单又被标记为已完成」这种脏数据。

3. 二手交易网站后端接口实现:从商品发布到订单状态流转

3.1 商品发布接口的完整实现与图片上传处理

商品发布是二手交易网站最核心的写操作,涉及表单校验、图片上传、数据入库三个步骤。下面这段 SpringBoot 代码是商品发布接口的典型实现,我把它拆成 Controller 和 Service 两层来看。

@RestController @RequestMapping("/api/product") public class ProductController { @Autowired private ProductService productService; @PostMapping("/publish") public Result publish(@RequestBody ProductPublishDTO dto, @RequestAttribute Long userId) { // 参数校验:标题非空、价格大于0、分类存在 if (StringUtils.isBlank(dto.getTitle())) { return Result.fail("商品标题不能为空"); } if (dto.getPrice() == null || dto.getPrice().compareTo(BigDecimal.ZERO) <= 0) { return Result.fail("价格必须大于0"); } // 调用 Service 层,传入当前登录用户ID Long productId = productService.publish(dto, userId); return Result.success(productId); } }

Controller 层只做参数校验和结果封装,业务逻辑全部下沉到 Service。@RequestAttribute Long userId是从拦截器里取的当前登录用户 ID,这样避免在每个接口里重复解析 token。参数校验用StringUtils.isBlank而不是isEmpty,因为用户可能输入空格作为标题,isBlank能拦住这种情况。

Service 层的实现要注意事务和图片处理的顺序:

@Service public class ProductServiceImpl implements ProductService { @Autowired private ProductMapper productMapper; @Autowired private ImageService imageService; @Override @Transactional(rollbackFor = Exception.class) public Long publish(ProductPublishDTO dto, Long userId) { // 1. 先处理图片,把 base64 或临时文件转成正式 URL List<String> imageUrls = imageService.saveImages(dto.getImages()); // 2. 构建商品实体 Product product = new Product(); product.setUserId(userId); product.setCategoryId(dto.getCategoryId()); product.setTitle(dto.getTitle()); product.setDescription(dto.getDescription()); product.setPrice(dto.getPrice()); product.setOriginalPrice(dto.getOriginalPrice()); product.setImages(JSON.toJSONString(imageUrls)); product.setStatus(0); // 待审核状态 product.setCreateTime(new Date()); // 3. 入库 productMapper.insert(product); return product.getId(); } }

@Transactional(rollbackFor = Exception.class)里的rollbackFor必须显式指定,因为 Spring 默认只对 RuntimeException 回滚,如果图片保存抛了 IOException,事务不会回滚,会出现图片存了但商品没入库的情况。图片处理放在入库之前,是因为如果先入库再处理图片,图片处理失败时商品记录已经存在,需要额外写补偿逻辑。

图片上传接口我一般单独拆一个/api/upload/image,接收 MultipartFile,存到本地磁盘或对象存储,返回可访问的 URL。本地存储时注意路径不要放在项目目录下,否则重新部署时图片会丢。常见做法是配置一个upload.path参数指向服务器固定目录,通过静态资源映射对外暴露。

3.2 订单创建与状态流转的接口设计

订单接口的难点不在创建,而在状态流转的控制。下面这段代码展示了订单创建和状态更新的核心逻辑。

@Service public class OrderServiceImpl implements OrderService { @Autowired private OrderMapper orderMapper; @Autowired private ProductMapper productMapper; @Override @Transactional(rollbackFor = Exception.class) public String createOrder(Long buyerId, Long productId, Long addressId) { // 1. 查询商品,校验是否在售 Product product = productMapper.selectById(productId); if (product == null || product.getStatus() != 1) { throw new BizException("商品已售出或已下架"); } // 2. 不能购买自己发布的商品 if (product.getUserId().equals(buyerId)) { throw new BizException("不能购买自己发布的商品"); } // 3. 生成订单号 String orderNo = generateOrderNo(); Orders order = new Orders(); order.setOrderNo(orderNo); order.setBuyerId(buyerId); order.setSellerId(product.getUserId()); order.setProductId(productId); order.setAmount(product.getPrice()); order.setStatus(0); // 待付款 order.setAddressId(addressId); order.setCreateTime(new Date()); orderMapper.insert(order); // 4. 锁定商品,防止重复下单 productMapper.updateStatus(productId, 2); // 已售 return orderNo; } private String generateOrderNo() { return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + String.format("%04d", new Random().nextInt(10000)); } }

创建订单时把商品状态直接改成「已售」是一种简化处理,实际项目中更稳妥的做法是加一个「锁定中」的中间状态,等付款成功后再改成「已售」,超时未付款则释放回「在售」。但课程设计阶段为了代码简洁,直接改状态也能跑通,只要在论文里说明这个简化即可。

订单状态更新接口要严格校验当前状态和目标状态是否允许流转:

public void updateOrderStatus(Long orderId, Integer targetStatus, Long operatorId) { Orders order = orderMapper.selectById(orderId); if (order == null) { throw new BizException("订单不存在"); } // 只有买家能取消待付款订单,只有卖家能发货 if (targetStatus == 4 && !order.getBuyerId().equals(operatorId)) { throw new BizException("无权取消该订单"); } if (targetStatus == 2 && !order.getSellerId().equals(operatorId)) { throw new BizException("无权发货"); } // 状态流转校验:待付款只能转已付款或已取消 if (order.getStatus() == 0 && targetStatus != 1 && targetStatus != 4) { throw new BizException("当前状态不允许该操作"); } orderMapper.updateStatus(orderId, targetStatus); }

这段代码里权限校验和状态校验缺一不可。我见过有源码只校验了登录状态,没校验操作人身份,结果任何登录用户都能取消别人的订单。状态流转的 if 判断要覆盖所有合法路径,宁可多写几个分支,也不要让非法状态跳转通过。

3.3 商品搜索与分页查询的 SQL 优化

二手交易网站的商品列表页通常支持关键词搜索、分类筛选、价格排序、分页四个条件组合。下面这条 SQL 是典型的组合查询:

SELECT p.id, p.title, p.price, p.images, p.create_time, u.username AS sellerName FROM product p LEFT JOIN user u ON p.user_id = u.id WHERE p.status = 1 AND (p.title LIKE CONCAT('%', #{keyword}, '%') OR p.description LIKE CONCAT('%', #{keyword}, '%')) AND (#{categoryId} IS NULL OR p.category_id = #{categoryId}) ORDER BY p.create_time DESC LIMIT #{offset}, #{pageSize}

这条 SQL 在数据量小的时候没问题,但当 product 表超过几万行时,LIKE '%keyword%'会导致全表扫描。优化方向有两个:一是给 title 和 description 建全文索引,用MATCH ... AGAINST替代 LIKE;二是引入 Elasticsearch 做搜索引擎,但这对课程设计来说太重了。我一般会建议在论文里提一句「后期可引入全文索引优化搜索性能」,代码里保持 LIKE 实现,这样既不影响运行,又体现了技术思考。

分页查询的LIMIT offset, pageSize在 offset 很大时也会变慢,因为 MySQL 要扫描前 offset 行再丢弃。优化方法是改用游标分页,记录上一页最后一条的 create_time,下一页查WHERE create_time < #{lastTime}。但这个改动会影响前端分页组件的逻辑,如果源码里用的是传统分页,不建议在课程设计阶段改,知道有这个优化点即可。

4. 二手交易网站前端页面与联调:Vue 组件拆分和接口对接

4.1 商品列表页的组件拆分与数据渲染

Vue 前端在二手交易网站里最核心的页面是商品列表页和商品详情页。列表页我一般拆成三个组件:搜索栏组件、分类筛选组件、商品卡片组件。这样拆的好处是搜索栏和分类筛选的逻辑可以独立测试,商品卡片可以在首页、搜索结果页、个人主页多处复用。

// ProductList.vue <template> <div class="product-list"> <SearchBar @search="handleSearch" /> <CategoryFilter :categories="categories" @change="handleCategoryChange" /> <div class="product-grid"> <ProductCard v-for="item in products" :key="item.id" :product="item" @click="goDetail(item.id)" /> </div> <Pagination :total="total" :page-size="pageSize" :current-page="currentPage" @page-change="handlePageChange" /> </div> </template> <script> export default { data() { return { products: [], categories: [], total: 0, pageSize: 12, currentPage: 1, keyword: '', categoryId: null }; }, mounted() { this.loadCategories(); this.loadProducts(); }, methods: { async loadProducts() { const res = await this.$http.get('/api/product/list', { params: { keyword: this.keyword, categoryId: this.categoryId, page: this.currentPage, size: this.pageSize } }); this.products = res.data.list; this.total = res.data.total; }, handleSearch(keyword) { this.keyword = keyword; this.currentPage = 1; this.loadProducts(); }, handleCategoryChange(categoryId) { this.categoryId = categoryId; this.currentPage = 1; this.loadProducts(); }, handlePageChange(page) { this.currentPage = page; this.loadProducts(); } } }; </script>

这段代码里handleSearch和handleCategoryChange都把currentPage重置为 1,这是一个容易漏掉的细节。如果用户在第三页搜索新关键词,不重置页码会导致查询结果为空,因为新关键词的结果可能只有一页。loadProducts用 async/await 而不是 then 链,是为了让错误处理更集中,可以在外层包 try-catch 统一提示。

4.2 前后端联调的跨域与登录态处理

前后端分离项目联调时第一个拦路虎就是跨域。SpringBoot 里配置跨域有两种方式:全局配置和注解配置。全局配置更省事,在配置类里加一个 CorsFilter 即可。

@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOriginPattern("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }

注意addAllowedOriginPattern("*")和setAllowCredentials(true)同时使用时,不能用addAllowedOrigin("*"),否则 SpringBoot 2.4 以上版本会报错。这是升级 SpringBoot 后最常见的跨域翻车点。

登录态处理我一般用 JWT,前端登录成功后把 token 存 localStorage,每次请求通过 axios 拦截器加到 header 里。后端写一个拦截器校验 token,把解析出的 userId 塞进 request attribute。这里要注意 token 过期时间的设置,课程设计里设 24 小时足够,太短会导致演示时频繁重新登录,太长则安全性差。

// axios 拦截器 axios.interceptors.request.use(config => { const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = 'Bearer ' + token; } return config; }); axios.interceptors.response.use( response => response.data, error => { if (error.response && error.response.status === 401) { localStorage.removeItem('token'); window.location.href = '/login'; } return Promise.reject(error); } );

响应拦截器里统一处理 401,避免每个接口都写一遍登录失效逻辑。return response.data让业务代码直接拿数据,不用每次写res.data.data。

5. 二手交易网站部署与常见问题排查:这些坑我替你踩过了

5.1 数据库连接失败与字符集乱码的排查

现象:项目启动时报Communications link failure或Access denied for user。原因:MySQL 8.0 的默认认证插件是caching_sha2_password,而旧版驱动包不支持;或者数据库用户名密码配置在application.yml里写错了。解决:把驱动包换成mysql-connector-j8.0 以上版本,或者在 MySQL 里执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';把认证插件改回旧版。

现象:商品标题里的中文在数据库里显示为???。原因:建表时字符集用了latin1或者连接 URL 没指定characterEncoding=utf8。解决:建表统一用utf8mb4,连接 URL 加上?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai。serverTimezone不指定的话,MySQL 8.0 会报时区错误。

5.2 图片上传后无法访问的路径问题

现象:图片上传成功,数据库里也有 URL,但前端<img>标签显示裂图。原因:图片存到了服务器磁盘目录,但没有配置静态资源映射,SpringBoot 默认只暴露classpath:/static/下的资源。解决:在配置类里加registry.addResourceHandler("/upload/**").addResourceLocations("file:" + uploadPath);,其中 uploadPath 是图片实际存储的绝对路径,末尾必须带斜杠。

现象:本地开发时图片能显示,部署到服务器后裂图。原因:代码里用了相对路径存图片,本地运行时相对于项目目录,服务器上相对于启动脚本目录,路径不一致。解决:在application.yml里配置upload.path为绝对路径,代码里统一用这个配置项拼接。

5.3 订单重复提交与并发下单的防重处理

现象:用户快速点击两次「立即购买」,生成了两笔订单。原因:前端没有防重复点击,后端也没有幂等校验。解决:前端在按钮点击后立即 disabled,请求返回后再恢复;后端在创建订单前先查一下该用户对该商品是否有未完成的订单,有则直接返回已有订单号。更严格的做法是用 Redis 分布式锁,但课程设计阶段用数据库查询判断就够了。

现象:两个用户同时购买同一件商品,都下单成功。原因:查询商品状态和更新商品状态之间有时间窗口,两个请求都查到了「在售」。解决:把更新商品状态的 SQL 改成UPDATE product SET status = 2 WHERE id = ? AND status = 1,根据 affected rows 判断是否更新成功,返回 0 说明已被别人买走。

5.4 前端打包后接口 404 的排查思路

现象:npm run dev时接口正常,npm run build部署后所有接口 404。原因:开发环境配置了 proxy 代理,打包后 proxy 不生效,请求直接打到了前端服务器。解决:生产环境要用 Nginx 反向代理,把/api开头的请求转发到后端端口。Nginx 配置里注意proxy_pass的地址末尾不要带斜杠,否则会丢掉/api前缀。

现象:前端路由刷新后 404。原因:Vue Router 的 history 模式需要服务器把所有未匹配的路径都返回 index.html。解决:Nginx 里加try_files $uri $uri/ /index.html;。

6. 让二手交易网站源码真正可复用的三个改造技巧

拿到一份二手交易网站源码,能跑起来只是第一步,真正有价值的是把它改造成自己能用的东西。我一般会做三个改造:把硬编码的配置抽成配置中心、把重复的 CRUD 代码抽成基类、把业务逻辑和框架代码分离。

第一个改造是配置外置。源码里经常把数据库密码、图片路径、JWT 密钥直接写在代码里,这样换一个环境就要改代码重新打包。我一般会把这些配置全部挪到application.yml,然后用@ConfigurationProperties绑定到一个配置类上。这样部署时只需要改 yml 文件,不用重新编译。

@Component @ConfigurationProperties(prefix = "app") public class AppConfig { private String uploadPath; private String jwtSecret; private Integer jwtExpireHours; // getter/setter 省略 }

第二个改造是抽基类。二手交易网站里用户、商品、订单、地址的 Controller 都有 list、get、save、update、delete 五个方法,代码结构几乎一样。我一般会写一个BaseController<T>把公共方法抽出来,子类只需要指定 Service 和实体类型。这样新增一个「举报」模块时,Controller 只需要写几行代码。

第三个改造是业务逻辑分层。源码里经常在 Controller 里直接调 Mapper,或者把业务规则写在 SQL 里。我一般会强制三层:Controller 只做参数校验和结果封装,Service 写业务规则和事务,Mapper 只做单表 CRUD。这样改需求时只需要动 Service 层,不会牵一发动全身。

最后一个技巧是关于论文和代码的对齐。论文里的功能模块图、流程图、ER 图,要和代码里的包结构、类名、表名一一对应。答辩时老师最常问的是「你这个功能在代码哪里实现的」,如果论文里叫「商品管理模块」,代码里却叫ProductController,你要能立刻指出对应关系。我一般会在论文附录里加一张「论文术语与代码类名对照表」,这个习惯帮我省了很多答辩时的解释时间。

这套方案我从第一个二手交易网站项目开始用,中间翻过车也补过坑,最大的教训是:不要为了追求技术栈的新颖而牺牲可运行性。用 SpringBoot + MyBatis + Vue 这套组合,虽然不酷,但遇到问题时能搜到的解决方案最多,答辩时老师也最容易理解。希望帮到你。

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

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

10 个最佳 Golang 库:用 TaoToken 统一 Key 打通 AI 编码工具链

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

作者头像 李华
网站建设 2026/9/26 17:59:17

TaoToken 配置 vscode 插件开发:五分钟上手 settings.json 骨架

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

作者头像 李华
网站建设 2026/9/26 17:58:44

HTML入门到进阶:从标签语法到前端开发实战完整指南

如果你想学网页开发&#xff0c;无论是想写一个个人主页、做一个前端项目、还是参与任何和网页有关的工作&#xff0c;HTML都是绕不开的第一站。它也是我教过这么多零基础学员里&#xff0c;被认为"上手最快"的语言——没有变量、没有逻辑、没有API&#xff0c;只有一…

作者头像 李华
网站建设 2026/9/26 17:58:44

Skill能力封装实战:从SKILL.md到SkillHub的复用指南

1. 为什么“经验复用”这件事值得单独做成一个能力包刚入行那几年&#xff0c;我最怕听到的一句话就是“这个需求上次不是做过类似的吗&#xff0c;你怎么又从头来一遍”。那时候我的工作方式很原始&#xff1a;每做完一个项目&#xff0c;把关键代码片段、踩坑记录、配置参数一…

作者头像 李华
网站建设 2026/9/26 17:57:59

零基础学Python:从环境搭建到数据可视化实战路线

Python 大概是过去十年里最值得花时间认真学一遍的编程语言。我身边陆续有人因为工作里的一件小事开始碰 Python&#xff1a;运维想批量处理服务器日志&#xff0c;财务想合并几十张 Excel&#xff0c;研究生想跑一组统计数据&#xff0c;最后基本上都能在两三周内写出真正能用…

作者头像 李华