浏览代码

首页修改聊天文件发送

“yueshang” 2 年之前
父节点
当前提交
4bb1cae278

+ 24 - 2
src/api/chat/msg.js

@@ -71,10 +71,32 @@ export function msgSend(data) {
       data
   })
 }
-export function msgRecord(data) {
+//获取聊天记录
+export function msgRecord(data,query) {
   return request({
     url: '/chat/msg/record/'+data,
+    method: 'get',
+    params: query
+  })
+}
+// 获取文件树,用于选择目录发送
+export function dirTree(data) {
+  return request({
+    url: '/biz/dir/dir-tree/'+data,
+    method: 'get'
+  })
+}
+// 获取文件树,用于选择文件发送
+export function fileTree(data) {
+  return request({
+    url: '/biz/dir/file-tree/'+data,
+    method: 'get'
+  })
+}
+//获取文件的详细信息,以便于在聊天中展示
+export function getConfigKeys(docId) {
+  return request({
+    url: '/biz/info/' + docId,
     method: 'get'
   })
 }
-

二进制
src/assets/images/file-img.png


+ 22 - 3
src/assets/styles/my-common.scss

@@ -46,7 +46,9 @@
         border-top-left-radius: 4px;
       }
       .right-container {
-        flex: 1;
+        // flex: 1;
+        height: 300px !important;
+        overflow: auto;
         border-bottom: 1px solid #c1cce3;
       }
       .right-footer {
@@ -148,16 +150,33 @@
   .message-container {
     display: flex;
     align-items: flex-start;
-    margin-bottom: 10px;
+    margin-bottom: 20px;
 
   }
   
   .message-left {
+    margin-right: 40%;   
     justify-content: flex-start;
+    .left-back{
+      background: #EBEFF6;
+    border-radius: 20px 20px 20px 0px;
+    padding: 8px 16px;
+    }
+
   }
   
   .message-right {
     // width: 80%;
-    margin-left: 100px;
+    margin-left: 40%;
     justify-content: flex-end;
+    .right-back{
+      padding: 8px 16px;
+      background: #2E6BC8;
+    border-radius: 20px 20px 0px 20px;
+    }
+  }
+  .time-text{
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
   }

+ 0 - 1
src/components/AddPerson/index.vue

@@ -103,7 +103,6 @@ const confirm=()=>{
 }
 onMounted(() => {
 });
-
 </script>
 <style lang="scss" scoped>
 :deep(.el-dialog__header) {

+ 131 - 0
src/components/FileTreeChoice/index.vue

@@ -0,0 +1,131 @@
+<template>
+  <el-dialog v-model="isOpen" append-to-body width="700">
+    <template #header>
+      <div class="my-header">
+        <div class="title">选择文件</div>
+      </div>
+    </template>
+    <div class="main-cont">
+      <div class="main-cont-left">
+        <el-tree-v2
+          ref="treeRef"
+          :data="treeData.data"
+          :show-checkbox="false"
+          :height="280"
+          :props="defaultProps"
+          @node-click="handleNodeClick"
+        >
+          <template #default="{ node }">
+            <span style="display: flex;align-items: center;">
+              <img :src="fileImg" alt="" style="width: 20px;height: 20px;margin-right: 5px;"/>
+              <!-- 放置图片 -->
+              <span>{{ node.label }}</span>
+              <!-- 显示节点标签 -->
+            </span>
+          </template>
+        </el-tree-v2>
+      </div>
+    </div>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="isOpen = false" class="cancel-button"
+          >取消</el-button
+        >
+        <el-button type="primary" @click="confirm" class="sure-button">
+          确认
+        </el-button>
+      </span>
+    </template>
+  </el-dialog>
+</template>
+  <script setup>
+import { reactive, ref, toRaw, toRefs, watch } from "vue";
+import { ElMessage } from "element-plus";
+import fileImg from "@/assets/images/file-img.png";
+import useUserStore from "@/store/modules/user";
+import { defineEmits } from "vue";
+const opent = ref(true);
+const props = defineProps({
+  openFile: {
+    type: Boolean,
+    default: false,
+  },
+  fileUserTreeData: {
+    type: Object,
+    default: () => {},
+  },
+});
+const defaultProps = {
+  children: "children",
+  label: "label",
+  value: "id",
+};
+const isOpen = ref(props.openFile);
+watch(
+  () => props.openFile,
+  (newValue) => {
+    isOpen.value = newValue;
+  }
+);
+
+const treeData = reactive({ data: [] });
+watchEffect(() => {
+  treeData.data[0]=props.fileUserTreeData
+  toRaw(treeData.data);
+});
+
+//树
+const clickData = ref({});
+const handleNodeClick = (data) => {
+  clickData.value = data;
+};
+
+//确定按钮
+  const emit = defineEmits(["fileChangeMsg"]);
+const confirm = () => {
+  const {disabled,label}=toRefs(clickData.value)
+  if(disabled.value){
+    return ElMessage({ message: '当前选中为目录,请重新选择文件', type: 'error' })
+  }
+    emit("fileChangeMsg",  clickData.value);
+    isOpen.value  = false
+};
+onMounted(() => {});
+</script>
+  <style lang="scss" scoped>
+:deep(.el-dialog__header) {
+  --el-dialog-bg-color: #0b4ab7 !important;
+}
+.my-header {
+  margin: -20px -36px -20px -20px;
+  .title {
+    background: #ebeff6;
+    padding: 15px;
+  }
+}
+
+.main-cont {
+  height: 348px;
+  border: 1px solid #c1cce3;
+  display: flex;
+
+  .main-cont-left,
+  .main-cont-right {
+    width: 99%;
+    height: 100%;
+  }
+  .main-cont-right {
+    border-left: 1px solid #c1cce3;
+  }
+}
+.w-50 {
+  width: 94%;
+  margin: 8px;
+}
+.cancel-button {
+  border: 1px solid #c1cce3;
+}
+.sure-button {
+  background-color: #2e6bc8;
+}
+</style>

+ 3 - 3
src/layout/indexCommon.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="common-layout">
     <el-container>
-      <el-header class="nav">
+      <el-header class="nav" style="position: sticky;top: 0;left: 0;width: 100%;z-index: 999">
         <div class="nav-top">
           <div>
             <img src="@/assets/images/logos.png" /><span>DOMINO'S File</span>
@@ -51,8 +51,8 @@
                 :class="$route.path==item.path ? 'acitve-img-style img-style' : 'img-style'
                 "
               >
-                <img :src="clickId == index ? item.beimgs : item.imgs" />
-                <div class="text-style" v-if="clickId != index">
+                <img :src="$route.path==item.path ? item.beimgs : item.imgs" />
+                <div class="text-style" v-if="$route.path!=item.path">
                   {{ item.label }}
                 </div>
               </div> </router-link

+ 5 - 3
src/store/modules/websocket.js

@@ -1,12 +1,13 @@
 // websoct.js
 import useUserStore from '@/store/modules/user'
 import {
-  msgSend,
+  msgSend
 } from "@/api/chat/msg";
 const useWebsoctStore = defineStore('websoct', {
   state: () => ({
     messages: [],
     socket: null,
+    messOne:{},
     newMessage: false
   }),
   actions: {
@@ -20,8 +21,9 @@ const useWebsoctStore = defineStore('websoct', {
       })
 
       this.socket.addEventListener("message", (event) => {
-        console.log('message', event)
-        const message = JSON.parse(JSON.stringify(event.data))
+        console.log('event发送消息', event)
+        const message=event.data!='连接成功'?JSON.parse(JSON.stringify(event.data)):''
+        this.messOne=event.data!='连接成功'?JSON.parse(event.data):{}
         this.messages.push(message)
 
       })

+ 116 - 36
src/views/liveChat/index.vue

@@ -4,8 +4,9 @@ export default {
 };
 </script>
 <script setup>
-import { ref, reactive, toRaw } from "vue";
+import { ref, reactive, toRaw, toRefs } from "vue";
 import useUserStore from "@/store/modules/user";
+import word from "@/assets/images/word.png";
 import chat from "@/assets/images/profile.jpg";
 import cebian from "@/assets/images/cebian.png";
 import send from "@/assets/images/send.png";
@@ -18,8 +19,12 @@ import {
   msgSend,
   msgRecord,
   delMsg,
+  dirTree,
+  fileTree,
+  getConfigKeys,
 } from "@/api/chat/msg";
 import Addperson from "@/components/AddPerson/index.vue"; //添加人员的弹框
+import FileTreeChoice from "@/components/FileTreeChoice/index.vue"; //选择文件发送的列表
 //websocket连接====
 import useWebsoctStore from "@/store/modules/websocket";
 import { ElMessage } from "element-plus";
@@ -30,6 +35,9 @@ const userIds = useUserStore();
 const height = ref(document.documentElement.clientHeight - 74 + "px;");
 const messageText = ref(""); //发送的内容
 const headerName = ref("");
+const total = ref(0);
+const sendId = ref(""); //选择发送的文件id
+const openFile = ref(false); //文件目录
 const chatRecords = reactive({ data: [] });
 const sendCont = reactive({
   //发送聊天内容数据组装
@@ -77,8 +85,31 @@ const getMsgList = async () => {
 };
 //获取用户的聊天记录
 const msgRecordEvent = async (toIdValue) => {
-  const resMsgData = await msgRecord(toIdValue);
+  const queryParams = {
+    pageNum: 1,
+    pageSize: 10,
+  };
+  const resMsgData = await msgRecord(toIdValue, queryParams);
   chatRecords.data = resMsgData.rows.reverse();
+  total.value = resMsgData.total;
+  console.log('sendId.value',sendId.value)
+  if (sendId.value) {
+    //转换文件名称
+    const res = await getConfigKeys(sendId.value);
+ 
+    chatRecords.data.forEach((i) => {
+      console.log('i.content', i.content,res.docId)
+      if (i.content == res.docId) {
+        console.log("res.docId======", res.docId);
+        i.content = res.fileName;
+        i.fileType = res.fileType;
+        i.dirId = res.dirId;
+        i.fileSize = res.fileSize;
+      }
+    });
+    sendId.value = "";
+  }
+
 };
 //点击左侧新建聊天
 const open = ref(false);
@@ -102,6 +133,7 @@ const clickPerson = (index, item) => {
     : item.toId == userIds.uid
     ? item.fromName
     : item.toName;
+  noMes.value = false;
   clickPersonIndex.value = index;
   msgRecordEvent(sendCont.data.toId);
 };
@@ -118,6 +150,7 @@ const delClick = (msgId) => {
       proxy.$modal.msgSuccess("删除成功");
     });
 };
+
 //树选中的人传过来的选中人的信息,push进入列表中
 const changeMsg = async (val) => {
   const resInfo = await userInfo(val.id);
@@ -141,50 +174,82 @@ const changeMsg = async (val) => {
   msgRecordEvent(sendCont.data.toId);
   headerName.value = resInfo.nickName;
 };
+
 //发送聊天
 const msgSendClick = () => {
-  const message = { content: messageText.value, msgType: "2",fileList: [],toId: sendCont.data.toId, };
-  // commonSendMsg(messageText.value, "2");
+  const message = {
+    content: messageText.value,
+    msgType: "2",
+    fileList: [],
+    toId: sendCont.data.toId,
+  }
   websoctStore.sendMessage(message);
   messageText.value = "";
 };
-//发送文件
-const openFile = ref(false);
-const sendFileClick = () => {
-  openFile.value = true;
+//发送文件确认按钮
+const fileChangeMsg = async (val) => {
+  const ids=toRefs(val)
+  const message = {
+    content: ids.value,
+    msgType: "1",
+    fileList: [],
+    toId: sendCont.data.toId,
+  };
+  sendId.value =ids.value;
+  websoctStore.sendMessage(message);
+  console.log('sendId.value',sendId.value)
 };
-//文件和信息共用的调用
-const commonSendMsg = async (cont, type) => {
-  sendCont.data.content = cont;
-  sendCont.data.msgType = type;
-  const mysendmsg = await msgSend(sendCont.data);
+//点击发送文件图标
+const fileUserTreeData = reactive({ data: {} });
+const sendFileClick = async () => {
+  const resDir = await fileTree(3);
+  fileUserTreeData.data = resDir;
+  toRaw(fileUserTreeData.data);
+  openFile.value = true;
 };
-// const confirmFile = () => {
-//   // commonSendMsg(messageText.value,"1")
-// };
-// // const handleFileUpdate = (value) => {
-// //   // 在这里处理子组件传递过来的文件
-// //   console.log(value, "valuevaluevalue"); // 打印子组件传递的数据
-// // };
-// 监听新消息通知
+//获取用户聊天记录
 const handleNewMessage = () => {
   if (websoctStore.newMessage) {
-    msgRecordEvent(sendCont.data.toId);
-    ElMessage.success("You have a new message");
+    msgRecordEvent(sendCont.data.toId); //获取用户的聊天记录
     websoctStore.newMessage = false; // 重置新消息标记
   }
 };
+watchEffect(() => {
+  console.log("first", websoctStore.messOne);
+  if (websoctStore.messOne?.fromId) {
+    msgRecordEvent(websoctStore.messOne.fromId);
+  }
+});
+// 滚动翻页========
+const noMes = ref(false);
+const handleScroll = (event) => {
+  // 在滚动到顶部时,加载上一页的聊天记录
+  const mainContainer = document.querySelector(".right-container");
+  if (event.deltaY < 0 && mainContainer.scrollTop <= 1) {
+    loadPreviousPage();
+  }
+};
+const loadPreviousPage = async () => {
+  const currentPageNum = Math.ceil(chatRecords.data.length / 10) + 1;
+  const queryParams = {
+    pageNum: currentPageNum,
+    pageSize: 10,
+  };
+  const resMsgData = await msgRecord(sendCont.data.toId, queryParams);
+  const previousPageData = resMsgData.rows.reverse();
+  if (currentPageNum * 10 >= resMsgData.total && !noMes.value) {
+    noMes.value = true;
+    return ElMessage("无更多聊天记录");
+  }
+  // 将加载的上一页聊天记录插入到 chatRecords.data 的前面
+  chatRecords.data = [...previousPageData, ...chatRecords.data];
+};
+// 滚动翻页========
 onMounted(() => {
   getMsgList();
   websoctStore.connect();
   setInterval(handleNewMessage, 1000); // 每秒钟检查是否有新消息
 });
-onMounted(() => {
-  try {
-    getMsgList();
-    websoctStore.connect();
-  } catch (e) {}
-});
 </script>
 
 <template>
@@ -259,7 +324,11 @@ onMounted(() => {
             headerName
           }}</el-header>
           <!-- 聊天 -->
-          <el-main class="right-container">
+          <el-main
+            class="right-container"
+            @mousewheel="handleScroll"
+            ref="mainContainer"
+          >
             <div
               class="message-container"
               v-for="(record, index) in chatRecords.data"
@@ -269,13 +338,18 @@ onMounted(() => {
               }"
               :key="index"
             >
-              <span v-if="useUserStore().uid !== record.toId">{{
-                record.content
-              }}</span>
+              <div
+                v-if="useUserStore().uid !== record.toId"
+                class="time-text right-back"
+              >
+                <div>{{ record.createTime }}</div>
+                <span>{{ record.content }}</span>
+              </div>
               <img :src="chat" class="head-sculpture" />
-              <span v-if="useUserStore().uid == record.toId">{{
-                record.content
-              }}</span>
+              <div v-if="useUserStore().uid == record.toId" class="left-back">
+                <div>{{ record.createTime }}</div>
+                <span>{{ record.content }}</span>
+              </div>
             </div>
           </el-main>
           <!-- 底部 -->
@@ -286,6 +360,12 @@ onMounted(() => {
               class="send-info-file"
               @click="sendFileClick"
             />
+            <FileTreeChoice
+              :openFile="openFile"
+              @close="openFile = false"
+              :fileUserTreeData="fileUserTreeData.data"
+              @fileChangeMsg="fileChangeMsg"
+            ></FileTreeChoice>
             <el-input
               v-model="messageText"
               class="w-50 m-2"