482 lines
11 KiB
Vue
482 lines
11 KiB
Vue
<template>
|
||
<view class="content">
|
||
<view class="navbox">
|
||
<view class="status_bar"></view>
|
||
<uni-nav-bar
|
||
left-icon="left"
|
||
title="患者消息"
|
||
@clickLeft="goBack"
|
||
color="#8B2316"
|
||
:border="false"
|
||
backgroundColor="#eee"
|
||
>
|
||
<template #right>
|
||
<view class="nav-right">
|
||
<uni-icons type="search" size="24" color="#8B2316" @click="searchPatients"></uni-icons>
|
||
<uni-icons type="staff" size="24" color="#8B2316" @click="managePatients" style="margin-left: 30rpx;"></uni-icons>
|
||
</view>
|
||
</template>
|
||
</uni-nav-bar>
|
||
</view>
|
||
|
||
<scroll-view
|
||
class="message-list"
|
||
scroll-y="true"
|
||
refresher-enabled="true"
|
||
:refresher-triggered="isRefreshing"
|
||
@refresherrefresh="onRefresh"
|
||
>
|
||
<empty></empty>
|
||
</scroll-view>
|
||
|
||
<view class="tab-bar">
|
||
<view class="tab-item active">
|
||
<text class="tab-text">患者消息</text>
|
||
</view>
|
||
<view class="tab-item" @click="goListTab">
|
||
<text class="tab-text">患者列表</text>
|
||
<view class="tab-dot" v-if="hasNewPatient">
|
||
<uni-badge class="uni-badge-left-margin" :text="applyList.length" :offset="[-3, -3]" size="small"></uni-badge>
|
||
</view>
|
||
</view>
|
||
<view class="tab-item" @click="goPlanTab">
|
||
<text class="tab-text">随访计划</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
<<<<<<< HEAD
|
||
import { computed, ref } from 'vue';
|
||
import { onBackPress, onLoad, onShow } from '@dcloudio/uni-app';
|
||
import api from '@/api/api.js';
|
||
import navTo from '@/utils/navTo.js';
|
||
=======
|
||
import { ref, getCurrentInstance, computed, nextTick, shallowRef } from 'vue';
|
||
import { onShow,onLoad,onBackPress,onHide} from "@dcloudio/uni-app";
|
||
import dayImg from "@/static/visit_data11.png"
|
||
import planImg from "@/static/visitplan.png"
|
||
import api from '@/api/api.js';
|
||
import navTo from '@/utils/navTo.js';
|
||
import docUrl from '@/utils/docUrl.js';
|
||
import unidialog from '@/components/dialog/dialog.vue'
|
||
import defaultImg from "@/static/default.png"
|
||
import newPatientImg from "@/static/new_patient.png"
|
||
import delImg from "@/static/iv_delete.png"
|
||
import editImg from "@/static/edit_patitent.png"
|
||
const patientList = ref([]);
|
||
const visible = ref(false)
|
||
const message = ref('')
|
||
const selectedPatientUuid = ref('')
|
||
const selectedPatientName = ref('')
|
||
const patientDataLoaded = ref(false);
|
||
const patientDataLoading = ref(false);
|
||
const firstLetterCache = new Map();
|
||
const showAlert = ref(false);
|
||
const navHeight = ref(40);
|
||
onBackPress(() => {
|
||
plus.runtime.quit();
|
||
return true;
|
||
});
|
||
onHide(() => {
|
||
patientDataLoaded.value = false;
|
||
});
|
||
import alertImg from "@/static/patientgif.png"
|
||
const getNavHeight = () => {
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
console.log(2223);
|
||
console.log(systemInfo);
|
||
navHeight.value = systemInfo.statusBarHeight + 44;
|
||
console.log(navHeight.value);
|
||
}
|
||
import pinyin from 'pinyin';
|
||
import dayjs from 'dayjs'
|
||
import lineImg from "@/static/item_visitplan_fg.png"
|
||
const loadFinish = ref(false);
|
||
//import ConversationList from './conversation-list/index.vue'
|
||
const title = ref('患者消息');
|
||
const goPatientDetail = (uuid) => {
|
||
navTo({
|
||
url: `/pages_app/patientDetail/patientDetail?uuid=${uuid}&from=patientMsg`
|
||
})
|
||
}
|
||
const editPatient = (uuid) => {
|
||
console.log(uuid)
|
||
navTo({
|
||
url: `/pages_app/patientSetting/patientSetting?uuid=${uuid}?from=patientMsg`
|
||
})
|
||
}
|
||
const onPatientItemLongPress = (item) => {
|
||
if (!item || !item.uuid) return
|
||
selectedPatientUuid.value = item.uuid
|
||
selectedPatientName.value = item.nickname || item.realName
|
||
message.value = `确认解除[${selectedPatientName.value || '该患者'}]的随访关系?`
|
||
visible.value = true
|
||
}
|
||
const deleteFollowUpFromList = async () => {
|
||
if (!selectedPatientUuid.value) {
|
||
visible.value = false
|
||
return
|
||
}
|
||
const res = await api.cancelRes({
|
||
patientUuid: selectedPatientUuid.value
|
||
})
|
||
if (res.code == 1) {
|
||
uni.showToast({
|
||
title: '解除成功',
|
||
icon: 'none'
|
||
})
|
||
patientListByGBK()
|
||
}
|
||
visible.value = false
|
||
}
|
||
const avatarErrorMap = ref({});
|
||
const getAvatarKey = (item = {}) => String(item.uuid || item.id || item.realName || item.nickname || '');
|
||
const normalizeAvatarUrl = (photo) => {
|
||
const raw = String(photo || '').trim();
|
||
if (!raw) return defaultImg;
|
||
if (/^https?:\/\//i.test(raw)) return raw;
|
||
return `${docUrl}${raw}`;
|
||
};
|
||
const getPatientAvatar = (item = {}) => {
|
||
const key = getAvatarKey(item);
|
||
if (key && avatarErrorMap.value[key]) return defaultImg;
|
||
return item.avatarUrl || defaultImg;
|
||
};
|
||
const handlePatientAvatarError = (item) => {
|
||
if (!item) return;
|
||
const key = getAvatarKey(item);
|
||
if (!key) return;
|
||
avatarErrorMap.value = {
|
||
...avatarErrorMap.value,
|
||
[key]: true
|
||
};
|
||
}
|
||
const goCode = () => {
|
||
navTo({
|
||
url: `/pages_app/myCode/myCode?from=patientMsg`
|
||
})
|
||
}
|
||
// 仅保留年月日
|
||
const formatYMD = (input) => {
|
||
if (!input) return '';
|
||
const d = dayjs(input);
|
||
return d.isValid() ? d.format('YYYY-MM-DD') : '';
|
||
}
|
||
|
||
const formatYearMonth = (input) => {
|
||
if (!input) return '';
|
||
const d = dayjs(input);
|
||
return d.isValid() ? d.format('YYYY年MM月') : '';
|
||
}
|
||
// 格式化显示日(如:03)
|
||
const formatDay = (input) => {
|
||
if (!input) return '';
|
||
const d = dayjs(input);
|
||
return d.isValid() ? d.format('DD日') : '';
|
||
}
|
||
// 申请列表数据
|
||
const messageList = ref([
|
||
{
|
||
id: 1,
|
||
patientName: '测试',
|
||
messagePreview: '[图片]',
|
||
time: '2025-08-11',
|
||
avatar: ''
|
||
}
|
||
]);
|
||
|
||
// 当前激活的标签
|
||
const activeTab = ref('message');
|
||
const activeLetter = ref('A');
|
||
const scrollIntoViewId = ref('');
|
||
|
||
// 控制添加菜单弹窗显示
|
||
const showAddMenuFlag = ref(false);
|
||
|
||
// 组件实例(用于 selectorQuery 作用域)
|
||
const { proxy } = getCurrentInstance();
|
||
|
||
const LETTER_ORDER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||
const sortLetter = (a, b) => {
|
||
if (a === '#') return 1;
|
||
if (b === '#') return -1;
|
||
const ai = LETTER_ORDER.indexOf(a);
|
||
const bi = LETTER_ORDER.indexOf(b);
|
||
if (ai === -1 && bi === -1) return String(a).localeCompare(String(b));
|
||
if (ai === -1) return 1;
|
||
if (bi === -1) return -1;
|
||
return ai - bi;
|
||
};
|
||
// up-index-list 索引使用实际分组字母,避免索引与锚点数量不一致
|
||
const indexList = ref([]);
|
||
// 列表高度(像素):窗口高度 - 顶部导航(rpx转px) - 底部tab(约100rpx->px) - 操作区(约200rpx->px)
|
||
const groupsListHeight = ref(0);
|
||
const rpxToPx = (rpx) => {
|
||
const { screenWidth } = uni.getSystemInfoSync();
|
||
return Math.round((screenWidth / 750) * rpx);
|
||
};
|
||
const computeListHeight = () => {
|
||
const { windowHeight } = uni.getSystemInfoSync();
|
||
const reserved = rpxToPx(240); // 140rpx(nav) + 100rpx(tab) 近似
|
||
groupsListHeight.value = Math.max(0, windowHeight - reserved);
|
||
};
|
||
>>>>>>> cbc427e41ce2bf41f4bd01d9206215c015e257ae
|
||
|
||
const applyList = ref([]);
|
||
const isRefreshing = ref(false);
|
||
const hasNewPatient = computed(() => applyList.value.length > 0);
|
||
|
||
const getApplyList = async () => {
|
||
try {
|
||
const res = await api.applyList();
|
||
if (res && res.code === 200) {
|
||
applyList.value = res.data || [];
|
||
}
|
||
} catch (error) {}
|
||
};
|
||
|
||
const onRefresh = async () => {
|
||
isRefreshing.value = true;
|
||
try {
|
||
await getApplyList();
|
||
uni.showToast({
|
||
title: '刷新成功',
|
||
icon: 'none',
|
||
duration: 1200
|
||
});
|
||
<<<<<<< HEAD
|
||
} finally {
|
||
isRefreshing.value = false;
|
||
=======
|
||
};
|
||
|
||
// 随访计划上拉加载
|
||
const onFollowUpLoadMore = async () => {
|
||
if (!followUpHasMore.value || followUpLoading.value) return;
|
||
await getFollowUpList(false);
|
||
};
|
||
|
||
// 搜索患者
|
||
const searchPatients = () => {
|
||
navTo({
|
||
url: `/pages_app/searchPatient/searchPatient?from=patientMsg`
|
||
})
|
||
};
|
||
|
||
// 管理患者
|
||
const managePatients = () => {
|
||
uni.showToast({
|
||
title: '患者管理',
|
||
icon: 'none'
|
||
});
|
||
};
|
||
|
||
// 打开消息
|
||
const openMessage = (item) => {
|
||
uni.showToast({
|
||
title: `打开患者 ${item?.patientName || '未知'} 的消息`,
|
||
icon: 'none'
|
||
});
|
||
// 这里可以跳转到消息详情页面
|
||
// uni.navigateTo({
|
||
// url: `/pages_app/messageDetail/messageDetail?id=${item?.id}`
|
||
// });
|
||
};
|
||
|
||
// 切换标签
|
||
const switchTab = (tab) => {
|
||
activeTab.value = tab;
|
||
|
||
|
||
switch(tab) {
|
||
case 'message':
|
||
// 患者消息页面逻辑 - 刷新申请列表
|
||
uni.sendNativeEvent('goPatientMsg', {
|
||
msg: 'goPatientMsg'
|
||
},ret => {
|
||
console.log(ret);
|
||
})
|
||
// getApplyList();
|
||
// title.value = '患者消息';
|
||
break;
|
||
case 'list':
|
||
title.value = '患者列表';
|
||
if (patientDataLoaded.value) {
|
||
loadFinish.value = true;
|
||
break;
|
||
}
|
||
uni.showLoading({
|
||
title: '加载中...',
|
||
mask: true
|
||
});
|
||
patientListByGBK();
|
||
// 显示患者列表
|
||
break;
|
||
case 'plan':
|
||
title.value = '随访计划';
|
||
// 随访计划页面 - 加载随访计划数据
|
||
if (followUpList.value.length === 0) {
|
||
getFollowUpList(true);
|
||
}
|
||
break;
|
||
}
|
||
};
|
||
|
||
// 添加新患者
|
||
const addNewPatient = () => {
|
||
navTo({
|
||
url: '/pages_app/myPatient/myPatient?from=patientMsg'
|
||
})
|
||
};
|
||
|
||
// 管理患者分组
|
||
const managePatientGroups = () => {
|
||
navTo({
|
||
url: '/pages_app/patientGroup/patientGroup?from=patientMsg'
|
||
})
|
||
};
|
||
|
||
// 打开患者详情
|
||
const openPatient = (patientName) => {
|
||
uni.showToast({
|
||
title: `打开患者: ${patientName}`,
|
||
icon: 'none'
|
||
});
|
||
};
|
||
|
||
// 添加随访计划
|
||
const addFollowUpPlan = () => {
|
||
showAddMenuFlag.value = false;
|
||
uni.navigateTo({
|
||
url: '/pages_app/visit/visit?from=patientMsg'
|
||
});
|
||
};
|
||
const goBack = () => {
|
||
plus.runtime.quit();
|
||
>>>>>>> cbc427e41ce2bf41f4bd01d9206215c015e257ae
|
||
}
|
||
};
|
||
|
||
const searchPatients = () => {
|
||
navTo({
|
||
url: '/pages_app/searchPatient/searchPatient'
|
||
});
|
||
};
|
||
|
||
const managePatients = () => {
|
||
uni.showToast({
|
||
title: '患者管理',
|
||
icon: 'none'
|
||
});
|
||
};
|
||
|
||
const goListTab = () => {
|
||
navTo({
|
||
url: '/pages_app/patientMsg/patientList'
|
||
});
|
||
};
|
||
|
||
const goPlanTab = () => {
|
||
navTo({
|
||
url: '/pages_app/patientMsg/patientPlan'
|
||
});
|
||
};
|
||
|
||
const goBack = () => {
|
||
plus.runtime.quit();
|
||
};
|
||
|
||
const notifyNativePatientMsg = () => {
|
||
uni.sendNativeEvent('goPatientMsg', { msg: 'goPatientMsg' }, () => {});
|
||
};
|
||
|
||
onBackPress(() => {
|
||
plus.runtime.quit();
|
||
return true;
|
||
});
|
||
|
||
onLoad((options) => {
|
||
if (options.type === 'list') {
|
||
goListTab();
|
||
return;
|
||
}
|
||
if (options.type === 'plan') {
|
||
goPlanTab();
|
||
return;
|
||
}
|
||
getApplyList();
|
||
notifyNativePatientMsg();
|
||
});
|
||
|
||
onShow(() => {
|
||
getApplyList();
|
||
notifyNativePatientMsg();
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.content {
|
||
background-color: #f5f5f5;
|
||
height: 100vh;
|
||
overflow-y: hidden;
|
||
}
|
||
|
||
.nav-right {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.message-list {
|
||
margin-top: calc(var(--status-bar-height) + 44px);
|
||
height: calc(100vh - var(--status-bar-height) - 44px - 103rpx);
|
||
background: #fff;
|
||
}
|
||
|
||
.tab-bar {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 100rpx;
|
||
background-color: #f8f8f8;
|
||
display: flex;
|
||
align-items: center;
|
||
border-top: 1rpx solid #e0e0e0;
|
||
z-index: 999;
|
||
}
|
||
|
||
.tab-item {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
height: 100%;
|
||
}
|
||
|
||
.tab-item:nth-child(2) {
|
||
border: 2rpx solid #ccc;
|
||
border-top: none;
|
||
border-bottom: none;
|
||
}
|
||
|
||
.tab-text {
|
||
font-size: 32rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.tab-item.active .tab-text {
|
||
color: #8B2316;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.tab-dot {
|
||
position: absolute;
|
||
top: 18rpx;
|
||
right: 28rpx;
|
||
}
|
||
</style>
|