Files
xh-medical-sign-web/clinical-web/src/views/workbench/home/components/TodoPanel.vue
T

278 lines
5.2 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.
<script setup lang="ts">
import { readPendingTag } from '@/utils/signing-method'
import type { HomeTodoItem } from '../types'
defineProps<{
items: HomeTodoItem[]
}>()
const emit = defineEmits<{
select: [item: HomeTodoItem]
viewAll: []
}>()
function getStatusLabel(item: HomeTodoItem) {
switch (item.status) {
case 'created':
return '待发送'
case 'pending':
return readPendingTag(item.method).text
case 'generating':
return '文书生成中'
case 'overdue':
return '已超时'
case 'signed':
return '已签署'
case 'voided':
return '已作废'
case 'failed':
return '处理失败'
}
}
function getStatusClass(item: HomeTodoItem) {
if (item.status === 'overdue') {
return 'todo-status--overdue'
}
if (item.status === 'pending') {
// 与签署工作台同口径:待签署徽标按具体方式分色
return `todo-status--${readPendingTag(item.method).className.replace('tg-', '')}`
}
if (item.status === 'signed') {
return 'todo-status--success'
}
if (item.status === 'failed') {
return 'todo-status--danger'
}
return 'todo-status--muted'
}
function getHint(item: HomeTodoItem) {
switch (item.status) {
case 'created':
return '⏳ 等待发送'
case 'pending':
return '⏳ 等待患者签署'
case 'generating':
return '⌛ 正在生成签署文书'
case 'overdue':
return '⚠ 已超时,需重新发起'
case 'signed':
return '✓ 已完成签署'
case 'voided':
return '— 任务已作废'
case 'failed':
return '⚠ 任务处理失败'
}
}
</script>
<template>
<section class="home-panel todo-panel">
<div class="panel-heading">
<h2>我的待办</h2>
<button type="button" class="panel-more" @click="emit('viewAll')">全部 ›</button>
</div>
<div v-if="items.length" class="todo-list">
<button
v-for="item in items"
:key="item.id"
type="button"
class="todo-item"
@click="emit('select', item)"
>
<span class="todo-row">
<strong>{{ item.patientName }}</strong>
<span class="patient-id">{{ item.patientId }}</span>
<span class="todo-spacer" />
<span class="todo-status" :class="getStatusClass(item)">
{{ getStatusLabel(item) }}
</span>
</span>
<span class="todo-row todo-row--detail">
<span class="todo-document">📄 {{ item.documentName }}</span>
<span class="todo-hint">{{ getHint(item) }}</span>
</span>
</button>
</div>
<div v-else class="todo-empty">
<span aria-hidden="true">🎉</span>
<p>暂无待办</p>
</div>
</section>
</template>
<style scoped>
.home-panel {
min-width: 0;
padding: 16px 18px;
background: var(--card);
border-radius: var(--r);
box-shadow: var(--sh);
}
.panel-heading {
display: flex;
gap: 10px;
align-items: center;
margin-bottom: 14px;
}
.panel-heading h2 {
margin: 0;
color: var(--ink);
font-size: 14.5px;
line-height: 1.4;
}
.panel-more {
margin-left: auto;
padding: 0;
color: var(--brand);
font-size: 12px;
background: transparent;
}
.panel-more:hover {
color: var(--brand-d);
}
.todo-list {
display: flex;
flex-direction: column;
/* 原型 .titem 是 margin-bottom:10px */
gap: 10px;
}
.todo-item {
display: block;
width: 100%;
/* 原型 .titem:padding 11px 13px + 圆角 10px */
padding: 11px 13px;
color: var(--ink);
text-align: left;
background: #fff;
border: 1px solid var(--line);
border-radius: 10px;
transition:
border-color 0.15s ease,
background 0.15s ease;
}
.todo-item:hover {
background: #f8fcfd;
border-color: var(--brand);
}
.todo-row {
display: flex;
min-width: 0;
gap: 8px;
align-items: center;
}
.todo-row strong {
flex-shrink: 0;
font-size: 14px;
}
.patient-id {
overflow: hidden;
color: var(--mut);
font-size: 11px;
text-overflow: ellipsis;
white-space: nowrap;
}
.todo-spacer {
flex: 1;
}
.todo-status {
flex-shrink: 0;
/* 原型 .tag:padding 2px 10px / 11.5px / 圆角 20px */
padding: 2px 10px;
font-size: 11.5px;
font-weight: 700;
border-radius: 20px;
}
.todo-status--pad {
color: var(--brand);
background: var(--brand-l);
}
.todo-status--ipad {
color: #2b6cb0;
background: #e8f1fb;
}
.todo-status--sms {
color: #7a4dbb;
background: #f3ecfb;
}
.todo-status--overdue,
.todo-status--danger {
color: var(--err);
background: var(--err-l);
}
.todo-status--success {
color: var(--ok);
background: var(--ok-l);
}
/* 原型 .tg-void */
.todo-status--muted {
color: #8a9aa3;
background: #eceef0;
}
.todo-row--detail {
margin-top: 5px;
gap: 12px;
flex-wrap: wrap;
color: var(--mut);
font-size: 12.5px;
}
.todo-document {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.todo-hint {
flex-shrink: 0;
white-space: nowrap;
}
.todo-empty {
display: grid;
min-height: 202px;
color: var(--mut);
font-size: 13px;
place-items: center;
align-content: center;
}
.todo-empty span {
margin-bottom: 7px;
font-size: 34px;
opacity: 0.5;
}
.todo-empty p {
margin: 0;
}
</style>