433 lines
11 KiB
Plaintext
433 lines
11 KiB
Plaintext
<template>
|
||
<hr-page page-bg="#F3F4F6" status-bg="#FFFFFF" nav-title="伤员查询" :xloading="true"
|
||
@right-click="onSort">
|
||
<template v-slot:right>
|
||
<x-icon name="arrow-up-down-line" color="#6B7280" font-size="17"></x-icon>
|
||
</template>
|
||
|
||
<!-- 离线条 -->
|
||
<view class="hr-offbar" @click="goOffline">
|
||
<x-icon name="cloud-off-line" color="#92400E" font-size="15"></x-icon>
|
||
<text class="vs-off-t">离线中 · 数据暂存本地</text>
|
||
<view class="hr-offbar-cnt">
|
||
<text class="vs-off-cnt-t">3</text>
|
||
</view>
|
||
<text class="hr-offbar-go">查看队列 ›</text>
|
||
</view>
|
||
|
||
<view class="hr-body">
|
||
|
||
<!-- ============ 搜索(xSearch) ============ -->
|
||
<x-search v-model="keyword" placeholder="姓名 / 身份证 / 编号" round="24rpx" height="84rpx"
|
||
:border="searchBorder" input-bg-color="#FFFFFF" icon-color="#9CA3AF" font-color="#1F2937"
|
||
:show-cancel="false"></x-search>
|
||
|
||
<!-- ============ 双下拉筛选 ============ -->
|
||
<view class="vs-filter">
|
||
<view :class="levelIdx > 0 ? 'vs-sel vs-sel-on' : 'vs-sel'" @click="openSheet(0)">
|
||
<text class="vs-sel-l">检伤等级</text>
|
||
<text :class="levelIdx > 0 ? 'vs-sel-v vs-sel-v-on' : 'vs-sel-v'">{{ levelOptions[levelIdx] }}</text>
|
||
<x-icon name="arrow-down-s-line" color="#9CA3AF" font-size="14"></x-icon>
|
||
</view>
|
||
<view :class="statusIdx > 0 ? 'vs-sel vs-sel-on' : 'vs-sel'"
|
||
style="margin-left:8px" @click="openSheet(1)">
|
||
<text class="vs-sel-l">检伤状态</text>
|
||
<text :class="statusIdx > 0 ? 'vs-sel-v vs-sel-v-on' : 'vs-sel-v'">{{ statusOptions[statusIdx] }}</text>
|
||
<x-icon name="arrow-down-s-line" color="#9CA3AF" font-size="14"></x-icon>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- ============ 伤员列表 ============ -->
|
||
<view style="margin-top:4px">
|
||
<view v-for="(v, i) in shown" :key="v.id" :class="cardClass(v.level)" @click="openDetail(v)">
|
||
<view class="hr-row">
|
||
<view :class="avatarClass(v.level)">
|
||
<text class="vs-avt-t">{{ v.name.substring(0, 1) }}</text>
|
||
</view>
|
||
<view class="hr-flex1">
|
||
<view class="hr-row">
|
||
<text class="vs-name">{{ v.name }}</text>
|
||
<hr-wb :level="v.level" small></hr-wb>
|
||
</view>
|
||
<text class="vs-code">{{ v.gender }} · {{ v.age }} 岁 · {{ v.code }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="vs-inj">
|
||
<text class="vs-inj-t">伤情:{{ v.injury }}</text>
|
||
</view>
|
||
<view class="vs-bot">
|
||
<view class="vs-status" :style="statusStyle(v.statusTheme)">
|
||
<text class="vs-status-t" :style="statusTextStyle(v.statusTheme)">{{ v.status }}</text>
|
||
</view>
|
||
<view class="hr-flex1"></view>
|
||
<text class="vs-time">{{ v.createdAt }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<hr-empty v-if="shown.length == 0" icon="♡" title="没有匹配的伤员"
|
||
sub="换个筛选条件,或点击右上角扫码按腕带编号查询"></hr-empty>
|
||
|
||
<view v-if="shown.length > 0" class="vs-hint">
|
||
<text class="vs-hint-t">✦ 点击卡片查看伤员详情</text>
|
||
</view>
|
||
|
||
<view style="height:14px"></view>
|
||
</view>
|
||
|
||
<!-- ============ 筛选选择器 ============ -->
|
||
<template v-slot:overlay>
|
||
<view v-if="sheet >= 0" class="hr-mask" @click="closeSheet">
|
||
<view class="hr-sheet" @click="stop">
|
||
<view class="hr-sheet-h">
|
||
<text class="hr-sheet-h-b">{{ sheet == 0 ? '选择检伤等级' : '选择检伤状态' }}</text>
|
||
<view class="hr-sheet-h-x" @click="closeSheet">
|
||
<x-icon name="close-line" color="#9CA3AF" font-size="18"></x-icon>
|
||
</view>
|
||
</view>
|
||
<view v-for="(o, i) in currentOptions" :key="i" class="hr-sheet-opt"
|
||
:class="i == currentOptions.length - 1 ? 'hr-sheet-opt-last' : ''" @click="pickOption(i)">
|
||
<text :class="isPicked(i) ? 'hr-sheet-opt-t hr-sheet-opt-on' : 'hr-sheet-opt-t'">{{ o }}</text>
|
||
<x-icon v-if="isPicked(i)" name="check-line" color="#2563EB" font-size="17"></x-icon>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
</hr-page>
|
||
</template>
|
||
|
||
<script lang="uts" setup>
|
||
import { ref, computed } from 'vue'
|
||
import { victimList } from '@/mock/index.uts'
|
||
import { HrVictim } from '@/mock/types.uts'
|
||
import { navTo } from '@/utils/nav.uts'
|
||
|
||
/**
|
||
* s04 伤员查询
|
||
* 支持按「检伤等级 / 检伤状态」双下拉筛选 + 关键字搜索 + 扫码查询。
|
||
*/
|
||
const levelOptions : string[] = ['全部', '危重', '重伤', '轻伤', '死亡']
|
||
const statusOptions : string[] = ['全部', '已检伤', '转运中', '待转运', '未转运']
|
||
|
||
const keyword = ref('')
|
||
const levelIdx = ref(0)
|
||
const statusIdx = ref(0)
|
||
const sheet = ref(-1)
|
||
const list = ref<HrVictim[]>(victimList)
|
||
|
||
/**
|
||
* xSearch 的 border 是「数组」prop,固定 3 项 = [宽度, 线型, 颜色],
|
||
* 少于 3 项内部直接返回 none。设计稿搜索框为 1px solid #E5E7EB。
|
||
*/
|
||
const searchBorder : string[] = ['1px', 'solid', '#E5E7EB']
|
||
|
||
const currentOptions = computed(() : string[] => {
|
||
return sheet.value == 0 ? levelOptions : statusOptions
|
||
})
|
||
|
||
const shown = computed(() : HrVictim[] => {
|
||
const out : HrVictim[] = []
|
||
for (let i = 0; i < list.value.length; i++) {
|
||
const v = list.value[i]
|
||
if (levelIdx.value > 0 && v.level != levelIdx.value) { continue }
|
||
if (statusIdx.value > 0) {
|
||
const label = statusOptions[statusIdx.value]
|
||
if (label == '转运中' && v.status.indexOf('转运中') < 0) { continue }
|
||
if (label == '待转运' && v.status.indexOf('待转运') < 0) { continue }
|
||
if (label == '未转运' && v.status.indexOf('未转运') < 0) { continue }
|
||
if (label == '已检伤' && v.status.indexOf('已转运') < 0 && v.status.indexOf('转运中') < 0) { continue }
|
||
}
|
||
if (keyword.value != '') {
|
||
const kw = keyword.value.toLowerCase()
|
||
const hit = v.name.toLowerCase().indexOf(kw) > -1 || v.code.toLowerCase().indexOf(kw) > -1
|
||
if (!hit) { continue }
|
||
}
|
||
out.push(v)
|
||
}
|
||
return out
|
||
})
|
||
|
||
function cardClass(level : number) : string {
|
||
return `vs-card vs-card-l${level}`
|
||
}
|
||
|
||
function avatarClass(level : number) : string {
|
||
return `vs-avt vs-avt-l${level}`
|
||
}
|
||
|
||
function statusStyle(theme : string) : string {
|
||
if (theme == 'pri') { return 'background-color:#EFF6FF;border:1px solid #BFDBFE' }
|
||
if (theme == 'amb') { return 'background-color:#FFFBEB;border:1px solid #FDE68A' }
|
||
if (theme == 'grn') { return 'background-color:#ECFDF5;border:1px solid #A7F3D0' }
|
||
return 'background-color:#F3F4F6;border:1px solid #E5E7EB'
|
||
}
|
||
|
||
function statusTextStyle(theme : string) : string {
|
||
if (theme == 'pri') { return 'color:#1D4ED8' }
|
||
if (theme == 'amb') { return 'color:#B45309' }
|
||
if (theme == 'grn') { return 'color:#047857' }
|
||
return 'color:#6B7280'
|
||
}
|
||
|
||
function openSheet(i : number) : void {
|
||
sheet.value = i
|
||
}
|
||
|
||
function closeSheet() : void {
|
||
sheet.value = -1
|
||
}
|
||
|
||
function stop() : void {
|
||
// 阻止点击面板时关闭
|
||
}
|
||
|
||
function isPicked(i : number) : boolean {
|
||
return sheet.value == 0 ? levelIdx.value == i : statusIdx.value == i
|
||
}
|
||
|
||
function pickOption(i : number) : void {
|
||
if (sheet.value == 0) { levelIdx.value = i } else { statusIdx.value = i }
|
||
sheet.value = -1
|
||
}
|
||
|
||
function openDetail(v : HrVictim) : void {
|
||
navTo('/pages/triage/detail?id=' + v.id)
|
||
}
|
||
|
||
function onSort() : void {
|
||
uni.showToast({ title: '按建档时间 / 分级排序', icon: 'none' })
|
||
}
|
||
|
||
function goOffline() : void {
|
||
navTo('/pages/triage/offline-sync')
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.vs-off-t {
|
||
font-size: 26.8rpx;
|
||
font-weight: bold;
|
||
color: #92400E;
|
||
margin-left: 18rpx;
|
||
}
|
||
|
||
.vs-off-cnt-t {
|
||
font-size: 22.4rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
/* ---------- 搜索 ---------- */
|
||
.vs-srch {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
background-color: #FFFFFF;
|
||
border: 2rpx solid #E5E7EB;
|
||
border-radius: 24rpx;
|
||
height: 84rpx;
|
||
padding: 0rpx 20rpx 0rpx 20rpx;
|
||
}
|
||
|
||
.vs-srch-input {
|
||
flex: 1;
|
||
font-size: 29.2rpx;
|
||
color: #1F2937;
|
||
height: 80rpx;
|
||
padding: 0rpx 16rpx 0rpx 16rpx;
|
||
}
|
||
|
||
.vs-srch-scan {
|
||
width: 52rpx;
|
||
height: 52rpx;
|
||
border-radius: 16rpx;
|
||
background-color: #EFF6FF;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.vs-scan-btn {
|
||
width: 84rpx;
|
||
height: 84rpx;
|
||
border-radius: 24rpx;
|
||
background-color: #EFF6FF;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-left: 16rpx;
|
||
}
|
||
|
||
/* ---------- 筛选 ---------- */
|
||
.vs-filter {
|
||
display: flex;
|
||
flex-direction: row;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.vs-sel {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
background-color: #FFFFFF;
|
||
border: 2rpx solid #E5E7EB;
|
||
border-radius: 22rpx;
|
||
padding: 18rpx 22rpx 18rpx 22rpx;
|
||
}
|
||
|
||
.vs-sel-on {
|
||
border: 2rpx solid #2563EB;
|
||
background-color: #EFF6FF;
|
||
}
|
||
|
||
.vs-sel-l {
|
||
font-size: 23.6rpx;
|
||
color: #9CA3AF;
|
||
margin-right: 14rpx;
|
||
}
|
||
|
||
.vs-sel-v {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #1F2937;
|
||
lines: 1;
|
||
}
|
||
|
||
.vs-sel-v-on {
|
||
color: #2563EB;
|
||
}
|
||
|
||
/* ---------- 伤员卡 ---------- */
|
||
.vs-card {
|
||
position: relative;
|
||
background-color: #FFFFFF;
|
||
border: 2rpx solid #E5E7EB;
|
||
border-radius: 26rpx;
|
||
padding: 22rpx 24rpx 22rpx 32rpx;
|
||
margin-bottom: 18rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.vs-card-bar {
|
||
position: absolute;
|
||
left: 0rpx;
|
||
top: 0rpx;
|
||
bottom: 0rpx;
|
||
width: 8rpx;
|
||
}
|
||
|
||
.vs-card-l1 {
|
||
border-left: 8rpx solid #DC2626;
|
||
}
|
||
|
||
.vs-card-l2 {
|
||
border-left: 8rpx solid #F59E0B;
|
||
}
|
||
|
||
.vs-card-l3 {
|
||
border-left: 8rpx solid #10B981;
|
||
}
|
||
|
||
.vs-card-l4 {
|
||
border-left: 8rpx solid #1F2937;
|
||
}
|
||
|
||
.vs-avt {
|
||
width: 76rpx;
|
||
height: 76rpx;
|
||
border-radius: 22rpx;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.vs-avt-l1 {
|
||
background-color: #DC2626;
|
||
}
|
||
|
||
.vs-avt-l2 {
|
||
background-color: #D97706;
|
||
}
|
||
|
||
.vs-avt-l3 {
|
||
background-color: #059669;
|
||
}
|
||
|
||
.vs-avt-l4 {
|
||
background-color: #1F2937;
|
||
}
|
||
|
||
.vs-avt-t {
|
||
font-size: 33.6rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.vs-name {
|
||
font-size: 30.2rpx;
|
||
font-weight: bold;
|
||
color: #1F2937;
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
.vs-code {
|
||
font-size: 23.6rpx;
|
||
color: #9CA3AF;
|
||
margin-top: 6rpx;
|
||
}
|
||
|
||
.vs-inj {
|
||
margin-top: 16rpx;
|
||
background-color: #F9FAFB;
|
||
border-radius: 16rpx;
|
||
padding: 12rpx 16rpx 12rpx 16rpx;
|
||
}
|
||
|
||
.vs-inj-t {
|
||
font-size: 24.6rpx;
|
||
color: #6B7280;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.vs-bot {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
.vs-status {
|
||
border-radius: 18rpx;
|
||
padding: 8rpx 20rpx 8rpx 20rpx;
|
||
}
|
||
|
||
.vs-status-t {
|
||
font-size: 24.6rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.vs-time {
|
||
font-size: 23.6rpx;
|
||
color: #9CA3AF;
|
||
}
|
||
|
||
.vs-hint {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 12rpx 0rpx 16rpx 0rpx;
|
||
}
|
||
|
||
.vs-hint-t {
|
||
font-size: 23.6rpx;
|
||
color: #9CA3AF;
|
||
}
|
||
</style>
|