feat(nursing): 护理文书+质量指标+交接班增强
- 护理文书: 已有完整实现(NursingRecordController+前端),无需新增 - 护理质量指标: 新增 /nursing-quality/collect 采集指标, /nursing-quality/indicators 查询指标 - 交接班: 新增 /nursing-execution/handoff/key-patients 重点患者列表 - 前端: nursingquality 新增采集按钮, nursingexecution 交接班tab增加重点患者提示
This commit is contained in:
@@ -78,6 +78,31 @@ public class NursingExecutionController {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/handoff/key-patients")
|
||||
public R<?> getKeyPatients(
|
||||
@RequestParam(value = "ward", required = false) String ward) {
|
||||
LambdaQueryWrapper<NursingHandoffRecord> w = new LambdaQueryWrapper<>();
|
||||
w.eq(StringUtils.hasText(ward), NursingHandoffRecord::getWard, ward)
|
||||
.isNotNull(NursingHandoffRecord::getKeyPatients)
|
||||
.ne(NursingHandoffRecord::getKeyPatients, "")
|
||||
.orderByDesc(NursingHandoffRecord::getHandoffDate)
|
||||
.last("LIMIT 20");
|
||||
List<NursingHandoffRecord> records = handoffService.list(w);
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (NursingHandoffRecord r : records) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("ward", r.getWard());
|
||||
item.put("shift", r.getShift());
|
||||
item.put("handoffDate", r.getHandoffDate());
|
||||
item.put("handoffNurseName", r.getHandoffNurseName());
|
||||
item.put("keyPatients", r.getKeyPatients());
|
||||
item.put("pendingMatters", r.getPendingMatters());
|
||||
item.put("specialNotes", r.getSpecialNotes());
|
||||
result.add(item);
|
||||
}
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
// ==================== 输液巡视 ====================
|
||||
@GetMapping("/infusion/page")
|
||||
public R<?> getInfusionPage(
|
||||
|
||||
@@ -41,6 +41,61 @@ public class NursingQualityController {
|
||||
return R.ok(indicator);
|
||||
}
|
||||
|
||||
@GetMapping("/indicators")
|
||||
public R<?> getIndicators(
|
||||
@RequestParam(value = "indicatorCategory", required = false) String category,
|
||||
@RequestParam(value = "departmentName", required = false) String departmentName,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
|
||||
LambdaQueryWrapper<NursingQualityIndicator> w = new LambdaQueryWrapper<>();
|
||||
w.eq(StringUtils.hasText(category), NursingQualityIndicator::getIndicatorCategory, category)
|
||||
.eq(StringUtils.hasText(departmentName), NursingQualityIndicator::getDepartmentName, departmentName)
|
||||
.orderByDesc(NursingQualityIndicator::getStatDate);
|
||||
return R.ok(indicatorService.page(new Page<>(pageNo, pageSize), w));
|
||||
}
|
||||
|
||||
@PostMapping("/collect")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> collectIndicators(@RequestBody Map<String, Object> params) {
|
||||
String departmentName = (String) params.getOrDefault("departmentName", "");
|
||||
String statPeriod = (String) params.getOrDefault("statPeriod", "MONTHLY");
|
||||
String statDate = (String) params.getOrDefault("statDate", new java.text.SimpleDateFormat("yyyy-MM-dd").format(new Date()));
|
||||
|
||||
List<Map<String, Object>> rules = List.of(
|
||||
Map.of("code", "NQ001", "name", "基础护理合格率", "category", "BASIC", "target", new java.math.BigDecimal("95"), "unit", "%"),
|
||||
Map.of("code", "NQ002", "name", "护理文书书写合格率", "category", "DOCUMENTATION", "target", new java.math.BigDecimal("98"), "unit", "%"),
|
||||
Map.of("code", "NQ003", "name", "急救物品完好率", "category", "SAFETY", "target", new java.math.BigDecimal("100"), "unit", "%"),
|
||||
Map.of("code", "NQ004", "name", "消毒隔离合格率", "category", "STERILIZATION", "target", new java.math.BigDecimal("100"), "unit", "%"),
|
||||
Map.of("code", "NQ005", "name", "压疮发生率", "category", "BASIC", "target", new java.math.BigDecimal("0"), "unit", "%"),
|
||||
Map.of("code", "NQ006", "name", "跌倒发生率", "category", "SAFETY", "target", new java.math.BigDecimal("0"), "unit", "%"),
|
||||
Map.of("code", "NQ007", "name", "患者满意度", "category", "BASIC", "target", new java.math.BigDecimal("90"), "unit", "%"),
|
||||
Map.of("code", "NQ008", "name", "护理操作并发症发生率", "category", "SAFETY", "target", new java.math.BigDecimal("1"), "unit", "%")
|
||||
);
|
||||
|
||||
int created = 0;
|
||||
for (Map<String, Object> rule : rules) {
|
||||
LambdaQueryWrapper<NursingQualityIndicator> exist = new LambdaQueryWrapper<>();
|
||||
exist.eq(NursingQualityIndicator::getIndicatorCode, rule.get("code"))
|
||||
.eq(NursingQualityIndicator::getStatDate, statDate);
|
||||
if (indicatorService.count(exist) > 0) continue;
|
||||
|
||||
NursingQualityIndicator indicator = new NursingQualityIndicator();
|
||||
indicator.setIndicatorCode((String) rule.get("code"));
|
||||
indicator.setIndicatorName((String) rule.get("name"));
|
||||
indicator.setIndicatorCategory((String) rule.get("category"));
|
||||
indicator.setTargetValue((java.math.BigDecimal) rule.get("target"));
|
||||
indicator.setUnit((String) rule.get("unit"));
|
||||
indicator.setStatPeriod(statPeriod);
|
||||
indicator.setStatDate(statDate);
|
||||
indicator.setDepartmentName(departmentName);
|
||||
indicator.setStatus("ACTIVE");
|
||||
indicator.setCreateTime(new Date());
|
||||
indicatorService.save(indicator);
|
||||
created++;
|
||||
}
|
||||
return R.ok(Map.of("created", created, "total", rules.size()));
|
||||
}
|
||||
|
||||
@GetMapping("/summary")
|
||||
public R<?> getSummary() {
|
||||
Map<String, Object> summary = new HashMap<>();
|
||||
|
||||
@@ -4,5 +4,6 @@ export function addScan(d){return request({url:'/nursing-execution/scan/add',met
|
||||
export function getHandoffPage(p){return request({url:'/nursing-execution/handoff/page',method:'get',params:p})}
|
||||
export function addHandoff(d){return request({url:'/nursing-execution/handoff/add',method:'post',data:d})}
|
||||
export function confirmHandoff(id){return request({url:'/nursing-execution/handoff/confirm',method:'post',params:{id}})}
|
||||
export function getKeyPatients(p){return request({url:'/nursing-execution/handoff/key-patients',method:'get',params:p})}
|
||||
export function getInfusionPage(p){return request({url:'/nursing-execution/infusion/page',method:'get',params:p})}
|
||||
export function addInfusion(d){return request({url:'/nursing-execution/infusion/add',method:'post',data:d})}
|
||||
|
||||
@@ -83,6 +83,33 @@
|
||||
新增交接
|
||||
</el-button>
|
||||
</div>
|
||||
<!-- 重点患者区域 -->
|
||||
<div
|
||||
v-if="keyPatients.length > 0"
|
||||
style="margin-bottom:16px;background:#fdf6ec;border:1px solid #e6a23c;border-radius:6px;padding:12px"
|
||||
>
|
||||
<div style="font-weight:bold;color:#e6a23c;margin-bottom:8px">
|
||||
重点患者提示
|
||||
</div>
|
||||
<div
|
||||
v-for="(kp, idx) in keyPatients"
|
||||
:key="idx"
|
||||
style="margin-bottom:6px;font-size:13px"
|
||||
>
|
||||
<el-tag
|
||||
type="warning"
|
||||
size="small"
|
||||
style="margin-right:6px"
|
||||
>
|
||||
{{ kp.ward }} {{ kp.shift }}
|
||||
</el-tag>
|
||||
<span style="font-weight:500">{{ kp.keyPatients }}</span>
|
||||
<span
|
||||
v-if="kp.pendingMatters"
|
||||
style="color:#999;margin-left:8px"
|
||||
>待办: {{ kp.pendingMatters }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
:data="handoffData"
|
||||
border
|
||||
@@ -224,14 +251,14 @@
|
||||
<script setup>
|
||||
import {ref,reactive,onMounted} from 'vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {getScanPage,addScan,getHandoffPage,addHandoff,confirmHandoff,getInfusionPage,addInfusion} from './api'
|
||||
import {getScanPage,addScan,getHandoffPage,addHandoff,confirmHandoff,getKeyPatients,getInfusionPage,addInfusion} from './api'
|
||||
const tab=ref('scan')
|
||||
const scanData=ref([]),handoffData=ref([]),infusionData=ref([])
|
||||
const scanData=ref([]),handoffData=ref([]),infusionData=ref([]),keyPatients=ref([])
|
||||
const showScan=ref(false),showHandoff=ref(false),showInfusion=ref(false)
|
||||
const scanForm=reactive({patientName:'',scanType:'WRISTBAND',barcode:'',nurseName:''})
|
||||
const handoffForm=reactive({ward:'',shift:'MORNING',handoffNurseName:'',receiveNurseName:'',patientCount:0,criticalCount:0,keyPatients:''})
|
||||
const infusionForm=reactive({patientName:'',drugName:'',dripRate:0,patencyStatus:'NORMAL',patrolNurseName:''})
|
||||
const loadData=async()=>{const [s,h,i]=await Promise.all([getScanPage({pageNo:1,pageSize:50}),getHandoffPage({pageNo:1,pageSize:50}),getInfusionPage({pageNo:1,pageSize:50})]);scanData.value=s.data?.records||[];handoffData.value=h.data?.records||[];infusionData.value=i.data?.records||[]}
|
||||
const loadData=async()=>{const [s,h,kp,i]=await Promise.all([getScanPage({pageNo:1,pageSize:50}),getHandoffPage({pageNo:1,pageSize:50}),getKeyPatients(),getInfusionPage({pageNo:1,pageSize:50})]);scanData.value=s.data?.records||[];handoffData.value=h.data?.records||[];keyPatients.value=kp.data||[];infusionData.value=i.data?.records||[]}
|
||||
const confirmAction=async(row)=>{await confirmHandoff(row.id);ElMessage.success('已确认');loadData()}
|
||||
const submitScan=async()=>{await addScan(scanForm);ElMessage.success('成功');showScan.value=false;loadData()}
|
||||
const submitHandoff=async()=>{await addHandoff(handoffForm);ElMessage.success('成功');showHandoff.value=false;loadData()}
|
||||
|
||||
@@ -2,3 +2,5 @@ import request from '@/utils/request'
|
||||
export function getQualityPage(p){return request({url:'/nursing-quality/page',method:'get',params:p})}
|
||||
export function addIndicator(d){return request({url:'/nursing-quality/add',method:'post',data:d})}
|
||||
export function getQualitySummary(){return request({url:'/nursing-quality/summary',method:'get'})}
|
||||
export function getIndicators(p){return request({url:'/nursing-quality/indicators',method:'get',params:p})}
|
||||
export function collectIndicators(d){return request({url:'/nursing-quality/collect',method:'post',data:d})}
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
@click="handleCollect"
|
||||
>
|
||||
采集指标
|
||||
</el-button>
|
||||
<el-button
|
||||
type="info"
|
||||
@click="exportReport"
|
||||
>
|
||||
导出报告
|
||||
@@ -324,7 +330,7 @@
|
||||
<script setup>
|
||||
import {ref, reactive, onMounted} from 'vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {getQualityPage, addIndicator, getQualitySummary} from './api'
|
||||
import {getQualityPage, addIndicator, getQualitySummary, collectIndicators} from './api'
|
||||
|
||||
const loading = ref(false)
|
||||
const indicatorData = ref([])
|
||||
@@ -391,5 +397,15 @@ async function submitForm() {
|
||||
|
||||
function exportReport() { ElMessage.info('导出功能开发中') }
|
||||
|
||||
async function handleCollect() {
|
||||
try {
|
||||
const res = await collectIndicators({ departmentName: q.value.departmentName || '' })
|
||||
ElMessage.success(`已采集 ${res.data?.created || 0} 项指标`)
|
||||
loadData()
|
||||
} catch (e) {
|
||||
ElMessage.error('采集失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => loadData())
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user