<template>
|
<el-card class="service-records" shadow="never" style="margin-top: 14px">
|
<div slot="header" class="card-header"><span>服务记录</span></div>
|
<div v-loading="loading">
|
<div v-if="record.length === 0" class="empty-mini">暂无服务记录</div>
|
<div v-else class="service-record">
|
<div class="service-item" v-for="(item, idx) in record" :key="idx">
|
<el-card shadow="never" class="service-card">
|
<!-- 标题行:服务类型 + 任务名称 + 随访状态 + 异常状态 -->
|
<div class="service-card__header">
|
<div class="service-card__title">
|
<span class="service-badge">{{ typeName(item.serviceType) }}</span>
|
<span class="service-name">{{ item.taskName || item.templatename || "-" }}</span>
|
</div>
|
<div class="service-card__tags">
|
<el-tag v-if="item.sendstateView == 1" type="primary" size="small" effect="dark">待随访</el-tag>
|
<el-tag v-else-if="item.sendstateView == 2" type="success" size="small" effect="dark">已完成</el-tag>
|
<el-tag v-else-if="item.sendstateView == 3" type="warning" size="small" effect="dark">无需随访</el-tag>
|
<span class="service-status" :class="item.excep == 0 ? 'is-ok' : 'is-bad'">
|
{{ item.excep == 0 ? "服务正常" : item.excep == 2 ? "警告" : "异常" }}
|
</span>
|
</div>
|
</div>
|
|
<!-- 时间线:出院 → 应访 → 完成 -->
|
<div class="service-card__timeline">
|
<span><em>出院</em>{{ fmtTime(item.endtime) }}</span>
|
<i>→</i>
|
<span><em>应访</em>{{ fmtTime(item.visitTime) }}</span>
|
<i>→</i>
|
<span><em>完成</em>{{ fmtTime(item.finishtime) }}</span>
|
</div>
|
|
<!-- 三栏主体 -->
|
<div class="service-card__columns">
|
<!-- ① 患者信息 -->
|
<div class="svc-block svc-block--blue">
|
<div class="svc-block__title"><i class="el-icon-user-solid"></i>患者信息</div>
|
<div class="svc-block__row">
|
<span class="svc-name">{{ item.sendname || "-" }}</span>
|
<span class="svc-sub">{{ sexName(item.sex) }}</span>
|
<span class="svc-sub">{{ item.phone || "-" }}</span>
|
<span class="svc-sub" v-if="item.endtime">出院{{ endDay(item.endtime) }}天</span>
|
</div>
|
<div class="svc-block__row svc-sub" v-if="item.sfzh">身份证:{{ item.sfzh }}</div>
|
<div class="svc-block__row" v-if="item.leavediagname"><span class="svc-diag">诊断</span>{{ item.leavediagname }}</div>
|
</div>
|
|
<!-- ② 科室病区 · 医护 -->
|
<div class="svc-block svc-block--green">
|
<div class="svc-block__title"><i class="el-icon-office-building"></i>科室病区 · 医护</div>
|
<div class="svc-block__row">科室:{{ item.deptname || "-" }} / 病区:{{ item.leavehospitaldistrictname || "-" }}</div>
|
<div class="svc-block__row">
|
主治:{{ item.drname || "-" }}
|
<span class="svc-sub">经管:{{ item.managementDoctor || "-" }}</span>
|
<span class="svc-sub">护士:{{ item.nurseName || "-" }}</span>
|
</div>
|
<div class="svc-block__row svc-sub">随访人员:{{ item.updateBy || "-" }}</div>
|
<div class="svc-block__row svc-sub">负责人:{{ item.createBy || "-" }}</div>
|
</div>
|
|
<!-- ③ 执行详情 -->
|
<div class="svc-block svc-block--gray">
|
<div class="svc-block__title"><i class="el-icon-s-management"></i>执行详情</div>
|
<div class="svc-meta">
|
<span v-if="item.sendstate || item.sendstate === 0"><em>状态</em>{{ sendStateName(item.sendstate) }}</span>
|
<span v-if="preach(item.preachform)"><em>执行</em>{{ preach(item.preachform) }}</span>
|
<span v-if="item.templatename"><em>模板</em>{{ item.templatename }}</span>
|
<span v-if="item.suggest !== undefined && item.suggest !== null && item.suggest !== ''"><em>意见</em><dict-tag :options="dict.type.sys_suggest" :value="item.suggest" /></span>
|
<span v-if="item.remark"><em>说明</em>{{ item.remark }}</span>
|
<span v-if="item.createTime"><em>创建</em>{{ fmtTime(item.createTime) }}</span>
|
</div>
|
</div>
|
</div>
|
</el-card>
|
</div>
|
</div>
|
</div>
|
</el-card>
|
</template>
|
|
<script>
|
import { getTaskservelist } from "@/api/AiCentre/index";
|
|
export default {
|
name: "ServiceRecords",
|
dicts: ["sys_suggest"],
|
props: {
|
patid: { default: "" },
|
},
|
data() {
|
return { loading: false, record: [] };
|
},
|
watch: {
|
patid: { immediate: true, handler(v) { if (v) this.load(v); } },
|
},
|
methods: {
|
load(patid) {
|
this.loading = true;
|
getTaskservelist({ patid })
|
.then((res) => {
|
if (res.code === 200 && res.rows && res.rows[0]) {
|
this.record = res.rows[0].serviceSubtaskList || [];
|
} else {
|
this.record = [];
|
}
|
})
|
.catch(() => { this.record = []; })
|
.finally(() => { this.loading = false; });
|
},
|
typeName(t) {
|
if (t == 1) return "心电随访";
|
if (t == 2) return "出院随访";
|
if (t == 3) return "影像随访";
|
if (t == 4) return "宣教关怀";
|
return "其他服务";
|
},
|
sexName(s) {
|
if (s == 1) return "男";
|
if (s == 2) return "女";
|
return "-";
|
},
|
sendStateName(s) {
|
const map = { 1: "已领取", 2: "待随访", 3: "已发送", 4: "不执行", 5: "失败", 6: "已完成", 7: "超时" };
|
return map[s] || "-";
|
},
|
fmtTime(t) {
|
if (!t) return "-";
|
const s = String(t).replace("T", " ");
|
return s.length > 16 ? s.substring(0, 16) : s.substring(0, 10);
|
},
|
endDay(t) {
|
if (!t) return "-";
|
const d = new Date(String(t).replace("T", " ").replace(/-/g, "/"));
|
const diff = Date.now() - d.getTime();
|
return Math.round(diff / (1000 * 3600 * 24));
|
},
|
preach(v) {
|
if (!v) return "";
|
return Array.isArray(v) ? v.join("、") : String(v);
|
},
|
},
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
$primary: #3f6ef0;
|
|
.service-records {
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
font-size: 16px;
|
font-weight: 600;
|
}
|
}
|
|
.empty-mini {
|
padding: 30px 0;
|
text-align: center;
|
color: #c0c4cc;
|
font-size: 14px;
|
}
|
|
.service-record {
|
.service-item {
|
margin-bottom: 16px;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.service-card {
|
border-radius: 12px;
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
|
::v-deep .el-card__body {
|
padding: 20px 24px;
|
}
|
}
|
|
.service-card__header {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding-bottom: 14px;
|
border-bottom: 1px dashed #eef0f4;
|
}
|
|
.service-card__title {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
min-width: 0;
|
}
|
|
.service-card__tags {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
flex-shrink: 0;
|
}
|
|
.service-badge {
|
display: inline-block;
|
padding: 4px 12px;
|
font-size: 13px;
|
font-weight: 600;
|
color: $primary;
|
background: #eef4ff;
|
border-radius: 6px;
|
white-space: nowrap;
|
}
|
|
.service-name {
|
font-size: 16px;
|
font-weight: 600;
|
color: #303133;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.service-status {
|
padding: 4px 12px;
|
font-size: 13px;
|
border-radius: 999px;
|
|
&.is-ok {
|
color: #12a182;
|
background: #e8f7f1;
|
}
|
|
&.is-bad {
|
color: #e0564c;
|
background: #fdeeee;
|
}
|
}
|
|
.service-card__timeline {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
flex-wrap: wrap;
|
padding: 12px 0;
|
font-size: 13px;
|
color: #606266;
|
|
em {
|
font-style: normal;
|
color: #909399;
|
margin-right: 2px;
|
}
|
|
i {
|
color: #c0c4cc;
|
font-style: normal;
|
}
|
}
|
|
.service-card__columns {
|
display: flex;
|
gap: 12px;
|
}
|
|
.svc-block {
|
flex: 1;
|
min-width: 0;
|
border-radius: 6px;
|
padding: 10px 12px;
|
font-size: 13px;
|
|
&--blue {
|
background: #ecf5ff;
|
.svc-block__title { color: #409eff; }
|
}
|
|
&--green {
|
background: #edf7f0;
|
.svc-block__title { color: #67c23a; }
|
}
|
|
&--gray {
|
background: #f5f7fa;
|
.svc-block__title { color: #909399; }
|
}
|
}
|
|
.svc-block__title {
|
font-size: 12px;
|
font-weight: 600;
|
margin-bottom: 6px;
|
|
i { margin-right: 4px; }
|
}
|
|
.svc-block__row {
|
color: #303133;
|
line-height: 1.7;
|
font-size: 13px;
|
word-break: break-all;
|
}
|
|
.svc-sub {
|
color: #909399;
|
font-size: 12px;
|
margin-left: 8px;
|
}
|
|
.svc-name {
|
color: #409eff;
|
font-weight: 600;
|
cursor: default;
|
}
|
|
.svc-diag {
|
display: inline-block;
|
font-size: 11px;
|
color: #e6a23c;
|
background: #fdf6ec;
|
padding: 1px 6px;
|
border-radius: 3px;
|
margin-right: 6px;
|
}
|
|
.svc-meta {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 4px 12px;
|
font-size: 12px;
|
color: #606266;
|
|
span { white-space: normal; }
|
|
em {
|
font-style: normal;
|
color: #909399;
|
margin-right: 2px;
|
}
|
}
|
}
|
</style>
|