美文网首页
聊天相关2>选中@用户整个交互

聊天相关2>选中@用户整个交互

作者: 衬fzy | 来源:发表于2023-02-20 16:53 被阅读0次
                  <!-- 输入框 -->
                 <div class="infoAdd2">
                    <el-input
                      id="keywordsText"
                      ref="keywordsText"
                      v-model="addOrderMsgForm.content"
                      maxlength="500"
                      class="keywordsText"
                      resize="none"
                      type="textarea"
                      :rows="2"
                      placeholder="请输入内容,点击回车发送。"
                      :disabled="form.status !== 1"
                      @keyup.enter.native="addOrderMsgFun($event)"
                      @input="contentFun()"
                      @keydown.up.native="onkeydownFun"
                      @keydown.down.native="onkeydownFun"
                      @focus="foucsFun()"
                    >
                    </el-input>
                  </div>
                  <!-- @选择框 -->
               <div v-if="urlListShow" class="urlList scroll">
                  <div class="ul">
                    <div
                      v-for="(item, k) in orderMsgMemberArrList"
                      :key="k"
                      :class="itemK == k ? 'li li0' : 'li'"
                      @mouseenter="mouseenterItemKFun(k)"
                      @click="setAtFun(1)"
                    >
                      {{ item.truename + ':' + item.username }}
                    </div>
                  </div>
                </div>

js

  mounted() {
    document.onkeydown = this.showkey;// 监听按键
  },
  methods: {
    showkey(event) {
      let key = event.keyCode;
      this.keyCode = key
      let i = null
      switch (key) {
        case 37:// "按了←键!"
          this.urlListShowFun('-')
          break;
        case 38:// "按了↑键!"
          i = this.itemK - 1
          this.itemK = i < 0 ? 0 : i
          // this.itemK最小值只能0
          break;
        case 39:// "按了→键!"
          this.urlListShowFun('+')
          break;
        case 40:// "按了↓键!"
          i = this.itemK + 1
          this.itemK = i == this.orderMsgMemberArrList.length ? this.orderMsgMemberArrList.length - 1 : i
          // this.itemK最大值只能是卡选项的长度
          break;
        case 13:// "按了回车键!"
          if (this.urlListShow == true) { // 可选项dom框打开时
            this.setAtFun(0)
          }
          break;
      }
    },
    /** 输入框内容变化 */
    contentFun() {
      if (this.urlListShow == true && this.keyCode == 13) {
        // 按回车就不允许下一步判断,否弹出@选项框
        return
      }
      this.urlListShowFun()
    },
    /** 移到可选人员上,修改选中项 */
    mouseenterItemKFun(k) {
      this.itemK = k
    },
    /** 写入选中@人信息 ,number==1是点击选中的*/
    setAtFun(number) {
      const index0 = this.$refs.keywordsText.$refs.textarea.selectionStart // 写入前的光标位置
      setTimeout(() => {
        if (this.checkarr.length > 0) { // 是模糊搜索打开的
          let lastIndex = this.addOrderMsgForm.content.lastIndexOf('@', this.num)// 光标前的@位置
          let txt = this.addOrderMsgForm.content.substring(0, lastIndex)
          let index = this.$refs.keywordsText.$refs.textarea.selectionStart// 光标位置
          let txt2 = this.addOrderMsgForm.content.substring(index)
          // console.log(txt, JSON.stringify(txt2))
          let item = this.orderMsgMemberArrList[this.itemK]
          let atTxt = ` @${item.username} (${item.truename}) `
          if (txt2.length == 0 || JSON.stringify(txt2) == JSON.stringify('\n')) {
            this.addOrderMsgForm.content = txt + atTxt
          } else {
            console.log(JSON.stringify(txt2))
            this.addOrderMsgForm.content = txt + atTxt + txt2
          }
          this.$nextTick(() => {
            // 光标复位
            let ctrl = this.$refs.keywordsText.$refs.textarea
            console.log(ctrl.setSelectionRange)
            // if (ctrl.setSelectionRange) {
            ctrl.focus()
            ctrl.setSelectionRange(index0 - 1 + atTxt.length, index0 - 1 + atTxt.length)
            // } else if (ctrl.createTextRange) {
            //   console.log(2)
            //   var range = ctrl.createTextRange()
            //   range.collapse(true)
            //   range.moveEnd('character', index0)
            //   range.moveStart('character', index0)
            //   range.select()
            // }
          })
        } else { // 非模糊搜索打开的
          let index = this.$refs.keywordsText.$refs.textarea.selectionStart
          let txt = this.addOrderMsgForm.content.substring(0, index - 2 + number)// 回车会多一个空格所以减去2,鼠标点击就是正常的所以+number,number就是1
          let txt2 = this.addOrderMsgForm.content.substring(index)
          console.log(txt, JSON.stringify(txt2))
          let item = this.orderMsgMemberArrList[this.itemK]
          let atTxt = ` @${item.username} (${item.truename}) `
          if (txt2.length == 0) {
            this.addOrderMsgForm.content = txt + atTxt
          } else {
            this.addOrderMsgForm.content = txt + atTxt + txt2
          }
          this.$nextTick(() => {
            // 光标复位
            let ctrl = this.$refs.keywordsText.$refs.textarea
            console.log(ctrl.setSelectionRange)
            // if (ctrl.setSelectionRange) {
            ctrl.focus()
            ctrl.setSelectionRange(index0 + atTxt.length, index0 + atTxt.length)
            // } else if (ctrl.createTextRange) {
            //   console.log(2)
            //   var range = ctrl.createTextRange()
            //   range.collapse(true)
            //   range.moveEnd('character', index0)
            //   range.moveStart('character', index0)
            //   range.select()
            // }
          })
        }
        setTimeout(() => { // 加延时是避免回车时关闭了选择框,消息就发送出去了
          this.urlListShow = false
          this.checkarr = []
        }, 200)
      }, 0)
    },
    /** 是否弹出@候选列表框 */
    urlListShowFun(val) {
      let index = this.$refs.keywordsText.$refs.textarea.selectionStart// 光标所在位置
      this.num = index
      if (val == '-') { // 按了←键
        this.num = this.num - 1 < 0 ? 0 : this.num - 1
      } else if (val == '+') { // 按了→键
        this.num = this.num + 1 > this.addOrderMsgForm.content.length ? this.addOrderMsgForm.content.length : this.num + 1
      }
      let typeTxt = this.addOrderMsgForm.content.substring(this.num - 1, this.num)// 拿光标前面两个字符
      let lastIndex = this.addOrderMsgForm.content.lastIndexOf('@', this.num)
      console.log(this.num, typeTxt, lastIndex)
      if (typeTxt == '@' || JSON.stringify(typeTxt) == JSON.stringify('\n@')) {
        // 光标在@和换行的@位置后面
        this.itemK = 0// @选中位置
        this.urlListShow = true
        console.log('this.urlListShow1')
        this.orderMsgMemberArrList = this.orderMsgMemberArr
      } else if (lastIndex != -1) {
        // 光标在非@后面时的前面发现@
        let lastATtxt = this.addOrderMsgForm.content.substring(lastIndex + 1, this.num)// @符号后面:模糊搜索内容
        this.checkarr = this.orderMsgMemberArr.filter((v) => (v.truename.includes(lastATtxt)))
        // console.log(this.checkarr)
        if (this.checkarr.length > 0) {
          // 发现@后面内容跟聊天任意名字有模糊搜索相符的
          this.orderMsgMemberArrList = this.checkarr// checkarr 模糊筛选的可选项, orderMsgMemberArrList 渲染的选项
          this.itemK = 0// 当前@选中项
          this.urlListShow = true
        } else {
          setTimeout(() => { // 加延时是避免回车时关闭了选择框,消息就发送出去了
            this.urlListShow = false
            this.checkarr = []
          }, 200)
        }
      } else {
        setTimeout(() => { // 加延时是避免回车时关闭了选择框,消息就发送出去了
          this.urlListShow = false
          this.checkarr = []
        }, 200)
      }
    },
    onkeydownFun(event) {
      event.preventDefault(); // 禁止键盘上下按键时光标移动
    },
  }


