feat(empi): T9.1 患者身份合并/拆分 — 后端splitPatients接口+前端拆分管理tab
This commit is contained in:
@@ -15,4 +15,5 @@ public interface IEmpiAppService {
|
||||
List<Patient> findLinkedPatients(String globalId);
|
||||
List<Patient> findLinkedPatientsByIdCard(String idCardNo);
|
||||
List<EmpiPerson> listPersons(String name, String idCardNo);
|
||||
void splitPatients(Long primaryId, List<Long> secondaryIds);
|
||||
}
|
||||
@@ -126,4 +126,25 @@ public class EmpiAppServiceImpl implements IEmpiAppService {
|
||||
wrapper.orderByDesc(EmpiPerson::getId);
|
||||
return personService.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void splitPatients(Long primaryId, List<Long> secondaryIds) {
|
||||
EmpiPerson primary = personService.getById(primaryId);
|
||||
if (primary == null) throw new RuntimeException("主患者不存在");
|
||||
for (Long secId : secondaryIds) {
|
||||
EmpiPerson sec = personService.getById(secId);
|
||||
if (sec == null || !"MERGED".equals(sec.getMergeStatus())) continue;
|
||||
sec.setMergeStatus("ACTIVE");
|
||||
personService.updateById(sec);
|
||||
EmpiMergeLog logRecord = new EmpiMergeLog();
|
||||
logRecord.setSourcePatientId(primaryId);
|
||||
logRecord.setTargetPatientId(secId);
|
||||
logRecord.setMergeType("SPLIT");
|
||||
logRecord.setMergeReason("EMPI拆分");
|
||||
logRecord.setMergeBy("system");
|
||||
logRecord.setMergeTime(new Date());
|
||||
logRecord.setStatus("SPLIT");
|
||||
mergeLogService.save(logRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.healthlink.his.web.empi.appservice.IEmpiAppService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,11 +26,20 @@ public class EmpiController {
|
||||
|
||||
@Operation(summary = "合并患者")
|
||||
@PostMapping("/merge")
|
||||
@PreAuthorize("infection:empi:edit")
|
||||
public AjaxResult merge(@RequestParam Long primaryId, @RequestParam List<Long> secondaryIds) {
|
||||
empiAppService.mergePersons(primaryId, secondaryIds);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "拆分患者")
|
||||
@PostMapping("/split")
|
||||
@PreAuthorize("infection:empi:edit")
|
||||
public AjaxResult split(@RequestParam Long primaryId, @RequestParam List<Long> secondaryIds) {
|
||||
empiAppService.splitPatients(primaryId, secondaryIds);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "按全局ID查询EMPI")
|
||||
@GetMapping("/person/global/{globalId}")
|
||||
public AjaxResult findByGlobalId(@PathVariable String globalId) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import request from '@/utils/request'
|
||||
// EMPI基础操作
|
||||
export function registerPerson(data) { return request({ url: '/api/v1/empi/person', method: 'post', data }) }
|
||||
export function mergePersons(primaryId, secondaryIds) { return request({ url: '/api/v1/empi/merge', method: 'post', params: { primaryId, secondaryIds: secondaryIds.join(',') } }) }
|
||||
export function splitPersons(primaryId, secondaryIds) { return request({ url: '/api/v1/empi/split', method: 'post', params: { primaryId, secondaryIds: secondaryIds.join(',') } }) }
|
||||
export function findByGlobalId(globalId) { return request({ url: '/api/v1/empi/person/global/' + globalId, method: 'get' }) }
|
||||
export function findByIdCard(idCardNo) { return request({ url: '/api/v1/empi/person/idcard/' + idCardNo, method: 'get' }) }
|
||||
export function getMappings(globalId) { return request({ url: '/api/v1/empi/mappings/' + globalId, method: 'get' }) }
|
||||
|
||||
@@ -136,12 +136,127 @@
|
||||
:type="row.status==='MERGED'?'success':'info'"
|
||||
size="small"
|
||||
>
|
||||
{{ row.status==='MERGED'?'已合并':'已撤回' }}
|
||||
{{ row.status==='MERGED'?'已合并':row.status==='SPLIT'?'已拆分':'已撤回' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
label="拆分管理"
|
||||
name="split"
|
||||
>
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
style="margin-bottom:12px"
|
||||
>
|
||||
选择一个已合并的患者作为"来源患者",再勾选要拆分的患者,点击"拆分选中患者"
|
||||
</el-alert>
|
||||
<el-form
|
||||
:inline="true"
|
||||
class="mb8"
|
||||
>
|
||||
<el-form-item label="姓名">
|
||||
<el-input
|
||||
v-model="splitSearchName"
|
||||
placeholder="患者姓名"
|
||||
clearable
|
||||
@keyup.enter="loadSplitPatients"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="loadSplitPatients"
|
||||
>
|
||||
查询
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
v-loading="splitLoading"
|
||||
:data="splitPatientsList"
|
||||
border
|
||||
stripe
|
||||
row-key="id"
|
||||
@selection-change="handleSplitSelection"
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="50"
|
||||
:selectable="(row) => row.mergeStatus === 'MERGED'"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
width="60"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="globalId"
|
||||
label="全局ID"
|
||||
width="160"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="姓名"
|
||||
width="100"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="gender"
|
||||
label="性别"
|
||||
width="60"
|
||||
>
|
||||
<template #default="{row}">
|
||||
{{ row.gender === 'M' ? '男' : row.gender === 'F' ? '女' : row.gender }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="idCardNo"
|
||||
label="身份证号"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="mergeStatus"
|
||||
label="状态"
|
||||
width="80"
|
||||
>
|
||||
<template #default="{row}">
|
||||
<el-tag
|
||||
:type="row.mergeStatus === 'MERGED' ? 'info' : 'success'"
|
||||
size="small"
|
||||
>
|
||||
{{ row.mergeStatus === 'MERGED' ? '已合并' : '正常' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="120"
|
||||
>
|
||||
<template #default="{row}">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
:type="splitSource && splitSource.id === row.id ? 'success' : ''"
|
||||
@click="splitSource = row"
|
||||
>
|
||||
{{ splitSource && splitSource.id === row.id ? '已选为来源' : '设为来源' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="margin-top:12px;text-align:right">
|
||||
<el-button
|
||||
type="warning"
|
||||
:disabled="!splitSource || splitSelectedRows.length === 0"
|
||||
@click="handleSplit"
|
||||
>
|
||||
拆分选中患者 ({{ splitSelectedRows.length }})
|
||||
</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
@@ -149,7 +264,7 @@
|
||||
<script setup>
|
||||
import {ref,reactive,onMounted} from 'vue'
|
||||
import {ElMessage,ElMessageBox} from 'element-plus'
|
||||
import {getFamilyMembers,addFamilyMember,deleteFamilyMember,getMergeLogPage} from './api'
|
||||
import {getFamilyMembers,addFamilyMember,deleteFamilyMember,getMergeLogPage,listPersons,splitPersons} from './api'
|
||||
const tab=ref('family')
|
||||
const searchPatientId=ref('')
|
||||
const familyData=ref([]),mergeData=ref([])
|
||||
@@ -158,5 +273,35 @@ const familyForm=reactive({patientId:null,memberName:'',relationship:'',gender:'
|
||||
const loadFamily=async()=>{if(!searchPatientId.value)return;const r=await getFamilyMembers({patientId:searchPatientId.value});familyData.value=r.data||[]}
|
||||
const deleteFamily=async(id)=>{await ElMessageBox.confirm('确认删除?');await deleteFamilyMember(id);ElMessage.success('已删除');loadFamily()}
|
||||
const loadData=async()=>{const m=await getMergeLogPage({pageNo:1,pageSize:50});mergeData.value=m.data?.records||[]}
|
||||
onMounted(()=>loadData())
|
||||
|
||||
const splitLoading=ref(false)
|
||||
const splitPatientsList=ref([])
|
||||
const splitSearchName=ref('')
|
||||
const splitSource=ref(null)
|
||||
const splitSelectedRows=ref([])
|
||||
|
||||
const loadSplitPatients=async()=>{
|
||||
splitLoading.value=true
|
||||
try{
|
||||
const res=await listPersons({name:splitSearchName.value})
|
||||
splitPatientsList.value=(res.data||[]).filter(p=>p.mergeStatus==='MERGED')
|
||||
}catch(e){splitPatientsList.value=[]}
|
||||
splitLoading.value=false
|
||||
}
|
||||
const handleSplitSelection=(selection)=>{splitSelectedRows.value=selection.filter(r=>r.id!==splitSource.value?.id)}
|
||||
const handleSplit=async()=>{
|
||||
if(!splitSource.value){ElMessage.warning('请先选择来源患者');return}
|
||||
if(splitSelectedRows.value.length===0){ElMessage.warning('请勾选要拆分的患者');return}
|
||||
await ElMessageBox.confirm(`确认拆分 ${splitSelectedRows.value.length} 个患者?`)
|
||||
try{
|
||||
await splitPersons(splitSource.value.id,splitSelectedRows.value.map(r=>r.id))
|
||||
ElMessage.success('拆分成功')
|
||||
splitSource.value=null
|
||||
splitSelectedRows.value=[]
|
||||
loadSplitPatients()
|
||||
loadData()
|
||||
}catch(e){ElMessage.error('拆分失败')}
|
||||
}
|
||||
|
||||
onMounted(()=>{loadData();loadSplitPatients()})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user