123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- <template>
- <page-layer>
- <template #main>
- <div style="display: flex">
- <!-- 左边部分 -->
- <div class="left-pane">
- <div class="divider-line">
- <div class="divider-text">
- <div class="avatar-box__inner">
- <el-avatar :size="80" :src="userInfo.avatar" @error="errorHandler">
- <img :src="makeTextPortrait()"/>
- </el-avatar>
- </div>
- </div>
- <div class="psninfo-box">
- {{ userInfo.name }} {{ userInfo.deptName }}
- <MyClock :show-logo="false" size="small"/>
- </div>
- </div>
- <div style="display: flex; flex-wrap: wrap; height: calc(100vh - 200px); overflow-y: auto">
- <Inpatient v-for="(itm, index) in briefs" :key="index" :brief="itm"/>
- </div>
- </div>
- <!-- 右下角消息弹窗 -->
- <div class="message-popup">
- <el-button
- class="popup-trigger"
- icon="Message"
- type="primary"
- circle
- @click="isPopupShow = !isPopupShow"
- ></el-button>
- <div class="popup-content" v-if="isPopupShow">
- <div class="popup-header">
- <span class="header-title">系统消息</span>
- <el-button
- class="close-btn"
- icon="Close"
- type="text"
- @click="isPopupShow = false"
- ></el-button>
- </div>
- <div class="check-more" @click="fetchMoreMessages" :class="{ disabled: loading }">
- 查看更多
- <el-loading v-if="loading" size="small" />
- <span v-if="noMore && !loading" class="no-more-text">没有更多消息</span>
- </div>
- <div class="message-list">
- <el-timeline v-for="item in messages" :key="item.id">
- <el-timeline-item :timestamp="item.simpledate" placement="top" icon="Warning" color="orange">
- <el-card>
- <div style="margin-bottom: 12px; font-size: 16px; font-weight: bold">{{ item.title }}</div>
- <div v-html="item.content"></div>
- </el-card>
- </el-timeline-item>
- </el-timeline>
- <div v-if="messages.length === 0 && !loading" class="empty-message">
- 暂无消息
- </div>
- <div v-if="loading && messages.length === 0" class="loading-message">
- <el-loading size="small" />
- <span>加载中...</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- </page-layer>
- </template>
- <script setup>
- import {onActivated, onMounted, ref} from 'vue'
- import {selectSystemMessages} from '../../api/messages/index'
- import {formatDate} from '@/utils/date'
- import {genTextPortrait} from '@/utils/portrait'
- import {isInpatientStaff} from '@/utils/permission'
- import {selectInpatientBriefs} from '../../api/dashboard/index'
- import MyClock from '@/components/MyClock.vue'
- import Inpatient from '@/components/dashboard/Inpatient.vue'
- import PageLayer from "@/layout/PageLayer";
- import {useUserStore} from "@/pinia/user-store";
- const messages = ref([])
- const loading = ref(false)
- const noMore = ref(false) // 仅作为UI提示,不阻止查询
- // 确保每次点击都触发查询
- const fetchMoreMessages = () => {
- if (loading.value) return; // 仅在加载中时阻止重复点击
- loading.value = true;
- noMore.value = false; // 每次查询前重置"没有更多"状态
- let lastdate = 'latest'
- if (messages.value.length > 0) {
- // 确保日期格式正确,与后端要求一致
- lastdate = formatDate(messages.value[0].simpledate, 'YYYY-MM-DD HH:mm:ss');
- }
- selectSystemMessages(lastdate)
- .then((res) => {
- if (res.length > 0) {
- // 新消息添加到列表前面
- messages.value.unshift(...res);
- noMore.value = false;
- } else {
- // 结果为空时仅更新UI提示,不阻止下次查询
- noMore.value = true;
- }
- })
- .catch((error) => {
- console.error('获取消息失败:', error);
- // 错误情况下也允许用户再次尝试
- })
- .finally(() => {
- loading.value = false;
- });
- }
- const userInfo = useUserStore().userInfo
- const errorHandler = () => {
- return true
- }
- const makeTextPortrait = () => {
- return genTextPortrait(userInfo.name)
- }
- onActivated(() => {
- loading.value = true;
- selectSystemMessages('latest')
- .then((res) => {
- messages.value = res;
- noMore.value = res.length === 0;
- })
- .finally(() => {
- loading.value = false;
- });
- })
- const briefs = ref([])
- onMounted(() => {
- if (isInpatientStaff()) {
- selectInpatientBriefs(userInfo.deptCode).then((list) => {
- briefs.value = list
- })
- }
- })
- const isPopupShow = ref(false)
- </script>
- <style lang="scss" scoped>
- .left-pane {
- margin-top: 20px;
- width: 100%;
- background-image: linear-gradient(#d0ddee, #64b6e6);
- height: 120px;
- border-radius: 6px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
- }
- .message-popup {
- position: fixed;
- bottom: 30px;
- right: 30px;
- z-index: 1000;
- .popup-trigger {
- width: 60px;
- height: 60px;
- font-size: 24px;
- box-shadow: 0 4px 12px rgba(16, 128, 240, 0.3);
- }
- .popup-content {
- width: 400px;
- max-height: 600px;
- background: #fff;
- border-radius: 8px;
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
- margin-bottom: 10px;
- overflow: hidden;
- .popup-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 12px 16px;
- border-bottom: 1px solid #e5e7eb;
- background: #f8fafc;
- .header-title {
- font-size: 16px;
- font-weight: 600;
- color: #1e293b;
- }
- .close-btn {
- color: #64748b;
- &:hover {
- color: #0f172a;
- }
- }
- }
- .check-more {
- width: 100%;
- text-align: right;
- padding: 8px 16px;
- color: #409eff;
- cursor: pointer;
- display: flex;
- justify-content: flex-end;
- align-items: center;
- gap: 8px;
- &:hover {
- color: #165dff;
- }
- &.disabled {
- cursor: not-allowed;
- opacity: 0.7;
- }
- .no-more-text {
- color: #94a3b8;
- font-size: 14px;
- }
- }
- .message-list {
- padding: 0 16px 16px;
- max-height: calc(600px - 50px);
- overflow-y: auto;
- }
- .empty-message {
- text-align: center;
- padding: 20px;
- color: #94a3b8;
- }
- .loading-message {
- text-align: center;
- padding: 20px;
- color: #94a3b8;
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 8px;
- }
- }
- }
- .avatar-box__inner {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 86px;
- height: 86px;
- border-radius: 43px;
- border-bottom: 3px solid #1080f0;
- z-index: 600;
- }
- .divider-line {
- display: block;
- height: 1px;
- width: 100%;
- margin: 70px 0 50px 0;
- background-color: #4297ec88;
- position: relative;
- }
- .divider-text {
- left: 12px;
- -webkit-transform: translateY(-55%);
- transform: translateY(-55%);
- position: absolute;
- font-weight: 500;
- color: black;
- font-size: 14px;
- }
- .psninfo-box {
- display: flex;
- left: 108px;
- -webkit-transform: translateY(-120%);
- transform: translateY(-120%);
- position: absolute;
- font-weight: 500;
- color: rgb(3, 72, 94);
- font-size: 20px;
- font-weight: bold;
- }
- </style>
|