1. 项目背景与核心价值
垃圾分类回收系统是当前智慧城市建设的重要组成部分。随着环保政策的持续推进,全国已有46个重点城市实施生活垃圾强制分类,但实际执行中仍存在居民分类意识不足、投放准确率低等问题。基于微信小程序的垃圾分类回收系统,正是为了解决这一痛点而生。
这个毕业设计项目的技术栈选择非常典型:
- 后端采用SpringBoot框架,提供RESTful API接口
- 前端使用微信小程序技术栈,保证用户触达率
- 数据库选用MySQL,满足结构化数据存储需求
我去年指导过三个类似项目,发现这种架构组合特别适合学生毕业设计:技术栈主流但不过度复杂,既能体现完整开发流程,又能在2-3个月周期内完成。最关键的是,微信小程序的即用即走特性,与垃圾分类这类低频但刚需的场景完美契合。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术选型决策
后端选择SpringBoot而非传统SSM框架,主要基于三点考虑:
- 自动配置特性大幅减少XML配置,新手更易上手
- 内嵌Tomcat简化部署流程,
mvn spring-boot:run即可启动 - Starter生态丰富,比如整合MyBatis-Plus只需添加一个依赖:
xml复制<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
前端选择微信小程序而非H5,核心优势在于:
- 无需下载安装,扫码即用
- 微信生态支持(用户体系、支付等)
- 开发工具链成熟(WXML/WXSS/JS)
2.2 数据库设计要点
垃圾分类系统主要涉及五张核心表:
- 用户表(user)
sql复制CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`openid` varchar(64) COMMENT '微信openid',
`nickname` varchar(64) COMMENT '昵称',
`avatar` varchar(255) COMMENT '头像',
`credit_score` int DEFAULT 100 COMMENT '环保积分',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_openid` (`openid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 垃圾类别表(garbage_category)
sql复制CREATE TABLE `garbage_category` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(20) COMMENT '可回收/有害/厨余/其他',
`icon` varchar(255) COMMENT '分类图标',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 垃圾物品表(garbage_item)
sql复制CREATE TABLE `garbage_item` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(50) COMMENT '物品名称',
`category_id` int COMMENT '所属分类',
`search_count` int DEFAULT 0 COMMENT '搜索次数',
PRIMARY KEY (`id`),
KEY `idx_category` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
关键技巧:垃圾物品表需要建立全文索引,支持模糊搜索:
sql复制ALTER TABLE `garbage_item` ADD FULLTEXT INDEX `idx_search`(`name`);
3. 核心功能实现
3.1 垃圾分类识别功能
这是系统的核心难点,我们采用三级识别策略:
- 本地缓存优先:使用微信小程序Storage缓存常见物品
javascript复制// 小程序端缓存策略
function checkLocalCache(name) {
try {
const cache = wx.getStorageSync('garbageCache') || {}
return cache[name] || null
} catch (e) {
console.error('缓存读取失败', e)
return null
}
}
- 数据库查询:SpringBoot接口实现模糊查询
java复制@RestController
@RequestMapping("/api/garbage")
public class GarbageController {
@Autowired
private GarbageItemMapper itemMapper;
@GetMapping("/search")
public Result search(@RequestParam String keyword) {
// 使用MyBatis-Plus的Lambda查询
List<GarbageItem> items = itemMapper.selectList(
Wrappers.<GarbageItem>lambdaQuery()
.apply("MATCH(name) AGAINST({0} IN BOOLEAN MODE)", keyword)
.last("LIMIT 10")
);
return Result.success(items);
}
}
- AI图像识别兜底(可选扩展):
- 使用百度EasyDL定制图像分类模型
- 微信小程序调用流程:
javascript复制wx.chooseImage({
success(res) {
wx.uploadFile({
url: 'https://your-domain.com/api/ai/recognize',
filePath: res.tempFilePaths[0],
name: 'image',
success(res) {
console.log(JSON.parse(res.data))
}
})
}
})
3.2 积分奖励系统设计
为提升用户粘性,建议设计积分体系:
java复制// 积分服务层示例
@Service
public class CreditService {
@Transactional
public void addCredit(Long userId, int points) {
userMapper.update(null,
Wrappers.<User>lambdaUpdate()
.eq(User::getId, userId)
.setSql("credit_score = credit_score + " + points));
creditRecordMapper.insert(new CreditRecord(userId, points, "分类奖励"));
}
}
微信小程序端展示积分变动动画:
javascript复制// pages/profile/profile.js
Page({
data: { credit: 0 },
onShow() {
this.animate('.credit', [
{ opacity: 0, scale: 0.5 },
{ opacity: 1, scale: 1 }
], 800)
}
})
4. 开发避坑指南
4.1 微信登录流程优化
新手常犯的错误是直接使用wx.login的code换openid。更安全的做法是:
- 小程序端先获取用户信息授权
javascript复制wx.getUserProfile({
desc: '用于展示用户信息',
success(res) {
wx.login({
success(loginRes) {
wx.request({
url: 'https://your-domain.com/api/login',
data: {
code: loginRes.code,
userInfo: res.userInfo
}
})
}
})
}
})
- 服务端验证流程
java复制public String wxLogin(String code, UserInfo userInfo) {
// 1. 使用code换取openid
String openid = wxService.getOpenid(code);
// 2. 查询或创建用户
User user = userMapper.selectOne(
Wrappers.<User>lambdaQuery().eq(User::getOpenid, openid));
if (user == null) {
user = new User();
user.setOpenid(openid);
user.setNickname(userInfo.getNickName());
user.setAvatar(userInfo.getAvatarUrl());
userMapper.insert(user);
}
// 3. 生成JWT token
return JwtUtil.generateToken(user.getId());
}
4.2 性能优化实践
- 小程序分包加载:
json复制// app.json
{
"pages": ["pages/index/index"],
"subpackages": [
{
"root": "subpackages/learn",
"pages": ["category", "search"]
}
]
}
- SpringBoot接口缓存:
java复制@Cacheable(value = "garbage", key = "#name")
@GetMapping("/category")
public String getCategory(String name) {
return categoryService.determineCategory(name);
}
- MySQL连接池配置:
yaml复制# application.yml
spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
5. 项目扩展方向
5.1 智能回收箱对接
通过蓝牙或WiFi模块连接硬件:
javascript复制// 小程序蓝牙连接示例
wx.openBluetoothAdapter({
success() {
wx.startBluetoothDevicesDiscovery({
services: ['0000FFE0-0000-1000-8000-00805F9B34FB'],
success(res) {
console.log('发现设备', res.devices)
}
})
}
})
5.2 数据可视化大屏
使用ECharts展示分类数据:
java复制@RestController
@RequestMapping("/api/stats")
public class StatsController {
@GetMapping("/daily")
public Map<String, Integer> getDailyStats() {
return recordMapper.selectMaps(
"SELECT category_id, COUNT(*) as count " +
"FROM recycling_record " +
"WHERE create_time >= CURDATE() " +
"GROUP BY category_id"
).stream()
.collect(Collectors.toMap(
m -> m.get("category_id").toString(),
m -> Integer.parseInt(m.get("count").toString())
));
}
}
5.3 消息订阅通知
垃圾分类提醒功能:
javascript复制// 小程序端订阅
wx.requestSubscribeMessage({
tmplIds: ['TEMPLATE_ID'],
success(res) {
console.log('订阅结果', res)
}
})
服务端发送示例:
java复制@Scheduled(cron = "0 0 19 * * ?") // 每晚7点
public void sendReminder() {
List<String> openids = userMapper.selectObjs(
Wrappers.<User>query()
.select("openid")
.eq("reminder_enable", 1)
).stream()
.map(o -> (String)o)
.collect(Collectors.toList());
openids.forEach(openid -> {
wxService.sendSubscribeMsg(openid, "垃圾分类提醒", "记得定时投放垃圾哦");
});
}
这个项目我实际部署过社区版本,最大的收获是:一定要做好垃圾名称的同义词处理(比如"电池"和"干电池"),建议在数据库增加alias字段存储别名。另外,小程序审核时要注意"垃圾分类"属于政务类目,需要选择"环保回收/废品回收"类目才能过审。
