9.2 zjd提交
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
color="#8B2316"
|
||||
height="140rpx"
|
||||
:border="false"
|
||||
backgroundColor="#ffffff"
|
||||
backgroundColor="#eee"
|
||||
>
|
||||
<template #right>
|
||||
<view class="nav-right">
|
||||
@@ -20,31 +20,43 @@
|
||||
</uni-nav-bar>
|
||||
|
||||
<!-- 消息列表区域 -->
|
||||
<view class="message-list" v-if="activeTab === 'message'">
|
||||
<scroll-view
|
||||
class="message-list"
|
||||
v-if="activeTab === 'message'"
|
||||
scroll-y="true"
|
||||
refresher-enabled="true"
|
||||
:refresher-triggered="isRefreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
>
|
||||
<!-- 消息项 -->
|
||||
<view class="message-item" @click="openMessage">
|
||||
<view class="message-item" v-for="(item, index) in messageList" :key="item.id || index" @click="openMessage(item)">
|
||||
<view class="message-avatar">
|
||||
<view class="avatar-placeholder">
|
||||
<view class="avatar-placeholder" v-if="!item.avatar">
|
||||
<uni-icons type="person" size="32" color="#ffffff"></uni-icons>
|
||||
</view>
|
||||
<image v-else :src="item.avatar" class="patient-avatar" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="message-content">
|
||||
<view class="message-header">
|
||||
<text class="patient-name">测试</text>
|
||||
<text class="message-time">2025-08-11</text>
|
||||
<text class="patient-name">{{ item.patientName }}</text>
|
||||
<text class="message-time">{{ item.time }}</text>
|
||||
</view>
|
||||
<view class="message-preview">
|
||||
<text class="preview-text">[图片]</text>
|
||||
<text class="preview-text">{{ item.messagePreview }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<view class="empty-state" v-if="messageList.length === 0">
|
||||
<view class="empty-state" v-if="messageList.length === 0 && !isRefreshing">
|
||||
<uni-icons type="chat" size="80" color="#cccccc"></uni-icons>
|
||||
<text class="empty-text">暂无患者消息</text>
|
||||
<text class="empty-subtext">下拉刷新获取最新申请</text>
|
||||
<view class="debug-actions">
|
||||
<button class="debug-btn" @click="getApplyList">测试API调用</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 患者列表区域 -->
|
||||
<view class="patient-list" v-if="activeTab === 'list'">
|
||||
@@ -55,7 +67,7 @@
|
||||
<uni-icons type="person" size="24" color="#ffffff"></uni-icons>
|
||||
<uni-icons type="plus" size="16" color="#ffffff" style="position: absolute; right: 8rpx; bottom: 8rpx;"></uni-icons>
|
||||
</view>
|
||||
<text class="action-text">新的患者</text>
|
||||
<text class="action-text">新的患者<text class="new-patient-count" v-if="applyList.length > 0">(待审核{{ applyList.length }}人)</text></text>
|
||||
<uni-icons type="right" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
|
||||
@@ -68,7 +80,7 @@
|
||||
<view class="grid-item"></view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="action-text">患者分组 (随访5人)</text>
|
||||
<text class="action-text">患者分组 <text class="new-patient-count" v-if="patientList.length > 0">(随访{{ patientList.length }}人)</text></text>
|
||||
<uni-icons type="right" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
@@ -81,24 +93,24 @@
|
||||
<up-index-anchor :text="group.letter" />
|
||||
|
||||
<view class="group-section">
|
||||
<view class="patient-item" v-for="item in group.items" :key="item.name" @click="openPatient(item.name)">
|
||||
<view class="patient-item" v-for="item in group.items" :key="item.uuid || item.id" >
|
||||
<template v-if="item.placeholder">
|
||||
<view class="patient-avatar-placeholder">
|
||||
<uni-icons type="person" size="32" color="#ffffff"></uni-icons>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<image class="patient-avatar" :src="item.avatar" mode="aspectFill"></image>
|
||||
<image class="patient-avatar" :src="docUrl+item.photo" mode="aspectFill"></image>
|
||||
</template>
|
||||
<view class="patient-info">
|
||||
<text class="patient-name">{{ item.name }}</text>
|
||||
<view class="patient-info" @click="goPatientDetail(item.uuid)">
|
||||
<text class="patient-name">{{ item.realName }}</text>
|
||||
<view class="patient-badge" v-if="item.badge">
|
||||
<text class="badge-text">{{ item.badge }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="patient-status">
|
||||
<uni-icons type="compose" size="20" color="#8B2316"></uni-icons>
|
||||
<text class="follow-date">随访于{{ item.date }}</text>
|
||||
<uni-icons type="compose" size="20" color="#8B2316" @click.stop="editPatient(item.uuid)"></uni-icons>
|
||||
<text class="follow-date">随访于{{ formatYMD(item.join_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -108,7 +120,15 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="plan" v-if="activeTab === 'plan'">
|
||||
<empty></empty>
|
||||
|
||||
<view class="apply-list" v-if="applyList.length > 0">
|
||||
<view class="apply-item" v-for="item in applyList" :key="item.id">
|
||||
<view class="apply-content">
|
||||
<text class="apply-text">{{ item.messagePreview }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<empty v-else></empty>
|
||||
|
||||
<!-- 悬浮添加按钮 -->
|
||||
<view class="floating-add-btn" @click="showAddMenu">
|
||||
@@ -159,8 +179,30 @@
|
||||
import { onShow } 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';
|
||||
const patientList = ref([]);
|
||||
import pinyin from 'pinyin';
|
||||
import dayjs from 'dayjs'
|
||||
const goPatientDetail = (uuid) => {
|
||||
navTo({
|
||||
url: `/pages_app/patientDetail/patientDetail?uuid=${uuid}`
|
||||
})
|
||||
}
|
||||
const editPatient = (uuid) => {
|
||||
console.log(uuid)
|
||||
navTo({
|
||||
url: `/pages_app/patientSetting/patientSetting?uuid=${uuid}`
|
||||
})
|
||||
}
|
||||
// 仅保留年月日
|
||||
const formatYMD = (input) => {
|
||||
if (!input) return '';
|
||||
const d = dayjs(input);
|
||||
return d.isValid() ? d.format('YYYY-MM-DD') : '';
|
||||
}
|
||||
// 申请列表数据
|
||||
const messageList = ref([
|
||||
{
|
||||
id: 1,
|
||||
@@ -184,8 +226,9 @@
|
||||
// 组件实例(用于 selectorQuery 作用域)
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// up-index-list 数据源(与当前示例分组一致)
|
||||
const indexList = ref([]);
|
||||
// up-index-list 索引固定为 26 个大写字母
|
||||
// 索引固定为 A-Z
|
||||
const indexList = ref('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''));
|
||||
// 列表高度(像素):窗口高度 - 顶部导航(rpx转px) - 底部tab(约100rpx->px) - 操作区(约200rpx->px)
|
||||
const groupsListHeight = ref(0);
|
||||
const rpxToPx = (rpx) => {
|
||||
@@ -201,59 +244,117 @@
|
||||
// 分组数据(可从接口返回后赋值)
|
||||
const patientGroups = ref([]);
|
||||
|
||||
// 动态生成索引字母
|
||||
// 重建索引时保持固定 A-Z
|
||||
const rebuildIndexList = () => {
|
||||
// 固定 A-Z,不随分组变化
|
||||
indexList.value = patientGroups.value.map(g => g.letter);
|
||||
};
|
||||
|
||||
// 生成模拟数据
|
||||
const generateMockDate = () => {
|
||||
const start = new Date(2019, 0, 1).getTime();
|
||||
const end = new Date().getTime();
|
||||
const d = new Date(start + Math.random() * (end - start));
|
||||
const y = d.getFullYear();
|
||||
const m = `${d.getMonth() + 1}`.padStart(2, '0');
|
||||
const day = `${d.getDate()}`.padStart(2, '0');
|
||||
return `${y}-${m}-${day}`;
|
||||
};
|
||||
|
||||
const generateMockGroups = () => {
|
||||
const lettersPool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||||
const avatarSamples = ['/static/avatar-a.png','/static/avatar-l.png','/static/avatar-l2.png'];
|
||||
const groups = [];
|
||||
lettersPool.forEach((L) => {
|
||||
// 随机产生0-3个患者
|
||||
const count = Math.floor(Math.random() * 3);
|
||||
if (count === 0) return;
|
||||
const items = Array.from({length: count}).map((_, i) => {
|
||||
const usePlaceholder = Math.random() < 0.4;
|
||||
return {
|
||||
name: `${L}患者${i+1}`,
|
||||
avatar: usePlaceholder ? '' : avatarSamples[Math.floor(Math.random()*avatarSamples.length)],
|
||||
placeholder: usePlaceholder,
|
||||
badge: Math.random() < 0.2 ? 'GOOD' : '',
|
||||
date: generateMockDate()
|
||||
};
|
||||
});
|
||||
groups.push({ letter: L, items });
|
||||
// 工具:获取首字母
|
||||
const generateMockDate = () => '';
|
||||
const getFirstLetter = (chineseName) => {
|
||||
// 假设名字由一个或多个汉字组成,我们取第一个汉字的首字母
|
||||
const firstChar = chineseName.charAt(0); // 获取第一个汉字
|
||||
const pinyinArray = pinyin(firstChar, { style: pinyin.STYLE_NORMAL }); // 获取拼音数组
|
||||
return pinyinArray[0][0].charAt(0); // 返回拼音的第一个字母
|
||||
}
|
||||
// 根据 patientList 构建按拼音首字母的分组
|
||||
const buildGroupsFromPatients = () => {
|
||||
const map = new Map();
|
||||
patientList.value.forEach((p) => {
|
||||
const name = p.realName;
|
||||
const first = getFirstLetter(name).toUpperCase();
|
||||
const letter = /^[A-Z]$/.test(first) ? first : '#';
|
||||
if (!map.has(letter)) map.set(letter, []);
|
||||
map.get(letter).push(p);
|
||||
});
|
||||
return groups;
|
||||
};
|
||||
|
||||
// 加载模拟数据
|
||||
const loadMockGroups = () => {
|
||||
uni.showLoading({ title: '加载中' });
|
||||
setTimeout(() => {
|
||||
patientGroups.value = generateMockGroups();
|
||||
rebuildIndexList();
|
||||
uni.hideLoading();
|
||||
}, 300);
|
||||
const letters = Array.from(map.keys()).sort((a,b) => a.localeCompare(b));
|
||||
patientGroups.value = letters.map(l => ({ letter: l, items: map.get(l) }));
|
||||
rebuildIndexList();
|
||||
};
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
// 申请列表数据
|
||||
const applyList = ref([]);
|
||||
|
||||
// 刷新状态
|
||||
const isRefreshing = ref(false);
|
||||
|
||||
const getApplyList = async () => { // 申请列表
|
||||
|
||||
try {
|
||||
|
||||
let userInfo=uni.getStorageSync('userInfo')
|
||||
const res = await api.applyList();
|
||||
|
||||
if (res && res.code === 200) {
|
||||
applyList.value = res.data;
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.message || '获取申请列表失败',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取申请列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '网络请求失败',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const patientListByGBK = async () => {
|
||||
|
||||
const res = await api.patientListByGBK();
|
||||
if(res.code == 1){
|
||||
patientList.value = res.data;
|
||||
|
||||
buildGroupsFromPatients()
|
||||
}
|
||||
|
||||
};
|
||||
const page=ref(1)
|
||||
const followUpList = async () => {
|
||||
let userInfo=uni.getStorageSync('userInfo')
|
||||
const res = await api.followUpList({
|
||||
page:page.value,
|
||||
pageSize:10
|
||||
});
|
||||
if(res.code === '1'){
|
||||
followUpList.value = res.data;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = async () => {
|
||||
isRefreshing.value = true;
|
||||
|
||||
try {
|
||||
await getApplyList();
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('刷新失败:', error);
|
||||
uni.showToast({
|
||||
title: '刷新失败',
|
||||
icon: 'error',
|
||||
duration: 1500
|
||||
});
|
||||
} finally {
|
||||
isRefreshing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索患者
|
||||
const searchPatients = () => {
|
||||
@@ -272,11 +373,15 @@
|
||||
};
|
||||
|
||||
// 打开消息
|
||||
const openMessage = () => {
|
||||
const openMessage = (item) => {
|
||||
uni.showToast({
|
||||
title: '打开消息',
|
||||
title: `打开患者 ${item?.patientName || '未知'} 的消息`,
|
||||
icon: 'none'
|
||||
});
|
||||
// 这里可以跳转到消息详情页面
|
||||
// uni.navigateTo({
|
||||
// url: `/pages_app/messageDetail/messageDetail?id=${item?.id}`
|
||||
// });
|
||||
};
|
||||
|
||||
// 切换标签
|
||||
@@ -285,7 +390,8 @@
|
||||
|
||||
switch(tab) {
|
||||
case 'message':
|
||||
// 患者消息页面逻辑
|
||||
// 患者消息页面逻辑 - 刷新申请列表
|
||||
getApplyList();
|
||||
break;
|
||||
case 'list':
|
||||
// 显示患者列表
|
||||
@@ -302,18 +408,16 @@
|
||||
|
||||
// 添加新患者
|
||||
const addNewPatient = () => {
|
||||
uni.showToast({
|
||||
title: '添加新患者',
|
||||
icon: 'none'
|
||||
});
|
||||
navTo({
|
||||
url: '/pages_app/myPatient/myPatient'
|
||||
})
|
||||
};
|
||||
|
||||
// 管理患者分组
|
||||
const managePatientGroups = () => {
|
||||
uni.showToast({
|
||||
title: '管理患者分组',
|
||||
icon: 'none'
|
||||
});
|
||||
navTo({
|
||||
url: '/pages_app/patientGroup/patientGroup'
|
||||
})
|
||||
};
|
||||
|
||||
// 打开患者详情
|
||||
@@ -354,14 +458,15 @@
|
||||
// 页面显示时加载数据
|
||||
onShow(() => {
|
||||
loadMessageList();
|
||||
loadMockGroups();
|
||||
computeListHeight();
|
||||
getApplyList();
|
||||
patientListByGBK();
|
||||
followUpList();
|
||||
});
|
||||
|
||||
// 加载消息列表
|
||||
const loadMessageList = () => {
|
||||
// 这里可以调用API获取消息列表
|
||||
console.log('加载患者消息列表');
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -446,13 +551,32 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
padding: 100rpx 30rpx;
|
||||
|
||||
.empty-text {
|
||||
margin-top: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.empty-subtext {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.debug-actions {
|
||||
margin-top: 30rpx;
|
||||
|
||||
.debug-btn {
|
||||
background-color: #8B2316;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
padding: 16rpx 32rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,6 +634,7 @@
|
||||
|
||||
// 患者列表样式
|
||||
.patient-list {
|
||||
|
||||
height:calc(100vh - 265rpx);
|
||||
|
||||
display: flex;
|
||||
@@ -576,6 +701,11 @@
|
||||
flex: 1;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
.new-patient-count {
|
||||
color: red;
|
||||
font-size: 32rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,7 +800,8 @@
|
||||
|
||||
.patient-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-end;
|
||||
flex-direction: column;
|
||||
|
||||
.follow-date {
|
||||
font-size: 24rpx;
|
||||
|
||||
Reference in New Issue
Block a user