ykt-wxapp/pages/case/visit-record-view.vue
2026-01-28 20:01:28 +08:00

367 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 详情页参考截图顶部蓝条显示创建信息支持编辑/删除黄底提示不渲染 -->
<view class="page">
<view class="topbar">
<view class="topbar-text">{{ topText }}</view>
</view>
<view class="content">
<view class="section">
<view class="row">
<view class="label">病历类型</view>
<view class="value">{{ typeLabel }}</view>
</view>
<view class="row">
<view class="label">就诊日期</view>
<view class="value">{{ visitDate || '--' }}</view>
</view>
<view class="row">
<view class="label">诊断</view>
<view class="value">{{ diagnosisText }}</view>
</view>
<view v-if="templateType === 'inhospital' && record.surgeryName" class="row">
<view class="label">手术名称</view>
<view class="value">{{ record.surgeryName }}</view>
</view>
</view>
<view v-for="(s, idx) in sections" :key="idx" class="section">
<view class="h2">{{ s.title }}</view>
<view class="p">{{ s.value }}</view>
</view>
<view class="section">
<view class="h2">文件上传</view>
<view v-if="files.length" class="files">
<view v-for="(f, idx) in files" :key="idx" class="file" @click="preview(idx)">
<image class="thumb" :src="f.url" mode="aspectFill" />
</view>
</view>
<view v-else class="files-empty">暂无附件</view>
</view>
</view>
<view class="footer">
<button class="btn danger" @click="remove">删除</button>
<button class="btn primary" @click="edit">编辑</button>
</view>
</view>
</template>
<script setup>
import { computed, ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import dayjs from 'dayjs';
import api from '@/utils/api';
import { loading, hideLoading, toast } from '@/utils/widget';
import { getVisitRecordTemplate } from '@/components/archive-detail/templates';
const archiveId = ref('');
const id = ref('');
const medicalType = ref('');
const record = ref({});
const files = computed(() => {
const arr = record.value?.files;
return Array.isArray(arr) ? arr.filter((i) => i && i.url) : [];
});
const templateType = computed(() => record.value?.templateType || record.value?.medicalType || '');
const typeLabel = computed(() => record.value?.tempName || getVisitRecordTemplate(templateType.value || medicalType.value)?.templateName || '病历');
function normalizeText(v) {
if (Array.isArray(v)) return v.filter((i) => i !== null && i !== undefined && String(i).trim()).join('');
if (v === 0) return '0';
return v ? String(v) : '';
}
function formatPositiveFind(v, { withOpinion = false } = {}) {
if (Array.isArray(v)) {
const list = v
.map((i) => (i && typeof i === 'object' ? { category: i.category, opinion: i.opinion } : null))
.filter((i) => i && (i.category || i.opinion));
if (!list.length) return '';
if (!withOpinion) return list.map((i) => String(i.category || '').trim()).filter(Boolean).join('');
return list
.map((i) => {
const c = String(i.category || '').trim();
const o = String(i.opinion || '').trim();
if (c && o) return `${c}${o}`;
return c || o;
})
.filter(Boolean)
.join('\n');
}
return normalizeText(v);
}
function getCorpId() {
const team = uni.getStorageSync('ykt_case_current_team') || {};
return team?.corpId ? String(team.corpId) : '';
}
const visitDate = computed(() => {
const t = templateType.value;
if (t === 'outpatient') return record.value?.visitTime || '';
if (t === 'inhospital') return record.value?.inhosDate || '';
if (t === 'preConsultation') return record.value?.consultDate || '';
if (t === 'physicalExaminationTemplate') return record.value?.inspectDate || '';
return record.value?.dateStr || '';
});
const diagnosisText = computed(() => {
const t = templateType.value;
if (t === 'preConsultation') return normalizeText(record.value?.chiefComplaint) || normalizeText(record.value?.summary) || '--';
if (t === 'physicalExaminationTemplate') return formatPositiveFind(record.value?.positiveFind) || normalizeText(record.value?.summary) || '--';
if (t === 'outpatient' || t === 'inhospital') return normalizeText(record.value?.diagnosisName || record.value?.diagnosis) || normalizeText(record.value?.summary) || '--';
return normalizeText(record.value?.diagnosisName || record.value?.diagnosis || record.value?.summary) || '--';
});
const sections = computed(() => {
const t = templateType.value;
const push = (title, value) => {
const v = value === 0 ? '0' : value ? String(value) : '';
if (!v.trim()) return;
return { title, value: v };
};
const list = [];
if (t === 'outpatient') {
const corp = push('就诊机构', record.value?.corpName);
const dept = push('科室', record.value?.deptName);
const doctor = push('医生', record.value?.doctor);
const treatment = push('治疗方案', record.value?.treatmentPlan);
const dispose = push('处置计划', record.value?.disposePlan);
const summary = push('备注/摘要', record.value?.summary);
[corp, dept, doctor, treatment, dispose, summary].forEach((i) => i && list.push(i));
return list;
}
if (t === 'inhospital') {
const corp = push('住院机构', record.value?.corpName);
const summary = push('摘要', record.value?.summary);
[corp, summary].forEach((i) => i && list.push(i));
return list;
}
if (t === 'preConsultation') {
const illness = push('现病史', record.value?.presentIllness);
const past = push('既往史', record.value?.pastHistory);
const allergy = push('过敏史', record.value?.allergyHistory);
const summary = push('摘要', record.value?.summary);
[illness, past, allergy, summary].forEach((i) => i && list.push(i));
return list;
}
if (t === 'physicalExaminationTemplate') {
const corp = push('体检机构', record.value?.corpName);
const pkg = push('体检套餐', record.value?.inspectPakageName);
const positive = push('阳性发现及处理意见', formatPositiveFind(record.value?.positiveFind, { withOpinion: true }));
const summary = push('摘要', record.value?.summary);
[corp, pkg, positive, summary].forEach((i) => i && list.push(i));
return list;
}
const summary = push('摘要', record.value?.summary);
if (summary) list.push(summary);
return list;
});
const topText = computed(() => {
const time = record.value?.createTime ? dayjs(record.value.createTime).format('YYYY-MM-DD HH:mm') : '';
const rawName = record.value?.creatorName ? String(record.value.creatorName) : '';
const cleanName = ['-', '—', '--'].includes(rawName.trim()) ? '' : rawName.trim();
const byCustomer = record.value?.ignore === 'checkIn';
const suffix = byCustomer ? '患者自建' : cleanName ? `${cleanName}代建` : record.value?.creator ? '员工代建' : '';
return suffix ? `${time || '--'} ${suffix}` : `${time || '--'}`;
});
onLoad(async (opt) => {
archiveId.value = opt?.archiveId ? String(opt.archiveId) : '';
id.value = opt?.id ? String(opt.id) : '';
medicalType.value = opt?.type ? String(opt.type) : '';
if (!archiveId.value || !id.value || !medicalType.value) {
toast('参数缺失');
setTimeout(() => uni.navigateBack(), 300);
return;
}
// 使用真实 API 获取病历记录
loading('加载中...');
try {
const corpId = getCorpId();
if (!corpId) {
hideLoading();
toast('缺少 corpId');
setTimeout(() => uni.navigateBack(), 300);
return;
}
const res = await api('getMedicalRecordById', {
_id: id.value,
corpId,
memberId: archiveId.value,
medicalType: medicalType.value,
});
hideLoading();
const r = res?.record || res?.data?.record || null;
if (!res?.success || !r) {
toast('记录不存在');
setTimeout(() => uni.navigateBack(), 300);
return;
}
// 兼容模板字段wxapp 使用 diagnosis但接口通常返回 diagnosisName
if ((r.medicalType === 'outpatient' || r.medicalType === 'inhospital') && !r.diagnosis && r.diagnosisName) {
r.diagnosis = r.diagnosisName;
}
record.value = r;
uni.setNavigationBarTitle({ title: String(typeLabel.value || '病历详情') });
} catch (error) {
hideLoading();
console.error('获取病历记录失败:', error);
toast('加载失败');
setTimeout(() => uni.navigateBack(), 300);
}
});
function preview(idx) {
const urls = files.value.map((i) => i.url);
uni.previewImage({ urls, current: urls[idx] });
}
function edit() {
const type = record.value?.templateType || record.value?.medicalType || '';
uni.navigateTo({
url: `/pages/case/visit-record-detail?archiveId=${encodeURIComponent(archiveId.value)}&id=${encodeURIComponent(id.value)}&type=${encodeURIComponent(type)}`,
});
}
function remove() {
uni.showModal({
title: '提示',
content: '确定删除当前记录?',
success: async (res) => {
if (!res.confirm) return;
loading('删除中...');
try {
const corpId = getCorpId();
if (!corpId) {
hideLoading();
return toast('缺少 corpId');
}
await api('removeMedicalRecord', { corpId, memberId: archiveId.value, medicalType: medicalType.value, _id: id.value });
hideLoading();
uni.$emit('archive-detail:visit-record-changed');
toast('已删除');
setTimeout(() => uni.navigateBack(), 300);
} catch (error) {
hideLoading();
console.error('删除病历记录失败:', error);
toast('删除失败');
}
},
});
}
</script>
<style scoped>
.page {
min-height: 100vh;
background: #fff;
padding-bottom: calc(152rpx + env(safe-area-inset-bottom));
}
.topbar {
background: #5d6df0;
padding: 20rpx 28rpx;
}
.topbar-text {
color: #fff;
font-size: 28rpx;
text-align: center;
}
.content {
padding: 28rpx 28rpx 0;
}
.section {
margin-bottom: 28rpx;
}
.row {
display: flex;
padding: 20rpx 0;
}
.label {
width: 180rpx;
font-size: 28rpx;
font-weight: 600;
color: #111827;
}
.value {
flex: 1;
font-size: 28rpx;
color: #111827;
word-break: break-all;
}
.h2 {
font-size: 28rpx;
font-weight: 700;
color: #111827;
padding: 16rpx 0;
}
.p {
font-size: 28rpx;
color: #111827;
line-height: 40rpx;
white-space: pre-wrap;
}
.files {
display: flex;
gap: 20rpx;
flex-wrap: wrap;
}
.file {
width: 180rpx;
height: 140rpx;
border: 2rpx solid #d1d5db;
background: #f9fafb;
}
.thumb {
width: 180rpx;
height: 140rpx;
}
.files-empty {
font-size: 26rpx;
color: #9aa0a6;
padding: 16rpx 0;
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
padding: 24rpx 28rpx calc(24rpx + env(safe-area-inset-bottom));
display: flex;
justify-content: flex-end;
gap: 28rpx;
box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
}
.btn {
width: 240rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 12rpx;
font-size: 30rpx;
}
.btn::after {
border: none;
}
.btn.danger {
background: #fff;
color: #ff4d4f;
border: 2rpx solid #ff4d4f;
}
.btn.primary {
background: #4f6ef7;
color: #fff;
}
</style>