377 lines
10 KiB
Vue
Raw Permalink Normal View History

2026-07-27 11:26:39 +08:00
<template>
<full-page mainStyle="background:white" @reachBottom="loadMore" :class="{ 'elder-mode-active': elderMode }">
<view class="select-disease-container" :class="{ 'elder-mode-active': elderMode }">
<template #header>
<view class="search-container">
<view class="search">
<uni-icons class="search-icon" type="search" size="28"></uni-icons>
<input v-model="keyword" type="text" placeholder="搜索疾病" class="search-input" />
<view class="search-btn" :style="hasKeyword ? '' : 'opacity:0'" @click="clear()">取消</view>
</view>
</view>
<view v-if="!hasKeyword && commonDisease.length" class="history">
<view class="history-title">
<text>常见疾病</text>
</view>
<view class="history-list">
<view v-for="i in commonDisease" :key="i" class="history-item" @click="useHistoryItem(i)">{{ i }}</view>
</view>
</view>
<view v-if="!hasKeyword && historySearch.length" class="history">
<view class="history-title">
<text>历史搜索</text>
<uni-icons type="trash" color="#999" size="22" @click="clearHistory()"></uni-icons>
</view>
<view class="history-list">
<view v-for="i in historySearch" :key="i" class="history-item" @click="useHistoryItem(i)">{{ i }}</view>
</view>
</view>
</template>
<view v-if="keyword" class="disease-list">
<view v-for="i in list" :key="i.code" class="disease-item" @click="add(i)">
<view class="disease-name">
<text v-for="item in i.result" :class="item.highlight ? 'active' : ''">{{ item.text }}</text>
</view>
<view v-if="selectionMap[i.name]" class="added active">已添加</view>
</view>
</view>
</view>
</full-page>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { onLoad, onUnload } from '@dcloudio/uni-app';
import useRefChange from '@/hooks/useRefChange';
import { getDisease, getCommonDiseases } from '@/utils/api'
import { confirm, toast } from '@/utils/widget';
import fullPage from '@/components/full-page.vue';
// 长辈模式状态
const elderMode = ref(false);
// 长辈模式变化监听
function handleElderModeChange(isElder) {
elderMode.value = isElder;
console.log('select-disease页面长辈模式已更新为:', isElder);
}
// const commonDisease = ['高血压', '糖尿病', '高脂血', '冠心病', '咳嗽', '前列腺疾病', '支气管哮喘', '乳腺疾病', '宫颈类疾病', '心脏病', '支气管炎', '疣', '鼻炎', '帕金森', '腰椎间盘突出', '关节炎', '痛风', '颈椎病', '甲状腺疾病', '尿道炎', '消化不良', '带状疱疹', '阿尔茨海默病', '慢性乙型肝炎', '癫痫', '肾结石', '泌尿结石', '月经不调', '急性上呼吸道感染']
const commonDisease = ref([])
const keyword = ref('');
const loading = ref(false);
const list = ref([])
const more = ref(false);
const page = ref(1);
const historySearch = ref([]);
const selections = ref([])
const hasKeyword = computed(() => keyword.value.trim() !== '');
const selectionMap = computed(() => selections.value.reduce((acc, cur) => {
acc[cur] = true;
return acc;
}, {}));
useRefChange(keyword, search);
onLoad(() => {
getCommonDiseasesData()
// 初始化长辈模式状态
const savedElderMode = uni.getStorageSync('elderMode');
console.log('select-disease页面从本地存储读取长辈模式状态:', savedElderMode);
if (savedElderMode !== null && savedElderMode !== undefined) {
elderMode.value = savedElderMode;
}
// 从全局状态读取
const app = getApp();
if (app && app.globalData && typeof app.globalData.elderMode === 'boolean') {
elderMode.value = app.globalData.elderMode;
console.log('select-disease页面从全局状态读取长辈模式:', app.globalData.elderMode);
}
// 监听全局长辈模式变化事件
uni.$on('elderModeChanged', handleElderModeChange);
// 原有初始化逻辑
// commonDisease.value = Array.isArray(getApp().globalData.commonDisease) ? getApp().globalData.commonDisease : [];
// if (commonDisease.value.length === 0) {
// getCommonDiseasesData()
// }
try {
selections.value = JSON.parse(uni.getStorageSync('diseases-selected'));
const list = JSON.parse(uni.getStorageSync('search_disease_history'));
historySearch.value = Array.isArray(list) ? list.filter(i => typeof i === 'string' && i.trim()) : [];
} catch (e) { console.log(e) }
})
onUnload(() => {
uni.$off('elderModeChanged', handleElderModeChange);
})
function add(item) {
addHistory(item.name);
uni.$emit('on-disease-selected', item.name);
uni.navigateBack()
}
function addHistory(text) {
const list = [...historySearch.value.filter(i => i !== text)];
historySearch.value = [text, ...list].slice(0, 10)
}
function clear() {
keyword.value = ''
}
function clearHistory() {
confirm('确认清空吗?').then(() => (historySearch.value = []))
}
function loadMore() {
if (!loading.value && more.value) {
page.value++;
getList()
}
}
function search() {
if (keyword.value.trim() !== '') {
page.value = 1;
loading.value = false;
getList()
}
}
function useHistoryItem(item) {
keyword.value = item;
}
async function getList() {
if (loading.value) return;
loading.value = true
const res = await getDisease({ page: page.value, pageSize: 30, keyword: keyword.value });
const listData = res && Array.isArray(res.data) ? highlightedText(res.data, keyword.value.trim()) : [];
list.value = page.value === 1 ? listData : [...list.value, ...listData];
const message = res && typeof res.message === 'string' ? res.message : '获取药品失败';
if (!res || !res.success) {
toast(message)
}
loading.value = false;
more.value = res && res.pages > page.value;
}
function escapeRegExp(str) {
return str.replace(/[.*+?^=!:${}()|\[\]\/\\]/g, '\\$&');
}
function highlightedText(list, target) {
return list.map(i => {
if (target === '') {
return { ...i, result: [{ text: i.name, highlight: false }] }
}
let result = [];
let lastIndex = 0;
const regex = new RegExp(escapeRegExp(target), 'g');;
const text = typeof i.name === 'string' ? i.name : '';
// 在文本中找到所有匹配的部分
let match;
try {
while ((match = regex.exec(text)) !== null) {
// 将非匹配部分作为普通文本加入结果数组
if (match.index > lastIndex) {
result.push({ text: text.slice(lastIndex, match.index), highlight: false });
}
// 将匹配部分加入并标记为高亮
result.push({ text: match[0], highlight: true });
lastIndex = regex.lastIndex;
}
// 如果还有剩余部分,也要加入
if (lastIndex < text.length) {
result.push({ text: text.slice(lastIndex), highlight: false });
}
} catch (e) {
return { ...i, result: [{ text: i.name, highlight: false }] }
}
return { ...i, result };
})
}
async function getCommonDiseasesData() {
const { data } = await getCommonDiseases()
commonDisease.value = data && Array.isArray(data.diseases) ? data.diseases : [];
getApp().globalData.commonDisease = [...commonDisease.value];
}
watch(historySearch, n => {
uni.setStorageSync('search_disease_history', Array.isArray(n) ? JSON.stringify(n) : '');
})
</script>
<style lang="scss" scoped>
.search-container {
padding: 24rpx 30rpx;
background-color: white;
}
.search {
flex-shrink: 0;
display: flex;
align-items: center;
background: #f5f6f7;
height: 100rpx;
border-radius: 50rpx;
padding: 0 40rpx 0 30rpx;
&-input {
flex-grow: 1;
margin: 0 20rpx 0 10rpx;
background-color: transparent;
}
&-btn {
color: #999;
flex-shrink: 0;
}
}
.history {
background: white;
padding: 0 40rpx;
&-title {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 32rpx;
font-weight: 500;
color: #333;
margin-bottom: 30rpx;
}
&-list {
display: flex;
flex-wrap: wrap;
margin-right: -20rpx;
}
&-item {
padding: 12rpx 30rpx;
background: #f0f0f0;
border-radius: 16rpx;
font-size: 28rpx;
color: #333;
margin: 0 20rpx 20rpx 0;
}
}
.disease-list {
padding: 0 30rpx;
}
.disease-item {
display: flex;
padding: 24rpx 0;
font-size: 28rpx;
line-height: 48rpx;
color: #333;
border-bottom: 1px solid #e5e5e5;
.disease-name {
width: 0;
flex-grow: 1;
}
.added {
flex-shrink: 0;
margin-left: 30rpx;
}
.active {
color: $theme-brown-primary;
}
}
/* 长辈模式特定样式 */
.elder-mode-active {
.search-container {
padding: 40rpx 30rpx !important;
}
.search {
height: 120rpx !important;
padding: 0 50rpx 0 40rpx !important;
border-radius: 60rpx !important;
.search-icon {
transform: scale(1.2) !important;
}
&-input {
font-size: 36rpx !important;
margin: 0 25rpx 0 15rpx !important;
}
&-btn {
font-size: 36rpx !important;
}
}
.history {
padding: 0 50rpx !important;
&-title {
font-size: 42rpx !important;
font-weight: bold !important;
margin-bottom: 40rpx !important;
text {
font-size: 42rpx !important;
}
}
&-list {
margin-right: -30rpx !important;
}
&-item {
font-size: 36rpx !important;
padding: 18rpx 35rpx !important;
margin: 0 30rpx 30rpx 0 !important;
border-radius: 20rpx !important;
line-height: 1.4 !important;
}
}
.disease-list {
padding: 0 40rpx !important;
}
.disease-item {
padding: 35rpx 0 !important;
font-size: 36rpx !important;
line-height: 1.5 !important;
.disease-name {
font-size: 36rpx !important;
line-height: 1.5 !important;
word-wrap: break-word !important;
text {
font-size: 36rpx !important;
}
}
.added {
font-size: 36rpx !important;
margin-left: 40rpx !important;
}
}
}
</style>