ARTICLE · 1358155
JAVA幼儿托育幼儿托管系统源码支持小程序+公众号+H5
小程序 + 公众号 + H5 |
CHILDCARE CENTER SYSTEM / JAVA 托育园 · 老师 · 动态 · 咨询 · 工作台 · 收藏 JAVA 幼儿托育托管系统 源码 支持小程序 从园区建档到家长咨询,一条链路跑完的托育 SaaS。 SpringBoot · MyBatisPlus · MySQL uniapp · Vue + ElementUI |
做托育这行,最尴尬的时刻不是没家长咨询,是家长就在门口站着,你翻了三台手机也说不清"这个班现在还有几个名额、今天谁带班、刚才那条咨询回了没有"。
园区信息在美团、在朋友圈、在老师自己的手机相册里;排班在 Excel;家长咨询在微信私聊里,谁回过的、谁没回的,全靠脑子记。等到月底想做一次复盘,发现连"这个月有多少家长点进过园区主页"都拿不出来。
这套幼儿托育幼儿托管系统不是再给你加一个后台,而是把三件事收进一条链路:园区和老师先建成档案,家长端的内容和咨询挂在档案上,最后所有动作汇到园区工作台的一张看板。下面按功能拆开讲,每一段都能对着截图找到对应界面。
技术栈是老搭档:SpringBoot + MyBatisPlus + MySQL 做服务端,uniapp 出一套代码跑小程序和 H5,公众号走同一套接口,管理后台用 Vue + ElementUI。源码交付,不是 SaaS 账号。
七个功能,一条主线
先看全景。七块功能不是并列的七个菜单,它们有先后:园区和老师是底座,动态和咨询是家长能看见的部分,详情页和收藏是转化环节,工作台是给老板看的账。
托育园管理 园区、班型、收费口径一次建档,家长端看到的就是准的 | 托育老师管理 资质、岗位、带班关系落库,师生比有数可查 |
动态管理 园所动态一次发布,小程序、公众号、H5 同步露出 | 育婴咨询 家长提问进工单,待回复、咨询中、已结束都有状态 |
动态详情 图文、评论、浏览、点赞收藏聚在一页,内容侧留痕 | 园区工作台 今日咨询、待回复、审核待办、园区浏览,打开就是今天的数 |
点赞收藏 收藏是意向池,能按园区沉淀可回访的家长名单 | 三端一体 小程序、公众号、H5 共用一个后端,不是三套系统 |
01 托育园管理:园区档案不是一张表
一个城市开三家园区,家长打开首页先选城市,再看到本城的园区列表——这个动作背后是"园区档案 + 城市编码 + 上架状态"三样东西。档案没建全,家长端就会出现这样的画面:园区卡片写着"全托班 半托班",但点进去发现营业时间空着、电话是私人号、地址只写到路口。
| 输入 | 园区名称、城市、详细地址、营业时间、班型(全托/半托/临托)、设施标签 |
| 状态变化 | 待审核 → 已上架 → 已下架;同城同名园区不允许重复建档 |
| 输出 | 家长端一张可筛选的园区卡:城市 → 班型 → 距离,点开进入详情 |
工程结论:园区档案要"对着家长端能看见的字段建",不是对着营业执照建。家长最先看的三样是班型、营业时间、位置。

