Browse Source

优化用户打开和查看消息

xiaochan 7 months ago
parent
commit
af40120a27

+ 22 - 15
src/api/messages/index.js

@@ -1,32 +1,39 @@
-import request from '../../utils/request'
+import request from "../../utils/request";
 
 export function selectSystemMessages(date) {
   return request({
-    url: '/socketMessage/selectSystemMessages',
-    method: 'get',
+    url: "/socketMessage/selectSystemMessages",
+    method: "get",
     params: { date },
-  })
+  });
 }
 
 export function onPageRefresh(data) {
   return request({
-    url: '/socketMessage/onPageRefresh',
-    method: 'post',
+    url: "/socketMessage/onPageRefresh",
+    method: "post",
     data,
-  })
+  });
 }
 
 export function fetchAllSenders() {
   return request({
-    url: '/socketMessage/fetchAllSenders',
-    method: 'get',
-  })
+    url: "/socketMessage/fetchAllSenders",
+    showLoading: false,
+    method: "get",
+  });
 }
 
-export function fetchAllMessages(sender) {
+/**
+ *
+ * @param data
+ * @return Promise<any[]>
+ */
+export function fetchAllMessages(data) {
   return request({
-    url: '/socketMessage/fetchAllMessages',
-    method: 'get',
-    params: { sender },
-  })
+    url: "/socketMessage/fetchAllMessages",
+    method: "post",
+    showLoading: false,
+    data,
+  });
 }

+ 1 - 1
src/layout/fillet-layout/ToolInfoBar.vue

@@ -25,7 +25,7 @@
 
 <script setup lang="ts">
 import Download from '@/layout/function-list/Download.vue'
-import Message from '@/layout/function-list/Message.vue'
+import Message from '@/layout/function-list/message/Message.vue'
 import FullScreen from '@/layout/function-list/Fullscreen.vue'
 import UserInfo from "@/layout/function-list/UserInfo.vue";
 import ScrollNotifications from "../HeaderV2/ScrollNotifications.vue";

+ 0 - 334
src/layout/function-list/Message.vue

