From 089bf5d2378b3c4a61d795b2a92bede2c193b771 Mon Sep 17 00:00:00 2001
From: admin <344137771@qq.com>
Date: Tue, 06 Jan 2026 11:22:58 +0800
Subject: [PATCH] 1

---
 src/components/editor/MeEditor.vue |  598 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 598 insertions(+), 0 deletions(-)

diff --git a/src/components/editor/MeEditor.vue b/src/components/editor/MeEditor.vue
new file mode 100644
index 0000000..ef25940
--- /dev/null
+++ b/src/components/editor/MeEditor.vue
@@ -0,0 +1,598 @@
+<template>
+  <div>
+
+    <el-container class="editor-container">
+      <div class="no-padding textarea main-editor padding0">
+        <div style="min-width: 38px;width: 38px;height: 38px;background-color: #fff;cursor: pointer;" 
+          @click="$refs.restFile.click()">
+          <img src="~@/assets/img/upload.png" style="width: 38px;height: 38px;"/>
+        </div>
+        <textarea class="box-sizing1"
+          ref="textarea"
+          v-model.trim="editorText"
+          rows="1"
+          placeholder="请输入消息..."
+          @keydown="keydownEvent($event)"
+          @input="inputEvent($event)"
+        ></textarea>
+        <div style="min-width: 38px;width: 38px;height: 38px;background-color: #fff;cursor: pointer;"
+          @click="SendText()">
+          <img v-if="this.$store.state.talks.sendStatus == 0" src="~@/assets/img/send.png" style="width: 38px;height: 38px;"/>
+          <div v-if="this.$store.state.talks.sendStatus == 1" class="loading"></div>
+        </div>
+      </div>
+      <form
+          enctype="multipart/form-data"
+          style="display: none"
+          ref="fileFrom"
+        >
+        <input
+          type="file"
+          ref="restFile"
+          accept="image/*"
+          @change="uploadImageChange"
+        />
+        <input type="file" ref="restFile2" @change="uploadFileChange" />
+      </form>
+    </el-container>
+  </div>
+</template>
+
+<script>
+// import MeEditorEmoticon from './MeEditorEmoticon'
+// import MeEditorFileManage from './MeEditorFileManage'
+import MeEditorImageView from './MeEditorImageView'
+// import MeEditorRecorder from './MeEditorRecorder'
+// import MeEditorVote from './MeEditorVote'
+// import MeEditorLocation from './MeEditorLocation'
+// import TalkCodeBlock from '@/components/chat/TalkCodeBlock'
+import { getPasteImgs, getDragPasteImg } from '@/utils/editor'
+import { findTalk } from '@/utils/talk'
+import store from '@/store'
+import {
+  ServeSendTalkCodeBlock,
+  ServeSendTalkImage,
+  ServeSendEmoticon,
+} from '@/api/chat'
+
+export default {
+  name: 'MeEditor',
+  components: {
+    MeEditorImageView,
+  },
+  computed: {
+    talkUser() {
+      return this.$store.state.dialogue.index_name
+    },
+    documentClientHeight: {
+      get () { return this.$store.state.common.documentClientHeight },
+      set (val) { this.$store.commit('common/updateDocumentClientHeight', val) }
+    },
+  },
+  watch: {
+    talkUser(n_index_name) {
+      this.$refs.filesManager.clear()
+      this.editorText = this.getDraftText(n_index_name)
+    },
+  },
+  data() {
+    return {
+      // 当前编辑的内容
+      editorText: '',
+
+      // 图片查看器相关信息
+      imageViewer: {
+        isShow: false,
+        file: null,
+      },
+
+      codeBlock: {
+        isShow: false,
+        editMode: true,
+      },
+
+      filesManager: {
+        isShow: false,
+      },
+
+      vote: {
+        isShow: false,
+      },
+
+      // 录音器
+      recorder: false,
+
+      // 上次发送消息的时间
+      sendtime: 0,
+
+      // 发送间隔时间(默认1秒)
+      interval: 1000,
+    }
+  },
+  created() {
+  },
+  mounted () {
+    this.resetDocumentClientHeight()
+  },
+  methods: {
+    // 读取对话编辑草稿信息
+    getDraftText(index_name) {
+      return findTalk(index_name).draft_text || ''
+    },
+
+    //复制粘贴图片回调方法
+    pasteImage(e) {
+      let files = getPasteImgs(e)
+      if (files.length == 0) return
+
+      this.openImageViewer(files[0])
+    },
+
+    //拖拽上传图片回调方法
+    dragPasteImage(e) {
+      let files = getDragPasteImg(e)
+      if (files.length == 0) return
+
+      this.openImageViewer(files[0])
+    },
+
+    inputEvent(e) {
+      this.$emit('keyboard-event', e.target.value)
+    },
+
+    // 键盘按下监听事件
+    keydownEvent(e) {
+      return;
+      if (e.keyCode == 13 && this.editorText == '') {
+        e.preventDefault()
+      }
+
+      // 回车发送消息
+      if (e.keyCode == 13 && e.shiftKey == false && this.editorText != '') {
+        let currentTime = new Date().getTime()
+
+        if (this.sendtime > 0) {
+          // 判断 1秒内只能发送一条消息
+          if (currentTime - this.sendtime < this.interval) {
+            e.preventDefault()
+            return false
+          }
+        }
+
+        this.$emit('send', this.editorText)
+        this.editorText = ''
+        this.sendtime = currentTime
+        e.preventDefault()
+      }
+    },
+    SendText(){
+      if(this.$store.state.talks.sendStatus == 1){return;}
+      this.$store.commit('SET_SEND_STATUS', 1)
+      let timer = setTimeout(() => {
+            clearTimeout(timer);
+            this.$store.commit('SET_SEND_STATUS', 0);
+        },5000);
+      let currentTime = new Date().getTime()
+
+        if (this.sendtime > 0) {
+          // 判断 1秒内只能发送一条消息
+          if (currentTime - this.sendtime < this.interval) {
+            // e.preventDefault()
+            return false
+          }
+        }
+
+        this.$emit('send', this.editorText)
+        this.editorText = ''
+        this.sendtime = currentTime
+        // e.preventDefault()
+    },
+
+    // 选择图片文件后回调方法
+    uploadImageChange(e) {
+      let file = e.target.files[0]
+      console.log(file)
+
+
+      const isLt2M = file.size / 1024 / 1024 < 10;
+        if (!isLt2M) {
+            Toast.fail('上传图片大小不能超过 10MB!');
+            return false;
+        }
+
+      let fileData = new FormData()
+      fileData.append('file', file)
+      //
+      this.$http({
+        url: this.$http.adornUrl('/api/uploadFile'),
+        method: 'post',
+        data: fileData,
+        headers: {
+          'Content-Type': 'multipart/form-data' // 设置请求头为 multipart/form-data
+        }
+      }).then(({ data }) => {
+        //
+        console.log("uploaded image = " + JSON.stringify(data));
+        if(data.code == 0){
+          this.$bus.$emit('SendMessage',{type:"img",content:""+data.data.httpUrl})
+        }else{
+          this.$message(''+data.msg)
+        }
+        //
+      })
+      .finally(() => {
+      })
+      //
+      // this.openImageViewer(file)
+      // this.openNewImageViewer(e);
+      //
+      // let file = e.target.files[0]
+      // console.log("file = " + file);
+      // this.imageViewer.isShow = true
+      // this.imageViewer.file = file
+      // store.commit('SET_IMAGE_VIEWER', this.imageViewer)
+      // this.$bus.$emit('SET_IMAGE_VIEWER', {file:file,isShow:true})
+      //
+      // this.$refs.restFile.value = null
+    },
+
+    // 选择文件回调事件
+    uploadFileChange(e) {
+      let maxsize = 100 * 1024 * 1024
+      if (e.target.files.length == 0) {
+        return false
+      }
+
+      let file = e.target.files[0]
+      if (/\.(gif|jpg|jpeg|png|webp|GIF|JPG|PNG|WEBP)$/.test(file.name)) {
+        this.openImageViewer(file)
+        return
+      }
+
+      if (file.size > maxsize) {
+        this.$notify.info({
+          title: '消息',
+          message: '上传文件不能大于100M',
+        })
+        return
+      }
+
+      this.filesManager.isShow = true
+      this.$refs.restFile2.value = null
+      this.$refs.filesManager.upload(file)
+    },
+
+    // 打开图片查看器
+    openImageViewer(file) {
+      console.log("file = " + file);
+      this.imageViewer.isShow = true
+      this.imageViewer.file = file
+      // store.commit('SET_IMAGE_VIEWER', this.imageViewer)
+      this.$bus.$emit('SET_IMAGE_VIEWER', {file:file,isShow:true})
+    },
+
+    // 打开图片查看器
+    openNewImageViewer(e) {
+      console.log("e = " + JSON.stringify(e));
+      let file = e.target.files[0]
+      console.log("file = " + file);
+      this.imageViewer.isShow = true
+      this.imageViewer.file = file
+      // store.commit('SET_IMAGE_VIEWER', this.imageViewer)
+      this.$bus.$emit('SET_IMAGE_VIEWER', {file:file,isShow:true})
+    },
+
+    sendRecorder(file) {
+      this.recorder = false
+      this.$refs.filesManager.upload(file)
+    },
+
+    // 代码块编辑器确认完成回调事件
+    confirmCodeBlock(data) {
+      const { talk_type, receiver_id } = this.$store.state.dialogue
+      ServeSendTalkCodeBlock({
+        talk_type,
+        receiver_id,
+        code: data.code,
+        lang: data.language,
+      }).then(res => {
+        if (res.code == 200) {
+          this.codeBlock.isShow = false
+        } else {
+          this.$notify({
+            title: '友情提示',
+            message: res.message,
+            type: 'warning',
+          })
+        }
+      })
+    },
+
+    // 确认上传图片消息回调事件
+    confirmUploadImage() {
+      const { talk_type, receiver_id } = this.$store.state.dialogue
+
+      let fileData = new FormData()
+      fileData.append('talk_type', talk_type)
+      fileData.append('receiver_id', receiver_id)
+      fileData.append('image', this.imageViewer.file)
+
+      let ref = this.$refs.imageViewer
+
+      ServeSendTalkImage(fileData)
+        .then(res => {
+          ref.loading = false
+          if (res.code == 200) {
+            ref.closeBox()
+          } else {
+            this.$notify({
+              title: '友情提示',
+              message: res.message,
+              type: 'warning',
+            })
+          }
+        })
+        .finally(() => {
+          ref.loading = false
+        })
+    },
+
+    // 选中表情包回调事件
+    selecteEmoticon(data) {
+      if (data.type == 1) {
+        let value = this.editorText
+        let el = this.$refs.textarea
+        let startPos = el.selectionStart
+        let endPos = el.selectionEnd
+        let newValue =
+          value.substring(0, startPos) +
+          data.value +
+          value.substring(endPos, value.length)
+
+        this.editorText = newValue
+
+        if (el.setSelectionRange) {
+          // setTimeout(() => {
+          //   let index = startPos + data.value.length
+          //   el.setSelectionRange(index, index)
+          //   el.focus()
+          // }, 0)
+        }
+      } else {
+        const { talk_type, receiver_id } = this.$store.state.dialogue
+        ServeSendEmoticon({
+          talk_type,
+          receiver_id,
+          emoticon_id: data.value,
+        })
+      }
+
+      this.$refs.popoverEmoticon.doClose()
+    },
+
+    sendGeoLocation() {},
+
+
+    siteContentViewHeight () {
+      var height = 1280 - 50
+     
+      return { minHeight: height + 'px' }
+    },
+    // 重置窗口可视高度
+    resetDocumentClientHeight () {
+      this.documentClientHeight = document.documentElement['clientHeight'] - 80
+      window.onresize = () => {
+        this.documentClientHeight = document.documentElement['clientHeight'] - 80
+      }
+      document.documentElement.clientHeight
+    },
+  },
+}
+</script>
+<style scoped>
+.editor-container {
+  height: 90px;
+  width: 100%;
+  background-color: #EDEDED;
+}
+
+.editor-container .toolbar {
+  line-height: 35px;
+  border-bottom: 1px solid #f5f0f0;
+  border-top: 1px solid #f5f0f0;
+}
+
+.editor-container .toolbar li {
+  list-style: none;
+  float: left;
+  width: 35px;
+  margin-left: 3px;
+  cursor: pointer;
+  text-align: center;
+  line-height: 35px;
+  position: relative;
+  color: #8d8d8d;
+}
+
+.editor-container .toolbar li .tip-title {
+  display: none;
+  position: absolute;
+  top: 38px;
+  left: 0px;
+  height: 26px;
+  line-height: 26px;
+  background-color: rgba(31, 35, 41, 0.9);
+  color: white;
+  min-width: 30px;
+  font-size: 10px;
+  padding: 0 5px;
+  border-radius: 2px;
+  white-space: pre;
+  text-align: center;
+  user-select: none;
+  z-index: 1;
+}
+
+.editor-container .toolbar li:hover .tip-title {
+  display: block;
+}
+
+.editor-container .toolbar li:hover {
+  background-color: #f7f5f5;
+}
+
+.editor-container .toolbar .text-tips {
+  float: right;
+  margin-right: 15px;
+  font-size: 12px;
+  color: #ccc;
+}
+
+.editor-container .toolbar .text-tips i {
+  font-size: 14px;
+  cursor: pointer;
+  margin-left: 5px;
+  color: rgb(255, 181, 111);
+}
+
+.editor-container .textarea {
+  overflow: hidden;
+  position: relative;
+}
+
+textarea {
+  /* width: calc(100% - 80px);
+  width: -moz-calc(100% - 80px);
+  width: -webkit-calc(100% - 80px);
+  height: calc(100% - 10px);
+  height: -moz-calc(100% - 10px);
+  height: -webkit-calc(100% - 10px); */
+  border: 0 none;
+  outline: none;
+  resize: none;
+  font-size: 15px;
+  /* overflow-y: auto; */
+  color: #464545;
+  /* padding: 5px; */
+  position: relative;
+  /* margin-top: -20px; */
+  width: calc(100vw - 80px);
+  height: 90px;
+
+}
+
+textarea::-webkit-scrollbar {
+  width: 4px;
+  height: 1px;
+}
+
+textarea::-webkit-scrollbar-thumb {
+  background: #d5cfcf;
+}
+
+textarea::-webkit-scrollbar-track {
+  background: #ededed;
+}
+
+textarea::-webkit-input-placeholder {
+  color: #dccdcd;
+  font-size: 12px;
+  font-weight: 400;
+}
+
+/* 编辑器文档说明 --- start */
+.editor-books .books-title {
+  font-size: 16px;
+  height: 30px;
+  line-height: 22px;
+  margin-top: 10px;
+  margin-bottom: 10px;
+  border-bottom: 1px solid #cbcbcb;
+  color: #726f6f;
+  font-weight: 400;
+  margin-left: 11px;
+}
+
+.editor-books p {
+  text-indent: 10px;
+  font-size: 12px;
+  height: 30px;
+  line-height: 30px;
+  color: #7f7c7c;
+}
+
+input::-webkit-input-placeholder,
+textarea::-webkit-input-placeholder {
+    color: #AFB1B5;
+    font-size: 14px; 
+    height: 90px;line-height: 90px; 
+}
+input::-moz-placeholder, 
+textarea::-moz-placeholder {  /* Mozilla Firefox 19+ */
+    color: #AFB1B5;
+    font-size: 14px;  
+    height: 90px;line-height: 90px;
+}
+input:-moz-placeholder, 
+textarea:-moz-placeholder {  /* Mozilla Firefox 4 to 18 */
+    color: #AFB1B5;
+    font-size: 14px;
+    height: 90px;line-height: 90px;
+}
+input:-ms-input-placeholder, 
+textarea:-ms-input-placeholder {  /* Internet Explorer 10-11 */
+    color: #AFB1B5;
+    font-size: 14px;  
+    height: 90px;line-height: 90px;
+}
+
+.main-editor{
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #fff;
+  width: auto;
+}
+
+.padding0{
+  padding: 0;
+}
+
+.box-sizing1 {
+  box-sizing: none; /* 1 */
+}
+
+
+*,
+*:before,
+*:after {
+  box-sizing: none;
+}
+
+/* 编辑器文档说明 --- end */
+
+.loading {
+  position: relative;
+  left: 0%;
+  top: 0%;
+  width: 34px;
+  height: 34px;
+  border: 2px solid #000;
+  border-top-color: rgba(0, 0, 0, 0.2);
+  border-right-color: rgba(0, 0, 0, 0.2);
+  border-bottom-color: rgba(0, 0, 0, 0.2);
+  border-radius: 100%;
+
+  animation: circle infinite 0.75s linear;
+}
+
+@keyframes circle {
+  0% {
+    transform: rotate(0);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
+
+</style>

--
Gitblit v1.9.3