【JAVA幼儿托育托管系统】实拍 01|首页:城市切换、首页/动态/育婴资讯三栏、园区卡片与师资团队;截图数据为演示数据
界面落地看这三点:顶部"托育园 / 托育老师"双 Tab,家长可以按园区找,也可以按老师找;园区卡左侧是缩略图和班型标签(全托班、半托班、儿童卫生间),右侧是地址和营业时间;卡片下方直接挂"师资团队",王老师、刘老师带头像。信息一口气给到,不用点进去猜。
02 托育老师管理:师生比是硬约束
托育和幼儿园最大的区别是照护密度。一个班 20 个孩子配 2 个老师,和家长看到的"1:10"对不上,第一次家访就会被问住。老师管理不只要存名字和照片,还要存岗位、资质证号、带哪个班、这个班现在几个人。
| 输入 | 老师姓名、头像、岗位(主班/配班/保育)、育婴师证号、所属园区、带班关系 |
| 状态变化 | 在职 → 调岗 → 离职;离职后家长端立刻不再展示,历史动态保留 |
| 输出 | 园区详情页的"师资团队"模块,以及后台按园区、按班级的师生比统计 |
工程结论:师生比别做成报表里算,做成报名时的校验。班级容量满了就拦住,别等排班时才发现。
03 动态管理:发布一次,三端露出
园区日常最想发的是"今天孩子们做了什么":手工课、户外活动、加餐。这些内容发在朋友圈里三天就沉了,家长想回看找不到;发在公众号里又要排版、要审核,老师不愿意发。动态管理的定位是轻量内容 + 一次发布三端同步。
| 输入 | 标题、正文图文(最多 9 张)、所属园区、可见范围(全部/本园家长) |
| 状态变化 | 草稿 → 待审核 → 已发布 → 已下架;下架不删数据,只改可见 |
| 输出 | 家长端"动态"信息流、园区详情页的最新三条、公众号图文素材 |
工程结论:动态要带"审核",不是防老师,是防孩子正脸。发布前必须有一个能拦住人脸的动作。
04 育婴咨询:把"问老师"变成工单
家长咨询的现实是:微信上问一句"你们半托怎么收费",老师正在带班,两小时后回;回的时候家长已经看了别家。问题不在态度,在没有"待办"这个概念——消息混在聊天列表里,谁回的、谁没回的、多久没回的,全靠自觉。
| 输入 | 家长提问内容、目标园区、意向班型、联系方式(可脱敏展示) |
| 状态变化 | 待回复 → 咨询中 → 已结束;同一位家长同一天重复提交合并成一条 |
| 输出 | 工作台"今日咨询/待回复/咨询中"三个数,以及消息页的对话记录 |
工程结论:咨询必须落成一条有状态的数据,而不是聊天记录。有状态才有时效,有时效才谈得上转化。
05 动态详情:内容页要能承接咨询
家长点进一条动态,通常是被一张教室照片吸引的。如果详情页只有图和一句"这个动态很好",家长看完就退出,这条内容白做了。详情页的任务是把浏览变成两个动作:收藏这个园区,或者问一句。
| 输入 | 动态 ID、当前用户身份(家长/游客)、是否需要关注作者 |
| 状态变化 | 游客 → 登录 → 关注/取消关注 → 点赞 → 收藏;浏览数只增不改 |
| 输出 | 一条可分享的详情链接(小程序、H5、公众号菜单都能打开)、评论区、浏览与收藏计数 |
工程结论:详情页的收藏按钮要比"点赞"大。点赞是情绪,收藏是意向,两者对运营的价值不一样。
06 园区工作台:老板要的是今天的数据
大多数托育系统的后台是给运营看的,老板一个月登一次。工作台的判断标准很简单:园长早上打开手机,30 秒内知道今天该干什么。所以它只放三类数:进来的(咨询、浏览)、要处理的(待回复、审核待办)、沉淀下来的(服务收藏、老师浏览)。
| 输入 | 当前登录园区、今日 0 点至今的咨询表与浏览埋点 |
| 状态变化 | 无状态看板:每次进入按园区 + 日期实时汇总,跨天自动归零 |
| 输出 | 八宫格看板 + 四个工作入口(园区资料、老师管理、服务管理、咨询、消息) |