css

              .infoAdd2 {
                padding-top: 8px;
                flex: 1;

                ::v-deep {
                  .keywordsText {
                    overflow-y: hidden !important;
                    border: 1px solid #eee;
                  }

                  .el-textarea__inner {
                    border: 0;
                  }
                }
              }

            .urlList {
              position: absolute;
              left: 0;
              bottom: 61px;
              background: #fff;
              width: 100%;
              padding-top: 5px;
              max-height: 230px;
              overflow-y: auto;

              .ul {
                .li {
                  padding: 3px 46px;
                  cursor: pointer;
                }

                .li0 {
                  background: #1026F1;
                  color: #fff;
                }
              }
            }

相关文章

  • Android 07--View的绘制机制简介

    从开发人员角度,我们可以知道,整个App主要有各个活动、服务等相关组成,而用户交互的基础来自于界面。存在用户交互就...

  • 案例2:图像选项组的交互运用

    多个图像,一次只能选中一个 2. 与案例1一样每个设置鼠标悬停及选中时的样式,添加选中交互,并将第一个的选中交互复...

  • 【altium designer】AD PCB 交互式布局

    1.交互式布局:PCB选中的时候再原理图也被选中;反之亦然。PCB总快捷键:TC。 2.交互模式:PCB and ...

  • 数据透视表

    1.认识数据透视表 功能强大 特点简单灵活 和用户交互性强 扩展性强 数据透视表需要系统的学习 2.操作步骤 选中...

  • Python-part3-基础

    与用户交互 1、什么是与用户交互 程序等待用户输入一些数据,然后程序执行完毕后为用户反馈信息 2、为何程序要与用户...

  • 实践4 自定义复选框

    1、触发事件:鼠标单击时 2、属性设置:交互样式 3、动作设置:切换选中状态 初始状态: 鼠标悬停状态: 选中状态:

  • 手势解锁

    效果 实现思路 1.继承UIview 包含 所有子按钮的数组 按钮设置不可交互 有选中 和 未选中的图片2.布局...

  • APP中弹窗类型

    一、弹窗定义 1.弹窗的作用 需要用户回应或给与用户相关信息提示等与之交互的窗口 2.app弹窗分类 3.模态窗口...

  • Android 的四大组件

    Activity:Activity 是一个负责与用户交互的组件,Activity 中所有操作都与用户密切相关,可以...

  • springboot Hibernate Validate 校

    前言在做web相关的应用时,经常需要提供接口与用户交互(获取数据、上传数据等),由于这个过程需要用户进行相关的操作...

网友评论

      本文标题:聊天相关2>选中@用户整个交互

      本文链接:https://www.haomeiwen.com/subject/bddgkdtx.html