ARTICLE DETAIL

资讯详情

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

自助购药小程序源码部署与二次开发指南:从数据库到前端全链路跑通

自助购药小程序源码部署与二次开发指南:从数据库到前端全链路跑通 简介基于Java与SSM框架的自助购药小程序完整源码可用于毕业设计、课程设计和小程序开发实战。项目实现药品搜索、浏览、下单、支付等核心流程覆盖首页、个人中心、用户管理、商家管理、药品信息管理、药品分类管理、发票信息管理及系统管理模块前端为小程序后端采用B/S架构SSM整合并配套MySQL数据库。资源包共1319个文件压缩后约22.55MB以Java源码、Vue组件、JavaScript、微信小程序wxml/wxss及图片素材为主要构成附带SQL数据库脚本、Maven配置和部署批处理文件目录完整便于直接导入和运行。当前已有57人学习/下载可作校园或社区自助购药平台的参考样例。项目完整呈现了从用户端到管理端的业务逻辑既能帮助理解电商类小程序的分层设计也为SSM框架整合、数据库表设计及微信开发者工具部署提供了可复用范本。1. 自助购药小程序源码包先想清楚解开 zip 后你会拿到一个什么系统拿到“基于小程序的自助购药小程序源代码java小程序mysqlLW.zip”这类压缩包我的习惯不是急着解压而是先想清楚里面装了什么、跑起来要几步、能不能真下单。这种包一般是一套毕业设计或课程设计级别的完整工程微信小程序做用户端Java 负责接口与业务逻辑MySQL 存用户、药品和订单数据LW 则是配套的论文与设计文档。自助购药的核心不是做个药房展示页而是把“选药、加购物车、下单、库存扣减”这条链路完整打通。下面按部署节奏把它拆开先讲系统怎么拆、数据怎么设计再给三步跑通步骤最后落到问题排查和二次改造。适合准备毕设、接手二手源码做二次开发或者想快速搭一个药店小程序原型的人。2. 自助购药系统的业务边界与数据模型先从三个问题谈起一批源码拿到手先别急着打开代码到处翻。我的习惯是先问三个问题谁来买、能买什么、买了之后的状态怎么流转。回答完这三个问题代码里哪些是核心、哪些是凑数页面就一目了然。自助购药场景里买家是附近居民商品是感冒药、肠胃药这类标品购买后的状态流转是“待支付→已支付→已取药”。大多数能跑的源码包会把角色收敛成用户与管理员两端Java 后端提供接口小程序端只负责页面与交互MySQL 管持久化。下面按这个思路把功能清单、数据流和表结构讲透。2.1 从“选药、下单、取药”反推最小功能集自助购药和外卖买菜类小程序的差异在于它不依赖骑手配送更多是到店自提或自助售药机取货。所以最小功能集不是越多越好而是紧贴六件事药品分类浏览、药品详情、购物车、提交订单、库存扣减、订单状态查询。分类浏览里常见做法是按感冒用药、肠胃用药、外用药等大类做一级列表再叠加一个关键词搜索。药品详情页注意用 wx.setNavigationBarTitle 动态设置页面标题把药品名称同步到导航栏用户返回列表时不迷路这个交互细节在源码里经常被忽略。购物车在自助购药场景里几乎都是小程序本地维护数量增减不需要每次都请求后端只在结算时把完整清单传上去。这个设计在小程序里很省流量弱网时体验更好。订单状态一般是 0 待支付、1 已支付、2 已取药、3 已取消四态。支付如果没接微信支付就做成模拟支付点“确认支付”后调后端接口把状态置为已支付。注意模拟支付的判定不能写死在前端后端必须单独提供一个支付确认接口否则用户改一下请求参数就能白拿药这是安全性上最不值得省的一环。2.2 前后端的数据流拆解登录、token 与购物车按下单这个动作拆数据流向大致是五步wx.login 拿到临时 code 传给后端的 /user/login 接口后端用 code 换 openid 并落库返回一个自定义 token小程序把 token 放进后续请求的 header后端通过拦截器校验 token结算时小程序把购物车数据整体提交到 /order/create。这条链路里有个典型坑是 code 只能换一次而且有效期只有 5 分钟。前端如果连续触发两次登录第二次必定失败所以登录按钮要加锁请求未返回时不能重复触发。后端拦截器校验 token 失败时统一返回 401小程序收到 401 后清掉本地 token 并重新执行 login。至于用户中途离开小程序购物车数据还留在本地缓存里下次进来看一眼就能继续下单不需要后端为此单独维护一张购物车表。如果需要提示用户有未支付订单在小程序 onHide 事件里做一次提示就够了。token 放 header 而不是 cookie是微信小程序天然的习惯后端不用处理跨域 cookie简单直接。2.3 用户、药品、订单三张核心表的建表姿势网上很多自助购药源码的表结构大同小异差异主要在字段命名和是否冗余。这里给出一组能支撑完整业务的建表 SQL按这套结构改也能适应大多数需求CREATE DATABASE IF NOT EXISTS pharmacy DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE pharmacy; CREATE TABLE user ( id INT NOT NULL AUTO_INCREMENT, openid VARCHAR(64) NOT NULL COMMENT 微信openid, nickname VARCHAR(50) DEFAULT COMMENT 昵称, phone VARCHAR(20) DEFAULT COMMENT 手机号, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_openid (openid) ) ENGINEInnoDB COMMENT用户表; CREATE TABLE medicine ( id INT NOT NULL AUTO_INCREMENT, category_id INT NOT NULL COMMENT 分类id, name VARCHAR(100) NOT NULL COMMENT 药品名, spec VARCHAR(100) DEFAULT COMMENT 规格如0.25g*24片, price DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT 售价单位元, stock INT NOT NULL DEFAULT 0 COMMENT 库存, prescription_flag TINYINT NOT NULL DEFAULT 0 COMMENT 0非处方 1处方, pic_url VARCHAR(255) DEFAULT COMMENT 图片路径, status TINYINT NOT NULL DEFAULT 1 COMMENT 1上架 0下架, PRIMARY KEY (id), KEY idx_category (category_id) ) ENGINEInnoDB COMMENT药品表; CREATE TABLE order_info ( id BIGINT NOT NULL AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL COMMENT 订单号, user_id INT NOT NULL COMMENT 用户id, total_amount DECIMAL(10,2) NOT NULL COMMENT 订单总金额, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待支付 1已支付 2已取药 3已取消, remark VARCHAR(255) DEFAULT COMMENT 用户备注, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, pay_time DATETIME DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no) ) ENGINEInnoDB COMMENT订单主表; CREATE TABLE order_item ( id BIGINT NOT NULL AUTO_INCREMENT, order_id BIGINT NOT NULL COMMENT 订单id, medicine_id INT NOT NULL, medicine_name VARCHAR(100) NOT NULL COMMENT 冗余药品名, price DECIMAL(10,2) NOT NULL COMMENT 下单时单价, quantity INT NOT NULL COMMENT 数量, PRIMARY KEY (id), KEY idx_order (order_id) ) ENGINEInnoDB COMMENT订单明细表;这段 SQL 里有三个值得留意的点。第一金额全部用 DECIMAL(10,2)不用 float 或 double因为浮点在累加时会丢精度订单总额差一分钱都会引来用户投诉。第二order_item 里冗余了 medicine_name 和 price这是有意为之商品改名或调价后历史订单依然保留下单那一刻的快照。第三user 表的 openid 加了唯一索引同一个微信号不会产生两条用户数据后端按 openid 做 insert or update 就很省事。如果你拿到的源码里没有 order_item 表只有一张订单表存了商品名快照那说明它不支持一笔订单买多个药品。自助购药场景里合并结算很常见建议还是拆成主表和明细表长期维护更顺手。2.4 管理端闭环药品上下架与订单状态推进管理端在源码包里通常和 Java 后端放在同一个工程只是用 /admin 前缀区分路由页面上调后端接口改表数据就能完成闭环。药品上下架很简单把 medicine 表的 status 从 1 改成 0小程序端列表接口查询时自动过滤掉下架商品。订单状态推进的核心是审核人员点击“已取药”后后端把 order_info.status 从 1 改为 2用户端“我的订单”页面随即显示已完成。不需要一开始就上 Spring Security 这类重量级权限框架管理端接口加一个校验 admin token 的拦截器就够用。等后面需要区分库管、药师、店长多个角色时再引入 JWT 和角色表。这也是我把这个系统称为“最小可复现”的原因表不多角色不多接口控制在十几个刚好够把闭环走完又不至于让新手淹没在代码里。3. 用 MySQLJava小程序跑通完整链路最小可复现操作步骤从 zip 压缩包到能下单的系统顺序很重要先落库、再起后端、最后开小程序。倒过来的话最常见的状态是小程序页面一片空白而后端日志全是数据库连接错误。整个启动过程可以拆成三个步骤每一步都给出需要改动的配置和验证方法。3.1 初始化 MySQL建库、导表、准备演示数据如果本机还没装 MySQL安装时尽量一次到位选 5.7 或 8.0 版本比如常见的 5.7.44字符集选 utf8mb4端口保持默认 3306root 密码设置成你记得住的。安装完成后用命令行或 Navicat 连接执行第 2 章里的建表脚本。也可以把脚本存成 pharmacy.sql然后在 mysql 客户端里一次性导入mysql -uroot -proot -e source /path/to/pharmacy.sql这条命令里-u 指定用户-p 指定密码中间不留空格。source 是 mysql 客户端的导入命令路径里尽量不要带中文和反斜杠在 Windows 下建议先把 SQL 文件放到 D:/sql/pharmacy.sql 这种干净路径避免解析问题。建库之后还要插入演示数据不然小程序端分类页全是空的INSERT INTO category (id, name) VALUES (1, 感冒用药), (2, 肠胃用药), (3, 外用药), (4, 营养补充); INSERT INTO medicine (category_id, name, spec, price, stock, prescription_flag) VALUES (1, 感冒灵颗粒, 10g*9袋, 18.50, 100, 0), (1, 布洛芬缓释胶囊, 0.3g*20粒, 25.00, 80, 0), (2, 健胃消食片, 0.8g*32片, 12.00, 60, 0), (3, 创可贴, 20片装, 8.90, 200, 0);插入后执行这条 SELECT 做验证SELECT id, name, price FROM medicine ORDER BY id;如果 name 返回问号说明字符集没生效需要改 my.ini 的 [mysqld] 段设置 character-set-serverutf8mb4然后重启 MySQL 服务再重新导入。这种中文乱码在 Windows 上很典型不用怀疑代码基本都是字符集问题。演示数据里为什么选感冒灵和布洛芬这两类因为属于非处方药自助购药流程里不需要处方审核适合跑通 demo。如果源码带了 prescription_flag 字段说明设计了处方药标识可以在详情页把处方药设为“仅展示不可下单”避免没有药师审核就卖出处方药这点在真实交付时是底线。3.2 启动 Java 后端改配置、跑日志、验证端口Java 后端如果是 Spring Boot MyBatis 的 Maven 工程解压后用 IDEA 导入等依赖下载完成。不要急着点 Run先打开 src/main/resources/application.yml核对下面几个配置项server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/pharmacy?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true wx: appid: 你的小程序appid secret: 你的小程序secreturl 那串参数不是拼着好看的。useUnicode 和 characterEncodingutf8 保证中文字段不乱码serverTimezoneAsia/Shanghai 解决 MySQL 8.0 和 JDBC 的时区冲突useSSLfalse 和 allowPublicKeyRetrievaltrue 绕过 MySQL 8.0 默认 SSL 带来的公钥获取报错。这三组参数在 MySQL 5.7 和 8.0 上都适用别删。wx.appid 和 wx.secret 需要去微信公众平台小程序账号里找后端要调微信的 jscode2session 接口时才用得上。改完配置在项目根目录执行mvn spring-boot:run看到 Tomcat started on port(s): 8080 就是启动成功。如果报 Access denied for user检查用户名密码报 Unknown database说明建库语句没执行先回到 3.1 补库。这两个错误占后端启动失败的八成。3.3 导入小程序前端开发者工具、BASE_URL、登录态微信开发者工具选择导入项目目录指向源码包里的小程序前端目录。AppID 可以先填测试号本地调试不受影响要真机预览就必须换成自己的小程序 AppID。导入后打开 app.js确认接口地址指向本机后端const BASE_URL http://localhost:8080/api; function request(path, method, data) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL path, method: method || GET, data: data || {}, header: { token: wx.getStorageSync(token) }, success(res) { if (res.data.code 0) { resolve(res.data.data); } else if (res.data.code 401) { // token失效重新登录后重试 wx.removeStorageSync(token); login().then(() request(path, method, data)).then(resolve).catch(reject); } else { reject(res.data); } }, fail: reject }); }); }这段代码把 wx.request 包了一层 Promise统一注入 token并处理了 401 重新登录的逻辑。注意 res.data.code 是后端业务码不是 HTTP 状态码后端可能返回 HTTP 200 但 code 为 1 表示业务异常前端不能只判断 HTTP 状态。本地调试时小程序默认不允许请求 http://localhost。在开发者工具右上角“详情→本地设置”勾选“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”。注意这只是开发环境的豁免真机预览时必须到微信公众平台的“开发管理→开发设置→服务器域名”里配置 request 合法域名且要求是 HTTPS。域名没配好真机打开时所有请求都是 request:fail这是最常见的翻车现场。3.4 看接口请求从哪里入手开发者工具 Network 面板与抓包小程序端调试接口我一般优先看开发者工具自带的 Network 面板每个请求的 url、状态码、请求头、响应体都列得很清楚。遇到“请求到了后端但数据不对”可以在这个面板里直接复制请求 url用 Postman 或 curl 重放排除小程序环境干扰。想看更细的链路也可以借助 Charles 这类抓包工具观察 HTTPS 流量但日常排查先用 Network 面板就够别一上来就上重型工具。如果后端返回了非 JSON 的 HTML 错误页Network 面板里响应体是一片乱码这时候后端控制台日志才是关键。所有接口排查我都遵循一个原则先确认请求到没到后端再谈后端返回对不对。这个顺序定下来调试效率能高出一截。4. 自助购药系统的常见问题与排查域名、登录、并发、金额四大坑这一章是部署和代跑各种源码包时的排错笔记按“现象→原因→解决”写可以对症直接定位。4.1 页面请求全部失败request:fail 与后端 500现象小程序里点登录或打开药品列表toast 提示网络异常控制台报 request:fail。原因两个方向。一是开发工具没勾选“不校验合法域名”导致 localhost 被拦截二是后端接口返回的不是合法 JSONwx.request 虽然拿到了 HTTP 响应但解析结果不符合预期前端把这种情况当成失败处理。解决先看后端控制台有没有收到请求。没收到就检查域名校验开关收到了就看返回状态码500 说明后端代码或 SQL 有错。这个二分法一分钟就能定位最怕两边同时排查越查越乱。4.2 登录接口报错code 只能换一次与 appid 不一致现象首次登录能成功再点登录就报 invalid code 或 errcode 40029。原因wx.login 拿到的 js_code 是临时凭证有效期 5 分钟且只能用一次。前端如果写了两处登录调用比如页面 onLoad 调一次、点击按钮又调一次第一个已经把 code 用完第二个必然失败。解决给登录动作加锁响应返回前禁止重复调用。同时在后端日志里打印 wx.appid 的前几位和小程序后台核对。如果 appid 和 secret 不匹配调用微信接口会返回 errcode 40125这类错误在日志里非常显眼不用猜。4.3 库存超卖并发扣减的经典竞态现象两个用户同一秒提交购买同一款药品都提示下单成功最后库存变成负数。原因大多数源码包写的是“先查库存再更新库存”两条 SQL 之间存在时间窗口。用户 A 查到库存 10用户 B 也查到 10A 扣减成 9B 再扣减成 8等于超卖了一次。解决改成一条原子 UPDATEUPDATE medicine SET stock stock - #{quantity} WHERE id #{medicineId} AND stock #{quantity};这条语句在 MySQL 里会锁住命中行只有库存足够时才扣减。后端拿影响行数等于 0 就抛异常回滚订单等于 1 才继续生成订单。这也是商城类项目里最常用的防超卖写法自助购药同样适用。4.4 MySQL 8.0 连接错误SSL 与时区报错现象后端启动时抛 Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException提示 serverTimezone 值不对或者提示 Public Key Retrieval is not allowed。原因MySQL 8.0 默认的认证插件是 caching_sha2_passwordJDBC 驱动需要获取公钥做加密通信同时数据库时区没显式指定JDBC 拿系统时区和 MySQL 会话时区对比对不上就抛异常。解决JDBC URL 加上 useSSLfalseallowPublicKeyRetrievaltrueserverTimezoneAsia/Shanghai。老项目如果仍用 com.mysql.jdbc.Driver换成 MySQL 8.0 驱动后要改成 com.mysql.cj.jdbc.Driver。改完重启基本就消停了。4.5 药品列表加载更多失效分页参数没有自增现象页面滑动到底部列表永远只有第一页或一直转圈不再加载。原因小程序端 onReachBottom 里 page 变量没有自增后端收到的始终是第 1 页或者后端返回的 total 被前端忽略hasMore 逻辑判断死掉。解决在列表页维护 page 和 hasMore 两个变量。每次请求成功后把新数组 concat 到原数组尾部不要用赋值返回条数小于 pageSize 时把 hasMore 置为 false。这样“加载更多”才能持续翻页。这套逻辑在小程序商城类项目里可以直接复用和自助购药药品列表的场景完全一致。5. 从“能跑”到“能交付”验证步骤、改造方向与版本习惯5.1 三步验证全链路接口、库存、订单状态跑通之后别急着在页面里点来点去用命令行验证反而更快。按顺序执行三个 curlcurl -X POST http://localhost:8080/api/user/login -H Content-Type: application/json -d {code:test-code} curl -X GET http://localhost:8080/api/medicine/list?page1pageSize10 curl -X POST http://localhost:8080/api/order/create -H Content-Type: application/json -d {medicineId:1,quantity:2}第一个接口如果返回 token说明后端到数据库的链路正常微信配置至少没有断在模拟层。第二个接口返回药品列表和 total说明分类和药品数据正常。第三个接口返回订单号后去数据库查 order_info、order_item再回头查 medicine.stock 有没有扣减。三步走完这个系统才真正具备交付条件也符合 Java 开发人员在面试时被追问项目细节的基本素养。5.2 值得继续投入的三个改造方向如果要把这套代码拿去落地我一般会顺着三个方向改。第一给库存表加一个预警阈值字段低于阈值时管理端弹出补货提醒避免畅销药品无感缺货。第二订单完成生成二维码取药时用 wx.scanCode 扫码核销把已支付推到已取药操作可追溯。第三如果后续想同时出安卓和 iOS 包把原生小程序迁移到 uniapp 是个方向后端接口协议保持不变前端只重写页面层。这里面最怕的是为了省事把后端也推倒重来最后越改越乱。如果以后想往多商户商城那一类规模发展这套订单结构还扛得住吗这个要诚实说扛不住。多商户需要引入商户表、分账字段、平台佣金和结算单那时候可以参照更复杂的商城源码来设计但自助购药的价值在于场景简单、边界清晰特别适合作为第一版跑通业务。这个项目写进 java 开发面试的自我介绍时可以讲清楚订单状态机、库存扣减、微信登录三个点比背一堆 java 基础题目更容易让面试官接话。我习惯在动手改造前先把原始 zip 压缩包在网盘或移动硬盘里存一份每改一次代码就往 Git 仓库提交提交前打一个 tag。这样哪怕改到一半发现思路不对也能回到上一个可用版本不给自己留后悔药。代码管理这件事做得越早返工成本越低。希望帮到你。本文还有配套的精品资源点击获取
返回列表