hn-hlw-pc/src/views/hlw-hospital/components/history-conversation-list.vue
2026-10-21 10:55:45 +08:00

339 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="conversation-list">
<el-scrollbar ref="scrollbarRef" class="scrollbar-container" @scroll="handleScroll">
<div class="user-list" @click="()=>console.log(userList)">
<div v-for="user in userList" :key="user._id" class="user-item" :class="{ active: activeUserId === user._id }" @click="handleSelectUser(user)">
<div class="user-info">
<div class="primary-row">
<div v-if="user.consultType === 'onlineMedicinePurchase'" class="purchase-tag mr-2">在线配药</div>
<div v-if="user.consultType === 'wineConsult'" class="purchase-tag mr-2">中药饮片</div>
<div class="w-0 flex-grow user-name mr-2">{{ user.name }}/{{ user.sex }}/{{ user.age }}</div>
<div class="status flex-shrink-0" :style="'color:' + user.statusColor">{{ user.status }}</div>
</div>
<div class="secondary-row">
<span class="message-preview"></span>
<span class="time">{{ formatTime(user.createTime) }}</span>
</div>
</div>
</div>
<div v-if="loading" class="loading-more">
<el-spinner type="primary" />
<span>加载中...</span>
</div>
<div v-if="noMoreData" class="no-more-data">没有更多数据了</div>
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, onMounted, computed, nextTick, inject, watch } from "vue";
import { getConsultOrder } from "@/api/hlw";
import { ElMessage } from "element-plus";
import dayjs from "dayjs";
const colorMap = {
pending: "red",
processing: "red",
cancelled: "#666",
completed: "#4cd964",
finished: "#4cd964",
};
const selectUser = inject("selectUser");
// 响应式状态
const userList = ref([]);
const page = ref(1);
const pageSize = ref(20);
const loading = ref(false);
const noMoreData = ref(false);
const searchKeyword = ref("");
const activeUserId = ref(null);
const scrollbarRef = ref(null);
const total = ref(0);
const fetchUserList = async (currentPage = 1, append = false) => {
if (loading.value) return;
const doctorCode = sessionStorage.getItem("doctorNo");
if (!doctorCode) {
userList.value = [];
total.value = 0;
noMoreData.value = true;
return;
}
loading.value = true;
try {
const res = await getConsultOrder({
page: currentPage,
pageSize: pageSize.value,
doctorCode,
mergeStatus: "已处理",
});
// 获取接口返回的总数
total.value = res.data.total;
const formattedData = res.data.data.map((item) => {
const { text, color } = getStatus(item);
return {
...item,
status: text,
statusColor: color,
};
});
// 如果是追加数据,则合并数据
if (append) {
userList.value = [...userList.value, ...formattedData];
} else {
userList.value = formattedData;
// 如果有数据,默认选中第一个用户
if (formattedData.length > 0) {
handleSelectUser(formattedData[0]);
}
}
// 判断是否还有更多数据
noMoreData.value = userList.value.length >= total.value;
return res;
} catch (error) {
console.error("获取会话列表失败:", error);
ElMessage.error("获取会话列表失败,请稍后重试");
} finally {
loading.value = false;
}
};
function getStatus(item) {
const { orderStatus, expireTime } = item;
const color = colorMap[orderStatus];
if (orderStatus === "pending") {
return {
text: "待处理",
color,
};
}
if (orderStatus === "processing") {
return {
text: "处理中",
color,
};
}
if (orderStatus === "cancelled") {
return {
text: "已取消",
color,
};
}
if (orderStatus === "completed") {
return {
text: "已完成",
color,
};
}
if (orderStatus === "finished") {
return {
text: "已结束",
color,
};
}
return {};
}
// 处理滚动事件,实现下拉加载更多
const handleScroll = (e) => {
if (!scrollbarRef.value) return;
const scrollWrap = scrollbarRef.value.wrapRef;
if (!scrollWrap) return;
const { scrollTop, scrollHeight, clientHeight } = scrollWrap;
if (scrollHeight - scrollTop - clientHeight < 10 && !loading.value && !noMoreData.value) {
loadMoreUsers();
}
};
// 加载更多用户
const loadMoreUsers = async () => {
if (loading.value || noMoreData.value) return;
// 增加页码
page.value += 1;
// 添加页码和true参数,表示追加数据
await fetchUserList(page.value, true);
};
// 格式化时间
const formatTime = (time) => {
const now = dayjs();
const messageTime = dayjs(time);
if (now.isSame(messageTime, "day")) {
return messageTime.format("HH:mm");
} else if (now.isSame(messageTime, "year")) {
return messageTime.format("MM-DD");
} else {
return messageTime.format("YYYY-MM-DD");
}
};
// 初始化加载数据
onMounted(async () => {
// 加载用户列表数据
await fetchUserList(1, false);
// 为确保 scrollbarRef 已被正确挂载,使用 nextTick
nextTick(() => {
// 初始化滚动监听
if (scrollbarRef.value && scrollbarRef.value.wrapRef) {
scrollbarRef.value.wrapRef.addEventListener("scroll", handleScroll);
}
});
});
// 新增处理用户点击的函数
const handleSelectUser = (user) => {
activeUserId.value = user._id;
selectUser(user);
};
// 添加监听器,当用户列表变化且没有选择用户时,自动选择第一个用户
watch(
userList,
(newList) => {
if (newList.length > 0 && !activeUserId.value) {
handleSelectUser(newList[0]);
}
},
{ immediate: true }
);
</script>
<style lang="scss" scoped>
/* 保持原有样式不变 */
.conversation-list {
display: flex;
flex-direction: column;
height: 100%;
border-right: 1px solid #ebeef5;
background-color: #f5f7fa;
}
.header {
padding: 15px;
border-bottom: 1px solid #ebeef5;
background-color: #fff;
h3 {
margin: 0 0 10px;
font-size: 16px;
font-weight: 600;
}
}
.search-box {
margin-bottom: 10px;
}
.scrollbar-container {
flex: 1;
overflow-x: hidden;
}
.user-list {
padding: 0;
}
.user-item {
display: flex;
align-items: center;
padding: 12px 15px;
cursor: pointer;
border-bottom: 1px solid #ebeef5;
background-color: #fff;
transition: background-color 0.2s;
&:hover {
background-color: #f5f7fa;
}
&.active {
background-color: #ecf5ff;
border-left: 3px solid #409eff; /* 添加左边框增强高亮效果 */
}
}
.avatar {
margin-right: 12px;
flex-shrink: 0;
}
.user-info {
flex: 1;
min-width: 0; // 确保可以正确截断文本
}
.primary-row {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.user-name {
font-weight: 500;
font-size: 14px;
color: #303133;
}
.time {
font-size: 12px;
color: #909399;
}
.secondary-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.message-preview {
font-size: 13px;
color: #999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 90%;
}
.badge {
background-color: #f56c6c;
color: #fff;
font-size: 12px;
border-radius: 10px;
padding: 0 6px;
min-width: 16px;
height: 16px;
line-height: 16px;
text-align: center;
}
.loading-more {
display: flex;
align-items: center;
justify-content: center;
padding: 15px 0;
color: #909399;
font-size: 14px;
.el-spinner {
margin-right: 5px;
}
}
.no-more-data {
text-align: center;
padding: 15px 0;
color: #909399;
font-size: 14px;
}
.status {
color: #67c23a;
font-size: 14px;
padding: 2px 6px;
border-radius: 2px;
}
.purchase-tag{
display: inline-block;
padding: 2px 6px;
border-radius: 4px;
background: #b8956a;
color: white;
font-size: 12px;
}
</style>