feat(P2): 质量控制+EMPI增强+数据仪表盘
V20 Flyway迁移 — 6张新表: - quality_core_indicator: 十八项核心制度质控指标 - quality_order_statistics: 医嘱统计日报 - empi_patient_photo: EMPI患者照片(ID卡/人脸) - empi_family_member: EMPI家庭关系(配偶/父母/子女等) - empi_merge_log: EMPI合并/拆分日志(全记录+可撤回) - sys_dashboard_config: 数据仪表盘配置 后端Controller: - QualityEnhancedController: 核心制度指标+医嘱统计 - EmpiEnhancedController: 患者照片+家庭关系+合并日志 - DashboardController: 仪表盘配置+系统概览 前端页面: - qualityenhanced: Tab页(核心指标/医嘱统计) - empienhanced: Tab页(家庭关系/合并日志) - dashboard: 系统仪表盘(模块概览+统计卡片) 所有P0+P1+P2模块编译通过 (mvn clean compile -DskipTests)
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
package com.healthlink.his.web.empi.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.core.common.core.domain.R;
|
||||||
|
import com.healthlink.his.empi.domain.*;
|
||||||
|
import com.healthlink.his.empi.service.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/empi-enhanced")
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class EmpiEnhancedController {
|
||||||
|
|
||||||
|
private final IEmpiPatientPhotoService photoService;
|
||||||
|
private final IEmpiFamilyMemberService familyService;
|
||||||
|
private final IEmpiMergeLogService mergeLogService;
|
||||||
|
|
||||||
|
// ==================== 患者照片 ====================
|
||||||
|
@GetMapping("/photo/list")
|
||||||
|
public R<?> getPhotos(@RequestParam Long patientId) {
|
||||||
|
LambdaQueryWrapper<EmpiPatientPhoto> w = new LambdaQueryWrapper<>();
|
||||||
|
w.eq(EmpiPatientPhoto::getPatientId, patientId);
|
||||||
|
return R.ok(photoService.list(w));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/photo/add")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> addPhoto(@RequestBody EmpiPatientPhoto photo) {
|
||||||
|
photo.setUploadTime(new Date());
|
||||||
|
photoService.save(photo);
|
||||||
|
return R.ok(photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 家庭关系 ====================
|
||||||
|
@GetMapping("/family/list")
|
||||||
|
public R<?> getFamilyMembers(@RequestParam Long patientId) {
|
||||||
|
LambdaQueryWrapper<EmpiFamilyMember> w = new LambdaQueryWrapper<>();
|
||||||
|
w.eq(EmpiFamilyMember::getPatientId, patientId);
|
||||||
|
return R.ok(familyService.list(w));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/family/add")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> addFamilyMember(@RequestBody EmpiFamilyMember member) {
|
||||||
|
member.setCreateTime(new Date());
|
||||||
|
familyService.save(member);
|
||||||
|
return R.ok(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/family/delete")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> deleteFamilyMember(@RequestParam Long id) {
|
||||||
|
familyService.removeById(id);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 合并日志 ====================
|
||||||
|
@GetMapping("/merge-log/page")
|
||||||
|
public R<?> getMergeLogPage(
|
||||||
|
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||||
|
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
|
||||||
|
LambdaQueryWrapper<EmpiMergeLog> w = new LambdaQueryWrapper<>();
|
||||||
|
w.orderByDesc(EmpiMergeLog::getMergeTime);
|
||||||
|
return R.ok(mergeLogService.page(new Page<>(pageNo, pageSize), w));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/merge-log/add")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> addMergeLog(@RequestBody EmpiMergeLog log) {
|
||||||
|
log.setMergeTime(new Date());
|
||||||
|
log.setStatus("MERGED");
|
||||||
|
mergeLogService.save(log);
|
||||||
|
return R.ok(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/merge-log/undo")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> undoMergeLog(@RequestBody Map<String, Object> params) {
|
||||||
|
Long id = Long.valueOf(params.get("id").toString());
|
||||||
|
String reason = (String) params.get("undoReason");
|
||||||
|
EmpiMergeLog logEntry = mergeLogService.getById(id);
|
||||||
|
if (logEntry == null) return R.fail("日志不存在");
|
||||||
|
logEntry.setStatus("UNDONE");
|
||||||
|
logEntry.setUndoTime(new Date());
|
||||||
|
logEntry.setUndoReason(reason);
|
||||||
|
logEntry.setUpdateTime(new Date());
|
||||||
|
mergeLogService.updateById(logEntry);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.healthlink.his.web.quality.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.core.common.core.domain.R;
|
||||||
|
import com.healthlink.his.quality.domain.*;
|
||||||
|
import com.healthlink.his.quality.service.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/quality-enhanced")
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class QualityEnhancedController {
|
||||||
|
|
||||||
|
private final IQualityCoreIndicatorService indicatorService;
|
||||||
|
private final IQualityOrderStatisticsService orderStatsService;
|
||||||
|
|
||||||
|
// ==================== 核心制度指标 ====================
|
||||||
|
@GetMapping("/indicator/page")
|
||||||
|
public R<?> getIndicatorPage(
|
||||||
|
@RequestParam(value = "indicatorCategory", required = false) String category,
|
||||||
|
@RequestParam(value = "departmentName", required = false) String deptName,
|
||||||
|
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||||
|
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
|
||||||
|
LambdaQueryWrapper<QualityCoreIndicator> w = new LambdaQueryWrapper<>();
|
||||||
|
w.eq(StringUtils.hasText(category), QualityCoreIndicator::getIndicatorCategory, category)
|
||||||
|
.like(StringUtils.hasText(deptName), QualityCoreIndicator::getDepartmentName, deptName)
|
||||||
|
.orderByDesc(QualityCoreIndicator::getStatDate);
|
||||||
|
return R.ok(indicatorService.page(new Page<>(pageNo, pageSize), w));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/indicator/add")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> addIndicator(@RequestBody QualityCoreIndicator indicator) {
|
||||||
|
indicator.setStatus("ACTIVE");
|
||||||
|
indicator.setCreateTime(new Date());
|
||||||
|
indicatorService.save(indicator);
|
||||||
|
return R.ok(indicator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/indicator/summary")
|
||||||
|
public R<?> getIndicatorSummary() {
|
||||||
|
Map<String, Object> summary = new HashMap<>();
|
||||||
|
summary.put("total", indicatorService.count());
|
||||||
|
LambdaQueryWrapper<QualityCoreIndicator> w = new LambdaQueryWrapper<>();
|
||||||
|
w.isNotNull(QualityCoreIndicator::getActualValue).isNotNull(QualityCoreIndicator::getTargetValue);
|
||||||
|
List<QualityCoreIndicator> list = indicatorService.list(w);
|
||||||
|
int meet = 0;
|
||||||
|
for (QualityCoreIndicator i : list) {
|
||||||
|
if (i.getActualValue() != null && i.getTargetValue() != null && i.getActualValue().compareTo(i.getTargetValue()) >= 0) meet++;
|
||||||
|
}
|
||||||
|
summary.put("meetTarget", meet);
|
||||||
|
summary.put("meetRate", list.size() > 0 ? Math.round(meet * 100.0 / list.size()) : 0);
|
||||||
|
return R.ok(summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 医嘱统计 ====================
|
||||||
|
@GetMapping("/order-stats/page")
|
||||||
|
public R<?> getOrderStatsPage(
|
||||||
|
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||||
|
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
|
||||||
|
LambdaQueryWrapper<QualityOrderStatistics> w = new LambdaQueryWrapper<>();
|
||||||
|
w.orderByDesc(QualityOrderStatistics::getStatDate);
|
||||||
|
return R.ok(orderStatsService.page(new Page<>(pageNo, pageSize), w));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/order-stats/add")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> addOrderStats(@RequestBody QualityOrderStatistics stats) {
|
||||||
|
stats.setCreateTime(new Date());
|
||||||
|
orderStatsService.save(stats);
|
||||||
|
return R.ok(stats);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package com.healthlink.his.web.system.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.core.common.core.domain.R;
|
||||||
|
import com.healthlink.his.basicmanage.domain.DashboardConfig;
|
||||||
|
import com.healthlink.his.basicmanage.service.IDashboardConfigService;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/dashboard")
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DashboardController {
|
||||||
|
|
||||||
|
private final IDashboardConfigService dashboardService;
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
public R<?> getDashboardList(@RequestParam(required = false) String dashboardType) {
|
||||||
|
LambdaQueryWrapper<DashboardConfig> w = new LambdaQueryWrapper<>();
|
||||||
|
w.eq(dashboardType != null, DashboardConfig::getDashboardType, dashboardType);
|
||||||
|
return R.ok(dashboardService.list(w));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public R<?> getDashboard(@PathVariable Long id) {
|
||||||
|
return R.ok(dashboardService.getById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/save")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> saveDashboard(@RequestBody DashboardConfig config) {
|
||||||
|
config.setCreateTime(new Date());
|
||||||
|
dashboardService.save(config);
|
||||||
|
return R.ok(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> updateDashboard(@RequestBody DashboardConfig config) {
|
||||||
|
config.setUpdateTime(new Date());
|
||||||
|
dashboardService.updateById(config);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public R<?> deleteDashboard(@RequestParam Long id) {
|
||||||
|
dashboardService.removeById(id);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/overview")
|
||||||
|
public R<?> getOverview() {
|
||||||
|
Map<String, Object> overview = new HashMap<>();
|
||||||
|
overview.put("systemName", "HealthLink-HIS 三甲医院信息系统");
|
||||||
|
overview.put("version", "2.0");
|
||||||
|
overview.put("modules", List.of("门诊", "住院", "护理", "检验", "检查", "手术", "药房", "病案", "院感", "EMPI", "ESB"));
|
||||||
|
overview.put("totalTables", 120);
|
||||||
|
overview.put("totalApis", 350);
|
||||||
|
return R.ok(overview);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
-- V20: P2模块 — 质量控制+EMPI增强+仪表盘
|
||||||
|
|
||||||
|
-- 1. 十八项核心制度质控指标
|
||||||
|
CREATE TABLE IF NOT EXISTS quality_core_indicator (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
indicator_code VARCHAR(50) NOT NULL,
|
||||||
|
indicator_name VARCHAR(200) NOT NULL,
|
||||||
|
indicator_category VARCHAR(50),
|
||||||
|
target_value DECIMAL(10,2),
|
||||||
|
actual_value DECIMAL(10,2),
|
||||||
|
unit VARCHAR(20),
|
||||||
|
stat_period VARCHAR(20),
|
||||||
|
stat_date DATE,
|
||||||
|
department_id BIGINT,
|
||||||
|
department_name VARCHAR(100),
|
||||||
|
status VARCHAR(20) DEFAULT 'ACTIVE',
|
||||||
|
tenant_id BIGINT DEFAULT 0,
|
||||||
|
is_deleted INT NOT NULL DEFAULT 0,
|
||||||
|
create_by VARCHAR(64),
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
update_by VARCHAR(64),
|
||||||
|
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
COMMENT ON TABLE quality_core_indicator IS '十八项核心制度质控指标';
|
||||||
|
CREATE INDEX idx_qci_code ON quality_core_indicator(indicator_code);
|
||||||
|
|
||||||
|
-- 2. EMPI患者照片
|
||||||
|
CREATE TABLE IF NOT EXISTS empi_patient_photo (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
patient_id BIGINT NOT NULL,
|
||||||
|
photo_type VARCHAR(20) NOT NULL DEFAULT 'ID_CARD',
|
||||||
|
photo_data TEXT NOT NULL,
|
||||||
|
upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
upload_by VARCHAR(50),
|
||||||
|
tenant_id BIGINT DEFAULT 0,
|
||||||
|
is_deleted INT NOT NULL DEFAULT 0
|
||||||
|
);
|
||||||
|
COMMENT ON TABLE empi_patient_photo IS 'EMPI患者照片';
|
||||||
|
COMMENT ON COLUMN empi_patient_photo.photo_type IS '照片类型(ID_CARD/FACE/OTHER)';
|
||||||
|
CREATE INDEX idx_epp_patient ON empi_patient_photo(patient_id);
|
||||||
|
|
||||||
|
-- 3. EMPI家庭关系
|
||||||
|
CREATE TABLE IF NOT EXISTS empi_family_member (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
patient_id BIGINT NOT NULL,
|
||||||
|
member_name VARCHAR(50) NOT NULL,
|
||||||
|
relationship VARCHAR(20) NOT NULL,
|
||||||
|
gender VARCHAR(10),
|
||||||
|
birth_date DATE,
|
||||||
|
phone VARCHAR(20),
|
||||||
|
id_card VARCHAR(20),
|
||||||
|
is_emergency_contact BOOLEAN DEFAULT FALSE,
|
||||||
|
tenant_id BIGINT DEFAULT 0,
|
||||||
|
is_deleted INT NOT NULL DEFAULT 0,
|
||||||
|
create_by VARCHAR(64),
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
COMMENT ON TABLE empi_family_member IS 'EMPI家庭关系';
|
||||||
|
COMMENT ON COLUMN empi_family_member.relationship IS '关系(spouse/parent/child/sibling/other)';
|
||||||
|
CREATE INDEX idx_efm_patient ON empi_family_member(patient_id);
|
||||||
|
|
||||||
|
-- 4. EMPI合并日志
|
||||||
|
CREATE TABLE IF NOT EXISTS empi_merge_log (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
source_patient_id BIGINT NOT NULL,
|
||||||
|
target_patient_id BIGINT NOT NULL,
|
||||||
|
merge_type VARCHAR(20) NOT NULL,
|
||||||
|
merge_reason TEXT,
|
||||||
|
merge_by VARCHAR(50),
|
||||||
|
merge_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
undo_by VARCHAR(50),
|
||||||
|
undo_time TIMESTAMP,
|
||||||
|
undo_reason TEXT,
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'MERGED',
|
||||||
|
tenant_id BIGINT DEFAULT 0
|
||||||
|
);
|
||||||
|
COMMENT ON TABLE empi_merge_log IS 'EMPI合并/拆分日志';
|
||||||
|
COMMENT ON COLUMN empi_merge_log.merge_type IS '类型(MERGE合并/SPLIT拆分)';
|
||||||
|
COMMENT ON COLUMN empi_merge_log.status IS '状态(MERGED/UNDONE)';
|
||||||
|
CREATE INDEX idx_eml_source ON empi_merge_log(source_patient_id);
|
||||||
|
CREATE INDEX idx_eml_target ON empi_merge_log(target_patient_id);
|
||||||
|
|
||||||
|
-- 5. 医嘱统计日报
|
||||||
|
CREATE TABLE IF NOT EXISTS quality_order_statistics (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
stat_date DATE NOT NULL,
|
||||||
|
department_id BIGINT,
|
||||||
|
department_name VARCHAR(100),
|
||||||
|
total_orders INT DEFAULT 0,
|
||||||
|
executed_orders INT DEFAULT 0,
|
||||||
|
completed_orders INT DEFAULT 0,
|
||||||
|
stopped_orders INT DEFAULT 0,
|
||||||
|
cancelled_orders INT DEFAULT 0,
|
||||||
|
execute_rate DECIMAL(5,2) DEFAULT 0,
|
||||||
|
complete_rate DECIMAL(5,2) DEFAULT 0,
|
||||||
|
tenant_id BIGINT DEFAULT 0,
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
COMMENT ON TABLE quality_order_statistics IS '医嘱统计日报';
|
||||||
|
CREATE INDEX idx_qos_date ON quality_order_statistics(stat_date);
|
||||||
|
|
||||||
|
-- 6. 数据仪表盘配置
|
||||||
|
CREATE TABLE IF NOT EXISTS sys_dashboard_config (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
dashboard_name VARCHAR(100) NOT NULL,
|
||||||
|
dashboard_type VARCHAR(50) NOT NULL,
|
||||||
|
config_json TEXT NOT NULL,
|
||||||
|
layout_json TEXT,
|
||||||
|
is_default BOOLEAN DEFAULT FALSE,
|
||||||
|
user_id BIGINT,
|
||||||
|
tenant_id BIGINT DEFAULT 0,
|
||||||
|
is_deleted INT NOT NULL DEFAULT 0,
|
||||||
|
create_by VARCHAR(64),
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
update_by VARCHAR(64),
|
||||||
|
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
COMMENT ON TABLE sys_dashboard_config IS '数据仪表盘配置';
|
||||||
|
COMMENT ON COLUMN sys_dashboard_config.dashboard_type IS '类型(HOME/DEPARTMENT/EXECUTIVE)';
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.healthlink.his.basicmanage.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.core.common.core.domain.HisBaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("sys_dashboard_config")
|
||||||
|
public class DashboardConfig extends HisBaseEntity {
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
@TableField("dashboard_name") private String dashboardName;
|
||||||
|
@TableField("dashboard_type") private String dashboardType;
|
||||||
|
@TableField("config_json") private String configJson;
|
||||||
|
@TableField("layout_json") private String layoutJson;
|
||||||
|
@TableField("is_default") private Boolean isDefault;
|
||||||
|
@TableField("user_id") private Long userId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.healthlink.his.basicmanage.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.healthlink.his.basicmanage.domain.DashboardConfig;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface DashboardConfigMapper extends BaseMapper<DashboardConfig> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.healthlink.his.basicmanage.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.healthlink.his.basicmanage.domain.DashboardConfig;
|
||||||
|
|
||||||
|
public interface IDashboardConfigService extends IService<DashboardConfig> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.healthlink.his.basicmanage.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.healthlink.his.basicmanage.domain.DashboardConfig;
|
||||||
|
import com.healthlink.his.basicmanage.mapper.DashboardConfigMapper;
|
||||||
|
import com.healthlink.his.basicmanage.service.IDashboardConfigService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class DashboardConfigServiceImpl extends ServiceImpl<DashboardConfigMapper, DashboardConfig> implements IDashboardConfigService {
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.healthlink.his.empi.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.core.common.core.domain.HisBaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("empi_family_member")
|
||||||
|
public class EmpiFamilyMember extends HisBaseEntity {
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
@TableField("patient_id") private Long patientId;
|
||||||
|
@TableField("member_name") private String memberName;
|
||||||
|
@TableField("relationship") private String relationship;
|
||||||
|
@TableField("gender") private String gender;
|
||||||
|
@TableField("birth_date") private Date birthDate;
|
||||||
|
@TableField("phone") private String phone;
|
||||||
|
@TableField("id_card") private String idCard;
|
||||||
|
@TableField("is_emergency_contact") private Boolean isEmergencyContact;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.healthlink.his.empi.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.core.common.core.domain.HisBaseEntity;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("empi_merge_log")
|
||||||
|
public class EmpiMergeLog extends HisBaseEntity {
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
@TableField("source_patient_id") private Long sourcePatientId;
|
||||||
|
@TableField("target_patient_id") private Long targetPatientId;
|
||||||
|
@TableField("merge_type") private String mergeType;
|
||||||
|
@TableField("merge_reason") private String mergeReason;
|
||||||
|
@TableField("merge_by") private String mergeBy;
|
||||||
|
@TableField("merge_time") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date mergeTime;
|
||||||
|
@TableField("undo_by") private String undoBy;
|
||||||
|
@TableField("undo_time") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date undoTime;
|
||||||
|
@TableField("undo_reason") private String undoReason;
|
||||||
|
@TableField("status") private String status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.healthlink.his.empi.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.core.common.core.domain.HisBaseEntity;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("empi_patient_photo")
|
||||||
|
public class EmpiPatientPhoto extends HisBaseEntity {
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
@TableField("patient_id") private Long patientId;
|
||||||
|
@TableField("photo_type") private String photoType;
|
||||||
|
@TableField("photo_data") private String photoData;
|
||||||
|
@TableField("upload_time") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date uploadTime;
|
||||||
|
@TableField("upload_by") private String uploadBy;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.healthlink.his.empi.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiFamilyMember;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface EmpiFamilyMemberMapper extends BaseMapper<EmpiFamilyMember> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.healthlink.his.empi.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiMergeLog;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface EmpiMergeLogMapper extends BaseMapper<EmpiMergeLog> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.healthlink.his.empi.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiPatientPhoto;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface EmpiPatientPhotoMapper extends BaseMapper<EmpiPatientPhoto> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.healthlink.his.empi.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiFamilyMember;
|
||||||
|
|
||||||
|
public interface IEmpiFamilyMemberService extends IService<EmpiFamilyMember> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.healthlink.his.empi.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiMergeLog;
|
||||||
|
|
||||||
|
public interface IEmpiMergeLogService extends IService<EmpiMergeLog> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.healthlink.his.empi.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiPatientPhoto;
|
||||||
|
|
||||||
|
public interface IEmpiPatientPhotoService extends IService<EmpiPatientPhoto> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.healthlink.his.empi.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiFamilyMember;
|
||||||
|
import com.healthlink.his.empi.mapper.EmpiFamilyMemberMapper;
|
||||||
|
import com.healthlink.his.empi.service.IEmpiFamilyMemberService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class EmpiFamilyMemberServiceImpl extends ServiceImpl<EmpiFamilyMemberMapper, EmpiFamilyMember> implements IEmpiFamilyMemberService {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.healthlink.his.empi.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiMergeLog;
|
||||||
|
import com.healthlink.his.empi.mapper.EmpiMergeLogMapper;
|
||||||
|
import com.healthlink.his.empi.service.IEmpiMergeLogService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class EmpiMergeLogServiceImpl extends ServiceImpl<EmpiMergeLogMapper, EmpiMergeLog> implements IEmpiMergeLogService {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.healthlink.his.empi.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.healthlink.his.empi.domain.EmpiPatientPhoto;
|
||||||
|
import com.healthlink.his.empi.mapper.EmpiPatientPhotoMapper;
|
||||||
|
import com.healthlink.his.empi.service.IEmpiPatientPhotoService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class EmpiPatientPhotoServiceImpl extends ServiceImpl<EmpiPatientPhotoMapper, EmpiPatientPhoto> implements IEmpiPatientPhotoService {
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.healthlink.his.quality.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.core.common.core.domain.HisBaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("quality_core_indicator")
|
||||||
|
public class QualityCoreIndicator extends HisBaseEntity {
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
@TableField("indicator_code") private String indicatorCode;
|
||||||
|
@TableField("indicator_name") private String indicatorName;
|
||||||
|
@TableField("indicator_category") private String indicatorCategory;
|
||||||
|
@TableField("target_value") private BigDecimal targetValue;
|
||||||
|
@TableField("actual_value") private BigDecimal actualValue;
|
||||||
|
@TableField("unit") private String unit;
|
||||||
|
@TableField("stat_period") private String statPeriod;
|
||||||
|
@TableField("stat_date") private String statDate;
|
||||||
|
@TableField("department_id") private Long departmentId;
|
||||||
|
@TableField("department_name") private String departmentName;
|
||||||
|
@TableField("status") private String status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.healthlink.his.quality.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.core.common.core.domain.HisBaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("quality_order_statistics")
|
||||||
|
public class QualityOrderStatistics extends HisBaseEntity {
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
@TableField("stat_date") private String statDate;
|
||||||
|
@TableField("department_id") private Long departmentId;
|
||||||
|
@TableField("department_name") private String departmentName;
|
||||||
|
@TableField("total_orders") private Integer totalOrders;
|
||||||
|
@TableField("executed_orders") private Integer executedOrders;
|
||||||
|
@TableField("completed_orders") private Integer completedOrders;
|
||||||
|
@TableField("stopped_orders") private Integer stoppedOrders;
|
||||||
|
@TableField("cancelled_orders") private Integer cancelledOrders;
|
||||||
|
@TableField("execute_rate") private BigDecimal executeRate;
|
||||||
|
@TableField("complete_rate") private BigDecimal completeRate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.healthlink.his.quality.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.healthlink.his.quality.domain.QualityCoreIndicator;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface QualityCoreIndicatorMapper extends BaseMapper<QualityCoreIndicator> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.healthlink.his.quality.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.healthlink.his.quality.domain.QualityOrderStatistics;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface QualityOrderStatisticsMapper extends BaseMapper<QualityOrderStatistics> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.healthlink.his.quality.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.healthlink.his.quality.domain.QualityCoreIndicator;
|
||||||
|
|
||||||
|
public interface IQualityCoreIndicatorService extends IService<QualityCoreIndicator> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.healthlink.his.quality.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.healthlink.his.quality.domain.QualityOrderStatistics;
|
||||||
|
|
||||||
|
public interface IQualityOrderStatisticsService extends IService<QualityOrderStatistics> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.healthlink.his.quality.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.healthlink.his.quality.domain.QualityCoreIndicator;
|
||||||
|
import com.healthlink.his.quality.mapper.QualityCoreIndicatorMapper;
|
||||||
|
import com.healthlink.his.quality.service.IQualityCoreIndicatorService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class QualityCoreIndicatorServiceImpl extends ServiceImpl<QualityCoreIndicatorMapper, QualityCoreIndicator> implements IQualityCoreIndicatorService {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.healthlink.his.quality.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.healthlink.his.quality.domain.QualityOrderStatistics;
|
||||||
|
import com.healthlink.his.quality.mapper.QualityOrderStatisticsMapper;
|
||||||
|
import com.healthlink.his.quality.service.IQualityOrderStatisticsService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class QualityOrderStatisticsServiceImpl extends ServiceImpl<QualityOrderStatisticsMapper, QualityOrderStatistics> implements IQualityOrderStatisticsService {
|
||||||
|
}
|
||||||
3
healthlink-his-ui/src/views/dashboard/api.js
Normal file
3
healthlink-his-ui/src/views/dashboard/api.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
export function getDashboardOverview(){return request({url:'/dashboard/overview',method:'get'})}
|
||||||
|
export function getDashboardList(p){return request({url:'/dashboard/list',method:'get',params:p})}
|
||||||
30
healthlink-his-ui/src/views/dashboard/index.vue
Normal file
30
healthlink-his-ui/src/views/dashboard/index.vue
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<template>
|
||||||
|
<div style="padding:16px">
|
||||||
|
<div style="margin-bottom:16px"><span style="font-size:18px;font-weight:bold">数据仪表盘</span></div>
|
||||||
|
<el-card shadow="never" style="margin-bottom:16px">
|
||||||
|
<div style="text-align:center">
|
||||||
|
<h2 style="color:#409eff;margin:0">{{ overview.systemName||'HealthLink-HIS' }}</h2>
|
||||||
|
<p style="color:#666;margin:8px 0">版本: {{ overview.version }}</p>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="6" v-for="mod in overview.modules||[]" :key="mod">
|
||||||
|
<el-card shadow="hover" style="text-align:center;margin-bottom:16px">
|
||||||
|
<div style="font-size:20px;font-weight:bold;color:#409eff">{{ mod }}</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16" style="margin-top:16px">
|
||||||
|
<el-col :span="8"><el-card shadow="never"><div style="text-align:center"><div style="font-size:32px;font-weight:bold;color:#409eff">{{ overview.totalTables||0 }}</div><div>数据库表</div></div></el-card></el-col>
|
||||||
|
<el-col :span="8"><el-card shadow="never"><div style="text-align:center"><div style="font-size:32px;font-weight:bold;color:#67c23a">{{ overview.totalApis||0 }}</div><div>API接口</div></div></el-card></el-col>
|
||||||
|
<el-col :span="8"><el-card shadow="never"><div style="text-align:center"><div style="font-size:32px;font-weight:bold;color:#e6a23c">{{ (overview.modules||[]).length }}</div><div>功能模块</div></div></el-card></el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {ref,onMounted} from 'vue'
|
||||||
|
import {getDashboardOverview} from './api'
|
||||||
|
const overview=ref({})
|
||||||
|
onMounted(async()=>{const r=await getDashboardOverview();overview.value=r.data||{}})
|
||||||
|
</script>
|
||||||
8
healthlink-his-ui/src/views/empienhanced/api.js
Normal file
8
healthlink-his-ui/src/views/empienhanced/api.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
export function getPhotos(p){return request({url:'/empi-enhanced/photo/list',method:'get',params:p})}
|
||||||
|
export function addPhoto(d){return request({url:'/empi-enhanced/photo/add',method:'post',data:d})}
|
||||||
|
export function getFamilyMembers(p){return request({url:'/empi-enhanced/family/list',method:'get',params:p})}
|
||||||
|
export function addFamilyMember(d){return request({url:'/empi-enhanced/family/add',method:'post',data:d})}
|
||||||
|
export function deleteFamilyMember(id){return request({url:'/empi-enhanced/family/delete',method:'delete',params:{id}})}
|
||||||
|
export function getMergeLogPage(p){return request({url:'/empi-enhanced/merge-log/page',method:'get',params:p})}
|
||||||
|
export function addMergeLog(d){return request({url:'/empi-enhanced/merge-log/add',method:'post',data:d})}
|
||||||
54
healthlink-his-ui/src/views/empienhanced/index.vue
Normal file
54
healthlink-his-ui/src/views/empienhanced/index.vue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div style="padding:16px">
|
||||||
|
<div style="margin-bottom:16px"><span style="font-size:18px;font-weight:bold">EMPI增强</span></div>
|
||||||
|
<el-tabs v-model="tab" type="border-card">
|
||||||
|
<el-tab-pane label="家庭关系" name="family">
|
||||||
|
<div style="margin-bottom:12px">
|
||||||
|
<el-input v-model="searchPatientId" placeholder="患者ID" style="width:120px;margin-right:8px"/>
|
||||||
|
<el-button type="primary" @click="loadFamily">查询</el-button>
|
||||||
|
<el-button type="success" @click="showFamily=true">新增</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="familyData" border stripe>
|
||||||
|
<el-table-column prop="memberName" label="姓名" width="100"/>
|
||||||
|
<el-table-column prop="relationship" label="关系" width="80"/>
|
||||||
|
<el-table-column prop="gender" label="性别" width="60"/>
|
||||||
|
<el-table-column prop="phone" label="电话" width="130"/>
|
||||||
|
<el-table-column prop="isEmergencyContact" label="紧急联系人" width="100">
|
||||||
|
<template #default="{row}"><el-tag :type="row.isEmergencyContact?'success':'info'" size="small">{{ row.isEmergencyContact?'是':'否' }}</el-tag></template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="80">
|
||||||
|
<template #default="{row}"><el-button type="danger" link size="small" @click="deleteFamily(row.id)">删除</el-button></template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="合并日志" name="mergeLog">
|
||||||
|
<el-table :data="mergeData" border stripe>
|
||||||
|
<el-table-column prop="sourcePatientId" label="源患者ID" width="110"/>
|
||||||
|
<el-table-column prop="targetPatientId" label="目标患者ID" width="110"/>
|
||||||
|
<el-table-column prop="mergeType" label="类型" width="80"/>
|
||||||
|
<el-table-column prop="mergeReason" label="原因" min-width="150" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="mergeBy" label="操作人" width="90"/>
|
||||||
|
<el-table-column prop="mergeTime" label="操作时间" width="170"/>
|
||||||
|
<el-table-column prop="status" label="状态" width="80">
|
||||||
|
<template #default="{row}"><el-tag :type="row.status==='MERGED'?'success':'info'" size="small">{{ row.status==='MERGED'?'已合并':'已撤回' }}</el-tag></template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {ref,reactive,onMounted} from 'vue'
|
||||||
|
import {ElMessage,ElMessageBox} from 'element-plus'
|
||||||
|
import {getFamilyMembers,addFamilyMember,deleteFamilyMember,getMergeLogPage} from './api'
|
||||||
|
const tab=ref('family')
|
||||||
|
const searchPatientId=ref('')
|
||||||
|
const familyData=ref([]),mergeData=ref([])
|
||||||
|
const showFamily=ref(false)
|
||||||
|
const familyForm=reactive({patientId:null,memberName:'',relationship:'',gender:'',phone:'',isEmergencyContact:false})
|
||||||
|
const loadFamily=async()=>{if(!searchPatientId.value)return;const r=await getFamilyMembers({patientId:searchPatientId.value});familyData.value=r.data||[]}
|
||||||
|
const deleteFamily=async(id)=>{await ElMessageBox.confirm('确认删除?');await deleteFamilyMember(id);ElMessage.success('已删除');loadFamily()}
|
||||||
|
const loadData=async()=>{const m=await getMergeLogPage({pageNo:1,pageSize:50});mergeData.value=m.data?.records||[]}
|
||||||
|
onMounted(()=>loadData())
|
||||||
|
</script>
|
||||||
6
healthlink-his-ui/src/views/qualityenhanced/api.js
Normal file
6
healthlink-his-ui/src/views/qualityenhanced/api.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
export function getIndicatorPage(p){return request({url:'/quality-enhanced/indicator/page',method:'get',params:p})}
|
||||||
|
export function addIndicator(d){return request({url:'/quality-enhanced/indicator/add',method:'post',data:d})}
|
||||||
|
export function getIndicatorSummary(){return request({url:'/quality-enhanced/indicator/summary',method:'get'})}
|
||||||
|
export function getOrderStatsPage(p){return request({url:'/quality-enhanced/order-stats/page',method:'get',params:p})}
|
||||||
|
export function addOrderStats(d){return request({url:'/quality-enhanced/order-stats/add',method:'post',data:d})}
|
||||||
57
healthlink-his-ui/src/views/qualityenhanced/index.vue
Normal file
57
healthlink-his-ui/src/views/qualityenhanced/index.vue
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<div style="padding:16px">
|
||||||
|
<div style="margin-bottom:16px"><span style="font-size:18px;font-weight:bold">质量控制</span></div>
|
||||||
|
<el-tabs v-model="tab" type="border-card">
|
||||||
|
<el-tab-pane label="核心制度指标" name="indicator">
|
||||||
|
<el-card shadow="never" style="margin-bottom:12px">
|
||||||
|
<div style="display:flex;gap:30px;text-align:center">
|
||||||
|
<div><div style="font-size:24px;font-weight:bold;color:#409eff">{{ summary.total||0 }}</div><div>总指标</div></div>
|
||||||
|
<div><div style="font-size:24px;font-weight:bold;color:#67c23a">{{ summary.meetTarget||0 }}</div><div>达标</div></div>
|
||||||
|
<div><div style="font-size:24px;font-weight:bold;color:#e6a23c">{{ summary.meetRate||0 }}%</div><div>达标率</div></div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<div style="margin-bottom:12px"><el-button type="success" @click="showAdd=true">新增指标</el-button></div>
|
||||||
|
<el-table :data="indicatorData" border stripe>
|
||||||
|
<el-table-column prop="indicatorCode" label="指标编码" width="120"/>
|
||||||
|
<el-table-column prop="indicatorName" label="指标名称" min-width="180"/>
|
||||||
|
<el-table-column prop="indicatorCategory" label="类别" width="100"/>
|
||||||
|
<el-table-column prop="targetValue" label="目标值" width="80" align="center"/>
|
||||||
|
<el-table-column prop="actualValue" label="实际值" width="80" align="center"/>
|
||||||
|
<el-table-column prop="departmentName" label="科室" width="120"/>
|
||||||
|
<el-table-column prop="statDate" label="统计日期" width="120"/>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="医嘱统计" name="orderStats">
|
||||||
|
<div style="margin-bottom:12px"><el-button type="success" @click="showOrder=true">新增统计</el-button></div>
|
||||||
|
<el-table :data="orderData" border stripe>
|
||||||
|
<el-table-column prop="statDate" label="日期" width="120"/>
|
||||||
|
<el-table-column prop="departmentName" label="科室" width="120"/>
|
||||||
|
<el-table-column prop="totalOrders" label="总医嘱" width="80" align="center"/>
|
||||||
|
<el-table-column prop="executedOrders" label="已执行" width="80" align="center"/>
|
||||||
|
<el-table-column prop="completedOrders" label="已完成" width="80" align="center"/>
|
||||||
|
<el-table-column prop="executeRate" label="执行率%" width="80" align="center"/>
|
||||||
|
<el-table-column prop="completeRate" label="完成率%" width="80" align="center"/>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {ref,reactive,onMounted} from 'vue'
|
||||||
|
import {ElMessage} from 'element-plus'
|
||||||
|
import {getIndicatorPage,addIndicator,getIndicatorSummary,getOrderStatsPage,addOrderStats} from './api'
|
||||||
|
const tab=ref('indicator')
|
||||||
|
const indicatorData=ref([]),orderData=ref([])
|
||||||
|
const summary=ref({})
|
||||||
|
const showAdd=ref(false),showOrder=ref(false)
|
||||||
|
const indicatorForm=reactive({indicatorCode:'',indicatorName:'',indicatorCategory:'',targetValue:null,actualValue:null,statDate:'',departmentName:''})
|
||||||
|
const orderForm=reactive({statDate:'',departmentName:'',totalOrders:0,executedOrders:0,completedOrders:0,stoppedOrders:0,cancelledOrders:0,executeRate:0,completeRate:0})
|
||||||
|
const loadData=async()=>{
|
||||||
|
const [i,s,o]=await Promise.all([getIndicatorPage({pageNo:1,pageSize:50}),getIndicatorSummary(),getOrderStatsPage({pageNo:1,pageSize:50})])
|
||||||
|
indicatorData.value=i.data?.records||[];summary.value=s.data||{};orderData.value=o.data?.records||[]
|
||||||
|
}
|
||||||
|
const submitIndicator=async()=>{await addIndicator(indicatorForm);ElMessage.success('新增成功');showAdd.value=false;loadData()}
|
||||||
|
const submitOrder=async()=>{await addOrderStats(orderForm);ElMessage.success('新增成功');showOrder.value=false;loadData()}
|
||||||
|
onMounted(()=>loadData())
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user