236 lines
6.8 KiB
Vue
236 lines
6.8 KiB
Vue
<template>
|
|
<div class="blockchain-case-system">
|
|
<!-- 病例列表 -->
|
|
<el-table :data="state.caseList" v-loading="state.loading" style="width: 100%">
|
|
<el-table-column prop="id" label="病例ID" align="center"/>
|
|
<el-table-column prop="user.nickName" label="患者姓名" align="center"/>
|
|
<el-table-column prop="createdTime" label="预约时间" align="center"/>
|
|
<el-table-column prop="amount" label="预约金额" align="center"/>
|
|
<el-table-column label="操作" align="center">
|
|
<template #default="{row}">
|
|
<el-button
|
|
v-if="row.audit === null"
|
|
type="primary"
|
|
size="small"
|
|
@click="requestAccess(row)"
|
|
>
|
|
申请查看
|
|
</el-button>
|
|
<el-button
|
|
v-if="row.audit?.status === '同意授权'"
|
|
type="success"
|
|
size="small"
|
|
@click="viewCase(row)"
|
|
>
|
|
查看病例
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
<!-- 查看病例对话框 -->
|
|
<el-dialog
|
|
v-model="state.dialogVisible"
|
|
:title="`病例详情 - ${state.selectedCase}`"
|
|
width="70%"
|
|
>
|
|
<div class="case-content">
|
|
<h3>诊断结果: {{ state.selectedCase?.diagnosis }}</h3>
|
|
<div class="case-details">
|
|
<!-- 这里显示实际的病例内容 -->
|
|
<p>这是一份加密存储的区块链病例,只有获得授权的医生可以查看完整内容。</p>
|
|
<p>病例ID: {{ state.selectedCase?.id }}</p>
|
|
<p>区块链哈希: 0x8923a7b8c5d6e4f2a1b9c8d7e6f5a4b3c2d1e0f</p>
|
|
</div>
|
|
</div>
|
|
</el-dialog>
|
|
<!-- 申请查看对话框 -->
|
|
<el-dialog v-model="state.requestDialogVisible" title="申请查看病例" width="50%">
|
|
<el-form :model="state.requestForm" ref="formRef" label-width="100px">
|
|
<el-form-item label="病例ID">
|
|
<el-input v-model="state.requestForm.orderId" disabled/>
|
|
</el-form-item>
|
|
<el-form-item label="患者姓名">
|
|
<el-input :value="state.selectedCase?.nickName" disabled/>
|
|
</el-form-item>
|
|
<el-form-item label="申请目的" prop="purpose"
|
|
:rules="[{ required: true, message: '请输入申请目的', trigger: 'blur' }]">
|
|
<el-input
|
|
v-model="state.requestForm.purpose"
|
|
type="textarea"
|
|
:rows="3"
|
|
placeholder="请输入申请查看该病例的目的"
|
|
/>
|
|
</el-form-item>
|
|
<!-- <el-form-item label="有效天数" prop="duration"-->
|
|
<!-- :rules="[{ required: true, message: '请选择有效天数', trigger: 'change' }]">-->
|
|
<!-- <el-select v-model="state.requestForm.duration" placeholder="请选择">-->
|
|
<!-- <el-option label="1天" :value="1" />-->
|
|
<!-- <el-option label="3天" :value="3" />-->
|
|
<!-- <el-option label="7天" :value="7" />-->
|
|
<!-- <el-option label="30天" :value="30" />-->
|
|
<!-- </el-select>-->
|
|
<!-- </el-form-item>-->
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="state.requestDialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="submitRequest" :loading="state.loading">提交申请</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
|
|
<!-- 患者授权对话框 -->
|
|
<el-dialog v-model="state.authDialogVisible" title="授权查看病例" width="50%">
|
|
<el-form :model="state.authForm" label-width="100px">
|
|
<el-form-item label="病例ID">
|
|
<el-input v-model="state.authForm.orderId" disabled/>
|
|
</el-form-item>
|
|
<el-form-item label="患者私钥" prop="privateKey"
|
|
:rules="[{ required: true, message: '请输入您的私钥', trigger: 'blur' }]">
|
|
<el-input
|
|
v-model="state.authForm.privateKey"
|
|
type="password"
|
|
placeholder="请输入您的区块链私钥以授权"
|
|
show-password
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-alert type="warning" show-icon>
|
|
请注意:私钥是您访问区块链病例的唯一凭证,请勿泄露给他人
|
|
</el-alert>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="state.authDialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="submitAuth" :loading="state.loading">授权</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import {ref, reactive} from 'vue'
|
|
import {ElMessage, ElMessageBox} from 'element-plus'
|
|
import type {FormInstance} from 'element-plus'
|
|
|
|
const formRef = ref<FormInstance>()
|
|
const user = userStore().doctorUserInfo
|
|
// 状态管理
|
|
const state = reactive(<any>{
|
|
loading: false,
|
|
caseList: [] as any[], // 病例列表
|
|
selectedCase: null as any, // 选中的病例
|
|
dialogVisible: false, // 查看病例对话框
|
|
requestDialogVisible: false, // 申请查看对话框
|
|
authDialogVisible: false, // 授权对话框
|
|
requestForm: {
|
|
orderId: '',
|
|
purpose: '',
|
|
duration: 1 // 默认1天
|
|
},
|
|
authForm: {
|
|
privateKey: '',
|
|
orderId: ''
|
|
}
|
|
})
|
|
// 模拟获取病例列表
|
|
const getCaseList = async () => {
|
|
state.loading = true
|
|
try {
|
|
const res = await frontRequest.get('/api/order/list', {params: {limit: 999,itemId: user.id}})
|
|
state.caseList = res.data
|
|
} catch (error) {
|
|
ElMessage.error('获取病例列表失败')
|
|
} finally {
|
|
state.loading = false
|
|
}
|
|
}
|
|
|
|
// 申请查看病例
|
|
const requestAccess = (caseItem: any) => {
|
|
state.selectedCase = caseItem.user
|
|
state.requestForm.orderId = caseItem.id
|
|
state.requestDialogVisible = true
|
|
}
|
|
// 提交查看申请
|
|
const submitRequest = async () => {
|
|
try {
|
|
state.loading = true
|
|
state.requestForm.itemId = user.id
|
|
state.requestForm.userId = state.selectedCase.id
|
|
await frontRequest.post('api/audit', state.requestForm)
|
|
ElMessage.success('查看申请已提交,等待患者授权')
|
|
state.requestDialogVisible = false
|
|
} catch (error) {
|
|
|
|
} finally {
|
|
state.loading = false
|
|
}
|
|
}
|
|
|
|
// 查看病例(已授权)
|
|
const viewCase = (caseItem: any) => {
|
|
if (caseItem.encrypted && !caseItem.accessGranted) {
|
|
requestAccess(caseItem)
|
|
return
|
|
}
|
|
state.selectedCase = caseItem
|
|
state.dialogVisible = true
|
|
}
|
|
|
|
// 患者授权查看
|
|
const grantAccess = (caseItem: any) => {
|
|
state.authDialogVisible = true
|
|
state.authForm.orderId = caseItem.id
|
|
}
|
|
|
|
// 提交授权
|
|
const submitAuth = async () => {
|
|
try {
|
|
state.loading = true
|
|
// 这里替换为实际的区块链API调用
|
|
// await blockchainApi.post('/access/grant', state.authForm)
|
|
|
|
ElMessage.success('授权成功')
|
|
state.authDialogVisible = false
|
|
// 刷新病例列表
|
|
getCaseList()
|
|
} catch (error) {
|
|
ElMessage.error('授权失败,请检查私钥是否正确')
|
|
} finally {
|
|
state.loading = false
|
|
}
|
|
}
|
|
|
|
// 初始化加载
|
|
onMounted(() => {
|
|
getCaseList()
|
|
})
|
|
</script>
|
|
<style scoped>
|
|
.blockchain-case-system {
|
|
padding: 20px;
|
|
}
|
|
|
|
.card-header {
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.case-content {
|
|
padding: 20px;
|
|
}
|
|
|
|
.case-details {
|
|
margin-top: 20px;
|
|
padding: 15px;
|
|
background-color: #f5f7fa;
|
|
border-radius: 4px;
|
|
}
|
|
</style>
|
|
|
|
<route lang="json">
|
|
{
|
|
"meta": {
|
|
"layout": "doctor"
|
|
}
|
|
}
|
|
</route>
|