@@ -1,334 +0,0 @@
-<template>
-  <div title="消息" @click="showMessageLayer" style="height: 18px"
-       :class="unreadCount > 0 ? 'twinkle' : ''">
-    <el-badge :hidden="unreadCount <= 0" :value="unreadCount" :max="99" type="danger">
-      <el-icon>
-        <Message/>
-      </el-icon>
-    </el-badge>
-  </div>
-  <div v-if="messageLayerVisible" class="message-layer">
-    <div style="position: absolute; top: 8px; left: 520px">
-      <el-button circle type="info" plain icon="Close" @click="messageLayerVisible = false"></el-button>
-    </div>
-    <div class="sender" style="overflow-y: auto">
-      <div v-for="(item, index) in allSenders" :key="index" :style="activated(item.sender)"
-           @click="handleClickSender(item)">
-        <el-badge :value="item.unreadCount" :max="99" type="danger" :hidden="item.unreadCount <= 0">
-          <div class="sender-info">{{ item.senderName }}</div>
-        </el-badge>
-      </div>
-    </div>
-    <div class="content">
-      <p v-show="currentSender.senderName">{{ currentSender.senderName }}</p>
-      <div style="height: 400px; overflow-y: auto">
-        <div v-for="(itm, index) in allMessages" :key="index" class="message-body" :style="borderColor(itm.status)">
-          <div class="content-title-box" :style="readStatus(itm.status)">
-            <div class="content-title">
-              {{ itm.title }}
-            </div>
-            <div class="content-time">{{ itm.sendDatetime }}</div>
-          </div>
-          <div class="content-box" v-html="itm.content"></div>
-        </div>
-      </div>
-    </div>
-  </div>
-  <el-dialog
-      title="重要系统通知"
-      v-model="systemMessages.show"
-      :append-to-body="true"
-      :destroy-on-close="true"
-      center
-      :close-on-click-modal="false"
-      :close-on-press-escape="false"
-      :show-close="false"
-  >
-    <div class="system-message-time">{{ systemMessages.list[systemMessages.current].sendDatetime }}</div>
-    <pre class="system-message-content">{{ systemMessages.list[systemMessages.current].content }}</pre>
-    <div class="system-message-footer">
-      <el-button type="primary" icon="ArrowLeft" :disabled="systemMessages.current === 0" circle title="上一条"
-                 @click="messageIndexIncrease(-1)"></el-button>
-      <span class="system-message-count">{{ systemMessages.current + 1 }} / {{ systemMessages.list.length }}</span>
-      <el-button
-          type="primary"
-          icon="Arrow-right"
-          :disabled="systemMessages.current === systemMessages.list.length - 1"
-          circle
-          title="下一条"
-          @click="messageIndexIncrease(1)"
-      ></el-button>
-    </div>
-    <div style="width: 100%; text-align: right; margin-top: -30px">
-      <el-button icon="Close" type="danger" :disabled="systemMessages.current !== systemMessages.list.length - 1"
-                 @click="systemMessages.show = false">关闭
-      </el-button>
-    </div>
-  </el-dialog>
-</template>
-
-<script>
-import {computed, defineComponent, onMounted, ref, reactive} from 'vue'
-import {onPageRefresh, fetchAllSenders, fetchAllMessages} from '../../api/messages'
-import {useSystemStore} from "@/pinia/system-store";
-
-export default defineComponent({
-  name: 'message',
-  setup() {
-    const systemStore = useSystemStore()
-    const unreadCount = computed(() => {
-      return systemStore.unreadMessageCount
-    })
-    const systemMessages = reactive({
-      show: false,
-      list: [],
-      current: 0,
-    })
-    const messageIndexIncrease = (val) => {
-      systemMessages.current += val
-      if (val === 1) {
-        if (pushedMessageIds.value.indexOf(systemMessages.list[systemMessages.current].id) === -1) {
-          systemStore.pushSystemMessage(systemMessages.list[systemMessages.current].id)
-        }
-      }
-    }
-    const pushedMessageIds = ref([])
-
-    const currentSender = ref({})
-    const activated = (sender) => {
-      return {
-        background: currentSender.value.sender === sender ? '#0b85ff' : '',
-        color: currentSender.value.sender === sender ? 'white' : '',
-        fontWeight: currentSender.value.sender === sender ? 'bold' : '',
-        borderRadius: '4px',
-      }
-    }
-    const readStatus = (status) => {
-      return {
-        background: status === 0 ? 'rgba(233, 158, 158, 0.548)' : 'rgba(198, 231, 148, 0.452)',
-      }
-    }
-    const borderColor = (status) => {
-      return {
-        borderColor: status === 0 ? 'red' : 'green',
-      }
-    }
-
-    const allSenders = ref([])
-    const allMessages = ref([])
-    const messageLayerVisible = ref(false)
-    const showMessageLayer = () => {
-      if (!messageLayerVisible.value) {
-        fetchAllSenders().then((res) => {
-          allSenders.value = res
-          messageLayerVisible.value = true
-          handleClickSender(res[0])
-        })
-      } else {
-        messageLayerVisible.value = false
-      }
-    }
-
-    const handleClickSender = (messageIndex) => {
-      currentSender.value = messageIndex
-      fetchAllMessages(messageIndex.sender).then((res) => {
-        allMessages.value = res
-        systemStore.minusUnreadMessageCount(messageIndex.unreadCount)
-        messageIndex.unreadCount = 0
-      })
-    }
-
-    onMounted(() => {
-      pushedMessageIds.value = systemStore.systemMessages
-      onPageRefresh(systemStore.getSystemMessages).then((res) => {
-        systemStore.setUnreadMessageCount(res.unreadCount)
-        if (res.systemMessage.length > 0) {
-          systemMessages.list = res.systemMessage
-          systemMessages.current = 0
-          systemMessages.show = true
-          if (pushedMessageIds.value.indexOf(systemMessages.list[0].id) === -1) {
-            pushedMessageIds.value.push(systemMessages.list[0].id)
-            systemStore.pushSystemMessage(systemMessages.list[0].id)
-          }
-        }
-      })
-    })
-
-    return {
-      allSenders,
-      allMessages,
-      unreadCount,
-      currentSender,
-      systemMessages,
-      messageLayerVisible,
-      activated,
-      readStatus,
-      borderColor,
-      messageIndexIncrease,
-      showMessageLayer,
-      handleClickSender,
-    }
-  },
-})
-</script>
-
-<style lang="scss" scoped>
-
-@keyframes fade {
-  from {
-    opacity: 1.0;
-  }
-  50% {
-    opacity: 0;
-  }
-  to {
-    opacity: 1.0;
-  }
-}
-
-@-webkit-keyframes fade {
-  from {
-    opacity: 1.0;
-  }
-  50% {
-    opacity: 0;
-  }
-  to {
-    opacity: 1.0;
-  }
-}
-
-.twinkle {
-  animation: fade 600ms infinite;
-  -webkit-animation: fade 600ms infinite;
-}
-
-i {
-  font-size: 18px !important;
-  cursor: pointer;
-  font-size: 18px;
-
-  &:focus {
-    outline: none;
-  }
-}
-
-.message-layer {
-  display: flex;
-  position: absolute;
-  top: 60px;
-  right: 100px;
-  width: 560px;
-  height: 460px;
-  border: 1px solid gray;
-  box-shadow: 2px 3px 10px 1px gray;
-  background: white;
-  z-index: 1000;
-
-  .sender {
-    width: 160px;
-    border-right: 1px solid lightgray;
-
-    > div {
-      height: 32px;
-      line-height: 32px;
-      padding: 0 8px;
-      margin: 8px;
-      border: 1px solid lightgray;
-
-      &:hover {
-        cursor: pointer;
-        background: #409eff;
-        color: white;
-        font-weight: bold;
-      }
-    }
-  }
-
-  .content {
-    width: 400px;
-    padding: 8px;
-
-    > p {
-      margin-top: 8px;
-      font-size: 15px;
-      font-weight: bold;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-      overflow: hidden;
-    }
-
-    > div {
-      margin-bottom: 16px;
-      border-radius: 4px;
-      border: 2px solid rgb(53, 131, 221);
-    }
-  }
-}
-
-.sender-info {
-  width: 106px;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  overflow: hidden;
-}
-
-.message-body {
-  margin: 8px;
-  border: 1px dashed;
-  border-radius: 4px;
-}
-
-.content-title-box {
-  display: flex;
-  height: 26px;
-  line-height: 26px;
-  padding: 0 4px;
-  font-weight: bold;
-  border-bottom: 1px dashed lightgray;
-}
-
-.content-title {
-  width: 260px;
-  padding-right: 10px;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  overflow: hidden;
-}
-
-.content-time {
-  font-size: 12px;
-  width: 130px;
-}
-
-.content-box {
-  padding: 4px;
-  margin-bottom: 12px;
-  background: rgb(248, 247, 247);
-}
-
-.system-message-time {
-  font-size: 13px;
-  color: gray;
-}
-
-.system-message-content {
-  margin-top: 16px;
-  font-size: 16px;
-  font-weight: bold;
-  color: #303133;
-  white-space: pre-wrap;
-}
-
-.system-message-footer {
-  margin-top: 20px;
-  width: 100%;
-  text-align: center;
-
-  > span {
-    font-size: 12px;
-    color: gray;
-    margin: 0 8px;
-  }
-}
-</style>

