diff --git a/intc-common/intc-common-core/src/main/java/com/intc/common/core/handler/JsonNodeTypeHandler.java b/intc-common/intc-common-core/src/main/java/com/intc/common/core/handler/JsonNodeTypeHandler.java new file mode 100644 index 0000000..cdb6ee5 --- /dev/null +++ b/intc-common/intc-common-core/src/main/java/com/intc/common/core/handler/JsonNodeTypeHandler.java @@ -0,0 +1,63 @@ +package com.intc.common.core.handler; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedTypes; +import org.postgresql.util.PGobject; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * PostgreSQL JSONB 类型处理器 + * 用于 MyBatis 映射 JsonNode 类型 + * + * @author bot5 + * @date 2026-03-19 + */ +@MappedTypes(JsonNode.class) +public class JsonNodeTypeHandler extends BaseTypeHandler { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, JsonNode parameter, JdbcType jdbcType) throws SQLException { + PGobject pgObject = new PGobject(); + pgObject.setType("jsonb"); + pgObject.setValue(parameter.toString()); + ps.setObject(i, pgObject); + } + + @Override + public JsonNode getNullableResult(ResultSet rs, String columnName) throws SQLException { + String value = rs.getString(columnName); + return parseJson(value); + } + + @Override + public JsonNode getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + String value = rs.getString(columnIndex); + return parseJson(value); + } + + @Override + public JsonNode getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + String value = cs.getString(columnIndex); + return parseJson(value); + } + + private JsonNode parseJson(String value) { + if (value == null || value.isEmpty()) { + return null; + } + try { + return objectMapper.readTree(value); + } catch (Exception e) { + return null; + } + } +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/controller/HealthMedicationPlanController.java b/intc-modules/intc-health/src/main/java/com/intc/health/controller/HealthMedicationPlanController.java deleted file mode 100644 index bea6b88..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/controller/HealthMedicationPlanController.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.intc.health.controller; - -import com.intc.common.core.utils.poi.ExcelUtil; -import com.intc.common.core.web.controller.BaseController; -import com.intc.common.core.web.domain.AjaxResult; -import com.intc.common.core.web.page.TableDataInfo; -import com.intc.common.log.annotation.Log; -import com.intc.common.log.enums.BusinessType; -import com.intc.common.security.annotation.RequiresPermissions; -import com.intc.health.domain.HealthMedicationPlan; -import com.intc.health.domain.dto.HealthMedicationPlanDto; -import com.intc.health.domain.vo.HealthMedicationPlanVo; -import com.intc.health.service.IHealthMedicationPlanService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * 用药计划Controller - * - * @author intc - * @date 2025-03-18 - */ -@Api(tags = "用药计划") -@RestController -@RequestMapping("/medicationPlan") -public class HealthMedicationPlanController extends BaseController -{ - @Resource - private IHealthMedicationPlanService healthMedicationPlanService; - - /** - * 查询用药计划列表 - */ - @ApiOperation(value = "查询用药计划列表", response = HealthMedicationPlanVo.class) - @RequiresPermissions("health:medicationPlan:list") - @GetMapping("/list") - public TableDataInfo list(HealthMedicationPlanDto dto) - { - startPage(); - List list = healthMedicationPlanService.selectHealthMedicationPlanList(dto); - return getDataTable(list); - } - - /** - * 导出用药计划列表 - */ - @ApiOperation(value = "导出用药计划列表") - @RequiresPermissions("health:medicationPlan:export") - @Log(title = "用药计划", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, HealthMedicationPlanDto dto) - { - List list = healthMedicationPlanService.selectHealthMedicationPlanList(dto); - ExcelUtil util = new ExcelUtil(HealthMedicationPlanVo.class); - util.exportExcel(response, list, "用药计划数据"); - } - - /** - * 获取用药计划详细信息 - */ - @ApiOperation(value = "获取用药计划详细信息") - @RequiresPermissions("health:medicationPlan:query") - @GetMapping(value = "/{id}") - public AjaxResult getInfo(@PathVariable("id") Long id) - { - return success(healthMedicationPlanService.selectHealthMedicationPlanById(id)); - } - - /** - * 新增用药计划 - */ - @ApiOperation(value = "新增用药计划") - @RequiresPermissions("health:medicationPlan:add") - @Log(title = "用药计划", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody HealthMedicationPlan plan) - { - return toAjax(healthMedicationPlanService.insertHealthMedicationPlan(plan)); - } - - /** - * 修改用药计划 - */ - @ApiOperation(value = "修改用药计划") - @RequiresPermissions("health:medicationPlan:edit") - @Log(title = "用药计划", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody HealthMedicationPlan plan) - { - return toAjax(healthMedicationPlanService.updateHealthMedicationPlan(plan)); - } - - /** - * 删除用药计划 - */ - @ApiOperation(value = "删除用药计划") - @RequiresPermissions("health:medicationPlan:remove") - @Log(title = "用药计划", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public AjaxResult remove(@PathVariable Long[] ids) - { - return toAjax(healthMedicationPlanService.deleteHealthMedicationPlanByIds(ids)); - } - - /** - * 暂停用药计划 - */ - @ApiOperation(value = "暂停用药计划") - @RequiresPermissions("health:medicationPlan:edit") - @Log(title = "用药计划", businessType = BusinessType.UPDATE) - @PutMapping("/pause/{id}") - public AjaxResult pause(@PathVariable Long id) - { - return toAjax(healthMedicationPlanService.pauseHealthMedicationPlan(id)); - } - - /** - * 恢复用药计划 - */ - @ApiOperation(value = "恢复用药计划") - @RequiresPermissions("health:medicationPlan:edit") - @Log(title = "用药计划", businessType = BusinessType.UPDATE) - @PutMapping("/resume/{id}") - public AjaxResult resume(@PathVariable Long id) - { - return toAjax(healthMedicationPlanService.resumeHealthMedicationPlan(id)); - } - - /** - * 结束用药计划 - */ - @ApiOperation(value = "结束用药计划") - @RequiresPermissions("health:medicationPlan:edit") - @Log(title = "用药计划", businessType = BusinessType.UPDATE) - @PutMapping("/end/{id}") - public AjaxResult end(@PathVariable Long id) - { - return toAjax(healthMedicationPlanService.endHealthMedicationPlan(id)); - } -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/controller/HealthMedicationRecordController.java b/intc-modules/intc-health/src/main/java/com/intc/health/controller/HealthMedicationRecordController.java deleted file mode 100644 index 6392cd8..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/controller/HealthMedicationRecordController.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.intc.health.controller; - -import com.intc.common.core.utils.poi.ExcelUtil; -import com.intc.common.core.web.controller.BaseController; -import com.intc.common.core.web.domain.AjaxResult; -import com.intc.common.core.web.page.TableDataInfo; -import com.intc.common.log.annotation.Log; -import com.intc.common.log.enums.BusinessType; -import com.intc.common.security.annotation.RequiresPermissions; -import com.intc.health.domain.HealthMedicationRecord; -import com.intc.health.domain.dto.HealthMedicationRecordDto; -import com.intc.health.domain.vo.HealthMedicationRecordVo; -import com.intc.health.service.IHealthMedicationRecordService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * 用药记录Controller - * - * @author intc - * @date 2025-03-18 - */ -@Api(tags = "用药记录") -@RestController -@RequestMapping("/medicationRecord") -public class HealthMedicationRecordController extends BaseController -{ - @Resource - private IHealthMedicationRecordService healthMedicationRecordService; - - /** - * 查询用药记录列表 - */ - @ApiOperation(value = "查询用药记录列表", response = HealthMedicationRecordVo.class) - @RequiresPermissions("health:medicationRecord:list") - @GetMapping("/list") - public TableDataInfo list(HealthMedicationRecordDto dto) - { - startPage(); - List list = healthMedicationRecordService.selectHealthMedicationRecordList(dto); - return getDataTable(list); - } - - /** - * 查询今日用药记录 - */ - @ApiOperation(value = "查询今日用药记录") - @RequiresPermissions("health:medicationRecord:list") - @GetMapping("/today") - public AjaxResult today(@RequestParam(required = false) Long personId) - { - List list = healthMedicationRecordService.getTodayRecords(personId); - return success(list); - } - - /** - * 查询某计划某天的用药记录 - */ - @ApiOperation(value = "查询某计划某天的用药记录") - @RequiresPermissions("health:medicationRecord:list") - @GetMapping("/plan/{planId}/date/{date}") - public AjaxResult getByPlanAndDate(@PathVariable Long planId, @PathVariable String date) - { - List list = healthMedicationRecordService.selectRecordByPlanAndDate(planId, date); - return success(list); - } - - /** - * 导出用药记录列表 - */ - @ApiOperation(value = "导出用药记录列表") - @RequiresPermissions("health:medicationRecord:export") - @Log(title = "用药记录", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, HealthMedicationRecordDto dto) - { - List list = healthMedicationRecordService.selectHealthMedicationRecordList(dto); - ExcelUtil util = new ExcelUtil(HealthMedicationRecordVo.class); - util.exportExcel(response, list, "用药记录数据"); - } - - /** - * 获取用药记录详细信息 - */ - @ApiOperation(value = "获取用药记录详细信息") - @RequiresPermissions("health:medicationRecord:query") - @GetMapping(value = "/{id}") - public AjaxResult getInfo(@PathVariable("id") Long id) - { - return success(healthMedicationRecordService.selectHealthMedicationRecordById(id)); - } - - /** - * 新增用药记录(手动记录补服) - */ - @ApiOperation(value = "新增用药记录") - @RequiresPermissions("health:medicationRecord:add") - @Log(title = "用药记录", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody HealthMedicationRecord record) - { - return toAjax(healthMedicationRecordService.insertHealthMedicationRecord(record)); - } - - /** - * 修改用药记录 - */ - @ApiOperation(value = "修改用药记录") - @RequiresPermissions("health:medicationRecord:edit") - @Log(title = "用药记录", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody HealthMedicationRecord record) - { - return toAjax(healthMedicationRecordService.updateHealthMedicationRecord(record)); - } - - /** - * 删除用药记录 - */ - @ApiOperation(value = "删除用药记录") - @RequiresPermissions("health:medicationRecord:remove") - @Log(title = "用药记录", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public AjaxResult remove(@PathVariable Long[] ids) - { - return toAjax(healthMedicationRecordService.deleteHealthMedicationRecordByIds(ids)); - } - - /** - * 服药(标记为已服用) - */ - @ApiOperation(value = "服药(标记为已服用)") - @RequiresPermissions("health:medicationRecord:edit") - @Log(title = "用药记录", businessType = BusinessType.UPDATE) - @PutMapping("/take/{id}") - public AjaxResult take(@PathVariable Long id, - @RequestParam(required = false) Double dosage, - @RequestParam(required = false) String remark) - { - return toAjax(healthMedicationRecordService.takeMedication(id, dosage, remark)); - } - - /** - * 跳过服药 - */ - @ApiOperation(value = "跳过服药") - @RequiresPermissions("health:medicationRecord:edit") - @Log(title = "用药记录", businessType = BusinessType.UPDATE) - @PutMapping("/skip/{id}") - public AjaxResult skip(@PathVariable Long id, - @RequestParam(required = false) String remark) - { - return toAjax(healthMedicationRecordService.skipMedication(id, remark)); - } -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationAdherenceController.java b/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationAdherenceController.java index 3ea6897..3f02a8d 100644 --- a/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationAdherenceController.java +++ b/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationAdherenceController.java @@ -1,15 +1,16 @@ package com.intc.health.controller; import com.intc.common.core.web.domain.AjaxResult; -import com.intc.health.domain.dto.MedicationAdherenceDto; import com.intc.health.domain.vo.DailyAdherenceVo; import com.intc.health.domain.vo.MedicationAdherenceVo; import com.intc.health.service.IMedicationAdherenceService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.time.LocalDate; import java.util.List; import java.util.Map; @@ -27,100 +28,55 @@ public class MedicationAdherenceController { @Resource private IMedicationAdherenceService adherenceService; - /** - * 获取总体依从性统计 - */ @GetMapping("/overall") @ApiOperation("获取总体依从性统计") - public AjaxResult getOverallAdherence(MedicationAdherenceDto dto) { - MedicationAdherenceVo vo = adherenceService.getOverallAdherence(dto); + public AjaxResult getOverallAdherence( + @RequestParam(required = false) Long memberId, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) { + MedicationAdherenceVo vo = adherenceService.getOverallAdherence(memberId, startDate, endDate); return AjaxResult.success(vo); } - /** - * 获取每日依从性统计列表(趋势图) - */ @GetMapping("/daily") @ApiOperation("获取每日依从性统计列表") - public AjaxResult getDailyAdherenceList(MedicationAdherenceDto dto) { - List list = adherenceService.getDailyAdherenceList(dto); + public AjaxResult getDailyAdherenceList( + @RequestParam(required = false) Long memberId, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) { + List list = adherenceService.getDailyAdherenceList(memberId, startDate, endDate); return AjaxResult.success(list); } - /** - * 获取日历视图数据 - */ @GetMapping("/calendar") @ApiOperation("获取日历视图数据") public AjaxResult getCalendarData( - @RequestParam(required = false) Long personId, + @RequestParam(required = false) Long memberId, @RequestParam String yearMonth) { - List list = adherenceService.getCalendarData(personId, yearMonth); + List list = adherenceService.getCalendarData(memberId, yearMonth); return AjaxResult.success(list); } - /** - * 获取各时段服药统计 - */ @GetMapping("/timeSlot") @ApiOperation("获取各时段服药统计") - public AjaxResult getTimeSlotAdherence(MedicationAdherenceDto dto) { - Map map = adherenceService.getTimeSlotAdherence(dto); + public AjaxResult getTimeSlotAdherence( + @RequestParam(required = false) Long memberId, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) { + Map map = adherenceService.getTimeSlotAdherence(memberId, startDate, endDate); return AjaxResult.success(map); } - /** - * 获取各药品依从性统计 - */ - @GetMapping("/medicine") - @ApiOperation("获取各药品依从性统计") - public AjaxResult getMedicineAdherenceList(MedicationAdherenceDto dto) { - List list = adherenceService.getMedicineAdherenceList(dto); - return AjaxResult.success(list); - } - - /** - * 获取各人员依从性统计 - */ - @GetMapping("/person") - @ApiOperation("获取各人员依从性统计") - public AjaxResult getPersonAdherenceList(MedicationAdherenceDto dto) { - List list = adherenceService.getPersonAdherenceList(dto); - return AjaxResult.success(list); - } - - /** - * 获取漏服原因统计 - */ - @GetMapping("/missedReason") - @ApiOperation("获取漏服原因统计") - public AjaxResult getMissedReasonStats(MedicationAdherenceDto dto) { - Map map = adherenceService.getMissedReasonStats(dto); - return AjaxResult.success(map); - } - - /** - * 获取仪表盘概览数据 - */ @GetMapping("/dashboard") @ApiOperation("获取仪表盘概览数据") - public AjaxResult getDashboard(@RequestParam(required = false) Long personId) { - // 获取最近7天的统计数据 - MedicationAdherenceDto dto = new MedicationAdherenceDto(); - dto.setPersonId(personId); - dto.setStartDate(java.time.LocalDate.now().minusDays(7).toString()); - dto.setEndDate(java.time.LocalDate.now().toString()); + public AjaxResult getDashboard(@RequestParam(required = false) Long memberId) { + LocalDate today = LocalDate.now(); + LocalDate weekAgo = today.minusDays(7); Map result = new java.util.HashMap<>(); - - // 总体统计 - result.put("overall", adherenceService.getOverallAdherence(dto)); - - // 每日趋势 - result.put("dailyTrend", adherenceService.getDailyAdherenceList(dto)); - - // 时段统计 - result.put("timeSlot", adherenceService.getTimeSlotAdherence(dto)); + result.put("overall", adherenceService.getOverallAdherence(memberId, weekAgo, today)); + result.put("dailyTrend", adherenceService.getDailyAdherenceList(memberId, weekAgo, today)); + result.put("timeSlot", adherenceService.getTimeSlotAdherence(memberId, weekAgo, today)); return AjaxResult.success(result); } diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationPlanController.java b/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationPlanController.java new file mode 100644 index 0000000..2949623 --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationPlanController.java @@ -0,0 +1,97 @@ +package com.intc.health.controller; + +import com.intc.common.core.web.controller.BaseController; +import com.intc.common.core.web.domain.AjaxResult; +import com.intc.common.core.web.page.TableDataInfo; +import com.intc.common.log.annotation.Log; +import com.intc.common.log.enums.BusinessType; +import com.intc.common.security.annotation.RequiresPermissions; +import com.intc.health.domain.MedicationPlan; +import com.intc.health.domain.dto.MedicationPlanDto; +import com.intc.health.domain.vo.MedicationPlanVo; +import com.intc.health.service.IMedicationPlanService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 用药计划Controller + * + * @author bot5 + * @date 2026-03-19 + */ +@RestController +@RequestMapping("/health/medicationPlan") +@Api(tags = "用药计划管理") +public class MedicationPlanController extends BaseController { + + @Resource + private IMedicationPlanService planService; + + @GetMapping("/list") + @ApiOperation("查询用药计划列表") + @RequiresPermissions("health:medicationPlan:list") + public TableDataInfo list(MedicationPlanDto dto) { + startPage(); + List list = planService.selectList(dto); + return getDataTable(list); + } + + @GetMapping("/{id}") + @ApiOperation("查询用药计划详情") + @RequiresPermissions("health:medicationPlan:query") + public AjaxResult getInfo(@PathVariable Long id) { + return success(planService.selectById(id)); + } + + @PostMapping + @ApiOperation("新增用药计划") + @RequiresPermissions("health:medicationPlan:add") + @Log(title = "用药计划", businessType = BusinessType.INSERT) + public AjaxResult add(@RequestBody MedicationPlan plan) { + return toAjax(planService.insert(plan)); + } + + @PutMapping + @ApiOperation("修改用药计划") + @RequiresPermissions("health:medicationPlan:edit") + @Log(title = "用药计划", businessType = BusinessType.UPDATE) + public AjaxResult edit(@RequestBody MedicationPlan plan) { + return toAjax(planService.update(plan)); + } + + @DeleteMapping("/{ids}") + @ApiOperation("删除用药计划") + @RequiresPermissions("health:medicationPlan:remove") + @Log(title = "用药计划", businessType = BusinessType.DELETE) + public AjaxResult remove(@PathVariable Long[] ids) { + return toAjax(planService.deleteByIds(ids)); + } + + @PutMapping("/pause/{id}") + @ApiOperation("暂停用药计划") + @RequiresPermissions("health:medicationPlan:edit") + @Log(title = "用药计划", businessType = BusinessType.UPDATE) + public AjaxResult pause(@PathVariable Long id) { + return toAjax(planService.pause(id)); + } + + @PutMapping("/resume/{id}") + @ApiOperation("恢复用药计划") + @RequiresPermissions("health:medicationPlan:edit") + @Log(title = "用药计划", businessType = BusinessType.UPDATE) + public AjaxResult resume(@PathVariable Long id) { + return toAjax(planService.resume(id)); + } + + @PutMapping("/end/{id}") + @ApiOperation("结束用药计划") + @RequiresPermissions("health:medicationPlan:edit") + @Log(title = "用药计划", businessType = BusinessType.UPDATE) + public AjaxResult end(@PathVariable Long id) { + return toAjax(planService.end(id)); + } +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationTaskController.java b/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationTaskController.java new file mode 100644 index 0000000..e1757e5 --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/controller/MedicationTaskController.java @@ -0,0 +1,80 @@ +package com.intc.health.controller; + +import com.intc.common.core.web.controller.BaseController; +import com.intc.common.core.web.domain.AjaxResult; +import com.intc.common.core.web.page.TableDataInfo; +import com.intc.common.log.annotation.Log; +import com.intc.common.log.enums.BusinessType; +import com.intc.common.security.annotation.RequiresPermissions; +import com.intc.health.domain.dto.MedicationTaskDto; +import com.intc.health.domain.vo.MedicationTaskVo; +import com.intc.health.service.IMedicationTaskService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 服药任务Controller + * + * @author bot5 + * @date 2026-03-19 + */ +@RestController +@RequestMapping("/health/medicationTask") +@Api(tags = "服药任务管理") +public class MedicationTaskController extends BaseController { + + @Resource + private IMedicationTaskService taskService; + + @GetMapping("/list") + @ApiOperation("查询服药任务列表") + @RequiresPermissions("health:medicationTask:list") + public TableDataInfo list(MedicationTaskDto dto) { + startPage(); + List list = taskService.selectList(dto); + return getDataTable(list); + } + + @GetMapping("/{id}") + @ApiOperation("查询服药任务详情") + @RequiresPermissions("health:medicationTask:query") + public AjaxResult getInfo(@PathVariable Long id) { + return success(taskService.selectById(id)); + } + + @DeleteMapping("/{ids}") + @ApiOperation("删除服药任务") + @RequiresPermissions("health:medicationTask:remove") + @Log(title = "服药任务", businessType = BusinessType.DELETE) + public AjaxResult remove(@PathVariable Long[] ids) { + return toAjax(taskService.deleteByIds(ids)); + } + + @PutMapping("/confirm/{id}") + @ApiOperation("确认服药") + @RequiresPermissions("health:medicationTask:edit") + @Log(title = "服药任务", businessType = BusinessType.UPDATE) + public AjaxResult confirm(@PathVariable Long id, @RequestParam(required = false) Integer confirmType) { + return toAjax(taskService.confirm(id, confirmType)); + } + + @PutMapping("/skip/{id}") + @ApiOperation("跳过服药") + @RequiresPermissions("health:medicationTask:edit") + @Log(title = "服药任务", businessType = BusinessType.UPDATE) + public AjaxResult skip(@PathVariable Long id, @RequestParam(required = false) String notes) { + return toAjax(taskService.skip(id, notes)); + } + + @PutMapping("/missed/{id}") + @ApiOperation("标记漏服") + @RequiresPermissions("health:medicationTask:edit") + @Log(title = "服药任务", businessType = BusinessType.UPDATE) + public AjaxResult missed(@PathVariable Long id, @RequestParam(required = false) String notes) { + return toAjax(taskService.markMissed(id, notes)); + } +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/ChronicDiseaseRecord.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/ChronicDiseaseRecord.java index 6c4006b..6327f99 100644 --- a/intc-modules/intc-health/src/main/java/com/intc/health/domain/ChronicDiseaseRecord.java +++ b/intc-modules/intc-health/src/main/java/com/intc/health/domain/ChronicDiseaseRecord.java @@ -1,119 +1,52 @@ package com.intc.health.domain; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.intc.common.core.annotation.Excel; -import com.intc.common.core.web.domain.BaseEntity; +import com.intc.common.core.domain.BaseEntity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import javax.validation.constraints.NotNull; -import java.util.Date; +import lombok.EqualsAndHashCode; /** * 慢性疾病档案对象 chronic_disease_record * * @author bot5 - * @date 2026-03-17 + * @date 2026-03-19 */ -@ApiModel("慢性疾病档案对象") @Data -public class ChronicDiseaseRecord extends BaseEntity -{ - private static final long serialVersionUID = 1L; +@EqualsAndHashCode(callSuper = true) +@ApiModel("慢性疾病档案") +public class ChronicDiseaseRecord extends BaseEntity { - /** 主键 */ + @ApiModelProperty("主键ID") private Long id; - /** 关联成员ID */ - @ApiModelProperty(value = "关联成员ID") - @NotNull(message = "成员不能为空") - @Excel(name = "成员ID") + @ApiModelProperty("关联成员ID") private Long memberId; - /** 成员名称(冗余字段) */ - @Excel(name = "成员名称") - private String memberName; - - /** 关联疾病ID(关联health_diseases表,可选) */ - @ApiModelProperty(value = "关联疾病ID") - @Excel(name = "疾病ID") - private Long diseaseId; - - /** 疾病名称 */ - @ApiModelProperty(value = "疾病名称") - @NotNull(message = "疾病名称不能为空") - @Excel(name = "疾病名称") + @ApiModelProperty("疾病名称") private String diseaseName; - /** 疾病编码(ICD-10标准) */ - @ApiModelProperty(value = "疾病编码(ICD-10标准)") - @Excel(name = "疾病编码") + @ApiModelProperty("疾病编码(ICD-10标准)") private String diseaseCode; - /** 确诊日期 */ - @ApiModelProperty(value = "确诊日期") - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "确诊日期", width = 30, dateFormat = "yyyy-MM-dd") - private Date diagnosisDate; + @ApiModelProperty("确诊日期") + private String diagnosisDate; - /** 状态:1-稳定 2-需关注 3-急性期 */ - @ApiModelProperty(value = "状态:1-稳定 2-需关注 3-急性期") - @NotNull(message = "状态不能为空") - @Excel(name = "状态", readConverterExp = "1=稳定,2=需关注,3=急性期") + @ApiModelProperty("状态:1-稳定 2-需关注 3-急性期") private Integer diseaseStatus; - /** 主治医生 */ - @ApiModelProperty(value = "主治医生") - @Excel(name = "主治医生") + @ApiModelProperty("主治医生") private String mainDoctor; - /** 就诊医院 */ - @ApiModelProperty(value = "就诊医院") - @Excel(name = "就诊医院") + @ApiModelProperty("就诊医院") private String hospital; - /** 科室 */ - @ApiModelProperty(value = "科室") - @Excel(name = "科室") + @ApiModelProperty("科室") private String department; - /** 备注说明 */ - @ApiModelProperty(value = "备注说明") + @ApiModelProperty("备注说明") private String notes; - /** 是否启用:1-是 0-否 */ - @ApiModelProperty(value = "是否启用:1-是 0-否") - @Excel(name = "是否启用", readConverterExp = "1=是,0=否") - private Integer isActive; - - /** 删除标志(0代表存在 1代表删除) */ - private String delFlag; - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) - .append("id", getId()) - .append("memberId", getMemberId()) - .append("memberName", getMemberName()) - .append("diseaseId", getDiseaseId()) - .append("diseaseName", getDiseaseName()) - .append("diseaseCode", getDiseaseCode()) - .append("diagnosisDate", getDiagnosisDate()) - .append("diseaseStatus", getDiseaseStatus()) - .append("mainDoctor", getMainDoctor()) - .append("hospital", getHospital()) - .append("department", getDepartment()) - .append("notes", getNotes()) - .append("isActive", getIsActive()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("delFlag", getDelFlag()) - .append("remark", getRemark()) - .toString(); - } + @ApiModelProperty("删除标记:0-正常 1-删除") + private Integer delFlag; } \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/HealthMedicationPlan.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/HealthMedicationPlan.java deleted file mode 100644 index f0cf9af..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/domain/HealthMedicationPlan.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.intc.health.domain; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.intc.common.core.annotation.Excel; -import com.intc.common.core.web.domain.BaseEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import javax.validation.constraints.NotNull; -import java.util.Date; - -/** - * 用药计划对象 health_medication_plan - * - * @author intc - * @date 2025-03-18 - */ -@ApiModel("用药计划对象") -@Data -public class HealthMedicationPlan extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 主键 */ - private Long id; - - /** 人员ID */ - @ApiModelProperty(value="人员ID") - @NotNull(message="人员ID不能为空") - @Excel(name = "人员ID") - private Long personId; - - /** 药品ID */ - @ApiModelProperty(value="药品ID") - @NotNull(message="药品ID不能为空") - @Excel(name = "药品ID") - private Long medicineId; - - /** 入库ID(用于扣减库存) */ - @ApiModelProperty(value="入库ID") - private Long stockInId; - - /** 计划名称 */ - @ApiModelProperty(value="计划名称") - @Excel(name = "计划名称") - private String planName; - - /** 每次剂量 */ - @ApiModelProperty(value="每次剂量") - @NotNull(message="剂量不能为空") - @Excel(name = "每次剂量") - private Double dosage; - - /** 剂量单位 */ - @ApiModelProperty(value="剂量单位") - @Excel(name = "剂量单位") - private String dosageUnit; - - /** 服药频率(每日次数) */ - @ApiModelProperty(value="服药频率") - @NotNull(message="服药频率不能为空") - @Excel(name = "服药频率") - private Integer frequency; - - /** 频率类型(1-每日 2-隔日 3-每周 4-自定义) */ - @ApiModelProperty(value="频率类型") - @Excel(name = "频率类型", readConverterExp = "1=每日,2=隔日,3=每周,4=自定义") - private String frequencyType; - - /** 服药时间点(JSON格式) */ - @ApiModelProperty(value="服药时间点") - private String timePoints; - - /** 周几服药(频率类型为每周时使用,JSON格式如[1,3,5]表示周一三五) */ - @ApiModelProperty(value="周几服药") - private String weekDays; - - /** 开始日期 */ - @ApiModelProperty(value="开始日期") - @NotNull(message="开始日期不能为空") - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "开始日期", width = 30, dateFormat = "yyyy-MM-dd") - private Date startDate; - - /** 结束日期 */ - @ApiModelProperty(value="结束日期") - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "结束日期", width = 30, dateFormat = "yyyy-MM-dd") - private Date endDate; - - /** 是否启用提醒(0-否 1-是) */ - @ApiModelProperty(value="是否启用提醒") - @Excel(name = "是否启用提醒", readConverterExp = "0=否,1=是") - private String reminderEnabled; - - /** 提前提醒时间(分钟) */ - @ApiModelProperty(value="提前提醒时间") - @Excel(name = "提前提醒时间(分钟)") - private Integer reminderMinutes; - - /** 状态(1-进行中 2-已结束 3-已暂停) */ - @ApiModelProperty(value="状态") - @Excel(name = "状态", readConverterExp = "1=进行中,2=已结束,3=已暂停") - private String status; - - /** 删除标志(0代表存在 1代表删除) */ - private String delFlag; - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) - .append("id", getId()) - .append("personId", getPersonId()) - .append("medicineId", getMedicineId()) - .append("stockInId", getStockInId()) - .append("planName", getPlanName()) - .append("dosage", getDosage()) - .append("dosageUnit", getDosageUnit()) - .append("frequency", getFrequency()) - .append("frequencyType", getFrequencyType()) - .append("timePoints", getTimePoints()) - .append("weekDays", getWeekDays()) - .append("startDate", getStartDate()) - .append("endDate", getEndDate()) - .append("reminderEnabled", getReminderEnabled()) - .append("reminderMinutes", getReminderMinutes()) - .append("status", getStatus()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("delFlag", getDelFlag()) - .append("remark", getRemark()) - .toString(); - } -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/HealthMedicationRecord.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/HealthMedicationRecord.java deleted file mode 100644 index 190036e..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/domain/HealthMedicationRecord.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.intc.health.domain; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.intc.common.core.annotation.Excel; -import com.intc.common.core.web.domain.BaseEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import javax.validation.constraints.NotNull; -import java.util.Date; - -/** - * 用药记录对象 health_medication_record - * - * @author intc - * @date 2025-03-18 - */ -@ApiModel("用药记录对象") -@Data -public class HealthMedicationRecord extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 主键 */ - private Long id; - - /** 计划ID */ - @ApiModelProperty(value="计划ID") - @NotNull(message="计划ID不能为空") - @Excel(name = "计划ID") - private Long planId; - - /** 人员ID */ - @ApiModelProperty(value="人员ID") - @NotNull(message="人员ID不能为空") - @Excel(name = "人员ID") - private Long personId; - - /** 药品ID */ - @ApiModelProperty(value="药品ID") - @NotNull(message="药品ID不能为空") - @Excel(name = "药品ID") - private Long medicineId; - - /** 计划服药时间 */ - @ApiModelProperty(value="计划服药时间") - @NotNull(message="计划服药时间不能为空") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @Excel(name = "计划服药时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") - private Date scheduledTime; - - /** 实际服药时间 */ - @ApiModelProperty(value="实际服药时间") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @Excel(name = "实际服药时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") - private Date actualTime; - - /** 服用剂量 */ - @ApiModelProperty(value="服用剂量") - @Excel(name = "服用剂量") - private Double dosage; - - /** 剂量单位 */ - @ApiModelProperty(value="剂量单位") - @Excel(name = "剂量单位") - private String dosageUnit; - - /** 状态(1-待服用 2-已服用 3-已跳过 4-已过期) */ - @ApiModelProperty(value="状态") - @Excel(name = "状态", readConverterExp = "1=待服用,2=已服用,3=已跳过,4=已过期") - private String status; - - /** 删除标志(0代表存在 1代表删除) */ - private String delFlag; - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) - .append("id", getId()) - .append("planId", getPlanId()) - .append("personId", getPersonId()) - .append("medicineId", getMedicineId()) - .append("scheduledTime", getScheduledTime()) - .append("actualTime", getActualTime()) - .append("dosage", getDosage()) - .append("dosageUnit", getDosageUnit()) - .append("status", getStatus()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("delFlag", getDelFlag()) - .append("remark", getRemark()) - .toString(); - } -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/MedicationPlan.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/MedicationPlan.java new file mode 100644 index 0000000..91d7287 --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/domain/MedicationPlan.java @@ -0,0 +1,83 @@ +package com.intc.health.domain; + +import com.fasterxml.jackson.databind.JsonNode; +import com.intc.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 用药计划对象 medication_plan + * + * @author bot5 + * @date 2026-03-19 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel("用药计划") +public class MedicationPlan extends BaseEntity { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("关联成员ID") + private Long memberId; + + @ApiModelProperty("关联慢性疾病ID") + private Long chronicDiseaseId; + + @ApiModelProperty("计划名称") + private String planName; + + @ApiModelProperty("关联药品ID") + private Long medicineId; + + @ApiModelProperty("药品名称") + private String medicineName; + + @ApiModelProperty("药品规格") + private String specification; + + @ApiModelProperty("单次剂量") + private BigDecimal dosagePerTime; + + @ApiModelProperty("剂量单位") + private String dosageUnit; + + @ApiModelProperty("频次类型:1-每天 2-每周 3-隔天 4-自定义") + private Integer frequencyType; + + @ApiModelProperty("频次配置(JSON格式)") + private JsonNode frequencyConfig; + + @ApiModelProperty("服药时段配置") + private JsonNode timeSlots; + + @ApiModelProperty("开始日期") + private LocalDate startDate; + + @ApiModelProperty("结束日期") + private LocalDate endDate; + + @ApiModelProperty("是否开启提醒:1-是 0-否") + private Integer remindEnabled; + + @ApiModelProperty("提前提醒分钟数") + private Integer remindAdvanceMin; + + @ApiModelProperty("漏服是否通知家属:1-是 0-否") + private Integer notifyFamily; + + @ApiModelProperty("通知家属成员ID列表") + private JsonNode familyMemberIds; + + @ApiModelProperty("状态:1-执行中 2-已暂停 3-已结束") + private Integer status; + + @ApiModelProperty("删除标记:0-正常 1-删除") + private Integer delFlag; +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/MedicationTask.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/MedicationTask.java new file mode 100644 index 0000000..43a3c73 --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/domain/MedicationTask.java @@ -0,0 +1,69 @@ +package com.intc.health.domain; + +import com.intc.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +/** + * 服药任务对象 medication_task + * + * @author bot5 + * @date 2026-03-19 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel("服药任务") +public class MedicationTask extends BaseEntity { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("关联用药计划ID") + private Long planId; + + @ApiModelProperty("关联成员ID") + private Long memberId; + + @ApiModelProperty("药品名称") + private String medicineName; + + @ApiModelProperty("计划服药日期") + private LocalDate plannedDate; + + @ApiModelProperty("计划服药时间") + private LocalTime plannedTime; + + @ApiModelProperty("计划剂量") + private BigDecimal plannedDosage; + + @ApiModelProperty("实际服药时间") + private LocalDateTime actualTime; + + @ApiModelProperty("实际剂量") + private BigDecimal actualDosage; + + @ApiModelProperty("状态:0-待服药 1-已服药 2-漏服 3-跳过") + private Integer status; + + @ApiModelProperty("确认方式:1-用户确认 2-家属代确认 3-系统自动") + private Integer confirmType; + + @ApiModelProperty("备注(如漏服原因)") + private String notes; + + @ApiModelProperty("提醒状态:0-未提醒 1-已提醒 2-已超时提醒") + private Integer remindStatus; + + @ApiModelProperty("提醒时间") + private LocalDateTime remindTime; + + @ApiModelProperty("删除标记:0-正常 1-删除") + private Integer delFlag; +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/HealthMedicationPlanDto.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/HealthMedicationPlanDto.java deleted file mode 100644 index d9ba52e..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/HealthMedicationPlanDto.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.intc.health.domain.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.util.Date; - -/** - * 用药计划DTO对象 health_medication_plan - * - * @author intc - * @date 2025-03-18 - */ -@ApiModel("用药计划DTO对象") -@Data -public class HealthMedicationPlanDto -{ - /** 主键 */ - private Long id; - - /** 人员ID */ - @ApiModelProperty(value="人员ID") - private Long personId; - - /** 人员姓名(模糊查询) */ - @ApiModelProperty(value="人员姓名") - private String personName; - - /** 药品ID */ - @ApiModelProperty(value="药品ID") - private Long medicineId; - - /** 计划名称 */ - @ApiModelProperty(value="计划名称") - private String planName; - - /** 频率类型 */ - @ApiModelProperty(value="频率类型") - private String frequencyType; - - /** 状态 */ - @ApiModelProperty(value="状态") - private String status; - - /** 开始日期-起 */ - @ApiModelProperty(value="开始日期-起") - private Date startDateBegin; - - /** 开始日期-止 */ - @ApiModelProperty(value="开始日期-止") - private Date startDateEnd; - - /** 结束日期-起 */ - @ApiModelProperty(value="结束日期-起") - private Date endDateBegin; - - /** 结束日期-止 */ - @ApiModelProperty(value="结束日期-止") - private Date endDateEnd; - - /** 关键字(计划名称、药品名称) */ - @ApiModelProperty(value="关键字") - private String keys; - - /** 分页参数 */ - private Integer pageNum; - private Integer pageSize; -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/HealthMedicationRecordDto.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/HealthMedicationRecordDto.java deleted file mode 100644 index ed4706c..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/HealthMedicationRecordDto.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.intc.health.domain.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.util.Date; - -/** - * 用药记录DTO对象 health_medication_record - * - * @author intc - * @date 2025-03-18 - */ -@ApiModel("用药记录DTO对象") -@Data -public class HealthMedicationRecordDto -{ - /** 主键 */ - private Long id; - - /** 计划ID */ - @ApiModelProperty(value="计划ID") - private Long planId; - - /** 人员ID */ - @ApiModelProperty(value="人员ID") - private Long personId; - - /** 人员姓名 */ - @ApiModelProperty(value="人员姓名") - private String personName; - - /** 药品ID */ - @ApiModelProperty(value="药品ID") - private Long medicineId; - - /** 状态 */ - @ApiModelProperty(value="状态") - private String status; - - /** 计划服药时间-起 */ - @ApiModelProperty(value="计划服药时间-起") - private Date scheduledTimeBegin; - - /** 计划服药时间-止 */ - @ApiModelProperty(value="计划服药时间-止") - private Date scheduledTimeEnd; - - /** 实际服药时间-起 */ - @ApiModelProperty(value="实际服药时间-起") - private Date actualTimeBegin; - - /** 实际服药时间-止 */ - @ApiModelProperty(value="实际服药时间-止") - private Date actualTimeEnd; - - /** 日期(按日期查询某天所有记录) */ - @ApiModelProperty(value="日期") - private Date queryDate; - - /** 分页参数 */ - private Integer pageNum; - private Integer pageSize; -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/MedicationPlanDto.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/MedicationPlanDto.java new file mode 100644 index 0000000..f634a5e --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/MedicationPlanDto.java @@ -0,0 +1,56 @@ +package com.intc.health.domain.dto; + +import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 用药计划查询DTO + * + * @author bot5 + * @date 2026-03-19 + */ +@Data +@ApiModel("用药计划查询DTO") +public class MedicationPlanDto { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("关联成员ID") + private Long memberId; + + @ApiModelProperty("关联慢性疾病ID") + private Long chronicDiseaseId; + + @ApiModelProperty("计划名称") + private String planName; + + @ApiModelProperty("关联药品ID") + private Long medicineId; + + @ApiModelProperty("药品名称") + private String medicineName; + + @ApiModelProperty("状态:1-执行中 2-已暂停 3-已结束") + private Integer status; + + @ApiModelProperty("开始日期-起") + private String startDateBegin; + + @ApiModelProperty("开始日期-止") + private String startDateEnd; + + @ApiModelProperty("结束日期-起") + private String endDateBegin; + + @ApiModelProperty("结束日期-止") + private String endDateEnd; + + @ApiModelProperty("关键字搜索") + private String keyword; +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/MedicationTaskDto.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/MedicationTaskDto.java new file mode 100644 index 0000000..ef9fbbb --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/domain/dto/MedicationTaskDto.java @@ -0,0 +1,42 @@ +package com.intc.health.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDate; + +/** + * 服药任务查询DTO + * + * @author bot5 + * @date 2026-03-19 + */ +@Data +@ApiModel("服药任务查询DTO") +public class MedicationTaskDto { + + @ApiModelProperty("关联用药计划ID") + private Long planId; + + @ApiModelProperty("关联成员ID") + private Long memberId; + + @ApiModelProperty("药品名称") + private String medicineName; + + @ApiModelProperty("计划服药日期-起") + private String plannedDateBegin; + + @ApiModelProperty("计划服药日期-止") + private String plannedDateEnd; + + @ApiModelProperty("状态:0-待服药 1-已服药 2-漏服 3-跳过") + private Integer status; + + @ApiModelProperty("查询日期(yyyy-MM-dd)") + private String queryDate; + + @ApiModelProperty("关键字搜索") + private String keyword; +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/HealthMedicationPlanVo.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/HealthMedicationPlanVo.java deleted file mode 100644 index b3fd978..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/HealthMedicationPlanVo.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.intc.health.domain.vo; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.intc.common.core.annotation.Excel; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.util.Date; - -/** - * 用药计划VO对象 health_medication_plan - * - * @author intc - * @date 2025-03-18 - */ -@ApiModel("用药计划VO对象") -@Data -public class HealthMedicationPlanVo -{ - /** 主键 */ - private Long id; - - /** 人员ID */ - @Excel(name = "人员ID") - private Long personId; - - /** 人员姓名 */ - @Excel(name = "人员姓名") - private String personName; - - /** 药品ID */ - @Excel(name = "药品ID") - private Long medicineId; - - /** 药品名称 */ - @Excel(name = "药品名称") - private String medicineName; - - /** 药品简称 */ - private String shortName; - - /** 品牌 */ - private String brand; - - /** 包装 */ - private String packaging; - - /** 入库ID */ - private Long stockInId; - - /** 计划名称 */ - @Excel(name = "计划名称") - private String planName; - - /** 每次剂量 */ - @Excel(name = "每次剂量") - private Double dosage; - - /** 剂量单位 */ - @Excel(name = "剂量单位") - private String dosageUnit; - - /** 服药频率 */ - @Excel(name = "服药频率") - private Integer frequency; - - /** 频率类型 */ - @Excel(name = "频率类型") - private String frequencyType; - - /** 服药时间点 */ - private String timePoints; - - /** 周几服药 */ - private String weekDays; - - /** 开始日期 */ - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "开始日期", width = 30, dateFormat = "yyyy-MM-dd") - private Date startDate; - - /** 结束日期 */ - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "结束日期", width = 30, dateFormat = "yyyy-MM-dd") - private Date endDate; - - /** 是否启用提醒 */ - @Excel(name = "是否启用提醒") - private String reminderEnabled; - - /** 提前提醒时间 */ - @Excel(name = "提前提醒时间(分钟)") - private Integer reminderMinutes; - - /** 状态 */ - @Excel(name = "状态") - private String status; - - /** 备注 */ - private String remark; - - /** 创建时间 */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private Date createTime; - - /** 药品简称-品牌(组合显示) */ - private String medicineDisplayName; - - /** 今日已服药次数 */ - private Integer todayTakenCount; - - /** 今日应服药次数 */ - private Integer todayTotalCount; - - /** 剩余库存 */ - private Double stockLeft; -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/HealthMedicationRecordVo.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/HealthMedicationRecordVo.java deleted file mode 100644 index 5fddc71..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/HealthMedicationRecordVo.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.intc.health.domain.vo; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.intc.common.core.annotation.Excel; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.util.Date; - -/** - * 用药记录VO对象 health_medication_record - * - * @author intc - * @date 2025-03-18 - */ -@ApiModel("用药记录VO对象") -@Data -public class HealthMedicationRecordVo -{ - /** 主键 */ - private Long id; - - /** 计划ID */ - @Excel(name = "计划ID") - private Long planId; - - /** 人员ID */ - @Excel(name = "人员ID") - private Long personId; - - /** 人员姓名 */ - @Excel(name = "人员姓名") - private String personName; - - /** 药品ID */ - @Excel(name = "药品ID") - private Long medicineId; - - /** 药品名称 */ - @Excel(name = "药品名称") - private String medicineName; - - /** 药品简称 */ - private String shortName; - - /** 品牌 */ - private String brand; - - /** 包装 */ - private String packaging; - - /** 计划服药时间 */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @Excel(name = "计划服药时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") - private Date scheduledTime; - - /** 实际服药时间 */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @Excel(name = "实际服药时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") - private Date actualTime; - - /** 服用剂量 */ - @Excel(name = "服用剂量") - private Double dosage; - - /** 剂量单位 */ - @Excel(name = "剂量单位") - private String dosageUnit; - - /** 状态 */ - @Excel(name = "状态") - private String status; - - /** 备注 */ - private String remark; - - /** 创建时间 */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private Date createTime; - - /** 药品简称-品牌(组合显示) */ - private String medicineDisplayName; - - /** 计划名称 */ - private String planName; -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/MedicationPlanVo.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/MedicationPlanVo.java new file mode 100644 index 0000000..afbfb1a --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/MedicationPlanVo.java @@ -0,0 +1,93 @@ +package com.intc.health.domain.vo; + +import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 用药计划VO + * + * @author bot5 + * @date 2026-03-19 + */ +@Data +@ApiModel("用药计划VO") +public class MedicationPlanVo { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("关联成员ID") + private Long memberId; + + @ApiModelProperty("成员名称") + private String memberName; + + @ApiModelProperty("关联慢性疾病ID") + private Long chronicDiseaseId; + + @ApiModelProperty("慢性疾病名称") + private String chronicDiseaseName; + + @ApiModelProperty("计划名称") + private String planName; + + @ApiModelProperty("关联药品ID") + private Long medicineId; + + @ApiModelProperty("药品名称") + private String medicineName; + + @ApiModelProperty("药品规格") + private String specification; + + @ApiModelProperty("单次剂量") + private BigDecimal dosagePerTime; + + @ApiModelProperty("剂量单位") + private String dosageUnit; + + @ApiModelProperty("频次类型:1-每天 2-每周 3-隔天 4-自定义") + private Integer frequencyType; + + @ApiModelProperty("频次配置(JSON格式)") + private JsonNode frequencyConfig; + + @ApiModelProperty("服药时段配置") + private JsonNode timeSlots; + + @ApiModelProperty("开始日期") + private LocalDate startDate; + + @ApiModelProperty("结束日期") + private LocalDate endDate; + + @ApiModelProperty("是否开启提醒:1-是 0-否") + private Integer remindEnabled; + + @ApiModelProperty("提前提醒分钟数") + private Integer remindAdvanceMin; + + @ApiModelProperty("漏服是否通知家属:1-是 0-否") + private Integer notifyFamily; + + @ApiModelProperty("通知家属成员ID列表") + private JsonNode familyMemberIds; + + @ApiModelProperty("状态:1-执行中 2-已暂停 3-已结束") + private Integer status; + + @ApiModelProperty("今日任务统计") + private Integer todayTotal; + + @ApiModelProperty("今日已完成") + private Integer todayCompleted; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/MedicationTaskVo.java b/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/MedicationTaskVo.java new file mode 100644 index 0000000..1f03a8f --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/domain/vo/MedicationTaskVo.java @@ -0,0 +1,75 @@ +package com.intc.health.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +/** + * 服药任务VO + * + * @author bot5 + * @date 2026-03-19 + */ +@Data +@ApiModel("服药任务VO") +public class MedicationTaskVo { + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("关联用药计划ID") + private Long planId; + + @ApiModelProperty("计划名称") + private String planName; + + @ApiModelProperty("关联成员ID") + private Long memberId; + + @ApiModelProperty("成员名称") + private String memberName; + + @ApiModelProperty("药品名称") + private String medicineName; + + @ApiModelProperty("计划服药日期") + private LocalDate plannedDate; + + @ApiModelProperty("计划服药时间") + private LocalTime plannedTime; + + @ApiModelProperty("计划剂量") + private BigDecimal plannedDosage; + + @ApiModelProperty("实际服药时间") + private LocalDateTime actualTime; + + @ApiModelProperty("实际剂量") + private BigDecimal actualDosage; + + @ApiModelProperty("状态:0-待服药 1-已服药 2-漏服 3-跳过") + private Integer status; + + @ApiModelProperty("状态名称") + private String statusName; + + @ApiModelProperty("确认方式:1-用户确认 2-家属代确认 3-系统自动") + private Integer confirmType; + + @ApiModelProperty("备注(如漏服原因)") + private String notes; + + @ApiModelProperty("提醒状态:0-未提醒 1-已提醒 2-已超时提醒") + private Integer remindStatus; + + @ApiModelProperty("提醒时间") + private LocalDateTime remindTime; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/mapper/HealthMedicationPlanMapper.java b/intc-modules/intc-health/src/main/java/com/intc/health/mapper/HealthMedicationPlanMapper.java deleted file mode 100644 index aea7726..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/mapper/HealthMedicationPlanMapper.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.intc.health.mapper; - -import java.util.List; -import com.intc.health.domain.HealthMedicationPlan; -import com.intc.health.domain.dto.HealthMedicationPlanDto; -import com.intc.health.domain.vo.HealthMedicationPlanVo; - -/** - * 用药计划Mapper接口 - * - * @author intc - * @date 2025-03-18 - */ -public interface HealthMedicationPlanMapper -{ - /** - * 查询用药计划 - * - * @param id 用药计划主键 - * @return 用药计划 - */ - public HealthMedicationPlanVo selectHealthMedicationPlanById(Long id); - - /** - * 查询用药计划列表 - * - * @param dto 用药计划 - * @return 用药计划集合 - */ - public List selectHealthMedicationPlanList(HealthMedicationPlanDto dto); - - /** - * 查询进行中的用药计划列表(用于生成用药记录) - * - * @return 用药计划集合 - */ - public List selectActivePlanList(); - - /** - * 新增用药计划 - * - * @param healthMedicationPlan 用药计划 - * @return 结果 - */ - public int insertHealthMedicationPlan(HealthMedicationPlan healthMedicationPlan); - - /** - * 修改用药计划 - * - * @param healthMedicationPlan 用药计划 - * @return 结果 - */ - public int updateHealthMedicationPlan(HealthMedicationPlan healthMedicationPlan); - - /** - * 删除用药计划 - * - * @param id 用药计划主键 - * @return 结果 - */ - public int deleteHealthMedicationPlanById(Long id); - - /** - * 批量删除用药计划 - * - * @param ids 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteHealthMedicationPlanByIds(Long[] ids); - - /** - * 逻辑删除用药计划 - * - * @param id 用药计划主键 - * @return 结果 - */ - public int removeHealthMedicationPlanById(Long id); - - /** - * 批量逻辑删除用药计划 - * - * @param ids 需要删除的数据主键集合 - * @return 结果 - */ - public int removeHealthMedicationPlanByIds(Long[] ids); -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/mapper/HealthMedicationRecordMapper.java b/intc-modules/intc-health/src/main/java/com/intc/health/mapper/HealthMedicationRecordMapper.java deleted file mode 100644 index 5dee335..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/mapper/HealthMedicationRecordMapper.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.intc.health.mapper; - -import java.util.List; -import com.intc.health.domain.HealthMedicationRecord; -import com.intc.health.domain.dto.HealthMedicationRecordDto; -import com.intc.health.domain.vo.HealthMedicationRecordVo; -import org.apache.ibatis.annotations.Param; - -/** - * 用药记录Mapper接口 - * - * @author intc - * @date 2025-03-18 - */ -public interface HealthMedicationRecordMapper -{ - /** - * 查询用药记录 - * - * @param id 用药记录主键 - * @return 用药记录 - */ - public HealthMedicationRecordVo selectHealthMedicationRecordById(Long id); - - /** - * 查询用药记录列表 - * - * @param dto 用药记录 - * @return 用药记录集合 - */ - public List selectHealthMedicationRecordList(HealthMedicationRecordDto dto); - - /** - * 查询某计划某天的用药记录 - * - * @param planId 计划ID - * @param date 日期 - * @return 用药记录集合 - */ - public List selectRecordByPlanAndDate(@Param("planId") Long planId, @Param("date") String date); - - /** - * 统计某计划某天已服药次数 - * - * @param planId 计划ID - * @param date 日期 - * @return 次数 - */ - public int countTakenByPlanAndDate(@Param("planId") Long planId, @Param("date") String date); - - /** - * 新增用药记录 - * - * @param record 用药记录 - * @return 结果 - */ - public int insertHealthMedicationRecord(HealthMedicationRecord record); - - /** - * 批量新增用药记录 - * - * @param records 用药记录列表 - * @return 结果 - */ - public int batchInsertHealthMedicationRecord(List records); - - /** - * 修改用药记录 - * - * @param record 用药记录 - * @return 结果 - */ - public int updateHealthMedicationRecord(HealthMedicationRecord record); - - /** - * 删除用药记录 - * - * @param id 用药记录主键 - * @return 结果 - */ - public int deleteHealthMedicationRecordById(Long id); - - /** - * 批量删除用药记录 - * - * @param ids 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteHealthMedicationRecordByIds(Long[] ids); - - /** - * 逻辑删除用药记录 - * - * @param id 用药记录主键 - * @return 结果 - */ - public int removeHealthMedicationRecordById(Long id); - - /** - * 批量逻辑删除用药记录 - * - * @param ids 需要删除的数据主键集合 - * @return 结果 - */ - public int removeHealthMedicationRecordByIds(Long[] ids); - - /** - * 统计某计划某天的记录数(用于检查是否已生成) - * - * @param planId 计划ID - * @param date 日期 - * @return 记录数 - */ - public int countByPlanAndDate(@Param("planId") Long planId, @Param("date") String date); - - /** - * 标记过期的服药记录(超过24小时未服用) - * - * @param expireThreshold 过期阈值时间 - * @return 更新的记录数 - */ - public int markExpiredRecords(@Param("expireThreshold") java.time.LocalDateTime expireThreshold); - - /** - * 查询待提醒的服药记录 - * - * @param startTime 开始时间 - * @param endTime 结束时间 - * @return 服药记录集合 - */ - public List selectPendingRemindRecords(@Param("startTime") java.time.LocalDateTime startTime, @Param("endTime") java.time.LocalDateTime endTime); - - // ========== 依从性统计相关 ========== - - /** - * 获取总体依从性统计 - * - * @param dto 查询参数 - * @return 统计结果Map - */ - public java.util.Map getAdherenceStats(@Param("dto") com.intc.health.domain.dto.MedicationAdherenceDto dto); - - /** - * 获取每日依从性统计 - * - * @param dto 查询参数 - * @return 每日统计列表 - */ - public java.util.List> getDailyAdherenceStats(@Param("dto") com.intc.health.domain.dto.MedicationAdherenceDto dto); - - /** - * 获取时段依从性统计 - * - * @param dto 查询参数 - * @return 时段统计列表 - */ - public java.util.List> getTimeSlotAdherenceStats(@Param("dto") com.intc.health.domain.dto.MedicationAdherenceDto dto); - - /** - * 获取药品依从性统计 - * - * @param dto 查询参数 - * @return 药品统计列表 - */ - public java.util.List> getMedicineAdherenceStats(@Param("dto") com.intc.health.domain.dto.MedicationAdherenceDto dto); - - /** - * 获取人员依从性统计 - * - * @param dto 查询参数 - * @return 人员统计列表 - */ - public java.util.List> getPersonAdherenceStats(@Param("dto") com.intc.health.domain.dto.MedicationAdherenceDto dto); - - /** - * 获取漏服原因统计 - * - * @param dto 查询参数 - * @return 原因统计列表 - */ - public java.util.List> getMissedReasonStats(@Param("dto") com.intc.health.domain.dto.MedicationAdherenceDto dto); -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/mapper/MedicationPlanMapper.java b/intc-modules/intc-health/src/main/java/com/intc/health/mapper/MedicationPlanMapper.java new file mode 100644 index 0000000..407cd7c --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/mapper/MedicationPlanMapper.java @@ -0,0 +1,62 @@ +package com.intc.health.mapper; + +import com.intc.health.domain.MedicationPlan; +import com.intc.health.domain.dto.MedicationPlanDto; +import com.intc.health.domain.vo.MedicationPlanVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 用药计划Mapper接口 + * + * @author bot5 + * @date 2026-03-19 + */ +public interface MedicationPlanMapper { + + /** + * 查询用药计划 + */ + MedicationPlanVo selectById(Long id); + + /** + * 查询用药计划列表 + */ + List selectList(MedicationPlanDto dto); + + /** + * 查询执行中的用药计划列表(用于生成任务) + */ + List selectActiveList(); + + /** + * 新增用药计划 + */ + int insert(MedicationPlan plan); + + /** + * 修改用药计划 + */ + int update(MedicationPlan plan); + + /** + * 删除用药计划 + */ + int deleteById(Long id); + + /** + * 批量删除用药计划 + */ + int deleteByIds(Long[] ids); + + /** + * 逻辑删除用药计划 + */ + int removeById(Long id); + + /** + * 批量逻辑删除用药计划 + */ + int removeByIds(Long[] ids); +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/mapper/MedicationTaskMapper.java b/intc-modules/intc-health/src/main/java/com/intc/health/mapper/MedicationTaskMapper.java new file mode 100644 index 0000000..cfb54a8 --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/mapper/MedicationTaskMapper.java @@ -0,0 +1,107 @@ +package com.intc.health.mapper; + +import com.intc.health.domain.MedicationTask; +import com.intc.health.domain.dto.MedicationTaskDto; +import com.intc.health.domain.vo.MedicationTaskVo; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 服药任务Mapper接口 + * + * @author bot5 + * @date 2026-03-19 + */ +public interface MedicationTaskMapper { + + /** + * 查询服药任务 + */ + MedicationTaskVo selectById(Long id); + + /** + * 查询服药任务列表 + */ + List selectList(MedicationTaskDto dto); + + /** + * 新增服药任务 + */ + int insert(MedicationTask task); + + /** + * 批量新增服药任务 + */ + int batchInsert(List tasks); + + /** + * 修改服药任务 + */ + int update(MedicationTask task); + + /** + * 删除服药任务 + */ + int deleteById(Long id); + + /** + * 批量删除服药任务 + */ + int deleteByIds(Long[] ids); + + /** + * 逻辑删除服药任务 + */ + int removeById(Long id); + + /** + * 批量逻辑删除服药任务 + */ + int removeByIds(Long[] ids); + + /** + * 统计某计划某天的任务数 + */ + int countByPlanAndDate(@Param("planId") Long planId, @Param("date") LocalDate date); + + /** + * 统计某计划某天的已服药数 + */ + int countCompletedByPlanAndDate(@Param("planId") Long planId, @Param("date") LocalDate date); + + /** + * 标记过期任务(超过24小时未服药) + */ + int markExpired(@Param("expireThreshold") LocalDateTime threshold); + + /** + * 查询待提醒的任务 + */ + List selectPendingRemind(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); + + // ========== 依从性统计 ========== + + /** + * 获取总体统计 + */ + java.util.Map getOverallStats(@Param("memberId") Long memberId, + @Param("startDate") LocalDate startDate, + @Param("endDate") LocalDate endDate); + + /** + * 获取每日统计 + */ + List> getDailyStats(@Param("memberId") Long memberId, + @Param("startDate") LocalDate startDate, + @Param("endDate") LocalDate endDate); + + /** + * 获取时段统计 + */ + List> getTimeSlotStats(@Param("memberId") Long memberId, + @Param("startDate") LocalDate startDate, + @Param("endDate") LocalDate endDate); +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/IHealthMedicationPlanService.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/IHealthMedicationPlanService.java deleted file mode 100644 index 7c6aef3..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/service/IHealthMedicationPlanService.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.intc.health.service; - -import java.util.List; -import com.intc.health.domain.HealthMedicationPlan; -import com.intc.health.domain.dto.HealthMedicationPlanDto; -import com.intc.health.domain.vo.HealthMedicationPlanVo; - -/** - * 用药计划Service接口 - * - * @author intc - * @date 2025-03-18 - */ -public interface IHealthMedicationPlanService -{ - /** - * 查询用药计划 - * - * @param id 用药计划主键 - * @return 用药计划 - */ - public HealthMedicationPlanVo selectHealthMedicationPlanById(Long id); - - /** - * 查询用药计划列表 - * - * @param dto 用药计划 - * @return 用药计划集合 - */ - public List selectHealthMedicationPlanList(HealthMedicationPlanDto dto); - - /** - * 新增用药计划 - * - * @param plan 用药计划 - * @return 结果 - */ - public int insertHealthMedicationPlan(HealthMedicationPlan plan); - - /** - * 修改用药计划 - * - * @param plan 用药计划 - * @return 结果 - */ - public int updateHealthMedicationPlan(HealthMedicationPlan plan); - - /** - * 批量删除用药计划 - * - * @param ids 需要删除的用药计划主键集合 - * @return 结果 - */ - public int deleteHealthMedicationPlanByIds(Long[] ids); - - /** - * 删除用药计划信息 - * - * @param id 用药计划主键 - * @return 结果 - */ - public int deleteHealthMedicationPlanById(Long id); - - /** - * 暂停用药计划 - * - * @param id 用药计划主键 - * @return 结果 - */ - public int pauseHealthMedicationPlan(Long id); - - /** - * 恢复用药计划 - * - * @param id 用药计划主键 - * @return 结果 - */ - public int resumeHealthMedicationPlan(Long id); - - /** - * 结束用药计划 - * - * @param id 用药计划主键 - * @return 结果 - */ - public int endHealthMedicationPlan(Long id); -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/IHealthMedicationRecordService.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/IHealthMedicationRecordService.java deleted file mode 100644 index 85eff4d..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/service/IHealthMedicationRecordService.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.intc.health.service; - -import java.util.List; -import com.intc.health.domain.HealthMedicationRecord; -import com.intc.health.domain.dto.HealthMedicationRecordDto; -import com.intc.health.domain.vo.HealthMedicationRecordVo; - -/** - * 用药记录Service接口 - * - * @author intc - * @date 2025-03-18 - */ -public interface IHealthMedicationRecordService -{ - /** - * 查询用药记录 - * - * @param id 用药记录主键 - * @return 用药记录 - */ - public HealthMedicationRecordVo selectHealthMedicationRecordById(Long id); - - /** - * 查询用药记录列表 - * - * @param dto 用药记录 - * @return 用药记录集合 - */ - public List selectHealthMedicationRecordList(HealthMedicationRecordDto dto); - - /** - * 查询某计划某天的用药记录 - * - * @param planId 计划ID - * @param date 日期(yyyy-MM-dd) - * @return 用药记录集合 - */ - public List selectRecordByPlanAndDate(Long planId, String date); - - /** - * 新增用药记录 - * - * @param record 用药记录 - * @return 结果 - */ - public int insertHealthMedicationRecord(HealthMedicationRecord record); - - /** - * 修改用药记录 - * - * @param record 用药记录 - * @return 结果 - */ - public int updateHealthMedicationRecord(HealthMedicationRecord record); - - /** - * 批量删除用药记录 - * - * @param ids 需要删除的用药记录主键集合 - * @return 结果 - */ - public int deleteHealthMedicationRecordByIds(Long[] ids); - - /** - * 删除用药记录信息 - * - * @param id 用药记录主键 - * @return 结果 - */ - public int deleteHealthMedicationRecordById(Long id); - - /** - * 服药(标记为已服用) - * - * @param id 记录ID - * @param dosage 实际服用剂量 - * @param remark 备注 - * @return 结果 - */ - public int takeMedication(Long id, Double dosage, String remark); - - /** - * 跳过服药 - * - * @param id 记录ID - * @param remark 原因 - * @return 结果 - */ - public int skipMedication(Long id, String remark); - - /** - * 获取今日用药记录 - * - * @param personId 人员ID(可选) - * @return 用药记录集合 - */ - public List getTodayRecords(Long personId); - - /** - * 统计某计划某天已服药次数 - * - * @param planId 计划ID - * @param date 日期(yyyy-MM-dd) - * @return 次数 - */ - public int countTakenByPlanAndDate(Long planId, String date); -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationAdherenceService.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationAdherenceService.java index 77aaa98..8d4b5e4 100644 --- a/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationAdherenceService.java +++ b/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationAdherenceService.java @@ -1,9 +1,9 @@ package com.intc.health.service; -import com.intc.health.domain.dto.MedicationAdherenceDto; import com.intc.health.domain.vo.DailyAdherenceVo; import com.intc.health.domain.vo.MedicationAdherenceVo; +import java.time.LocalDate; import java.util.List; import java.util.Map; @@ -17,58 +17,21 @@ public interface IMedicationAdherenceService { /** * 获取总体依从性统计 - * - * @param dto 查询参数 - * @return 统计结果 */ - MedicationAdherenceVo getOverallAdherence(MedicationAdherenceDto dto); + MedicationAdherenceVo getOverallAdherence(Long memberId, LocalDate startDate, LocalDate endDate); /** - * 获取每日依从性统计列表(用于趋势图) - * - * @param dto 查询参数 - * @return 每日统计列表 + * 获取每日依从性统计列表 */ - List getDailyAdherenceList(MedicationAdherenceDto dto); + List getDailyAdherenceList(Long memberId, LocalDate startDate, LocalDate endDate); /** - * 获取日历视图数据(某月的每日统计) - * - * @param personId 人员ID - * @param yearMonth 年月(yyyy-MM) - * @return 每日统计列表 + * 获取日历视图数据 */ - List getCalendarData(Long personId, String yearMonth); + List getCalendarData(Long memberId, String yearMonth); /** - * 获取各时段服药统计(早中晚) - * - * @param dto 查询参数 - * @return 时段统计Map + * 获取各时段服药统计 */ - Map getTimeSlotAdherence(MedicationAdherenceDto dto); - - /** - * 获取各药品依从性统计 - * - * @param dto 查询参数 - * @return 药品统计列表 - */ - List getMedicineAdherenceList(MedicationAdherenceDto dto); - - /** - * 获取各人员依从性统计(家属视角) - * - * @param dto 查询参数 - * @return 人员统计列表 - */ - List getPersonAdherenceList(MedicationAdherenceDto dto); - - /** - * 获取漏服原因统计 - * - * @param dto 查询参数 - * @return 原因统计Map - */ - Map getMissedReasonStats(MedicationAdherenceDto dto); + Map getTimeSlotAdherence(Long memberId, LocalDate startDate, LocalDate endDate); } \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationPlanService.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationPlanService.java new file mode 100644 index 0000000..0a5df55 --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationPlanService.java @@ -0,0 +1,56 @@ +package com.intc.health.service; + +import com.intc.health.domain.MedicationPlan; +import com.intc.health.domain.dto.MedicationPlanDto; +import com.intc.health.domain.vo.MedicationPlanVo; + +import java.util.List; + +/** + * 用药计划Service接口 + * + * @author bot5 + * @date 2026-03-19 + */ +public interface IMedicationPlanService { + + /** + * 查询用药计划 + */ + MedicationPlanVo selectById(Long id); + + /** + * 查询用药计划列表 + */ + List selectList(MedicationPlanDto dto); + + /** + * 新增用药计划 + */ + int insert(MedicationPlan plan); + + /** + * 修改用药计划 + */ + int update(MedicationPlan plan); + + /** + * 删除用药计划 + */ + int deleteByIds(Long[] ids); + + /** + * 暂停用药计划 + */ + int pause(Long id); + + /** + * 恢复用药计划 + */ + int resume(Long id); + + /** + * 结束用药计划 + */ + int end(Long id); +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationTaskService.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationTaskService.java new file mode 100644 index 0000000..4354210 --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/service/IMedicationTaskService.java @@ -0,0 +1,56 @@ +package com.intc.health.service; + +import com.intc.health.domain.MedicationTask; +import com.intc.health.domain.dto.MedicationTaskDto; +import com.intc.health.domain.vo.MedicationTaskVo; + +import java.util.List; + +/** + * 服药任务Service接口 + * + * @author bot5 + * @date 2026-03-19 + */ +public interface IMedicationTaskService { + + /** + * 查询服药任务 + */ + MedicationTaskVo selectById(Long id); + + /** + * 查询服药任务列表 + */ + List selectList(MedicationTaskDto dto); + + /** + * 新增服药任务 + */ + int insert(MedicationTask task); + + /** + * 修改服药任务 + */ + int update(MedicationTask task); + + /** + * 删除服药任务 + */ + int deleteByIds(Long[] ids); + + /** + * 确认服药 + */ + int confirm(Long id, Integer confirmType); + + /** + * 跳过服药 + */ + int skip(Long id, String notes); + + /** + * 标记漏服 + */ + int markMissed(Long id, String notes); +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/HealthMedicationPlanServiceImpl.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/HealthMedicationPlanServiceImpl.java deleted file mode 100644 index f09c5b3..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/HealthMedicationPlanServiceImpl.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.intc.health.service.impl; - -import com.intc.common.core.utils.DateUtils; -import com.intc.common.core.utils.IdWorker; -import com.intc.common.security.utils.SecurityUtils; -import com.intc.health.domain.HealthMedicationPlan; -import com.intc.health.domain.dto.HealthMedicationPlanDto; -import com.intc.health.domain.vo.HealthMedicationPlanVo; -import com.intc.health.mapper.HealthMedicationPlanMapper; -import com.intc.health.mapper.HealthMedicationRecordMapper; -import com.intc.health.service.IHealthMedicationPlanService; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.List; - -/** - * 用药计划Service业务层处理 - * - * @author intc - * @date 2025-03-18 - */ -@Service -public class HealthMedicationPlanServiceImpl implements IHealthMedicationPlanService -{ - @Resource - private HealthMedicationPlanMapper healthMedicationPlanMapper; - - @Resource - private HealthMedicationRecordMapper healthMedicationRecordMapper; - - /** - * 查询用药计划 - * - * @param id 用药计划主键 - * @return 用药计划 - */ - @Override - public HealthMedicationPlanVo selectHealthMedicationPlanById(Long id) - { - HealthMedicationPlanVo vo = healthMedicationPlanMapper.selectHealthMedicationPlanById(id); - if (vo != null) { - // 设置药品显示名称 - vo.setMedicineDisplayName(vo.getShortName() + "-" + vo.getBrand() + "(" + vo.getPackaging() + ")"); - // 统计今日服药情况 - String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); - int takenCount = healthMedicationRecordMapper.countTakenByPlanAndDate(id, today); - vo.setTodayTakenCount(takenCount); - vo.setTodayTotalCount(vo.getFrequency()); - } - return vo; - } - - /** - * 查询用药计划列表 - * - * @param dto 用药计划 - * @return 用药计划 - */ - @Override - public List selectHealthMedicationPlanList(HealthMedicationPlanDto dto) - { - List list = healthMedicationPlanMapper.selectHealthMedicationPlanList(dto); - String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); - for (HealthMedicationPlanVo vo : list) { - // 设置药品显示名称 - vo.setMedicineDisplayName(vo.getShortName() + "-" + vo.getBrand() + "(" + vo.getPackaging() + ")"); - // 统计今日服药情况 - if ("1".equals(vo.getStatus())) { - int takenCount = healthMedicationRecordMapper.countTakenByPlanAndDate(vo.getId(), today); - vo.setTodayTakenCount(takenCount); - vo.setTodayTotalCount(vo.getFrequency()); - } - } - return list; - } - - /** - * 新增用药计划 - * - * @param plan 用药计划 - * @return 结果 - */ - @Override - public int insertHealthMedicationPlan(HealthMedicationPlan plan) - { - plan.setId(IdWorker.getId()); - plan.setCreateBy(SecurityUtils.getUsername()); - plan.setCreateTime(DateUtils.getNowDate()); - plan.setDelFlag("0"); - // 默认状态为进行中 - if (plan.getStatus() == null) { - plan.setStatus("1"); - } - return healthMedicationPlanMapper.insertHealthMedicationPlan(plan); - } - - /** - * 修改用药计划 - * - * @param plan 用药计划 - * @return 结果 - */ - @Override - public int updateHealthMedicationPlan(HealthMedicationPlan plan) - { - plan.setUpdateBy(SecurityUtils.getUsername()); - plan.setUpdateTime(DateUtils.getNowDate()); - return healthMedicationPlanMapper.updateHealthMedicationPlan(plan); - } - - /** - * 批量删除用药计划 - * - * @param ids 需要删除的用药计划主键 - * @return 结果 - */ - @Override - public int deleteHealthMedicationPlanByIds(Long[] ids) - { - return healthMedicationPlanMapper.removeHealthMedicationPlanByIds(ids); - } - - /** - * 删除用药计划信息 - * - * @param id 用药计划主键 - * @return 结果 - */ - @Override - public int deleteHealthMedicationPlanById(Long id) - { - return healthMedicationPlanMapper.removeHealthMedicationPlanById(id); - } - - /** - * 暂停用药计划 - * - * @param id 用药计划主键 - * @return 结果 - */ - @Override - public int pauseHealthMedicationPlan(Long id) - { - HealthMedicationPlan plan = new HealthMedicationPlan(); - plan.setId(id); - plan.setStatus("3"); // 已暂停 - plan.setUpdateBy(SecurityUtils.getUsername()); - plan.setUpdateTime(DateUtils.getNowDate()); - return healthMedicationPlanMapper.updateHealthMedicationPlan(plan); - } - - /** - * 恢复用药计划 - * - * @param id 用药计划主键 - * @return 结果 - */ - @Override - public int resumeHealthMedicationPlan(Long id) - { - HealthMedicationPlan plan = new HealthMedicationPlan(); - plan.setId(id); - plan.setStatus("1"); // 进行中 - plan.setUpdateBy(SecurityUtils.getUsername()); - plan.setUpdateTime(DateUtils.getNowDate()); - return healthMedicationPlanMapper.updateHealthMedicationPlan(plan); - } - - /** - * 结束用药计划 - * - * @param id 用药计划主键 - * @return 结果 - */ - @Override - public int endHealthMedicationPlan(Long id) - { - HealthMedicationPlan plan = new HealthMedicationPlan(); - plan.setId(id); - plan.setStatus("2"); // 已结束 - plan.setUpdateBy(SecurityUtils.getUsername()); - plan.setUpdateTime(DateUtils.getNowDate()); - return healthMedicationPlanMapper.updateHealthMedicationPlan(plan); - } -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/HealthMedicationRecordServiceImpl.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/HealthMedicationRecordServiceImpl.java deleted file mode 100644 index 0e7e713..0000000 --- a/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/HealthMedicationRecordServiceImpl.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.intc.health.service.impl; - -import com.intc.common.core.utils.DateUtils; -import com.intc.common.core.utils.IdWorker; -import com.intc.common.security.utils.SecurityUtils; -import com.intc.health.domain.HealthMedicationRecord; -import com.intc.health.domain.dto.HealthMedicationRecordDto; -import com.intc.health.domain.vo.HealthMedicationRecordVo; -import com.intc.health.mapper.HealthMedicationRecordMapper; -import com.intc.health.service.IHealthMedicationRecordService; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.List; - -/** - * 用药记录Service业务层处理 - * - * @author intc - * @date 2025-03-18 - */ -@Service -public class HealthMedicationRecordServiceImpl implements IHealthMedicationRecordService -{ - @Resource - private HealthMedicationRecordMapper healthMedicationRecordMapper; - - /** - * 查询用药记录 - * - * @param id 用药记录主键 - * @return 用药记录 - */ - @Override - public HealthMedicationRecordVo selectHealthMedicationRecordById(Long id) - { - HealthMedicationRecordVo vo = healthMedicationRecordMapper.selectHealthMedicationRecordById(id); - if (vo != null) { - vo.setMedicineDisplayName(vo.getShortName() + "-" + vo.getBrand() + "(" + vo.getPackaging() + ")"); - } - return vo; - } - - /** - * 查询用药记录列表 - * - * @param dto 用药记录 - * @return 用药记录 - */ - @Override - public List selectHealthMedicationRecordList(HealthMedicationRecordDto dto) - { - List list = healthMedicationRecordMapper.selectHealthMedicationRecordList(dto); - for (HealthMedicationRecordVo vo : list) { - vo.setMedicineDisplayName(vo.getShortName() + "-" + vo.getBrand() + "(" + vo.getPackaging() + ")"); - } - return list; - } - - /** - * 查询某计划某天的用药记录 - * - * @param planId 计划ID - * @param date 日期(yyyy-MM-dd) - * @return 用药记录集合 - */ - @Override - public List selectRecordByPlanAndDate(Long planId, String date) - { - List list = healthMedicationRecordMapper.selectRecordByPlanAndDate(planId, date); - for (HealthMedicationRecordVo vo : list) { - vo.setMedicineDisplayName(vo.getShortName() + "-" + vo.getBrand() + "(" + vo.getPackaging() + ")"); - } - return list; - } - - /** - * 新增用药记录 - * - * @param record 用药记录 - * @return 结果 - */ - @Override - public int insertHealthMedicationRecord(HealthMedicationRecord record) - { - record.setId(IdWorker.getId()); - record.setCreateBy(SecurityUtils.getUsername()); - record.setCreateTime(DateUtils.getNowDate()); - record.setDelFlag("0"); - // 默认状态为待服用 - if (record.getStatus() == null) { - record.setStatus("1"); - } - return healthMedicationRecordMapper.insertHealthMedicationRecord(record); - } - - /** - * 修改用药记录 - * - * @param record 用药记录 - * @return 结果 - */ - @Override - public int updateHealthMedicationRecord(HealthMedicationRecord record) - { - record.setUpdateBy(SecurityUtils.getUsername()); - record.setUpdateTime(DateUtils.getNowDate()); - return healthMedicationRecordMapper.updateHealthMedicationRecord(record); - } - - /** - * 批量删除用药记录 - * - * @param ids 需要删除的用药记录主键 - * @return 结果 - */ - @Override - public int deleteHealthMedicationRecordByIds(Long[] ids) - { - return healthMedicationRecordMapper.removeHealthMedicationRecordByIds(ids); - } - - /** - * 删除用药记录信息 - * - * @param id 用药记录主键 - * @return 结果 - */ - @Override - public int deleteHealthMedicationRecordById(Long id) - { - return healthMedicationRecordMapper.removeHealthMedicationRecordById(id); - } - - /** - * 服药(标记为已服用) - * - * @param id 记录ID - * @param dosage 实际服用剂量 - * @param remark 备注 - * @return 结果 - */ - @Override - public int takeMedication(Long id, Double dosage, String remark) - { - HealthMedicationRecord record = new HealthMedicationRecord(); - record.setId(id); - record.setStatus("2"); // 已服用 - record.setActualTime(new Date()); - if (dosage != null) { - record.setDosage(dosage); - } - if (remark != null) { - record.setRemark(remark); - } - record.setUpdateBy(SecurityUtils.getUsername()); - record.setUpdateTime(DateUtils.getNowDate()); - return healthMedicationRecordMapper.updateHealthMedicationRecord(record); - } - - /** - * 跳过服药 - * - * @param id 记录ID - * @param remark 原因 - * @return 结果 - */ - @Override - public int skipMedication(Long id, String remark) - { - HealthMedicationRecord record = new HealthMedicationRecord(); - record.setId(id); - record.setStatus("3"); // 已跳过 - if (remark != null) { - record.setRemark(remark); - } - record.setUpdateBy(SecurityUtils.getUsername()); - record.setUpdateTime(DateUtils.getNowDate()); - return healthMedicationRecordMapper.updateHealthMedicationRecord(record); - } - - /** - * 获取今日用药记录 - * - * @param personId 人员ID(可选) - * @return 用药记录集合 - */ - @Override - public List getTodayRecords(Long personId) - { - HealthMedicationRecordDto dto = new HealthMedicationRecordDto(); - dto.setQueryDate(new Date()); - if (personId != null) { - dto.setPersonId(personId); - } - return selectHealthMedicationRecordList(dto); - } - - /** - * 统计某计划某天已服药次数 - * - * @param planId 计划ID - * @param date 日期(yyyy-MM-dd) - * @return 次数 - */ - @Override - public int countTakenByPlanAndDate(Long planId, String date) - { - return healthMedicationRecordMapper.countTakenByPlanAndDate(planId, date); - } -} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationAdherenceServiceImpl.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationAdherenceServiceImpl.java index e87e31d..e16a7d6 100644 --- a/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationAdherenceServiceImpl.java +++ b/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationAdherenceServiceImpl.java @@ -1,10 +1,9 @@ package com.intc.health.service.impl; -import com.intc.health.domain.dto.MedicationAdherenceDto; -import com.intc.health.domain.vo.DailyAdherenceVo; -import com.intc.health.domain.vo.MedicationAdherenceVo; -import com.intc.health.mapper.HealthMedicationRecordMapper; +import com.intc.health.mapper.MedicationTaskMapper; import com.intc.health.service.IMedicationAdherenceService; +import com.intc.health.domain.vo.MedicationAdherenceVo; +import com.intc.health.domain.vo.DailyAdherenceVo; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -17,7 +16,7 @@ import java.time.temporal.ChronoUnit; import java.util.*; /** - * 依从性统计Service业务层处理 + * 依从性统计Service实现 * * @author bot5 * @date 2026-03-19 @@ -26,11 +25,11 @@ import java.util.*; public class MedicationAdherenceServiceImpl implements IMedicationAdherenceService { @Resource - private HealthMedicationRecordMapper recordMapper; + private MedicationTaskMapper taskMapper; @Override - public MedicationAdherenceVo getOverallAdherence(MedicationAdherenceDto dto) { - Map stats = recordMapper.getAdherenceStats(dto); + public MedicationAdherenceVo getOverallAdherence(Long memberId, LocalDate startDate, LocalDate endDate) { + Map stats = taskMapper.getOverallStats(memberId, startDate, endDate); MedicationAdherenceVo vo = new MedicationAdherenceVo(); vo.setTotalTasks(getIntValue(stats, "total_tasks")); @@ -60,17 +59,12 @@ public class MedicationAdherenceServiceImpl implements IMedicationAdherenceServi vo.setOntimeRate(BigDecimal.ZERO); } - vo.setStartDate(dto.getStartDate()); - vo.setEndDate(dto.getEndDate()); - vo.setPersonId(dto.getPersonId()); - vo.setPlanId(dto.getPlanId()); - return vo; } @Override - public List getDailyAdherenceList(MedicationAdherenceDto dto) { - List> dailyStats = recordMapper.getDailyAdherenceStats(dto); + public List getDailyAdherenceList(Long memberId, LocalDate startDate, LocalDate endDate) { + List> dailyStats = taskMapper.getDailyStats(memberId, startDate, endDate); List result = new ArrayList<>(); for (Map stat : dailyStats) { @@ -82,7 +76,6 @@ public class MedicationAdherenceServiceImpl implements IMedicationAdherenceServi vo.setSkippedTasks(getIntValue(stat, "skipped_tasks")); vo.setOntimeTasks(getIntValue(stat, "ontime_tasks")); - // 计算服药率 if (vo.getTotalTasks() > 0) { BigDecimal rate = BigDecimal.valueOf(vo.getCompletedTasks()) .multiply(BigDecimal.valueOf(100)) @@ -92,7 +85,6 @@ public class MedicationAdherenceServiceImpl implements IMedicationAdherenceServi vo.setAdherenceRate(BigDecimal.ZERO); } - // 计算准时率 if (vo.getCompletedTasks() > 0) { BigDecimal rate = BigDecimal.valueOf(vo.getOntimeTasks()) .multiply(BigDecimal.valueOf(100)) @@ -109,20 +101,14 @@ public class MedicationAdherenceServiceImpl implements IMedicationAdherenceServi } @Override - public List getCalendarData(Long personId, String yearMonth) { - // 解析年月 + public List getCalendarData(Long memberId, String yearMonth) { YearMonth ym = YearMonth.parse(yearMonth, DateTimeFormatter.ofPattern("yyyy-MM")); LocalDate startDate = ym.atDay(1); LocalDate endDate = ym.atEndOfMonth(); - MedicationAdherenceDto dto = new MedicationAdherenceDto(); - dto.setPersonId(personId); - dto.setStartDate(startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); - dto.setEndDate(endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + List dailyList = getDailyAdherenceList(memberId, startDate, endDate); - List dailyList = getDailyAdherenceList(dto); - - // 补全缺失的日期 + // 补全缺失日期 List result = new ArrayList<>(); Map dateMap = new HashMap<>(); for (DailyAdherenceVo vo : dailyList) { @@ -137,7 +123,6 @@ public class MedicationAdherenceServiceImpl implements IMedicationAdherenceServi if (dateMap.containsKey(dateStr)) { result.add(dateMap.get(dateStr)); } else { - // 没有数据的日期补零 DailyAdherenceVo vo = new DailyAdherenceVo(); vo.setDate(dateStr); vo.setTotalTasks(0); @@ -155,14 +140,14 @@ public class MedicationAdherenceServiceImpl implements IMedicationAdherenceServi } @Override - public Map getTimeSlotAdherence(MedicationAdherenceDto dto) { - List> slotStats = recordMapper.getTimeSlotAdherenceStats(dto); + public Map getTimeSlotAdherence(Long memberId, LocalDate startDate, LocalDate endDate) { + List> slotStats = taskMapper.getTimeSlotStats(memberId, startDate, endDate); Map result = new LinkedHashMap<>(); - result.put("morning", new MedicationAdherenceVo()); // 6:00-12:00 - result.put("afternoon", new MedicationAdherenceVo()); // 12:00-18:00 - result.put("evening", new MedicationAdherenceVo()); // 18:00-24:00 - result.put("night", new MedicationAdherenceVo()); // 0:00-6:00 + result.put("morning", new MedicationAdherenceVo()); + result.put("afternoon", new MedicationAdherenceVo()); + result.put("evening", new MedicationAdherenceVo()); + result.put("night", new MedicationAdherenceVo()); for (Map stat : slotStats) { int hour = getIntValue(stat, "hour"); @@ -182,7 +167,6 @@ public class MedicationAdherenceServiceImpl implements IMedicationAdherenceServi vo.setOntimeTasks(vo.getOntimeTasks() + getIntValue(stat, "ontime_tasks")); } - // 计算各时段的服药率 for (Map.Entry entry : result.entrySet()) { MedicationAdherenceVo vo = entry.getValue(); if (vo.getTotalTasks() != null && vo.getTotalTasks() > 0) { @@ -198,124 +182,22 @@ public class MedicationAdherenceServiceImpl implements IMedicationAdherenceServi return result; } - @Override - public List getMedicineAdherenceList(MedicationAdherenceDto dto) { - List> medicineStats = recordMapper.getMedicineAdherenceStats(dto); - - List result = new ArrayList<>(); - for (Map stat : medicineStats) { - MedicationAdherenceVo vo = new MedicationAdherenceVo(); - vo.setTotalTasks(getIntValue(stat, "total_tasks")); - vo.setCompletedTasks(getIntValue(stat, "completed_tasks")); - vo.setMissedTasks(getIntValue(stat, "missed_tasks")); - vo.setOntimeTasks(getIntValue(stat, "ontime_tasks")); - - // 药品信息 - // planId 和 planName 需要从查询结果获取 - - // 计算服药率 - if (vo.getTotalTasks() > 0) { - BigDecimal rate = BigDecimal.valueOf(vo.getCompletedTasks()) - .multiply(BigDecimal.valueOf(100)) - .divide(BigDecimal.valueOf(vo.getTotalTasks()), 2, RoundingMode.HALF_UP); - vo.setAdherenceRate(rate); - } else { - vo.setAdherenceRate(BigDecimal.ZERO); - } - - result.add(vo); - } - - return result; - } - - @Override - public List getPersonAdherenceList(MedicationAdherenceDto dto) { - List> personStats = recordMapper.getPersonAdherenceStats(dto); - - List result = new ArrayList<>(); - for (Map stat : personStats) { - MedicationAdherenceVo vo = new MedicationAdherenceVo(); - vo.setPersonId(getLongValue(stat, "person_id")); - vo.setPersonName(getStringValue(stat, "person_name")); - vo.setTotalTasks(getIntValue(stat, "total_tasks")); - vo.setCompletedTasks(getIntValue(stat, "completed_tasks")); - vo.setMissedTasks(getIntValue(stat, "missed_tasks")); - vo.setOntimeTasks(getIntValue(stat, "ontime_tasks")); - - // 计算服药率 - if (vo.getTotalTasks() > 0) { - BigDecimal rate = BigDecimal.valueOf(vo.getCompletedTasks()) - .multiply(BigDecimal.valueOf(100)) - .divide(BigDecimal.valueOf(vo.getTotalTasks()), 2, RoundingMode.HALF_UP); - vo.setAdherenceRate(rate); - } else { - vo.setAdherenceRate(BigDecimal.ZERO); - } - - result.add(vo); - } - - return result; - } - - @Override - public Map getMissedReasonStats(MedicationAdherenceDto dto) { - List> reasonStats = recordMapper.getMissedReasonStats(dto); - - Map result = new LinkedHashMap<>(); - for (Map stat : reasonStats) { - String reason = getStringValue(stat, "remark"); - if (reason == null || reason.isEmpty()) { - reason = "未填写原因"; - } - int count = getIntValue(stat, "count"); - result.merge(reason, count, Integer::sum); - } - - return result; - } - - // ========== 辅助方法 ========== - private String getTimeSlot(int hour) { - if (hour >= 6 && hour < 12) { - return "morning"; - } else if (hour >= 12 && hour < 18) { - return "afternoon"; - } else if (hour >= 18 && hour < 24) { - return "evening"; - } else { - return "night"; - } + if (hour >= 6 && hour < 12) return "morning"; + if (hour >= 12 && hour < 18) return "afternoon"; + if (hour >= 18 && hour < 24) return "evening"; + return "night"; } private Integer getIntValue(Map map, String key) { - if (map == null || map.get(key) == null) { - return 0; - } + if (map == null || map.get(key) == null) return 0; Object value = map.get(key); - if (value instanceof Number) { - return ((Number) value).intValue(); - } + if (value instanceof Number) return ((Number) value).intValue(); return 0; } - private Long getLongValue(Map map, String key) { - if (map == null || map.get(key) == null) { - return null; - } - Object value = map.get(key); - if (value instanceof Number) { - return ((Number) value).longValue(); - } - return null; - } - private String getStringValue(Map map, String key) { - if (map == null || map.get(key) == null) { - return null; - } + if (map == null || map.get(key) == null) return null; return map.get(key).toString(); } } \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationPlanServiceImpl.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationPlanServiceImpl.java new file mode 100644 index 0000000..e05e7b1 --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationPlanServiceImpl.java @@ -0,0 +1,94 @@ +package com.intc.health.service.impl; + +import com.intc.common.core.utils.DateUtils; +import com.intc.common.security.utils.SecurityUtils; +import com.intc.health.domain.MedicationPlan; +import com.intc.health.domain.dto.MedicationPlanDto; +import com.intc.health.domain.vo.MedicationPlanVo; +import com.intc.health.mapper.MedicationPlanMapper; +import com.intc.health.service.IMedicationPlanService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 用药计划Service实现 + * + * @author bot5 + * @date 2026-03-19 + */ +@Service +public class MedicationPlanServiceImpl implements IMedicationPlanService { + + @Resource + private MedicationPlanMapper planMapper; + + @Override + public MedicationPlanVo selectById(Long id) { + MedicationPlanVo vo = planMapper.selectById(id); + if (vo != null) { + // 统计今日任务情况 + // TODO: 添加今日任务统计 + } + return vo; + } + + @Override + public List selectList(MedicationPlanDto dto) { + List list = planMapper.selectList(dto); + // TODO: 可以添加今日任务统计 + return list; + } + + @Override + public int insert(MedicationPlan plan) { + plan.setStatus(1); // 默认执行中 + plan.setDelFlag(0); + plan.setCreateBy(SecurityUtils.getUsername()); + plan.setCreateTime(DateUtils.getNowDate()); + return planMapper.insert(plan); + } + + @Override + public int update(MedicationPlan plan) { + plan.setUpdateBy(SecurityUtils.getUsername()); + plan.setUpdateTime(DateUtils.getNowDate()); + return planMapper.update(plan); + } + + @Override + public int deleteByIds(Long[] ids) { + return planMapper.removeByIds(ids); + } + + @Override + public int pause(Long id) { + MedicationPlan plan = new MedicationPlan(); + plan.setId(id); + plan.setStatus(2); // 已暂停 + plan.setUpdateBy(SecurityUtils.getUsername()); + plan.setUpdateTime(DateUtils.getNowDate()); + return planMapper.update(plan); + } + + @Override + public int resume(Long id) { + MedicationPlan plan = new MedicationPlan(); + plan.setId(id); + plan.setStatus(1); // 执行中 + plan.setUpdateBy(SecurityUtils.getUsername()); + plan.setUpdateTime(DateUtils.getNowDate()); + return planMapper.update(plan); + } + + @Override + public int end(Long id) { + MedicationPlan plan = new MedicationPlan(); + plan.setId(id); + plan.setStatus(3); // 已结束 + plan.setUpdateBy(SecurityUtils.getUsername()); + plan.setUpdateTime(DateUtils.getNowDate()); + return planMapper.update(plan); + } +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationTaskServiceImpl.java b/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationTaskServiceImpl.java new file mode 100644 index 0000000..ce00e2b --- /dev/null +++ b/intc-modules/intc-health/src/main/java/com/intc/health/service/impl/MedicationTaskServiceImpl.java @@ -0,0 +1,93 @@ +package com.intc.health.service.impl; + +import com.intc.common.core.utils.DateUtils; +import com.intc.common.security.utils.SecurityUtils; +import com.intc.health.domain.MedicationTask; +import com.intc.health.domain.dto.MedicationTaskDto; +import com.intc.health.domain.vo.MedicationTaskVo; +import com.intc.health.mapper.MedicationTaskMapper; +import com.intc.health.service.IMedicationTaskService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 服药任务Service实现 + * + * @author bot5 + * @date 2026-03-19 + */ +@Service +public class MedicationTaskServiceImpl implements IMedicationTaskService { + + @Resource + private MedicationTaskMapper taskMapper; + + @Override + public MedicationTaskVo selectById(Long id) { + return taskMapper.selectById(id); + } + + @Override + public List selectList(MedicationTaskDto dto) { + return taskMapper.selectList(dto); + } + + @Override + public int insert(MedicationTask task) { + task.setStatus(0); // 待服药 + task.setRemindStatus(0); // 未提醒 + task.setDelFlag(0); + task.setCreateBy(SecurityUtils.getUsername()); + task.setCreateTime(DateUtils.getNowDate()); + return taskMapper.insert(task); + } + + @Override + public int update(MedicationTask task) { + task.setUpdateBy(SecurityUtils.getUsername()); + task.setUpdateTime(DateUtils.getNowDate()); + return taskMapper.update(task); + } + + @Override + public int deleteByIds(Long[] ids) { + return taskMapper.removeByIds(ids); + } + + @Override + public int confirm(Long id, Integer confirmType) { + MedicationTask task = new MedicationTask(); + task.setId(id); + task.setStatus(1); // 已服药 + task.setConfirmType(confirmType != null ? confirmType : 1); + task.setActualTime(LocalDateTime.now()); + task.setUpdateBy(SecurityUtils.getUsername()); + task.setUpdateTime(DateUtils.getNowDate()); + return taskMapper.update(task); + } + + @Override + public int skip(Long id, String notes) { + MedicationTask task = new MedicationTask(); + task.setId(id); + task.setStatus(3); // 跳过 + task.setNotes(notes); + task.setUpdateBy(SecurityUtils.getUsername()); + task.setUpdateTime(DateUtils.getNowDate()); + return taskMapper.update(task); + } + + @Override + public int markMissed(Long id, String notes) { + MedicationTask task = new MedicationTask(); + task.setId(id); + task.setStatus(2); // 漏服 + task.setNotes(notes); + task.setUpdateBy(SecurityUtils.getUsername()); + task.setUpdateTime(DateUtils.getNowDate()); + return taskMapper.update(task); + } +} \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/task/MedicationRemindJob.java b/intc-modules/intc-health/src/main/java/com/intc/health/task/MedicationRemindJob.java index 56864e0..616bbc3 100644 --- a/intc-modules/intc-health/src/main/java/com/intc/health/task/MedicationRemindJob.java +++ b/intc-modules/intc-health/src/main/java/com/intc/health/task/MedicationRemindJob.java @@ -1,18 +1,19 @@ package com.intc.health.task; -import com.intc.health.domain.vo.HealthMedicationRecordVo; -import com.intc.health.mapper.HealthMedicationRecordMapper; +import com.intc.health.domain.vo.MedicationTaskVo; +import com.intc.health.mapper.MedicationTaskMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; /** * 用药提醒定时器 - * 用于扫描待提醒的服药任务并发送提醒 * * @author bot5 * @date 2026-03-19 @@ -23,131 +24,93 @@ public class MedicationRemindJob { private static final Logger log = LoggerFactory.getLogger(MedicationRemindJob.class); @Resource - private HealthMedicationRecordMapper recordMapper; - - // TODO: 注入消息推送服务,后续实现 - // @Resource - // private MessagePushService messagePushService; + private MedicationTaskMapper taskMapper; /** - * 扫描并发送服药提醒 + * 扫描并发送提醒 * 定时任务配置:每分钟执行 - * 调用方式:medicationRemindJob.scanAndSendReminders */ public void scanAndSendReminders() { log.debug("========== 开始扫描服药提醒 =========="); LocalDateTime now = LocalDateTime.now(); - // 扫描未来1分钟内的待服药记录 - LocalDateTime startTime = now.plusMinutes(-1); + // 扫描未来1分钟内的待服药任务 + LocalDateTime startTime = now.minusMinutes(1); LocalDateTime endTime = now.plusMinutes(1); - List pendingRecords = recordMapper.selectPendingRemindRecords(startTime, endTime); + List pendingTasks = taskMapper.selectPendingRemind(startTime, endTime); - if (pendingRecords == null || pendingRecords.isEmpty()) { - log.debug("没有需要提醒的服药记录"); + if (pendingTasks == null || pendingTasks.isEmpty()) { return; } - log.info("发现 {} 条待提醒的服药记录", pendingRecords.size()); + log.info("发现 {} 条待提醒的服药任务", pendingTasks.size()); - for (HealthMedicationRecordVo record : pendingRecords) { + for (MedicationTaskVo task : pendingTasks) { try { - sendReminder(record); + sendReminder(task); } catch (Exception e) { - log.error("发送服药提醒失败,记录ID: {}, 错误: {}", record.getId(), e.getMessage(), e); + log.error("发送提醒失败,任务ID: {}", task.getId(), e); } } - - log.debug("========== 服药提醒扫描完成 =========="); } /** - * 发送服药提醒 - * - * @param record 服药记录 + * 发送提醒 */ - private void sendReminder(HealthMedicationRecordVo record) { - log.info("发送服药提醒: 人员={}, 药品={}, 计划时间={}", - record.getPersonName(), - record.getMedicineName(), - record.getScheduledTime()); + private void sendReminder(MedicationTaskVo task) { + log.info("发送提醒: 成员={}, 药品={}, 计划时间={} {}", + task.getMemberName(), task.getMedicineName(), + task.getPlannedDate(), task.getPlannedTime()); - // TODO: 实现消息推送逻辑 + // TODO: 实现消息推送 // 1. 查询用户的提醒设置 - // 2. 根据设置选择推送渠道(APP推送/微信/短信) + // 2. 根据设置选择推送渠道 // 3. 发送推送消息 // 4. 记录提醒日志 - - // 暂时只打印日志 - String message = String.format("【服药提醒】%s,请按时服用 %s,剂量:%s%s", - record.getPersonName(), - record.getMedicineName(), - record.getDosage() != null ? record.getDosage() : "", - record.getDosageUnit() != null ? record.getDosageUnit() : ""); - - log.info("推送消息: {}", message); - - // TODO: 调用消息推送服务 - // messagePushService.push(record.getPersonId(), message); } /** - * 扫描超时未服药记录并发送二次提醒 + * 扫描超时未服药任务 * 定时任务配置:每5分钟执行 - * 调用方式:medicationRemindJob.scanOverdueRecords */ public void scanOverdueRecords() { - log.debug("========== 开始扫描超时未服药记录 =========="); + log.debug("========== 开始扫描超时未服药任务 =========="); LocalDateTime now = LocalDateTime.now(); - // 扫描超过计划时间30分钟仍未服药的记录 + // 扫描超过计划时间30分钟仍未服药的任务 LocalDateTime overdueThreshold = now.minusMinutes(30); - // 查询超时的待服药记录 - List overdueRecords = recordMapper.selectPendingRemindRecords( - overdueThreshold.minusMinutes(5), // 查询5分钟内超时的 - overdueThreshold - ); + LocalDateTime startTime = overdueThreshold.minusMinutes(5); + LocalDateTime endTime = overdueThreshold; - if (overdueRecords == null || overdueRecords.isEmpty()) { - log.debug("没有超时未服药记录"); + List overdueTasks = taskMapper.selectPendingRemind(startTime, endTime); + + if (overdueTasks == null || overdueTasks.isEmpty()) { return; } - log.info("发现 {} 条超时未服药记录", overdueRecords.size()); + log.info("发现 {} 条超时未服药任务", overdueTasks.size()); - for (HealthMedicationRecordVo record : overdueRecords) { + for (MedicationTaskVo task : overdueTasks) { try { - sendOverdueReminder(record); + sendOverdueReminder(task); } catch (Exception e) { - log.error("发送超时提醒失败,记录ID: {}, 错误: {}", record.getId(), e.getMessage(), e); + log.error("发送超时提醒失败,任务ID: {}", task.getId(), e); } } - - log.debug("========== 超时未服药扫描完成 =========="); } /** - * 发送超时提醒(二次提醒/通知家属) - * - * @param record 服药记录 + * 发送超时提醒 */ - private void sendOverdueReminder(HealthMedicationRecordVo record) { - log.warn("超时未服药: 人员={}, 药品={}, 计划时间={}", - record.getPersonName(), - record.getMedicineName(), - record.getScheduledTime()); + private void sendOverdueReminder(MedicationTaskVo task) { + log.warn("超时未服药: 成员={}, 药品={}, 计划时间={} {}", + task.getMemberName(), task.getMedicineName(), + task.getPlannedDate(), task.getPlannedTime()); // TODO: 实现超时提醒逻辑 - // 1. 发送二次提醒给用户 - // 2. 如果配置了家属通知,同时通知家属 - // 3. 记录提醒日志 - - String message = String.format("【漏服提醒】%s 未按时服用 %s,请及时处理", - record.getPersonName(), - record.getMedicineName()); - - log.info("推送超时消息: {}", message); + // 1. 发送二次提醒 + // 2. 如果配置了家属通知,通知家属 } } \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/java/com/intc/health/task/MedicationTaskJob.java b/intc-modules/intc-health/src/main/java/com/intc/health/task/MedicationTaskJob.java index 6194b4c..eeeb79f 100644 --- a/intc-modules/intc-health/src/main/java/com/intc/health/task/MedicationTaskJob.java +++ b/intc-modules/intc-health/src/main/java/com/intc/health/task/MedicationTaskJob.java @@ -1,30 +1,28 @@ package com.intc.health.task; -import com.alibaba.fastjson2.JSON; -import com.alibaba.fastjson2.JSONArray; -import com.intc.common.core.utils.IdWorker; -import com.intc.health.domain.HealthMedicationRecord; -import com.intc.health.domain.vo.HealthMedicationPlanVo; -import com.intc.health.mapper.HealthMedicationPlanMapper; -import com.intc.health.mapper.HealthMedicationRecordMapper; +import com.fasterxml.jackson.databind.JsonNode; +import com.intc.common.core.utils.DateUtils; +import com.intc.health.domain.MedicationTask; +import com.intc.health.domain.vo.MedicationPlanVo; +import com.intc.health.mapper.MedicationPlanMapper; +import com.intc.health.mapper.MedicationTaskMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.math.BigDecimal; import java.time.DayOfWeek; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** - * 用药任务定时器 - * 用于每日自动生成服药记录 + * 服药任务生成定时器 + * 按文档规范实现 * * @author bot5 * @date 2026-03-19 @@ -35,15 +33,14 @@ public class MedicationTaskJob { private static final Logger log = LoggerFactory.getLogger(MedicationTaskJob.class); @Resource - private HealthMedicationPlanMapper planMapper; + private MedicationPlanMapper planMapper; @Resource - private HealthMedicationRecordMapper recordMapper; + private MedicationTaskMapper taskMapper; /** * 每日生成服药任务 * 定时任务配置:每日 00:05 执行 - * 调用方式:medicationTaskJob.generateDailyTasks */ public void generateDailyTasks() { log.info("========== 开始生成每日服药任务 =========="); @@ -54,47 +51,39 @@ public class MedicationTaskJob { /** * 生成指定日期的服药任务 - * 可用于补生成历史任务 - * - * @param date 日期 - * @return 生成的记录数 */ public int generateTasksForDate(LocalDate date) { int generatedCount = 0; - // 查询所有进行中的计划 - List activePlans = planMapper.selectActivePlanList(); + // 查询所有执行中的计划 + List activePlans = planMapper.selectActiveList(); if (activePlans == null || activePlans.isEmpty()) { - log.info("没有进行中的用药计划"); + log.info("没有执行中的用药计划"); return 0; } - String dateStr = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); - - for (HealthMedicationPlanVo plan : activePlans) { + for (MedicationPlanVo plan : activePlans) { try { // 检查该计划当天是否需要服药 if (!shouldTakeMedicineOnDate(plan, date)) { - log.debug("计划 {} 在 {} 不需要服药", plan.getPlanName(), dateStr); continue; } - // 检查该计划当天是否已生成过记录 - int existCount = recordMapper.countByPlanAndDate(plan.getId(), dateStr); + // 检查是否已生成过任务 + int existCount = taskMapper.countByPlanAndDate(plan.getId(), date); if (existCount > 0) { - log.debug("计划 {} 在 {} 已有 {} 条记录,跳过", plan.getPlanName(), dateStr, existCount); continue; } - // 生成当天的服药记录 - List records = generateRecordsForPlan(plan, date); - if (!records.isEmpty()) { - recordMapper.batchInsertHealthMedicationRecord(records); - generatedCount += records.size(); - log.info("计划 {} 在 {} 生成了 {} 条服药记录", plan.getPlanName(), dateStr, records.size()); + // 生成任务 + List tasks = generateTasksForPlan(plan, date); + if (!tasks.isEmpty()) { + taskMapper.batchInsert(tasks); + generatedCount += tasks.size(); + log.info("计划 {} 在 {} 生成了 {} 条任务", plan.getPlanName(), date, tasks.size()); } } catch (Exception e) { - log.error("生成计划 {} 的服药记录失败: {}", plan.getId(), e.getMessage(), e); + log.error("生成计划 {} 的任务失败: {}", plan.getId(), e.getMessage(), e); } } @@ -103,39 +92,30 @@ public class MedicationTaskJob { /** * 判断某计划在指定日期是否需要服药 - * - * @param plan 用药计划 - * @param date 日期 - * @return true-需要服药,false-不需要 */ - private boolean shouldTakeMedicineOnDate(HealthMedicationPlanVo plan, LocalDate date) { - // 检查是否在计划日期范围内 - LocalDate startDate = plan.getStartDate() != null ? - plan.getStartDate().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate() : null; - LocalDate endDate = plan.getEndDate() != null ? - plan.getEndDate().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate() : null; - - if (startDate != null && date.isBefore(startDate)) { + private boolean shouldTakeMedicineOnDate(MedicationPlanVo plan, LocalDate date) { + // 检查日期范围 + if (plan.getStartDate() != null && date.isBefore(plan.getStartDate())) { return false; } - if (endDate != null && date.isAfter(endDate)) { + if (plan.getEndDate() != null && date.isAfter(plan.getEndDate())) { return false; } - // 根据频率类型判断 - String frequencyType = plan.getFrequencyType(); + // 根据频次类型判断 + Integer frequencyType = plan.getFrequencyType(); if (frequencyType == null) { - frequencyType = "1"; // 默认每日 + frequencyType = 1; } switch (frequencyType) { - case "1": // 每日 + case 1: // 每天 return true; - case "2": // 隔日 - return shouldTakeOnAlternateDay(plan, date); - case "3": // 每周 + case 2: // 每周 return shouldTakeOnWeekly(plan, date); - case "4": // 自定义 + case 3: // 隔天 + return shouldTakeOnAlternate(plan, date); + case 4: // 自定义 return shouldTakeOnCustom(plan, date); default: return true; @@ -143,191 +123,130 @@ public class MedicationTaskJob { } /** - * 判断隔日服药 + * 每周服药判断 */ - private boolean shouldTakeOnAlternateDay(HealthMedicationPlanVo plan, LocalDate date) { - LocalDate startDate = plan.getStartDate() != null ? - plan.getStartDate().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate() : date; - long daysBetween = ChronoUnit.DAYS.between(startDate, date); - return daysBetween % 2 == 0; - } - - /** - * 判断每周服药 - */ - private boolean shouldTakeOnWeekly(HealthMedicationPlanVo plan, LocalDate date) { - String weekDays = plan.getWeekDays(); - if (weekDays == null || weekDays.isEmpty()) { + private boolean shouldTakeOnWeekly(MedicationPlanVo plan, LocalDate date) { + JsonNode config = plan.getFrequencyConfig(); + if (config == null || !config.has("days")) { return true; } - try { - // weekDays 格式为 JSON 数组,如 [1,3,5] 表示周一三五 - JSONArray daysArray = JSON.parseArray(weekDays); - DayOfWeek dayOfWeek = date.getDayOfWeek(); - int dayValue = dayOfWeek.getValue(); // 1=周一, 7=周日 + JsonNode daysNode = config.get("days"); + if (!daysNode.isArray()) { + return true; + } - for (int i = 0; i < daysArray.size(); i++) { - if (daysArray.getInteger(i) == dayValue) { - return true; - } + DayOfWeek dayOfWeek = date.getDayOfWeek(); + int dayValue = dayOfWeek.getValue(); // 1=周一, 7=周日 + + for (JsonNode day : daysNode) { + if (day.asInt() == dayValue) { + return true; } - return false; - } catch (Exception e) { - log.error("解析周几配置失败: {}", weekDays, e); - return true; } + return false; } /** - * 判断自定义频率服药 - * 暂时默认返回 true,后续可根据具体需求扩展 + * 隔天服药判断 */ - private boolean shouldTakeOnCustom(HealthMedicationPlanVo plan, LocalDate date) { - // 自定义频率可以根据 remark 或其他字段配置 - // 暂时默认每日都服药 + private boolean shouldTakeOnAlternate(MedicationPlanVo plan, LocalDate date) { + LocalDate startDate = plan.getStartDate(); + if (startDate == null) { + startDate = date; + } + + JsonNode config = plan.getFrequencyConfig(); + int intervalDays = 2; // 默认隔天 + if (config != null && config.has("interval_days")) { + intervalDays = config.get("interval_days").asInt(2); + } + + long daysBetween = ChronoUnit.DAYS.between(startDate, date); + return daysBetween % intervalDays == 0; + } + + /** + * 自定义频次判断 + */ + private boolean shouldTakeOnCustom(MedicationPlanVo plan, LocalDate date) { + // 自定义频次,暂时默认返回 true return true; } /** - * 为某个计划生成指定日期的服药记录 - * - * @param plan 用药计划 - * @param date 日期 - * @return 服药记录列表 + * 为某个计划生成指定日期的任务 */ - private List generateRecordsForPlan(HealthMedicationPlanVo plan, LocalDate date) { - List records = new ArrayList<>(); + private List generateTasksForPlan(MedicationPlanVo plan, LocalDate date) { + List tasks = new ArrayList<>(); - // 获取服药时间点 - String timePoints = plan.getTimePoints(); - if (timePoints == null || timePoints.isEmpty()) { - // 如果没有配置时间点,根据频率生成默认时间点 - timePoints = generateDefaultTimePoints(plan.getFrequency()); + JsonNode timeSlots = plan.getTimeSlots(); + if (timeSlots == null || !timeSlots.isArray()) { + // 如果没有配置时段,使用默认时段 + timeSlots = createDefaultTimeSlots(plan); } - try { - JSONArray timePointsArray = JSON.parseArray(timePoints); - LocalDateTime now = LocalDateTime.now(); - - for (int i = 0; i < timePointsArray.size(); i++) { - String timeStr = timePointsArray.getString(i); - LocalTime time = parseTime(timeStr); - - HealthMedicationRecord record = new HealthMedicationRecord(); - record.setId(IdWorker.getId()); - record.setPlanId(plan.getId()); - record.setPersonId(plan.getPersonId()); - record.setMedicineId(plan.getMedicineId()); - record.setScheduledTime(LocalDateTime.of(date, time)); - record.setDosage(plan.getDosage()); - record.setDosageUnit(plan.getDosageUnit()); - record.setStatus("1"); // 待服用 - record.setCreateTime(now); - record.setDelFlag("0"); - - records.add(record); + for (JsonNode slot : timeSlots) { + if (!slot.has("enabled") || !slot.get("enabled").asBoolean(true)) { + continue; } - } catch (Exception e) { - log.error("解析时间点配置失败: {}", timePoints, e); + + String timeStr = slot.has("time") ? slot.get("time").asText() : "08:00"; + LocalTime time = parseTime(timeStr); + + BigDecimal dosage = plan.getDosagePerTime(); + if (slot.has("dosage")) { + dosage = new BigDecimal(slot.get("dosage").asText()); + } + + MedicationTask task = new MedicationTask(); + task.setPlanId(plan.getId()); + task.setMemberId(plan.getMemberId()); + task.setMedicineName(plan.getMedicineName()); + task.setPlannedDate(date); + task.setPlannedTime(time); + task.setPlannedDosage(dosage); + task.setStatus(0); // 待服药 + task.setRemindStatus(0); // 未提醒 + task.setCreateTime(DateUtils.getNowDate()); + + tasks.add(task); } - return records; + return tasks; } /** - * 根据每日次数生成默认时间点 - * - * @param frequency 每日次数 - * @return JSON 格式的时间点数组 + * 创建默认时段配置 */ - private String generateDefaultTimePoints(Integer frequency) { - if (frequency == null || frequency <= 0) { - frequency = 1; + private JsonNode createDefaultTimeSlots(MedicationPlanVo plan) { + // 根据剂量单位推测服药时段 + String json = "[{\"slot_name\":\"早\",\"time\":\"08:00\",\"dosage\":1,\"enabled\":true}]"; + try { + return new com.fasterxml.jackson.databind.ObjectMapper().readTree(json); + } catch (Exception e) { + return null; } - - JSONArray timePoints = new JSONArray(); - switch (frequency) { - case 1: - timePoints.add("08:00"); - break; - case 2: - timePoints.add("08:00"); - timePoints.add("20:00"); - break; - case 3: - timePoints.add("08:00"); - timePoints.add("12:00"); - timePoints.add("20:00"); - break; - case 4: - timePoints.add("08:00"); - timePoints.add("12:00"); - timePoints.add("16:00"); - timePoints.add("20:00"); - break; - default: - // 超过4次,均匀分布在 8:00-22:00 之间 - int startHour = 8; - int endHour = 22; - int interval = (endHour - startHour) / frequency; - for (int i = 0; i < frequency; i++) { - int hour = startHour + i * interval; - timePoints.add(String.format("%02d:00", hour)); - } - } - - return timePoints.toJSONString(); } /** * 解析时间字符串 - * - * @param timeStr 时间字符串,格式如 "08:00" 或 "8:00" - * @return LocalTime */ private LocalTime parseTime(String timeStr) { try { - // 支持多种格式 - String normalized = timeStr.trim(); - if (normalized.length() == 4 && !normalized.contains(":")) { - // "0800" -> "08:00" - normalized = normalized.substring(0, 2) + ":" + normalized.substring(2); - } - - String[] parts = normalized.split(":"); - int hour = Integer.parseInt(parts[0]); - int minute = parts.length > 1 ? Integer.parseInt(parts[1]) : 0; - return LocalTime.of(hour, minute); + return LocalTime.parse(timeStr, DateTimeFormatter.ofPattern("HH:mm")); } catch (Exception e) { - log.warn("解析时间失败: {},使用默认时间 08:00", timeStr); return LocalTime.of(8, 0); } } /** - * 检查并标记过期的服药记录 - * 定时任务配置:每5分钟执行 - * 调用方式:medicationTaskJob.markExpiredRecords + * 标记过期任务 */ public void markExpiredRecords() { - log.info("========== 开始检查过期服药记录 =========="); - LocalDateTime now = LocalDateTime.now(); - // 超过计划时间24小时的记录标记为过期 - LocalDateTime expireThreshold = now.minusHours(24); - - int count = recordMapper.markExpiredRecords(expireThreshold); - log.info("========== 标记过期记录完成,共 {} 条 ==========", count); - } - - /** - * 手动触发生成指定日期的任务(用于测试或补录) - * - * @param dateStr 日期字符串,格式 yyyy-MM-dd - * @return 生成的记录数 - */ - public int generateTasksManually(String dateStr) { - LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd")); - return generateTasksForDate(date); + log.info("========== 开始标记过期服药任务 =========="); + LocalDateTime expireThreshold = LocalDateTime.now().minusHours(24); + int count = taskMapper.markExpired(expireThreshold); + log.info("========== 标记过期任务完成,共 {} 条 ==========", count); } } \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/resources/mapper/health/HealthMedicationPlanMapper.xml b/intc-modules/intc-health/src/main/resources/mapper/health/HealthMedicationPlanMapper.xml deleted file mode 100644 index ed091c4..0000000 --- a/intc-modules/intc-health/src/main/resources/mapper/health/HealthMedicationPlanMapper.xml +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select - a.id, - a.person_id, - p.name as person_name, - a.medicine_id, - m.name as medicine_name, - m.short_name, - m.brand, - m.packaging, - a.stock_in_id, - a.plan_name, - a.dosage, - a.dosage_unit, - a.frequency, - a.frequency_type, - a.time_points, - a.week_days, - a.start_date, - a.end_date, - a.reminder_enabled, - a.reminder_minutes, - a.status, - a.remark, - a.create_time - from - health_medication_plan a - left join health_person p on a.person_id = p.id - left join health_medicine_basic m on a.medicine_id = m.id - - - - - - - - - - insert into health_medication_plan - - id, - person_id, - medicine_id, - stock_in_id, - plan_name, - dosage, - dosage_unit, - frequency, - frequency_type, - time_points, - week_days, - start_date, - end_date, - reminder_enabled, - reminder_minutes, - status, - create_by, - create_time, - del_flag, - remark, - - - #{id}, - #{personId}, - #{medicineId}, - #{stockInId}, - #{planName}, - #{dosage}, - #{dosageUnit}, - #{frequency}, - #{frequencyType}, - #{timePoints}, - #{weekDays}, - #{startDate}, - #{endDate}, - #{reminderEnabled}, - #{reminderMinutes}, - #{status}, - #{createBy}, - #{createTime}, - #{delFlag}, - #{remark}, - - - - - update health_medication_plan - - person_id = #{personId}, - medicine_id = #{medicineId}, - stock_in_id = #{stockInId}, - plan_name = #{planName}, - dosage = #{dosage}, - dosage_unit = #{dosageUnit}, - frequency = #{frequency}, - frequency_type = #{frequencyType}, - time_points = #{timePoints}, - week_days = #{weekDays}, - start_date = #{startDate}, - end_date = #{endDate}, - reminder_enabled = #{reminderEnabled}, - reminder_minutes = #{reminderMinutes}, - status = #{status}, - update_by = #{updateBy}, - update_time = #{updateTime}, - del_flag = #{delFlag}, - remark = #{remark}, - - where id = #{id} - - - - delete from health_medication_plan where id = #{id} - - - - delete from health_medication_plan where id in - - #{id} - - - - - update health_medication_plan set del_flag='1' where id = #{id} - - - - update health_medication_plan set del_flag='1' where id in - - #{id} - - - \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/resources/mapper/health/HealthMedicationRecordMapper.xml b/intc-modules/intc-health/src/main/resources/mapper/health/HealthMedicationRecordMapper.xml deleted file mode 100644 index bdc58a9..0000000 --- a/intc-modules/intc-health/src/main/resources/mapper/health/HealthMedicationRecordMapper.xml +++ /dev/null @@ -1,310 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - select - a.id, - a.plan_id, - a.person_id, - p.name as person_name, - a.medicine_id, - m.name as medicine_name, - m.short_name, - m.brand, - m.packaging, - a.scheduled_time, - a.actual_time, - a.dosage, - a.dosage_unit, - a.status, - a.remark, - a.create_time, - pl.plan_name - from - health_medication_record a - left join health_person p on a.person_id = p.id - left join health_medicine_basic m on a.medicine_id = m.id - left join health_medication_plan pl on a.plan_id = pl.id - - - - - - - - - - - - insert into health_medication_record - - id, - plan_id, - person_id, - medicine_id, - scheduled_time, - actual_time, - dosage, - dosage_unit, - status, - create_by, - create_time, - del_flag, - remark, - - - #{id}, - #{planId}, - #{personId}, - #{medicineId}, - #{scheduledTime}, - #{actualTime}, - #{dosage}, - #{dosageUnit}, - #{status}, - #{createBy}, - #{createTime}, - #{delFlag}, - #{remark}, - - - - - insert into health_medication_record (id, plan_id, person_id, medicine_id, scheduled_time, dosage, dosage_unit, status, create_time, del_flag) - values - - (#{item.id}, #{item.planId}, #{item.personId}, #{item.medicineId}, #{item.scheduledTime}, #{item.dosage}, #{item.dosageUnit}, #{item.status}, #{item.createTime}, '0') - - - - - update health_medication_record - - plan_id = #{planId}, - person_id = #{personId}, - medicine_id = #{medicineId}, - scheduled_time = #{scheduledTime}, - actual_time = #{actualTime}, - dosage = #{dosage}, - dosage_unit = #{dosageUnit}, - status = #{status}, - update_by = #{updateBy}, - update_time = #{updateTime}, - del_flag = #{delFlag}, - remark = #{remark}, - - where id = #{id} - - - - delete from health_medication_record where id = #{id} - - - - delete from health_medication_record where id in - - #{id} - - - - - update health_medication_record set del_flag='1' where id = #{id} - - - - update health_medication_record set del_flag='1' where id in - - #{id} - - - - - - - update health_medication_record - set status = '4', update_time = current_timestamp - where del_flag='0' and status = '1' - and scheduled_time < #{expireThreshold} - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/resources/mapper/health/MedicationPlanMapper.xml b/intc-modules/intc-health/src/main/resources/mapper/health/MedicationPlanMapper.xml new file mode 100644 index 0000000..2b194af --- /dev/null +++ b/intc-modules/intc-health/src/main/resources/mapper/health/MedicationPlanMapper.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select a.id, a.member_id, p.name as member_name, a.chronic_disease_id, + c.disease_name as chronic_disease_name, a.plan_name, a.medicine_id, + a.medicine_name, a.specification, a.dosage_per_time, a.dosage_unit, + a.frequency_type, a.frequency_config, a.time_slots, a.start_date, a.end_date, + a.remind_enabled, a.remind_advance_min, a.notify_family, a.family_member_ids, + a.status, a.create_time + from medication_plan a + left join health_person p on a.member_id = p.id + left join chronic_disease_record c on a.chronic_disease_id = c.id + + + + + + + + + + insert into medication_plan ( + member_id, chronic_disease_id, plan_name, medicine_id, medicine_name, + specification, dosage_per_time, dosage_unit, frequency_type, + frequency_config, time_slots, start_date, end_date, + remind_enabled, remind_advance_min, notify_family, family_member_ids, status, + create_by, create_time, remark, del_flag + ) values ( + #{memberId}, #{chronicDiseaseId}, #{planName}, #{medicineId}, #{medicineName}, + #{specification}, #{dosagePerTime}, #{dosageUnit}, #{frequencyType}, + #{frequencyConfig, typeHandler=com.intc.common.core.handler.JsonNodeTypeHandler}, + #{timeSlots, typeHandler=com.intc.common.core.handler.JsonNodeTypeHandler}, + #{startDate}, #{endDate}, + #{remindEnabled}, #{remindAdvanceMin}, #{notifyFamily}, + #{familyMemberIds, typeHandler=com.intc.common.core.handler.JsonNodeTypeHandler}, + #{status}, + #{createBy}, #{createTime}, #{remark}, 0 + ) + + + + update medication_plan + + member_id = #{memberId}, + chronic_disease_id = #{chronicDiseaseId}, + plan_name = #{planName}, + medicine_id = #{medicineId}, + medicine_name = #{medicineName}, + specification = #{specification}, + dosage_per_time = #{dosagePerTime}, + dosage_unit = #{dosageUnit}, + frequency_type = #{frequencyType}, + frequency_config = #{frequencyConfig, typeHandler=com.intc.common.core.handler.JsonNodeTypeHandler}, + time_slots = #{timeSlots, typeHandler=com.intc.common.core.handler.JsonNodeTypeHandler}, + start_date = #{startDate}, + end_date = #{endDate}, + remind_enabled = #{remindEnabled}, + remind_advance_min = #{remindAdvanceMin}, + notify_family = #{notifyFamily}, + family_member_ids = #{familyMemberIds, typeHandler=com.intc.common.core.handler.JsonNodeTypeHandler}, + status = #{status}, + update_by = #{updateBy}, + update_time = #{updateTime}, + remark = #{remark}, + + where id = #{id} + + + + delete from medication_plan where id = #{id} + + + + delete from medication_plan where id in + #{id} + + + + update medication_plan set del_flag = 1 where id = #{id} + + + + update medication_plan set del_flag = 1 where id in + #{id} + + \ No newline at end of file diff --git a/intc-modules/intc-health/src/main/resources/mapper/health/MedicationTaskMapper.xml b/intc-modules/intc-health/src/main/resources/mapper/health/MedicationTaskMapper.xml new file mode 100644 index 0000000..2d221e6 --- /dev/null +++ b/intc-modules/intc-health/src/main/resources/mapper/health/MedicationTaskMapper.xml @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + select a.id, a.plan_id, p.plan_name, a.member_id, m.name as member_name, + a.medicine_name, a.planned_date, a.planned_time, a.planned_dosage, + a.actual_time, a.actual_dosage, a.status, a.confirm_type, a.notes, + a.remind_status, a.remind_time, a.create_time + from medication_task a + left join medication_plan p on a.plan_id = p.id + left join health_person m on a.member_id = m.id + + + + + + + + insert into medication_task ( + plan_id, member_id, medicine_name, planned_date, planned_time, + planned_dosage, actual_time, actual_dosage, status, confirm_type, + notes, remind_status, remind_time, create_by, create_time, remark, del_flag + ) values ( + #{planId}, #{memberId}, #{medicineName}, #{plannedDate}, #{plannedTime}, + #{plannedDosage}, #{actualTime}, #{actualDosage}, #{status}, #{confirmType}, + #{notes}, #{remindStatus}, #{remindTime}, #{createBy}, #{createTime}, #{remark}, 0 + ) + + + + insert into medication_task ( + plan_id, member_id, medicine_name, planned_date, planned_time, + planned_dosage, status, remind_status, create_time, del_flag + ) values + + (#{item.planId}, #{item.memberId}, #{item.medicineName}, #{item.plannedDate}, #{item.plannedTime}, + #{item.plannedDosage}, #{item.status}, #{item.remindStatus}, #{item.createTime}, 0) + + + + + update medication_task + + actual_time = #{actualTime}, + actual_dosage = #{actualDosage}, + status = #{status}, + confirm_type = #{confirmType}, + notes = #{notes}, + remind_status = #{remindStatus}, + remind_time = #{remindTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + remark = #{remark}, + + where id = #{id} + + + + delete from medication_task where id = #{id} + + + + delete from medication_task where id in + #{id} + + + + update medication_task set del_flag = 1 where id = #{id} + + + + update medication_task set del_flag = 1 where id in + #{id} + + + + + + + + update medication_task + set status = 2, update_time = current_timestamp + where del_flag = 0 and status = 0 + and (planned_date || ' ' || planned_time)::timestamp < #{expireThreshold} + + + + + + + + + + + + \ No newline at end of file diff --git a/sql/20250319-medication-adherence.sql b/sql/20250319-medication-adherence.sql deleted file mode 100644 index ff539f4..0000000 --- a/sql/20250319-medication-adherence.sql +++ /dev/null @@ -1,53 +0,0 @@ --- ======================================== --- 依从性统计功能 - SQL脚本 --- ======================================== - --- 用药统计菜单 -INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES ( - nextval('seq_sys_menu'), - '用药统计', - (SELECT menu_id FROM sys_menu WHERE menu_name = '健康管理' LIMIT 1), - 12, - 'medicationStatistic', - 'health/medicationStatistic/index', - NULL, - 1, - 0, - 'C', - '0', - '0', - 'health:medicationStatistic:query', - 'chart', - 'admin', - NOW(), - '用药统计菜单' -); - --- 用药统计按钮权限 -INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -SELECT nextval('seq_sys_menu'), '用药统计查询', m.menu_id, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationStatistic:query', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationStatistic:query'; - --- ======================================== --- 添加依从性统计汇总表(可选,用于预计算性能优化) --- ======================================== -DROP TABLE IF EXISTS health_medication_adherence_stats; -CREATE TABLE health_medication_adherence_stats ( - id BIGINT NOT NULL, - person_id BIGINT NOT NULL, - plan_id BIGINT NULL, - stat_date DATE NOT NULL, - total_tasks INT DEFAULT 0, - completed_tasks INT DEFAULT 0, - missed_tasks INT DEFAULT 0, - skipped_tasks INT DEFAULT 0, - ontime_tasks INT DEFAULT 0, - adherence_rate DECIMAL(5,2) DEFAULT 0.00, - ontime_rate DECIMAL(5,2) DEFAULT 0.00, - create_time DATETIME DEFAULT CURRENT_TIMESTAMP, - update_time DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE=InnoDB COMMENT='依从性统计汇总表'; - -CREATE UNIQUE INDEX idx_hmas_person_date ON health_medication_adherence_stats(person_id, stat_date, plan_id); -CREATE INDEX idx_hmas_stat_date ON health_medication_adherence_stats(stat_date); \ No newline at end of file diff --git a/sql/20250319-medication-task-job.sql b/sql/20250319-medication-task-job.sql deleted file mode 100644 index f04ccb9..0000000 --- a/sql/20250319-medication-task-job.sql +++ /dev/null @@ -1,90 +0,0 @@ --- ======================================== --- 用药任务定时任务配置 --- 在 sys_job 表中插入定时任务 --- ======================================== - --- 1. 每日生成服药任务(每日 00:05 执行) -INSERT INTO sys_job (job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark) -VALUES ( - nextval('seq_sys_job'), - '每日生成服药任务', - 'DEFAULT', - 'medicationTaskJob.generateDailyTasks', - '0 5 0 * * ?', - '2', - '1', - '0', - 'admin', - NOW(), - '每日凌晨00:05自动生成当天的服药任务' -); - --- 2. 扫描并发送服药提醒(每分钟执行) -INSERT INTO sys_job (job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark) -VALUES ( - nextval('seq_sys_job'), - '扫描服药提醒', - 'DEFAULT', - 'medicationRemindJob.scanAndSendReminders', - '0 * * * * ?', - '2', - '1', - '0', - 'admin', - NOW(), - '每分钟扫描待提醒的服药任务并发送提醒' -); - --- 3. 扫描超时未服药记录(每5分钟执行) -INSERT INTO sys_job (job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark) -VALUES ( - nextval('seq_sys_job'), - '扫描超时未服药', - 'DEFAULT', - 'medicationRemindJob.scanOverdueRecords', - '0 */5 * * * ?', - '2', - '1', - '0', - 'admin', - NOW(), - '每5分钟扫描超时未服药的记录并发送提醒' -); - --- 4. 标记过期服药记录(每小时执行) -INSERT INTO sys_job (job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark) -VALUES ( - nextval('seq_sys_job'), - '标记过期服药记录', - 'DEFAULT', - 'medicationTaskJob.markExpiredRecords', - '0 0 * * * ?', - '2', - '1', - '0', - 'admin', - NOW(), - '每小时检查并标记过期的服药记录' -); - --- ======================================== --- 提醒日志表(可选,用于记录提醒历史) --- ======================================== -DROP TABLE IF EXISTS health_medication_remind_log; -CREATE TABLE health_medication_remind_log ( - id BIGINT NOT NULL, - record_id BIGINT NOT NULL, - plan_id BIGINT NOT NULL, - person_id BIGINT NOT NULL, - remind_type CHAR(1) DEFAULT '1' COMMENT '提醒类型:1-按时提醒 2-超时提醒 3-漏服通知家属', - remind_time DATETIME NOT NULL, - remind_channel VARCHAR(20) DEFAULT 'app' COMMENT '提醒渠道:app/sms/wechat', - remind_result CHAR(1) DEFAULT '1' COMMENT '结果:1-成功 2-失败', - error_msg VARCHAR(500) NULL, - create_time DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE=InnoDB COMMENT='用药提醒日志表'; - -CREATE INDEX idx_rmrl_record_id ON health_medication_remind_log(record_id); -CREATE INDEX idx_rmrl_person_id ON health_medication_remind_log(person_id); -CREATE INDEX idx_rmrl_remind_time ON health_medication_remind_log(remind_time); \ No newline at end of file diff --git a/sql/chronic_disease_record.sql b/sql/chronic_disease_record.sql deleted file mode 100644 index 03eed8f..0000000 --- a/sql/chronic_disease_record.sql +++ /dev/null @@ -1,105 +0,0 @@ --- ======================================== --- 慢性疾病档案表 --- ======================================== -DROP TABLE IF EXISTS chronic_disease_record; -CREATE TABLE chronic_disease_record ( - id BIGSERIAL PRIMARY KEY, - member_id BIGINT NOT NULL, - disease_id BIGINT, - disease_name VARCHAR(100) NOT NULL, - disease_code VARCHAR(20), - diagnosis_date DATE, - disease_status SMALLINT NOT NULL DEFAULT 1, - main_doctor VARCHAR(50), - hospital VARCHAR(100), - department VARCHAR(50), - notes TEXT, - is_active SMALLINT DEFAULT 1, - -- 若依标准字段 - create_by VARCHAR(64) DEFAULT '', - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_by VARCHAR(64) DEFAULT '', - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - remark VARCHAR(500) DEFAULT '', - del_flag SMALLINT DEFAULT 0 -); - -COMMENT ON TABLE chronic_disease_record IS '慢性疾病档案表'; -COMMENT ON COLUMN chronic_disease_record.id IS '主键ID'; -COMMENT ON COLUMN chronic_disease_record.member_id IS '关联成员ID'; -COMMENT ON COLUMN chronic_disease_record.disease_id IS '关联疾病ID(关联health_diseases表)'; -COMMENT ON COLUMN chronic_disease_record.disease_name IS '疾病名称(高血压/糖尿病/冠心病等)'; -COMMENT ON COLUMN chronic_disease_record.disease_code IS '疾病编码(ICD-10标准)'; -COMMENT ON COLUMN chronic_disease_record.diagnosis_date IS '确诊日期'; -COMMENT ON COLUMN chronic_disease_record.disease_status IS '状态:1-稳定 2-需关注 3-急性期'; -COMMENT ON COLUMN chronic_disease_record.main_doctor IS '主治医生'; -COMMENT ON COLUMN chronic_disease_record.hospital IS '就诊医院'; -COMMENT ON COLUMN chronic_disease_record.department IS '科室'; -COMMENT ON COLUMN chronic_disease_record.notes IS '备注说明'; -COMMENT ON COLUMN chronic_disease_record.is_active IS '是否启用:1-是 0-否'; -COMMENT ON COLUMN chronic_disease_record.create_by IS '创建者'; -COMMENT ON COLUMN chronic_disease_record.create_time IS '创建时间'; -COMMENT ON COLUMN chronic_disease_record.update_by IS '更新者'; -COMMENT ON COLUMN chronic_disease_record.update_time IS '更新时间'; -COMMENT ON COLUMN chronic_disease_record.remark IS '备注'; -COMMENT ON COLUMN chronic_disease_record.del_flag IS '删除标记:0-正常 1-删除'; - -CREATE INDEX idx_cdr_member_id ON chronic_disease_record(member_id); -CREATE INDEX idx_cdr_disease_id ON chronic_disease_record(disease_id); -CREATE INDEX idx_cdr_disease_status ON chronic_disease_record(disease_status); -CREATE INDEX idx_cdr_is_active ON chronic_disease_record(is_active); - --- ======================================== --- 菜单 SQL(若依框架标准格式) --- ======================================== --- 慢性疾病档案菜单 -INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES ('慢性疾病档案', 0, 5, 'chronicDisease', 'health/chronicDisease/index', 1, 0, 'C', '0', '0', 'health:chronicDisease:list', '#', 'admin', NOW(), '慢性疾病档案菜单'); - --- 获取刚插入的菜单ID -SELECT @parentId := LAST_INSERT_ID(); - --- 按钮权限 -INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES ('慢性疾病档案查询', @parentId, 1, '#', '', 1, 0, 'F', '0', '0', 'health:chronicDisease:query', '#', 'admin', NOW(), ''); - -INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES ('慢性疾病档案权增', @parentId, 2, '#', '', 1, 0, 'F', '0', '0', 'health:chronicDisease:add', '#', 'admin', NOW(), ''); - -INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES ('慢性疾病档案修改', @parentId, 3, '#', '', 1, 0, 'F', '0', '0', 'health:chronicDisease:edit', '#', 'admin', NOW(), ''); - -INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES ('慢性疾病档案删除', @parentId, 4, '#', '', 1, 0, 'F', '0', '0', 'health:chronicDisease:remove', '#', 'admin', NOW(), ''); - -INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES ('慢性疾病档案导出', @parentId, 5, '#', '', 1, 0, 'F', '0', '0', 'health:chronicDisease:export', '#', 'admin', NOW(), ''); - --- ======================================== --- 字典数据 --- ======================================== --- 疾病状态字典 -INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) -VALUES ('疾病状态', 'disease_status', '0', 'admin', NOW(), '慢性疾病状态'); - -INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) -VALUES (1, '稳定', '1', 'disease_status', '', 'success', 'Y', '0', 'admin', NOW(), '疾病状态-稳定'); - -INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) -VALUES (2, '需关注', '2', 'disease_status', '', 'warning', 'N', '0', 'admin', NOW(), '疾病状态-需关注'); - -INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) -VALUES (3, '急性期', '3', 'disease_status', '', 'danger', 'N', '0', 'admin', NOW(), '疾病状态-急性期'); - --- 是否启用字典(如果不存在) -INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) -VALUES ('是否启用', 'is_active', '0', 'admin', NOW(), '是否启用状态') -ON CONFLICT (dict_type) DO NOTHING; - -INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) -VALUES (1, '是', '1', 'is_active', '', 'success', 'Y', '0', 'admin', NOW(), '启用') -ON CONFLICT DO NOTHING; - -INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) -VALUES (2, '否', '0', 'is_active', '', 'danger', 'N', '0', 'admin', NOW(), '停用') -ON CONFLICT DO NOTHING; \ No newline at end of file diff --git a/sql/medication.sql b/sql/medication.sql deleted file mode 100644 index 896f87c..0000000 --- a/sql/medication.sql +++ /dev/null @@ -1,128 +0,0 @@ --- ---------------------------- --- 用药计划表 --- ---------------------------- -DROP TABLE IF EXISTS health_medication_plan; -CREATE TABLE health_medication_plan ( - id BIGINT NOT NULL, - person_id BIGINT NOT NULL, - medicine_id BIGINT NOT NULL, - stock_in_id BIGINT NULL, - plan_name VARCHAR(200) NULL, - dosage DECIMAL(10,2) NOT NULL, - dosage_unit VARCHAR(20) NULL, - frequency INT NOT NULL, - frequency_type CHAR(1) DEFAULT '1', - time_points VARCHAR(500) NULL, - week_days VARCHAR(50) NULL, - start_date DATE NOT NULL, - end_date DATE NULL, - reminder_enabled CHAR(1) DEFAULT '0', - reminder_minutes INT DEFAULT 15, - status CHAR(1) DEFAULT '1', - del_flag CHAR(1) DEFAULT '0', - create_by VARCHAR(64) DEFAULT '', - create_time DATETIME NULL, - update_by VARCHAR(64) DEFAULT '', - update_time DATETIME NULL, - remark VARCHAR(500) NULL, - PRIMARY KEY (id) -) ENGINE=InnoDB COMMENT='用药计划表'; - -CREATE INDEX idx_person_id ON health_medication_plan(person_id); -CREATE INDEX idx_medicine_id ON health_medication_plan(medicine_id); -CREATE INDEX idx_status ON health_medication_plan(status); -CREATE INDEX idx_start_date ON health_medication_plan(start_date); - --- ---------------------------- --- 用药记录表 --- ---------------------------- -DROP TABLE IF EXISTS health_medication_record; -CREATE TABLE health_medication_record ( - id BIGINT NOT NULL, - plan_id BIGINT NOT NULL, - person_id BIGINT NOT NULL, - medicine_id BIGINT NOT NULL, - scheduled_time DATETIME NOT NULL, - actual_time DATETIME NULL, - dosage DECIMAL(10,2) NULL, - dosage_unit VARCHAR(20) NULL, - status CHAR(1) DEFAULT '1', - del_flag CHAR(1) DEFAULT '0', - create_by VARCHAR(64) DEFAULT '', - create_time DATETIME NULL, - update_by VARCHAR(64) DEFAULT '', - update_time DATETIME NULL, - remark VARCHAR(500) NULL, - PRIMARY KEY (id) -) ENGINE=InnoDB COMMENT='用药记录表'; - -CREATE INDEX idx_plan_id ON health_medication_record(plan_id); -CREATE INDEX idx_person_id ON health_medication_record(person_id); -CREATE INDEX idx_scheduled_time ON health_medication_record(scheduled_time); -CREATE INDEX idx_status ON health_medication_record(status); - --- ---------------------------- --- 字典数据 --- ---------------------------- -INSERT INTO sys_dict_type (dict_id, dict_name, dict_type, status, create_by, create_time, remark) -VALUES -(nextval('seq_sys_dict_type'), '用药频率类型', 'medication_frequency_type', '0', 'admin', NOW(), '用药频率类型字典'), -(nextval('seq_sys_dict_type'), '用药计划状态', 'medication_plan_status', '0', 'admin', NOW(), '用药计划状态字典'), -(nextval('seq_sys_dict_type'), '用药记录状态', 'medication_record_status', '0', 'admin', NOW(), '用药记录状态字典'); - -INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) -VALUES -(nextval('seq_sys_dict_data'), 1, '每日', '1', 'medication_frequency_type', '', 'primary', 'Y', '0', 'admin', NOW(), NULL), -(nextval('seq_sys_dict_data'), 2, '隔日', '2', 'medication_frequency_type', '', 'success', 'N', '0', 'admin', NOW(), NULL), -(nextval('seq_sys_dict_data'), 3, '每周', '3', 'medication_frequency_type', '', 'info', 'N', '0', 'admin', NOW(), NULL), -(nextval('seq_sys_dict_data'), 4, '自定义', '4', 'medication_frequency_type', '', 'warning', 'N', '0', 'admin', NOW(), NULL); - -INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) -VALUES -(nextval('seq_sys_dict_data'), 1, '进行中', '1', 'medication_plan_status', '', 'primary', 'Y', '0', 'admin', NOW(), NULL), -(nextval('seq_sys_dict_data'), 2, '已结束', '2', 'medication_plan_status', '', 'info', 'N', '0', 'admin', NOW(), NULL), -(nextval('seq_sys_dict_data'), 3, '已暂停', '3', 'medication_plan_status', '', 'warning', 'N', '0', 'admin', NOW(), NULL); - -INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) -VALUES -(nextval('seq_sys_dict_data'), 1, '待服用', '1', 'medication_record_status', '', 'warning', 'Y', '0', 'admin', NOW(), NULL), -(nextval('seq_sys_dict_data'), 2, '已服用', '2', 'medication_record_status', '', 'success', 'N', '0', 'admin', NOW(), NULL), -(nextval('seq_sys_dict_data'), 3, '已跳过', '3', 'medication_record_status', '', 'info', 'N', '0', 'admin', NOW(), NULL), -(nextval('seq_sys_dict_data'), 4, '已过期', '4', 'medication_record_status', '', 'danger', 'N', '0', 'admin', NOW(), NULL); - --- ---------------------------- --- 菜单权限 --- ---------------------------- --- 用药计划菜单 -INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES -(nextval('seq_sys_menu'), '用药计划', (SELECT menu_id FROM sys_menu WHERE menu_name = '健康管理' LIMIT 1), 10, 'medicationPlan', 'health/medicationPlan/index', NULL, 1, 0, 'C', '0', '0', 'health:medicationPlan:list', 'calendar', 'admin', NOW(), '用药计划菜单'); - --- 用药计划按钮权限 -INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -SELECT nextval('seq_sys_menu'), '用药计划查询', m.menu_id, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:query', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list' -UNION ALL -SELECT nextval('seq_sys_menu'), '用药计划新增', m.menu_id, 2, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:add', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list' -UNION ALL -SELECT nextval('seq_sys_menu'), '用药计划修改', m.menu_id, 3, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:edit', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list' -UNION ALL -SELECT nextval('seq_sys_menu'), '用药计划删除', m.menu_id, 4, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:remove', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list' -UNION ALL -SELECT nextval('seq_sys_menu'), '用药计划导出', m.menu_id, 5, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:export', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list'; - --- 用药记录菜单 -INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -VALUES -(nextval('seq_sys_menu'), '用药记录', (SELECT menu_id FROM sys_menu WHERE menu_name = '健康管理' LIMIT 1), 11, 'medicationRecord', 'health/medicationRecord/index', NULL, 1, 0, 'C', '0', '0', 'health:medicationRecord:list', 'log', 'admin', NOW(), '用药记录菜单'); - --- 用药记录按钮权限 -INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) -SELECT nextval('seq_sys_menu'), '用药记录查询', m.menu_id, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationRecord:query', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationRecord:list' -UNION ALL -SELECT nextval('seq_sys_menu'), '用药记录新增', m.menu_id, 2, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationRecord:add', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationRecord:list' -UNION ALL -SELECT nextval('seq_sys_menu'), '用药记录修改', m.menu_id, 3, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationRecord:edit', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationRecord:list' -UNION ALL -SELECT nextval('seq_sys_menu'), '用药记录删除', m.menu_id, 4, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationRecord:remove', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationRecord:list' -UNION ALL -SELECT nextval('seq_sys_menu'), '用药记录导出', m.menu_id, 5, '', NULL, NULL, 1, 0, 'F', '0', '0', 'health:medicationRecord:export', '#', 'admin', NOW(), '' FROM sys_menu m WHERE m.perms = 'health:medicationRecord:list'; \ No newline at end of file diff --git a/sql/medication_job_pg.sql b/sql/medication_job_pg.sql new file mode 100644 index 0000000..44d7b56 --- /dev/null +++ b/sql/medication_job_pg.sql @@ -0,0 +1,64 @@ +-- ======================================== +-- 用药管理模块 - 定时任务配置 +-- PostgreSQL 版本 +-- ======================================== + +-- 1. 每日生成服药任务(每日 00:05 执行) +INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark) +VALUES ( + '每日生成服药任务', + 'DEFAULT', + 'medicationTaskJob.generateDailyTasks', + '0 5 0 * * ?', + '2', + '1', + '0', + 'admin', + NOW(), + '每日凌晨00:05自动生成当天的服药任务' +); + +-- 2. 扫描并发送服药提醒(每分钟执行) +INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark) +VALUES ( + '扫描服药提醒', + 'DEFAULT', + 'medicationRemindJob.scanAndSendReminders', + '0 * * * * ?', + '2', + '1', + '0', + 'admin', + NOW(), + '每分钟扫描待提醒的服药任务并发送提醒' +); + +-- 3. 扫描超时未服药记录(每5分钟执行) +INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark) +VALUES ( + '扫描超时未服药', + 'DEFAULT', + 'medicationRemindJob.scanOverdueRecords', + '0 */5 * * * ?', + '2', + '1', + '0', + 'admin', + NOW(), + '每5分钟扫描超时未服药的记录并发送提醒' +); + +-- 4. 标记过期服药记录(每小时执行) +INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark) +VALUES ( + '标记过期服药记录', + 'DEFAULT', + 'medicationTaskJob.markExpiredRecords', + '0 0 * * * ?', + '2', + '1', + '0', + 'admin', + NOW(), + '每小时检查并标记过期的服药记录' +); \ No newline at end of file diff --git a/sql/medication_menu_pg.sql b/sql/medication_menu_pg.sql new file mode 100644 index 0000000..3a49f92 --- /dev/null +++ b/sql/medication_menu_pg.sql @@ -0,0 +1,106 @@ +-- ======================================== +-- 用药管理模块 - 菜单权限配置 +-- PostgreSQL 版本 +-- ======================================== + +-- 用药计划菜单 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +SELECT '用药计划', menu_id, 10, 'medicationPlan', 'health/medicationPlan/index', 1, 0, 'C', '0', '0', 'health:medicationPlan:list', 'calendar', 'admin', NOW(), '用药计划菜单' +FROM sys_menu WHERE menu_name = '健康管理' LIMIT 1; + +-- 用药计划按钮权限 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +SELECT '用药计划查询', m.menu_id, 1, '', NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:query', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list' +UNION ALL +SELECT '用药计划新增', m.menu_id, 2, '', NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:add', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list' +UNION ALL +SELECT '用药计划修改', m.menu_id, 3, '', NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:edit', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list' +UNION ALL +SELECT '用药计划删除', m.menu_id, 4, '', NULL, 1, 0, 'F', '0', '0', 'health:medicationPlan:remove', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:medicationPlan:list'; + +-- 用药任务菜单 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +SELECT '用药任务', menu_id, 11, 'medicationTask', 'health/medicationTask/index', 1, 0, 'C', '0', '0', 'health:medicationTask:list', 'log', 'admin', NOW(), '用药任务菜单' +FROM sys_menu WHERE menu_name = '健康管理' LIMIT 1; + +-- 用药任务按钮权限 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +SELECT '用药任务查询', m.menu_id, 1, '', NULL, 1, 0, 'F', '0', '0', 'health:medicationTask:query', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:medicationTask:list' +UNION ALL +SELECT '用药任务修改', m.menu_id, 2, '', NULL, 1, 0, 'F', '0', '0', 'health:medicationTask:edit', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:medicationTask:list' +UNION ALL +SELECT '用药任务删除', m.menu_id, 3, '', NULL, 1, 0, 'F', '0', '0', 'health:medicationTask:remove', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:medicationTask:list'; + +-- 用药统计菜单 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +SELECT '用药统计', menu_id, 12, 'medicationStatistic', 'health/medicationStatistic/index', 1, 0, 'C', '0', '0', 'health:medicationStatistic:query', 'chart', 'admin', NOW(), '用药统计菜单' +FROM sys_menu WHERE menu_name = '健康管理' LIMIT 1; + +-- 慢性疾病档案菜单 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +SELECT '慢性疾病档案', menu_id, 9, 'chronicDisease', 'health/chronicDisease/index', 1, 0, 'C', '0', '0', 'health:chronicDisease:list', 'folder', 'admin', NOW(), '慢性疾病档案菜单' +FROM sys_menu WHERE menu_name = '健康管理' LIMIT 1; + +-- 慢性疾病档案按钮权限 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +SELECT '慢性疾病档案查询', m.menu_id, 1, '', NULL, 1, 0, 'F', '0', '0', 'health:chronicDisease:query', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:chronicDisease:list' +UNION ALL +SELECT '慢性疾病档案新增', m.menu_id, 2, '', NULL, 1, 0, 'F', '0', '0', 'health:chronicDisease:add', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:chronicDisease:list' +UNION ALL +SELECT '慢性疾病档案修改', m.menu_id, 3, '', NULL, 1, 0, 'F', '0', '0', 'health:chronicDisease:edit', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:chronicDisease:list' +UNION ALL +SELECT '慢性疾病档案删除', m.menu_id, 4, '', NULL, 1, 0, 'F', '0', '0', 'health:chronicDisease:remove', '#', 'admin', NOW(), '' +FROM sys_menu m WHERE m.perms = 'health:chronicDisease:list'; + +-- ======================================== +-- 字典类型 +-- ======================================== +INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) +VALUES +('用药频率类型', 'medication_frequency_type', '0', 'admin', NOW(), '用药频率类型字典'), +('用药计划状态', 'medication_plan_status', '0', 'admin', NOW(), '用药计划状态字典'), +('服药任务状态', 'medication_task_status', '0', 'admin', NOW(), '服药任务状态字典'), +('疾病状态', 'disease_status', '0', 'admin', NOW(), '疾病状态字典'); + +-- ======================================== +-- 字典数据 +-- ======================================== +-- 用药频率类型 +INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) +VALUES +(1, '每天', '1', 'medication_frequency_type', '', 'primary', 'Y', '0', 'admin', NOW()), +(2, '每周', '2', 'medication_frequency_type', '', 'success', 'N', '0', 'admin', NOW()), +(3, '隔天', '3', 'medication_frequency_type', '', 'info', 'N', '0', 'admin', NOW()), +(4, '自定义', '4', 'medication_frequency_type', '', 'warning', 'N', '0', 'admin', NOW()); + +-- 用药计划状态 +INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) +VALUES +(1, '执行中', '1', 'medication_plan_status', '', 'primary', 'Y', '0', 'admin', NOW()), +(2, '已暂停', '2', 'medication_plan_status', '', 'warning', 'N', '0', 'admin', NOW()), +(3, '已结束', '3', 'medication_plan_status', '', 'info', 'N', '0', 'admin', NOW()); + +-- 服药任务状态 +INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) +VALUES +(0, '待服药', '0', 'medication_task_status', '', 'warning', 'Y', '0', 'admin', NOW()), +(1, '已服药', '1', 'medication_task_status', '', 'success', 'N', '0', 'admin', NOW()), +(2, '漏服', '2', 'medication_task_status', '', 'danger', 'N', '0', 'admin', NOW()), +(3, '跳过', '3', 'medication_task_status', '', 'info', 'N', '0', 'admin', NOW()); + +-- 疾病状态 +INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) +VALUES +(1, '稳定', '1', 'disease_status', '', 'success', 'Y', '0', 'admin', NOW()), +(2, '需关注', '2', 'disease_status', '', 'warning', 'N', '0', 'admin', NOW()), +(3, '急性期', '3', 'disease_status', '', 'danger', 'N', '0', 'admin', NOW()); \ No newline at end of file diff --git a/sql/medication_module_pg.sql b/sql/medication_module_pg.sql new file mode 100644 index 0000000..28dfe74 --- /dev/null +++ b/sql/medication_module_pg.sql @@ -0,0 +1,293 @@ +-- ======================================== +-- 用药管理模块 - PostgreSQL 建表语句 +-- 依据:慢性病用药管理模块-功能规划文档 +-- ======================================== + +-- ======================================== +-- 1. 慢性疾病档案表 +-- ======================================== +DROP TABLE IF EXISTS chronic_disease_record; +CREATE TABLE chronic_disease_record ( + id BIGSERIAL PRIMARY KEY, + member_id BIGINT NOT NULL, + disease_name VARCHAR(100) NOT NULL, + disease_code VARCHAR(20), + diagnosis_date DATE, + disease_status SMALLINT NOT NULL DEFAULT 1, + main_doctor VARCHAR(50), + hospital VARCHAR(100), + department VARCHAR(50), + notes TEXT, + -- 若依标准字段 + create_by VARCHAR(64) DEFAULT '', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_by VARCHAR(64) DEFAULT '', + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + del_flag SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE chronic_disease_record IS '慢性疾病档案表'; +COMMENT ON COLUMN chronic_disease_record.id IS '主键ID'; +COMMENT ON COLUMN chronic_disease_record.member_id IS '关联成员ID'; +COMMENT ON COLUMN chronic_disease_record.disease_name IS '疾病名称(高血压/糖尿病/冠心病等)'; +COMMENT ON COLUMN chronic_disease_record.disease_code IS '疾病编码(ICD-10标准)'; +COMMENT ON COLUMN chronic_disease_record.diagnosis_date IS '确诊日期'; +COMMENT ON COLUMN chronic_disease_record.disease_status IS '状态:1-稳定 2-需关注 3-急性期'; +COMMENT ON COLUMN chronic_disease_record.main_doctor IS '主治医生'; +COMMENT ON COLUMN chronic_disease_record.hospital IS '就诊医院'; +COMMENT ON COLUMN chronic_disease_record.department IS '科室'; +COMMENT ON COLUMN chronic_disease_record.notes IS '备注说明'; +COMMENT ON COLUMN chronic_disease_record.create_by IS '创建者'; +COMMENT ON COLUMN chronic_disease_record.create_time IS '创建时间'; +COMMENT ON COLUMN chronic_disease_record.update_by IS '更新者'; +COMMENT ON COLUMN chronic_disease_record.update_time IS '更新时间'; +COMMENT ON COLUMN chronic_disease_record.remark IS '备注'; +COMMENT ON COLUMN chronic_disease_record.del_flag IS '删除标记:0-正常 1-删除'; + +CREATE INDEX idx_cdr_member_id ON chronic_disease_record(member_id); +CREATE INDEX idx_cdr_disease_status ON chronic_disease_record(disease_status); + +-- ======================================== +-- 2. 用药计划表 +-- ======================================== +DROP TABLE IF EXISTS medication_plan; +CREATE TABLE medication_plan ( + id BIGSERIAL PRIMARY KEY, + member_id BIGINT NOT NULL, + chronic_disease_id BIGINT, + plan_name VARCHAR(100) NOT NULL, + medicine_id BIGINT NOT NULL, + medicine_name VARCHAR(100) NOT NULL, + specification VARCHAR(50), + dosage_per_time DECIMAL(10,2) NOT NULL, + dosage_unit VARCHAR(20) NOT NULL, + frequency_type SMALLINT NOT NULL, + frequency_config JSONB NOT NULL, + time_slots JSONB NOT NULL, + start_date DATE NOT NULL, + end_date DATE, + remind_enabled SMALLINT NOT NULL DEFAULT 1, + remind_advance_min INTEGER, + notify_family SMALLINT DEFAULT 0, + family_member_ids JSONB, + status SMALLINT NOT NULL DEFAULT 1, + -- 若依标准字段 + create_by VARCHAR(64) DEFAULT '', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_by VARCHAR(64) DEFAULT '', + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + del_flag SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE medication_plan IS '用药计划表'; +COMMENT ON COLUMN medication_plan.id IS '主键ID'; +COMMENT ON COLUMN medication_plan.member_id IS '关联成员ID'; +COMMENT ON COLUMN medication_plan.chronic_disease_id IS '关联慢性疾病ID'; +COMMENT ON COLUMN medication_plan.plan_name IS '计划名称(如"降压药计划")'; +COMMENT ON COLUMN medication_plan.medicine_id IS '关联药品ID'; +COMMENT ON COLUMN medication_plan.medicine_name IS '药品名称(冗余字段)'; +COMMENT ON COLUMN medication_plan.specification IS '药品规格(如"10mg/片")'; +COMMENT ON COLUMN medication_plan.dosage_per_time IS '单次剂量'; +COMMENT ON COLUMN medication_plan.dosage_unit IS '剂量单位(片/粒/毫升/喷)'; +COMMENT ON COLUMN medication_plan.frequency_type IS '频次类型:1-每天 2-每周 3-隔天 4-自定义'; +COMMENT ON COLUMN medication_plan.frequency_config IS '频次配置(JSON格式)'; +COMMENT ON COLUMN medication_plan.time_slots IS '服药时段配置'; +COMMENT ON COLUMN medication_plan.start_date IS '开始日期'; +COMMENT ON COLUMN medication_plan.end_date IS '结束日期(空表示长期)'; +COMMENT ON COLUMN medication_plan.remind_enabled IS '是否开启提醒:1-是 0-否'; +COMMENT ON COLUMN medication_plan.remind_advance_min IS '提前提醒分钟数'; +COMMENT ON COLUMN medication_plan.notify_family IS '漏服是否通知家属:1-是 0-否'; +COMMENT ON COLUMN medication_plan.family_member_ids IS '通知家属成员ID列表'; +COMMENT ON COLUMN medication_plan.status IS '状态:1-执行中 2-已暂停 3-已结束'; +COMMENT ON COLUMN medication_plan.create_by IS '创建者'; +COMMENT ON COLUMN medication_plan.create_time IS '创建时间'; +COMMENT ON COLUMN medication_plan.update_by IS '更新者'; +COMMENT ON COLUMN medication_plan.update_time IS '更新时间'; +COMMENT ON COLUMN medication_plan.remark IS '备注'; +COMMENT ON COLUMN medication_plan.del_flag IS '删除标记:0-正常 1-删除'; + +CREATE INDEX idx_mp_member_id ON medication_plan(member_id); +CREATE INDEX idx_mp_status ON medication_plan(status); +CREATE INDEX idx_mp_medicine_id ON medication_plan(medicine_id); + +-- ======================================== +-- 3. 服药任务表 +-- ======================================== +DROP TABLE IF EXISTS medication_task; +CREATE TABLE medication_task ( + id BIGSERIAL PRIMARY KEY, + plan_id BIGINT NOT NULL, + member_id BIGINT NOT NULL, + medicine_name VARCHAR(100) NOT NULL, + planned_date DATE NOT NULL, + planned_time TIME NOT NULL, + planned_dosage DECIMAL(10,2) NOT NULL, + actual_time TIMESTAMP, + actual_dosage DECIMAL(10,2), + status SMALLINT NOT NULL DEFAULT 0, + confirm_type SMALLINT, + notes VARCHAR(255), + remind_status SMALLINT DEFAULT 0, + remind_time TIMESTAMP, + -- 若依标准字段 + create_by VARCHAR(64) DEFAULT '', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_by VARCHAR(64) DEFAULT '', + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + del_flag SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE medication_task IS '服药任务表'; +COMMENT ON COLUMN medication_task.id IS '主键ID'; +COMMENT ON COLUMN medication_task.plan_id IS '关联用药计划ID'; +COMMENT ON COLUMN medication_task.member_id IS '关联成员ID'; +COMMENT ON COLUMN medication_task.medicine_name IS '药品名称'; +COMMENT ON COLUMN medication_task.planned_date IS '计划服药日期'; +COMMENT ON COLUMN medication_task.planned_time IS '计划服药时间'; +COMMENT ON COLUMN medication_task.planned_dosage IS '计划剂量'; +COMMENT ON COLUMN medication_task.actual_time IS '实际服药时间'; +COMMENT ON COLUMN medication_task.actual_dosage IS '实际剂量'; +COMMENT ON COLUMN medication_task.status IS '状态:0-待服药 1-已服药 2-漏服 3-跳过'; +COMMENT ON COLUMN medication_task.confirm_type IS '确认方式:1-用户确认 2-家属代确认 3-系统自动'; +COMMENT ON COLUMN medication_task.notes IS '备注(如漏服原因)'; +COMMENT ON COLUMN medication_task.remind_status IS '提醒状态:0-未提醒 1-已提醒 2-已超时提醒'; +COMMENT ON COLUMN medication_task.remind_time IS '提醒时间'; +COMMENT ON COLUMN medication_task.create_by IS '创建者'; +COMMENT ON COLUMN medication_task.create_time IS '创建时间'; +COMMENT ON COLUMN medication_task.update_by IS '更新者'; +COMMENT ON COLUMN medication_task.update_time IS '更新时间'; +COMMENT ON COLUMN medication_task.remark IS '备注'; +COMMENT ON COLUMN medication_task.del_flag IS '删除标记:0-正常 1-删除'; + +CREATE INDEX idx_mt_plan_id ON medication_task(plan_id); +CREATE INDEX idx_mt_member_id ON medication_task(member_id); +CREATE INDEX idx_mt_planned_date ON medication_task(planned_date); +CREATE INDEX idx_mt_status ON medication_task(status); +CREATE INDEX idx_mt_planned_datetime ON medication_task(planned_date, planned_time); + +-- ======================================== +-- 4. 用药提醒日志表 +-- ======================================== +DROP TABLE IF EXISTS medication_remind_log; +CREATE TABLE medication_remind_log ( + id BIGSERIAL PRIMARY KEY, + task_id BIGINT NOT NULL, + remind_type SMALLINT NOT NULL, + remind_time TIMESTAMP NOT NULL, + remind_channel VARCHAR(20) NOT NULL, + remind_result SMALLINT NOT NULL, + error_msg VARCHAR(255), + -- 若依标准字段 + create_by VARCHAR(64) DEFAULT '', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_by VARCHAR(64) DEFAULT '', + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + del_flag SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE medication_remind_log IS '用药提醒日志表'; +COMMENT ON COLUMN medication_remind_log.id IS '主键ID'; +COMMENT ON COLUMN medication_remind_log.task_id IS '关联服药任务ID'; +COMMENT ON COLUMN medication_remind_log.remind_type IS '提醒类型:1-按时提醒 2-超时提醒 3-漏服通知家属'; +COMMENT ON COLUMN medication_remind_log.remind_time IS '提醒时间'; +COMMENT ON COLUMN medication_remind_log.remind_channel IS '提醒渠道:app/sms/wechat'; +COMMENT ON COLUMN medication_remind_log.remind_result IS '结果:1-成功 2-失败'; +COMMENT ON COLUMN medication_remind_log.error_msg IS '错误信息'; +COMMENT ON COLUMN medication_remind_log.create_by IS '创建者'; +COMMENT ON COLUMN medication_remind_log.create_time IS '创建时间'; +COMMENT ON COLUMN medication_remind_log.update_by IS '更新者'; +COMMENT ON COLUMN medication_remind_log.update_time IS '更新时间'; +COMMENT ON COLUMN medication_remind_log.remark IS '备注'; +COMMENT ON COLUMN medication_remind_log.del_flag IS '删除标记:0-正常 1-删除'; + +CREATE INDEX idx_mrl_task_id ON medication_remind_log(task_id); +CREATE INDEX idx_mrl_remind_time ON medication_remind_log(remind_time); + +-- ======================================== +-- 5. 药品库存变动表 +-- ======================================== +DROP TABLE IF EXISTS medicine_stock_log; +CREATE TABLE medicine_stock_log ( + id BIGSERIAL PRIMARY KEY, + medicine_id BIGINT NOT NULL, + member_id BIGINT NOT NULL, + change_type SMALLINT NOT NULL, + change_quantity DECIMAL(10,2) NOT NULL, + before_quantity DECIMAL(10,2) NOT NULL, + after_quantity DECIMAL(10,2) NOT NULL, + relate_id BIGINT, + notes VARCHAR(255), + -- 若依标准字段 + create_by VARCHAR(64) DEFAULT '', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_by VARCHAR(64) DEFAULT '', + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + del_flag SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE medicine_stock_log IS '药品库存变动表'; +COMMENT ON COLUMN medicine_stock_log.id IS '主键ID'; +COMMENT ON COLUMN medicine_stock_log.medicine_id IS '关联药品ID'; +COMMENT ON COLUMN medicine_stock_log.member_id IS '关联成员ID'; +COMMENT ON COLUMN medicine_stock_log.change_type IS '变动类型:1-入库 2-服药消耗 3-手动调整 4-过期报废'; +COMMENT ON COLUMN medicine_stock_log.change_quantity IS '变动数量(正数为增,负数为减)'; +COMMENT ON COLUMN medicine_stock_log.before_quantity IS '变动前库存'; +COMMENT ON COLUMN medicine_stock_log.after_quantity IS '变动后库存'; +COMMENT ON COLUMN medicine_stock_log.relate_id IS '关联ID(入库ID/任务ID等)'; +COMMENT ON COLUMN medicine_stock_log.notes IS '备注'; +COMMENT ON COLUMN medicine_stock_log.create_by IS '创建者'; +COMMENT ON COLUMN medicine_stock_log.create_time IS '创建时间'; +COMMENT ON COLUMN medicine_stock_log.update_by IS '更新者'; +COMMENT ON COLUMN medicine_stock_log.update_time IS '更新时间'; +COMMENT ON COLUMN medicine_stock_log.remark IS '备注'; +COMMENT ON COLUMN medicine_stock_log.del_flag IS '删除标记:0-正常 1-删除'; + +CREATE INDEX idx_msl_medicine_id ON medicine_stock_log(medicine_id); +CREATE INDEX idx_msl_member_id ON medicine_stock_log(member_id); +CREATE INDEX idx_msl_create_time ON medicine_stock_log(create_time); + +-- ======================================== +-- 6. 依从性统计汇总表 +-- ======================================== +DROP TABLE IF EXISTS medication_adherence_stats; +CREATE TABLE medication_adherence_stats ( + id BIGSERIAL PRIMARY KEY, + member_id BIGINT NOT NULL, + plan_id BIGINT, + stat_date DATE NOT NULL, + total_tasks INTEGER NOT NULL DEFAULT 0, + completed_tasks INTEGER NOT NULL DEFAULT 0, + missed_tasks INTEGER NOT NULL DEFAULT 0, + skipped_tasks INTEGER NOT NULL DEFAULT 0, + ontime_tasks INTEGER NOT NULL DEFAULT 0, + adherence_rate DECIMAL(5,2) NOT NULL DEFAULT 0.00, + ontime_rate DECIMAL(5,2) NOT NULL DEFAULT 0.00, + -- 若依标准字段 + create_by VARCHAR(64) DEFAULT '', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_by VARCHAR(64) DEFAULT '', + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + del_flag SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE medication_adherence_stats IS '依从性统计汇总表'; +COMMENT ON COLUMN medication_adherence_stats.id IS '主键ID'; +COMMENT ON COLUMN medication_adherence_stats.member_id IS '关联成员ID'; +COMMENT ON COLUMN medication_adherence_stats.plan_id IS '关联用药计划ID(为空表示该成员汇总)'; +COMMENT ON COLUMN medication_adherence_stats.stat_date IS '统计日期'; +COMMENT ON COLUMN medication_adherence_stats.total_tasks IS '总任务数'; +COMMENT ON COLUMN medication_adherence_stats.completed_tasks IS '已完成任务数'; +COMMENT ON COLUMN medication_adherence_stats.missed_tasks IS '漏服任务数'; +COMMENT ON COLUMN medication_adherence_stats.skipped_tasks IS '跳过任务数'; +COMMENT ON COLUMN medication_adherence_stats.ontime_tasks IS '准时服药任务数'; +COMMENT ON COLUMN medication_adherence_stats.adherence_rate IS '服药率(%)'; +COMMENT ON COLUMN medication_adherence_stats.ontime_rate IS '准时率(%)'; + +CREATE UNIQUE INDEX idx_mas_member_date ON medication_adherence_stats(member_id, stat_date, plan_id); +CREATE INDEX idx_mas_stat_date ON medication_adherence_stats(stat_date); \ No newline at end of file