377 lines
10 KiB
Vue
377 lines
10 KiB
Vue
|
|
<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>
|