调整BUG

This commit is contained in:
Flow 2025-07-23 17:23:45 +08:00
parent 07c5cc5b5d
commit 8f7dec1902
8 changed files with 2130 additions and 14 deletions

View File

@ -1,4 +1,5 @@
import request from '@/config/axios'
import { patientinfoVO } from '../patientinfo'
// CGM数据 VO
export interface CgmVO {
@ -50,5 +51,26 @@ export const CgmApi = {
// 导出CGM数据 Excel
exportCgm: async (params) => {
return await request.download({ url: `/system/cgm/export-excel`, params })
},
// 批量新增CGM患者数据
insertCgmPatientData: async (data: patientinfoVO[]) => {
return await request.post({ url: `/system/cgm/insertCgmPatientData`, data })
},
//根据examid更新CGM动态血糖监测分析结果
updatecgmanalysis: async (examid: string, analysisResult: string) => {
return await request.put({
url: `/system/cgm/updatecgmanalysis`,
params: {
examid,
analysisResult
}
})
},
//根据examid查询CGM动态血糖监测分析结果
getcgmanalysis: async (examid: string) => {
return await request.get({ url: `/system/cgm/getcgmanalysis`, params: { examid } })
}
}
}

View File

@ -44,5 +44,9 @@ export const CgmdataApi = {
// 导出CGM动态血糖数据 Excel
exportCgmdata: async (params) => {
return await request.download({ url: `/system/cgmdata/export-excel`, params })
},
// 查询CGM数据统计
getCgmStatistics: async (params: any) => {
return await request.get({ url: `/system/cgmdata/CgmStatistics`, params })
}
}
}

View File

