ARTICLE DETAIL

资讯详情

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

微信小程序+SSM农产品销售平台实战源码解析

微信小程序+SSM农产品销售平台实战源码解析 简介这是一套完整的微信小程序农产品销售平台实战项目源码面向前端与全栈开发者尤其适合学习小程序Java后端SSM框架MySQL数据库协同开发的中初级工程师。项目涵盖用户端与管理后台双视角功能用户可完成注册登录、浏览首页/农产品/个人中心管理员可进行农产品、分类、订单、用户等10余类模块的全流程CRUD操作具备真实电商系统典型架构特征。资源包共1195个文件以166个JS逻辑文件、133个Vue组件、127个Java后端代码、231个PNG/SVG图标及80个WXML/WXSS页面样式文件为主辅以SQL脚本、配置文件与批处理脚本如install.bat/run.bat结构清晰、开箱即用压缩包仅14.86MB。已有488人学习下载提供完整可运行工程、模块化目录结构、前后端分离实现范例及常见微信小程序调试排错参考是快速掌握小程序商业项目落地的优质实践样本。1. 这不是又一个“Hello World”小程序一个能真上架、真走通订单闭环的农产品销售平台源码为什么值得你花20分钟拆开看你见过太多“微信小程序源码”——点开是空荡荡的app.js、三行console.log、首页只有一张轮播图加两行文字连登录按钮都绑不上事件。但这份微信小程序开发项目实例-农产品销售平台(源码).zip不是Demo是实打实跑在微信开发者工具里、后端用SSMSpringSpringMVCMyBatis搭在本地Tomcat、MySQL存着真实商品和订单数据的完整业务系统。它不教你怎么写wx.showToast而是直接给你一套「用户扫码进店→浏览分类→加购→微信支付→管理员后台发货→订单状态自动流转」的全链路代码骨架。尤其适合两类人一是Java后端想补全小程序前端能力的工程师二是高校课程设计/毕设需要可演示、可答辩、可改写、不翻车的实战项目。它没用uni-app或Taro就是原生WXMLWXSSJS所有接口调用、token管理、分页逻辑、表单校验都写死在.vue文件里注意这是Vue风格的WXML结构非uni-app但命名和组织方式高度接近意味着你能一眼看清微信小程序与Java后端如何通过RESTful API咬合。别被.bak文件吓退——那是开发者留下的历史快照不是残缺备份。2. 拆包即运行从解压到首页渲染的5步落地流程含.bat脚本真相解析2.1 解压后第一眼该盯什么识别项目分层结构解压微信小程序开发项目实例-农产品销售平台(源码).zip后你会看到混合目录既有main.css.bak、update-password.vue.bak这类带.bak后缀的文件也有3-build.bat、2-run.bat、1-install.bat三个批处理脚本还有.classpath和org.eclipse.wst.common.component这种Eclipse专属配置文件。这说明这不是纯前端项目而是Java Web工程 小程序前端的混合体且开发环境基于Eclipse Tomcat。关键目录结构如下手动整理非IDE自动生成目录/文件名类型作用是否必须src/main/webapp/Java Web根路径存放小程序前端静态资源WXML/WXSS/JS、后端JSP页面、静态HTML✅ 必须src/main/java/Java源码SSM三层结构controller接口层、service业务逻辑、mapper数据库操作✅ 必须src/main/resources/配置文件spring-context.xml、spring-mvc.xml、mybatis-config.xml、jdbc.properties✅ 必须WebContent/或webapp/前端资源入口小程序project.config.json所在目录也是微信开发者工具导入路径✅ 必须3-build.bat构建脚本执行mvn clean package -Dmaven.test.skiptrue生成WAR包⚠️ 可跳过新手建议先手动部署2-run.bat启动脚本调用startup.bat启动Tomcat并部署WAR包⚠️ 可跳过新手建议用IDE直启提示.bak文件如IndexHeader.vue.bak是开发者用Eclipse保存的旧版本快照不是损坏文件也不是必须删除。它们的存在恰恰证明这个项目经历过多次迭代比如update-password.vue.bak很可能对应密码修改功能的V1版而当前生效的是无后缀的update-password.vue。初学者可先忽略所有.bak专注无后缀文件。2.2 后端启动用Eclipse直启Tomcat绕过.bat脚本的玄学依赖很多新手卡在2-run.bat报错“找不到JAVA_HOME”、“mvn 不是内部命令”。这不是源码问题而是环境变量未配齐。我一般会跳过所有.bat用Eclipse直启——因为项目自带.project和.classpathEclipse能自动识别为Dynamic Web Project。操作步骤确保已安装 JDK 8必须SSM老项目普遍不兼容JDK 17和 Eclipse IDE for Enterprise Java Developers2021-06或更新版Eclipse → File → Import → Existing Projects into Workspace → 选择解压后的根目录 → Finish右键项目 → Properties → Targeted Runtimes → 勾选已配置的 Apache Tomcat v8.5必须v8.5v9有Servlet 4.0兼容问题右键项目 → Run As → Run on Server → 选择Tomcat v8.5 → Finish控制台输出INFO: Server startup in [xxx] ms后在浏览器访问http://localhost:8080/—— 应看到Tomcat欢迎页说明服务已起再访问http://localhost:8080/manager/html需配置Tomcat用户权限可确认应用是否部署成功。参数说明jdbc.properties中默认数据库地址为jdbc:mysql://localhost:3306/agriculture?useUnicodetruecharacterEncodingutf-8serverTimezoneGMT%2B8用户名root密码为空。若你的MySQL端口不是3306或密码非空必须修改此处否则后端启动时会报Communications link failure。这是新手踩坑率最高的点——不是代码错是数据库连不上。2.3 小程序前端导入微信开发者工具认准project.config.json而非app.js微信开发者工具不能直接打开src/main/webapp/目录因为那只是Java Web项目的静态资源存放位置。小程序真正的根目录是src/main/webapp/下的子目录通常叫miniprogram/或weapp/。但本项目没显式创建该目录——它的WXML/WXSS/JS文件就散落在src/main/webapp/下且project.config.json就在此层级。验证方法在src/main/webapp/目录下执行ls -laMac/Linux或dirWindows你会看到project.config.json app.js app.json app.wxss pages/ utils/这说明src/main/webapp/就是小程序项目根目录。微信开发者工具导入时路径必须选到这里而不是整个ZIP解压根目录。导入步骤打开微信开发者工具 → 新建项目 → 选择src/main/webapp/目录AppID填*测试号项目名称随意勾选“在新窗口打开”点击“确定”等待编译完成。首次编译可能报Cannot find module utils/util.js这是因为utils/util.js里引用了require(util)而微信小程序环境没有Node.js的util模块。解决方法注释掉utils/util.js第1行const util require(util);并删除所有util.format()调用改用字符串模板。这是本项目最典型的环境适配坑后面章节详述。2.4 接口联调前端如何调用Java后端看懂app.js里的全局 baseURL小程序前端所有网络请求都通过app.js中定义的全局baseURL发起。打开src/main/webapp/app.js找到App({ globalData: { userInfo: null, baseURL: http://localhost:8080/agriculture/ // ← 关键必须与后端Context Path一致 } })注意agriculture是Tomcat部署的应用名Context Path。你在Eclipse中右键项目 → Properties → Web Project Settings → Context root确认值为agriculture。若不同必须同步修改baseURL否则所有请求返回404。再看首页商品列表请求pages/index/index.jswx.request({ url: getApp().globalData.baseURL product/list, // 实际请求 http://localhost:8080/agriculture/product/list method: GET, success: (res) { this.setData({ productList: res.data }) } })这就是SSM后端Controller的映射路径// src/main/java/com/agriculture/controller/ProductController.java RestController RequestMapping(/product) public class ProductController { GetMapping(/list) public ListProduct list() { ... } }前后端路径严格对应没有网关、没有Nginx代理、没有跨域配置——因为同域localhost:8080。这是本地开发的最大便利也是上线前必须改造的点需加反向代理或CORS。3. 功能模块逐个击穿注册登录、商品管理、订单闭环代码在哪、怎么改3.1 用户注册与登录JWT Token如何存、取、验看login.vue和拦截器用户登录不是简单发个POST而是涉及Token生成、存储、请求头携带、后端校验四步闭环。本项目用JWTJSON Web Token但实现极简——Token存在wx.setStorageSync(token, res.data.token)每次请求从wx.getStorageSync(token)取出拼在Header里。打开pages/login/login.vue注意这是Vue语法写的WXML组件非标准Vue项目但结构一致!-- login.vue -- view classbtn-login bindtapdoLogin登录/view// login.vue 的js部分 doLogin() { wx.request({ url: getApp().globalData.baseURL user/login, method: POST, data: { username: this.data.username, password: this.data.password }, success: (res) { if (res.data.code 200) { wx.setStorageSync(token, res.data.token) // ← Token存本地 wx.switchTab({ url: /pages/index/index }) } } }) }后端UserController.login()方法生成Token// UserController.java PostMapping(/login) public Result login(RequestBody User user) { User dbUser userService.findByUsername(user.getUsername()); if (dbUser ! null dbUser.getPassword().equals(user.getPassword())) { String token JWTUtil.sign(dbUser.getId(), dbUser.getUsername()); // 使用jjwt库生成 return Result.success(token); } return Result.error(用户名或密码错误); }关键拦截器JwtInterceptor.java在src/main/java/com/agriculture/interceptor/下public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); // ← 前端必须传Header if (token null || !token.startsWith(Bearer )) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, Token缺失); return false; } try { Jwts.parser().setSigningKey(agriculture-secret).parseClaimsJws(token.substring(7)); } catch (Exception e) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, Token无效); return false; } return true; }注意agriculture-secret是硬编码密钥上线前必须替换成环境变量或配置中心读取。当前代码里所有/admin/**路径都注册了此拦截器意味着管理员接口也走JWT校验——但实际登录态管理是分离的管理员用Session这点设计有矛盾后面避坑章会讲。3.2 农产品管理后台SSM三层如何联动从ProductController到ProductMapper.xml管理员登录后进入pages/admin/product/product-list.vue点击“新增”调用addProduct()addProduct() { wx.navigateTo({ url: /pages/admin/product/product-add.vue }) }product-add.vue提交表单wx.request({ url: getApp().globalData.baseURL admin/product/add, method: POST, data: this.data.formData, header: { Authorization: Bearer wx.getStorageSync(token) }, // ← 携带Token success: () wx.navigateBack() })后端AdminProductController.add()PostMapping(/admin/product/add) public Result add(RequestBody Product product) { productService.add(product); // ← Service层 return Result.success(); }ProductService.add()Transactional public void add(Product product) { productMapper.insert(product); // ← Mapper层操作数据库 }ProductMapper.xmlsrc/main/resources/mapper/ProductMapper.xmlinsert idinsert parameterTypecom.agriculture.entity.Product INSERT INTO product (name, price, category_id, image_url, description) VALUES (#{name}, #{price}, #{categoryId}, #{imageUrl}, #{description}) /insert这就是SSM经典三层Controller接收请求 → Service编排业务含事务→ Mapper执行SQL。所有实体类Product.java、Mapper接口ProductMapper.java、XML映射文件一一对应字段名完全一致。若你要新增“产地”字段只需三步①Product.java加private String origin;②ProductMapper.xmlinsertSQL里加origin③product-add.vue表单加输入框并绑定formData.origin。3.3 订单全流程从购物车提交到状态变更状态机如何用数据库字段驱动订单不是单次请求而是状态流转待支付 → 已支付 → 已发货 → 已签收。本项目用order_status字段tinyint驱动值为0/1/2/3。用户下单pages/cart/cart.vuesubmitOrder() { wx.request({ url: getApp().globalData.baseURL order/submit, method: POST, data: { cartItems: this.data.cartItems }, success: (res) { if (res.data.code 200) { // 调用微信支付API此处省略具体调用实际需后端统一下单 wx.requestPayment({ /* 支付参数 */ }) } } }) }后端OrderController.submit()创建订单PostMapping(/order/submit) public Result submit(RequestBody OrderSubmitDTO dto) { Order order new Order(); order.setUserId(getCurrentUserId()); // 从JWT解析 order.setOrderStatus(0); // ← 初始状态待支付 order.setTotalPrice(dto.getTotalPrice()); orderService.create(order); return Result.success(order.getId()); }管理员发货pages/admin/order/order-list.vueshipOrder(id) { wx.request({ url: getApp().globalData.baseURL admin/order/ship, method: POST, data: { id: id }, success: () this.loadOrders() // 刷新列表 }) }AdminOrderController.ship()PostMapping(/admin/order/ship) public Result ship(RequestBody MapString, Long params) { Order order orderService.findById(params.get(id)); order.setOrderStatus(2); // ← 直接设为已发货 orderService.update(order); return Result.success(); }没有状态机引擎全靠if-else和字段值判断。例如订单详情页pages/order/detail.vue根据order_status渲染不同按钮view wx:if{{order.orderStatus 0}} button bindtappayOrder去支付/button /view view wx:if{{order.orderStatus 1}} button bindtapconfirmReceive确认收货/button /view这种设计简单直接适合中小项目。若未来要加“取消订单”、“申请售后”只需扩展order_status值和对应前端逻辑。4. 避坑指南5个血泪经验总结避开90%新手翻车现场4.1 现象微信开发者工具编译报错Cannot find module utils/util.js原因utils/util.js第1行const util require(util);尝试引入Node.js内置模块但小程序环境无此模块。解决打开src/main/webapp/utils/util.js注释第1行// const util require(util);并将所有util.format()替换为ES6模板字符串。例如// 原代码报错 console.log(util.format(用户%s登录失败, username)); // 改为正常 console.log(用户${username}登录失败);4.2 现象Eclipse启动Tomcat后访问http://localhost:8080/agriculture/返回404原因项目未正确部署到Tomcat或Context Path不匹配。解决Eclipse中右键项目 → Properties → Web Project Settings → 确认 Context root 为agriculture右键项目 → Run As → Run on Server → 确保勾选 “Always use this server configuration”启动后打开http://localhost:8080/manager/html在“Applications”列表中查找agriculture若状态为stopped点击Start若仍404检查src/main/webapp/WEB-INF/web.xml中welcome-file-list是否包含index.jsp且该文件存在。4.3 现象登录成功后跳转首页但商品列表空白控制台报GET http://localhost:8080/agriculture/product/list 401原因前端未在请求Header中携带Token或后端JWT拦截器未放行/product/list路径。解决检查pages/index/index.js中wx.request是否添加header: { Authorization: Bearer wx.getStorageSync(token) }检查JwtInterceptor.java的preHandle方法确认request.getRequestURI()包含/product/list时未被return false拦截关键/product/list是用户接口不应被JWT拦截器拦截因用户登录态用Token管理员用Session需在拦截器中加白名单if (request.getRequestURI().startsWith(/product/) || request.getRequestURI().startsWith(/user/)) { return true; // 放行用户相关接口 }4.4 现象MySQL插入中文乱码商品名显示为????原因MySQL连接URL未指定UTF-8编码或数据库/表字符集非utf8mb4。解决修改src/main/resources/jdbc.propertiesjdbc.urljdbc:mysql://localhost:3306/agriculture?useUnicodetruecharacterEncodingutf8mb4serverTimezoneGMT%2B8allowPublicKeyRetrievaltrueuseSSLfalse登录MySQL执行ALTER DATABASE agriculture CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ALTER TABLE product CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;4.5 现象管理员登录后点击“农产品管理”报403 Forbidden原因管理员接口/admin/**使用Session校验但前端未发送JSESSIONID Cookie。解决微信小程序默认不发送Cookie需显式开启withCredentials: true修改所有管理员接口请求如pages/admin/product/product-list.vuewx.request({ url: getApp().globalData.baseURL admin/product/list, method: GET, withCredentials: true, // ← 关键让小程序发送Cookie success: (res) { ... } })后端WebConfig.java需配置CORS允许凭据Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList(https://devtools.qyapi.weixin.qq.com)); configuration.setAllowCredentials(true); // ← 允许Cookie configuration.addAllowedMethod(*); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, configuration); return source; }5. 进阶技巧把这套源码改造成你的课程设计/毕设项目含3个可立即落地的改造点5.1 改造点一替换微信支付为模拟支付绕过企业资质审核微信小程序真实支付需企业认证微信支付商户号学生项目根本搞不定。本项目pages/order/submit.vue里wx.requestPayment()是占位符直接删掉改成模拟支付成功逻辑// pages/order/submit.vue payOrder() { // 删除 wx.requestPayment({...}) 整段 wx.request({ url: getApp().globalData.baseURL order/pay, method: POST, data: { orderId: this.data.orderId }, success: (res) { if (res.data.code 200) { wx.showToast({ title: 支付成功, icon: success }); setTimeout(() wx.switchTab({ url: /pages/order/order-list }), 1500); } } }) }后端OrderController.pay()PostMapping(/order/pay) public Result pay(RequestBody MapString, Long params) { Order order orderService.findById(params.get(orderId)); order.setOrderStatus(1); // ← 设为已支付 orderService.update(order); return Result.success(); }这样点击“去支付”直接跳转订单列表状态变为“已支付”。答辩时演示流畅且代码改动仅3处零风险。5.2 改造点二增加图片上传功能用本地路径替代七牛云原项目商品图用绝对路径http://localhost:8080/upload/xxx.jpg但upload目录不在项目内。用小程序自带wx.chooseImagewx.uploadFile上传到后端再存入src/main/webapp/upload/前端pages/admin/product/product-add.vue加按钮button bindtapchooseImage选择图片/button image src{{imageUrl}} modeaspectFill /JS中chooseImage() { wx.chooseImage({ count: 1, success: (res) { const tempFilePath res.tempFilePaths[0]; wx.uploadFile({ url: getApp().globalData.baseURL admin/upload, filePath: tempFilePath, name: file, success: (uploadRes) { const data JSON.parse(uploadRes.data); this.setData({ imageUrl: data.url }); // data.url 如 /upload/20231001123456.jpg } }) } }) }后端UploadController.javaPostMapping(/admin/upload) public Result upload(RequestParam(file) MultipartFile file) throws IOException { String fileName System.currentTimeMillis() _ file.getOriginalFilename(); String uploadPath src/main/webapp/upload/; new File(uploadPath).mkdirs(); file.transferTo(new File(uploadPath fileName)); return Result.success(/upload/ fileName); // 返回相对路径供前端显示 }5.3 改造点三导出订单Excel用Apache POI一行代码搞定毕设常要求“数据导出”。本项目订单列表只有展示加一个导出按钮后端用POI生成Excelpom.xml加依赖dependency groupIdorg.apache.poi/groupId artifactIdpoi-ooxml/artifactId version4.1.2/version /dependencyAdminOrderController.java加方法GetMapping(/admin/order/export) public void export(HttpServletResponse response) throws IOException { ListOrder orders orderService.findAll(); XSSFWorkbook workbook new XSSFWorkbook(); XSSFSheet sheet workbook.createSheet(订单列表); // 写表头... for (int i 0; i orders.size(); i) { XSSFRow row sheet.createRow(i 1); row.createCell(0).setCellValue(orders.get(i).getId()); row.createCell(1).setCellValue(orders.get(i).getTotalPrice()); // ...其他字段 } response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setHeader(Content-Disposition, attachment; filenameorders.xlsx); workbook.write(response.getOutputStream()); }前端pages/admin/order/order-list.vue加按钮button bindtapexportOrders导出Excel/buttonexportOrders() { wx.downloadFile({ url: getApp().globalData.baseURL admin/order/export, success: (res) { if (res.statusCode 200) { wx.openDocument({ filePath: res.tempFilePath, success: () console.log(打开成功) }) } } }) }从那以后我每次接手课程设计源码都强制走一遍这三步① 把支付改成模拟逻辑确保演示不卡壳② 把图片上传路径本地化避免七牛云配置黑洞③ 给核心列表加导出功能答辩时老师问“数据怎么分析”直接点按钮弹Excel。这三步做完项目就从“能跑”变成“能讲、能演、能交”比堆砌炫酷动画实在得多。希望帮到你。本文还有配套的精品资源点击获取
返回列表