+ 281 - 0
src/layout/function-list/message/Message.vue

@@ -0,0 +1,281 @@
+<template>
+  <div
+    title="消息"
+    @click="showMessageLayer"
+    style="height: 18px"
+    :class="unreadCount > 0 ? 'twinkle' : ''"
+  >
+    <el-badge
+      :hidden="unreadCount <= 0"
+      :value="unreadCount"
+      :max="99"
+      type="danger"
+    >
+      <el-icon>
+        <Message />
+      </el-icon>
+    </el-badge>
+  </div>
+  <MessageDialog v-model="messageLayerVisible" />
+  <el-dialog
+    title="重要系统通知"
+    v-model="systemMessages.show"
+    :append-to-body="true"
+    :destroy-on-close="true"
+    center
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :show-close="false"
+  >
+    <div class="system-message-time">
+      {{ systemMessages.list[systemMessages.current].sendDatetime }}
+    </div>
+    <pre class="system-message-content">{{
+      systemMessages.list[systemMessages.current].content
+    }}</pre>
+    <div class="system-message-footer">
+      <el-button
+        type="primary"
+        icon="ArrowLeft"
+        :disabled="systemMessages.current === 0"
+        circle
+        title="上一条"
+        @click="messageIndexIncrease(-1)"
+      ></el-button>
+      <span class="system-message-count"
+        >{{ systemMessages.current + 1 }} /
+        {{ systemMessages.list.length }}</span
+      >
+      <el-button
+        type="primary"
+        icon="Arrow-right"
+        :disabled="systemMessages.current === systemMessages.list.length - 1"
+        circle
+        title="下一条"
+        @click="messageIndexIncrease(1)"
+      ></el-button>
+    </div>
+    <div style="width: 100%; text-align: right; margin-top: -30px">
+      <el-button
+        icon="Close"
+        type="danger"
+        :disabled="systemMessages.current !== systemMessages.list.length - 1"
+        @click="systemMessages.show = false"
+        >关闭
+      </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script setup>
+import { computed, onMounted, ref, reactive } from "vue";
+import { onPageRefresh } from "@/api/messages";
+import { useSystemStore } from "@/pinia/system-store";
+import MessageDialog from "@/layout/function-list/message/MessageDialog.vue";
+
+const systemStore = useSystemStore();
+const unreadCount = computed(() => {
+  return systemStore.unreadMessageCount;
+});
+const systemMessages = reactive({
+  show: false,
+  list: [],
+  current: 0,
+});
+const messageIndexIncrease = val => {
+  systemMessages.current += val;
+  if (val === 1) {
+    if (
+      pushedMessageIds.value.indexOf(
+        systemMessages.list[systemMessages.current].id
+      ) === -1
+    ) {
+      systemStore.pushSystemMessage(
+        systemMessages.list[systemMessages.current].id
+      );
+    }
+  }
+};
+const pushedMessageIds = ref([]);
+
+const messageLayerVisible = ref(false);
+const showMessageLayer = () => {
+  messageLayerVisible.value = true;
+};
+
+onMounted(() => {
+  pushedMessageIds.value = systemStore.systemMessages;
+  onPageRefresh(systemStore.getSystemMessages).then(res => {
+    systemStore.setUnreadMessageCount(res.unreadCount);
+    if (res.systemMessage.length > 0) {
+      systemMessages.list = res.systemMessage;
+      systemMessages.current = 0;
+      systemMessages.show = true;
+      if (pushedMessageIds.value.indexOf(systemMessages.list[0].id) === -1) {
+        pushedMessageIds.value.push(systemMessages.list[0].id);
+        systemStore.pushSystemMessage(systemMessages.list[0].id);
+      }
+    }
+  });
+});
+</script>
+
+<style lang="scss" scoped>
+@keyframes fade {
+  from {
+    opacity: 1;
+  }
+  50% {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+
+@-webkit-keyframes fade {
+  from {
+    opacity: 1;
+  }
+  50% {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+
+.twinkle {
+  animation: fade 600ms infinite;
+  -webkit-animation: fade 600ms infinite;
+}
+
+i {
+  font-size: 18px !important;
+  cursor: pointer;
+  font-size: 18px;
+
+  &:focus {
+    outline: none;
+  }
+}
+
+.message-layer {
+  display: flex;
+  position: absolute;
+  top: 60px;
+  right: 100px;
+  width: 560px;
+  height: 460px;
+  border: 1px solid gray;
+  box-shadow: 2px 3px 10px 1px gray;
+  background: white;
+  z-index: 1000;
+
+  .sender {
+    width: 160px;
+    border-right: 1px solid lightgray;
+
+    > div {
+      height: 32px;
+      line-height: 32px;
+      padding: 0 8px;
+      margin: 8px;
+      border: 1px solid lightgray;
+
+      &:hover {
+        cursor: pointer;
+        background: #409eff;
+        color: white;
+        font-weight: bold;
+      }
+    }
+  }
+
+  .content {
+    width: 400px;
+    padding: 8px;
+
+    > p {
+      margin-top: 8px;
+      font-size: 15px;
+      font-weight: bold;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      overflow: hidden;
+    }
+
+    > div {
+      margin-bottom: 16px;
+      border-radius: 4px;
+      border: 2px solid rgb(53, 131, 221);
+    }
+  }
+}
+
+.sender-info {
+  width: 106px;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  overflow: hidden;
+}
+
+.message-body {
+  margin: 8px;
+  border: 1px dashed;
+  border-radius: 4px;
+}
+
+.content-title-box {
+  display: flex;
+  height: 26px;
+  line-height: 26px;
+  padding: 0 4px;
+  font-weight: bold;
+  border-bottom: 1px dashed lightgray;
+}
+
+.content-title {
+  width: 260px;
+  padding-right: 10px;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  overflow: hidden;
+}
+
+.content-time {
+  font-size: 12px;
+  width: 130px;
+}
+
+.content-box {
+  padding: 4px;
+  margin-bottom: 12px;
+  background: rgb(248, 247, 247);
+}
+
+.system-message-time {
+  font-size: 13px;
+  color: gray;
+}
+
+.system-message-content {
+  margin-top: 16px;
+  font-size: 16px;
+  font-weight: bold;
+  color: #303133;
+  white-space: pre-wrap;
+}
+
+.system-message-footer {
+  margin-top: 20px;
+  width: 100%;
+  text-align: center;
+
+  > span {
+    font-size: 12px;
+    color: gray;
+    margin: 0 8px;
+  }
+}
+</style>

+ 310 - 0
src/layout/function-list/message/MessageDialog.vue

@@ -0,0 +1,310 @@
+<script setup lang="ts">
+import { useVModel } from "@vueuse/core";
+import { fetchAllMessages, fetchAllSenders } from "@/api/messages";
+import { xcMessage } from "@/utils/xiaochan-element-plus";
+import { useSystemStore } from "@/pinia/system-store";
+
+type Data = { sender: string; senderName: string; unreadCount: number };
+
+const props = defineProps<{
+  modelValue: boolean;
+}>();
+
+type CacheData = {
+  sender: string;
+  data: any[];
+  currentPage: number;
+  reachingTheMax: number | null;
+  senderName: string;
+};
+
+const emits = defineEmits(["update:modelValue"]);
+const modelValue = useVModel(props, "modelValue", emits);
+const loading = ref(false);
+const mainLoading = ref(false);
+const currentInfo = ref<CacheData>({
+  sender: "",
+  data: [],
+  currentPage: 0,
+  reachingTheMax: null,
+  senderName: "",
+});
+const allSenders = ref<Data[]>([]);
+const systemStore = useSystemStore();
+
+const cacheData: {
+  [key: string]: CacheData;
+} = {};
+
+async function handleClick(item: Data) {
+  let cache = cacheData[item.sender];
+
+  if (!cache) {
+    cache = {
+      sender: item.sender,
+      data: [],
+      currentPage: 1,
+      reachingTheMax: null,
+      senderName: item.senderName,
+    };
+    mainLoading.value = true;
+
+    await fetchAllMessages({ ...cache, updateReadStatus: true }).then(res => {
+      if (res.length > 0) {
+        // @ts-ignore
+        cache.data.push(...res);
+        cacheData[item.sender] = cache;
+        systemStore.minusUnreadMessageCount(item.unreadCount);
+        item.unreadCount = 0;
+      } else {
+        cache.reachingTheMax = cache.currentPage;
+      }
+    });
+  }
+  mainLoading.value = false;
+  currentInfo.value = cache;
+}
+
+const borderColor = status => {
+  return {
+    borderColor: status === 0 ? "red" : "green",
+  };
+};
+
+const activated = (sender: string) => {
+  const has = currentInfo.value.sender === sender;
+  return {
+    background: has ? "#0b85ff" : "",
+    color: has ? "white" : "",
+    fontWeight: has ? "bold" : "",
+    borderRadius: "4px",
+  };
+};
+
+const readStatus = status => {
+  return {
+    background:
+      status === 0
+        ? "rgba(233, 158, 158, 0.548)"
+        : "rgba(198, 231, 148, 0.452)",
+  };
+};
+
+async function loadMore() {
+  const cache = cacheData[currentInfo.value.sender];
+  if (!cache) {
+    xcMessage.error("没有更多的数据可以加载了");
+    return;
+  }
+
+  if (cache.reachingTheMax) {
+    xcMessage.error("没有更多的数据可以加载了");
+    return;
+  }
+
+  cache.currentPage++;
+
+  await fetchAllMessages({ ...cache, updateReadStatus: false }).then(res => {
+    if (res.length > 0) {
+      // @ts-ignore
+      cache.data.push(...res);
+      cacheData[currentInfo.value.sender] = cache;
+    } else {
+      cache.reachingTheMax = cache.currentPage;
+    }
+  });
+  currentInfo.value = cache;
+  console.log(currentInfo.value);
+}
+
+function opended() {
+  loading.value = true;
+  fetchAllSenders().then(res => {
+    allSenders.value = res;
+    loading.value = false;
+  });
+}
+</script>
+
+<template>
+  <el-dialog
+    v-model="modelValue"
+    draggable
+    width="80vw"
+    title="消息"
+    class="system-message-dialog"
+    append-to-body
+    destroy-on-close
+    @opened="opended"
+  >
+    <el-container class="system-message-dialog__content">
+      <el-aside v-loading="loading">
+        <el-scrollbar>
+          <div
+            v-for="item in allSenders"
+            class="system-message-dialog__badge"
+            @click="handleClick(item)"
+            :style="activated(item.sender)"
+            :key="item.sender"
+          >
+            <div class="system-message-dialog__user-name">
+              {{ item.senderName }}
+            </div>
+            <div
+              class="system-message-dialog__count"
+              v-if="item.unreadCount > 0"
+            >
+              <div>
+                {{ item.unreadCount > 99 ? "99+" : item.unreadCount }}
+              </div>
+            </div>
+          </div>
+        </el-scrollbar>
+      </el-aside>
+      <el-main v-loading="mainLoading">
+        <div class="layout_container" style="padding: 5px 0">
+          <header class="system-message-dialog--user-name">
+            {{ currentInfo.senderName }}
+          </header>
+          <div class="layout_main">
+            <el-scrollbar>
+              <div
+                v-for="(itm, index) in currentInfo.data"
+                :key="`${currentInfo.sender}-${index}`"
+                class="message-body"
+                :style="borderColor(itm.status)"
+              >
+                <div class="content-title-box" :style="readStatus(itm.status)">
+                  <div class="content-title">
+                    {{ itm.title }}
+                  </div>
+                  <div class="content-time">{{ itm.sendDatetime }}</div>
+                </div>
+                <div class="content-box" v-html="itm.content"></div>
+              </div>
+              <div
+                v-if="currentInfo.data.length > 0"
+                style="text-align: center; margin: 5px 0"
+              >
+                <el-button
+                  text
+                  v-el-btn="loadMore"
+                  icon="Loading"
+                  type="primary"
+                  >加载更多
+                </el-button>
+              </div>
+            </el-scrollbar>
+          </div>
+        </div>
+      </el-main>
+    </el-container>
+  </el-dialog>
+</template>
+
+<style lang="scss">
+.system-message-dialog {
+  padding: 10px 0 0;
+
+  .el-aside {
+    width: 220px;
+    border-right: 1px solid var(--el-border-color);
+  }
+
+  .el-dialog__body {
+    border: 1px solid var(--el-border-color);
+  }
+
+  .system-message-dialog__content {
+    height: 50vh;
+    width: 100%;
+  }
+
+  .system-message-dialog__tag {
+    width: 100%;
+    padding: 5px;
+  }
+
+  .el-badge {
+    width: 100%;
+  }
+
+  .system-message-dialog__badge {
+    line-height: 30px;
+    display: flex;
+    border-radius: 5px;
+    padding: 5px;
+    cursor: pointer;
+    user-select: none;
+
+    &:hover {
+      background-color: var(--el-border-color);
+    }
+
+    .system-message-dialog__user-name {
+      width: 80%;
+    }
+
+    .system-message-dialog__count {
+      flex: 1;
+      display: inline-flex;
+      justify-content: end;
+      align-items: center;
+
+      > div {
+        padding: 0 6px;
+        height: 18px;
+        align-items: center;
+        display: inline-flex;
+        justify-content: center;
+        border-radius: 10px;
+        background-color: var(--el-color-danger);
+        text-align: center;
+        font-size: 12px;
+        color: white;
+        white-space: nowrap;
+      }
+    }
+  }
+
+  .message-body {
+    margin: 8px;
+    border: 1px dashed;
+    border-radius: 4px;
+  }
+
+  .content-title-box {
+    display: flex;
+    height: 26px;
+    line-height: 26px;
+    padding: 0 4px;
+    font-weight: bold;
+    border-bottom: 1px dashed lightgray;
+  }
+
+  .content-title {
+    width: 260px;
+    padding-right: 10px;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    overflow: hidden;
+  }
+
+  .content-time {
+    font-size: 12px;
+    width: 130px;
+  }
+
+  .content-box {
+    padding: 4px;
+    margin-bottom: 12px;
+    background: rgb(248, 247, 247);
+  }
+
+  .system-message-dialog--user-name {
+    text-align: center;
+    font-size: 14px;
+    font-weight: bold;
+  }
+}
+</style>

+ 3 - 3
src/main.js

@@ -14,12 +14,9 @@ import DataVVue3 from "@kjgl77/datav-vue3";
 import VXETable from "vxe-table";
 import "vxe-table/lib/style.css";
 import print from "vue3-print-nb";
-import VElBtn from "@/directives/v-el-btn";
-import VTitle from "@/directives/v-title";
 import "driver.js/dist/driver.css";
 import DomZIndex from "dom-zindex";
 import initVxeConfig from "@/utils/xe-utils-enhance/vxe-formatter";
-import VWaves from "@/directives/v-waves";
 import piniaInstall from "@/pinia/pinia-install";
 import VxeUIPluginRenderChart from "@vxe-ui/plugin-render-chart";
 import "@vxe-ui/plugin-render-chart/dist/style.css";
@@ -29,6 +26,9 @@ import VxeUIPluginExportXLSX from "@vxe-ui/plugin-export-xlsx";
 import ExcelJS from "exceljs";
 import "@imengyu/vue3-context-menu/lib/vue3-context-menu.css";
 import ContextMenu from "@imengyu/vue3-context-menu";
+import VTitle from "./directives/v-title";
+import VWaves from "./directives/v-waves";
+import VElBtn from "./directives/v-el-btn";
 
 DomZIndex.getNext = () => {
   return useZIndex().nextZIndex();