@ -207,6 +207,7 @@ import { patientinfoApi, patientinfoVO } from '@/api/patientinfo'
import { getUserProfile, ProfileVO } from '@/api/system/user/profile'
import { Search, Refresh, Delete } from '@element-plus/icons-vue'
import { StaticecgApi } from '@/api/staticecg'
import { CgmApi } from '@/api/cgm/index'
const message = useMessage() //
@ -358,6 +359,10 @@ const handleConfirm = async () => {
// ECG
await StaticecgApi.insertEcgPatientData(selectedPatients.value)
}
if (props.type === 'cgm') {
// CGM
await CgmApi.insertCgmPatientData(selectedPatients.value)
}
handleCancel()
} catch (error) {
message.error('操作失败,请重试')

View File

@ -193,6 +193,8 @@ import PatientSelect from '@/patientcom/index.vue'
import { abpmApi, abpmVO } from '@/api/abpm'
import { getUserProfile } from '@/api/system/user/profile'
import { OrgApi } from '@/api/org'
import { AbpmdataApi } from '@/api/abpmdata'
import dayjs from 'dayjs'
const loading = ref(false)
const analysisDialogRef = ref()
@ -401,7 +403,7 @@ const cancelEditMeasureTime = (row: any, index: number) => {
delete row.originalMeasureTime
}
const onAnalyze = (row: any) => {
const onAnalyze = async (row: any) => {
//
const params = {
examid: row.examid,
@ -415,7 +417,19 @@ const onAnalyze = (row: any) => {
age: row.age,
orgname: row.orgname
}
analysisDialogRef.value?.open(params)
const data = {
examid: row.examid,
regid: row.regid,
deviceid: row.deviceid,
devicename: row.devicename,
weartime: dayjs(row.weartime).format('YYYY-MM-DD HH:mm:ss')
}
const res = await AbpmdataApi.getAbpmdataStatistics(data)
if (res && res.length > 0) {
analysisDialogRef.value?.open(params)
} else {
ElMessage.error('暂无数据')
}
}
const onViewReport = (row: any) => {
ElMessage.success(`查看报告:${row.name}`)

View File

@ -0,0 +1,444 @@
<template>
<div class="cgm-analysis">
<!-- CGM分析弹窗组件 -->
<CGM_analysis ref="cgmAnalysisRef" />
<!-- 患者选择组件后续可补充 -->
<PatientSelect
ref="patientSelectRef"
title="选择患者"
type="cgm"
:multiple="true"
:max-select="50"
@confirm="handlePatientConfirm"
@cancel="handlePatientCancel"
/>
<!-- 顶部筛选区 -->
<el-card class="filter-card" shadow="never">
<el-form :inline="true" :model="queryParams" class="filter-form">
<el-form-item label="姓名:">
<el-input
v-model="queryParams.name"
placeholder="请输入姓名"
clearable
style="width: 120px"
/>
</el-form-item>
<el-form-item label="性别:">
<el-select
v-model="queryParams.gender"
placeholder="请选择"
clearable
style="width: 100px"
>
<el-option label="男" value="1" />
<el-option label="女" value="2" />
</el-select>
</el-form-item>
<el-form-item label="日期:">
<el-date-picker
v-model="queryParams.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
style="width: 240px"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="状态:">
<el-select
v-model="queryParams.status"
placeholder="请选择"
clearable
style="width: 140px"
>
<el-option label="已申请" value="1" />
<el-option label="未申请" value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"
><el-icon><Search /></el-icon></el-button
>
<el-button @click="resetQuery"
><el-icon><Refresh /></el-icon></el-button
>
<el-button type="primary" @click="handleSelectPatients"
><el-icon><Plus /></el-icon></el-button
>
</el-form-item>
</el-form>
</el-card>
<!-- 数据表格区 -->
<el-card class="table-card" shadow="never" style="margin-top: 16px">
<el-table v-loading="loading" :data="tableData" border stripe style="width: 100%">
<el-table-column prop="examid" label="检查ID" align="center" min-width="220" />
<el-table-column prop="name" label="姓名" align="center" min-width="90" />
<el-table-column prop="gender" label="性别" align="center" min-width="60">
<template #default="{ row }">
<span>{{ row.gender === '1' ? '男' : row.gender === '2' ? '女' : '未知' }}</span>
</template>
</el-table-column>
<el-table-column prop="age" label="年龄" align="center" min-width="60">
<template #default="{ row }">
<span>{{ row.age + '岁' }}</span>
</template>
</el-table-column>
<el-table-column prop="weartime" label="佩戴时间" align="center" min-width="180">
<template #default="{ row, $index }">
<!-- 编辑状态 -->
<div v-if="row.editingMeasureTime" style="display: flex; align-items: center; gap: 8px">
<el-date-picker
v-model="row.weartime"
type="datetime"
placeholder="选择时间"
size="small"
style="width: 130px"
value-format="YYYY-MM-DD HH:mm:ss"
/>
<el-button type="primary" size="small" @click="saveMeasureTime(row, $index)" link>
<el-icon><Check /></el-icon>
</el-button>
<el-button size="small" @click="cancelEditMeasureTime(row, $index)" link>
<el-icon><Close /></el-icon>
</el-button>
</div>
<!-- 显示状态 -->
<div
v-else
style="display: flex; align-items: center; justify-content: center; gap: 8px"
>
<span>{{ formatTime(row.weartime) }}</span>
<el-button type="primary" size="small" @click="editMeasureTime(row, $index)" link>
<el-icon><Edit /></el-icon>
</el-button>
</div>
</template>
</el-table-column>
<el-table-column prop="device" label="设备" align="center" min-width="150">
<template #default="{ row, $index }">
<!-- 编辑状态 -->
<div v-if="row.editingDevice" style="display: flex; align-items: center; gap: 8px">
<el-select
v-model="row.deviceid"
placeholder="选择设备"
size="small"
style="width: 110px"
clearable
>
<el-option
v-for="item in deviceList"
:key="item.id"
:label="item.deviceName"
:value="item.id"
/>
</el-select>
<el-button type="primary" size="small" @click="saveDevice(row, $index)" link>
<el-icon><Check /></el-icon>
</el-button>
<el-button size="small" @click="cancelEditDevice(row, $index)" link>
<el-icon><Close /></el-icon>
</el-button>
</div>
<!-- 显示状态 -->
<div
v-else
style="display: flex; align-items: center; justify-content: center; gap: 8px"
>
<span>{{ row.devicename }}</span>
<el-button type="primary" size="small" @click="editDevice(row, $index)" link>
<el-icon><Edit /></el-icon>
</el-button>
</div>
</template>
</el-table-column>
<el-table-column prop="orgname" label="机构" align="center" min-width="120" />
<el-table-column label="分析" align="center" min-width="70">
<template #default="{ row }">
<el-link type="primary" @click="onAnalyze(row)">分析</el-link>
</template>
</el-table-column>
<el-table-column label="报告" align="center" min-width="70">
<template #default="{ row }">
<el-link type="primary" @click="onViewReport(row)">查看</el-link>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" align="center" min-width="70">
<template #default="{ row }">
<el-link v-if="row.status == '1'" type="success" :underline="false" disabled
>已申请</el-link
>
<el-link v-else type="primary" @click="handleApply(row)">申请</el-link>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-card>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import PatientSelect from '@/patientcom/index.vue'
import { CgmApi, CgmVO } from '@/api/cgm/index'
import { getUserProfile } from '@/api/system/user/profile'
import { OrgApi } from '@/api/org'
import { Search, Refresh, Plus, Edit, Check, Close } from '@element-plus/icons-vue'
import dayjs from 'dayjs'
import CGM_analysis from './CGM_analysis.vue'
import { CgmdataApi } from '@/api/cgmdata'
const loading = ref(false)
const total = ref(0)
//
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: '',
gender: '',
dateRange: [],
status: '',
orgid: '',
orgname: '',
age: ''
})
//
const tableData = ref<CgmVO[]>([])
const patientSelectRef = ref()
const cgmAnalysisRef = ref()
//
const deviceList = ref<any[]>([])
onMounted(() => {
getDeviceList()
getList()
})
const getDeviceList = () => {
deviceList.value = [
{ id: '1001', deviceName: 'CGM设备-1001' },
{ id: '1002', deviceName: 'CGM设备-1002' },
{ id: '1003', deviceName: 'CGM设备-1003' }
]
}
onMounted(() => {
getList()
})
//
const getList = async () => {
loading.value = true
try {
//
const userinfo = await getUserProfile()
const orginfo = await OrgApi.getOrgByOrgId(userinfo.orgid)
// ID[0]
if (userinfo.orgid != 0 && userinfo.orgid != null) {
// ID&ID&ID
if (userinfo.orgid != orginfo.parentOrgId) {
queryParams.orgid = userinfo.orgid
const data = await CgmApi.getCgmPage(queryParams)
tableData.value = data.list
total.value = data.total
} else if (userinfo.orgid == orginfo.parentOrgId) {
// &ID
const childinfo = await OrgApi.getOrgByParentOrgId(userinfo.orgid)
queryParams.orgid = childinfo.orgId
queryParams.status = '1'
const data = await CgmApi.getCgmPage(queryParams)
tableData.value = data.list
total.value = data.total
}
} else if (userinfo.orgid == 0) {
//
const data = await CgmApi.getCgmPage(queryParams)
tableData.value = data.list
total.value = data.total
} else {
console.error('用户机构为空')
return
}
} catch (error) {
console.error('获取CGM数据失败:', error)
ElMessage.error('获取数据失败')
} finally {
loading.value = false
}
}
//
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
const resetQuery = () => {
Object.assign(queryParams, {
pageNo: 1,
pageSize: 10,
name: '',
gender: '',
dateRange: [],
status: '',
age: ''
})
getList()
}
const handleSelectPatients = () => {
patientSelectRef.value?.open()
}
const handlePatientConfirm = async (selectedPatients: any[]) => {
try {
// CGM
// await CgmApi.insertCgmPatientData(selectedPatients)
ElMessage.success(`已成功添加 ${selectedPatients.length} 位患者到CGM系统`)
//
handleQuery()
} catch (error) {
console.error('添加CGM患者数据失败:', error)
ElMessage.error('添加患者数据失败,请重试')
}
}
const handlePatientCancel = () => {
handleQuery()
}
const onAnalyze = async (row: any) => {
const res = await CgmdataApi.getCgmStatistics({
examid: row.examid,
regid: row.regid,
deviceid: row.deviceid,
devicename: row.devicename,
weartime: dayjs(row.weartime).format('YYYY-MM-DD HH:mm:ss')
})
if (res && res.length > 0) {
cgmAnalysisRef.value?.open(row)
} else {
ElMessage.error('暂无数据')
}
}
const onViewReport = (row: any) => {
ElMessage.success(`查看报告:${row.name}`)
}
const handleApply = async (row: any) => {
try {
const userinfo = await getUserProfile()
const orginfo = await OrgApi.getOrg(userinfo.orgid)
if (orginfo.parentOrgId != null) {
const updateData = { ...row, status: 1, managerorg: orginfo.parentOrgId }
await CgmApi.updateCgm(updateData)
ElMessage.success(`${row.name} 申请成功`)
getList()
} else {
ElMessage.error('无上级机构')
return
}
} catch (error) {
console.error('申请失败:', error)
ElMessage.error('申请失败,请重试')
}
}
const formatTime = (timestamp: number | string) => {
if (!timestamp) return ''
const ts = typeof timestamp === 'string' ? parseInt(timestamp) : timestamp
return dayjs(ts).isValid() ? dayjs(ts).format('YYYY-MM-DD HH:mm:ss') : timestamp
}
//
const editMeasureTime = (row: any, index: number) => {
row.editingMeasureTime = true
row.originalWeartime = row.weartime //
}
//
const saveMeasureTime = async (row: any, index: number) => {
if (!row.weartime) {
ElMessage.error('佩戴时间不能为空')
return
}
try {
const timestamp =
typeof row.weartime === 'string' ? new Date(row.weartime).getTime() : row.weartime
await CgmApi.updateCgm({ ...row, weartime: timestamp })
row.weartime = timestamp //
ElMessage.success('佩戴时间更新成功')
row.editingMeasureTime = false
getList()
} catch (error) {
console.error('更新佩戴时间失败:', error)
ElMessage.error('更新佩戴时间失败,请重试')
row.weartime = row.originalWeartime //
}
}
//
const cancelEditMeasureTime = (row: any, index: number) => {
row.weartime = row.originalWeartime
row.editingMeasureTime = false
}
//
const editDevice = (row: any, index: number) => {
row.editingDevice = true
row.originalDeviceId = row.deviceid //
}
//
const saveDevice = async (row: any, index: number) => {
if (!row.deviceid) {
ElMessage.error('设备不能为空')
return
}
try {
await CgmApi.updateCgm(row)
ElMessage.success('设备更新成功')
row.editingDevice = false
getList()
} catch (error) {
console.error('更新设备失败:', error)
ElMessage.error('更新设备失败,请重试')
row.deviceid = row.originalDeviceId //
}
}
//
const cancelEditDevice = (row: any, index: number) => {
row.deviceid = row.originalDeviceId
row.editingDevice = false
}
</script>
<style scoped>
.ecg-analysis {
padding: 24px;
background: #f6f8fa;
min-height: 100vh;
}
.filter-card {
margin-bottom: 0;
background: #fff;
}
.filter-form {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 16px;
}
.table-card {
background: #fff;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -88,13 +88,71 @@
</template>
</el-table-column>
<el-table-column prop="weartime" label="佩戴时间" align="center" min-width="180">
<template #default="{ row }">
<span>{{ formatTime(row.weartime) }}</span>
<template #default="{ row, $index }">
<!-- 编辑状态 -->
<div v-if="row.editingMeasureTime" style="display: flex; align-items: center; gap: 8px">
<el-date-picker
v-model="row.weartime"
type="datetime"
placeholder="选择时间"
size="small"
style="width: 130px"
value-format="YYYY-MM-DD HH:mm:ss"
/>
<el-button type="primary" size="small" @click="saveMeasureTime(row, $index)" link>
<el-icon><Check /></el-icon>
</el-button>
<el-button size="small" @click="cancelEditMeasureTime(row, $index)" link>
<el-icon><Close /></el-icon>
</el-button>
</div>
<!-- 显示状态 -->
<div
v-else
style="display: flex; align-items: center; justify-content: center; gap: 8px"
>
<span>{{ formatTime(row.weartime) }}</span>
<el-button type="primary" size="small" @click="editMeasureTime(row, $index)" link>
<el-icon><Edit /></el-icon>
</el-button>
</div>
</template>
</el-table-column>
<el-table-column prop="device" label="设备" align="center" min-width="150">
<template #default="{ row }">
<span>{{ row.devicename }}</span>
<template #default="{ row, $index }">
<!-- 编辑状态 -->
<div v-if="row.editingDevice" style="display: flex; align-items: center; gap: 8px">
<el-select
v-model="row.deviceid"
placeholder="选择设备"
size="small"
style="width: 110px"
clearable
>
<el-option
v-for="item in deviceList"
:key="item.id"
:label="item.deviceName"
:value="item.id"
/>
</el-select>
<el-button type="primary" size="small" @click="saveDevice(row, $index)" link>
<el-icon><Check /></el-icon>
</el-button>
<el-button size="small" @click="cancelEditDevice(row, $index)" link>
<el-icon><Close /></el-icon>
</el-button>
</div>
<!-- 显示状态 -->
<div
v-else
style="display: flex; align-items: center; justify-content: center; gap: 8px"
>
<span>{{ row.devicename }}</span>
<el-button type="primary" size="small" @click="editDevice(row, $index)" link>
<el-icon><Edit /></el-icon>
</el-button>
</div>
</template>
</el-table-column>
<el-table-column prop="orgname" label="机构" align="center" min-width="120" />
@ -136,8 +194,9 @@ import ECGWorkstation from './ECG_workstation.vue'
import { StaticecgApi, StaticecgVO } from '@/api/staticecg'
import { getUserProfile } from '@/api/system/user/profile'
import { OrgApi } from '@/api/org'
import { Search, Refresh, Plus } from '@element-plus/icons-vue'
import { Search, Refresh, Plus, Edit, Check, Close } from '@element-plus/icons-vue'
import dayjs from 'dayjs'
import { StaticdataApi } from '@/api/staticdata'
const loading = ref(false)
const total = ref(0)
@ -161,8 +220,12 @@ const tableData = ref<StaticecgVO[]>([])
const patientSelectRef = ref()
const ecgWorkstationRef = ref()
//
const deviceList = ref<any[]>([])
onMounted(() => {
getList()
getDeviceList()
})
//
@ -206,6 +269,27 @@ const getList = async () => {
}
}
//
const getDeviceList = async () => {
try {
// 使
const testData = [
{ id: '1001', deviceName: '心电设备-1001' },
{ id: '1002', deviceName: '心电设备-1002' },
{ id: '1003', deviceName: '心电设备-1003' }
]
deviceList.value = testData
} catch (error) {
console.error('获取设备列表失败:', error)
deviceList.value = [
{ id: '1001', deviceName: '心电设备-1001' },
{ id: '1002', deviceName: '心电设备-1002' },
{ id: '1003', deviceName: '心电设备-1003' }
]
ElMessage.error('获取设备列表失败,已加载测试数据')
}
}
//
const handleQuery = () => {
queryParams.pageNo = 1
@ -246,19 +330,26 @@ const handlePatientConfirm = async (selectedPatients: any[]) => {
const handlePatientCancel = () => {
handleQuery()
}
const onAnalyze = (row: any) => {
// ECG
ecgWorkstationRef.value?.open(row)
//
const onAnalyze = async (row: any) => {
const res = await StaticdataApi.getStaticdataByExamidAndRegid(row.examid, row.regid)
if (res) {
ecgWorkstationRef.value?.open(row)
} else {
ElMessage.error('暂无数据')
}
}
//
const onViewReport = (row: any) => {
ElMessage.success(`查看报告:${row.name}`)
}
//
const handleApply = async (row: any) => {
try {
cc
const userinfo = await getUserProfile()
const orginfo = await OrgApi.getOrg(userinfo.orgid)
if (orginfo.parentOrgId != null) {
const updateData = { ...row, status: 1, managerorg: orginfo.parentOrgId }
await StaticecgApi.updateStaticecg(updateData)
@ -279,6 +370,70 @@ const formatTime = (timestamp: number | string) => {
const ts = typeof timestamp === 'string' ? parseInt(timestamp) : timestamp
return dayjs(ts).isValid() ? dayjs(ts).format('YYYY-MM-DD HH:mm:ss') : timestamp
}
//
const editMeasureTime = (row: any, index: number) => {
row.editingMeasureTime = true
row.originalWeartime = row.weartime //
}
//
const saveMeasureTime = async (row: any, index: number) => {
if (!row.weartime) {
ElMessage.error('佩戴时间不能为空')
return
}
try {
//
const timestamp =
typeof row.weartime === 'string' ? new Date(row.weartime).getTime() : row.weartime
await StaticecgApi.updateStaticecg({ ...row, weartime: timestamp })
row.weartime = timestamp //
ElMessage.success('佩戴时间更新成功')
row.editingMeasureTime = false
getList()
} catch (error) {
console.error('更新佩戴时间失败:', error)
ElMessage.error('更新佩戴时间失败,请重试')
row.weartime = row.originalWeartime //
}
}
//
const cancelEditMeasureTime = (row: any, index: number) => {
row.weartime = row.originalWeartime
row.editingMeasureTime = false
}
//
const editDevice = (row: any, index: number) => {
row.editingDevice = true
row.originalDeviceId = row.deviceid //
}
//
const saveDevice = async (row: any, index: number) => {
if (!row.deviceid) {
ElMessage.error('设备不能为空')
return
}
try {
await StaticecgApi.updateStaticecg(row)
ElMessage.success('设备更新成功')
row.editingDevice = false
getList()
} catch (error) {
console.error('更新设备失败:', error)
ElMessage.error('更新设备失败,请重试')
row.deviceid = row.originalDeviceId //
}
}
//
const cancelEditDevice = (row: any, index: number) => {
row.deviceid = row.originalDeviceId
row.editingDevice = false
}
</script>
<style scoped>