ykt-wxapp/pages/library/diagnosis-list.vue

186 lines
4.5 KiB
Vue
Raw Permalink Normal View History

2026-01-27 16:46:36 +08:00
<template>
<view class="page">
<view class="top">
<uni-easyinput v-model="keyword" prefixIcon="search" placeholder="请搜索诊断名称" @input="onInput" />
</view>
<scroll-view scroll-y class="scroll">
<view v-for="item in showList" :key="item.key" class="row" @click="toggle(item)">
<view class="label">{{ item.label }}</view>
<uni-icons :type="selectedMap[item.label] ? 'checkmarkempty' : ''" size="22" color="#007aff" />
</view>
<view v-if="showList.length === 0" class="empty">暂无诊断数据</view>
2026-01-28 20:01:28 +08:00
<view style="height: 240rpx;"></view>
2026-01-27 16:46:36 +08:00
</scroll-view>
<view class="footer">
<button class="btn primary" @click="save">确定</button>
</view>
</view>
</template>
<script setup>
import { computed, onUnmounted, ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import api from '@/utils/api';
import { toast } from '@/utils/widget';
const ready = ref(false);
const keyword = ref('');
const list = ref([]);
const selections = ref([]);
const mult = ref(false);
const eventName = ref('change-diagnosis');
const selectedMap = computed(() => selections.value.reduce((m, i) => ((m[i] = true), m), {}));
function normalizeText(v) {
return v ? String(v) : '';
}
const fullMatched = computed(() => {
const value = String(keyword.value || '').trim();
if (!value) return null;
return { label: value, value, key: `full_${value}` };
});
const showList = computed(() => {
const base = Array.isArray(list.value) ? list.value : [];
const arr = [];
if (fullMatched.value) arr.push(fullMatched.value);
base.forEach((i) => {
if (!i || !i.label) return;
if (fullMatched.value && i.label === fullMatched.value.label) return;
arr.push(i);
});
return arr;
});
let timer = null;
function onInput() {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
query();
}, 600);
}
onUnmounted(() => {
if (timer) clearTimeout(timer);
});
onLoad((opt) => {
eventName.value = opt?.eventName ? String(opt.eventName) : 'change-diagnosis';
mult.value = String(opt?.mult || '') === 'YES';
if (mult.value) {
const data = uni.getStorageSync('diagnosis-list-selection');
selections.value = Array.isArray(data) ? data : [];
uni.removeStorageSync('diagnosis-list-selection');
} else {
const v = opt?.value ? String(opt.value) : '';
selections.value = v ? [v] : [];
}
ready.value = true;
query();
});
async function query() {
if (!ready.value) return;
const value = String(keyword.value || '').trim();
uni.showLoading({ title: '加载中...' });
try {
const res = await api('getDisease', { diseaseName: value });
const arr = Array.isArray(res?.data?.data) ? res.data.data : [];
list.value = arr
.map((i) => {
const label = normalizeText(i?.diseaseName);
const code = normalizeText(i?.code);
if (!label) return null;
return { label, value: code || label, key: code || label };
})
.filter(Boolean);
} catch (e) {
list.value = [];
} finally {
uni.hideLoading();
}
}
function toggle(item) {
if (!item || !item.label) return;
const index = selections.value.findIndex((i) => i === item.label);
if (index >= 0) {
selections.value.splice(index, 1);
return;
}
if (mult.value) selections.value.push(item.label);
else selections.value = [item.label];
}
function save() {
if (selections.value.length === 0) return toast('请选择');
if (mult.value) uni.$emit(eventName.value, selections.value);
else uni.$emit(eventName.value, selections.value[0]);
uni.navigateBack();
}
</script>
<style scoped>
.page {
min-height: 100vh;
background: #fff;
2026-01-28 20:01:28 +08:00
padding-bottom: calc(152rpx + env(safe-area-inset-bottom));
2026-01-27 16:46:36 +08:00
}
.top {
2026-01-28 20:01:28 +08:00
padding: 24rpx 28rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
2026-01-27 16:46:36 +08:00
}
.scroll {
2026-01-28 20:01:28 +08:00
height: calc(100vh - 280rpx);
2026-01-27 16:46:36 +08:00
}
.row {
display: flex;
align-items: center;
justify-content: space-between;
2026-01-28 20:01:28 +08:00
padding: 28rpx 28rpx;
border-bottom: 2rpx solid #f2f2f2;
2026-01-27 16:46:36 +08:00
}
.label {
2026-01-28 20:01:28 +08:00
font-size: 28rpx;
2026-01-27 16:46:36 +08:00
color: #111827;
2026-01-28 20:01:28 +08:00
margin-right: 20rpx;
2026-01-27 16:46:36 +08:00
}
.empty {
2026-01-28 20:01:28 +08:00
padding: 120rpx 0;
2026-01-27 16:46:36 +08:00
text-align: center;
color: #9aa0a6;
2026-01-28 20:01:28 +08:00
font-size: 26rpx;
2026-01-27 16:46:36 +08:00
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
2026-01-28 20:01:28 +08:00
padding: 24rpx 28rpx calc(24rpx + env(safe-area-inset-bottom));
box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
2026-01-27 16:46:36 +08:00
}
.btn {
width: 100%;
2026-01-28 20:01:28 +08:00
height: 88rpx;
line-height: 88rpx;
border-radius: 12rpx;
font-size: 30rpx;
2026-01-27 16:46:36 +08:00
}
.btn::after {
border: none;
}
.btn.primary {
background: #4f6ef7;
color: #fff;
}
</style>