大家好我是Java1234_小锋老师分享一套锋哥原创的微信小程序个人健康管理系统(带AI智能客服功能)(Spring AI 2.0SpringBoot4Vue3)项目介绍随着国民生活水平的不断提高和健康意识的逐步增强人们对个人健康的日常管理需求日益迫切。传统的健康记录方式多以纸质笔记或单机软件为主存在数据分散、难以长期追踪、缺乏专业指导等问题。与此同时微信小程序凭借“无需安装、即用即走”的特性已成为移动互联网时代轻量级应用的主流载体而以大语言模型为核心的人工智能技术的成熟则为健康咨询的智能化、个性化提供了全新的可能。在此背景下本文设计并实现了一套微信小程序个人健康管理系统并集成基于Spring AI 2.0的AI智能客服功能。本系统采用前后端分离架构。用户端基于微信小程序原生框架开发后台管理端采用Vue3构建服务端基于SpringBoot4搭建数据持久化采用MySQL数据库并通过MyBatis-Plus实现数据访问。系统主要实现了用户管理、健康数据记录与可视化、饮食与运动记录、健康计划管理、健康资讯浏览以及AI智能客服等核心功能。其中AI智能客服模块借助Spring AI 2.0统一的ChatClient抽象对接大语言模型结合用户的健康画像构建提示词Prompt实现了流式输出的个性化健康问答与建议。经过系统测试本系统功能完整、运行稳定、交互友好能够帮助用户便捷地记录和管理个人健康数据并通过AI智能客服获得即时的健康咨询服务具有较好的实用价值和推广意义。源码下载链接https://pan.baidu.com/s/16V9LEpyuDZ2vzt7Z2OUnuw?pwd1234提取码1234系统展示核心代码package com.java1234.health.controller; import com.java1234.health.common.PageResult; import com.java1234.health.common.Result; import com.java1234.health.entity.HealthMetric; import com.java1234.health.service.HealthMetricService; import org.springframework.web.bind.annotation.*; import java.util.List; /** * 健康指标控制器 * * author Java1234 */ RestController public class HealthMetricController { private final HealthMetricService healthMetricService; public HealthMetricController(HealthMetricService healthMetricService) { this.healthMetricService healthMetricService; } /** 后台分页查询 */ GetMapping(/admin/metric/page) public ResultPageResultHealthMetric adminPage( RequestParam(defaultValue 1) int pageNum, RequestParam(defaultValue 10) int pageSize, RequestParam(required false) Long userId, RequestParam(required false) String type) { return Result.success(healthMetricService.page(pageNum, pageSize, userId, type)); } /** 小程序分页查询 */ GetMapping(/wx/metric/page) public ResultPageResultHealthMetric wxPage( RequestAttribute Long userId, RequestParam(defaultValue 1) int pageNum, RequestParam(defaultValue 10) int pageSize, RequestParam(required false) String type) { return Result.success(healthMetricService.page(pageNum, pageSize, userId, type)); } /** 指标趋势 */ GetMapping(/wx/metric/trend) public ResultListHealthMetric trend( RequestAttribute Long userId, RequestParam String type) { return Result.success(healthMetricService.trend(userId, type)); } /** 最新指标 */ GetMapping(/wx/metric/latest) public ResultListHealthMetric latest(RequestAttribute Long userId) { return Result.success(healthMetricService.latest(userId)); } PostMapping({/admin/metric, /wx/metric}) public ResultVoid add(RequestBody HealthMetric metric, RequestAttribute(required false) Long userId) { if (userId ! null) metric.setUserId(userId); healthMetricService.add(metric); return Result.success(); } PutMapping({/admin/metric, /wx/metric}) public ResultVoid update(RequestBody HealthMetric metric) { healthMetricService.update(metric); return Result.success(); } DeleteMapping({/admin/metric/{id}, /wx/metric/{id}}) public ResultVoid delete(PathVariable Long id) { healthMetricService.delete(id); return Result.success(); } }template div classpage-container div classpage-headerh2健康指标/h2/div div classsearch-bar el-select v-modelqueryType placeholder指标类型 clearable stylewidth:140px changeloadData el-option v-fort in types :keyt :labelt :valuet / /el-select el-button typeprimary clickloadDatael-iconSearch //el-icon搜索/el-button el-button typesuccess clickopenDialog()el-iconPlus //el-icon新增/el-button /div el-table :datatableData stripe border stylewidth:100% el-table-column propid labelID min-width60 / el-table-column propnickname label用户 min-width90 / el-table-column proptype label类型 min-width80 / el-table-column label数值 min-width120 template #default{ row } {{ row.value }}{{ row.value2 ? / row.value2 : }} {{ row.unit }} /template /el-table-column el-table-column proprecordTime label记录时间 min-width160 template #default{ row }{{ formatDateTime(row.recordTime) }}/template /el-table-column el-table-column propremark label备注 min-width120 show-overflow-tooltip / el-table-column label操作 min-width140 fixedright template #default{ row } el-button typeprimary link clickopenDialog(row)编辑/el-button el-button typedanger link clickhandleDelete(row.id)删除/el-button /template /el-table-column /el-table el-pagination classpagination v-model:current-pagepageNum v-model:page-sizepageSize :totaltotal layouttotal, prev, pager, next changeloadData / el-dialog v-modeldialogVisible :titleform.id ? 编辑指标 : 新增指标 width500px el-form :modelform label-width90px el-form-item label用户IDel-input-number v-modelform.userId :min1 //el-form-item el-form-item label类型 el-select v-modelform.typeel-option v-fort in types :keyt :labelt :valuet //el-select /el-form-item el-form-item label数值el-input-number v-modelform.value :precision2 //el-form-item el-form-item label辅助值 v-ifform.type 血压el-input-number v-modelform.value2 :precision2 //el-form-item el-form-item label单位el-input v-modelform.unit //el-form-item el-form-item label记录时间el-date-picker v-modelform.recordTime typedatetime value-formatYYYY-MM-DD HH:mm:ss //el-form-item el-form-item label备注el-input v-modelform.remark //el-form-item /el-form template #footer el-button clickdialogVisible false取消/el-button el-button typeprimary clickhandleSave保存/el-button /template /el-dialog /div /template script setup import { ref, reactive, onMounted } from vue import { ElMessage, ElMessageBox } from element-plus import request from /utils/request import { formatDateTime } from /utils/format const types [体重, 血压, 血糖, 心率, 体温] const tableData ref([]) const total ref(0) const pageNum ref(1) const pageSize ref(10) const queryType ref() const dialogVisible ref(false) const form reactive({ id: null, userId: 1, type: 体重, value: 0, value2: null, unit: kg, recordTime: , remark: }) onMounted(() loadData()) async function loadData() { const res await request.get(/admin/metric/page, { params: { pageNum: pageNum.value, pageSize: pageSize.value, type: queryType.value } }) tableData.value res.data.records total.value res.data.total } function openDialog(row) { Object.assign(form, row ? { ...row } : { id: null, userId: 1, type: 体重, value: 0, value2: null, unit: kg, recordTime: new Date().toISOString().slice(0,19).replace(T, ), remark: }) dialogVisible.value true } async function handleSave() { if (form.id) await request.put(/admin/metric, form) else await request.post(/admin/metric, form) ElMessage.success(保存成功) dialogVisible.value false loadData() } async function handleDelete(id) { await ElMessageBox.confirm(确定删除吗, 提示, { type: warning }) await request.delete(/admin/metric/${id}) ElMessage.success(删除成功) loadData() } /script style scoped .pagination { margin-top: 16px; justify-content: flex-end; } /style
分享一套锋哥原创的微信小程序个人健康管理系统(带AI智能客服功能)(Spring AI 2.0+SpringBoot4+Vue3)
大家好我是Java1234_小锋老师分享一套锋哥原创的微信小程序个人健康管理系统(带AI智能客服功能)(Spring AI 2.0SpringBoot4Vue3)项目介绍随着国民生活水平的不断提高和健康意识的逐步增强人们对个人健康的日常管理需求日益迫切。传统的健康记录方式多以纸质笔记或单机软件为主存在数据分散、难以长期追踪、缺乏专业指导等问题。与此同时微信小程序凭借“无需安装、即用即走”的特性已成为移动互联网时代轻量级应用的主流载体而以大语言模型为核心的人工智能技术的成熟则为健康咨询的智能化、个性化提供了全新的可能。在此背景下本文设计并实现了一套微信小程序个人健康管理系统并集成基于Spring AI 2.0的AI智能客服功能。本系统采用前后端分离架构。用户端基于微信小程序原生框架开发后台管理端采用Vue3构建服务端基于SpringBoot4搭建数据持久化采用MySQL数据库并通过MyBatis-Plus实现数据访问。系统主要实现了用户管理、健康数据记录与可视化、饮食与运动记录、健康计划管理、健康资讯浏览以及AI智能客服等核心功能。其中AI智能客服模块借助Spring AI 2.0统一的ChatClient抽象对接大语言模型结合用户的健康画像构建提示词Prompt实现了流式输出的个性化健康问答与建议。经过系统测试本系统功能完整、运行稳定、交互友好能够帮助用户便捷地记录和管理个人健康数据并通过AI智能客服获得即时的健康咨询服务具有较好的实用价值和推广意义。源码下载链接https://pan.baidu.com/s/16V9LEpyuDZ2vzt7Z2OUnuw?pwd1234提取码1234系统展示核心代码package com.java1234.health.controller; import com.java1234.health.common.PageResult; import com.java1234.health.common.Result; import com.java1234.health.entity.HealthMetric; import com.java1234.health.service.HealthMetricService; import org.springframework.web.bind.annotation.*; import java.util.List; /** * 健康指标控制器 * * author Java1234 */ RestController public class HealthMetricController { private final HealthMetricService healthMetricService; public HealthMetricController(HealthMetricService healthMetricService) { this.healthMetricService healthMetricService; } /** 后台分页查询 */ GetMapping(/admin/metric/page) public ResultPageResultHealthMetric adminPage( RequestParam(defaultValue 1) int pageNum, RequestParam(defaultValue 10) int pageSize, RequestParam(required false) Long userId, RequestParam(required false) String type) { return Result.success(healthMetricService.page(pageNum, pageSize, userId, type)); } /** 小程序分页查询 */ GetMapping(/wx/metric/page) public ResultPageResultHealthMetric wxPage( RequestAttribute Long userId, RequestParam(defaultValue 1) int pageNum, RequestParam(defaultValue 10) int pageSize, RequestParam(required false) String type) { return Result.success(healthMetricService.page(pageNum, pageSize, userId, type)); } /** 指标趋势 */ GetMapping(/wx/metric/trend) public ResultListHealthMetric trend( RequestAttribute Long userId, RequestParam String type) { return Result.success(healthMetricService.trend(userId, type)); } /** 最新指标 */ GetMapping(/wx/metric/latest) public ResultListHealthMetric latest(RequestAttribute Long userId) { return Result.success(healthMetricService.latest(userId)); } PostMapping({/admin/metric, /wx/metric}) public ResultVoid add(RequestBody HealthMetric metric, RequestAttribute(required false) Long userId) { if (userId ! null) metric.setUserId(userId); healthMetricService.add(metric); return Result.success(); } PutMapping({/admin/metric, /wx/metric}) public ResultVoid update(RequestBody HealthMetric metric) { healthMetricService.update(metric); return Result.success(); } DeleteMapping({/admin/metric/{id}, /wx/metric/{id}}) public ResultVoid delete(PathVariable Long id) { healthMetricService.delete(id); return Result.success(); } }template div classpage-container div classpage-headerh2健康指标/h2/div div classsearch-bar el-select v-modelqueryType placeholder指标类型 clearable stylewidth:140px changeloadData el-option v-fort in types :keyt :labelt :valuet / /el-select el-button typeprimary clickloadDatael-iconSearch //el-icon搜索/el-button el-button typesuccess clickopenDialog()el-iconPlus //el-icon新增/el-button /div el-table :datatableData stripe border stylewidth:100% el-table-column propid labelID min-width60 / el-table-column propnickname label用户 min-width90 / el-table-column proptype label类型 min-width80 / el-table-column label数值 min-width120 template #default{ row } {{ row.value }}{{ row.value2 ? / row.value2 : }} {{ row.unit }} /template /el-table-column el-table-column proprecordTime label记录时间 min-width160 template #default{ row }{{ formatDateTime(row.recordTime) }}/template /el-table-column el-table-column propremark label备注 min-width120 show-overflow-tooltip / el-table-column label操作 min-width140 fixedright template #default{ row } el-button typeprimary link clickopenDialog(row)编辑/el-button el-button typedanger link clickhandleDelete(row.id)删除/el-button /template /el-table-column /el-table el-pagination classpagination v-model:current-pagepageNum v-model:page-sizepageSize :totaltotal layouttotal, prev, pager, next changeloadData / el-dialog v-modeldialogVisible :titleform.id ? 编辑指标 : 新增指标 width500px el-form :modelform label-width90px el-form-item label用户IDel-input-number v-modelform.userId :min1 //el-form-item el-form-item label类型 el-select v-modelform.typeel-option v-fort in types :keyt :labelt :valuet //el-select /el-form-item el-form-item label数值el-input-number v-modelform.value :precision2 //el-form-item el-form-item label辅助值 v-ifform.type 血压el-input-number v-modelform.value2 :precision2 //el-form-item el-form-item label单位el-input v-modelform.unit //el-form-item el-form-item label记录时间el-date-picker v-modelform.recordTime typedatetime value-formatYYYY-MM-DD HH:mm:ss //el-form-item el-form-item label备注el-input v-modelform.remark //el-form-item /el-form template #footer el-button clickdialogVisible false取消/el-button el-button typeprimary clickhandleSave保存/el-button /template /el-dialog /div /template script setup import { ref, reactive, onMounted } from vue import { ElMessage, ElMessageBox } from element-plus import request from /utils/request import { formatDateTime } from /utils/format const types [体重, 血压, 血糖, 心率, 体温] const tableData ref([]) const total ref(0) const pageNum ref(1) const pageSize ref(10) const queryType ref() const dialogVisible ref(false) const form reactive({ id: null, userId: 1, type: 体重, value: 0, value2: null, unit: kg, recordTime: , remark: }) onMounted(() loadData()) async function loadData() { const res await request.get(/admin/metric/page, { params: { pageNum: pageNum.value, pageSize: pageSize.value, type: queryType.value } }) tableData.value res.data.records total.value res.data.total } function openDialog(row) { Object.assign(form, row ? { ...row } : { id: null, userId: 1, type: 体重, value: 0, value2: null, unit: kg, recordTime: new Date().toISOString().slice(0,19).replace(T, ), remark: }) dialogVisible.value true } async function handleSave() { if (form.id) await request.put(/admin/metric, form) else await request.post(/admin/metric, form) ElMessage.success(保存成功) dialogVisible.value false loadData() } async function handleDelete(id) { await ElMessageBox.confirm(确定删除吗, 提示, { type: warning }) await request.delete(/admin/metric/${id}) ElMessage.success(删除成功) loadData() } /script style scoped .pagination { margin-top: 16px; justify-content: flex-end; } /style