修改检测页
This commit is contained in:
parent
edd6ed78f4
commit
0962146d8b
@ -24,13 +24,15 @@
|
|||||||
<!-- 患者列表区域 -->
|
<!-- 患者列表区域 -->
|
||||||
<div class="patient-section">
|
<div class="patient-section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<div class="module-title">患者列表</div>
|
<div class="module-title">
|
||||||
|
<div class="module-title-text">患者列表</div>
|
||||||
|
</div>
|
||||||
<div class="search-box">
|
<div class="search-box">
|
||||||
<el-input v-model="searchKeyword" placeholder="搜索患者姓名" prefix-icon="Search" clearable
|
<el-input v-model="searchKeyword" placeholder="搜索患者姓名" prefix-icon="Search" clearable
|
||||||
@input="handleSearch" />
|
@input="handleSearch" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="filteredPatients" style="width: 100%" border @cell-click="selectPatient"
|
<el-table ref="tableRef" :data="filteredPatients" style="width: 100%" border @cell-click="selectPatient"
|
||||||
highlight-current-row>
|
highlight-current-row>
|
||||||
<el-table-column prop="name" label="姓名" min-width="60" />
|
<el-table-column prop="name" label="姓名" min-width="60" />
|
||||||
<el-table-column prop="id" label="测试者ID" min-width="60" />
|
<el-table-column prop="id" label="测试者ID" min-width="60" />
|
||||||
@ -49,7 +51,9 @@
|
|||||||
<div class="patient-detail" v-if="selectedPatient">
|
<div class="patient-detail" v-if="selectedPatient">
|
||||||
<div class="patient-detail-box">
|
<div class="patient-detail-box">
|
||||||
<div class="detail-header">
|
<div class="detail-header">
|
||||||
<div class="module-title">基础信息</div>
|
<div class="module-title">
|
||||||
|
<div class="module-title-text">基础信息</div>
|
||||||
|
</div>
|
||||||
<el-button link @click="editPatient">
|
<el-button link @click="editPatient">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Edit />
|
<Edit />
|
||||||
@ -133,6 +137,112 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<el-dialog v-model="dialogVisible" title="编辑基础信息" width="50%" :before-close="handleClose">
|
||||||
|
<div class="form-box" style="margin-top: 10px;">
|
||||||
|
<el-form ref="patientFormRef" :model="patientForm" :rules="formRules" label-width="100px" class="patient-form">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="测试者ID" prop="testerId">
|
||||||
|
<el-input v-model="patientForm.id" disabled placeholder="请输入测试者ID" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="姓名" prop="name" required>
|
||||||
|
<el-input v-model="patientForm.name" placeholder="请输入" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="性别" prop="gender" required>
|
||||||
|
<el-select v-model="patientForm.gender" placeholder="请选择">
|
||||||
|
<el-option label="男" value="男" />
|
||||||
|
<el-option label="女" value="女" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="出生日期" prop="birth_date" required>
|
||||||
|
<el-date-picker v-model="patientForm.birth_date" type="date" placeholder="请选择" style="width: 100%"
|
||||||
|
@change="calculateAgeres" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="年龄">
|
||||||
|
<el-input v-model="calculatedAge" placeholder="自动计算" readonly suffix-icon="Calendar" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="民族" prop="nationality">
|
||||||
|
<el-select v-model="patientForm.nationality" placeholder="请选择">
|
||||||
|
<el-option v-for="item in nationalityOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="长期居住地" prop="residence">
|
||||||
|
<el-input v-model="patientForm.residence" placeholder="请输入" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="身高" prop="height" required>
|
||||||
|
<el-input v-model="patientForm.height" placeholder="请输入" clearable>
|
||||||
|
<template #suffix>cm</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="体重" prop="weight" required>
|
||||||
|
<el-input v-model="patientForm.weight" placeholder="请输入" clearable>
|
||||||
|
<template #suffix>kg</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="鞋码" prop="shoe_size">
|
||||||
|
<el-input v-model="patientForm.shoe_size" placeholder="请输入" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="电话号码" prop="phone" required>
|
||||||
|
<el-input v-model="patientForm.phone" placeholder="请输入" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="电子邮箱" prop="email">
|
||||||
|
<el-input v-model="patientForm.email" placeholder="请输入" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="职业" prop="occupation">
|
||||||
|
<el-select v-model="patientForm.occupation" placeholder="请选择">
|
||||||
|
<el-option v-for="item in occupationOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="单位" prop="workplace">
|
||||||
|
<el-input v-model="patientForm.workplace" placeholder="请输入" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="handleClose" style="margin-right: 20px;">退出</el-button>
|
||||||
|
<el-button type="primary" @click="handleSave" :loading="saveLoading">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -155,7 +265,83 @@ const userInfo = reactive({
|
|||||||
username: '医生',
|
username: '医生',
|
||||||
avatar: ''
|
avatar: ''
|
||||||
})
|
})
|
||||||
|
const tableRef = ref(null)
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
// 表单引用
|
||||||
|
const patientFormRef = ref()
|
||||||
|
// 表单数据
|
||||||
|
const saveLoading = ref(false)
|
||||||
|
const patientForm = ref({
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
gender: '',
|
||||||
|
birth_date: '',
|
||||||
|
nationality: '',
|
||||||
|
residence: '',
|
||||||
|
height: '',
|
||||||
|
weight: '',
|
||||||
|
shoe_size: '',
|
||||||
|
phone: '',
|
||||||
|
occupation: '',
|
||||||
|
workplace: '',
|
||||||
|
email: ''
|
||||||
|
})
|
||||||
|
const occupationOptions = ref([
|
||||||
|
{ label: '学生', value: '学生' }
|
||||||
|
])
|
||||||
|
const residenceOptions = ref([
|
||||||
|
{ label: '北京', value: '北京' }
|
||||||
|
])
|
||||||
|
const nationalityOptions = ref([
|
||||||
|
{ label: '汉族', value: '汉族' }
|
||||||
|
])
|
||||||
|
// 表单验证规则
|
||||||
|
const formRules = {
|
||||||
|
name: [
|
||||||
|
{ required: true, message: '请输入患者姓名', trigger: 'blur' },
|
||||||
|
{ min: 2, max: 20, message: '姓名长度在 2 到 20 个字符', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
gender: [
|
||||||
|
{ required: true, message: '请选择性别', trigger: 'change' }
|
||||||
|
],
|
||||||
|
birthDate: [
|
||||||
|
{ required: true, message: '请选择出生日期', trigger: 'change' }
|
||||||
|
],
|
||||||
|
height: [
|
||||||
|
{ required: true, message: '请输入身高', trigger: 'blur' },
|
||||||
|
{ pattern: /^\d+(\.\d+)?$/, message: '请输入有效的身高', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
weight: [
|
||||||
|
{ required: true, message: '请输入体重', trigger: 'blur' },
|
||||||
|
{ pattern: /^\d+(\.\d+)?$/, message: '请输入有效的体重', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
phone: [
|
||||||
|
{ required: true, message: '请输入联系电话', trigger: 'blur' },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const validateForm = async () => {
|
||||||
|
try {
|
||||||
|
await patientFormRef.value.validate()
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('请完善必填信息')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const calculatedAge = ref('')
|
||||||
|
// 实现年龄计算方法 calculateAgeres
|
||||||
|
const calculateAgeres = (date) => {
|
||||||
|
if (!date) return '0'
|
||||||
|
const today = new Date()
|
||||||
|
const birthDate = new Date(date)
|
||||||
|
let age = today.getFullYear() - birthDate.getFullYear()
|
||||||
|
const monthDiff = today.getMonth() - birthDate.getMonth()
|
||||||
|
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
||||||
|
age--
|
||||||
|
}
|
||||||
|
calculatedAge.value = age
|
||||||
|
}
|
||||||
// 计算属性
|
// 计算属性
|
||||||
const filteredPatients = computed(() => {
|
const filteredPatients = computed(() => {
|
||||||
if (!searchKeyword.value) {
|
if (!searchKeyword.value) {
|
||||||
@ -181,11 +367,71 @@ const selectPatient = (patient) => {
|
|||||||
|
|
||||||
|
|
||||||
const editPatient = () => {
|
const editPatient = () => {
|
||||||
router.push(`/patient/edit/${selectedPatient.value.id}`)
|
// router.push(`/patient/edit/${selectedPatient.value.id}`)
|
||||||
|
// 修改选中患者信息
|
||||||
|
patientForm.value = JSON.parse(JSON.stringify(selectedPatient.value))
|
||||||
|
if (patientForm.value.birth_date) {
|
||||||
|
calculatedAge.value = calculateAgeres(patientForm.value.birth_date)
|
||||||
|
}
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (!(await validateForm())) return
|
||||||
|
saveLoading.value = true
|
||||||
|
try {
|
||||||
|
await savePatient()
|
||||||
|
ElMessage.success('修改成功')
|
||||||
|
dialogVisible.value = false
|
||||||
|
saveLoading.value = false
|
||||||
|
await loadPatients()
|
||||||
|
if (patients.value.length > 0 && selectedPatient.value.id) {
|
||||||
|
for (var i = 0; i < patients.value.length; i++) {
|
||||||
|
if (patients.value[i].id === selectedPatient.value.id) {
|
||||||
|
selectedPatient.value = patients.value[i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
tableRef.value.setCurrentRow(selectedPatient.value)
|
||||||
|
}, 300)
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('修改失败:' + error.message)
|
||||||
|
saveLoading.value = false
|
||||||
|
} finally {
|
||||||
|
saveLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const savePatient = async () => {
|
||||||
|
const patientData = {
|
||||||
|
id: patientForm.value.id,
|
||||||
|
name: patientForm.value.name,
|
||||||
|
gender: patientForm.value.gender,
|
||||||
|
age: calculatedAge.value,
|
||||||
|
birth_date: patientForm.value.birth_date,
|
||||||
|
height: patientForm.value.height,
|
||||||
|
weight: patientForm.value.weight,
|
||||||
|
shoe_size: patientForm.value.shoe_size,
|
||||||
|
phone: patientForm.value.phone,
|
||||||
|
occupation: patientForm.value.occupation,
|
||||||
|
email: patientForm.value.email,
|
||||||
|
nationality: patientForm.value.nationality,
|
||||||
|
residence: patientForm.value.residence,
|
||||||
|
workplace: patientForm.value.workplace
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const response = await patientAPI.updatePatient(patientForm.value.id, patientData)
|
||||||
|
if (response.success) {
|
||||||
|
return response.data
|
||||||
|
} else {
|
||||||
|
throw new Error(response.message || '修改失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewPatientProfile = () => {
|
const viewPatientProfile = () => {
|
||||||
router.push(`/patient/profile/${selectedPatient.value.id}`)
|
router.push(`/patient/${selectedPatient.value.id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const startDetection = () => {
|
const startDetection = () => {
|
||||||
@ -310,7 +556,10 @@ const loadPatients = async () => {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const handleClose = () => {
|
||||||
|
patientFormRef.value?.resetFields()
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
// 生命周期
|
// 生命周期
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 从认证状态管理中加载用户信息
|
// 从认证状态管理中加载用户信息
|
||||||
@ -330,7 +579,7 @@ function delClick(id) {
|
|||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
try {
|
try {
|
||||||
const response = await patientAPI.deletePatient(id);
|
const response = await patientAPI.deletePatient(id);
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
@ -603,7 +852,7 @@ function delClick(id) {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
border-bottom: 1px solid #e4e7ed;
|
border-bottom: 1px solid #434343;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-header h3 {
|
.detail-header h3 {
|
||||||
@ -689,13 +938,22 @@ function delClick(id) {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border: 2px solid #ffffff;
|
/* border: 2px solid #ffffff; */
|
||||||
border-image: linear-gradient(to right, rgb(245, 173, 7), rgb(160, 5, 216)) 1;
|
background: linear-gradient(to right, rgb(245, 173, 7), rgb(160, 5, 216));
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 1px 10px;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-title-text {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 116px;
|
||||||
|
background: #2C2C2C;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 0px 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-input__wrapper) {
|
:deep(.el-input__wrapper) {
|
||||||
@ -763,6 +1021,60 @@ function delClick(id) {
|
|||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
font-family: 'Arial Normal', 'Arial', sans-serif;
|
font-family: 'Arial Normal', 'Arial', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 必填项标识 */
|
||||||
|
:deep(.el-form-item.is-required .el-form-item__label::before) {
|
||||||
|
content: '*';
|
||||||
|
color: #f56c6c;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
background-color: rgba(51, 51, 51, 1);
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: rgba(127, 127, 127, 1);
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-select__wrapper) {
|
||||||
|
background-color: rgba(51, 51, 51, 1);
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: rgba(127, 127, 127, 1);
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item__label) {
|
||||||
|
font-size: 14px;
|
||||||
|
font-family: '苹方 粗体', '苹方 中等', '苹方', sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-col-12) {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__inner) {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-select__placeholder) {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input.is-disabled .el-input__wrapper) {
|
||||||
|
background-color: rgba(127, 127, 127, 1);
|
||||||
|
box-shadow: none;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: rgba(215, 215, 215, 1);
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
@ -817,15 +1129,45 @@ function delClick(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-container.dashboard-container-home .el-input__wrapper {
|
.dashboard-container.dashboard-container-home .el-input__wrapper {
|
||||||
box-shadow: 0 0 0 1px #787878;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
.dashboard-container.dashboard-container-home .el-table__cell{
|
|
||||||
|
.dashboard-container.dashboard-container-home .el-table__cell {
|
||||||
border-bottom: 1px solid #787878;
|
border-bottom: 1px solid #787878;
|
||||||
}
|
}
|
||||||
.dashboard-container.dashboard-container-home .el-table__cell{
|
|
||||||
|
.dashboard-container.dashboard-container-home .el-table__cell {
|
||||||
border-bottom: 1px solid #787878;
|
border-bottom: 1px solid #787878;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-container.dashboard-container-home .el-table__header th {
|
.dashboard-container.dashboard-container-home .el-table__header th {
|
||||||
border-color: #787878;
|
border-color: #787878;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-container.dashboard-container-home .el-dialog {
|
||||||
|
background-color: rgba(85, 85, 85, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-container.dashboard-container-home .el-dialog__title {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-container.dashboard-container-home .el-dialog__headerbtn .el-dialog__close {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-container.dashboard-container-home .el-dialog__footer {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-container.dashboard-container-home .dialog-footer .el-button {
|
||||||
|
background: linear-gradient(to right, #F135A6, #A005D8);
|
||||||
|
border: none;
|
||||||
|
color: #ffffff;
|
||||||
|
height: 55px;
|
||||||
|
width: 190px;
|
||||||
|
border-radius: 50px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-family: 'Arial Normal', 'Arial', sans-serif;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -1,37 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="dashboard-container">
|
<div class="dashboard-container">
|
||||||
<!-- 左侧导航栏 -->
|
<Header />
|
||||||
<aside class="sidebar">
|
|
||||||
<div class="sidebar-item active">
|
|
||||||
<el-icon class="sidebar-icon"><UserFilled /></el-icon>
|
|
||||||
<span class="sidebar-text">检测</span>
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
<!-- 主内容区域 -->
|
<!-- 主内容区域 -->
|
||||||
<div class="main-content">
|
<div class="main-content">
|
||||||
<!-- 顶部工具栏 -->
|
<!-- 顶部工具栏 -->
|
||||||
|
|
||||||
<header class="top-bar">
|
<header class="top-bar">
|
||||||
<div style="display: flex;align-items: center;">
|
<div style="display: flex;align-items: center;">
|
||||||
<div class="top-bar-left" @click="routeTo('/')">
|
<div v-if="!isRecording" class="top-bar-left" @click="routeTo('/')">
|
||||||
<el-icon class="back-icon" @click="handleBack"><ArrowLeft /></el-icon>
|
<img src="@/assets/svg/goback.svg" alt="">
|
||||||
|
<!-- <el-icon class="back-icon" @click="handleBack"><ArrowLeft /></el-icon> -->
|
||||||
<span class="page-title">实时检测</span>
|
<span class="page-title">实时检测</span>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- <div >
|
||||||
|
{{ formattedTime }}
|
||||||
|
</div> -->
|
||||||
<el-button
|
<el-button
|
||||||
v-if="!isStart"
|
v-if="!isRecording"
|
||||||
@click="handleStartStop"
|
@click="handleStartStop"
|
||||||
:disabled="!isConnected"
|
:disabled="!isConnected"
|
||||||
type="primary"
|
type="primary"
|
||||||
class="start-btn"
|
class="start-btn"
|
||||||
style="background-image: linear-gradient(to right, rgb(236, 50, 166), rgb(160, 5, 216));
|
style="background-image: linear-gradient(to right, rgb(236, 50, 166), rgb(160, 5, 216));
|
||||||
--el-button-border-color: #409EFF;
|
--el-button-border-color: #409EFF;
|
||||||
--el-button-border-color: transparent "
|
--el-button-border-color: transparent;"
|
||||||
>
|
>
|
||||||
{{ isConnected ? '开始检测' : '连接中...' }}
|
{{ isConnected ? '开始' : '连接中saveRecording...' }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<!-- handleStartStop -->
|
||||||
<el-button
|
<el-button
|
||||||
v-if="isStart"
|
v-if="isRecording"
|
||||||
@click="handleStartStop"
|
@click="handleStartStop"
|
||||||
type="primary"
|
type="primary"
|
||||||
class="start-btn"
|
class="start-btn"
|
||||||
@ -39,9 +36,20 @@
|
|||||||
--el-button-border-color: #409EFF;
|
--el-button-border-color: #409EFF;
|
||||||
--el-button-border-color: transparent "
|
--el-button-border-color: transparent "
|
||||||
>
|
>
|
||||||
停止检测
|
结束
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
|
v-if="isStart && isConnected"
|
||||||
|
@click="handleDataCollection"
|
||||||
|
type="primary"
|
||||||
|
class="start-btn"
|
||||||
|
style="background-image: linear-gradient(to right, #FBB106, #A817C6);
|
||||||
|
--el-button-border-color: #409EFF;
|
||||||
|
--el-button-border-color: transparent "
|
||||||
|
>
|
||||||
|
保存数据
|
||||||
|
</el-button>
|
||||||
|
<!-- <el-button
|
||||||
@click="handleStartStopRecording"
|
@click="handleStartStopRecording"
|
||||||
:disabled="!isConnected"
|
:disabled="!isConnected"
|
||||||
type="warning"
|
type="warning"
|
||||||
@ -51,8 +59,8 @@
|
|||||||
--el-button-border-color: transparent; margin-left: 10px;"
|
--el-button-border-color: transparent; margin-left: 10px;"
|
||||||
>
|
>
|
||||||
{{ isRecording ? '停止录制' : '开始录制' }}
|
{{ isRecording ? '停止录制' : '开始录制' }}
|
||||||
</el-button>
|
</el-button> -->
|
||||||
<el-button
|
<!-- <el-button
|
||||||
v-if="isStart == true"
|
v-if="isStart == true"
|
||||||
@click="handleDataCollection"
|
@click="handleDataCollection"
|
||||||
:loading="dataCollectionLoading"
|
:loading="dataCollectionLoading"
|
||||||
@ -62,7 +70,7 @@
|
|||||||
--el-button-border-color: transparent; margin-left: 10px;"
|
--el-button-border-color: transparent; margin-left: 10px;"
|
||||||
>
|
>
|
||||||
检测数据采集
|
检测数据采集
|
||||||
</el-button>
|
</el-button> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@ -331,6 +339,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<el-dialog v-model="dialogVisible" center title="诊断信息" width="600" :before-close="handleClose" >
|
||||||
|
<div>
|
||||||
|
<div class="dialog-title">
|
||||||
|
<div class="dialog-title-item"><div>用户ID:</div>{{patientInfo.sessionId}}</div>
|
||||||
|
<div class="dialog-title-item"><div>姓名:{{patientInfo.name}}</div></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-form :model="diagnosticForm" label-width="50px">
|
||||||
|
<el-form-item label="记录">
|
||||||
|
<el-input v-model="diagnosticForm.textarea" :rows="6" type="textarea" placeholder="请输入"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="处理">
|
||||||
|
<el-input v-model="diagnosticForm.textarea" :rows="6" type="textarea" placeholder="请输入"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="建议">
|
||||||
|
<el-input v-model="diagnosticForm.textarea" :rows="6" type="textarea" placeholder="请输入"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex;justify-content: flex-end;">测试医生:李四</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">取消</el-button>
|
||||||
|
<el-button @click="handleDataCollection">暂存</el-button>
|
||||||
|
<el-button type="primary" @click="handleDataCollection">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -340,9 +379,11 @@ import { ElMessage } from 'element-plus'
|
|||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { io } from 'socket.io-client'
|
import { io } from 'socket.io-client'
|
||||||
import html2canvas from 'html2canvas'
|
import html2canvas from 'html2canvas'
|
||||||
|
import Header from '@/views/Header.vue'
|
||||||
|
import { useAuthStore } from '../stores/index.js'
|
||||||
|
const authStore = useAuthStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const isStart = ref(false)
|
const isStart = ref(false)
|
||||||
const isConnected = ref(false)
|
const isConnected = ref(false)
|
||||||
const rtspImgSrc = ref('')
|
const rtspImgSrc = ref('')
|
||||||
@ -378,10 +419,14 @@ let socket = null
|
|||||||
let frameCount = 0
|
let frameCount = 0
|
||||||
|
|
||||||
// 后端服务器地址配置
|
// 后端服务器地址配置
|
||||||
const BACKEND_URL = 'http://localhost:5000'
|
const BACKEND_URL = 'http://192.168.1.173:5000'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const formattedTime = ref(0)
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const handleClose = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
const diagnosticForm = ref({})
|
||||||
// 模拟历史数据
|
// 模拟历史数据
|
||||||
const historyData = ref([
|
const historyData = ref([
|
||||||
{ id: 3, rotLeft: '-55.2°', rotRight: '54.2°', tiltLeft: '-17.7°', tiltRight: '18.2°', pitchDown: '-20.2°', pitchUp: '10.5°' },
|
{ id: 3, rotLeft: '-55.2°', rotRight: '54.2°', tiltLeft: '-17.7°', tiltRight: '18.2°', pitchDown: '-20.2°', pitchUp: '10.5°' },
|
||||||
@ -568,7 +613,6 @@ function handleStartStopRecording() {
|
|||||||
// 检测数据采集功能
|
// 检测数据采集功能
|
||||||
async function handleDataCollection() {
|
async function handleDataCollection() {
|
||||||
if (dataCollectionLoading.value) return
|
if (dataCollectionLoading.value) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dataCollectionLoading.value = true
|
dataCollectionLoading.value = true
|
||||||
|
|
||||||
@ -587,8 +631,11 @@ async function handleDataCollection() {
|
|||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
patient_id: patientInfo.value.id,
|
// patient_id: patientInfo.value.id,
|
||||||
timestamp: Date.now()
|
// timestamp: Date.now()
|
||||||
|
head_pose:{},
|
||||||
|
body_pose:{},
|
||||||
|
foot_data:{}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -934,7 +981,6 @@ function stopRecording() {
|
|||||||
saveRecording()
|
saveRecording()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recordingStream) {
|
if (recordingStream) {
|
||||||
recordingStream.getTracks().forEach(track => track.stop())
|
recordingStream.getTracks().forEach(track => track.stop())
|
||||||
recordingStream = null
|
recordingStream = null
|
||||||
@ -955,7 +1001,7 @@ async function saveRecording() {
|
|||||||
if (recordedChunks.length === 0) {
|
if (recordedChunks.length === 0) {
|
||||||
throw new Error('没有录制数据')
|
throw new Error('没有录制数据')
|
||||||
}
|
}
|
||||||
|
console.log()
|
||||||
// 验证必需的患者信息
|
// 验证必需的患者信息
|
||||||
if (!patientInfo.value.id || !patientInfo.value.name || !patientInfo.value.sessionId) {
|
if (!patientInfo.value.id || !patientInfo.value.name || !patientInfo.value.sessionId) {
|
||||||
throw new Error(`缺少必需的患者信息: ID=${patientInfo.value.id}, 姓名=${patientInfo.value.name}, 会话ID=${patientInfo.value.sessionId}`)
|
throw new Error(`缺少必需的患者信息: ID=${patientInfo.value.id}, 姓名=${patientInfo.value.name}, 会话ID=${patientInfo.value.sessionId}`)
|
||||||
@ -1006,7 +1052,7 @@ async function saveRecording() {
|
|||||||
message: `录像保存成功!文件路径: ${result.filepath}`,
|
message: `录像保存成功!文件路径: ${result.filepath}`,
|
||||||
duration: 5000
|
duration: 5000
|
||||||
})
|
})
|
||||||
|
dialogVisible.value = false
|
||||||
// 更新会话的视频路径
|
// 更新会话的视频路径
|
||||||
if (patientInfo.value.sessionId) {
|
if (patientInfo.value.sessionId) {
|
||||||
try {
|
try {
|
||||||
@ -1015,15 +1061,15 @@ async function saveRecording() {
|
|||||||
console.error('更新会话视频路径失败:', error)
|
console.error('更新会话视频路径失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空录制数据,避免重复保存
|
// 清空录制数据,避免重复保存
|
||||||
recordedChunks.length = 0
|
recordedChunks.length = 0
|
||||||
console.log('🧹 录像数据已清空')
|
console.log('🧹 录像数据已清空')
|
||||||
|
|
||||||
// 录像保存完成后,清空会话ID,正式结束会话
|
// 录像保存完成后,清空会话ID,正式结束会话
|
||||||
patientInfo.value.sessionId = null
|
// patientInfo.value.sessionId = null
|
||||||
console.log('✅ 会话正式结束,会话ID已清空')
|
console.log('✅ 会话正式结束,会话ID已清空')
|
||||||
} else {
|
} else {
|
||||||
|
dialogVisible.value = false
|
||||||
throw new Error(result.message || '保存失败')
|
throw new Error(result.message || '保存失败')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1033,7 +1079,7 @@ async function saveRecording() {
|
|||||||
message: `保存录像失败: ${error.message}`,
|
message: `保存录像失败: ${error.message}`,
|
||||||
duration: 5000
|
duration: 5000
|
||||||
})
|
})
|
||||||
|
dialogVisible.value = false
|
||||||
// 即使保存失败,也要清空会话ID,避免状态混乱
|
// 即使保存失败,也要清空会话ID,避免状态混乱
|
||||||
patientInfo.value.sessionId = null
|
patientInfo.value.sessionId = null
|
||||||
console.log('⚠️ 录像保存失败,但会话已结束,会话ID已清空')
|
console.log('⚠️ 录像保存失败,但会话已结束,会话ID已清空')
|
||||||
@ -1059,6 +1105,7 @@ async function saveRecording() {
|
|||||||
|
|
||||||
// 处理开始/停止按钮点击
|
// 处理开始/停止按钮点击
|
||||||
async function handleStartStop() {
|
async function handleStartStop() {
|
||||||
|
patientInfo.value.sessionId = null
|
||||||
if (!isConnected.value) {
|
if (!isConnected.value) {
|
||||||
ElMessage.warning('WebSocket未连接,无法操作')
|
ElMessage.warning('WebSocket未连接,无法操作')
|
||||||
return
|
return
|
||||||
@ -1072,17 +1119,14 @@ async function handleStartStop() {
|
|||||||
await startDetection()
|
await startDetection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始检测
|
// 开始检测
|
||||||
async function startDetection() {
|
async function startDetection() {
|
||||||
try {
|
try {
|
||||||
console.log('🚀 正在开始检测...')
|
console.log('🚀 正在开始检测...')
|
||||||
|
|
||||||
// 验证患者信息
|
// 验证患者信息
|
||||||
if (!patientInfo.value || !patientInfo.value.id) {
|
if (!patientInfo.value || !patientInfo.value.id) {
|
||||||
throw new Error('缺少患者信息,无法开始检测')
|
throw new Error('缺少患者信息,无法开始检测')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用后端API开始检测
|
// 调用后端API开始检测
|
||||||
const response = await fetch(`${BACKEND_URL}/api/detection/start`, {
|
const response = await fetch(`${BACKEND_URL}/api/detection/start`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -1090,31 +1134,31 @@ async function startDetection() {
|
|||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
patientId: patientInfo.value.id,
|
patient_id: patientInfo.value.id,
|
||||||
// 可以添加其他检测参数
|
// 可以添加其他检测参数
|
||||||
settings: JSON.stringify({
|
creator_id:creatorId.value,
|
||||||
frequency: 30, // 采样频率
|
// settings: JSON.stringify({
|
||||||
// 其他设置参数
|
// frequency: 30, // 采样频率
|
||||||
})
|
// // 其他设置参数
|
||||||
|
// })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
console.log('✅ 检测开始成功')
|
console.log('✅ 检测开始成功')
|
||||||
|
|
||||||
// 保存会话ID和检测开始时间
|
// 保存会话ID和检测开始时间
|
||||||
patientInfo.value.sessionId = result.data.session_id
|
patientInfo.value.sessionId = result.session_id
|
||||||
patientInfo.value.detectionStartTime = Date.now()
|
patientInfo.value.detectionStartTime = Date.now()
|
||||||
console.log('✅ 检测会话创建成功,会话ID:', patientInfo.value.sessionId)
|
console.log('✅ 检测会话创建成功,会话ID:', patientInfo.value.sessionId)
|
||||||
|
|
||||||
isStart.value = true
|
isStart.value = true
|
||||||
|
startRecording()
|
||||||
ElMessage.success('检测已开始')
|
ElMessage.success('检测已开始')
|
||||||
} else {
|
} else {
|
||||||
throw new Error(result.message || '开始检测失败')
|
throw new Error(result.message || '开始检测失败')
|
||||||
@ -1161,16 +1205,18 @@ async function stopDetection() {
|
|||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
console.log('✅ 检测会话已停止')
|
console.log('✅ 检测会话已停止')
|
||||||
|
//停止弹出诊断信息
|
||||||
|
dialogVisible.value = true
|
||||||
if (result.duration) {
|
if (result.duration) {
|
||||||
console.log(`⏱️ 检测持续时间: ${result.duration}秒`)
|
console.log(`⏱️ 检测持续时间: ${result.duration}秒`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dialogVisible.value = true
|
||||||
// 清除检测开始时间和会话ID
|
// 清除检测开始时间和会话ID
|
||||||
patientInfo.value.detectionStartTime = null
|
patientInfo.value.detectionStartTime = null
|
||||||
patientInfo.value.sessionId = null
|
// patientInfo.value.sessionId = null
|
||||||
|
|
||||||
ElMessage.success('检测已停止,视频继续播放')
|
ElMessage.success('检测已停止,视频继续播放')
|
||||||
|
|
||||||
@ -1233,7 +1279,7 @@ const handleBeforeUnload = () => {
|
|||||||
socket.disconnect()
|
socket.disconnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const creatorId = ref('')
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 加载患者信息
|
// 加载患者信息
|
||||||
loadPatientInfo()
|
loadPatientInfo()
|
||||||
@ -1243,6 +1289,10 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 监听页面关闭或刷新事件
|
// 监听页面关闭或刷新事件
|
||||||
window.addEventListener('beforeunload', handleBeforeUnload)
|
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||||
|
if (authStore.currentUser) {
|
||||||
|
console.log(authStore.currentUser)
|
||||||
|
creatorId.value = authStore.currentUser.id
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
@ -1274,9 +1324,9 @@ onUnmounted(() => {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
/* 全局容器 */
|
/* 全局容器 */
|
||||||
.dashboard-container {
|
.dashboard-container {
|
||||||
display: flex;
|
/* display: flex; */
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: #1E1E1E;
|
background-color: #000000;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1324,7 +1374,7 @@ onUnmounted(() => {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
background-color: #2C2C2C;
|
background-color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-bar-left {
|
.top-bar-left {
|
||||||
@ -1341,6 +1391,7 @@ onUnmounted(() => {
|
|||||||
.page-title {
|
.page-title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.start-btn {
|
.start-btn {
|
||||||
@ -1357,7 +1408,7 @@ onUnmounted(() => {
|
|||||||
.info-item {
|
.info-item {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
color: #CCCCCC;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-icon {
|
.top-icon {
|
||||||
@ -1682,6 +1733,15 @@ onUnmounted(() => {
|
|||||||
align-content: center;
|
align-content: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
.dialog-title{
|
||||||
|
display: flex;
|
||||||
|
justify-content:space-between ;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.dialog-title-item{
|
||||||
|
display: flex;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
@ -1704,4 +1764,11 @@ onUnmounted(() => {
|
|||||||
.el-table td.el-table__cell, .el-table th.el-table__cell.is-leaf{
|
.el-table td.el-table__cell, .el-table th.el-table__cell.is-leaf{
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
.top-bar .el-button{
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 25px;
|
||||||
|
font-size: 28px;
|
||||||
|
border-radius:20px;
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -17,8 +17,11 @@
|
|||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<el-form ref="patientFormRef" :model="patientForm" :rules="formRules" label-width="120px" class="patient-form">
|
<el-form ref="patientFormRef" :model="patientForm" :rules="formRules" label-width="120px" class="patient-form">
|
||||||
<div class="form-section">
|
<div class="form-section">
|
||||||
<!-- <h3 class="section-title">基本信息</h3> -->
|
<div class="section-title">
|
||||||
<div class="section-title">基本信息</div>
|
<div class="section-title-text">
|
||||||
|
基本信息
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@ -63,10 +66,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="长期居住地" prop="residence">
|
<el-form-item label="长期居住地" prop="residence">
|
||||||
<el-select v-model="patientForm.residence" placeholder="请选择">
|
<el-input v-model="patientForm.residence" placeholder="请输入" clearable />
|
||||||
<el-option v-for="item in residenceOptions" :key="item.value" :label="item.label"
|
|
||||||
:value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@ -334,6 +334,7 @@ const handleSaveAndDetect = async () => {
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
width: calc(100% - 500px);
|
width: calc(100% - 500px);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-container-info {
|
.nav-container-info {
|
||||||
@ -391,16 +392,25 @@ const handleSaveAndDetect = async () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border: 2px solid #ffffff;
|
/* border: 2px solid #ffffff; */
|
||||||
border-image: linear-gradient(to right, rgb(245, 173, 7), rgb(160, 5, 216)) 1;
|
background: linear-gradient(to right, rgb(245, 173, 7), rgb(160, 5, 216));
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 1px 10px;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
|
padding: 2px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section-title-text {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 116px;
|
||||||
|
background: #2C2C2C;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 0px 25px;
|
||||||
|
}
|
||||||
|
|
||||||
.footer-actions {
|
.footer-actions {
|
||||||
height: 142px;
|
height: 142px;
|
||||||
background: #000000;
|
background: #000000;
|
||||||
@ -412,8 +422,9 @@ const handleSaveAndDetect = async () => {
|
|||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
:deep(.footer-actions .el-button){
|
|
||||||
background: linear-gradient(to right,#F135A6,#A005D8,#A005D8);
|
:deep(.footer-actions .el-button) {
|
||||||
|
background: linear-gradient(to right, #F135A6, #A005D8);
|
||||||
border: none;
|
border: none;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="patient-profile-container">
|
<div class="patient-profile-container">
|
||||||
<!-- 顶部导航 -->
|
<!-- 顶部导航 -->
|
||||||
<div class="header">
|
<Header />
|
||||||
<div class="header-left">
|
<div class="nav-container">
|
||||||
<el-button link @click="goBack" class="back-btn">
|
<div class="nav-container-title" @click="goBack">
|
||||||
<el-icon><ArrowLeft /></el-icon>
|
<img src="@/assets/svg/goback.svg" alt="">
|
||||||
返回
|
<div style="margin-left: 20px;">
|
||||||
</el-button>
|
患者档案
|
||||||
<h1 class="page-title">患者档案</h1>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="nav-container-info">
|
||||||
<el-button type="primary" @click="startDetection">
|
<div>测试时间:2025-08-03 17:13:18<span></span></div>
|
||||||
<el-icon><Monitor /></el-icon>
|
<div style="margin-left: 15px;">测试医生:<span>李医生</span></div>
|
||||||
开始检测
|
|
||||||
</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="main-content">
|
||||||
<div class="main-content" v-if="patient">
|
<!-- <div v-for="value in source">
|
||||||
|
{{}}
|
||||||
|
</div> -->
|
||||||
<!-- 患者基本信息 -->
|
<!-- 患者基本信息 -->
|
||||||
<div class="patient-info-card">
|
<div v-if="patient" class="patient-info-card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>基本信息</h2>
|
<h2>基本信息</h2>
|
||||||
<el-button link @click="editPatient">
|
<el-button link @click="editPatient">
|
||||||
@ -70,7 +70,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 检测记录 -->
|
<!-- 检测记录 -->
|
||||||
<div class="detection-records-card">
|
<div class="detection-records-card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
@ -142,11 +141,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 加载状态 -->
|
|
||||||
<div v-else class="loading-container">
|
|
||||||
<el-loading-service lock="true" text="加载患者信息中..." />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 视频播放对话框 -->
|
<!-- 视频播放对话框 -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="videoDialogVisible"
|
v-model="videoDialogVisible"
|
||||||
@ -238,6 +232,7 @@ import { ref, reactive, computed, onMounted } from 'vue'
|
|||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { patientAPI, detectionAPI } from '../services/api.js'
|
import { patientAPI, detectionAPI } from '../services/api.js'
|
||||||
|
import Header from '@/views/Header.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@ -396,6 +391,7 @@ const loadPatientInfo = async () => {
|
|||||||
const response = await patientAPI.getById(patientId)
|
const response = await patientAPI.getById(patientId)
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
patient.value = response.data
|
patient.value = response.data
|
||||||
|
console.log('加载患者信息成功:', response.data)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.message)
|
throw new Error(response.message)
|
||||||
}
|
}
|
||||||
@ -494,9 +490,32 @@ onMounted(() => {
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: #f5f7fa;
|
background: #000000;
|
||||||
|
}
|
||||||
|
.nav-container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 15px 20px 0px;
|
||||||
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-container-title {
|
||||||
|
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 18px;
|
||||||
|
width: calc(100% - 500px);
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-container-info {
|
||||||
|
display: flex;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-family: 'Arial Normal', 'Arial', sans-serif;
|
||||||
|
}
|
||||||
.header {
|
.header {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
@ -768,4 +787,26 @@ onMounted(() => {
|
|||||||
.data-item:last-child {
|
.data-item:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
.main-dashboard-top {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 15px 20px 0px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-dashboard-top-title {
|
||||||
|
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 18px;
|
||||||
|
width: calc(100% - 500px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-dashboard-top-info {
|
||||||
|
display: flex;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-family: 'Arial Normal', 'Arial', sans-serif;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue
Block a user