167 lines
5.4 KiB
Plaintext
167 lines
5.4 KiB
Plaintext
<template>
|
||
<view class="emergency-page">
|
||
<view class="header">
|
||
<text class="title">急诊管理</text>
|
||
<button class="add-btn" @click="showAddEmergency">➕ 新建急诊</button>
|
||
</view>
|
||
<view class="stats">
|
||
<text>今日急诊: {{ stats.today }}</text>
|
||
<text>处理中: {{ stats.processing }}</text>
|
||
<text>已解决: {{ stats.resolved }}</text>
|
||
</view>
|
||
<scroll-view class="emergency-list" scroll-y="true">
|
||
<view v-for="item in emergencies" :key="item.id" class="emergency-item" :class="item.severity">
|
||
<view class="item-header">
|
||
<text class="type">{{ getTypeText(item.emergency_type) }}</text>
|
||
<text class="severity">{{ getSeverityText(item.severity) }}</text>
|
||
<text class="status">{{ getStatusText(item.status) }}</text>
|
||
</view>
|
||
<view class="item-content">
|
||
<text class="elder">患者: {{ item.elder_name }}</text>
|
||
<text class="desc">{{ item.description }}</text>
|
||
</view>
|
||
<view class="item-footer">
|
||
<text class="time">{{ formatDateTime(item.occurred_at) }}</text>
|
||
<button v-if="item.status==='active'" class="handle-btn" @click="handleEmergency(item)">处理</button>
|
||
</view>
|
||
</view>
|
||
<view v-if="emergencies.length===0" class="empty-state">
|
||
<text>暂无急诊事件</text>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="uts">
|
||
import { ref, onMounted } from 'vue'
|
||
import supa from '@/components/supadb/aksupainstance.uts'
|
||
import { formatDateTime } from '../types_new.uts'
|
||
|
||
type Emergency = {
|
||
id: string
|
||
appointment_id: string
|
||
elder_id: string
|
||
elder_name: string
|
||
doctor_id: string
|
||
emergency_type: string
|
||
severity: string
|
||
status: string
|
||
description: string
|
||
occurred_at: string
|
||
handled_at: string
|
||
handler_notes: string
|
||
created_at: string
|
||
updated_at: string
|
||
}
|
||
|
||
type EmergencyStats = {
|
||
today: number
|
||
processing: number
|
||
resolved: number
|
||
}
|
||
|
||
const emergencies = ref<Emergency[]>([])
|
||
const stats = ref<EmergencyStats>({ today: 0, processing: 0, resolved: 0 })
|
||
|
||
onMounted(() => {
|
||
loadEmergencies()
|
||
loadStats()
|
||
})
|
||
|
||
const loadEmergencies = async () => {
|
||
const result = await supa
|
||
.from('ec_emergencies')
|
||
.select('*')
|
||
.order('occurred_at', { ascending: false })
|
||
.limit(30)
|
||
.executeAs<Emergency[]>()
|
||
if (result.error == null && result.data != null) {
|
||
emergencies.value = result.data
|
||
}
|
||
}
|
||
|
||
const loadStats = async () => {
|
||
const todayStart = new Date()
|
||
todayStart.setHours(0,0,0,0)
|
||
const todayEnd = new Date()
|
||
todayEnd.setHours(23,59,59,999)
|
||
const todayResult = await supa
|
||
.from('ec_emergencies')
|
||
.select('*', { count: 'exact' })
|
||
.gte('occurred_at', todayStart.toISOString())
|
||
.lte('occurred_at', todayEnd.toISOString())
|
||
.executeAs<Emergency[]>()
|
||
const processingResult = await supa
|
||
.from('ec_emergencies')
|
||
.select('*', { count: 'exact' })
|
||
.eq('status', 'processing')
|
||
.executeAs<Emergency[]>()
|
||
const resolvedResult = await supa
|
||
.from('ec_emergencies')
|
||
.select('*', { count: 'exact' })
|
||
.eq('status', 'resolved')
|
||
.executeAs<Emergency[]>()
|
||
stats.value = {
|
||
today: todayResult.count ?? 0,
|
||
processing: processingResult.count ?? 0,
|
||
resolved: resolvedResult.count ?? 0
|
||
}
|
||
}
|
||
|
||
const getTypeText = (type: string): string => {
|
||
const map = new Map([
|
||
['fall', '跌倒'],
|
||
['stroke', '中风'],
|
||
['cardiac', '心脏'],
|
||
['other', '其他']
|
||
])
|
||
return map.get(type) ?? type
|
||
}
|
||
const getSeverityText = (sev: string): string => {
|
||
const map = new Map([
|
||
['low', '低'],
|
||
['medium', '中'],
|
||
['high', '高'],
|
||
['critical', '危急']
|
||
])
|
||
return map.get(sev) ?? sev
|
||
}
|
||
const getStatusText = (status: string): string => {
|
||
const map = new Map([
|
||
['active', '待处理'],
|
||
['processing', '处理中'],
|
||
['resolved', '已解决'],
|
||
['cancelled', '已取消']
|
||
])
|
||
return map.get(status) ?? status
|
||
}
|
||
const showAddEmergency = () => {
|
||
uni.navigateTo({ url: '/pages/ec/doctor/emergency-form' })
|
||
}
|
||
const handleEmergency = (item: Emergency) => {
|
||
uni.navigateTo({ url: `/pages/ec/doctor/emergency-handle?id=${item.id}` })
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.emergency-page { padding: 20px; background: #f5f5f5; min-height: 100vh; }
|
||
.header { display: flex; flex-direction: row; justify-content: space-between; align-items: center; margin-bottom: 16px; }
|
||
.title { font-size: 20px; font-weight: bold; }
|
||
.add-btn { background: #ff4757; color: #fff; border: none; border-radius: 16px; padding: 8px 18px; font-size: 15px; }
|
||
.stats { display: flex; flex-direction: row; gap: 18px; margin-bottom: 12px; }
|
||
.emergency-list { background: #fff; border-radius: 10px; }
|
||
.emergency-item { padding: 14px 10px; border-bottom: 1px solid #f0f0f0; }
|
||
.emergency-item:last-child { border-bottom: none; }
|
||
.item-header { display: flex; flex-direction: row; gap: 10px; margin-bottom: 6px; }
|
||
.type { font-size: 14px; font-weight: 600; }
|
||
.severity { font-size: 13px; color: #e67e22; }
|
||
.status { font-size: 13px; color: #3498db; }
|
||
.item-content { font-size: 13px; color: #555; margin-bottom: 6px; }
|
||
.elder { color: #888; margin-right: 10px; }
|
||
.desc { color: #555; }
|
||
.item-footer { display: flex; flex-direction: row; justify-content: space-between; align-items: center; }
|
||
.time { font-size: 12px; color: #999; }
|
||
.handle-btn { background: #27ae60; color: #fff; border: none; border-radius: 12px; padding: 6px 14px; font-size: 13px; }
|
||
.empty-state { padding: 30px 0; text-align: center; color: #999; }
|
||
</style>
|