510 lines
12 KiB
Vue
510 lines
12 KiB
Vue
<template>
|
||
<view class="page">
|
||
<!-- 顶部导航 -->
|
||
<navBar title="群发消息" />
|
||
|
||
<!-- 下拉刷新和上拉加载容器 -->
|
||
<scroll-view
|
||
class="scroll-container"
|
||
scroll-y
|
||
refresher-enabled
|
||
:refresher-triggered="refreshing"
|
||
@refresherrefresh="onRefresh"
|
||
@scrolltolower="onLoadMore"
|
||
:lower-threshold="100"
|
||
>
|
||
<!-- 卡片区域 -->
|
||
<view class="card-cell" v-if="list.length > 0" v-for="(item, index) in list" :key="item.uuid">
|
||
<view class="time-row">{{ item.msg_send_date }}</view>
|
||
<view class="card" >
|
||
|
||
<view class="card-body">
|
||
|
||
<view class="card-header">
|
||
<text class="label">{{ item.realname.split(',').length }}位患者:</text>
|
||
<view class="close" @click="delGroupSendMsg(item)">
|
||
<text>×</text>
|
||
</view>
|
||
</view>
|
||
<view class="line" >
|
||
{{ item.realname }}
|
||
</view>
|
||
<view class="line phone" v-if="item.msg_type==1">
|
||
{{ item.msg_content }}
|
||
</view>
|
||
<view class="line phone" v-if="item.msg_type==3" @click="onDetail(item)">
|
||
<view class="custom">
|
||
<view class="title">{{JSON.parse(item.msg_content).summary }}</view>
|
||
<view class="row">
|
||
<view class="left">{{ docUrl+JSON.parse(item.msg_content).path }}</view>
|
||
<view class="right">
|
||
<image :src="docUrl+JSON.parse(item.msg_content).imgPath" ></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="line phone" v-else-if="item.msg_type==4" @click="onDetail(item)">
|
||
<view class="custom">
|
||
<view class="title">{{JSON.parse(item.msg_content).name }}</view>
|
||
<view class="row">
|
||
<view class="left">{{ docUrl+JSON.parse(item.msg_content).path }}</view>
|
||
<view class="right">
|
||
<image :src="docUrl+JSON.parse(item.msg_content).imgpath" ></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="line phone" v-else-if="item.msg_type==5" @click="onDetail(item)">
|
||
<view class="custom">
|
||
<view class="title">{{JSON.parse(item.msg_content).topic }}</view>
|
||
<view class="row">
|
||
<view class="left">{{ docUrl+JSON.parse(item.msg_content).path }}</view>
|
||
<view class="right">
|
||
<image :src="JSON.parse(item.msg_content).imgPath" ></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="line phone" v-else-if="item.msg_type==6" @click="onDetail(item)">
|
||
<view class="custom">
|
||
<view class="title">{{JSON.parse(item.msg_content).topic }}</view>
|
||
<view class="row">
|
||
<view class="left">{{JSON.parse(item.msg_content).path }}</view>
|
||
<view class="right">
|
||
<image :src="JSON.parse(item.msg_content).imgPath" ></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="card-footer">
|
||
<view class="btn-outline" @click="onResend(item)">再发一条</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<view class="card" v-else>
|
||
<view class="card-header">
|
||
<text class="label">群发消息记录</text>
|
||
</view>
|
||
<view class="card-body">
|
||
<view class="line">暂无群发消息记录</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 加载状态 -->
|
||
<view class="loading-state" v-if="loading">
|
||
<text>加载中...</text>
|
||
</view>
|
||
|
||
<!-- 没有更多数据 -->
|
||
<view class="no-more" v-if="!hasMore && list.length > 0">
|
||
<text>没有更多数据了</text>
|
||
</view>
|
||
|
||
<!-- 占位滚动区域 -->
|
||
<view class="spacer" />
|
||
</scroll-view>
|
||
|
||
<!-- 底部按钮 -->
|
||
<view class="bottom-bar" @click="openModal">
|
||
<view class="btn-primary" >群发消息</view>
|
||
</view>
|
||
<!-- 弹窗与遮罩 -->
|
||
<view v-if="showModal" class="mask" @click="closeModal"></view>
|
||
<view v-if="showModal" class="center-modal">
|
||
<view class="modal-title">温馨提示</view>
|
||
<view class="modal-divider"></view>
|
||
<view class="modal-item" @click="onSelect('single')">
|
||
<text>单独选择</text>
|
||
</view>
|
||
<view class="modal-divider"></view>
|
||
<view class="modal-item" @click="onSelect('group')">
|
||
<text>分组选择</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted } from 'vue'
|
||
import navBar from '@/components/navBar/navBar.vue'
|
||
import api from '@/api/api.js'
|
||
import { onShow } from '@dcloudio/uni-app'
|
||
import docUrl from '@/utils/docUrl.js'
|
||
import navTo from '@/utils/navTo.js'
|
||
const currentTime = ref('')
|
||
const patientCount = ref(1)
|
||
const patientName = ref('测试')
|
||
const patientPhone = ref('155555555')
|
||
const showModal=ref(false);
|
||
const page=ref(1);
|
||
const list=ref([]);
|
||
const refreshing=ref(false);
|
||
const loading=ref(false);
|
||
const hasMore=ref(true);
|
||
const pad = (n) => (n < 10 ? `0${n}` : `${n}`)
|
||
|
||
// 格式化时间显示
|
||
const formatTime = (dateStr) => {
|
||
if (!dateStr) return ''
|
||
const date = new Date(dateStr)
|
||
const now = new Date()
|
||
const diff = now - date
|
||
|
||
// 如果是今天
|
||
if (diff < 24 * 60 * 60 * 1000 && date.getDate() === now.getDate()) {
|
||
return `${pad(date.getHours())}:${pad(date.getMinutes())}`
|
||
}
|
||
// 如果是昨天
|
||
else if (diff < 48 * 60 * 60 * 1000 && date.getDate() === now.getDate() - 1) {
|
||
return `昨天 ${pad(date.getHours())}:${pad(date.getMinutes())}`
|
||
}
|
||
// 其他情况显示完整日期
|
||
else {
|
||
return `${date.getMonth() + 1}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
|
||
}
|
||
}
|
||
|
||
// 加载数据
|
||
const listGroupSendMsg=async(isRefresh = false)=>{
|
||
if(loading.value) return;
|
||
|
||
loading.value = true;
|
||
|
||
try {
|
||
const res=await api.listGroupSendMsg({
|
||
page: page.value,
|
||
});
|
||
|
||
if(res.code==200){
|
||
const newList = res.data.list || [];
|
||
|
||
if(isRefresh) {
|
||
// 下拉刷新,替换数据
|
||
list.value = newList;
|
||
} else {
|
||
// 上拉加载,追加数据
|
||
list.value = [...list.value, ...newList];
|
||
}
|
||
|
||
// 判断是否还有更多数据
|
||
hasMore.value = newList.length >= 10; // 假设每页10条数据
|
||
|
||
// 如果不是刷新,页码+1
|
||
if(!isRefresh) {
|
||
page.value++;
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('加载数据失败:', error);
|
||
uni.showToast({ title: '加载失败', icon: 'none' });
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
// 下拉刷新
|
||
const onRefresh = async () => {
|
||
refreshing.value = true;
|
||
page.value = 1;
|
||
hasMore.value = true;
|
||
|
||
await listGroupSendMsg(true);
|
||
|
||
refreshing.value = false;
|
||
uni.showToast({ title: '刷新成功', icon: 'none' });
|
||
};
|
||
const onDetail = (item) => {
|
||
let path='';
|
||
if(item.msg_type==3){
|
||
path=docUrl+JSON.parse(item.msg_content).path;
|
||
}else if(item.msg_type==4){
|
||
path=docUrl+JSON.parse(item.msg_content).path;
|
||
}else if(item.msg_type==5){
|
||
path=JSON.parse(item.msg_content).path;
|
||
}else if(item.msg_type==6){
|
||
path=JSON.parse(item.msg_content).path;
|
||
}
|
||
navTo({
|
||
url: `/pages_app/webview/webview?url=${encodeURIComponent(path)}`,
|
||
})
|
||
}
|
||
// 上拉加载更多
|
||
const onLoadMore = async () => {
|
||
if(!hasMore.value || loading.value) return;
|
||
|
||
await listGroupSendMsg(false);
|
||
};
|
||
onMounted(() => {
|
||
|
||
})
|
||
onShow(() => {
|
||
listGroupSendMsg()
|
||
})
|
||
const onBack = () => {
|
||
uni.navigateBack()
|
||
}
|
||
const openModal = () => {
|
||
showModal.value = true;
|
||
};
|
||
|
||
const closeModal = () => {
|
||
showModal.value = false;
|
||
};
|
||
|
||
const onSelect = (type) => {
|
||
showModal.value = false;
|
||
if (type === 'single') {
|
||
navTo({
|
||
url: "/pages_app/selectPatient/selectPatient?from=chatMsg"
|
||
})
|
||
} else if (type === 'group') {
|
||
navTo({
|
||
url: '/pages_chat/patientGroup/patientGroup',
|
||
})
|
||
}
|
||
};
|
||
const delGroupSendMsg = (obj) => {
|
||
// 清空选择的患者(占位)
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定删除该群发消息吗?',
|
||
success: (res) => {
|
||
if(res.confirm){
|
||
api.delGroupSendMsg({
|
||
uuid: obj.uuid
|
||
}).then(res => {
|
||
if(res.code == 200){
|
||
uni.showToast({ title: '删除成功', icon: 'none' })
|
||
list.value = list.value.filter(item => obj.uuid != item.uuid)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
const onResend = (obj) => {
|
||
let arr=[];
|
||
let idArr=obj.patient_uuid.split(',');
|
||
obj.realname.split(',').forEach((item,index) => {
|
||
arr.push({
|
||
uuid: idArr[index],
|
||
realName: item,
|
||
})
|
||
})
|
||
uni.setStorageSync('selectedChatPatientsSingle', {
|
||
patients: arr
|
||
});
|
||
navTo({
|
||
url: `/pages_chat/groupSend/groupSend?from=chatMsg`
|
||
})
|
||
}
|
||
const onSendGroup = () => {
|
||
uni.showToast({ title: '已触发群发', icon: 'none' })
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
$page-bg: #f5f5f5;
|
||
$brand: #8B2316;
|
||
$brand-deep: #8B2316;
|
||
$primary: #00cbc0;
|
||
$red: #D32F2F;
|
||
.custom{
|
||
padding: 25rpx;
|
||
border-radius: 16rpx;
|
||
border: 2rpx solid #f0f0f0;
|
||
width:80%;
|
||
margin: 0 auto;
|
||
.title{
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
font-size: 32rpx;
|
||
}
|
||
.row{
|
||
margin-top: 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
.left{
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
word-break: break-all;
|
||
}
|
||
.right{
|
||
image{
|
||
width: 150rpx;
|
||
height: 150rpx;
|
||
margin-left: 20rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/* 遮罩与弹窗 */
|
||
.mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0,0,0,0.6);
|
||
z-index: 10;
|
||
}
|
||
|
||
.center-modal {
|
||
position: fixed;
|
||
left: 50%;
|
||
top: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 650rpx;
|
||
background: #ffffff;
|
||
border-radius: 16rpx;
|
||
z-index: 11;
|
||
overflow: hidden;
|
||
box-shadow: 0 10rpx 40rpx rgba(0,0,0,0.15);
|
||
}
|
||
|
||
.modal-title {
|
||
text-align: center;
|
||
font-size: 34rpx;
|
||
color: #8B2316;
|
||
padding: 28rpx 20rpx;
|
||
}
|
||
|
||
.modal-item {
|
||
padding: 36rpx 28rpx;
|
||
font-size: 30rpx;
|
||
color: #333333;
|
||
background: #ffffff;
|
||
}
|
||
|
||
.modal-divider {
|
||
height: 2rpx;
|
||
background: #eeeeee;
|
||
}
|
||
.page {
|
||
background: $page-bg;
|
||
min-height: 100vh;
|
||
position: relative;
|
||
}
|
||
|
||
.nav {
|
||
height: 88rpx;
|
||
padding: 0 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
background: #fff;
|
||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
|
||
.back { width: 80rpx; display: flex; align-items: center; }
|
||
.title { flex: 1; text-align: center; font-size: 34rpx; color: $red; font-weight: 600; }
|
||
.right { width: 80rpx; }
|
||
}
|
||
|
||
// 滚动容器样式
|
||
.scroll-container {
|
||
position: fixed;
|
||
top: 140rpx;
|
||
width:100%;
|
||
bottom: 107rpx;
|
||
|
||
}
|
||
|
||
.time-row {
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
padding: 32rpx 0;
|
||
color: #333;
|
||
}
|
||
|
||
// 加载状态样式
|
||
.loading-state {
|
||
text-align: center;
|
||
padding: 40rpx 0;
|
||
color: #999;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.no-more {
|
||
text-align: center;
|
||
padding: 40rpx 0;
|
||
color: #ccc;
|
||
font-size: 24rpx;
|
||
}
|
||
.card-cell{
|
||
display: flex;
|
||
flex-direction: column;
|
||
margin: 0 30rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
.card {
|
||
margin: 24rpx 0;
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.06);
|
||
overflow: hidden;
|
||
.card-header {
|
||
position: relative;
|
||
padding: 28rpx 28rpx 12rpx 28rpx;
|
||
.border { height: 2rpx; background: #eee; }
|
||
.label { font-size: 32rpx; color: #333; }
|
||
.close {
|
||
position: absolute;
|
||
right: -30rpx;
|
||
top: -36rpx;
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-bottom-left-radius: 100rpx;
|
||
background: #8B2316;
|
||
display: flex; align-items: center; justify-content: center;
|
||
text { color: #fff; font-size: 40rpx; font-weight: 500; }
|
||
}
|
||
}
|
||
.card-body {
|
||
padding: 20rpx 28rpx 8rpx 28rpx;
|
||
.line { font-size: 32rpx; color: #333; padding: 16rpx 0; }
|
||
.phone { font-size: 36rpx; }
|
||
}
|
||
.card-footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
padding: 16rpx 28rpx 28rpx 28rpx;
|
||
.btn-outline {
|
||
border: 2rpx solid $red;
|
||
color: $red;
|
||
padding: 10rpx 24rpx;
|
||
border-radius: 28rpx;
|
||
font-size: 28rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.spacer { height: 200rpx; }
|
||
|
||
.bottom-bar {
|
||
position: fixed;
|
||
left: 0; right: 0; bottom: 0;
|
||
background: #00cbc0;
|
||
height: 100rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
.btn-primary {
|
||
color: #fff;
|
||
font-size: 34rpx;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
</style>
|