news 2026/9/4 5:23:06

微信小程序宿舍水电缴费系统开发实战:Spring Boot+MySQL全栈实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微信小程序宿舍水电缴费系统开发实战:Spring Boot+MySQL全栈实现

基于微信小程序的宿舍水电缴费系统开发实战

在校园信息化建设中,宿舍水电缴费一直是个高频且痛点明显的场景。传统的人工收费方式效率低下,学生排队缴费耗时耗力,管理员对账工作繁琐。基于微信小程序的解决方案能够完美解决这些问题,让学生随时随地完成缴费,管理员实时掌握数据。

本文将完整介绍一个宿舍水电缴费小程序的开发全过程,从环境搭建到功能实现,包含前端界面设计、后端API开发、数据库设计以及支付集成等核心模块。无论你是计算机专业的学生需要完成毕业设计,还是开发者想要学习微信小程序开发,都能从中获得实用的技术方案。

1. 系统架构与技术选型

1.1 整体架构设计

宿舍水电缴费系统采用典型的前后端分离架构。前端使用微信小程序原生框架,后端采用Spring Boot构建RESTful API,数据库使用MySQL存储业务数据,同时集成微信支付完成交易流程。

系统主要包含以下模块:

  • 用户认证模块:微信授权登录、手机号绑定
  • 费用查询模块:水电用量查询、费用计算
  • 支付模块:微信支付集成、订单管理
  • 管理后台:数据统计、费用设置、用户管理

1.2 技术栈说明

前端技术栈:

  • 微信小程序原生框架
  • WXML/WXSS/JavaScript
  • Vant Weapp组件库
  • 微信支付SDK

后端技术栈:

  • Spring Boot 2.7+
  • MySQL 8.0+
  • MyBatis Plus
  • Redis缓存
  • 微信开放平台SDK

2. 开发环境准备

2.1 前端开发环境

首先需要安装微信开发者工具,这是开发微信小程序的必备工具。

# 下载微信开发者工具(最新稳定版) # 官方下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

创建小程序项目的基本结构:

miniprogram/ ├── pages/ # 页面文件 │ ├── index/ # 首页 │ ├── bill/ # 账单页面 │ └── profile/ # 个人中心 ├── components/ # 自定义组件 ├── utils/ # 工具类 ├── app.js # 小程序入口 ├── app.json # 小程序配置 ├── app.wxss # 全局样式 └── project.config.json # 项目配置

2.2 后端开发环境

后端使用Spring Initializr快速创建项目:

<!-- pom.xml 主要依赖 --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> </dependencies>

3. 数据库设计

3.1 核心表结构设计

宿舍水电缴费系统的数据库设计需要充分考虑扩展性和数据一致性。以下是几个核心表的设计:

-- 用户表 CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `openid` varchar(64) NOT NULL COMMENT '微信openid', `student_id` varchar(20) NOT NULL COMMENT '学号', `name` varchar(50) NOT NULL COMMENT '姓名', `phone` varchar(11) DEFAULT NULL COMMENT '手机号', `dormitory_id` bigint(20) NOT NULL COMMENT '宿舍ID', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_openid` (`openid`), UNIQUE KEY `uk_student_id` (`student_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 宿舍表 CREATE TABLE `dormitory` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `building` varchar(10) NOT NULL COMMENT '楼栋', `room_number` varchar(10) NOT NULL COMMENT '房间号', `water_rate` decimal(10,2) DEFAULT '5.00' COMMENT '水费单价', `electricity_rate` decimal(10,2) DEFAULT '0.60' COMMENT '电费单价', PRIMARY KEY (`id`), UNIQUE KEY `uk_building_room` (`building`, `room_number`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 水电记录表 CREATE TABLE `utility_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `dormitory_id` bigint(20) NOT NULL, `type` tinyint(1) NOT NULL COMMENT '1-水费 2-电费', `previous_reading` decimal(10,2) NOT NULL COMMENT '上次读数', `current_reading` decimal(10,2) NOT NULL COMMENT '本次读数', `usage_amount` decimal(10,2) NOT NULL COMMENT '使用量', `amount` decimal(10,2) NOT NULL COMMENT '金额', `record_date` date NOT NULL COMMENT '记录日期', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 订单表 CREATE TABLE `payment_order` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `order_no` varchar(32) NOT NULL COMMENT '订单号', `user_id` bigint(20) NOT NULL, `dormitory_id` bigint(20) NOT NULL, `amount` decimal(10,2) NOT NULL COMMENT '支付金额', `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0-待支付 1-已支付 2-已取消', `pay_time` datetime DEFAULT NULL COMMENT '支付时间', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_order_no` (`order_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.2 数据关系设计

用户与宿舍是多对一关系,一个宿舍可以有多个用户,但一个用户只能属于一个宿舍。水电记录与宿舍是一对多关系,每个宿舍会有多条水电使用记录。订单与用户是多对一关系,一个用户可以有多个支付订单。

4. 前端界面开发

4.1 首页设计

首页需要展示用户基本信息、当前水电费用情况以及快捷缴费入口。

<!-- pages/index/index.wxml --> <view class="container"> <view class="user-info"> <image class="avatar" src="{{userInfo.avatarUrl}}"></image> <text class="username">{{userInfo.nickName}}</text> <text class="dormitory">{{dormitoryInfo.building}}栋{{dormitoryInfo.roomNumber}}</text> </view> <view class="bill-card"> <view class="card-title">本月费用明细</view> <view class="bill-item"> <text>水费</text> <text class="amount">¥{{waterBill.amount}}</text> </view> <view class="bill-item"> <text>电费</text> <text class="amount">¥{{electricityBill.amount}}</text> </view> <view class="total-amount"> <text>合计</text> <text class="amount">¥{{totalAmount}}</text> </view> </view> <button class="pay-btn" bindtap="goToPay">立即缴费</button> </view>

对应的样式文件:

/* pages/index/index.wxss */ .container { padding: 20rpx; } .user-info { display: flex; align-items: center; margin-bottom: 30rpx; } .avatar { width: 120rpx; height: 120rpx; border-radius: 50%; margin-right: 20rpx; } .bill-card { background: #fff; border-radius: 16rpx; padding: 30rpx; margin-bottom: 30rpx; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1); } .card-title { font-size: 32rpx; font-weight: bold; margin-bottom: 20rpx; } .bill-item { display: flex; justify-content: space-between; padding: 20rpx 0; border-bottom: 1rpx solid #f0f0f0; } .total-amount { display: flex; justify-content: space-between; padding: 20rpx 0; font-weight: bold; color: #e64340; } .pay-btn { background: #07c160; color: white; border-radius: 50rpx; font-size: 32rpx; }

4.2 用户登录逻辑

微信小程序需要实现用户授权登录,获取用户基本信息。

// pages/index/index.js Page({ data: { userInfo: {}, dormitoryInfo: {}, waterBill: {}, electricityBill: {}, totalAmount: 0 }, onLoad() { this.checkLoginStatus(); }, checkLoginStatus() { const token = wx.getStorageSync('token'); if (token) { this.getUserInfo(); this.getBillInfo(); } else { this.login(); } }, login() { wx.login({ success: (res) => { if (res.code) { this.requestLogin(res.code); } } }); }, requestLogin(code) { wx.request({ url: 'https://your-domain.com/api/login', method: 'POST', data: { code }, success: (res) => { if (res.data.success) { wx.setStorageSync('token', res.data.data.token); this.getUserInfo(); this.getBillInfo(); } } }); }, getUserInfo() { wx.getUserInfo({ success: (res) => { this.setData({ userInfo: res.userInfo }); } }); }, getBillInfo() { wx.request({ url: 'https://your-domain.com/api/bill/current', header: { 'Authorization': wx.getStorageSync('token') }, success: (res) => { if (res.data.success) { this.setData({ dormitoryInfo: res.data.data.dormitory, waterBill: res.data.data.waterBill, electricityBill: res.data.data.electricityBill, totalAmount: res.data.data.totalAmount }); } } }); }, goToPay() { wx.navigateTo({ url: '/pages/pay/pay?amount=' + this.data.totalAmount }); } });

5. 后端API开发

5.1 用户登录接口

后端需要处理微信登录code,换取openid并生成用户token。

// UserController.java @RestController @RequestMapping("/api") public class UserController { @Autowired private UserService userService; @PostMapping("/login") public Result login(@RequestBody LoginRequest request) { try { // 调用微信接口获取openid String openid = wechatService.getOpenid(request.getCode()); // 查询或创建用户 User user = userService.findOrCreateUser(openid); // 生成JWT token String token = jwtUtil.generateToken(user.getId()); LoginResponse response = new LoginResponse(); response.setToken(token); response.setUser(user); return Result.success(response); } catch (Exception e) { return Result.error("登录失败"); } } } // LoginRequest.java @Data public class LoginRequest { private String code; private String encryptedData; private String iv; } // WechatService.java @Service public class WechatService { @Value("${wechat.appid}") private String appid; @Value("${wechat.secret}") private String secret; public String getOpenid(String code) { String url = "https://api.weixin.qq.com/sns/jscode2session" + "?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code"; RestTemplate restTemplate = new RestTemplate(); String response = restTemplate.getForObject(url, String.class); JSONObject json = JSON.parseObject(response); return json.getString("openid"); } }

5.2 费用查询接口

根据用户所在宿舍查询当前水电费用。

// BillController.java @RestController @RequestMapping("/api/bill") public class BillController { @Autowired private BillService billService; @GetMapping("/current") public Result getCurrentBill(@RequestHeader("Authorization") String token) { try { Long userId = jwtUtil.getUserIdFromToken(token); CurrentBillResponse response = billService.getCurrentBill(userId); return Result.success(response); } catch (Exception e) { return Result.error("查询失败"); } } } // BillService.java @Service public class BillService { @Autowired private UserMapper userMapper; @Autowired private UtilityRecordMapper recordMapper; @Autowired private DormitoryMapper dormitoryMapper; public CurrentBillResponse getCurrentBill(Long userId) { User user = userMapper.selectById(userId); Dormitory dormitory = dormitoryMapper.selectById(user.getDormitoryId()); // 查询最近的水电记录 UtilityRecord lastWaterRecord = recordMapper.selectLastRecord( dormitory.getId(), 1); // 1表示水费 UtilityRecord lastElectricityRecord = recordMapper.selectLastRecord( dormitory.getId(), 2); // 2表示电费 CurrentBillResponse response = new CurrentBillResponse(); response.setDormitory(dormitory); // 计算水费 if (lastWaterRecord != null) { BillItem waterBill = calculateBill(lastWaterRecord, dormitory.getWaterRate()); response.setWaterBill(waterBill); } // 计算电费 if (lastElectricityRecord != null) { BillItem electricityBill = calculateBill(lastElectricityRecord, dormitory.getElectricityRate()); response.setElectricityBill(electricityBill); } return response; } private BillItem calculateBill(UtilityRecord record, BigDecimal rate) { BillItem bill = new BillItem(); bill.setPreviousReading(record.getPreviousReading()); bill.setCurrentReading(record.getCurrentReading()); bill.setUsageAmount(record.getUsageAmount()); bill.setAmount(record.getAmount()); return bill; } }

6. 微信支付集成

6.1 支付流程设计

微信支付的完整流程包括:创建订单、调用统一下单API、生成支付参数、前端调起支付、处理支付结果。

// PaymentController.java @RestController @RequestMapping("/api/payment") public class PaymentController { @Autowired private PaymentService paymentService; @PostMapping("/create") public Result createPayment(@RequestBody PaymentRequest request, @RequestHeader("Authorization") String token) { try { Long userId = jwtUtil.getUserIdFromToken(token); PaymentResponse response = paymentService.createPayment(userId, request.getAmount()); return Result.success(response); } catch (Exception e) { return Result.error("创建支付失败"); } } } // PaymentService.java @Service public class PaymentService { @Autowired private OrderMapper orderMapper; @Value("${wechat.pay.appid}") private String appid; @Value("${wechat.pay.mchid}") private String mchid; @Value("${wechat.pay.key}") private String key; public PaymentResponse createPayment(Long userId, BigDecimal amount) { // 创建订单 PaymentOrder order = new PaymentOrder(); order.setOrderNo(generateOrderNo()); order.setUserId(userId); order.setAmount(amount); order.setStatus(0); orderMapper.insert(order); // 调用微信支付统一下单 Map<String, String> params = new HashMap<>(); params.put("appid", appid); params.put("mch_id", mchid); params.put("nonce_str", generateNonceStr()); params.put("body", "宿舍水电费缴纳"); params.put("out_trade_no", order.getOrderNo()); params.put("total_fee", amount.multiply(new BigDecimal(100)).intValue() + ""); params.put("spbill_create_ip", "127.0.0.1"); params.put("notify_url", "https://your-domain.com/api/payment/notify"); params.put("trade_type", "JSAPI"); params.put("openid", getOpenidByUserId(userId)); // 生成签名 String sign = generateSign(params); params.put("sign", sign); // 调用微信支付API String xmlResult = postWechatPay("https://api.mch.weixin.qq.com/pay/unifiedorder", params); // 解析返回结果 Map<String, String> result = parseXml(xmlResult); if ("SUCCESS".equals(result.get("return_code"))) { PaymentResponse response = new PaymentResponse(); response.setOrderNo(order.getOrderNo()); response.setPrepayId(result.get("prepay_id")); response.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000)); response.setNonceStr(generateNonceStr()); response.setSignType("MD5"); // 生成前端支付参数 Map<String, String> payParams = new HashMap<>(); payParams.put("appId", appid); payParams.put("timeStamp", response.getTimeStamp()); payParams.put("nonceStr", response.getNonceStr()); payParams.put("package", "prepay_id=" + response.getPrepayId()); payParams.put("signType", "MD5"); String paySign = generateSign(payParams); response.setPaySign(paySign); return response; } else { throw new RuntimeException("微信支付下单失败: " + result.get("return_msg")); } } }

6.2 前端支付调用

小程序端调用微信支付接口:

// pages/pay/pay.js Page({ data: { amount: 0, orderInfo: null }, onLoad(options) { this.setData({ amount: options.amount }); this.createOrder(); }, createOrder() { wx.request({ url: 'https://your-domain.com/api/payment/create', method: 'POST', header: { 'Authorization': wx.getStorageSync('token'), 'Content-Type': 'application/json' }, data: { amount: this.data.amount }, success: (res) => { if (res.data.success) { this.setData({ orderInfo: res.data.data }); } } }); }, handlePayment() { const orderInfo = this.data.orderInfo; wx.requestPayment({ timeStamp: orderInfo.timeStamp, nonceStr: orderInfo.nonceStr, package: orderInfo.package, signType: orderInfo.signType, paySign: orderInfo.paySign, success: (res) => { wx.showToast({ title: '支付成功', icon: 'success' }); setTimeout(() => { wx.navigateBack(); }, 1500); }, fail: (res) => { wx.showToast({ title: '支付失败', icon: 'error' }); } }); } });

7. 管理后台功能

7.1 费用设置模块

管理员可以设置不同宿舍的水电费用单价。

// AdminController.java @RestController @RequestMapping("/api/admin") public class AdminController { @Autowired private DormitoryService dormitoryService; @PostMapping("/dormitory/rate") public Result updateRate(@RequestBody RateUpdateRequest request) { try { dormitoryService.updateRate(request.getDormitoryId(), request.getWaterRate(), request.getElectricityRate()); return Result.success("更新成功"); } catch (Exception e) { return Result.error("更新失败"); } } } // DormitoryService.java @Service public class DormitoryService { @Autowired private DormitoryMapper dormitoryMapper; public void updateRate(Long dormitoryId, BigDecimal waterRate, BigDecimal electricityRate) { Dormitory dormitory = dormitoryMapper.selectById(dormitoryId); if (dormitory != null) { dormitory.setWaterRate(waterRate); dormitory.setElectricityRate(electricityRate); dormitoryMapper.updateById(dormitory); } } }

7.2 数据统计功能

提供数据统计接口,方便管理员查看缴费情况。

// StatisticsController.java @RestController @RequestMapping("/api/admin/statistics") public class StatisticsController { @Autowired private StatisticsService statisticsService; @GetMapping("/daily") public Result getDailyStatistics(@RequestParam String date) { try { DailyStatistics stats = statisticsService.getDailyStatistics(date); return Result.success(stats); } catch (Exception e) { return Result.error("获取统计失败"); } } } // StatisticsService.java @Service public class StatisticsService { @Autowired private PaymentOrderMapper orderMapper; public DailyStatistics getDailyStatistics(String date) { DailyStatistics stats = new DailyStatistics(); // 查询当日总缴费金额 BigDecimal totalAmount = orderMapper.selectTotalAmountByDate(date); stats.setTotalAmount(totalAmount); // 查询缴费订单数 Integer orderCount = orderMapper.selectCountByDate(date); stats.setOrderCount(orderCount); // 查询各楼栋缴费情况 List<BuildingStatistics> buildingStats = orderMapper.selectBuildingStatistics(date); stats.setBuildingStatistics(buildingStats); return stats; } }

8. 系统部署与运维

8.1 小程序发布流程

小程序开发完成后需要提交审核发布:

  1. 代码上传:在微信开发者工具中点击"上传"
  2. 提交审核:在微信公众平台提交版本审核
  3. 发布上线:审核通过后发布到线上环境

8.2 服务端部署

使用Docker容器化部署后端服务:

# Dockerfile FROM openjdk:8-jre-slim VOLUME /tmp COPY target/dormitory-payment-0.0.1-SNAPSHOT.jar app.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

部署命令:

# 构建镜像 docker build -t dormitory-payment . # 运行容器 docker run -d -p 8080:8080 \ -e SPRING_DATASOURCE_URL=jdbc:mysql://mysql-server:3306/dormitory \ -e SPRING_REDIS_HOST=redis-server \ dormitory-payment

9. 常见问题与解决方案

9.1 支付相关问题

问题1:支付签名错误

  • 原因:参数顺序错误或密钥不正确
  • 解决方案:检查签名算法,确保参数按字典序排序

问题2:支付回调失败

  • 原因:网络问题或证书配置错误
  • 解决方案:检查服务器网络,配置正确的SSL证书

9.2 数据库连接问题

问题:数据库连接超时

  • 原因:连接池配置不合理或网络延迟
  • 解决方案:优化连接池参数,增加超时时间设置
# application.yml 数据库配置 spring: datasource: url: jdbc:mysql://localhost:3306/dormitory?useSSL=false username: root password: your_password hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000

9.3 微信登录问题

问题:获取openid失败

  • 原因:appid和secret配置错误或网络问题
  • 解决方案:检查微信开放平台配置,确保网络连通性

10. 性能优化建议

10.1 数据库优化

  1. 索引优化:为常用查询字段添加索引
  2. 查询优化:避免SELECT *,使用分页查询
  3. 缓存策略:使用Redis缓存热点数据

10.2 前端优化

  1. 图片优化:压缩图片,使用WebP格式
  2. 请求合并:合并API请求,减少网络开销
  3. 本地缓存:合理使用本地存储

10.3 后端优化

  1. 异步处理:使用异步处理耗时操作
  2. 连接池:优化数据库连接池配置
  3. 负载均衡:部署多实例,使用负载均衡

这个宿舍水电缴费小程序项目涵盖了微信小程序开发的完整流程,从需求分析到系统部署,每个环节都提供了详细的技术实现方案。在实际开发中,还需要根据具体需求进行调整和优化,特别是支付安全和数据一致性方面需要格外重视。

对于计算机专业的毕业设计来说,这个项目具有很好的实用性和技术深度,既展示了前端界面设计能力,也体现了后端业务逻辑处理能力。建议在实现基础功能后,可以进一步扩展如数据可视化、智能提醒等高级功能,提升项目的完整度和竞争力。

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

微信小程序社交平台开发实战:以书会友毕业设计指南

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

作者头像 李华
网站建设 2026/9/4 5:22:52

python爬虫: 初识Requests与Robots协议

文章目录 爬虫robots协议GET请求POST 请求GET请求带参数 爬虫 爬虫, 也称网网络爬虫(网络机器人), 是一种按照一定的预设规则, 自动浏览并抓取网络数据的程序或脚本. 网络机器人的执行流程: 数据清洗: 是指对采集到的原始数据进行处理, 修正, 转换和标准化的过程, 目的是让数…

作者头像 李华
网站建设 2026/9/4 5:22:49

Facebook BM 交易平台推荐

做 Meta 矩阵投放&#xff0c;BM 商务管理账户是管理广告账户、主页、像素的核心载体。不少卖家自己注册 BM 时&#xff0c;经常遭遇资质审核、平台风控拦截&#xff0c;想要快速拿到可用资产&#xff0c;就会考虑第三方交易渠道。但市面上渠道鱼龙混杂&#xff0c;私下个人交易…

作者头像 李华
网站建设 2026/9/4 5:20:54

Runway平台集成Grok Imagine Video 1.5: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/4 5:19:48

物流分拣中心排班优化:MILP+规则引擎落地实践

简介&#xff1a;本资源面向2026年辽宁省数学建模竞赛B题参赛者&#xff0c;聚焦物流分拣中心排班优化这一典型运筹学实战问题&#xff0c;专为需突破建模瓶颈的队长、编程基础薄弱但追求高分的队员及冲刺特等奖的精英团队设计。压缩包共60个文件&#xff08;1.5MB&#xff09;…

作者头像 李华
网站建设 2026/9/4 5:19:24

C# MVC+EasyUI+ECharts后台管理系统架构解析与实战指南

简介&#xff1a;这是一套面向C#初学者与Web开发进阶者的后台管理系统完整源码&#xff0c;适用于学习MVC架构设计、前后端分离实践及数据可视化集成。资源基于ASP.NET MVC框架构建后端逻辑&#xff0c;采用EasyUI实现响应式管理界面&#xff0c;结合ECharts完成多维度图表分析…

作者头像 李华