ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于微信小程序的药店管理系统:架构拆分与避坑指南

基于微信小程序的药店管理系统:架构拆分与避坑指南 简介《毕业设计论文基于微信小程序的药店管理系统》是一篇典型的本科毕业设计论文模板面向计算机、信息管理类专业学生以药店管理系统微信小程序为课题展示了从选题到开发的完整过程。文档正文包含中文摘要、英文摘要、目录、绪论以及开发工具与关键技术介绍、系统分析、可行性分析等主体内容重点涉及微信开发者工具、小程序目录结构、Java语言、MySql数据库和SSM框架并详细描述了需求分析、界面设计、前后端实现、测试优化等环节技术路线清晰章节结构规范。资源包中仅含1个docx文件大小3.16MB文件类型单一便于直接打开阅读或作为格式模板。目前已有83人学习适合毕业设计初期拟定提纲、中期撰写论文或后期规范排版时参考也能帮助理解药店管理类小程序的实际业务模型与设计思路。1. 基于微信小程序的药店管理系统为什么最像 CRUD 的毕设反而最需要提前拆架构一套「基于微信小程序的药店管理系统」在题目列表里从来不是最抢眼的那个但它是学生和外包开发者都爱碰的类型药店业务听上去就是药品增删改查、下单、库存逻辑不绕。可实际动手就会发现它同时踩中了小程序开发、后端接口设计、MySQL 数据建模和论文撰写四座大山。处方药要不要做、订单状态怎么流转、库存扣减会不会超卖每一个问题都能在答辩现场变成连环追问。这篇笔记不解决「论文怎么写」而是解决更前置的问题这套系统该被拆成哪几个部分、每部分怎么做、坑在哪里。适合正在做这个题目、想把代码和论文一起交上去的应届生也适合想快速复制同类型订单系统的开发者。2. 先拆三端再写代码小程序、管理端和数据库的边界划定药店管理系统和一个普通电商小程序的差别不在页面上而在数据约束药品有批次、有有效期、有库存下限订单要关联处方登记管理端要审核。按我的习惯动手写第一行代码之前必须把三端边界画出来。小程序端负责浏览、搜索、下单、支付记录和个人订单管理端负责商品维护、订单审核、库存调整、会员管理数据库是三者的交汇点字段没定好后面接口和页面全要返工。2.1 小程序端选原生还是 uni-app毕设场景下我更推荐原生很多同学一上来就纠结用原生微信小程序还是用 Vue 语法的 uni-app我的建议很直接如果你是拿这个项目做毕业设计优先原生。原生微信小程序的调试链路最短。微信开发者工具打开即所见模拟器和真机的差异可以直接用工具看到遇到问题搜索到的解决方案绝大部分都是原生语法复现门槛低。而 uni-app 的优势是一套代码多端复用但毕设只需要一个端这个优势用不上反而要承担打包层带来的黑匣子编译报错要看 vue 文件还是看编译产物、sourcemap 对不对得上都是额外精力。尤其是上传代码的时候uni-app 打包出来的包体积很容易撞上 2MB 上限一个组件库没按需引入就超了这在原生开发里是可控的。如果你已经熟练 Vue实在要用 uni-app我不拦你但要在论文里额外解释清楚「为什么选跨端框架」这个问题答辩老师大概率会问。选原生论文架构图的表述成本最低。2.2 管理端与数据库Spring Boot MySQL 的常规骨架与字段设计管理端不需要花哨。常见做法是 Spring Boot MyBatis-Plus MySQL。如果后端还不熟直接用 Spring Boot 起步Bean 管理、事务、拦截器都是现成的论文里也能写出「基于 RESTful 风格的前后端分离架构」这种标准的系统设计。数据库是重点。药店系统的核心表我一般会建这几张user用户表存微信用户的 openid、昵称、手机号drug药品表药品名、规格、厂家、批准文号、零售价、库存下限stock_batch药品批次表一个药品对应多个批次批次有进货价、有效期、库存量order_master订单主表订单号、用户 id、总金额、状态、配送方式order_item订单明细表每个订单下的药品、数量、单价、快照prescription处方登记表处方药订单必填记录患者信息、处方图片、审核状态药品信息不直接存库存数量我建议拆出批次表。这样拆的原因有两个药店进货是按批次来的不同批次的进货价和有效期不同只存一个 total_stock 字段会丢失「哪些库存快过期」这种信息另外订单销售的是某个批次的库存批次表能让财务和效期管理都能对上账。给个最核心的库存批次表 SQLCREATE TABLE stock_batch ( id BIGINT PRIMARY KEY AUTO_INCREMENT, drug_id BIGINT NOT NULL COMMENT 药品ID关联 drug 表, batch_no VARCHAR(64) NOT NULL COMMENT 批次号, stock_qty INT NOT NULL DEFAULT 0 COMMENT 当前库存量, expire_date DATE NOT NULL COMMENT 有效期, purchase_price DECIMAL(10,2) NOT NULL COMMENT 进货价, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_drug_id (drug_id), KEY idx_expire (expire_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;说明这里把批次拆成独立表主键 id 只是自增代理键drug_id 加索引是订单查询和报表统计的必经之路expire_date 也单独加索引是为了做效期预警——写论文时可以顺手把「近效期药品预警」作为一个模块写进去成本不高但听起来很完整。另外药品表的批准文号建议加唯一索引。药店管理系统在答辩演示时很容易被问到「怎么防止同一种药品重复录入」一个 unique key 就是最直接的答案。2.3 先定接口协议再写页面一份 JSON 契约怎么省一半联调时间页面和小程序端联调时最容易翻车的是前后端对字段名各写各的。后端返回的是 createTime前端用的是 create_time分页后端默认从 0 开始前端从 1 传。这些问题本身不大但每改一次接口就要重新发一次体验版收集反馈的周期被拉得非常长。我的做法是先定义一份 JSON 契约再开工写页面。以药品列表接口为例// GET /api/drugs // 请求参数 { keyword: 阿莫西林, page: 1, pageSize: 10 } // 响应 { code: 0, message: ok, data: { list: [ { drugId: 1001, drugName: 阿莫西林胶囊, spec: 0.25g*24粒, price: 12.80, stock: 156, prescriptionRequired: 1 } ], total: 128, page: 1, pageSize: 10 } }参数说明keyword 允许为空空字符串时后端不做过滤page 从 1 开始pageSize 上限 50stock 显示的是「在售库存」是各有效批次库存之和prescriptionRequired 这个字段决定前端要不要展示「处方登记」入口很重要。响应 code 为 0 表示成功非 0 统一在拦截器里弹出 message前端页面不用到处写失败分支。字段命名统一用驼峰数据库用下划线由 MyBatis-Plus 映射转换。先定这份 JSON小程序端页面、管理端列表、论文里的接口设计表写起来都只有一份参照物。3. 从小程序新建到登录闭环用微信开发者工具跑起第一个页面这一章解决的是「从拿到一个空项目到小程序能访问后端」的过程。很多人的毕设卡在第一步微信开发者工具打开了appid 不知道填什么按钮做出来了请求后端却一直报 url not found。下面按我的操作顺序来。3.1 初始化项目目录与 app.json 基础配置用微信开发者工具新建项目时如果不注册小程序账号就用「测试号」也能开发大部分功能。测试号的好处是免注册、立刻能跑代价是 wx.login 拿到的 openid 是测试环境的数据不影响联调。如果你要发布体验版给老师试用需要换成正式 appid这一步在项目后期做也来得及。常见的代码结构pages 目录放页面utils 放请求封装和工具函数api 目录集中放接口定义components 放自定义组件。app.json 是全局配置pages 数组第一项是启动页。app.json 的要点{ pages: [ pages/index/index, pages/category/category, pages/cart/cart, pages/order/list, pages/user/user ], window: { navigationBarTitleText: 安心药房, navigationBarBackgroundColor: #ffffff, navigationBarTextStyle: black }, style: v2, sitemapLocation: sitemap.json }说明pages 的第一项决定小程序启动后进入哪个页面放首页。window 里的导航栏配置很多新人会忽略导致每个页面都要单独写一遍标题。如果你的页面需要自定义导航栏在 app.json 里把 navigationStyle 设成 custom然后自己在页面顶部留出状态栏高度。只要用了 custom 导航栏就必须用 getMenuButtonBoundingClientRect 相关接口量高度不能写死 64px具体方法在 3.4 会说。3.2 wx.login 换 code 再换 openid登录链路与 token 存哪里药店的订单、会员信息都跟用户身份绑定所以登录是第一个要做完整的链路。小程序端的登录方式是 wx.login 拿到 code把 code 交给后端后端拿 code 去微信官方接口换 openid 和 session_key然后后端生成自己的 token 返回给小程序。wx.login 在小程序端的调用长这样const login () { return new Promise((resolve, reject) { wx.login({ success(res) { if (res.code) { // 把这个 code 发给自己的后端 /api/auth/login request.post(/api/auth/login, { code: res.code }) .then(data { wx.setStorageSync(token, data.token); resolve(data); }) .catch(reject); } else { reject(new Error(wx.login 失败 res.errMsg)); } } }); }); };逻辑说明wx.login 拿到的 code 只能使用一次有效期五分钟后端和微信服务器通信换取 openid 后这个 code 就作废了。前端拿到后端返回的自定义 token 后存进 storage后续请求带上而不是存那个只有后端才需要的 code。参数说明request.post 是我封装的请求方法会在 header 里自动带上 Authorization。如果你的后端还没有实现 /api/auth/login最小的 Spring Boot 处理逻辑是接收 code调用微信接口返回自定义 token。这里有个毕业设计里很容易出现的错误——有人会把 session_key 或 openid 直接返回给前端存起来。openid 算用户标识但缺失过期机制session_key 是解密用户敏感信息的密钥都不能随便暴露给小程序端正确做法是把它们留在后端前端只持有 token。注意wx.login 在页面 onLoad 里调用一次就够了。每次都调会出现「登录态被覆盖导致上一步请求失效」的奇怪现象后面 5.4 还会单独讲。3.3 药品列表、搜索与「加载更多」列表页从能用到好用药店小程序最核心的页面就是药品列表。它要解决的问题是数据量大时不能一次全量渲染搜索输入时请求要防抖滚动到底部要自动加载下一页。列表请求的核心代码// pages/drug/list.js Page({ data: { list: [], page: 1, pageSize: 10, hasMore: true, keyword: , loading: false }, async loadDrugs(reset false) { if (this.data.loading) return; if (!reset !this.data.hasMore) return; this.setData({ loading: true }); const page reset ? 1 : this.data.page; try { const data await request.get(/api/drugs, { keyword: this.data.keyword, page, pageSize: this.data.pageSize }); const list reset ? data.list : this.data.list.concat(data.list); this.setData({ list, page: page 1, hasMore: list.length data.total, loading: false }); } catch (e) { this.setData({ loading: false }); wx.showToast({ title: 加载失败, icon: none }); } }, onReachBottom() { this.loadDrugs(); }, onSearchInput(e) { this.setData({ keyword: e.detail.value }); clearTimeout(this._timer); this._timer setTimeout(() this.loadDrugs(true), 300); } });逻辑说明loadDrugs 方法的 reset 参数区分「刷新第一页」和「加载更多」两种场景。搜索输入时用防抖把 300ms 内的连续输入合并成一次请求onReachBottom 是微信小程序自带的页面上拉触底事件不需要手动监听滚动位置。参数说明hasMore 的判断用 list.length data.total而不是总页数这样后端没返回 total 时也能正常工作loading 标志防止用户在加载时连续触底造成重复请求。还有一点data.list 是只增不删的数组切换药品分类时必须 reset 传 true否则会把上一类的药品列表累加在下面。3.4 顶部导航栏高度与自定义导航栏适配默认导航栏其实够用但列表页想要把搜索框做到视觉上融入导航栏就会用到自定义导航栏。很多人在这一步被劝退不是布局不会写而是状态栏高度在不同机型上不一样。常见适配代码// 自定义导航栏时动态计算 Page({ data: { statusBarHeight: 20, navBarHeight: 44 }, onLoad() { const systemInfo wx.getSystemInfoSync(); const capsule wx.getMenuButtonBoundingClientRect(); // 胶囊按钮定位信息包含 top、bottom、height是计算导航栏高度的基准 this.setData({ statusBarHeight: systemInfo.statusBarHeight, navBarHeight: capsule.bottom capsule.top - systemInfo.statusBarHeight }); } });说明导航栏高度的计算思路是约等于胶囊按钮底边到状态栏底边的距离。不同机型上胶囊的位置不完全一致用它自身的位置来倒推导航栏高度比写死一个值要稳。数据来源是 wx.getSystemInfoSync 和 wx.getMenuButtonBoundingClientRect前者确定状态栏高度后者拿到胶囊按钮的实际占据位置。在自定义导航栏页面顶部的搜索框或标题要在这个动态值基础上做 padding。用固定值的项目往往只在 iPhone 上看没问题换到全面屏安卓就顶到摄像头上了这类问题演示时最容易翻车。4. 从下单到库存扣减把订单、库存和处方药三个闭环串起来药店系统的联调难度不大但业务完整度体现在「闭环」上用户下单 → 扣库存 → 管理端审核 → 发货 → 用户确认。任何一个环节断了答辩的时候都容易被追问「状态去哪了」。4.1 订单状态机与库存扣减的顺序超卖是怎么来的订单不是建一条记录就结束我会把状态字段设计成一组数字枚举后端用状态机流转前端按数字翻译文案。状态设计参考10 待支付20 待审核涉及处方药时30 待发货已审核通过库存已扣40 已发货50 已完成90 已取消其中待审核这个状态是药店和普通电商系统的差异点。普通商城下单即扣库存、立即支付药店需要管理端先确认订单里有没有处方药、处方图片是否有效所以未审核订单不能进入配送环节。库存扣减这一句是超卖问题的核心。很多初学者先查库存数量if 够再 update但两台手机同时下单时两个请求都读到了库存为 1都往下一步走就产生了超卖。推荐做法是把查询和扣减放进一条带条件的 updateUPDATE stock_batch SET stock_qty stock_qty - #{buyQty} WHERE id #{batchId} AND stock_qty #{buyQty} AND expire_date NOW();说明这句 update 利用 MySQL 的行锁保证同一时刻只有一个事务能成功扣减受影响行数为 1 表示扣减成功为 0 表示库存不足或过期代码里根据影响行数回滚并返回「库存不足」。条件里同时带上 expire_date NOW() 还有一个附加好处过期批次的药品不会被卖出去。扣减的调用位置也很重要建议在支付回调或管理端审核通过时扣减不要在用户加购时就扣。放到购物车的商品最终可能不买早扣库存会造成其他用户买不到货的假象。4.2 管理端审核、配送状态与操作日志管理端页面可以简朴但「审核」这个动作不能没有记录。使用管理端的角色包括管理员admin和店员staff权限差异一般是店员能处理订单和发货管理员才能调整药品价格、编辑库存、查看财务报表。审核接口的一个建议是把「审核结果 操作人 备注」三个字段一起提交后端写一条审核记录// 审核订单 PostMapping(/api/admin/order/audit) public Result auditOrder(RequestBody AuditDTO dto) { OrderMaster order orderMapper.selectById(dto.getOrderId()); // 幂等校验已审核的订单不能重复审核 if (order.getStatus() ! 20) { return Result.error(订单当前状态不允许审核); } // 更新订单状态并写入操作日志 order.setStatus(dto.getPass() ? 30 : 90); order.setAuditor(dto.getOperator()); order.setAuditRemark(dto.getRemark()); orderMapper.updateById(order); logMapper.insert(OrderLog.from(order, 审核)); if (dto.getPass()) { stockService.deductByOrder(order.getId()); } return Result.ok(); }逻辑说明接口先做幂等校验——只有状态为 20待审核的订单才允许审核这样前端即使连点两次提交第二次也会被挡回来。审核通过后状态置 30 并调用库存扣减服务这里把扣库存放在了审核动作里和 4.1 提到的时机保持一致。参数说明AuditDTO 里包含 orderId、pass、operator、remark 四个字段operator 从管理端登录会话中取不允许前端传值伪造——这是个容易忽略的安全点。如果你用的是 JWT 方案从 token 里解析操作人。操作日志这一块很多毕设会砍掉但我强烈建议留一张表原因很实际演示的时候老师问「这个药品价格是谁改的」你能现场打开日志列表查到记录比嘴上解释「有权限的人才能改」要有说服力得多。日志表不用复杂记录操作人、操作类型、目标对象、操作时间、操作详情就行。4.3 会员、处方药登记与订阅消息功能取舍和边界药店系统的功能里最容易把自己绕进去的是会员和处方药。会员可以做积分和折扣但如果论文篇幅有限我会建议做成基础版用户表上存一个积分字段订单完成后积分累加下单时按积分抵扣金额。做太多反而让论文重点失焦。处方药是药店系统的必答题。我的处理方式是前端把处方药单独标识加入购物车时检测到处方药就提示去登记登记表单需要用户填写患者姓名、身份证、手机号并拍照上传处方图片后端创建订单时自动把订单置为待审核状态由管理端审核处方后放行。处方登记表的核心字段CREATE TABLE prescription ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT NOT NULL, user_id BIGINT NOT NULL, patient_name VARCHAR(64) NOT NULL COMMENT 患者姓名, id_card VARCHAR(32) NOT NULL COMMENT 身份证号, phone VARCHAR(32) NOT NULL, image_url VARCHAR(255) NOT NULL COMMENT 处方图片, audit_status TINYINT NOT NULL DEFAULT 0 COMMENT 0未审 1通过 2驳回, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;说明order_id 关联订单表处方审核状态和订单审核状态可以保持一致也可以由管理端单独审核。image_url 存的是图片上传后的 URL 或云存储路径毕设里可以直接用小程序云开发或后端本地静态目录省掉对象存储的配置成本。这里要注意一个边界微信小程序对个人开发者开放的能力里蓝牙、消息订阅这些在模拟器里表现良好真机上受权限和环境限制表现可能不一样。如果你的药店场景里想对接蓝牙扫码枪或电子秤属于加分项不是必做项做之前先确认自己的小程序类目有没有开通对应接口权限。订阅消息也一样用户点了一次「允许」之后按钮不会再次弹窗你只能引导用户去设置页开启。在毕设答辩演示时订阅消息容易现场翻车因为弹窗权限已经被上一次点击消耗掉了后面 5.6 会说怎么处理。5. 药价改错了、订单丢了、列表翻不动6 个高发坑点与排查清单这一章把我在类似项目里看到过的、新手最容易被卡住的 6 个问题整理成清单。每条按「现象、原因、解决」写方便你直接对照排查。5.1 真机上请求一直失败模拟器却正常合法域名与 TLS 版本现象微信开发者工具里请求后端一切正常一到真机预览所有接口都报 request:fail。这是毕设项目里出现频率最高的一个问题。原因小程序真机环境要求请求的域名必须在小程序后台配置为合法域名并且该域名备案、支持 HTTPS。本机开发时使用的是 http://localhost模拟器不做拦截真机直接拒绝。解决开发阶段在微信开发者工具右上角「详情 → 本地设置」里勾选「不校验合法域名」可以暂时绕过要给别人试用的体验版必须用 HTTPS 域名。如果你的后端没有公网 HTTPS 域名常见做法是用内网穿透工具临时映射本机端口或直接把后端部署到一台有公网 IP 的服务器上。注意这适合开发联调和演示体验版要稳定使用还是得走正规域名。5.2 上传代码提示包体积超限一张宣传图吃掉几百 KB现象编译运行没问题上传时提示主包大小超过 2MB或提示分包大小超限。原因图片资源放在本地、引入完整版组件库、或使用 uniapp 打包时生成了冗余依赖都会让包体积迅速膨胀。很多项目的本地图片一张轮播图就 300~500KB几张图就超了。解决图片能放云端就不要放本地小程序里用网络图片 URL 而不是本地文件组件库使用按需引入如果项目是 uniapp 构建的检查构建产物里是否有重复的 js 文件。另一个方案是启用分包加载把仅用户操作时才需要的页面比如订单详情、处方登记放进分包。主包只保留首页、药品列表、用户中心三个核心页面体积能降一大截。5.3 真机上页面内容和开发者工具长得不一样不光是样式问题现象模拟器上导航栏高度正常、输入框位置正确真机上标题顶到最上面或者图片显示不出来。原因模拟器按默认机型渲染真机是用户的实际屏幕尺寸和浏览器内核。自定义导航栏如果没有用 3.4 的方法动态计算高度在小屏或全面屏机型上必然错位。另一个常见原因是本地图片路径没写对开发者工具会自动补路径真机上找不到文件就直接白屏。解决导航栏高度一律动态计算图片统一走网络 URL 或打包到代码包内并严格按相对路径引用。发布体验版之前至少在 iPhone 和一台安卓真机上各跑一遍核心页面。注意体验版发给同学收集试用反馈时要提醒对方在微信中打开并确认自己的微信号被加入体验成员名单。这个问题不是代码问题但没有它代码跑不起来。5.4 用户反复要求重新登录wx.login 被放在每个页面 onLoad 里现象用户在 A 页面操作完跳转到 B 页面B 页面要求重新登录或者一次操作过程中 token 被刷新之后带着新 token 的请求失败。原因wx.login 被放在了 page 的 onLoad 里每次进入页面都会调用后一次调用把前一次后端下发的 token 覆盖了导致同时进行中的其他请求用了过期 token 被后端拒收。解决把 wx.login 收敛到一个入口App 启动或用户第一次需要登录信息时统一调用一次把 token 写入 storage每次请求从 storage 读 token不重复发起登录流程。后端对 token 过期返回 401 时前端再重新走一次登录。5.5 订单状态和库存对不上只改了订单表没动批次库存现象管理端审核通过后订单状态显示已审核但药品列表里的库存数字没减或者客户下单后库存扣了但订单取消时库存没加回来。原因库存扣减的调用点和订单状态更新没有放在同一个事务里或者取消订单的补偿逻辑漏写了。解决建议把「更新订单状态 扣减库存」放进同一个事务取消订单时同样在事务里做「更新状态 回补库存」。Spring Boot 里直接在 service 方法上加 Transactional并把 4.1 的条件 update 作为操作方式。血泪经验是扣库存和订单状态更新一旦分开线上数据会以肉眼可见的速度开始漂移。5.6 订阅消息弹窗只在第一次出现现场演示最容易翻车的功能现象开发时订阅消息授权弹窗每次都弹但用户在真实点击一次「允许」之后后续再调用同一模板就不再弹窗。原因微信订阅消息是「一次性订阅」用户授权一次只能发送一次消息。前端每次调用弹窗是否出现取决于用户当前的订阅次数是否耗尽不是每次都弹。解决设计成用户每次下单后主动点击一个「开启配送通知」按钮在按钮的点击事件里调用订阅消息接口这样弹窗出现在用户有明确意向的时刻成功率最高。演示时准备两个测试微信号轮换或者提前触发一次授权。另外不同模板的订阅次数是分开计算的。6. 答辩前 30 分钟用一套演示脚本把「看起来能用」变成「确实能用」最后一个实操技巧是演示脚本。开发时你会登录自己账号、数据都是本地的但答辩教室的电脑和网络环境你控制不了。我的习惯是准备一台装好开发者工具和本地后端的电脑所有服务提前启动然后在工具里打开三个页面管理端药品列表、小程序药品列表、订单列表。演示时按一条固定的业务线走小程序搜索「阿莫西林」→ 加入购物车 → 模拟支付 → 管理端看到待审核订单 → 审核通过 → 小程序端订单状态变为已发货。整个过程不超过三分钟每一屏都指向系统的一个核心能力。我踩过的最深一个坑是演示前为了秀功能把数据库测试数据的数量改得很大结果列表接口 timeout页面白屏现场从「功能演示」变成「事故复盘」。从那以后我养成了一个习惯——演示用数据永远不虚构就用真实的 10 条药品、3 个订单让演示链路短而可靠。还有一个小技巧把后端日志级别调到 debug 并保留终端窗口老师问「这一步发生了什么」的时候你能指着 SQL 日志说出库里发生了什么这个细节在答辩里的分量比多做一个模块更重。这个方向值不值得投入我的结论是值得但价值不在「药店管理系统」本身而在于你通过它完整走了一遍小程序、服务端、数据库三方协作的流程。框架会过期这套协作经验不会。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进