【JAVA幼儿托育托管系统】实拍 02|园区详情、动态详情与园区工作台八宫格看板;截图数据为演示数据
看图对着数:工作台上半部是2×4 的八宫格——今日咨询 0、待回复 3、咨询中 3、已结束 0、审核待办 0、园区浏览 244、老师浏览 113、服务收藏 0;下半部是"工作入口"六个按钮。"待回复 3"这个数就是园长今天的动作清单,比任何报表都直接。
工程结论:看板上的数字要能点进去。点"待回复 3"直接跳到那三条咨询,"浏览 244"跳到来访明细,否则就只是个装饰。
07 点赞收藏:收藏是意向,不是数字
点赞和收藏常被做成一致的两个图标,实际价值差一个量级。点赞是刷到就点,收藏是"我以后要来看看这家"。所以收藏表要能回答三个问题:谁收藏的、收藏的是园区还是动态、什么时候收藏的。有了这三点,才有"本周新增 12 位收藏家长,其中 5 位没来过"的回访名单。
| 输入 | 用户 ID、目标类型(园区/动态)、目标 ID、动作(点赞|收藏|取消) |
| 状态变化 | 未收藏 → 已收藏 → 已取消;同一用户对同一目标只有一条有效记录 |
| 输出 | 家长"我的"页三栏数据(点赞、历史浏览、我的收藏),以及后台按园区的收藏明细 |

