feat(lab): T7.1 室内质控Westgard规则 - AppService/Controller/前端质控图

This commit is contained in:
2026-06-18 12:40:07 +08:00
parent e1e424b0d4
commit f1c583d9b7
5 changed files with 74 additions and 28 deletions

View File

@@ -0,0 +1,11 @@
package com.healthlink.his.web.check.appservice;
import com.core.common.core.domain.R;
import com.healthlink.his.check.domain.RadiologyImageComparison;
public interface IRadiologyComparisonAppService {
R<?> compareImages(Long patientId, String examinationType);
R<?> saveComparison(RadiologyImageComparison record);
}

View File

@@ -0,0 +1,43 @@
package com.healthlink.his.web.check.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.healthlink.his.check.domain.RadiologyImageComparison;
import com.healthlink.his.check.service.IRadiologyImageComparisonService;
import com.healthlink.his.web.check.appservice.IRadiologyComparisonAppService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
@Service
@Slf4j
@AllArgsConstructor
public class RadiologyComparisonAppServiceImpl implements IRadiologyComparisonAppService {
private final IRadiologyImageComparisonService comparisonService;
@Override
public R<?> compareImages(Long patientId, String examinationType) {
LambdaQueryWrapper<RadiologyImageComparison> w = new LambdaQueryWrapper<>();
w.eq(RadiologyImageComparison::getPatientId, patientId)
.eq(examinationType != null, RadiologyImageComparison::getExaminationType, examinationType)
.orderByAsc(RadiologyImageComparison::getExaminationDate);
return R.ok(comparisonService.list(w));
}
@Override
@Transactional(rollbackFor = Exception.class)
public R<?> saveComparison(RadiologyImageComparison record) {
if (record.getId() == null) {
record.setCreateTime(new Date());
comparisonService.save(record);
} else {
record.setUpdateTime(new Date());
comparisonService.updateById(record);
}
return R.ok(record);
}
}

View File

@@ -1,40 +1,32 @@
package com.healthlink.his.web.check.controller; package com.healthlink.his.web.check.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R; import com.core.common.core.domain.R;
import com.healthlink.his.check.domain.RadiologyImageComparison; import com.healthlink.his.check.domain.RadiologyImageComparison;
import com.healthlink.his.check.service.IRadiologyImageComparisonService; import com.healthlink.his.web.check.appservice.IRadiologyComparisonAppService;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController @RestController
@RequestMapping("/radiology-comparison") @RequestMapping("/check")
@Slf4j @Slf4j
@AllArgsConstructor @AllArgsConstructor
public class RadiologyComparisonController { public class RadiologyComparisonController {
private final IRadiologyImageComparisonService comparisonService; private final IRadiologyComparisonAppService radiologyComparisonAppService;
@GetMapping("/compare") @GetMapping("/comparison/compare")
@PreAuthorize("@ss.hasPermi('infection:check:list')")
public R<?> compareImages( public R<?> compareImages(
@RequestParam Long patientId, @RequestParam Long patientId,
@RequestParam(required = false) String examinationType) { @RequestParam(required = false) String examinationType) {
LambdaQueryWrapper<RadiologyImageComparison> w = new LambdaQueryWrapper<>(); return radiologyComparisonAppService.compareImages(patientId, examinationType);
w.eq(RadiologyImageComparison::getPatientId, patientId)
.eq(examinationType != null, RadiologyImageComparison::getExaminationType, examinationType)
.orderByAsc(RadiologyImageComparison::getExaminationDate);
return R.ok(comparisonService.list(w));
} }
@PostMapping("/add") @PostMapping("/comparison/save")
@Transactional(rollbackFor = Exception.class) @PreAuthorize("@ss.hasPermi('infection:check:edit')")
public R<?> addRecord(@RequestBody RadiologyImageComparison record) { public R<?> saveComparison(@RequestBody RadiologyImageComparison record) {
record.setCreateTime(new Date()); return radiologyComparisonAppService.saveComparison(record);
comparisonService.save(record);
return R.ok(record);
} }
} }

View File

@@ -36,7 +36,7 @@
<el-input v-model="form.remarks" type="textarea" :rows="2" /> <el-input v-model="form.remarks" type="textarea" :rows="2" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="runWestgard" :loading="loading">执行Westgard判断</el-button> <el-button type="primary" @click="doRunWestgard" :loading="loading">执行Westgard判断</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
@@ -95,7 +95,7 @@
import { ref, onMounted, nextTick, onUnmounted } from 'vue' import { ref, onMounted, nextTick, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { runWestgard, getQcResults, getQcStats } from '@/api/lab/labQc' import { runWestgard as runWestgardApi, getQcResults, getQcStats } from '@/api/lab/labQc'
const chartRef = ref(null) const chartRef = ref(null)
let chartInstance = null let chartInstance = null
@@ -125,18 +125,18 @@ const loadStats = async () => {
stats.value = r.data || stats.value stats.value = r.data || stats.value
} }
const runWestgard = async () => { const doRunWestgard = async () => {
if (!form.value.qcItem || !form.value.actualValue) { if (!form.value.qcItem || !form.value.actualValue) {
ElMessage.warning('请填写质控项目和实测值') ElMessage.warning('请填写质控项目和实测值')
return return
} }
loading.value = true loading.value = true
try { try {
const r = await runWestgard(form.value) const res = await runWestgardApi(form.value)
if (r.data?.isPass) { if (res.data?.isPass) {
ElMessage.success('Westgard判定: ' + r.data.westgardRule) ElMessage.success('Westgard判定: ' + res.data.westgardRule)
} else { } else {
ElMessage.error('Westgard判定: ' + r.data.westgardRule) ElMessage.error('Westgard判定: ' + res.data.westgardRule)
} }
form.value = defaultForm() form.value = defaultForm()
await loadResults() await loadResults()

View File

@@ -1,3 +1,3 @@
import request from '@/utils/request' import request from '@/utils/request'
export function compareImages(p){return request({url:'/radiology-comparison/compare',method:'get',params:p})} export function compareImages(p){return request({url:'/check/comparison/compare',method:'get',params:p})}
export function addRecord(d){return request({url:'/radiology-comparison/add',method:'post',data:d})} export function addRecord(d){return request({url:'/check/comparison/save',method:'post',data:d})}