目的
uniapp-ts 的危急值管理页面提供后端实现设计与参考代码结构。GET(只读)与 POST(写)两种请求方法。范围
说明
docs/新增危急值模块.md 的字段与接口约定:表 t_critical_value_module、字段 value_type、critical_above_value、critical_below_value 等;接口仅使用 GET 与 POST。一、数据库设计
表名:t_critical_value_module
示例建表 SQL:
CREATE TABLE `t_critical_value_module` (
`id` BIGINT NOT NULL,
`value_type` VARCHAR(50) NOT NULL COMMENT '危急值类型,如 height, weight, systolic, fasting 等',
`critical_above_value` DECIMAL(10,2) DEFAULT NULL COMMENT '危急值上限',
`critical_below_value` DECIMAL(10,2) DEFAULT NULL COMMENT '危急值下限',
`record_time` DATETIME DEFAULT NULL COMMENT '记录时间',
`create_user` BIGINT DEFAULT NULL,
`create_time` DATETIME DEFAULT NULL,
`update_user` BIGINT DEFAULT NULL,
`update_time` DATETIME DEFAULT NULL,
`remark` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `idx_value_type` (`value_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='危急值配置表';
备注:
value_type 使用枚举值(参见前端 critical-values.vue 提取的枚举),后端可以在 Service 层做校验。BaseEntity/CustomMetaObjectHandler 约定保持一致:IdType.ASSIGN_ID(雪花算法)或项目通用 ID 策略来生成 id,因此建表时可不使用 AUTO_INCREMENT,以与现有表保持一致。create_time / update_time 通常由项目的 CustomMetaObjectHandler 自动填充(见 model/po/BaseEntity.java),建议数据库列不依赖 DEFAULT CURRENT_TIMESTAMP,而由应用层填充以保持一致性和时区控制。create_user / update_user 在项目中为 BIGINT(用户 id),文档上方示例已做相应调整。二、后端包/类结构(建议,基于 Spring Boot + MyBatis-Plus)
建议使用项目现有包路径风格:work.baiyun.chronicdiseaseapp.processing.critical(模块根包),目录结构示例:
controller
CriticalValueController.java — REST 接口入口service
CriticalValueService.java (接口)CriticalValueServiceImpl.java (实现)mapper
CriticalValueMapper.java (MyBatis-Plus 接口,继承 BaseMapper<CriticalValue>,使用注解或 Mapper 扫描,无 XML)model.po
CriticalValue.java(实体,对应数据库表 t_critical_value_module)model.vo
CreateOrUpdateCriticalValueRequest.java(请求)CriticalValueResponse.java(响应)enum
ValueType.java(后端枚举,值与前端一致)exception
ProcessingException.java(模块内统一异常)说明:
mapper 文件如 MedicineMapper),推荐 CriticalValueMapper 直接继承 com.baomidou.mybatisplus.core.mapper.BaseMapper<CriticalValue> 并添加 @Mapper 注解或通过包扫描注册,不需要 *.xml 映射文件。QueryWrapper / LambdaQueryWrapper / UpdateWrapper 进行查询与更新;仅在特殊场景(复杂 SQL 或性能优化)下使用 @Select 注解编写原生 SQL。三、主要接口(与文档一致)
1) 获取危急值列表
/api/critical-valuesvalue_type(可选)value_type 过滤并返回对应记录集合;若不传 value_type 返回所有。返回示例(HTTP 200):
[{
"id": 1,
"value_type": "fasting",
"critical_above_value": 7.0,
"critical_below_value": 3.9,
"remark": "空腹血糖危急值"
}]
2) 获取危急值详情
/api/critical-values/{id}3) 新增或更新危急值
/api/critical-valuesid 字段时视为更新(先校验存在),否则为新增。value_type 非空并为合法枚举critical_above_value 与 critical_below_value 至少有一个非空4) 删除危急值
/api/critical-values/deleteid(或 ids 列表)作为写操作进行删除。5) 获取危急值类型枚举
/api/critical-values/types返回示例:
[
{"value":"height","label":"身高"},
{"value":"weight","label":"体重"},
{"value":"fasting","label":"血糖-空腹"}
]
四、示例 DTO / Entity(简化)
实体(model.po)示例:CriticalValue.java
package work.baiyun.chronicdiseaseapp.model.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import work.baiyun.chronicdiseaseapp.model.po.BaseEntity;
@TableName("t_critical_value_module")
public class CriticalValue extends BaseEntity {
private String valueType;
@TableField("critical_above_value")
private BigDecimal criticalAboveValue;
@TableField("critical_below_value")
private BigDecimal criticalBelowValue;
@TableField("record_time")
private LocalDateTime recordTime;
// remark / create/update fields inherited from BaseEntity
// getter/setter
}
请求/响应(model.vo)示例命名:
1) 创建/更新请求:CreateOrUpdateCriticalValueRequest.java
public class CreateOrUpdateCriticalValueRequest {
private Long id; // 可选,存在则为更新
private String valueType;
private BigDecimal criticalAboveValue;
private BigDecimal criticalBelowValue;
private String remark;
// getter/setter
}
2) 对外响应:CriticalValueResponse.java
public class CriticalValueResponse {
private String id; // 返回给前端为 String,避免 JS 精度问题
private String valueType;
private BigDecimal criticalAboveValue;
private BigDecimal criticalBelowValue;
private String remark;
private LocalDateTime recordTime;
// getter/setter
}
五、Controller 示例方法签名(伪码)
@RestController
@RequestMapping("/api/critical-values")
public class CriticalValueController {
@GetMapping("")
public R<List<CriticalValueResponse>> list(@RequestParam(required=false) String valueType) { ... }
@GetMapping("/{id}")
public R<CriticalValueResponse> get(@PathVariable String id) { ... }
@PostMapping("")
public R<?> saveOrUpdate(@RequestBody CreateOrUpdateCriticalValueRequest req) { ... }
@PostMapping("/delete")
public R<?> delete(@RequestBody DeleteRequest req) { ... }
@GetMapping("/types")
public R<List<EnumVO>> types() { ... }
}
六、Mapper (MyBatis-Plus) 示例(QueryWrapper / 注解 SQL)
说明:本项目优先使用 MyBatis-Plus 的 QueryWrapper / LambdaQueryWrapper 进行查询与更新;仅在复杂或性能敏感场景使用 @Select 注解编写原生 SQL。下面给出 QueryWrapper 的伪代码与经修正的示例 SQL(供参考),SQL 中参数请使用 MyBatis 占位符 #{...}。
QueryWrapper 伪代码示例:
LambdaQueryWrapper<CriticalValue> wrapper = new LambdaQueryWrapper<>();
if (valueType != null) {
wrapper.eq(CriticalValue::getValueType, valueType);
}
wrapper.orderByAsc(CriticalValue::getId);
List<CriticalValue> list = criticalValueMapper.selectList(wrapper);
原生 SQL(示意,若使用 @Select 请使用类似写法并注意字段映射):
查询(按 type)
SELECT id, value_type, critical_above_value, critical_below_value, remark
FROM t_critical_value_module
WHERE (#{valueType} IS NULL OR value_type = #{valueType})
ORDER BY id;
插入
INSERT INTO t_critical_value_module (value_type, critical_above_value, critical_below_value, remark, create_user)
VALUES (#{valueType}, #{criticalAboveValue}, #{criticalBelowValue}, #{remark}, #{createUser});
更新
UPDATE t_critical_value_module
SET value_type = #{valueType}, critical_above_value = #{criticalAboveValue},
critical_below_value = #{criticalBelowValue}, remark = #{remark}, update_user = #{updateUser}
WHERE id = #{id};
删除
DELETE FROM t_critical_value_module WHERE id = #{id};
备注:推荐在文档中把以上 SQL 视为参考;实际实现优先用 QueryWrapper。如果使用 @Select 注解,请确保 SQL 与 VO 字段别名一致并使用 #{} 占位。
七、校验与异常处理
@NotBlank、@DecimalMin 等。id 不存在返回 404/自定义错误)。文档 / Swagger 注意:
若项目使用泛型包装类(如 R<T>)返回值,Swagger 可能无法正确展示泛型内部结构。建议在 Controller 方法上使用 @ApiResponse / @Content / @Schema(implementation = ...) 明确指定实际返回类型;对于分页等复杂泛型,创建专用的文档 VO 并在注解中引用。示例:
@Operation(summary = "获取危急值列表")
@ApiResponse(responseCode = "200", description = "OK",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = CriticalValueListResponse.class)))
public R<?> list(...) { ... }
@ApiResponse 注解(400/401/403/404/500),提高文档准确性和前端对接效率。八、安全与权限
九、测试建议
十、迁移与上线说明
api-springboot/docs/Dev/modules/Processing/critical-values-backend-design.md十一、注意事项与前端对接要点
ValueType 一致;推荐在后端 /types 接口返回 label 与 value,前端直接消费。POST /api/critical-values/delete,前端发送 {id: 123};避免跨域或预检问题需与前端同事确认请求头与 Content-Type(建议 application/json)。补充要点(从历史问题与经验教训中提取,强烈建议遵循):
ID 精度(前端显示/处理):
建议:在 API 响应的 VO 中将 id 定义为 String 并在 Service 层转换:
// VO / Response
public class CriticalValueResponse {
private String id; // 注意:String 类型以避免前端精度丢失
// ...其他字段
}
// Service 层转换示例
CriticalValueResponse vo = new CriticalValueResponse();
BeanUtils.copyProperties(entity, vo);
vo.setId(entity.getId() == null ? null : entity.getId().toString());
说明:请求入参仍可按现有习惯使用 Long(或前端传 String 再后端解析),但响应务必返回 String,避免前端误差。
类型映射兼容性(TINYINT(1) 与 Boolean):
TINYINT(1) 在某些 JDBC 驱动下不能稳定映射为 Java Boolean,导致 VO 中布尔字段为 null。TINYINT(1) 布尔字段,PO 使用 Byte 或 Integer 更稳妥;由 Service 在返回 VO 时明确转换为 Boolean。示例:
// PO
private Byte notificationEnabled; // 对应 TINYINT(1)
// Service -> VO 转换
vo.setNotificationEnabled(entity.getNotificationEnabled() != null && entity.getNotificationEnabled() == 1);
—— 结束 ——