feat(kg): 医疗知识图谱全栈实现
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package com.healthlink.his.web.knowledgegraph.appservice;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.healthlink.his.web.knowledgegraph.dto.*;
|
||||
|
||||
public interface IKgEntityAppService {
|
||||
|
||||
Boolean addDisease(KgDiseaseDto dto);
|
||||
|
||||
Boolean updateDisease(KgDiseaseDto dto);
|
||||
|
||||
Boolean deleteDisease(Long id);
|
||||
|
||||
KgDiseaseDto getDiseaseById(Long id);
|
||||
|
||||
IPage<KgDiseaseDto> pageDisease(String keyword, String category, Integer pageNo, Integer pageSize);
|
||||
|
||||
Boolean addSymptom(KgSymptomDto dto);
|
||||
|
||||
Boolean updateSymptom(KgSymptomDto dto);
|
||||
|
||||
Boolean deleteSymptom(Long id);
|
||||
|
||||
KgSymptomDto getSymptomById(Long id);
|
||||
|
||||
IPage<KgSymptomDto> pageSymptom(String keyword, String symptomType, Integer pageNo, Integer pageSize);
|
||||
|
||||
Boolean addDrug(KgDrugDto dto);
|
||||
|
||||
Boolean updateDrug(KgDrugDto dto);
|
||||
|
||||
Boolean deleteDrug(Long id);
|
||||
|
||||
KgDrugDto getDrugById(Long id);
|
||||
|
||||
IPage<KgDrugDto> pageDrug(String keyword, String category, Integer pageNo, Integer pageSize);
|
||||
|
||||
Boolean addExamination(KgExaminationDto dto);
|
||||
|
||||
Boolean updateExamination(KgExaminationDto dto);
|
||||
|
||||
Boolean deleteExamination(Long id);
|
||||
|
||||
KgExaminationDto getExaminationById(Long id);
|
||||
|
||||
IPage<KgExaminationDto> pageExamination(String keyword, String examType, Integer pageNo, Integer pageSize);
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package com.healthlink.his.web.knowledgegraph.appservice.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.healthlink.his.knowledgegraph.domain.*;
|
||||
import com.healthlink.his.knowledgegraph.service.*;
|
||||
import com.healthlink.his.web.knowledgegraph.appservice.IKgEntityAppService;
|
||||
import com.healthlink.his.web.knowledgegraph.dto.*;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@Service
|
||||
public class KgEntityAppServiceImpl implements IKgEntityAppService {
|
||||
|
||||
private final IKgDiseaseService kgDiseaseService;
|
||||
private final IKgSymptomService kgSymptomService;
|
||||
private final IKgDrugService kgDrugService;
|
||||
private final IKgExaminationService kgExaminationService;
|
||||
|
||||
public KgEntityAppServiceImpl(IKgDiseaseService kgDiseaseService,
|
||||
IKgSymptomService kgSymptomService,
|
||||
IKgDrugService kgDrugService,
|
||||
IKgExaminationService kgExaminationService) {
|
||||
this.kgDiseaseService = kgDiseaseService;
|
||||
this.kgSymptomService = kgSymptomService;
|
||||
this.kgDrugService = kgDrugService;
|
||||
this.kgExaminationService = kgExaminationService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean addDisease(KgDiseaseDto dto) {
|
||||
KgDisease entity = new KgDisease();
|
||||
BeanUtils.copyProperties(dto, entity);
|
||||
return kgDiseaseService.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateDisease(KgDiseaseDto dto) {
|
||||
if (dto.getId() == null) {
|
||||
return false;
|
||||
}
|
||||
KgDisease entity = new KgDisease();
|
||||
BeanUtils.copyProperties(dto, entity);
|
||||
return kgDiseaseService.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteDisease(Long id) {
|
||||
return kgDiseaseService.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KgDiseaseDto getDiseaseById(Long id) {
|
||||
KgDisease entity = kgDiseaseService.getById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
KgDiseaseDto dto = new KgDiseaseDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<KgDiseaseDto> pageDisease(String keyword, String category, Integer pageNo, Integer pageSize) {
|
||||
Page<KgDisease> page = new Page<>(pageNo, pageSize);
|
||||
LambdaQueryWrapper<KgDisease> wrapper = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.hasText(keyword)) {
|
||||
wrapper.and(w -> w.like(KgDisease::getDiseaseName, keyword)
|
||||
.or().like(KgDisease::getDiseaseCode, keyword));
|
||||
}
|
||||
if (StringUtils.hasText(category)) {
|
||||
wrapper.eq(KgDisease::getCategory, category);
|
||||
}
|
||||
wrapper.orderByDesc(KgDisease::getCreateTime);
|
||||
Page<KgDisease> result = kgDiseaseService.page(page, wrapper);
|
||||
return result.convert(entity -> {
|
||||
KgDiseaseDto dto = new KgDiseaseDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean addSymptom(KgSymptomDto dto) {
|
||||
KgSymptom entity = new KgSymptom();
|
||||
BeanUtils.copyProperties(dto, entity);
|
||||
return kgSymptomService.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateSymptom(KgSymptomDto dto) {
|
||||
if (dto.getId() == null) {
|
||||
return false;
|
||||
}
|
||||
KgSymptom entity = new KgSymptom();
|
||||
BeanUtils.copyProperties(dto, entity);
|
||||
return kgSymptomService.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteSymptom(Long id) {
|
||||
return kgSymptomService.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KgSymptomDto getSymptomById(Long id) {
|
||||
KgSymptom entity = kgSymptomService.getById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
KgSymptomDto dto = new KgSymptomDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<KgSymptomDto> pageSymptom(String keyword, String symptomType, Integer pageNo, Integer pageSize) {
|
||||
Page<KgSymptom> page = new Page<>(pageNo, pageSize);
|
||||
LambdaQueryWrapper<KgSymptom> wrapper = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.hasText(keyword)) {
|
||||
wrapper.and(w -> w.like(KgSymptom::getSymptomName, keyword)
|
||||
.or().like(KgSymptom::getSymptomCode, keyword));
|
||||
}
|
||||
if (StringUtils.hasText(symptomType)) {
|
||||
wrapper.eq(KgSymptom::getSymptomType, symptomType);
|
||||
}
|
||||
wrapper.orderByDesc(KgSymptom::getCreateTime);
|
||||
Page<KgSymptom> result = kgSymptomService.page(page, wrapper);
|
||||
return result.convert(entity -> {
|
||||
KgSymptomDto dto = new KgSymptomDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean addDrug(KgDrugDto dto) {
|
||||
KgDrug entity = new KgDrug();
|
||||
BeanUtils.copyProperties(dto, entity);
|
||||
return kgDrugService.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateDrug(KgDrugDto dto) {
|
||||
if (dto.getId() == null) {
|
||||
return false;
|
||||
}
|
||||
KgDrug entity = new KgDrug();
|
||||
BeanUtils.copyProperties(dto, entity);
|
||||
return kgDrugService.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteDrug(Long id) {
|
||||
return kgDrugService.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KgDrugDto getDrugById(Long id) {
|
||||
KgDrug entity = kgDrugService.getById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
KgDrugDto dto = new KgDrugDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<KgDrugDto> pageDrug(String keyword, String category, Integer pageNo, Integer pageSize) {
|
||||
Page<KgDrug> page = new Page<>(pageNo, pageSize);
|
||||
LambdaQueryWrapper<KgDrug> wrapper = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.hasText(keyword)) {
|
||||
wrapper.and(w -> w.like(KgDrug::getDrugName, keyword)
|
||||
.or().like(KgDrug::getDrugCode, keyword));
|
||||
}
|
||||
if (StringUtils.hasText(category)) {
|
||||
wrapper.eq(KgDrug::getCategory, category);
|
||||
}
|
||||
wrapper.orderByDesc(KgDrug::getCreateTime);
|
||||
Page<KgDrug> result = kgDrugService.page(page, wrapper);
|
||||
return result.convert(entity -> {
|
||||
KgDrugDto dto = new KgDrugDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean addExamination(KgExaminationDto dto) {
|
||||
KgExamination entity = new KgExamination();
|
||||
BeanUtils.copyProperties(dto, entity);
|
||||
return kgExaminationService.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateExamination(KgExaminationDto dto) {
|
||||
if (dto.getId() == null) {
|
||||
return false;
|
||||
}
|
||||
KgExamination entity = new KgExamination();
|
||||
BeanUtils.copyProperties(dto, entity);
|
||||
return kgExaminationService.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteExamination(Long id) {
|
||||
return kgExaminationService.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KgExaminationDto getExaminationById(Long id) {
|
||||
KgExamination entity = kgExaminationService.getById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
KgExaminationDto dto = new KgExaminationDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<KgExaminationDto> pageExamination(String keyword, String examType, Integer pageNo, Integer pageSize) {
|
||||
Page<KgExamination> page = new Page<>(pageNo, pageSize);
|
||||
LambdaQueryWrapper<KgExamination> wrapper = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.hasText(keyword)) {
|
||||
wrapper.and(w -> w.like(KgExamination::getExamName, keyword)
|
||||
.or().like(KgExamination::getExamCode, keyword));
|
||||
}
|
||||
if (StringUtils.hasText(examType)) {
|
||||
wrapper.eq(KgExamination::getExamType, examType);
|
||||
}
|
||||
wrapper.orderByDesc(KgExamination::getCreateTime);
|
||||
Page<KgExamination> result = kgExaminationService.page(page, wrapper);
|
||||
return result.convert(entity -> {
|
||||
KgExaminationDto dto = new KgExaminationDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
package com.healthlink.his.web.knowledgegraph.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.healthlink.his.web.knowledgegraph.appservice.IKgEntityAppService;
|
||||
import com.healthlink.his.web.knowledgegraph.dto.*;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Slf4j
|
||||
@Tag(name = "知识图谱-实体管理")
|
||||
@RestController
|
||||
@RequestMapping("/knowledgegraph")
|
||||
public class KgEntityController {
|
||||
|
||||
private final IKgEntityAppService kgEntityAppService;
|
||||
|
||||
public KgEntityController(IKgEntityAppService kgEntityAppService) {
|
||||
this.kgEntityAppService = kgEntityAppService;
|
||||
}
|
||||
|
||||
@Operation(summary = "创建疾病")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@PostMapping("/disease")
|
||||
public R<String> addDisease(@RequestBody KgDiseaseDto dto) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.addDisease(dto);
|
||||
return result ? R.ok("创建成功") : R.fail("创建失败");
|
||||
} catch (Exception e) {
|
||||
log.error("创建疾病失败", e);
|
||||
return R.fail("创建疾病失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "疾病分页查询")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
|
||||
@GetMapping("/disease/page")
|
||||
public R<IPage<KgDiseaseDto>> pageDisease(
|
||||
@Parameter(description = "关键词") @RequestParam(required = false) String keyword,
|
||||
@Parameter(description = "分类") @RequestParam(required = false) String category,
|
||||
@Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNo,
|
||||
@Parameter(description = "每页数量") @RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
try {
|
||||
IPage<KgDiseaseDto> page = kgEntityAppService.pageDisease(keyword, category, pageNo, pageSize);
|
||||
return R.ok(page);
|
||||
} catch (Exception e) {
|
||||
log.error("查询疾病列表失败", e);
|
||||
return R.fail("查询疾病列表失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "更新疾病")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@PutMapping("/disease")
|
||||
public R<String> updateDisease(@RequestBody KgDiseaseDto dto) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.updateDisease(dto);
|
||||
return result ? R.ok("更新成功") : R.fail("更新失败");
|
||||
} catch (Exception e) {
|
||||
log.error("更新疾病失败", e);
|
||||
return R.fail("更新疾病失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "删除疾病")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@DeleteMapping("/disease/{id}")
|
||||
public R<String> deleteDisease(@PathVariable Long id) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.deleteDisease(id);
|
||||
return result ? R.ok("删除成功") : R.fail("删除失败");
|
||||
} catch (Exception e) {
|
||||
log.error("删除疾病失败", e);
|
||||
return R.fail("删除疾病失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "疾病详情")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
|
||||
@GetMapping("/disease/{id}")
|
||||
public R<KgDiseaseDto> getDiseaseById(@PathVariable Long id) {
|
||||
try {
|
||||
KgDiseaseDto dto = kgEntityAppService.getDiseaseById(id);
|
||||
return dto != null ? R.ok(dto) : R.fail("未找到疾病信息");
|
||||
} catch (Exception e) {
|
||||
log.error("获取疾病详情失败", e);
|
||||
return R.fail("获取疾病详情失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "创建症状")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@PostMapping("/symptom")
|
||||
public R<String> addSymptom(@RequestBody KgSymptomDto dto) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.addSymptom(dto);
|
||||
return result ? R.ok("创建成功") : R.fail("创建失败");
|
||||
} catch (Exception e) {
|
||||
log.error("创建症状失败", e);
|
||||
return R.fail("创建症状失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "症状分页查询")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
|
||||
@GetMapping("/symptom/page")
|
||||
public R<IPage<KgSymptomDto>> pageSymptom(
|
||||
@Parameter(description = "关键词") @RequestParam(required = false) String keyword,
|
||||
@Parameter(description = "症状类型") @RequestParam(required = false) String symptomType,
|
||||
@Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNo,
|
||||
@Parameter(description = "每页数量") @RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
try {
|
||||
IPage<KgSymptomDto> page = kgEntityAppService.pageSymptom(keyword, symptomType, pageNo, pageSize);
|
||||
return R.ok(page);
|
||||
} catch (Exception e) {
|
||||
log.error("查询症状列表失败", e);
|
||||
return R.fail("查询症状列表失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "更新症状")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@PutMapping("/symptom")
|
||||
public R<String> updateSymptom(@RequestBody KgSymptomDto dto) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.updateSymptom(dto);
|
||||
return result ? R.ok("更新成功") : R.fail("更新失败");
|
||||
} catch (Exception e) {
|
||||
log.error("更新症状失败", e);
|
||||
return R.fail("更新症状失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "删除症状")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@DeleteMapping("/symptom/{id}")
|
||||
public R<String> deleteSymptom(@PathVariable Long id) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.deleteSymptom(id);
|
||||
return result ? R.ok("删除成功") : R.fail("删除失败");
|
||||
} catch (Exception e) {
|
||||
log.error("删除症状失败", e);
|
||||
return R.fail("删除症状失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "症状详情")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
|
||||
@GetMapping("/symptom/{id}")
|
||||
public R<KgSymptomDto> getSymptomById(@PathVariable Long id) {
|
||||
try {
|
||||
KgSymptomDto dto = kgEntityAppService.getSymptomById(id);
|
||||
return dto != null ? R.ok(dto) : R.fail("未找到症状信息");
|
||||
} catch (Exception e) {
|
||||
log.error("获取症状详情失败", e);
|
||||
return R.fail("获取症状详情失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "创建药物")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@PostMapping("/drug")
|
||||
public R<String> addDrug(@RequestBody KgDrugDto dto) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.addDrug(dto);
|
||||
return result ? R.ok("创建成功") : R.fail("创建失败");
|
||||
} catch (Exception e) {
|
||||
log.error("创建药物失败", e);
|
||||
return R.fail("创建药物失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "药物分页查询")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
|
||||
@GetMapping("/drug/page")
|
||||
public R<IPage<KgDrugDto>> pageDrug(
|
||||
@Parameter(description = "关键词") @RequestParam(required = false) String keyword,
|
||||
@Parameter(description = "分类") @RequestParam(required = false) String category,
|
||||
@Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNo,
|
||||
@Parameter(description = "每页数量") @RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
try {
|
||||
IPage<KgDrugDto> page = kgEntityAppService.pageDrug(keyword, category, pageNo, pageSize);
|
||||
return R.ok(page);
|
||||
} catch (Exception e) {
|
||||
log.error("查询药物列表失败", e);
|
||||
return R.fail("查询药物列表失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "更新药物")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@PutMapping("/drug")
|
||||
public R<String> updateDrug(@RequestBody KgDrugDto dto) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.updateDrug(dto);
|
||||
return result ? R.ok("更新成功") : R.fail("更新失败");
|
||||
} catch (Exception e) {
|
||||
log.error("更新药物失败", e);
|
||||
return R.fail("更新药物失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "删除药物")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@DeleteMapping("/drug/{id}")
|
||||
public R<String> deleteDrug(@PathVariable Long id) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.deleteDrug(id);
|
||||
return result ? R.ok("删除成功") : R.fail("删除失败");
|
||||
} catch (Exception e) {
|
||||
log.error("删除药物失败", e);
|
||||
return R.fail("删除药物失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "药物详情")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
|
||||
@GetMapping("/drug/{id}")
|
||||
public R<KgDrugDto> getDrugById(@PathVariable Long id) {
|
||||
try {
|
||||
KgDrugDto dto = kgEntityAppService.getDrugById(id);
|
||||
return dto != null ? R.ok(dto) : R.fail("未找到药物信息");
|
||||
} catch (Exception e) {
|
||||
log.error("获取药物详情失败", e);
|
||||
return R.fail("获取药物详情失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "创建检查")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@PostMapping("/examination")
|
||||
public R<String> addExamination(@RequestBody KgExaminationDto dto) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.addExamination(dto);
|
||||
return result ? R.ok("创建成功") : R.fail("创建失败");
|
||||
} catch (Exception e) {
|
||||
log.error("创建检查失败", e);
|
||||
return R.fail("创建检查失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "检查分页查询")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
|
||||
@GetMapping("/examination/page")
|
||||
public R<IPage<KgExaminationDto>> pageExamination(
|
||||
@Parameter(description = "关键词") @RequestParam(required = false) String keyword,
|
||||
@Parameter(description = "检查类型") @RequestParam(required = false) String examType,
|
||||
@Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNo,
|
||||
@Parameter(description = "每页数量") @RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
try {
|
||||
IPage<KgExaminationDto> page = kgEntityAppService.pageExamination(keyword, examType, pageNo, pageSize);
|
||||
return R.ok(page);
|
||||
} catch (Exception e) {
|
||||
log.error("查询检查列表失败", e);
|
||||
return R.fail("查询检查列表失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "更新检查")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@PutMapping("/examination")
|
||||
public R<String> updateExamination(@RequestBody KgExaminationDto dto) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.updateExamination(dto);
|
||||
return result ? R.ok("更新成功") : R.fail("更新失败");
|
||||
} catch (Exception e) {
|
||||
log.error("更新检查失败", e);
|
||||
return R.fail("更新检查失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "删除检查")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
|
||||
@DeleteMapping("/examination/{id}")
|
||||
public R<String> deleteExamination(@PathVariable Long id) {
|
||||
try {
|
||||
Boolean result = kgEntityAppService.deleteExamination(id);
|
||||
return result ? R.ok("删除成功") : R.fail("删除失败");
|
||||
} catch (Exception e) {
|
||||
log.error("删除检查失败", e);
|
||||
return R.fail("删除检查失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "检查详情")
|
||||
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
|
||||
@GetMapping("/examination/{id}")
|
||||
public R<KgExaminationDto> getExaminationById(@PathVariable Long id) {
|
||||
try {
|
||||
KgExaminationDto dto = kgEntityAppService.getExaminationById(id);
|
||||
return dto != null ? R.ok(dto) : R.fail("未找到检查信息");
|
||||
} catch (Exception e) {
|
||||
log.error("获取检查详情失败", e);
|
||||
return R.fail("获取检查详情失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.healthlink.his.web.knowledgegraph.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class KgDiseaseDto implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String diseaseCode;
|
||||
|
||||
private String diseaseName;
|
||||
|
||||
private String category;
|
||||
|
||||
private String department;
|
||||
|
||||
private String severityLevel;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.healthlink.his.web.knowledgegraph.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class KgDrugDto implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String drugCode;
|
||||
|
||||
private String drugName;
|
||||
|
||||
private String genericName;
|
||||
|
||||
private String category;
|
||||
|
||||
private String dosageForm;
|
||||
|
||||
private String contraindications;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.healthlink.his.web.knowledgegraph.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class KgExaminationDto implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String examCode;
|
||||
|
||||
private String examName;
|
||||
|
||||
private String examType;
|
||||
|
||||
private String department;
|
||||
|
||||
private String referenceRange;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.healthlink.his.web.knowledgegraph.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class KgSymptomDto implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String symptomCode;
|
||||
|
||||
private String symptomName;
|
||||
|
||||
private String bodyPart;
|
||||
|
||||
private String symptomType;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.healthlink.his.knowledgegraph.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("kg_disease")
|
||||
public class KgDisease extends HisBaseEntity {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String diseaseCode;
|
||||
|
||||
private String diseaseName;
|
||||
|
||||
private String category;
|
||||
|
||||
private String department;
|
||||
|
||||
private String severityLevel;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.healthlink.his.knowledgegraph.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("kg_drug")
|
||||
public class KgDrug extends HisBaseEntity {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String drugCode;
|
||||
|
||||
private String drugName;
|
||||
|
||||
private String genericName;
|
||||
|
||||
private String category;
|
||||
|
||||
private String dosageForm;
|
||||
|
||||
private String contraindications;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.healthlink.his.knowledgegraph.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("kg_examination")
|
||||
public class KgExamination extends HisBaseEntity {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String examCode;
|
||||
|
||||
private String examName;
|
||||
|
||||
private String examType;
|
||||
|
||||
private String department;
|
||||
|
||||
private String referenceRange;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.healthlink.his.knowledgegraph.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("kg_symptom")
|
||||
public class KgSymptom extends HisBaseEntity {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String symptomCode;
|
||||
|
||||
private String symptomName;
|
||||
|
||||
private String bodyPart;
|
||||
|
||||
private String symptomType;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.knowledgegraph.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgDisease;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface KgDiseaseMapper extends BaseMapper<KgDisease> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.knowledgegraph.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgDrug;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface KgDrugMapper extends BaseMapper<KgDrug> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.knowledgegraph.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgExamination;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface KgExaminationMapper extends BaseMapper<KgExamination> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.knowledgegraph.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgSymptom;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface KgSymptomMapper extends BaseMapper<KgSymptom> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.knowledgegraph.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgDisease;
|
||||
|
||||
public interface IKgDiseaseService extends IService<KgDisease> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.knowledgegraph.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgDrug;
|
||||
|
||||
public interface IKgDrugService extends IService<KgDrug> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.knowledgegraph.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgExamination;
|
||||
|
||||
public interface IKgExaminationService extends IService<KgExamination> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.knowledgegraph.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgSymptom;
|
||||
|
||||
public interface IKgSymptomService extends IService<KgSymptom> {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.knowledgegraph.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgDisease;
|
||||
import com.healthlink.his.knowledgegraph.mapper.KgDiseaseMapper;
|
||||
import com.healthlink.his.knowledgegraph.service.IKgDiseaseService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class KgDiseaseServiceImpl extends ServiceImpl<KgDiseaseMapper, KgDisease> implements IKgDiseaseService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.knowledgegraph.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgDrug;
|
||||
import com.healthlink.his.knowledgegraph.mapper.KgDrugMapper;
|
||||
import com.healthlink.his.knowledgegraph.service.IKgDrugService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class KgDrugServiceImpl extends ServiceImpl<KgDrugMapper, KgDrug> implements IKgDrugService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.knowledgegraph.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgExamination;
|
||||
import com.healthlink.his.knowledgegraph.mapper.KgExaminationMapper;
|
||||
import com.healthlink.his.knowledgegraph.service.IKgExaminationService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class KgExaminationServiceImpl extends ServiceImpl<KgExaminationMapper, KgExamination> implements IKgExaminationService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.knowledgegraph.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.knowledgegraph.domain.KgSymptom;
|
||||
import com.healthlink.his.knowledgegraph.mapper.KgSymptomMapper;
|
||||
import com.healthlink.his.knowledgegraph.service.IKgSymptomService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class KgSymptomServiceImpl extends ServiceImpl<KgSymptomMapper, KgSymptom> implements IKgSymptomService {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.healthlink.his.knowledgegraph.mapper.KgDiseaseMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.healthlink.his.knowledgegraph.mapper.KgDrugMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.healthlink.his.knowledgegraph.mapper.KgExaminationMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.healthlink.his.knowledgegraph.mapper.KgSymptomMapper">
|
||||
|
||||
</mapper>
|
||||
105
healthlink-his-ui/src/api/knowledgegraph/api.js
Normal file
105
healthlink-his-ui/src/api/knowledgegraph/api.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function addDisease(data) {
|
||||
return request({ url: '/knowledgegraph/disease', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getDiseasePage(params) {
|
||||
return request({ url: '/knowledgegraph/disease/page', method: 'get', params })
|
||||
}
|
||||
|
||||
export function getDiseaseById(id) {
|
||||
return request({ url: '/knowledgegraph/disease/' + id, method: 'get' })
|
||||
}
|
||||
|
||||
export function updateDisease(data) {
|
||||
return request({ url: '/knowledgegraph/disease', method: 'put', data })
|
||||
}
|
||||
|
||||
export function deleteDisease(id) {
|
||||
return request({ url: '/knowledgegraph/disease/' + id, method: 'delete' })
|
||||
}
|
||||
|
||||
export function addSymptom(data) {
|
||||
return request({ url: '/knowledgegraph/symptom', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getSymptomPage(params) {
|
||||
return request({ url: '/knowledgegraph/symptom/page', method: 'get', params })
|
||||
}
|
||||
|
||||
export function getSymptomById(id) {
|
||||
return request({ url: '/knowledgegraph/symptom/' + id, method: 'get' })
|
||||
}
|
||||
|
||||
export function updateSymptom(data) {
|
||||
return request({ url: '/knowledgegraph/symptom', method: 'put', data })
|
||||
}
|
||||
|
||||
export function deleteSymptom(id) {
|
||||
return request({ url: '/knowledgegraph/symptom/' + id, method: 'delete' })
|
||||
}
|
||||
|
||||
export function addDrug(data) {
|
||||
return request({ url: '/knowledgegraph/drug', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getDrugPage(params) {
|
||||
return request({ url: '/knowledgegraph/drug/page', method: 'get', params })
|
||||
}
|
||||
|
||||
export function getDrugById(id) {
|
||||
return request({ url: '/knowledgegraph/drug/' + id, method: 'get' })
|
||||
}
|
||||
|
||||
export function updateDrug(data) {
|
||||
return request({ url: '/knowledgegraph/drug', method: 'put', data })
|
||||
}
|
||||
|
||||
export function deleteDrug(id) {
|
||||
return request({ url: '/knowledgegraph/drug/' + id, method: 'delete' })
|
||||
}
|
||||
|
||||
export function addExamination(data) {
|
||||
return request({ url: '/knowledgegraph/examination', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getExaminationPage(params) {
|
||||
return request({ url: '/knowledgegraph/examination/page', method: 'get', params })
|
||||
}
|
||||
|
||||
export function getExaminationById(id) {
|
||||
return request({ url: '/knowledgegraph/examination/' + id, method: 'get' })
|
||||
}
|
||||
|
||||
export function updateExamination(data) {
|
||||
return request({ url: '/knowledgegraph/examination', method: 'put', data })
|
||||
}
|
||||
|
||||
export function deleteExamination(id) {
|
||||
return request({ url: '/knowledgegraph/examination/' + id, method: 'delete' })
|
||||
}
|
||||
|
||||
export function createRelation(data) {
|
||||
return request({ url: '/knowledgegraph/relation', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getRelationPage(params) {
|
||||
return request({ url: '/knowledgegraph/relation/page', method: 'get', params })
|
||||
}
|
||||
|
||||
export function getRelationGraph(entityType, entityId) {
|
||||
return request({ url: `/knowledgegraph/relation/graph/${entityType}/${entityId}`, method: 'get' })
|
||||
}
|
||||
|
||||
export function createPathway(data) {
|
||||
return request({ url: '/knowledgegraph/pathway', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getPathwayPage(params) {
|
||||
return request({ url: '/knowledgegraph/pathway/page', method: 'get', params })
|
||||
}
|
||||
|
||||
export function getPathwaySteps(id) {
|
||||
return request({ url: `/knowledgegraph/pathway/${id}/steps`, method: 'get' })
|
||||
}
|
||||
94
healthlink-his-ui/src/views/knowledgegraph/DiseaseForm.vue
Normal file
94
healthlink-his-ui/src/views/knowledgegraph/DiseaseForm.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<el-dialog :model-value="visible" :title="form.id ? '编辑疾病' : '新增疾病'" width="600px" @close="handleClose">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="疾病编码" prop="diseaseCode">
|
||||
<el-input v-model="form.diseaseCode" placeholder="请输入疾病编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病名称" prop="diseaseName">
|
||||
<el-input v-model="form.diseaseName" placeholder="请输入疾病名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病分类" prop="category">
|
||||
<el-input v-model="form.category" placeholder="请输入疾病分类" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属科室" prop="department">
|
||||
<el-input v-model="form.department" placeholder="请输入所属科室" />
|
||||
</el-form-item>
|
||||
<el-form-item label="严重等级" prop="severityLevel">
|
||||
<el-select v-model="form.severityLevel" placeholder="请选择严重等级" clearable style="width:100%">
|
||||
<el-option label="轻度" value="MILD" />
|
||||
<el-option label="中度" value="MODERATE" />
|
||||
<el-option label="重度" value="SEVERE" />
|
||||
<el-option label="危重" value="CRITICAL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { addDisease, updateDisease } from '@/api/knowledgegraph/api'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const props = defineProps({
|
||||
visible: Boolean,
|
||||
data: { type: Object, default: () => ({}) }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:visible', 'success'])
|
||||
|
||||
const formRef = ref(null)
|
||||
const submitting = ref(false)
|
||||
|
||||
const form = reactive({
|
||||
id: undefined,
|
||||
diseaseCode: '',
|
||||
diseaseName: '',
|
||||
category: '',
|
||||
department: '',
|
||||
severityLevel: ''
|
||||
})
|
||||
|
||||
const rules = {
|
||||
diseaseCode: [{ required: true, message: '请输入疾病编码', trigger: 'blur' }],
|
||||
diseaseName: [{ required: true, message: '请输入疾病名称', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
watch(() => props.visible, (val) => {
|
||||
if (val && props.data && props.data.id) {
|
||||
Object.assign(form, props.data)
|
||||
} else {
|
||||
Object.assign(form, { id: undefined, diseaseCode: '', diseaseName: '', category: '', department: '', severityLevel: '' })
|
||||
}
|
||||
})
|
||||
|
||||
function handleClose() {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
submitting.value = true
|
||||
try {
|
||||
if (form.id) {
|
||||
await updateDisease({ ...form })
|
||||
ElMessage.success('更新成功')
|
||||
} else {
|
||||
await addDisease({ ...form })
|
||||
ElMessage.success('创建成功')
|
||||
}
|
||||
emit('update:visible', false)
|
||||
emit('success')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
121
healthlink-his-ui/src/views/knowledgegraph/DiseaseList.vue
Normal file
121
healthlink-his-ui/src/views/knowledgegraph/DiseaseList.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="关键词" prop="keyword">
|
||||
<el-input v-model="queryParams.keyword" placeholder="疾病名称/编码" clearable style="width:200px" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病分类" prop="category">
|
||||
<el-input v-model="queryParams.category" placeholder="分类" clearable style="width:160px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="tableData" border stripe>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="diseaseCode" label="疾病编码" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="diseaseName" label="疾病名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="category" label="疾病分类" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="department" label="所属科室" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="severityLevel" label="严重等级" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.severityLevel" :type="severityType(row.severityLevel)" size="small">
|
||||
{{ severityLabel(row.severityLevel) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" icon="Edit" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button link type="danger" icon="Delete" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
|
||||
|
||||
<DiseaseForm v-model:visible="showForm" :data="currentRow" @success="getList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="KgDiseaseList">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { getDiseasePage, deleteDisease } from '@/api/knowledgegraph/api'
|
||||
import DiseaseForm from './DiseaseForm.vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const tableData = ref([])
|
||||
const loading = ref(false)
|
||||
const showSearch = ref(true)
|
||||
const total = ref(0)
|
||||
const showForm = ref(false)
|
||||
const currentRow = ref({})
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
keyword: '',
|
||||
category: ''
|
||||
})
|
||||
|
||||
const severityMap = { MILD: '轻度', MODERATE: '中度', SEVERE: '重度', CRITICAL: '危重' }
|
||||
const severityTypeMap = { MILD: 'info', MODERATE: '', SEVERE: 'warning', CRITICAL: 'danger' }
|
||||
const severityLabel = (v) => severityMap[v] || v
|
||||
const severityType = (v) => severityTypeMap[v] || 'info'
|
||||
|
||||
async function getList() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getDiseasePage(queryParams)
|
||||
if (res.code === 200) {
|
||||
tableData.value = res.data?.records || []
|
||||
total.value = res.data?.total || 0
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleQuery() {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
function resetQuery() {
|
||||
queryParams.keyword = ''
|
||||
queryParams.category = ''
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
currentRow.value = {}
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function handleEdit(row) {
|
||||
currentRow.value = { ...row }
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
ElMessageBox.confirm('确认删除该疾病吗?', '提示', { type: 'warning' })
|
||||
.then(() => deleteDisease(row.id))
|
||||
.then(() => {
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => getList())
|
||||
</script>
|
||||
146
healthlink-his-ui/src/views/knowledgegraph/DrugList.vue
Normal file
146
healthlink-his-ui/src/views/knowledgegraph/DrugList.vue
Normal file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="关键词" prop="keyword">
|
||||
<el-input v-model="queryParams.keyword" placeholder="药物名称/编码" clearable style="width:200px" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="药物分类" prop="category">
|
||||
<el-input v-model="queryParams.category" placeholder="分类" clearable style="width:160px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="tableData" border stripe>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="drugCode" label="药物编码" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="drugName" label="药物名称" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="genericName" label="通用名" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="category" label="药物分类" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="dosageForm" label="剂型" width="100" align="center" />
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" icon="Edit" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button link type="danger" icon="Delete" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
|
||||
|
||||
<el-dialog v-model="showForm" :title="form.id ? '编辑药物' : '新增药物'" width="600px" @close="resetForm">
|
||||
<el-form ref="formRef" :model="form" :rules="formRules" label-width="90px">
|
||||
<el-form-item label="药物编码" prop="drugCode">
|
||||
<el-input v-model="form.drugCode" placeholder="请输入药物编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="药物名称" prop="drugName">
|
||||
<el-input v-model="form.drugName" placeholder="请输入药物名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="通用名" prop="genericName">
|
||||
<el-input v-model="form.genericName" placeholder="请输入通用名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="药物分类" prop="category">
|
||||
<el-input v-model="form.category" placeholder="请输入药物分类" />
|
||||
</el-form-item>
|
||||
<el-form-item label="剂型" prop="dosageForm">
|
||||
<el-input v-model="form.dosageForm" placeholder="请输入剂型" />
|
||||
</el-form-item>
|
||||
<el-form-item label="禁忌症" prop="contraindications">
|
||||
<el-input v-model="form.contraindications" type="textarea" :rows="3" placeholder="请输入禁忌症" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showForm = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="KgDrugList">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { getDrugPage, addDrug, updateDrug, deleteDrug } from '@/api/knowledgegraph/api'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const tableData = ref([])
|
||||
const loading = ref(false)
|
||||
const showSearch = ref(true)
|
||||
const total = ref(0)
|
||||
const showForm = ref(false)
|
||||
const submitting = ref(false)
|
||||
const formRef = ref(null)
|
||||
|
||||
const queryParams = reactive({ pageNo: 1, pageSize: 10, keyword: '', category: '' })
|
||||
const form = reactive({ id: undefined, drugCode: '', drugName: '', genericName: '', category: '', dosageForm: '', contraindications: '' })
|
||||
const formRules = {
|
||||
drugCode: [{ required: true, message: '请输入药物编码', trigger: 'blur' }],
|
||||
drugName: [{ required: true, message: '请输入药物名称', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
async function getList() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getDrugPage(queryParams)
|
||||
if (res.code === 200) {
|
||||
tableData.value = res.data?.records || []
|
||||
total.value = res.data?.total || 0
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleQuery() { queryParams.pageNo = 1; getList() }
|
||||
function resetQuery() { queryParams.keyword = ''; queryParams.category = ''; handleQuery() }
|
||||
|
||||
function handleAdd() {
|
||||
Object.assign(form, { id: undefined, drugCode: '', drugName: '', genericName: '', category: '', dosageForm: '', contraindications: '' })
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function handleEdit(row) {
|
||||
Object.assign(form, row)
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
ElMessageBox.confirm('确认删除该药物吗?', '提示', { type: 'warning' })
|
||||
.then(() => deleteDrug(row.id))
|
||||
.then(() => { ElMessage.success('删除成功'); getList() })
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
try { await formRef.value.validate() } catch { return }
|
||||
submitting.value = true
|
||||
try {
|
||||
if (form.id) {
|
||||
await updateDrug({ ...form })
|
||||
ElMessage.success('更新成功')
|
||||
} else {
|
||||
await addDrug({ ...form })
|
||||
ElMessage.success('创建成功')
|
||||
}
|
||||
showForm.value = false
|
||||
getList()
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => getList())
|
||||
</script>
|
||||
143
healthlink-his-ui/src/views/knowledgegraph/ExaminationList.vue
Normal file
143
healthlink-his-ui/src/views/knowledgegraph/ExaminationList.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="关键词" prop="keyword">
|
||||
<el-input v-model="queryParams.keyword" placeholder="检查名称/编码" clearable style="width:200px" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检查类型" prop="examType">
|
||||
<el-input v-model="queryParams.examType" placeholder="检查类型" clearable style="width:160px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="tableData" border stripe>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="examCode" label="检查编码" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="examName" label="检查名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="examType" label="检查类型" width="120" align="center" />
|
||||
<el-table-column prop="department" label="所属科室" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="referenceRange" label="参考范围" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" icon="Edit" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button link type="danger" icon="Delete" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
|
||||
|
||||
<el-dialog v-model="showForm" :title="form.id ? '编辑检查' : '新增检查'" width="600px" @close="resetForm">
|
||||
<el-form ref="formRef" :model="form" :rules="formRules" label-width="90px">
|
||||
<el-form-item label="检查编码" prop="examCode">
|
||||
<el-input v-model="form.examCode" placeholder="请输入检查编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检查名称" prop="examName">
|
||||
<el-input v-model="form.examName" placeholder="请输入检查名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检查类型" prop="examType">
|
||||
<el-input v-model="form.examType" placeholder="请输入检查类型" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属科室" prop="department">
|
||||
<el-input v-model="form.department" placeholder="请输入所属科室" />
|
||||
</el-form-item>
|
||||
<el-form-item label="参考范围" prop="referenceRange">
|
||||
<el-input v-model="form.referenceRange" placeholder="请输入参考范围" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showForm = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="KgExaminationList">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { getExaminationPage, addExamination, updateExamination, deleteExamination } from '@/api/knowledgegraph/api'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const tableData = ref([])
|
||||
const loading = ref(false)
|
||||
const showSearch = ref(true)
|
||||
const total = ref(0)
|
||||
const showForm = ref(false)
|
||||
const submitting = ref(false)
|
||||
const formRef = ref(null)
|
||||
|
||||
const queryParams = reactive({ pageNo: 1, pageSize: 10, keyword: '', examType: '' })
|
||||
const form = reactive({ id: undefined, examCode: '', examName: '', examType: '', department: '', referenceRange: '' })
|
||||
const formRules = {
|
||||
examCode: [{ required: true, message: '请输入检查编码', trigger: 'blur' }],
|
||||
examName: [{ required: true, message: '请输入检查名称', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
async function getList() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getExaminationPage(queryParams)
|
||||
if (res.code === 200) {
|
||||
tableData.value = res.data?.records || []
|
||||
total.value = res.data?.total || 0
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleQuery() { queryParams.pageNo = 1; getList() }
|
||||
function resetQuery() { queryParams.keyword = ''; queryParams.examType = ''; handleQuery() }
|
||||
|
||||
function handleAdd() {
|
||||
Object.assign(form, { id: undefined, examCode: '', examName: '', examType: '', department: '', referenceRange: '' })
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function handleEdit(row) {
|
||||
Object.assign(form, row)
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
ElMessageBox.confirm('确认删除该检查吗?', '提示', { type: 'warning' })
|
||||
.then(() => deleteExamination(row.id))
|
||||
.then(() => { ElMessage.success('删除成功'); getList() })
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
try { await formRef.value.validate() } catch { return }
|
||||
submitting.value = true
|
||||
try {
|
||||
if (form.id) {
|
||||
await updateExamination({ ...form })
|
||||
ElMessage.success('更新成功')
|
||||
} else {
|
||||
await addExamination({ ...form })
|
||||
ElMessage.success('创建成功')
|
||||
}
|
||||
showForm.value = false
|
||||
getList()
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => getList())
|
||||
</script>
|
||||
178
healthlink-his-ui/src/views/knowledgegraph/KnowledgeGraph.vue
Normal file
178
healthlink-his-ui/src/views/knowledgegraph/KnowledgeGraph.vue
Normal file
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<div style="padding:16px">
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
|
||||
<span style="font-size:18px;font-weight:bold">知识图谱</span>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" style="margin-bottom:16px">
|
||||
<el-form inline>
|
||||
<el-form-item label="实体类型">
|
||||
<el-select v-model="entityType" placeholder="请选择" style="width:130px">
|
||||
<el-option label="疾病" value="disease" />
|
||||
<el-option label="症状" value="symptom" />
|
||||
<el-option label="药物" value="drug" />
|
||||
<el-option label="检查" value="exam" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="实体ID">
|
||||
<el-input v-model="entityId" placeholder="请输入实体ID" style="width:200px" @keyup.enter="loadGraph" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadGraph" :loading="loading">加载图谱</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never">
|
||||
<div ref="chartRef" style="width:100%;height:600px" />
|
||||
<el-empty v-if="!hasData && !loading" description="请输入实体类型和ID,点击加载图谱" />
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="showDetail" :title="detailTitle" width="500px" append-to-body>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="实体类型">{{ detailNode.entityType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="实体ID">{{ detailNode.entityId }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-if="detailRelations.length" style="margin-top:16px">
|
||||
<div style="font-weight:bold;margin-bottom:8px">关联关系</div>
|
||||
<el-table :data="detailRelations" border size="small">
|
||||
<el-table-column prop="relationType" label="关系" width="120" />
|
||||
<el-table-column prop="target" label="目标" />
|
||||
<el-table-column prop="strength" label="强度" width="80" />
|
||||
</el-table>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="showDetail = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { getRelationGraph } from '@/api/knowledgegraph/api'
|
||||
|
||||
const chartRef = ref(null)
|
||||
const loading = ref(false)
|
||||
const hasData = ref(false)
|
||||
const entityType = ref('disease')
|
||||
const entityId = ref('')
|
||||
let chartInstance = null
|
||||
|
||||
const showDetail = ref(false)
|
||||
const detailTitle = ref('')
|
||||
const detailNode = ref({})
|
||||
const detailRelations = ref([])
|
||||
|
||||
const nodeColorMap = {
|
||||
disease: '#f56c6c',
|
||||
symptom: '#409eff',
|
||||
drug: '#67c23a',
|
||||
exam: '#e6a23c'
|
||||
}
|
||||
const nodeLabelMap = { disease: '疾病', symptom: '症状', drug: '药物', exam: '检查' }
|
||||
const relationLabelMap = {
|
||||
CAUSES: '导致', TREATS: '治疗', CONTRAINDICATES: '禁忌',
|
||||
INTERACTS_WITH: '相互作用', REQUIRES_EXAM: '需要检查',
|
||||
HAS_SYMPTOM: '具有症状', SIDE_EFFECT: '副作用', ALTERNATIVE: '替代'
|
||||
}
|
||||
|
||||
function initChart() {
|
||||
if (!chartRef.value) return
|
||||
chartInstance = echarts.init(chartRef.value)
|
||||
chartInstance.on('click', (params) => {
|
||||
if (params.dataType === 'node') {
|
||||
handleNodeClick(params.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function handleNodeClick(data) {
|
||||
detailNode.value = data
|
||||
detailTitle.value = `${nodeLabelMap[data.entityType] || data.entityType} - ${data.entityId}`
|
||||
detailRelations.value = []
|
||||
if (graphData.value) {
|
||||
graphData.value.edges.forEach(e => {
|
||||
if (e.source === data.id) {
|
||||
detailRelations.value.push({ relationType: relationLabelMap[e.relationType] || e.relationType, target: e.target, strength: e.relationStrength })
|
||||
} else if (e.target === data.id) {
|
||||
detailRelations.value.push({ relationType: relationLabelMap[e.relationType] || e.relationType, target: e.source, strength: e.relationStrength })
|
||||
}
|
||||
})
|
||||
}
|
||||
showDetail.value = true
|
||||
}
|
||||
|
||||
const graphData = ref(null)
|
||||
|
||||
function renderChart(data) {
|
||||
if (!chartInstance) return
|
||||
graphData.value = data
|
||||
const nodes = (data.nodes || []).map(n => ({
|
||||
id: n.id,
|
||||
name: n.entityId,
|
||||
symbolSize: 50,
|
||||
itemStyle: { color: nodeColorMap[n.entityType] || '#909399' },
|
||||
label: { show: true, fontSize: 12 },
|
||||
entityType: n.entityType,
|
||||
entityId: n.entityId
|
||||
}))
|
||||
const edges = (data.edges || []).map(e => ({
|
||||
source: e.source,
|
||||
target: e.target,
|
||||
label: { show: true, formatter: relationLabelMap[e.relationType] || e.relationType, fontSize: 10 },
|
||||
lineStyle: { curveness: 0.2 }
|
||||
}))
|
||||
|
||||
chartInstance.setOption({
|
||||
tooltip: { trigger: 'item' },
|
||||
legend: {
|
||||
data: Object.keys(nodeColorMap).map(k => nodeLabelMap[k]),
|
||||
bottom: 10
|
||||
},
|
||||
series: [{
|
||||
type: 'graph',
|
||||
layout: 'force',
|
||||
data: nodes,
|
||||
links: edges,
|
||||
roam: true,
|
||||
draggable: true,
|
||||
force: { repulsion: 400, gravity: 0.1, edgeLength: [120, 250] },
|
||||
emphasis: { focus: 'adjacency', lineStyle: { width: 4 } },
|
||||
categories: Object.keys(nodeColorMap).map(k => ({ name: nodeLabelMap[k] }))
|
||||
}]
|
||||
}, true)
|
||||
}
|
||||
|
||||
async function loadGraph() {
|
||||
if (!entityId.value) return
|
||||
loading.value = true
|
||||
try {
|
||||
const r = await getRelationGraph(entityType.value, entityId.value)
|
||||
const data = r.data || { nodes: [], edges: [] }
|
||||
hasData.value = data.nodes && data.nodes.length > 0
|
||||
if (hasData.value) {
|
||||
await nextTick()
|
||||
if (!chartInstance) initChart()
|
||||
renderChart(data)
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleResize() {
|
||||
chartInstance && chartInstance.resize()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initChart()
|
||||
window.addEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
chartInstance && chartInstance.dispose()
|
||||
})
|
||||
</script>
|
||||
120
healthlink-his-ui/src/views/knowledgegraph/PathwayEdit.vue
Normal file
120
healthlink-his-ui/src/views/knowledgegraph/PathwayEdit.vue
Normal file
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="新增临床路径" width="750px" append-to-body @close="handleClose">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="路径编码" prop="pathwayCode">
|
||||
<el-input v-model="form.pathwayCode" placeholder="如: CP-DM-001" />
|
||||
</el-form-item>
|
||||
<el-form-item label="路径名称" prop="pathwayName">
|
||||
<el-input v-model="form.pathwayName" placeholder="如: 2型糖尿病标准路径" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病编码">
|
||||
<el-input v-model="form.diseaseCode" placeholder="ICD-10编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病名称">
|
||||
<el-input v-model="form.diseaseName" placeholder="疾病名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="标准天数">
|
||||
<el-input-number v-model="form.standardDays" :min="1" :max="365" />
|
||||
</el-form-item>
|
||||
<el-form-item label="路径描述">
|
||||
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="路径说明" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div style="margin-top:16px;display:flex;justify-content:space-between;align-items:center">
|
||||
<span style="font-weight:bold">路径步骤</span>
|
||||
<el-button size="small" type="primary" @click="addStep">添加步骤</el-button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top:8px;min-height:80px;max-height:300px;overflow-y:auto">
|
||||
<div v-for="(step, idx) in steps" :key="idx"
|
||||
style="display:flex;align-items:center;gap:8px;padding:8px;margin-bottom:8px;background:#f5f7fa;border-radius:4px;cursor:move"
|
||||
draggable="true"
|
||||
@dragstart="onDragStart(idx)"
|
||||
@dragover.prevent
|
||||
@drop="onDrop(idx)"
|
||||
>
|
||||
<span style="color:#999;cursor:grab;width:20px;text-align:center">⋮⋮</span>
|
||||
<el-tag size="small" type="info">{{ idx + 1 }}</el-tag>
|
||||
<el-select v-model="step.dayNumber" placeholder="天" style="width:80px" size="small">
|
||||
<el-option v-for="d in 30" :key="d" :label="`第${d}天`" :value="d" />
|
||||
</el-select>
|
||||
<el-select v-model="step.stepType" placeholder="类型" style="width:100px" size="small">
|
||||
<el-option label="检查" value="exam" />
|
||||
<el-option label="治疗" value="treatment" />
|
||||
<el-option label="护理" value="nursing" />
|
||||
<el-option label="用药" value="medication" />
|
||||
</el-select>
|
||||
<el-input v-model="step.stepContent" placeholder="步骤内容" size="small" style="flex:1" />
|
||||
<el-button link type="danger" @click="removeStep(idx)" size="small">删除</el-button>
|
||||
</div>
|
||||
<el-empty v-if="!steps.length" description="点击上方添加步骤" :image-size="60" />
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { createPathway } from '@/api/knowledgegraph/api'
|
||||
|
||||
const props = defineProps({ visible: Boolean })
|
||||
const emit = defineEmits(['update:visible', 'success'])
|
||||
|
||||
const formRef = ref(null)
|
||||
const submitting = ref(false)
|
||||
const steps = ref([])
|
||||
let dragIdx = -1
|
||||
|
||||
const defaultForm = () => ({
|
||||
pathwayCode: '', pathwayName: '', diseaseCode: '',
|
||||
diseaseName: '', standardDays: 7, description: ''
|
||||
})
|
||||
const form = ref(defaultForm())
|
||||
|
||||
const rules = {
|
||||
pathwayCode: [{ required: true, message: '请输入路径编码', trigger: 'blur' }],
|
||||
pathwayName: [{ required: true, message: '请输入路径名称', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
watch(() => props.visible, (v) => {
|
||||
if (v) { form.value = defaultForm(); steps.value = [] }
|
||||
})
|
||||
|
||||
function handleClose() { emit('update:visible', false) }
|
||||
|
||||
function addStep() {
|
||||
steps.value.push({ dayNumber: 1, stepType: 'exam', stepContent: '' })
|
||||
}
|
||||
|
||||
function removeStep(idx) {
|
||||
steps.value.splice(idx, 1)
|
||||
}
|
||||
|
||||
function onDragStart(idx) { dragIdx = idx }
|
||||
|
||||
function onDrop(idx) {
|
||||
if (dragIdx < 0 || dragIdx === idx) return
|
||||
const item = steps.value.splice(dragIdx, 1)[0]
|
||||
steps.value.splice(idx, 0, item)
|
||||
dragIdx = -1
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await formRef.value.validate()
|
||||
submitting.value = true
|
||||
try {
|
||||
await createPathway({ pathway: form.value, steps: steps.value })
|
||||
ElMessage.success('创建成功')
|
||||
emit('update:visible', false)
|
||||
emit('success')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
119
healthlink-his-ui/src/views/knowledgegraph/PathwayList.vue
Normal file
119
healthlink-his-ui/src/views/knowledgegraph/PathwayList.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div style="padding:16px">
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
|
||||
<span style="font-size:18px;font-weight:bold">临床路径管理</span>
|
||||
<div>
|
||||
<el-button type="primary" @click="loadData">刷新</el-button>
|
||||
<el-button type="success" @click="showEdit = true">新增路径</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" style="margin-bottom:16px">
|
||||
<el-form inline>
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="keyword" placeholder="路径名称/疾病名称/编码" clearable style="width:220px" @keyup.enter="loadData" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadData">搜索</el-button>
|
||||
<el-button @click="keyword = ''; loadData()">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-table v-loading="loading" :data="tableData" border stripe>
|
||||
<el-table-column prop="pathwayCode" label="路径编码" width="140" />
|
||||
<el-table-column prop="pathwayName" label="路径名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="diseaseCode" label="疾病编码" width="120" />
|
||||
<el-table-column prop="diseaseName" label="疾病名称" width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="standardDays" label="标准天数" width="90" align="center" />
|
||||
<el-table-column prop="status" label="状态" width="80" align="center">
|
||||
<template #default="{row}">
|
||||
<el-tag :type="row.status === 'ACTIVE' ? 'success' : 'info'" size="small">
|
||||
{{ row.status === 'ACTIVE' ? '启用' : '停用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="160" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{row}">
|
||||
<el-button link type="primary" @click="viewSteps(row)">查看步骤</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:current-page="pageNo"
|
||||
v-model:page-size="pageSize"
|
||||
style="margin-top:12px;justify-content:flex-end"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="loadData"
|
||||
@current-change="loadData"
|
||||
/>
|
||||
|
||||
<PathwayEdit v-model:visible="showEdit" @success="loadData" />
|
||||
|
||||
<el-dialog v-model="showSteps" :title="stepsTitle" width="700px" append-to-body>
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="step in stepsData"
|
||||
:key="step.id"
|
||||
:type="stepTypeColor(step.stepType)"
|
||||
:timestamp="`第${step.dayNumber || '-'}天 - ${stepTypeName(step.stepType)}`"
|
||||
placement="top"
|
||||
>
|
||||
<el-card shadow="never" :body-style="{padding:'10px'}">
|
||||
<div style="font-size:13px">{{ step.stepContent }}</div>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
<el-empty v-if="!stepsData.length" description="暂无步骤" />
|
||||
<template #footer>
|
||||
<el-button @click="showSteps = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getPathwayPage, getPathwaySteps } from '@/api/knowledgegraph/api'
|
||||
import PathwayEdit from './PathwayEdit.vue'
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref([])
|
||||
const total = ref(0)
|
||||
const pageNo = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const keyword = ref('')
|
||||
const showEdit = ref(false)
|
||||
const showSteps = ref(false)
|
||||
const stepsTitle = ref('')
|
||||
const stepsData = ref([])
|
||||
|
||||
const stepTypeMap = { exam: '检查', treatment: '治疗', nursing: '护理', medication: '用药' }
|
||||
const stepColorMap = { exam: 'warning', treatment: 'primary', nursing: 'success', medication: 'danger' }
|
||||
const stepTypeName = (t) => stepTypeMap[t] || t
|
||||
const stepTypeColor = (t) => stepColorMap[t] || 'info'
|
||||
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const r = await getPathwayPage({ keyword: keyword.value, pageNo: pageNo.value, pageSize: pageSize.value })
|
||||
tableData.value = r.data?.records || []
|
||||
total.value = r.data?.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function viewSteps(row) {
|
||||
stepsTitle.value = `${row.pathwayName} - 路径步骤`
|
||||
stepsData.value = []
|
||||
showSteps.value = true
|
||||
const r = await getPathwaySteps(row.id)
|
||||
stepsData.value = r.data || []
|
||||
}
|
||||
|
||||
onMounted(() => loadData())
|
||||
</script>
|
||||
102
healthlink-his-ui/src/views/knowledgegraph/RelationForm.vue
Normal file
102
healthlink-his-ui/src/views/knowledgegraph/RelationForm.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="新增实体关系" width="600px" append-to-body @close="handleClose">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
|
||||
<el-form-item label="源实体类型" prop="sourceType">
|
||||
<el-select v-model="form.sourceType" placeholder="请选择" style="width:100%">
|
||||
<el-option v-for="t in entityTypes" :key="t.code" :label="t.name" :value="t.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="源实体ID" prop="sourceId">
|
||||
<el-input v-model="form.sourceId" placeholder="请输入源实体ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="目标实体类型" prop="targetType">
|
||||
<el-select v-model="form.targetType" placeholder="请选择" style="width:100%">
|
||||
<el-option v-for="t in entityTypes" :key="t.code" :label="t.name" :value="t.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标实体ID" prop="targetId">
|
||||
<el-input v-model="form.targetId" placeholder="请输入目标实体ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关系类型" prop="relationType">
|
||||
<el-select v-model="form.relationType" placeholder="请选择" style="width:100%">
|
||||
<el-option v-for="r in relationTypes" :key="r.code" :label="r.name" :value="r.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关系强度">
|
||||
<el-slider v-model="form.relationStrength" :min="0" :max="1" :step="0.1" show-input />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="关系描述" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { createRelation } from '@/api/knowledgegraph/api'
|
||||
|
||||
const props = defineProps({ visible: Boolean })
|
||||
const emit = defineEmits(['update:visible', 'success'])
|
||||
|
||||
const formRef = ref(null)
|
||||
const submitting = ref(false)
|
||||
|
||||
const entityTypes = [
|
||||
{ code: 'disease', name: '疾病' },
|
||||
{ code: 'symptom', name: '症状' },
|
||||
{ code: 'drug', name: '药物' },
|
||||
{ code: 'exam', name: '检查' }
|
||||
]
|
||||
|
||||
const relationTypes = [
|
||||
{ code: 'CAUSES', name: '导致' },
|
||||
{ code: 'TREATS', name: '治疗' },
|
||||
{ code: 'CONTRAINDICATES', name: '禁忌' },
|
||||
{ code: 'INTERACTS_WITH', name: '相互作用' },
|
||||
{ code: 'REQUIRES_EXAM', name: '需要检查' },
|
||||
{ code: 'HAS_SYMPTOM', name: '具有症状' },
|
||||
{ code: 'SIDE_EFFECT', name: '副作用' },
|
||||
{ code: 'ALTERNATIVE', name: '替代' }
|
||||
]
|
||||
|
||||
const defaultForm = () => ({
|
||||
sourceType: '', sourceId: '', targetType: '', targetId: '',
|
||||
relationType: '', relationStrength: 1.0, description: ''
|
||||
})
|
||||
const form = ref(defaultForm())
|
||||
|
||||
const rules = {
|
||||
sourceType: [{ required: true, message: '请选择源实体类型', trigger: 'change' }],
|
||||
sourceId: [{ required: true, message: '请输入源实体ID', trigger: 'blur' }],
|
||||
targetType: [{ required: true, message: '请选择目标实体类型', trigger: 'change' }],
|
||||
targetId: [{ required: true, message: '请输入目标实体ID', trigger: 'blur' }],
|
||||
relationType: [{ required: true, message: '请选择关系类型', trigger: 'change' }]
|
||||
}
|
||||
|
||||
watch(() => props.visible, (v) => {
|
||||
if (v) form.value = defaultForm()
|
||||
})
|
||||
|
||||
function handleClose() {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await formRef.value.validate()
|
||||
submitting.value = true
|
||||
try {
|
||||
await createRelation(form.value)
|
||||
ElMessage.success('创建成功')
|
||||
emit('update:visible', false)
|
||||
emit('success')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
136
healthlink-his-ui/src/views/knowledgegraph/RelationList.vue
Normal file
136
healthlink-his-ui/src/views/knowledgegraph/RelationList.vue
Normal file
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div style="padding:16px">
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
|
||||
<span style="font-size:18px;font-weight:bold">实体关系管理</span>
|
||||
<div>
|
||||
<el-button type="primary" @click="loadData">刷新</el-button>
|
||||
<el-button type="success" @click="showForm = true">新增关系</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" style="margin-bottom:16px">
|
||||
<el-form inline>
|
||||
<el-form-item label="源实体类型">
|
||||
<el-select v-model="filters.sourceType" clearable placeholder="全部" style="width:130px">
|
||||
<el-option v-for="t in entityTypes" :key="t.code" :label="t.name" :value="t.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标实体类型">
|
||||
<el-select v-model="filters.targetType" clearable placeholder="全部" style="width:130px">
|
||||
<el-option v-for="t in entityTypes" :key="t.code" :label="t.name" :value="t.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关系类型">
|
||||
<el-select v-model="filters.relationType" clearable placeholder="全部" style="width:150px">
|
||||
<el-option v-for="r in relationTypes" :key="r.code" :label="r.name" :value="r.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadData">搜索</el-button>
|
||||
<el-button @click="resetFilters">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-table v-loading="loading" :data="tableData" border stripe>
|
||||
<el-table-column prop="sourceType" label="源实体类型" width="120" align="center">
|
||||
<template #default="{row}">
|
||||
<el-tag size="small" :style="{background: typeColor(row.sourceType), color:'#fff', border:'none'}">
|
||||
{{ typeName(row.sourceType) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sourceId" label="源实体ID" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="targetType" label="目标实体类型" width="120" align="center">
|
||||
<template #default="{row}">
|
||||
<el-tag size="small" :style="{background: typeColor(row.targetType), color:'#fff', border:'none'}">
|
||||
{{ typeName(row.targetType) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="targetId" label="目标实体ID" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="relationType" label="关系类型" width="140" align="center">
|
||||
<template #default="{row}">
|
||||
<el-tag size="small" type="warning">{{ relationName(row.relationType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="relationStrength" label="强度" width="80" align="center" />
|
||||
<el-table-column prop="description" label="描述" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="createTime" label="创建时间" width="160" />
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:current-page="pageNo"
|
||||
v-model:page-size="pageSize"
|
||||
style="margin-top:12px;justify-content:flex-end"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="loadData"
|
||||
@current-change="loadData"
|
||||
/>
|
||||
|
||||
<RelationForm v-model:visible="showForm" @success="loadData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getRelationPage } from '@/api/knowledgegraph/api'
|
||||
import RelationForm from './RelationForm.vue'
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref([])
|
||||
const total = ref(0)
|
||||
const pageNo = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const showForm = ref(false)
|
||||
|
||||
const filters = ref({ sourceType: '', targetType: '', relationType: '' })
|
||||
|
||||
const entityTypes = [
|
||||
{ code: 'disease', name: '疾病' },
|
||||
{ code: 'symptom', name: '症状' },
|
||||
{ code: 'drug', name: '药物' },
|
||||
{ code: 'exam', name: '检查' }
|
||||
]
|
||||
|
||||
const relationTypes = [
|
||||
{ code: 'CAUSES', name: '导致' },
|
||||
{ code: 'TREATS', name: '治疗' },
|
||||
{ code: 'CONTRAINDICATES', name: '禁忌' },
|
||||
{ code: 'INTERACTS_WITH', name: '相互作用' },
|
||||
{ code: 'REQUIRES_EXAM', name: '需要检查' },
|
||||
{ code: 'HAS_SYMPTOM', name: '具有症状' },
|
||||
{ code: 'SIDE_EFFECT', name: '副作用' },
|
||||
{ code: 'ALTERNATIVE', name: '替代' }
|
||||
]
|
||||
|
||||
const typeColorMap = { disease: '#f56c6c', symptom: '#409eff', drug: '#67c23a', exam: '#e6a23c' }
|
||||
const typeColor = (t) => typeColorMap[t] || '#909399'
|
||||
const typeName = (t) => (entityTypes.find(e => e.code === t) || {}).name || t
|
||||
const relationName = (r) => (relationTypes.find(e => e.code === r) || {}).name || r
|
||||
|
||||
function resetFilters() {
|
||||
filters.value = { sourceType: '', targetType: '', relationType: '' }
|
||||
loadData()
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const r = await getRelationPage({
|
||||
sourceType: filters.value.sourceType,
|
||||
targetType: filters.value.targetType,
|
||||
relationType: filters.value.relationType,
|
||||
pageNo: pageNo.value,
|
||||
pageSize: pageSize.value
|
||||
})
|
||||
tableData.value = r.data?.records || []
|
||||
total.value = r.data?.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => loadData())
|
||||
</script>
|
||||
139
healthlink-his-ui/src/views/knowledgegraph/SymptomList.vue
Normal file
139
healthlink-his-ui/src/views/knowledgegraph/SymptomList.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="关键词" prop="keyword">
|
||||
<el-input v-model="queryParams.keyword" placeholder="症状名称/编码" clearable style="width:200px" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="症状类型" prop="symptomType">
|
||||
<el-input v-model="queryParams.symptomType" placeholder="症状类型" clearable style="width:160px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="tableData" border stripe>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="symptomCode" label="症状编码" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="symptomName" label="症状名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="bodyPart" label="所属部位" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="symptomType" label="症状类型" width="120" align="center" />
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" icon="Edit" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button link type="danger" icon="Delete" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
|
||||
|
||||
<el-dialog v-model="showForm" :title="form.id ? '编辑症状' : '新增症状'" width="550px" @close="resetForm">
|
||||
<el-form ref="formRef" :model="form" :rules="formRules" label-width="90px">
|
||||
<el-form-item label="症状编码" prop="symptomCode">
|
||||
<el-input v-model="form.symptomCode" placeholder="请输入症状编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="症状名称" prop="symptomName">
|
||||
<el-input v-model="form.symptomName" placeholder="请输入症状名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部位" prop="bodyPart">
|
||||
<el-input v-model="form.bodyPart" placeholder="请输入所属部位" />
|
||||
</el-form-item>
|
||||
<el-form-item label="症状类型" prop="symptomType">
|
||||
<el-input v-model="form.symptomType" placeholder="请输入症状类型" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showForm = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="KgSymptomList">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { getSymptomPage, addSymptom, updateSymptom, deleteSymptom } from '@/api/knowledgegraph/api'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const tableData = ref([])
|
||||
const loading = ref(false)
|
||||
const showSearch = ref(true)
|
||||
const total = ref(0)
|
||||
const showForm = ref(false)
|
||||
const submitting = ref(false)
|
||||
const formRef = ref(null)
|
||||
|
||||
const queryParams = reactive({ pageNo: 1, pageSize: 10, keyword: '', symptomType: '' })
|
||||
const form = reactive({ id: undefined, symptomCode: '', symptomName: '', bodyPart: '', symptomType: '' })
|
||||
const formRules = {
|
||||
symptomCode: [{ required: true, message: '请输入症状编码', trigger: 'blur' }],
|
||||
symptomName: [{ required: true, message: '请输入症状名称', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
async function getList() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getSymptomPage(queryParams)
|
||||
if (res.code === 200) {
|
||||
tableData.value = res.data?.records || []
|
||||
total.value = res.data?.total || 0
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleQuery() { queryParams.pageNo = 1; getList() }
|
||||
function resetQuery() { queryParams.keyword = ''; queryParams.symptomType = ''; handleQuery() }
|
||||
|
||||
function handleAdd() {
|
||||
Object.assign(form, { id: undefined, symptomCode: '', symptomName: '', bodyPart: '', symptomType: '' })
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function handleEdit(row) {
|
||||
Object.assign(form, row)
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
ElMessageBox.confirm('确认删除该症状吗?', '提示', { type: 'warning' })
|
||||
.then(() => deleteSymptom(row.id))
|
||||
.then(() => { ElMessage.success('删除成功'); getList() })
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
try { await formRef.value.validate() } catch { return }
|
||||
submitting.value = true
|
||||
try {
|
||||
if (form.id) {
|
||||
await updateSymptom({ ...form })
|
||||
ElMessage.success('更新成功')
|
||||
} else {
|
||||
await addSymptom({ ...form })
|
||||
ElMessage.success('创建成功')
|
||||
}
|
||||
showForm.value = false
|
||||
getList()
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => getList())
|
||||
</script>
|
||||
Reference in New Issue
Block a user