【JAVA幼儿托育托管系统】实拍 03|我的、我的主页、消息三页;截图数据为演示数据
第三张图是家长侧的收口:"我的"页顶部三个数(1 点赞 / 13 历史浏览 / 1 我的收藏),下面是"我的主页"和"园区工作台"两个入口,再往下是联系客服、分享好友、意见反馈、帮助中心、设置。消息页保留了"系统通知"和"老师对话"两条线,咨询回复和系统提醒不会混在一起。
工程结论:收藏表要建唯一索引(用户 + 类型 + 目标),不然取消再收藏会堆出一堆脏数据,统计直接翻倍。
三端分工:一套后端,三种壳
小程序、公众号、H5 不是三个项目。uniapp 一套代码编译出小程序和 H5 两个端,公众号走 H5 域名 + 微信授权登录,服务端只认一套 token。判断标准只有一条:同一条业务逻辑,是否只在一处实现。
| 端 | 负责什么 | 不该做什么 |
一句话判定:如果某个价格、名额或状态是前端算出来直接展示的,这套代码就不合格。三端各自只负责展示和采集,判断全部回服务端。
数据库与核心代码
七段代码都从真实链路里抽出来的,顺序是先有表、再有事务、然后解决并发与幂等、最后是权限和多端封装。字段名前后一致,`campus_id`、`consult_no`、`request_id` 这些在 SQL 和 Java 里是同一个名字,方便你对着改。
代码 1 核心表结构:园区、老师、班级、咨询、收藏
SQL · 核心表结构 |
-- 园区CREATE TABLE `campus` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `campus_name` VARCHAR(64) NOT NULL COMMENT '园区名称', `city_code` VARCHAR(12) NOT NULL COMMENT '城市编码', `address` VARCHAR(128) NOT NULL, `service_phone` VARCHAR(20) DEFAULT NULL, `class_type` VARCHAR(64) DEFAULT NULL COMMENT '全托/半托/临托', `status` TINYINT NOT NULL DEFAULT 0 COMMENT '0待审 1上架 2下架', `version` INT NOT NULL DEFAULT 0 COMMENT '乐观锁', `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_name_city` (`campus_name`,`city_code`), KEY `idx_city_status` (`city_code`,`status`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 老师CREATE TABLE `teacher` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `campus_id` BIGINT NOT NULL, `teacher_name` VARCHAR(32) NOT NULL, `post` VARCHAR(16) DEFAULT NULL COMMENT '主班/配班/保育', `cert_no` VARCHAR(32) DEFAULT NULL COMMENT '育婴师证号', `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1在职 2离职', PRIMARY KEY (`id`), KEY `idx_campus` (`campus_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 班级:容量与在册人数CREATE TABLE `campus_class` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `campus_id` BIGINT NOT NULL, `class_name` VARCHAR(32) NOT NULL, `capacity` INT NOT NULL COMMENT '核定名额', `enrolled` INT NOT NULL DEFAULT 0 COMMENT '在册人数', `version` INT NOT NULL DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY `uk_campus_class` (`campus_id`,`class_name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 咨询工单:状态机 + 幂等键CREATE TABLE `consult_order` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `campus_id` BIGINT NOT NULL, `user_id` BIGINT NOT NULL, `content` VARCHAR(512) NOT NULL, `request_id` VARCHAR(64) NOT NULL COMMENT '客户端幂等键', `status` VARCHAR(16) NOT NULL DEFAULT 'WAIT' COMMENT 'WAIT/DOING/DONE', `reply` VARCHAR(512) DEFAULT NULL, `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_request` (`request_id`), KEY `idx_campus_status` (`campus_id`,`status`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 收藏:唯一索引防脏数据CREATE TABLE `favorite` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `user_id` BIGINT NOT NULL, `target_type` VARCHAR(16) NOT NULL COMMENT 'CAMPUS/MOMENT', `target_id` BIGINT NOT NULL, `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_user_target` (`user_id`,`target_type`,`target_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
示例实现,生产环境需补充参数校验、权限、日志、监控、限流。
代码 2 咨询工单流转:待回复到已结束
JAVA · 咨询状态流转 |
@Transactional(rollbackFor = Exception.class)public void reply(Long consultId, String reply, Long campusId) { // 条件更新:只有 WAIT 才能被认领,避免两位老师同时回 LambdaUpdateWrapper<ConsultOrder> uw = new LambdaUpdateWrapper<>(); uw.eq(ConsultOrder::getId, consultId) .eq(ConsultOrder::getCampusId, campusId) .eq(ConsultOrder::getStatus, "WAIT") .set(ConsultOrder::getStatus, "DOING") .set(ConsultOrder::getReply, reply); if (consultMapper.update(null, uw) == 0) { throw new BizException("该咨询已被其他老师接单或已结束"); } // 结束由家长确认或超时任务触发,不在这里直落 DONE}// 家长端提交:用唯一索引挡重复提交public Long submit(ConsultDto dto) { ConsultOrder o = new ConsultOrder(); o.setCampusId(dto.getCampusId()); o.setUserId(dto.getUserId()); o.setContent(dto.getContent()); o.setStatus("WAIT"); o.setRequestId(dto.getRequestId()); // 前端 X-Request-Id try { consultMapper.insert(o); } catch (DuplicateKeyException e) { return consultMapper.selectByRequestId(dto.getRequestId()).getId(); } return o.getId();} |
示例实现,生产环境需补充参数校验、权限、日志、监控、限流。
代码 3 名额扣减:把师生比做成报名校验
JAVA · 名额条件扣减 |
// 不做“先查后改”,直接条件更新@Transactional(rollbackFor = Exception.class)public void enroll(Long classId, Long campusId) { LambdaUpdateWrapper<CampusClass> uw = new LambdaUpdateWrapper<>(); uw.eq(CampusClass::getId, classId) .eq(CampusClass::getCampusId, campusId) .apply("enrolled < capacity") // 名额还有余 .setSql("enrolled = enrolled + 1"); if (campusClassMapper.update(null, uw) == 0) { throw new BizException("该班名额已满,请调整班型或等待释放"); } // 名额变动后立刻校验师生比,不足则回滚 checkTeacherRatio(campusId, classId);}// 师生比:一班至少 1 主班 + 1 保育,超过 15 人追加配班private void checkTeacherRatio(Long campusId, Long classId) { int enrolled = campusClassMapper.countEnrolled(classId); int certified = teacherMapper.countOnDuty(campusId, "主班", "保育"); int need = enrolled <= 15 ? 2 : 3; if (certified < need) { throw new BizException("在职师资不足,不能继续收人"); }} |
示例实现,生产环境需补充参数校验、权限、日志、监控、限流。
代码 4 动态审核:草稿到上架的 CAS
JAVA · 内容审核 CAS |
public boolean publish(Long momentId, Long campusId) { LambdaUpdateWrapper<Moment> uw = new LambdaUpdateWrapper<>(); uw.eq(Moment::getId, momentId) .eq(Moment::getCampusId, campusId) .eq(Moment::getStatus, "AUDIT") // 只有待审的能发布 .set(Moment::getStatus, "ONLINE") .set(Moment::getPublishTime, LocalDateTime.now()); boolean ok = momentMapper.update(null, uw) > 0; if (ok) { // 审核通过后推公众号素材,失败不回滚(内容已上架) wxMaterialService.pushAfterCommit(momentId); } return ok;}// 下架只改可见,不删数据:家长端查 ONLINE,后台仍可追溯public void offline(Long momentId) { momentMapper.updateStatus(momentId, "OFFLINE");} |
示例实现,生产环境需补充参数校验、权限、日志、监控、限流。
代码 5 多园区隔离:注解 + AOP 自动拼 campus_id
JAVA · 多园区数据隔离 |
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface CampusScope { }@Aspect@Componentpublic class CampusScopeAspect { @Around("@annotation(campusScope)") public Object around(ProceedingJoinPoint pjp, CampusScope campusScope) throws Throwable { Long campusId = LoginContext.getCampusId(); if (campusId == null) throw new BizException("未登录或无园区权限"); CampusContext.set(campusId); try { return pjp.proceed(); } finally { CampusContext.clear(); // 线程池必须清 } }}// 业务层统一走 wrapper,园区 ID 不由前端传public List<ConsultOrder> waitList() { return consultMapper.selectList( new LambdaQueryWrapper<ConsultOrder>() .eq(ConsultOrder::getCampusId, CampusContext.get()) .eq(ConsultOrder::getStatus, "WAIT") .orderByAsc(ConsultOrder::getCreateTime));} |
示例实现,生产环境需补充参数校验、权限、日志、监控、限流。
代码 6 uniapp 请求封装:三端共用幂等键
JAVASCRIPT · uniapp 请求封装 |
const BASE = process.env.VUE_APP_BASE_API;function uuid() { return 'xxxxxx'.replace(/x/g, () => Math.floor(Math.random() * 16).toString(16));}export default function request(opts) { const id = uuid(); // 一次提交一个幂等键 return new Promise((resolve, reject) => { uni.request({ url: BASE + opts.url, method: opts.method || 'GET', data: opts.data, header: { 'content-type': 'application/json', 'X-Request-Id': id, 'X-Client': opts.client || 'mp', // mp / h5 / oa 'Authorization': uni.getStorageSync('token') || '' }, success: (res) => { const body = res.data || {}; if (body.code === 0) return resolve(body.data); if (body.code === 401) { uni.reLaunch({ url: '/pages/login/index' }); return reject(body); } uni.showToast({ title: body.msg || '请求失败', icon: 'none' }); reject(body); }, fail: (err) => reject(err) }); });} |
示例实现,生产环境需补充参数校验、权限、日志、监控、限流。
代码 7 后台咨询列表:ElementUI 表格与状态映射
VUE · 后台咨询表格 |
<el-table :data="list" border size="small"> <el-table-column prop="createTime" label="提交时间" width="150"></el-table-column> <el-table-column prop="campusName" label="园区" width="120"></el-table-column> <el-table-column prop="content" label="咨询内容" show-overflow-tooltip></el-table-column> <el-table-column prop="status" label="状态" width="100"> <template slot-scope="scope"> <el-tag :type="statusType(scope.row.status)" size="mini"> {{ statusText(scope.row.status) }} </el-tag> </template> </el-table-column> <el-table-column label="操作" width="120"> <template slot-scope="scope"> <el-button type="text" size="mini" :disabled="scope.row.status === 'DONE'" @click="openReply(scope.row)">回复</el-button> </template> </el-table-column></el-table><el-pagination background layout="total, prev, pager, next" :total="total" :page-size="10" @current-change="load"></el-pagination>statusText(s) { return { WAIT: '待回复', DOING: '咨询中', DONE: '已结束' }[s]; }statusType(s) { return { WAIT: 'warning', DOING: '', DONE: 'info' }[s]; } |
示例实现,生产环境需补充参数校验、权限、日志、监控、限流。
合规与上线检查
托育行业同时被教育和卫健两条线管,家长端又涉及未成年人信息,合规检查比一般商城严。下面六条是上线前必须落地的,不是建议。
1. 未成年人信息最小化。动态里的孩子照片必须打码或只拍背影,人脸不留原始图;家长手机号在列表页脱敏展示(159****8330 这种)。
2. 资质要在园区档案里留痕。托育机构备案证明、食品经营许可、老师育婴师证,建议只存证号与有效期,扫描件放对象存储并加权限。
3. 收费口径必须公示且可追溯。班型、月费、餐费、退费规则写进园区档案,家长端展示的与合同一致,改动留版本。
4. 咨询与回访要有时间记录。谁在什么时候回复的、隔了多久,后台能查,既是管理也是纠纷时的凭证。
5. 数据分级与权限。家长看不到别的园区的咨询,老师看不到财务,园区管理员只能看本园区,权限用注解 + 拦截器兜住。
6. 不做违规承诺。招生文案里不出现"包过""保证入托""与某园直连"这类表述,也不要把家长信息导出成名单对外提供。
| 检查项 | 上线前状态 |
适合谁
连锁托育机构。两家以上园区、老师在园区之间调岗,最需要"一套后台管多个园区 + 家长端按城市找园"。
单店但想做私域的园长。不指望投广告,靠动态和家长转介绍招生,需要内容能沉淀、咨询不漏。
做托育 SaaS 的独立开发者。要一套能改的底座:表结构清爽、权限是注解式的、三端一套代码,方便按客户加模块。
刚拿牌照准备开业的新园。先把园区档案、班型、老师资质建成"能对家长展示"的样子,开业当天就能用。
常见问题
Q:只有小程序够用吗,为什么还要公众号和 H5?小程序负责"用起来",公众号负责"传出去"(文章、菜单、模板消息),H5 负责"发得动"(朋友圈、微信群、短信落地页)。三端共用一套后端,维护成本不在三倍。
Q:源码交付包含管理后台吗?包含。Vue + ElementUI 的后台源码、uniapp 家长端源码、SpringBoot 服务端源码三套一起给,不含第三方付费插件。
Q:能改成幼儿园或早教中心用吗?能。园区、班级、老师、咨询、动态这套模型是通用的,改字段和文案即可,班型可以从托育的"全托/半托/临托"换成幼儿园的小班中班大班。
Q:咨询多了会不会漏?不会静默丢。工单有状态和唯一索引,工作台的"待回复"就是未处理数,超时可以做提醒。
Q:部署要什么环境?一台 2C4G 的云服务器 + MySQL 5.7/8.0 即可起步,小程序需要企业主体和类目资质,公众号需要认证服务号才能用模板消息。
Q:能对接现有的收费或门禁系统吗?服务端留了统一出口层,按对方接口补一个适配器即可,不需要改业务代码。
写在最后
这套系统解决不了"招生难",它解决的是把已经进来的家长接住:园区信息是准的、老师是谁查得到、动态有人看、咨询有人回、收藏的人能再联系上。这五件事做到了,剩下的才是投放和口碑。
如果你正在做托育系统、或者手里有一个园要上线,欢迎找我领取演示账号和部署说明,也可以按你的业务形态聊改造点。源码交付,能改、能扩、能私有化部署。















































































