ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python+uniapp微信小程序自助购药商城:拆单、发票与合规流程全解析

Python+uniapp微信小程序自助购药商城:拆单、发票与合规流程全解析 干毕业设计或者做练手项目的时候很多人喜欢直接套一套现成的“商城小程序”源码跑起来就算完最后文档和答辩都讲不清楚系统里为什么有那些表、那些状态。这个标题——Python uniapp 微信小程序自助购药药品网上商城系统第一眼就能看出它不是一个普通的花架子商城自助购药、多商家、发票、论文这四个关键词背后全是真实的业务取舍。这套系统本质上是带微信生态的 B2C 多商家商城只不过商品换成了药品核心链路从“浏览-下单-支付”延伸到了“处方药的合规流程、按商家拆单、按订单开票”。我打算把它彻底拆开按前端、后端、上线和论文四条线讲一遍帮你把这种带真实业务场景的项目在手里玩明白。1. 立项拆解一个药品商城到底在解决什么问题1.1 药品商城与普通商城的核心差异我刚看到这个标题的第一反应是这跟那种“仿京东商城”或者“水果生鲜小程序”完全不是一个量级的光是“药品”两个字就带出了一堆特殊业务属性。普通商城只要做好商品、分类、购物车、订单、支付这五件事就能跑药品商城却多出了非处方药OTC与处方药的区分、药品说明书、生产厂家与批准文号、库存批次效期、购买数量限制、合规提示这些信息维度。一个销售感冒灵的页面至少要把“功能主治、用法用量、禁忌、批准文号、生产企业、有效期”这几样说清楚否则这个商城在业务上就不成立。自助购药这个描述也很有意思。自助意味着用户全程不需要跟药师或客服对话自己搜、自己选、自己下单。为了让用户真的能“自助”起来前端的搜索和分类必须足够刁钻按病症搜头痛、发烧、腹泻按科室搜消化内科、皮肤科、耳鼻喉科按药品名或品牌搜还要支持模糊拼音首字母。初版很多同学只会做一个商品名 LIKE %关键词%结果搜“感冒”出来一堆乱七八糟的东西不是代码写错了而是数据建模阶段没把“用药需求”和“商品属性”拆开。发票和多商家这两个需求叠加之后系统的复杂度直接翻倍。多商家意味着平台不能直接按订单总额走单店铺逻辑必须支持 A 商家和 B 商家的商品在同一个购物车里结算时拆成多个子订单各自收款、各自发货、各自开票。发票模块则要求每个子订单都能独立申请开票抬头信息个人/企业、税号、邮箱、电子发票状态这些都得在库里落下。很多毕设项目把发票做成“下单自动生成一张 PDF”的静态页面那纯粹是糊弄事真正的发票模块应该支持抬头管理、开票申请、开票状态流转待申请、审核中、已开具、已发送并且和订单一一关联重复申请要有幂等控制。1.2 技术选型为什么是 Python 后端 uniapp 前端先说后端。标题里明确写了 Python那主流选择就是 Flask 或 Django 二选一。我自己在这个项目里更推荐 Flask 搭配 Flask-SQLAlchemy理由很实际药品商城这种业务的数据模型虽然多但都是标准 CRUDDjango 的 Admin、ORM、认证体系对这种场景来说偏重而且写起来“魔法感”太强答辩被问到“中间件怎么注册、信号量怎么传”很容易卡壳。Flask 轻、路由直观、每个接口的请求-响应链路一眼望到底对毕设同学来说既好写文章又好答问题。如果你对 FastAPI 的异步和自动文档感兴趣也可以换但要注意网上药店管理系统类的参考代码大多是 Flask 写或 Django 写的抄作业时适配成本低一些。再说前端。既然要跑在微信小程序里大多数人第一反应是用原生 WXML WXSS 开发但标题特意点出 uniapp说明它有刻意选型的成分。uniapp 的价值在于一套代码可以同时编译到微信小程序、H5、App并且它背后是 Vue 语法生态熟悉 Vue 的人上手极快。更重要的一点是编译到 App 端之后还能调用 plus.geolocation、plus.nativeUI 这些原生能力将来想在这个项目上加 GPS 定位找附近药店、扫码验真都不用重写前端。代价是你会多踩一点平台的兼容性坑这个在第五章我会用一整节说。1.3 项目目录与代码组织直接决定论文好不好写很多项目的代码是一坨的接口和页面混在一起十个文件里八个是复制粘贴改出来的。我强烈建议从一开始就把工程分成三块backendPython 后端、frontenduniapp 前端和 docs数据库设计、接口文档、论文素材。后端内部再按蓝图拆分模块比如用户模块、商家模块、药品模块、订单模块、发票模块、支付模块每个模块下放 model 和 api 两层。这样做的好处是论文里可以直接抄你的模块图测试计划也可以按模块逐项写“系统由六大功能模块组成”这句话一摆出来答辩老师的第一个问题就能被压住。前端页面不要全塞在 pages 根目录。首页、分类、购物车、我的这类高频页面放主包商家列表、全部评论、发票抬头管理、发票申请、订单详情、用药人管理之类的低频页面放分包。我在第四章会给出具体的分包配置这里先记结论不分包等代码量上来之后编译会直接报超限错误。2. 前端核心模块拆分与交互设计2.1 药品浏览、搜索与购物车的交互设计前端的首页一般包含搜索框、分类导航、药品轮播图和促销位。分类导航建议不要用一层平铺而是做成两层一级分类感冒用药、肠胃用药、皮肤用药、儿科用药、医疗器械、保健食品点击之后进列表页再按二级分类或品牌筛选。药品列表页的关键不只是筛选而是信息的优先级药品缩略图、通用名、品牌名、规格、价格、库存和“OTC/处方药”标识是一屏内必须出现的购买按钮反而可以弱化因为处方药需要先走审核流程普通药才能直接加购。购物车是一个在多商家场景下最容易被低估的地方。用户在购物车里勾选 A 商家的药和 B 商家的药点结算时前端不能简单地带着商品 ID 数组就往后端甩而是要把勾选商品按 merchant_id 分组每组生成一个子订单的临时数据后端再根据这些数据做订单拆分。这个分组逻辑写在 HBuilderX 控制台上看非常清楚实际开发时我见过一个同学把所有商品塞进一个订单里结果后端只能按同一商家发货逻辑处理商家信息互相覆盖发货地址全乱。搜索功能建议别只做一个 LIKE可以做成三层精确匹配药品通用名其次是模糊匹配商品名最后匹配症状关键字。比如说“999感冒灵”的通用名是“感冒灵颗粒”一个用户搜“感冒灵”的时候如果不能命中通用名而是只匹配商品名那么搜索结果里可能只出现“999”而搜不到其他牌子的感冒灵这在小程序这种面向普通用户的场景里是致命的。药品商城和书城不一样用户是带着症状来搜的不是带着准确商品名来的。2.2 微信登录与手机号绑定2023 年之后不一样了微信小程序的登录链路现在分成两个阶段wx.login 获取临时 code再把 code 交给后端换取 openid获取手机号则是用户点击一个 open-type 为 getPhoneNumber 的按钮拿到动态 code后端拿 code 调接口解密出手机号。以前获取手机号是免费的现在每个账号有成本限制很多项目接完才发现会报错或者被风控。毕设里建议做出完整的流程但前后端都加一个“开发环境模拟手机号”的开关这样答辩时既能展示真实流程又不会被审核或成本卡住。登录态这块我习惯用后端签发的自定义 token 而不是直接拿微信 session_key 当身份令牌。用 token 的好处是可以在后端控制过期时间也能在 token 里只存 user_id 和用户类型普通用户、商家管理员、平台管理员小程序端每次请求都往 header 里放 Authorization后端统一鉴权。在小程序里用户点“微信一键登录”后按钮的颜色要立刻有状态变化不然用户会手欠狂点短时间触发太多次 wx.login 接口会被微信限流表现为突然取不到 code。2.3 处方药与 OTC 的购买流程差异这一块最容易在答辩时被追问。真正的互联网药品交易对处方药有严格要求需要用户上传真实处方由执业药师审核后才能下单合规链路极其复杂。毕设项目不可能完整接互联网医院所以我们用“模拟审核 流程占位”的方式来做用户选择购买处方药时前端弹窗让用户填写用药人姓名、身份证号后四位、确诊疾病并上传处方照片后端把这些信息保存到 prescription 表订单先进入“待药方审核”状态平台管理员在后台审核通过后订单才流转到“待支付”。这个状态在订单状态机里必须存在否则整个业务模型是不自洽的。OTC 药品则可以直接加购支付但页面上要有“请按说明书使用”的安全提示。医疗器械和保健食品也可以走 OTC 流程数据模型里的 product 表加一个 sale_type 字段1-OTC 2-处方药 3-医疗器械 4-保健食品前端按类型渲染不同的购买按钮和提示框这样代码就不用每个页面写死 if 分支。这个字段几乎是论文里数据库设计章节的必画内容。2.4 uniapp 的条件编译与 manifest 配置uniapp 编译到微信小程序时很多能力是平台相关的。如果你在 App 端调用 plus.geolocation 定位或者在 H5 端调用 localStorage这些代码直接放在公共文件里就会被各个端一起编译真机运行发现报错后才一头雾水。解决办法是用条件编译注释块// #ifdef MP-WEIXIN // 只有微信小程序会执行的代码 wx.setNavigationBarTitle({ title: 药品商城 }) // #endif // #ifndef MP-WEIXIN // 除了微信小程序以外的端App、H5执行 uni.setNavigationBarTitle({ title: 药品商城 }) // #endifmanifest.json 里的配置直接影响打包结果。微信小程序 appid 要填成自己申请的真实 appid否则真机预览和上传代码都走不通。你还会在热搜词里看到 uniapp 微信小程序打包 source size 2612kb exceed max limit 2mb 这样的报错这就是典型的主包体积超限。除了把页面分包之外图片资源不要直接打包全部上传 CDN 或放静态服务器本地只留占位图。还有一个容易被忽略的点HBuilderX 菜单栏“运行”里要勾选“压缩编译”压缩后代码体积能少 20% 左右。3. 后端接口设计与多商家业务逻辑3.1 数据表结构一张表也别设计错好的数据库设计撑起半篇论文也撑起整个系统的可维护性。我下面给出一组核心表你可以直接拿去做基线再根据自己的功能增删。表名核心字段说明tb_userid, openid, nickname, avatar, phone, user_type, status用户表user_type 区分普通用户、商家管理员、平台管理员tb_merchantid, name, contact_person, contact_phone, address, status商家表一个商家可以挂多个店铺或直接就是店铺tb_categoryid, parent_id, name, sort, icon_url分类表支持两级分类tb_productid, merchant_id, category_id, generic_name, brand_name, approval_number, manufacturer, sale_type, price, stock, cover_img, detail_html药品商品表批准文号是药品的关键标识tb_skuid, product_id, spec, price, stock, weight同一药品可能有盒装、瓶装多个规格tb_cartid, user_id, product_id, sku_id, quantity, checked购物车表按用户维度存储tb_orderid, order_no, user_id, merchant_id, total_amount, pay_amount, status, invoice_status, receiver_info订单主表一个用户一次下单拆成多个商家订单tb_order_itemid, order_id, product_id, sku_id, quantity, price, amount订单明细表关联药品和优惠快照tb_prescriptionid, user_id, order_item_id, patient_name, disease_desc, image_url, audit_status处方审核表处方药下单前必填tb_invoice_applyid, apply_no, user_id, order_id, merchant_id, title_type, company_name, tax_no, email, amount, status发票申请表按订单粒度开票tb_addressid, user_id, name, phone, province, city, district, detail, is_default收货地址表订单主表里我特意放了 merchant_id两个字段提示你多商家拆单已经内建在数据结构里。很多初版设计把订单设计成纯用户维度一个订单关联一堆商品然后商品再去反查商家这样“订单属于哪个商家”就变成隐式逻辑后端查一次要 JOIN 三张表效率低不说还容易把 A 商家的商品发成 B 商家的货。3.2 多商家拆单与库存扣减的正确姿势先讲拆单的实现思路。前端提交购物车勾选商品时后端接口不仅要把订单拆开还要保证同一个订单号不能乱。我的做法是接收 shop_cart_ids 数组后先从 tb_cart 查出所有商品按 merchant_id 分组然后对每个商家生成一个订单号订单号用规则ORD 时间戳 两位商家序号再把订单明细插入 tb_order_item。事务要包住整个流程任何一个子订单插入失败所有订单全部回滚避免出现半单。这里有个新手容易踩的重灾区前端一次支付请求同时支付多笔子订单时微信支付金额是分单位后端计算 price * quantity 时要统一转成“分”而且要对每个子订单分别调用统一下单接口不能让前端把多个订单金额加在一起付一次。多商家商城的支付就是多笔独立支付前端循环调 uni.requestPayment 的风险是用户可能只支付了第一笔就退出所以订单状态必须做轮询展示已支付的子订单立即变“待发货”未支付的仍保持“待支付”。库存扣减我推荐“下单时校验 支付后真实扣减”的组合。下单时用SELECT stock FROM tb_sku WHERE id ?做乐观判断支付回调里再执行原子扣减result db.session.execute( text(UPDATE tb_sku SET stock stock - :num \ WHERE id :sku_id AND stock :num), {num: num, sku_id: sku_id} ) if result.rowcount 0: raise BizException(库存不足该商品已被抢空)这种写法能避免两个用户同时购买同一件商品时超卖。加一个行锁或者直接使用 SELECT ... FOR UPDATE 也可以但 UPDATE 影响行数等于 0 就抛异常的方案最直观论文里也很好解释。3.3 发票与资金流多商家发票到底怎么开发票模块在一个药品商城里的存在感很强因为企业客户团体购药是真实且高频的场景。普通用户确实不太关心发票但你可以做出一个发票抬头管理功能用户先录入抬头抬头分个人和企业两种企业抬头需要填税号申请开票时选择抬头、填写接收邮箱后端生成一条 invoice_apply 记录。多商家场景下发票申请必须绑定“某个子订单”而不是“整个购物车”。如果一个用户从 A 药店和 B 药店各买了药发票申请要分成两条开票金额分别是两个子订单的实付金额。否则一张发票对应两个税号在税务环节完全没法处理。前端在申请页直接按子订单展示一个订单一个申请按钮申请后状态变成“待审核”平台管理员在后台审核后点击“确认开具”状态变成“已开具”系统往邮箱发送一个带发票附件的模拟通知。还有一个重要的幂等处理用户疯狂点击申请开票不能让同一订单生成多条发票申请。最简单的方式是在发票表把 order_id 设成唯一索引一个订单只能有一张发票如果要支持多次申请那也要加一个 active 字段同一订单同时只能有一条 active 状态的申请。很多毕设项目的发票模块连这个都没考虑数据一多全是脏数据答辩时一旦被问“用户重复点击发票申请会发生什么”基本就稳不住。3.4 订单状态机设计订单状态必须由后端统一驱动而不是前端页面跳来跳去。我常用的状态集合状态值含义下一步操作PENDING_PRESCRIPTION等待处方审核管理员审核通过 → PENDING_PAYPENDING_PAY待支付用户支付 → PAIDPAID已支付/待发货商家发货 → SHIPPEDSHIPPED已发货/待收货用户确认收货 → COMPLETEDCOMPLETED已完成可申请发票/售后CANCELLED已取消用户取消或超时关单REFUNDING退款中审核退款 → REFUNDED每个状态流转都要写进 tb_order_status_log 表记录是谁在什么时间把订单从什么状态改到什么状态。这个小表在开发时你可能会觉得多余但等到联调时排查问题你会发现它比 DEBUG 日志还好使。答辩时“订单状态可追溯”也是一个非常加分的点老师一听你的系统有完整状态日志基本就不再纠结业务复杂度的提问了。4. 核心实战从 0 到 1 的落地流程4.1 开发环境准备环境准备阶段的优先级要分清楚。第一步肯定是搭 Python 后端因为小程序页面没有接口支撑就是空壳。我推荐用虚拟环境 requirements.txt 的方式python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install flask flask-cors flask-sqlalchemy pymysql requests数据库建议用 MySQL如果本机没有 MySQL 服务至少也要用 SQLite 把结构先跑通后期生产再切。Windows 上安装 MySQL 容易踩乱码和权限的坑配置连接串时注意加 charset 参数。小程序开发工具和 HBuilderX 都要从官方渠道下载别用社区里一堆“破解版”“绿色版”小程序上传代码时需要开发者工具版本匹配旧版本经常连不上最新的微信客户端。uniapp 项目的创建可以直接在 HBuilderX 里选“uni-ui 项目”或 Vue 3 模板。强烈建议初始创建时勾选“uni-ui 组件库”这样列表、卡片、表单这些组件就不用自己写了。如果创建项目后你发现跑不起来大概率是 node 版本和 HBuilderX 内置 webpack 版本冲突把本机 Node 换到 LTS 版本基本能解决。4.2 从 Flask 蓝图开始搭建后端骨架目录结构可以这样安排backend/ ├─ app.py ├─ config.py ├─ models/ │ ├─ user.py │ ├─ product.py │ ├─ order.py │ └─ invoice.py ├─ api/ │ ├─ auth.py │ ├─ product.py │ ├─ order.py │ └─ invoice.py └─ requirements.txtapp.py 里做三件事初始化 Flask、加载配置、注册蓝图。后面每次新增模块只需要在 api 下新增一个文件再在 app.py 里多注册一个蓝图不会把路由全堆在一个文件里。config.py 里把数据库连接串和密钥单独存放让论文的“系统环境配置”章节可以直接引用。4.3 后端接口示例登录、下单、开票三段核心代码先写用户登录接口这也是小程序的第一个接口。前端的 wx.login 拿到 code 后发到后端后端拿 code 去微信的 jscode2session 接口兑换 openidapp.route(/api/auth/login, methods[POST]) def login(): code request.json.get(code) resp requests.get( https://api.weixin.qq.com/sns/jscode2session, params{ appid: app.config[WX_APPID], secret: app.config[WX_SECRET], js_code: code, grant_type: authorization_code }, timeout5 ).json() openid resp.get(openid) if not openid: return jsonify({code: 40001, msg: 登录失败}) user User.query.filter_by(openidopenid).first() if not user: user User(openidopenid, nickname微信用户, user_type1) db.session.add(user) db.session.commit() token generate_token(user.id) return jsonify({code: 0, data: {token: token, user_id: user.id}})注意这句话openid 一定不要返回给前端再传给后端。正确做法是后端从微信接口拿到 openid 后自己维护用户身份前端存 token 就够了。很多同学把 openid 直接暴露给前端是因为调试方便但这是安全大忌论文里提一句“openid 仅在后端保存不经过前端传输”特别合适。下单接口要体现拆单逻辑这里给一个关键片段。先读购物车按商家分组再在各分组内生成子订单def create_orders(user_id, cart_ids, receiver_info): checked_items Cart.query.filter(Cart.id.in_(cart_ids), Cart.user_id user_id).all() grouped {} for item in checked_items: sku Sku.query.get(item.sku_id) merchant_id sku.merchant_id grouped.setdefault(merchant_id, []).append(item) orders [] for merchant_id, items in grouped.items(): order Order( order_nogenerate_order_no(merchant_id), user_iduser_id, merchant_idmerchant_id, statusPENDING_PAY, receiver_infojson.dumps(receiver_info) ) order_amount 0 for it in items: amount it.quantity * it.price order_amount amount db.session.add(OrderItem( order_idorder.id, product_idit.product_id, sku_idit.sku_id, quantityit.quantity, priceit.price, amountamount )) db.session.delete(it) # 购物车同步删除 order.total_amount order_amount orders.append(order) db.session.add_all(orders) db.session.commit() return orders这里用grouped.setdefault(merchant_id, []).append(item)就能干净地完成分组。真正写代码时别在拿数据之后又嵌套循环的调数据库能一次查出商品带出商家信息就一次查出来不然下单接口会被你写成慢 SQL 表演现场。然后看开票接口。核心是幂等app.route(/api/invoice/apply, methods[POST]) def apply_invoice(): uid get_current_user_id() order_id request.json.get(order_id) title_type request.json.get(title_type) company_name request.json.get(company_name, ) tax_no request.json.get(tax_no, ) email request.json.get(email, ) order Order.query.filter_by(idorder_id, user_iduid).first() if not order or order.status ! COMPLETED: return jsonify({code: 40010, msg: 订单不可开票}) exists InvoiceApply.query.filter_by(order_idorder_id, active1).first() if exists: return jsonify({code: 40011, msg: 该订单已申请过发票请勿重复申请}) inv InvoiceApply( apply_noINV datetime.now().strftime(%Y%m%d%H%M%S) str(uid), user_iduid, order_idorder_id, merchant_idorder.merchant_id, title_typetitle_type, company_namecompany_name, tax_notax_no, amountorder.pay_amount, emailemail, statusPENDING ) db.session.add(inv) db.session.commit() return jsonify({code: 0, data: {apply_no: inv.apply_no}})这段代码里最值得学习的是“先查状态再查重复最后插入”。你不先确认订单已完成就想开票那发票金额都不知道对不对。另外邮箱格式校验可以用正则税号长度校验也写上否则一条脏数据下去后端管理员审核的时候真的会骂人。4.4 联调与真机预览的关键操作前后端联调时最烦的问题是域名校验。微信开发者工具默认会拦截非 https 的请求你有两个选择正式把后端部署到服务器上配好 HTTPS或在开发工具“详情 - 本地设置”里勾选“不校验合法域名”。开发阶段勾选不校验合法域名就行但论文里的部署章节一定要写正式域名和 Nginx 反向代理的步骤。真机预览时前端要拿着后端给的 token 去请求数据如果 401 了大概率是 token 过期或者 header 名称对不上。前后端约定好 header 的名字例如 x-token 或者 Authorization: Bearer xxx然后在后端的请求拦截器里统一校验。联调阶段我习惯在后端打印每个请求的 method、path 和 status_code配合 uni.request 的 success 回调十分钟就能定位一个 bug。5. 上线路上的坑实测排查与避坑清单5.1 小程序主包超 2MB分包策略是最优解uniapp 项目编译到微信小程序时报 source size 2612kb exceed max limit 2mb这是每个做 uniapp 小程序必踩的一课。解决方案不是压缩图片而是做分包。在 manifest.json 或 pages.json 里配置 subPackages{ pages: [pages/index/index, pages/category/category, pages/cart/cart, pages/my/my], subPackages: [ { root: pages/detail, pages: [product-detail/product-detail] }, { root: pages/order, pages: [order-list/order-list, order-detail/order-detail] }, { root: pages/invoice, pages: [invoice-list/invoice-list, invoice-apply/invoice-apply] } ] }配置分包的逻辑用户进入小程序首先打开的是主包页面所以首页、分类、购物车、我的这四个 Tab 页留在主包其他页面全部放子包。子包里的页面之间跳转没问题但从子包跳回主包也没问题微信会自动加载对应包。这样配置完之后你还会顺手解决一个搜索问题微信搜索收录时分包页面也能被索引到对后续小程序搜索流量有好处。除了分包还要把本地的图片资源能少放就少放。详情页的图片应该都用云存储或对象存储不要在项目里放几十张 200KB 的药品图。编译时勾选“压缩代码”也能减体积但代码压缩只是辅助真正决定生死的是包结构。5.2 微信登录、手机号与真机预览的乱象小程序获取手机号在真机预览和测试版时经常不稳定表现为用户在手机上点“获取手机号”按钮没反应控制台报getPhoneNumber:fail或invalid code。第一个可能原因是你的小程序账号还没有通过认证手机号快速验证组件要求小程序已经完成微信认证第二个原因是后端解密参数写错了前端拿到的 code 要配合 session_key 才能解密而 session_key 是你用 wx.login 的 code 换来的这两个 code 不能混用。开发时我建议后端写一个调试开关比如在 config 里设DEV_GET_PHONE True前端调用接口时传一个模拟手机号 13800138000绕过微信的 getPhoneNumber。等答辩前几天再切回真实链路省下的时间至少够你改十个 bug。很多人在联调阶段死磕手机号解密实际上这不是他们的核心链路纸面设计里把真实流程写清楚开发时用模拟环境完全够用这也是我在这个项目里一直提倡的。5.3 发票模块的金额单位陷阱发票模块最隐蔽的坑不是逻辑而是单位。你在数据库里存 12.50 元前端显示 ¥12.50微信支付接口需要 1250 分发票接口又需要 12.50 元一旦前后端有人没注意单位就会出现“订单实付 12.50 元开发票时却成了 1250 元”这种离谱事故。我的建议是数据库统一用 Decimal 类型存“元”后端只传元给小程序小程序展示也是元只有调用微信支付时将元转成分。每个接口都自己约定单位而不是临时转换可以避免 90% 的金额 bug。另外税号校验也要认真对待。企业抬头时税号的格式是 15 位或 18 位数字和大写字母的组合你可以用简单的正则做校验但千万别只校验非空。邮箱格式同理。审核端也要显示申请人的邮箱和抬头管理员多次核对后再确认开票。5.4 常见问题速查表现象排查方向解决思路小程序编译报主包超限主包 pages 太多页面拆入分包图片放 CDN登录报 code 无效多次调用 wx.login 或 code 已过期登录成功后立即把 code 传给后端一分钟内使用开发工具请求失败未关闭域名校验或端口未开详情-本地设置-勾选不校验合法域名真机预览看不到登录状态token 没有持久化登录成功后将 token 存入 uni.setStorageSync订单支付回调重复微信重复推送通知回调里做幂等判断已处理状态直接 return success发票重复申请没有唯一约束或 active 判断添加 order_id 唯一索引 active 字段uniapp 不打印日志控制台过滤或条件编译屏蔽了日志检查 console 输出级别真机用 vConsole 查看5.5 药品类目与上线合规意识最后必须说合规虽然这是毕设或者学习项目但只要你体验过“小程序提交审核被驳回”你就知道这类目有多严格。药品销售类小程序在上线时需要提交对应的开放类目并按要求提供资质凭证。个人主体基本没有操作空间企业主体也需要相应资质才能开通真实交易。所以做这个项目时尽量明确项目定位是“毕业设计/技术学习演示”后台可以设置一个演示模式开关不接入真实的支付和真实的开票对接避免审核卡在资质上。论文的“系统实现”这一章也建议用“由于资质限制本系统在开发环境中模拟了支付和开票流程真实生产环境需对接合规服务”这种表述既不回避责任又保护自己。6. 论文与答辩素材把工程做成模板6.1 论文结构怎么搭最稳毕业设计论文不要真的从零开始写而要跟着工程走。我推荐五个章节第一章绪论写药品零售行业和微信小程序的场景背景、国内外研究现状第二章需求分析画用例图、列功能需求和非功能需求第三章系统设计画总体架构图、模块拆分、数据库 E-R 图和表结构设计第四章系统实现按前端页面和后端接口两条线逐个展示功能和代码片段第五章系统测试列功能测试用例表、兼容性测试结果和问题修复记录。这样的结构最贴合大多数学校毕设模板而且每一章都能在这套代码里找到对应的素材。6.2 测试用例这么写才像“做过的”一个项目如果测试章节只有“首页加载正常”这种空话答辩老师十秒钟就看穿。我建议你按模块写好关键用例例如登录模块未注册用户首次登录自动创建账号二次登录直接返回 token购物车模块勾选不同商家商品后提交订单返回多个子订单号处方药模块未上传处方照片时无法提交订单发票模块同一订单重复点击申请仅生成一条申请记录支付回调同一支付通知连续发送两次订单金额只入账一次。测试结果表至少要有 20 条以上覆盖正常流程、边界条件、异常输入。弱网测试可以写“通过开发者工具 Network 面板模拟慢速网络页面在 3G 环境下可正常加载核心信息”这种细节一说出来答辩老师会觉得你真的在一线调试过。6.3 素材清单现在就积累别等最后补论文里需要的图不是最后临时画的。从现在开始就存这些素材前端每个核心页面的截图、后端接口文档的导图、数据库表关系图、订单状态流转图、登录时序图、发票申请时序图、部署环境结构图。有条件的话把每个核心流程图在画图工具里重绘一遍矢量图插入论文比截图清晰得多。代码片段不用多每章挑 2 到 3 段重点展示就行比如 Flask 的登录接口、拆单逻辑、分包的配置、发票幂等判断这些片段在你写论文时直接复制过来排版就完事。答辩还有一个灵魂三连为什么不用 Spring Boot多商家拆单会不会产生一致性问题处方药在系统里怎么保证合规答案分别是Python 的 Flask 在中小型业务快速开发和教学场景下具有足够表达能力拆单用数据库事务保证一致性同时配合订单状态日志可追溯处方药流程仅作为教学演示生产环境需对接具有资质的互联网医院服务并接受监管。提前把这三个问题想透远比临时背稿有用。我个人做过、也帮人评审过不少这种带真实业务的中型项目最大的体会是这种项目的价值永远不在“会跑”而在跑起来之前你对业务逻辑想的有多透。药品、发票、多商家这三个词一叠加随便拉出一个功能都能在面试或者答辩现场聊十分钟。你完全可以在这套基线上升级很多花样加一个地理围栏实现“附近 3 公里药店配送”、加一个会员积分和满减券、把发票对接真实电子发票服务商。最后再分享一个小技巧开发时顺手在 README 里记录每个功能模块的完成日期和踩坑摘要等你动笔写论文或者更新简历时你会发现这些随手记的东西比任何记忆都可靠。
返回列表