<template>
  <div class="dialog-page">
    <ZPaging
      use-chat-record-mode
      use-virtual-list
      cell-height-mode="dynamic"
      :refresher-enabled="true"
      :show-scrollbar="false"
      :loading-more-enabled="true"
      :hide-empty-view="true"
      height="100%"
      ref="zpagingRef"
      v-model="virtualList"
      :loading-more-custom-style="{ display: 'none', height: '0' }"
      @scrolltolower="onScrollToLower"
      @scrolltoupper="onScrollToUpper"
    >
      <template #top>
        <customNavbar
          :title="talkParams.username"
          id="navBarArea"
          :hideBack="dialogueStore.isOpenMultiSelect"
        >
          <template #left v-if="dialogueStore.isOpenMultiSelect">
            <text
              class="ml-[36rpx]"
              @click="dialogueStore.isOpenMultiSelect = false"
            >
              取消
            </text>
          </template>
          <template
            #subTitle
            v-if="talkStore?.findItem(talkParams.index_name)?.group_type === 4"
          >
            <div class="text-[24rpx] text-[#999999]">公司群</div>
          </template>
          <template #right>
            <div
              class="mr-[36rpx] toChatSetting_btn"
              v-if="!talkParams.isDismiss && !talkParams.isQuit"
            >
              <tm-icon
                color="rgb(51, 51, 51)"
                :font-size="36"
                name="tmicon-gengduo"
                @click="toChatSettingsPage"
              ></tm-icon>
            </div>
          </template>
        </customNavbar>
      </template>
      <!-- <template #top>
            <div class="load-toolbar pointer">
              <span v-if="loadConfig.status == 0"> 正在加载数据中 ... </span>
              <span v-else-if="loadConfig.status == 1" @click="onScrollToLower"> 查看更多消息 ... </span>
              <span v-else class="no-more"> 没有更多消息了 </span>
            </div>
          </template> -->

      <!-- 数据加载状态栏 -->
      <div class="dialog-list" @touchstart="handleHidePanel">
        <div
          class="message-item"
          v-for="item in virtualList"
          :id="`zp-id-${item.msg_id}`"
          :key="item.zp_index"
          style="transform: scaleY(-1);"
        >
          <!-- 系统消息 -->
          <div v-if="item.msg_type >= 1000" class="message-box">
            <component
              :is="MessageComponents[item.msg_type] || 'unknown-message'"
              :extra="item.extra"
              :data="item"
            />
          </div>
          <!-- 撤回消息 -->
          <div v-else-if="item.is_revoke == 1" class="message-box">
            <revoke-message
              :login_uid="userStore.uid"
              :user_id="item.user_id"
              :nickname="item.nickname"
              :talk_type="item.talk_type"
              :datetime="item.created_at"
              :msg_id="item.msg_id"
              :revokeInfo="item.revokeInfo"
              :extra="item.extra"
            >
              <template
                v-if="
                  canEditRevokedMessage(item) && item.user_id === userStore.uid
                "
              >
                <span
                  class="edit-revoked-message"
                  @click="restoreRevokedMessage(item)"
                >
                  重新编辑
                </span>
              </template>
            </revoke-message>
          </div>

          <div
            v-else
            class="message-box record-box"
            :class="{
              'direction-rt': item.user_id === talkParams.uid,
              'multi-select': dialogueStore.isOpenMultiSelect,
              'multi-select-check': item.isCheck,
            }"
          >
            <!-- 多选按钮 -->
            <aside
              v-if="dialogueStore.isOpenMultiSelect"
              class="checkbox-column"
            >
              <!-- <n-checkbox size="small" :checked="item.isCheck" @update:checked="item.isCheck = !item.isCheck" /> -->
              <tm-checkbox
                :round="10"
                :defaultChecked="item.isCheck"
                @update:modelValue="item.isCheck = !item.isCheck"
                :size="42"
                color="#46299D"
              ></tm-checkbox>
            </aside>

            <!-- 头像信息 -->
            <aside
              class="avatar-column"
              @click="toUserDetailPage(item)"
              @touchstart="() => handleAvatarTouchStart(item)"
              @touchend="handleAvatarTouchEnd"
            >
              <im-avatar
                class="pointer"
                :src="item.avatar"
                :size="80"
                :username="item.nickname"
                @click="showUserInfoModal(item.user_id)"
              />
            </aside>

            <!-- 主体信息 -->
            <main class="main-column">
              <div class="talk-title">
                <span
                  class="nickname pointer"
                  v-show="
                    talkParams.type == 2 && item.user_id !== talkParams.uid
                  "
                >
                  <!-- <span class="at">@</span> -->
                  {{ item.nickname }}
                </span>
                <span>
                  {{ parseTime(item.created_at, '{m}/{d} {h}:{i}') }}
                </span>
              </div>

              <div
                class="talk-content"
                :class="{ pointer: dialogueStore.isOpenMultiSelect }"
              >
                <deepBubble
                  @clickMenu="(menuType) => onContextMenu(menuType, item)"
                  :isShowCopy="isShowCopy(item)"
                  :isShowWithdraw="isRevoke(talkParams.uid, item) || isLeader"
                >
                  <component
                    class="component-content"
                    :key="item.zp_index"
                    :is="MessageComponents[item.msg_type] || 'unknown-message'"
                    :extra="item.extra"
                    :data="item"
                    :max-width="true"
                    :source="'panel'"
                  />
                </deepBubble>
                <!-- <div class="talk-tools">
                    <template v-if="talkParams.type == 1 && item.float == 'right'">
                      <loading theme="outline" size="19" fill="#000" :sxtrokeWidth="1" class="icon-rotate"
                        v-show="item.send_status == 1" />

                      <span v-show="item.send_status == 1"> 正在发送... </span>
                      <span v-show="item.send_status != 1"> 已送达 </span>
                    </template>

                  </div> -->
              </div>

              <div
                v-if="item.extra.reply"
                class="talk-reply pointer"
                @click="onJumpMessage(item.extra?.reply?.msg_id)"
              >
                <!-- <n-icon :component="ToTop" size="14" class="icon-top" /> -->
                <span class="ellipsis">
                  回复 {{ item.extra?.reply?.nickname }}:
                  {{ item.extra?.reply?.content }}
                </span>
              </div>
            </main>
          </div>
        </div>
        <div class="load-toolbar pointer" style="transform: scaleY(-1);">
          <span v-if="loadConfig.status == 0">正在加载数据中 ...</span>
          <span v-if="loadConfig.status == 1" @click="onScrollToLower">
            查看更多消息 ...
          </span>
          <span v-if="loadConfig.status == 2" class="no-more">
            没有更多消息了
          </span>
        </div>
      </div>
      <template #bottom>
        <div class="footBox" id="footBoxArea">
          <div v-if="!dialogueStore.isOpenMultiSelect">
            <div
              class="pt-[16rpx] ml-[32rpx] mr-[32rpx] flex items-start justify-between"
            >
              <div class="flex-1 quillBox" style="">
                <QuillEditor
                  ref="editor"
                  id="editor"
                  :options="editorOption"
                  @editorChange="onEditorChange"
                  style="
                    width: 100%;
                    flex: 1;
                    height: 100%;
                  "
                  @click="onEditorClick"
                />
                <!-- <tm-input type=textarea autoHeight focusColor="#F9F9F9" color="#F9F9F9" :inputPadding="[12]"
              placeholder=""></tm-input> -->
                <div class="quote-area" v-if="state?.quoteInfo">
                  <span
                    v-if="state?.quoteInfo?.msg_type === 1"
                    class="text-[28rpx] text-[#999]"
                  >
                    {{
                      state?.quoteInfo?.nickname +
                      ':' +
                      state?.quoteInfo?.extra?.content
                    }}
                  </span>
                  <span
                    v-if="state?.quoteInfo?.msg_type !== 1"
                    class="text-[28rpx] text-[#999]"
                  >
                    {{
                      state?.quoteInfo?.nickname +
                      ':' +
                      ChatMsgTypeMapping[state?.quoteInfo?.msg_type]
                    }}
                  </span>
                  <img
                    @click="clearQuoteInfo"
                    style="width: 30rpx; height: 30rpx;"
                    src="@/static/image/login/check-circle-filled@3x.png"
                  />
                </div>
              </div>
              <div class="flex items-center justify-end h-[72rpx]">
                <tm-image
                  :margin="[10, 0]"
                  @click="handleEmojiPanel"
                  :width="52"
                  :height="52"
                  :round="12"
                  :src="state.isOpenEmojiPanel ? keyboard : smile"
                ></tm-image>
                <tm-image
                  @click="handleFilePanel"
                  :margin="[10, 0]"
                  :width="52"
                  :height="52"
                  :round="12"
                  :src="addCircleGray"
                ></tm-image>
                <tm-button
                  @click="onSendMessageClick"
                  :margin="[0, 0]"
                  :padding="[0, 30]"
                  color="#46299D"
                  :fontSize="28"
                  size="mini"
                  :shadow="0"
                  label="发送"
                ></tm-button>
              </div>
            </div>
            <div v-if="state.isOpenEmojiPanel" class="mt-[50rpx]">
              <emojiPanel @on-select="onEmoticonEvent" />
            </div>
            <div v-if="state.isOpenFilePanel" class="mt-[16rpx]">
              <filePanel
                @selectImg="handleSelectImg"
                :talkParams="talkParams"
              />
            </div>
          </div>
          <div v-else class="h-[232rpx]">
            <div
              class="flex items-center justify-center mt-[12rpx] text-[24rpx] text-[#747474] leading-[44rpx]"
            >
              <div class="mr-[8rpx]">已选中:</div>
              <div>{{ selectedMessage.length }}条消息</div>
            </div>
            <div
              class="flex items-center justify-around pl-[128rpx] pr-[128rpx] mt-[18rpx] text-[20rpx] text-[#737373]"
            >
              <div
                @click="handleMergeForward"
                class="flex flex-col items-center justify-center"
              >
                <tm-image :width="68" :height="68" :src="zu6050"></tm-image>
                <div class="mt-[6rpx]">合并转发</div>
              </div>
              <div
                @click="handleSingleForward"
                class="flex flex-col items-center justify-center"
              >
                <tm-image :width="68" :height="68" :src="zu6051"></tm-image>
                <div class="mt-[6rpx]">逐条转发</div>
              </div>
              <!-- <div
                @click="handleWechatForward"
                class="flex flex-col items-center justify-center"
              >
                <tm-image :width="68" :height="68" :src="zu6052"></tm-image>
                <div class="mt-[6rpx]">微信</div>
              </div> -->
              <div
                @click="handleDelete"
                class="flex flex-col items-center justify-center"
              >
                <tm-image :width="68" :height="68" :src="zu6053"></tm-image>
                <div class="mt-[6rpx]">删除</div>
              </div>
            </div>
          </div>

          <!--底部安全区-->
          <div class="content-placeholder"></div>
          <tm-drawer
            placement="bottom"
            v-model:show="state.showWin"
            :hideHeader="true"
            :height="416"
            :round="6"
          >
            <div class="w-full h-full flex flex-col items-center">
              <div
                class="mt-[46rpx] mb-[44rpx] leading-[48rpx] text-[#747474] text-[24rpx]"
              >
                撤回该条消息?
              </div>
              <div class="divider"></div>
              <div
                @click="withdrawerConfirm"
                class="mt-[32rpx] mb-[32rpx] text-[32rpx] text-[#CF3050] leading-[48rpx]"
              >
                撤回
              </div>
              <div class="divider"></div>
              <div
                @click="state.showWin = false"
                class="mt-[32rpx] mb-[32rpx] text-[32rpx] text-[#000000] leading-[48rpx]"
              >
                取消
              </div>
            </div>
          </tm-drawer>
        </div>
      </template>
    </ZPaging>
    <tm-drawer
      placement="bottom"
      v-model:show="state.isShowMentionSelect"
      :hideHeader="true"
      :round="5"
      :height="state.mentionSelectHeight"
    >
      <div
        class="mention-select-drawer flex flex-row flex-1 flex-row flex-row-center-between"
      >
        <div
          class="cancel-btns flex-row flex flex-row-center-start"
          style="width: 210rpx;"
        >
          <div
            class="hide-btn"
            v-if="!state.mentionIsMulSelect"
            @click="hideMentionSelect"
          >
            <img
              style="width: 40rpx; height: 40rpx;"
              src="@/static/image/chatList/mention_select_hide_bg.png"
            />
            <img
              style="
                position: absolute;
                top: 50%;
                left: 50%;
                margin-left: -9rpx;
                margin-top: -5rpx;
              "
              src="@/static/image/chatList/mention_select_hide_icon.png"
            />
          </div>
          <span
            style="flex-shrink: 0; display: block;"
            class="text-[32rpx] font-regular text-[#191919]"
            v-if="state.mentionIsMulSelect"
            @click="changeMentionSelectMul(false)"
          >
            {{ $t('cancel') }}
          </span>
        </div>
        <div
          class="flex flex-row-center-center flex-col"
          style="padding: 6rpx 0;"
        >
          <text>{{ $t('chat.mention.select') }}</text>
        </div>
        <div class="flex-row flex flex-row-center-end" style="width: 210rpx;">
          <div
            class="mention-edit-btn"
            v-if="!state.mentionIsMulSelect"
            @click="changeMentionSelectMul(true)"
          >
            <span class="text-[32rpx] font-regular text-[#191919]">
              {{ $t('button.multiple.choice') }}
            </span>
          </div>
          <div
            class="mention-done-btn"
            :class="
              state?.selectedMembersNum > 0 ? 'mention-done-btn-can-do' : ''
            "
            v-if="state.mentionIsMulSelect"
            @click="confirmMentionSelect"
          >
            <span class="text-[32rpx] font-regular text-[#191919]">
              {{ $t('button.text.done') }}
            </span>
            <span
              class="text-[32rpx] font-regular text-[#191919]"
              v-if="state?.selectedMembersNum > 0"
            >
              {{ '(' + state?.selectedMembersNum + ')' }}
            </span>
          </div>
        </div>
      </div>
      <selectMemberByAlphabet
        :manageType="'mention'"
        ref="selectMemberByAlphabetRef"
        :selectAreaHeight="state.selectAreaHeight"
        @updateSelectedMembersNum="updateSelectedMembersNum"
        :isMulSelect="state.mentionIsMulSelect"
        @getSelectResult="getSelectResult"
        @getMentionSelectLists="getMentionSelectLists"
      ></selectMemberByAlphabet>
    </tm-drawer>
  </div>
</template>
<script setup>
import selectMemberByAlphabet from '../chatSettings/components/selectMemberByAlphabet.vue'
import {
  ref,
  reactive,
  watch,
  computed,
  onMounted,
  onUnmounted,
  nextTick,
} from 'vue'
import { QuillEditor, Quill } from '@vueup/vue-quill'
import EmojiBlot from './formats/emoji'
import { useChatList } from '@/store/chatList/index.js'
import { useAuth } from '@/store/auth'
import {
  useUserStore,
  useDialogueStore,
  useUploadsStore,
  useEditorDraftStore,
  useTalkStore,
  useSettingsStore,
  useDialogueListStore,
} from '@/store'
import addCircleGray from '@/static/image/chatList/addCircleGray.png'
import {
  MessageComponents,
  ForwardableMessageType,
  ChatMsgTypeMapping,
} from '@/constant/message'
import { formatTime, parseTime } from '@/utils/datetime'
import { deltaToMessage, deltaToString, isEmptyDelta } from './util'
import smile from '@/static/image/chatList/smile@2x.png'
import keyboard from '@/static/image/chatList/keyboard@2x.png'
import { useInject, useTalkRecord } from '@/hooks'
import { emitCall } from '@/utils/common'
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
import emojiPanel from './components/emojiPanel.vue'
import filePanel from './components/filePanel.vue'
import lodash from 'lodash'
import {
  ServePublishMessage,
  detailGetRecordsContext,
  ServeClearTalkUnreadNum,
  ServeTalkRecords,
} from '@/api/chat'
import copy07 from '@/static/image/chatList/copy07@2x.png'
import multipleChoices from '@/static/image/chatList/multipleChoices@2x.png'
import cite from '@/static/image/chatList/cite@2x.png'
import withdraw from '@/static/image/chatList/withdraw@2x.png'
import delete07 from '@/static/image/chatList/delete@2x.png'
import zu6050 from '@/static/image/chatList/zu6050@2x.png'
import zu6051 from '@/static/image/chatList/zu6051@2x.png'
import zu6052 from '@/static/image/chatList/zu6052@2x.png'
import zu6053 from '@/static/image/chatList/zu6053@2x.png'
import deepBubble from '@/components/deep-bubble/deep-bubble.vue'
import { isRevoke } from './menu'
import useConfirm from '@/components/x-confirm/useConfirm.js'
import { onLoad as uniOnload, onUnload as uniOnUnload } from '@dcloudio/uni-app'

Quill.register('formats/emoji', EmojiBlot)
import 'quill-mention'
const selectMemberByAlphabetRef = ref(null)

const {
  getDialogueList,
  updateZpagingRef,
  virtualList,
} = useDialogueListStore()
const talkStore = useTalkStore()
const { showConfirm } = useConfirm()
const settingsStore = useSettingsStore()
const userStore = useUserStore()
const dialogueStore = useDialogueStore()
const editorDraftStore = useEditorDraftStore()
const editor = ref()
const zpagingRef = ref()
useZPaging(zpagingRef)
const indexName = computed(() => dialogueStore.index_name)
const talkParams = reactive({
  uid: computed(() => userStore.uid),
  index_name: computed(() => dialogueStore.index_name),
  type: computed(() => dialogueStore.talk.talk_type),
  receiver_id: computed(() => dialogueStore.talk.receiver_id),
  username: computed(() => dialogueStore.talk.username),
  online: computed(() => dialogueStore.online),
  keyboard: computed(() => dialogueStore.keyboard),
  num: computed(() => dialogueStore.members.length),
  isDismiss: computed(() => dialogueStore.isDismiss),
  isQuit: computed(() => dialogueStore.isQuit),
  adminList: computed(() => dialogueStore.getAdminList),
  unReadNum: computed(() => dialogueStore.unreadNum),
})

const state = ref({
  isOpenEmojiPanel: false,
  isOpenFilePanel: false,
  showWin: false,
  onfocusItem: null,
  sessionId: '', //会话Id
  localPageLoadDone: true, //分页加载缓存中的聊天记录是否完毕
  quoteInfo: null, //引用信息
  mentionIsMulSelect: false, //是否是多选提醒的人
  selectedMembersNum: 0, //选中的要提醒的人数
  mentionSelectHeight: 0, //选择要提醒人的区域高度
  selectAreaHeight: 0, //选择要提醒人的可选人员列表区域高度
  isShowMentionSelect: false, //是否显示要提醒人的选择区域
  useCustomLoadMore: false, //是否使用自定义加载更多事件(下拉刷新、上拉加载)
  recordDate: '', //按日期查询聊天记录的开始日期
  serveFindRecord: [], //调用接口查找到的聊天记录
  middleMsg: {}, //缓存中没有时,调用接口初次使用的依据记录
  keepDialogInfo: false, //是否保存会话信息
  lastCursorIndex: undefined, //在失焦前保存光标位置
  mentionUserIds: [], //存储所有被@的用户ID
  isInsertingMention: false, //是否正在插入mention
  showMentionSelectTimer: null, //显示提醒选择框的定时器
  lastMentionText: '', // 记录上一次触发@时的完整文本内容
  lastMentionTriggered: false, // 记录当前@是否已经触发过
  lastMentionPosition: -1, // 添加新的状态来记录上一次@的位置
})

uniOnload(async (options) => {
  console.log('onLoad' + JSON.stringify(options))
  if (options.sessionId) {
    state.value.sessionId = options.sessionId
  }
  if (options.keepDialogInfo) {
    state.value.keepDialogInfo = options.keepDialogInfo === '1' ? true : false
  }
  if (options.msgInfo) {
    const msgInfo = JSON.parse(decodeURIComponent(options.msgInfo))
    queryRecordsByMsgInfo(msgInfo)
    state.value.useCustomLoadMore = true
    return
  }
  if (options.recordDate) {
    state.value.recordDate = options.recordDate
    const msgInfo = await findTalkRecords(options.recordDate, true)
    queryRecordsByMsgInfo(msgInfo)
    state.value.useCustomLoadMore = true
    return
  }
  initData()
})
uniOnUnload(() => {
  console.log('onUnload')
  ServeClearTalkUnreadNum(
    {
      talk_type: Number(talkParams.type),
      receiver_id: Number(talkParams.receiver_id),
    },
    talkParams.unReadNum,
  ).then(() => {
    talkStore.updateItem({
      index_name: talkParams.index_name,
      unread_num: 0,
    })
    dialogueStore.clearUnreadNum()
  })
})
const handleEmojiPanel = () => {
  state.value.isOpenFilePanel = false
  state.value.isOpenEmojiPanel = !state.value.isOpenEmojiPanel
}
const handleFilePanel = () => {
  state.value.isOpenEmojiPanel = false
  state.value.isOpenFilePanel = !state.value.isOpenFilePanel
}

//点击隐藏表情/文件上传 面板
const handleHidePanel = () => {
  state.value.isOpenFilePanel = false
  state.value.isOpenEmojiPanel = false
}

//点击编辑区聚焦输入框
const onEditorClick = () => {
  handleHidePanel()
  const quill = getQuill()
  // if (quill.getText().endsWith('@\n')) {
  //   showMentionSelectDebounced(quill)
  // }
  quill.focus()
}

const onSendMessage = (data = {}, callBack) => {
  let message = {
    ...data,
    receiver: {
      receiver_id: talkParams.receiver_id,
      talk_type: talkParams.type,
    },
  }

  ServePublishMessage(message)
    .then(({ code, message }) => {
      if (code == 200) {
        if (callBack) {
          callBack(true)
        }
      } else {
        message.warning(message)
      }
    })
    .catch(() => {
      message.warning('网络繁忙,请稍后重试!')
    })
}

const onSendMessageClick = () => {
  // 发送前确保 mentionUserIds 是最新的
  updateMentionUserIds()

  let delta = getQuill().getContents()
  if (state.value.quoteInfo) {
    delta.ops.unshift({
      insert: {
        quote: {
          id: state.value.quoteInfo.msg_id,
        },
      },
    })
  }
  let data = deltaToMessage(delta)

  if (data.items.length === 0) {
    return
  }

  switch (data.msgType) {
    case 1: // 文字消息
      if (data.items[0].content.length > 1024) {
        return message.info('发送内容超长,请分条发送')
      }
      onSendTextEvent({
        data,
        callBack: (ok) => {
          if (!ok) return
          getQuill().setContents([], Quill.sources.USER)
          if (state.value.quoteInfo) {
            state.value.quoteInfo = null
          }
        },
      })
      break
  }
}

// 发送文本消息
const onSendTextEvent = lodash.throttle((value) => {
  let { data, callBack } = value

  let message = {
    type: 'text',
    content: data.items[0].content,
    quote_id: data.quoteId,
    mentions: state.value.mentionUserIds, // 使用最终的用户ID数组
  }
  console.log(message)

  onSendMessage(message, callBack)
}, 1000)

// 编辑器输入事件
const onInputEvent = ({ data }) => {
  talkStore.updateItem({
    index_name: indexName.value,
    draft_text: data,
  })

  // 判断对方是否在线和是否需要推送
  // 3秒时间内推送一次
  if (settingsStore.isKeyboard && props.online) {
    onKeyboardPush()
  }
}

// 发送表情消息
const onSendEmoticonEvent = ({ data }) => {
  onSendMessage({ type: 'emoticon', emoticon_id: data })
}

// 注册事件
const evnets = {
  text_event: onSendTextEvent,
  input_event: onInputEvent,
  emoticon_event: onSendEmoticonEvent,
  history_event: () => {
    isShowHistory.value = true
  },
}

const {
  loadConfig,
  records,
  onLoad,
  onRefreshLoad,
  onJumpMessage,
} = useTalkRecord(talkParams.uid)

const getQuill = () => {
  return editor.value?.getQuill()
}

const isShowCopy = (item) => {
  switch (item.msg_type) {
    case 1:
      return true
    case 3:
      return true
    case 5:
      return true
    case 6:
      return true
    default:
      return false
  }
}

const selectedMessage = computed(() => {
  return virtualList.value.filter((item) => item.isCheck)
})

// 编辑器事件
const onEditorEvent = (msg) => {
  evnets[msg.event] && evnets[msg.event](msg)
}

const getQuillSelectionIndex = () => {
  let quill = getQuill()
  return (quill.getSelection() || {}).index
}

const onEmoticonEvent = (data) => {
  if (data.type == 1) {
    const quill = getQuill()
    let index = getQuillSelectionIndex()

    if (index == 1 && quill.getLength() == 1 && quill.getText(0, 1) == '\n') {
      quill.deleteText(0, 1)
      index = 0
    }
    if (data.img) {
      quill.insertEmbed(index, 'emoji', {
        alt: data.value,
        src: data.img,
      })
    } else {
      quill.insertText(index, data.value)
    }

    quill.setSelection(index + 1, 0, 'user')
  } else {
    let fn = emitCall('emoticon_event', data.value, () => {})
    emit('editor-event', fn)
  }
}

const onEditorChange = () => {
  if (getQuill().getText() !== state.value.lastMentionText) {
    state.value.lastMentionTriggered = false
  }
  let delta = getQuill().getContents()
  let text = deltaToString(delta)

  // 如果正在插入mention,不进行mention的检查和更新
  if (!state.value.isInsertingMention) {
    updateMentionUserIds()
  }

  if (!isEmptyDelta(delta)) {
    editorDraftStore.items[indexName.value || ''] = JSON.stringify({
      text: text,
      ops: delta.ops,
    })
  } else {
    // 删除 editorDraftStore.items 下的元素
    delete editorDraftStore.items[indexName.value || '']
  }
  onEditorEvent(emitCall('input_event', text))
  // emit('editor-event', emitCall('input_event', text))
  // 清理过期的撤回消息(超过5分钟)
  const now = new Date().getTime()
  Object.keys(state.value.revokedMessages || {}).forEach((msgId) => {
    if (now - state.value.revokedMessages[msgId].revokeTime > 5 * 60 * 1000) {
      delete state.value.revokedMessages[msgId]
    }
  })
}

const onClipboardMatcher = (node, Delta) => {
  const ops = []

  Delta.ops.forEach((op) => {
    // 如果粘贴了图片,这里会是一个对象,所以可以这样处理
    if (op.insert && typeof op.insert === 'string') {
      ops.push({
        insert: op.insert, // 文字内容
        attributes: {}, //文字样式(包括背景色和文字颜色等)
      })
    } else {
      ops.push(op)
    }
  })

  Delta.ops = ops
  return Delta
}

const editorOption = {
  debug: false,
  modules: {
    toolbar: false,
    clipboard: {
      // 粘贴版,处理粘贴时候的自带样式
      matchers: [[Node.ELEMENT_NODE, onClipboardMatcher]],
    },

    keyboard: {
      bindings: {
        enter: {
          key: 13,
          handler: onSendMessageClick,
        },
      },
    },

    // imageUploader: {
    //   upload: onEditorUpload
    // },

    mention: {
      allowedChars: /^[\u4e00-\u9fa5]*$/,
      mentionDenotationChars: ['@'],
      positioningStrategy: 'fixed',
      renderItem: (data) => {
        const el = document.createElement('div')
        el.className = 'ed-member-item'
        el.innerHTML += `<span class="nickname">${data.nickname}</span>`
        return el
      },
      source: function (searchTerm, renderList, mentionChar) {
        if (talkParams.type === 1) {
          return
        }
        // 在失焦前保存光标位置
        const quill = getQuill()
        const range = quill.getSelection()
        if (range) {
          state.value.lastCursorIndex = range.index
        }

        // 使用防抖函数
        showMentionSelectDebounced(quill)
      },
      mentionContainerClass: '',
    },
  },
  placeholder: '',
}

const handleSelectImg = (data, file_num) => {
  onSendMessage({ ...data, file_num })
}

const virtualListChange = (vList) => {
  virtualList.value = vList
}

const onContextMenu = (menuType, item) => {
  console.log(menuType, item, 'item')
  switch (menuType) {
    case 'actionCopy':
      actionCopy(item)
      break
    case 'multipleChoose':
      multipleChoose(item)
      break
    case 'actionCite':
      actionCite(item)
      break
    case 'actionWithdraw':
      actionWithdraw(item)
      break
    case 'actionDelete':
      actionDelete(item)
      break

    default:
      break
  }
}

const actionCopy = (item) => {
  console.log('复制')
  let content = ''
  switch (item.msg_type) {
    case 1:
      content = item.extra.content
      break
    case 3:
      content = item.extra.url
      break
    case 5:
      content = item.extra.url
      break

    default:
      break
  }
  uni.setClipboardData({
    data: content,
  })
}

const multipleChoose = (item) => {
  item.isCheck = true
  dialogueStore.setMultiSelect(true)
}

const actionCite = (item) => {
  console.log('引用')
  state.value.quoteInfo = item
}

//清除引用信息
const clearQuoteInfo = () => {
  state.value.quoteInfo = null
}

const actionWithdraw = (item) => {
  console.log('撤回')
  state.value.onfocusItem = item
  state.value.showWin = true
}

const withdrawerConfirm = () => {
  dialogueStore.ApiRevokeRecord(state.value.onfocusItem.msg_id)
  state.value.onfocusItem = null
  state.value.showWin = false
}

// 添加检查是否可以重新编辑撤回消息的函数
const canEditRevokedMessage = (item) => {
  // console.log(item)
  if (item.is_revoke === 1 && item.msg_type === 1) {
    const now = new Date().getTime()
    const revokeTime = new Date(item.created_at).getTime()
    // console.log(now)
    // 检查是否在5分钟内
    return now - revokeTime <= 5 * 60 * 1000
  }
  return false
}

// 添加恢复撤回消息到输入框的函数
const restoreRevokedMessage = async (item) => {
  // 接口拿数据,之后把查询的内容给输入框
  const res = await detailGetRecordsContext({
    msgId: item.msg_id,
  })
  console.log(res)
  if (res.code == 200) {
    const content = res.data.item?.extra?.content
    const quill = getQuill()
    quill.setText(content)
    // 将光标设置到文本末尾
    quill.setSelection(content.length, 0)
    quill.focus()
  }
  /* const revokedMsg = state.value.revokedMessages[msgId]

  // 根据消息类型处理
  if (revokedMsg.msgType === 1) { // 文本消息
    const quill = getQuill()
    quill.setText(revokedMsg.content)
    quill.focus()
  } */
  // 可以根据需要添加其他类型消息的处理
}

const actionDelete = (item) => {
  console.log('删除')
  item.isCheck = true
  handleDelete()
}

const handleMergeForward = () => {
  if (selectedMessage.value.length == 0) {
    return message.warning('未选择消息')
  }
  console.log('合并转发')
  dialogueStore.setForwardType(2)
  dialogueStore.setForwardMessages(selectedMessage.value)
  uni.navigateTo({
    url: '/pages/chooseChat/index',
    success: function (res) {
      clearMultiSelect()
    },
  })
}

const handleSingleForward = () => {
  if (selectedMessage.value.length == 0) {
    return message.warning('未选择消息')
  }
  console.log('逐条转发')
  dialogueStore.setForwardType(1)
  dialogueStore.setForwardMessages(selectedMessage.value)
  uni.navigateTo({
    url: '/pages/chooseChat/index',
    success: function (res) {
      clearMultiSelect()
    },
  })
}

const handleWechatForward = () => {
  if (selectedMessage.value.length == 0) {
    return message.warning('未选择消息')
  }
  console.log('微信转发')
}

const handleDelete = () => {
  if (selectedMessage.value.length == 0) {
    return message.warning('未选择消息')
  }
  console.log('删除')
  showConfirm({
    content: '确定删除聊天记录',
    confirmText: '删除',
    confirmColor: '#CF3050',
    onConfirm: async () => {
      const msgIds = selectedMessage.value.map((item) => item.msg_id)
      virtualList.value = virtualList.value.filter(
        (item) => !msgIds.includes(item.msg_id),
      )
      dialogueStore.ApiDeleteRecord(msgIds)
      clearMultiSelect()
    },
    onCancel: () => {},
  })
}

//更新选中的要提醒的人数
const updateSelectedMembersNum = (numChange) => {
  state.value.selectedMembersNum = state.value.selectedMembersNum + numChange
}

watch(
  () => zpagingRef.value,
  (newValue, oldValue) => {
    if (newValue) {
      updateZpagingRef(newValue)
    }
  },
)

watch(
  () => virtualList.value,
  (newValue, oldValue) => {
    if (newValue) {
      const dialogueList = getDialogueList(talkParams.index_name)
      // console.log(newValue[newValue.length - 1]?.sequence, dialogueList?.records?.[0]?.sequence)
      if (!dialogueList || dialogueList?.length === 0) {
        state.value.localPageLoadDone = true
        return
      }
      // 只在正常加载模式下检查是否加载完缓存数据
      if (!state.value.useCustomLoadMore) {
        if (
          newValue[newValue.length - 1]?.sequence ===
          dialogueList?.records?.[0]?.sequence
        ) {
          if (
            dialogueList?.records?.[0]?.sequence !== 1 &&
            !state.value.localPageLoadDone
          ) {
            loadConfig.status = 1
          }
          //相同意味着分页加载缓存中的聊天记录完毕
          state.value.localPageLoadDone = true
        } else {
          state.value.localPageLoadDone = false
        }
      }
    }
  },
  {
    deep: true,
  },
)

const onScrollToLower = async () => {
  if (state.value.useCustomLoadMore) {
    const tempVirtualList = lodash.cloneDeep(virtualList.value).reverse()
    const dialogueList = getDialogueList(talkParams.index_name)
    const recordIndex = dialogueList?.records?.findIndex(
      (record) => record.msg_id === tempVirtualList[0].msg_id,
    )
    if (!recordIndex || recordIndex === -1) {
      const moreRecords = await findTalkRecords(
        '',
        false,
        tempVirtualList[0].sequence,
        {
          direction: 'up',
          sort_sequence: '',
        },
      )
      console.log(moreRecords)

      // 格式化新加载的消息
      const formattedMoreRecords = moreRecords.map((item) => ({
        ...item,
        float: item.user_id === talkParams.uid ? 'right' : 'left',
      }))

      virtualList.value = formattedMoreRecords.concat(tempVirtualList).reverse()
      loadConfig.status =
        dialogueList?.records?.[0]?.sequence > 1 && moreRecords.length > 0
          ? 1
          : 2
    } else {
      if (tempVirtualList[0].sequence > dialogueList.records[0].sequence) {
        virtualList.value = dialogueList.records
          .slice(Math.max(0, recordIndex - 10), recordIndex)
          .concat(tempVirtualList)
          .reverse()
        // zpagingRef.value.setLocalPaging(
        //   dialogueList.records
        //     .slice(0, recordIndex)
        //     .concat(tempVirtualList)
        //     .reverse(),
        //   // zpagingRef.value.scrollIntoViewById('zp-id-' + virtualList.value[virtualList.value.length - 1].msg_id)
        // )

        console.log(virtualList.value)
      }
    }
    return
  }
  if (state.value.localPageLoadDone) {
    //本地缓存的聊天记录分页加载完之后,才可以请求接口
    onRefreshLoad()
  }
}

//本来的下拉刷新——列表倒置后为上拉加载
const onScrollToUpper = async () => {
  if (state.value.useCustomLoadMore) {
    const tempVirtualList = lodash.cloneDeep(virtualList.value).reverse()
    const dialogueList = getDialogueList(talkParams.index_name)
    const recordIndex = dialogueList?.records?.findIndex(
      (record) =>
        record.msg_id === tempVirtualList[tempVirtualList.length - 1].msg_id,
    )
    console.log(recordIndex)
    if (!recordIndex || recordIndex === -1) {
      // 记住加载更多前消息的ID
      const currentMsgId = tempVirtualList[tempVirtualList.length - 1].msg_id
      const moreRecords = await findTalkRecords(
        '',
        false,
        tempVirtualList[tempVirtualList.length - 1].sequence,
      )
      console.log(moreRecords)

      // 格式化新加载的消息
      const formattedMoreRecords = moreRecords.map((item) => ({
        ...item,
        float: item.user_id === talkParams.uid ? 'right' : 'left',
      }))

      virtualList.value = tempVirtualList
        .concat(formattedMoreRecords.reverse())
        .reverse()

      console.log(virtualList.value)

      // 数据更新后,滚动到之前的位置
      nextTick(() => {
        zpagingRef.value?.scrollIntoViewById('zp-id-' + currentMsgId)
      })
    } else {
      if (
        tempVirtualList[tempVirtualList.length - 1].sequence <
        dialogueList.records[dialogueList.records.length - 1].sequence
      ) {
        // 记住加载更多前消息的ID
        const currentMsgId = tempVirtualList[tempVirtualList.length - 1].msg_id

        virtualList.value = tempVirtualList
          .concat(
            dialogueList.records.slice(
              recordIndex + 1,
              Math.min(recordIndex + 11, dialogueList.records.length),
            ),
          )
          .reverse()

        // 数据更新后,滚动到之前的位置
        nextTick(() => {
          zpagingRef.value?.scrollIntoViewById('zp-id-' + currentMsgId)
        })
      }
    }
  }
}

const clearMultiSelect = () => {
  dialogueStore.setMultiSelect(false)
  virtualList.value.forEach((item) => {
    item.isCheck = false
  })
}

const initData = async () => {
  const dialogueList = getDialogueList(talkParams.index_name)

  let objT = {
    uid: talkParams.uid,
    talk_type: talkParams.type,
    receiver_id: talkParams.receiver_id,
    index_name: talkParams.index_name,
    direction: dialogueList ? 'down' : 'up',
    no_limit: dialogueList ? 1 : 0,
  }
  await onLoad({ ...objT })
  zpagingRef.value?.setLocalPaging(records.value)
}

//点击跳转到聊天设置页面
const toChatSettingsPage = () => {
  uni.navigateTo({
    url:
      '/pages/chatSettings/index?groupId=' +
      talkParams?.receiver_id +
      '&sessionId=' +
      state.value.sessionId,
  })
}

//点击跳转到用户详情页面
const toUserDetailPage = (userItem) => {
  uni.navigateTo({
    url:
      '/pages/dialog/dialogDetail/userDetail?erpUserId=' + userItem.erp_user_id,
  })
}

//切换提醒的人选择弹窗多选状态
const changeMentionSelectMul = (status) => {
  state.value.mentionIsMulSelect = status
}

//隐藏要提醒人的选择
const hideMentionSelect = () => {
  state.value.isShowMentionSelect = false
  // 清除保存的光标位置
  state.value.lastCursorIndex = undefined
  // 获得焦点
  const quill = getQuill()
  quill.focus()
}

//确认要提醒人的选择
const confirmMentionSelect = () => {
  if (state?.value.selectedMembersNum > 0) {
    if (selectMemberByAlphabetRef.value) {
      selectMemberByAlphabetRef.value.confirmSelectMembers()
    }
    hideMentionSelect()
  }
}

//获取选择的结果
const getSelectResult = (mentionSelect) => {
  console.log(mentionSelect)
  getMentionSelectLists(mentionSelect)
}

//处理要提醒人的消息样式
const getMentionSelectLists = (mentionSelectList) => {
  const quill = getQuill()
  const mention = quill.getModule('mention')

  // 使用之前保存的光标位置
  if (state.value.lastCursorIndex !== undefined) {
    // 删除光标前的 @ 符号
    quill.deleteText(state.value.lastCursorIndex - 1, 1)
  }

  // 设置正在插入mention的标记
  state.value.isInsertingMention = true

  // 逐个插入mention
  mentionSelectList.forEach((mentionSelectItem) => {
    // 如果是@所有人,确保 id 为 0
    const id =
      mentionSelectItem?.nickname === '所有人' ? 0 : mentionSelectItem?.id
    mention.insertItem(
      {
        id: id,
        denotationChar: '@',
        value: mentionSelectItem?.nickname + ' ',
      },
      true,
    )
  })

  // 将光标设置到文本末尾
  const length = quill.getLength()
  quill.setSelection(length, 0)

  // 清除保存的光标位置
  state.value.lastCursorIndex = undefined

  // 延迟清除插入mention的标记并手动触发一次内容更新
  setTimeout(() => {
    state.value.isInsertingMention = false
    // 手动触发一次内容更新,确保 mentionUserIds 是最新的
    updateMentionUserIds()
  }, 100)

  hideMentionSelect()
}

// 新增一个更新 mentionUserIds 的函数
const updateMentionUserIds = () => {
  const delta = getQuill().getContents()
  const ops = delta.ops || []
  const currentMentions = new Set()

  // 收集当前所有@的用户ID,并转换为number类型
  ops.forEach((op) => {
    if (op.insert && op.insert.mention) {
      const id = Number(op.insert.mention.id)
      // 过滤掉 null 值
      if (!isNaN(id)) {
        currentMentions.add(id)
      }
    }
  })

  // 如果当前有@所有人,则添加0
  if (currentMentions.has(0)) {
    state.value.mentionUserIds = [0]
  } else {
    // 如果没有@任何人,保持空数组
    state.value.mentionUserIds = Array.from(currentMentions)
  }
}

//根据msg信息找到对应的聊天记录,并根据sequence等查看上下文
const queryRecordsByMsgInfo = async (msgInfo) => {
  console.log(msgInfo)
  state.value.middleMsg = msgInfo
  const dialogueList = getDialogueList(talkParams.index_name)
  const recordIndex = dialogueList?.records?.findIndex(
    (record) => record.msg_id === msgInfo.msg_id,
  )
  let recordsList = []
  console.log(recordIndex)
  if (!recordIndex || recordIndex === -1) {
    recordsList = await findTalkRecords('', true, msgInfo.sequence)
  } else {
    // console.log(recordIndex)
    const startRecordIndex = Math.max(0, recordIndex - 10)
    const endRecordIndex = Math.max(0, recordIndex + 10)
    // console.log(dialogueList.records.slice(startRecordIndex, endRecordIndex))
    // console.log(recordIndex-startRecordIndex)
    recordsList = dialogueList.records.slice(startRecordIndex, endRecordIndex)
  }

  // 格式化消息,确保每条消息都有正确的 float
  recordsList = recordsList.map((item) => {
    return {
      ...item,
      float: item.user_id === talkParams.uid ? 'right' : 'left',
    }
  })

  nextTick(() => {
    zpagingRef.value.complete(recordsList.reverse())
    loadConfig.status =
      dialogueList?.records?.[0]?.sequence > 1 && recordsList.length > 0 ? 1 : 2
    nextTick(() => {
      let offset = uni.getSystemInfoSync().windowHeight
      const navBarAreaQuery = uni.createSelectorQuery()
      navBarAreaQuery
        .select('#navBarArea')
        .boundingClientRect((res) => {
          if (res) {
            // console.log('元素高度:', res.height)
            offset = offset - res.height
          }
        })
        .exec()
      const footBoxAreaQuery = uni.createSelectorQuery()
      footBoxAreaQuery
        .select('#footBoxArea')
        .boundingClientRect((res) => {
          if (res) {
            // console.log('元素高度:', res.height)
            offset = offset - res.height
          }
        })
        .exec()
      setTimeout(() => {
        zpagingRef.value.scrollIntoViewById(
          'zp-id-' + msgInfo.msg_id,
          offset - 60,
        )
      }, 1000)
    })
  })
}

//查找聊天记录
const findTalkRecords = (record, isMiddle, sequence, appointParams) => {
  return new Promise((resolve, reject) => {
    let params = {
      talk_type: talkParams.type, //1私聊;2群聊
      receiver_id: talkParams.receiver_id, //目标用户id或群聊id
      no_limit: '', //1不限制
      file_name: '',
      msg_type: 0, //消息类型:0:全部;2:代码;3:图片;4:音频;5:视频;6:文件;7:位置;9:会话;11群投票;12图文混合
      cursor: sequence || 0, //上次查询的游标
      limit: 10, //数据行数
      direction: 'down', //down向下查最新,up向上查老数据
      start_time: '',
      end_time: '',
      group_member_user_id: 0, //群成员id,当查询群历史消息的时候,需要指定群成员的时候送
      sort_sequence: 'asc',
      create_time: state.value.middleMsg.created_at,
    }
    if (record) {
      params = Object.assign({}, params, {
        start_time: record,
        end_time: record,
        limit: 1,
        direction: '',
      })
    }
    if (appointParams) {
      params = Object.assign({}, params, appointParams)
    }
    console.log(params)
    const resp = ServeTalkRecords(params)
    console.log(resp)
    resp.then(({ code, data }) => {
      console.log(data)
      if (code == 200) {
        if (data?.items.length > 0) {
          if (record) {
            resolve(data?.items[0])
            return
          }
          if (isMiddle) {
            state.value.serveFindRecord = JSON.parse(
              JSON.stringify(data?.items),
            )
            return findTalkRecords('', false, sequence + 1, {
              direction: 'up',
              sort_sequence: '',
            }).then((finalResult) => {
              console.log(finalResult)
              resolve(finalResult)
            })
          } else {
            state.value.serveFindRecord = data?.items
              .reverse()
              .concat(state.value.serveFindRecord)
            resolve(JSON.parse(JSON.stringify(state.value.serveFindRecord)))
            state.value.serveFindRecord = []
          }
        } else {
          resolve([])
        }
      } else {
        resolve([])
      }
    })
    resp.catch(() => {})
  })
}

//是否是管理员
const isLeader = computed(() => {
  if (talkParams.adminList.length > 0) {
    return (
      talkParams.adminList.filter(
        (adminItem) => adminItem.erp_user_id === useAuth()?.userInfo?.value?.ID,
      ).length > 0
    )
  }
  return false
})

//长按头像@用户
const doMentionUser = (mentionSelect) => {
  console.log(mentionSelect)
  // 构造正确的 mention 对象
  const mentionObj = {
    id: mentionSelect.user_id, // 使用 user_id 而不是 erp_user_id
    nickname: mentionSelect.nickname,
  }
  getMentionSelectLists([mentionObj])
}

let avatarPressTimer = null
let currentPressItem = null

const handleAvatarTouchStart = (item) => {
  currentPressItem = item
  avatarPressTimer = setTimeout(() => {
    doMentionUser(item)
  }, 500)
}

const handleAvatarTouchEnd = () => {
  if (avatarPressTimer) {
    clearTimeout(avatarPressTimer)
    avatarPressTimer = null
  }
  currentPressItem = null
}

onMounted(async () => {
  if (typeof plus !== 'undefined') {
    const webview = plus.webview.currentWebview()
    webview.setStyle({
      bottom: 0,
    })
  } else {
    document.addEventListener('plusready', () => {
      const webview = plus.webview.currentWebview()
      webview.setStyle({
        bottom: 0,
      })
    })
  }
  nextTick(() => {
    state.value.mentionSelectHeight = pxTorPx(
      uni.getSystemInfoSync().windowHeight * 0.86,
    )

    state.value.selectAreaHeight =
      rpxToPx(state.value.mentionSelectHeight) - rpxToPx(90) + 'px'
  })
})

const pxTorPx = (px) => {
  const sysInfo = uni.getSystemInfoSync()
  const rpx = px / (sysInfo.screenWidth / 750)
  return rpx
}

const rpxToPx = (rpx) => {
  const sysInfo = uni.getSystemInfoSync()
  const px = (sysInfo.screenWidth / 750) * rpx
  return px
}

onUnmounted(() => {
  if (!state.value.keepDialogInfo) {
    dialogueStore.setDialogue({})
  }
  clearMultiSelect()
  if (avatarPressTimer) {
    clearTimeout(avatarPressTimer)
  }
  // 清理防抖定时器
  if (state.value.showMentionSelectTimer) {
    clearTimeout(state.value.showMentionSelectTimer)
  }
})

// 修改防抖函数的实现
const showMentionSelectDebounced = (quill) => {
  const text = quill.getText()
  // 如果文本内容与上次不同,重置触发状态

  if (text !== state.value.lastMentionText) {
    state.value.lastMentionTriggered = false
  }

  // 如果已经触发过,则不再触发
  if (state.value.lastMentionTriggered) {
    console.log('return')
    return
  }

  // 记录当前文本内容和触发状态
  state.value.lastMentionText = text
  state.value.lastMentionTriggered = true
  state.value.isShowMentionSelect = true
  quill.blur()
}
</script>
<style scoped lang="less">
.dialog-page {
  flex: 1;
  background-image: url('@/static/image/clockIn/z3280@3x.png');
  background-size: cover;
  background-position: bottom center;
  background-attachment: scroll;
  width: 100%;

  .dialog-list {
    padding: 20rpx 32rpx;
  }

  .toChatSetting_btn {
    ::v-deep .tmicon-gengduo {
      line-height: unset !important;
    }
  }
}

.edit-revoked-message {
  margin-left: 10rpx;
  color: #46299d;
  cursor: pointer;
  font-size: 24rpx;

  &:hover {
    text-decoration: underline;
  }
}

.searchRoot {
  background-color: #fff;
  padding: 22rpx 18rpx;
}

.contentRoot {
  margin-top: 20rpx;
  background-color: #fff;
}

.footBox {
  min-height: 162rpx;
  background-color: #fff;

  .quote-area {
    margin: 4rpx 0 0 0;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    overflow: hidden;
    width: 100%;

    span {
      display: -webkit-inline-box;
      text-overflow: ellipsis;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      width: 100%;
      word-break: break-all;
    }

    img {
      margin: 0 0 0 30rpx;
      flex-shrink: 0;
    }
  }
}

.load-toolbar {
  height: 50rpx;
  color: #409eff;
  text-align: center;
  line-height: 50rpx;
  font-size: 24rpx;

  .no-more {
    color: #b9b3b3;
  }
}

.message-item {
  &.border {
    border-radius: 16rpx;
  }
}

.message-box {
  width: 100%;
  min-height: 30rpx;
  margin-bottom: 5rpx;
}

.record-box {
  display: flex;
  flex-direction: row;
  align-items: flex-start;

  .checkbox-column {
    display: flex;
    justify-content: center;
    width: 42rpx;
    order: 1;
    user-select: none;
    margin-top: 20rpx;
    margin-right: 20rpx;
  }

  .avatar-column {
    width: 80rpx;
    display: flex;
    align-items: center;
    order: 2;
    user-select: none;
    margin-top: 16rpx;
    flex-direction: column;
  }

  .main-column {
    flex: 1 auto;
    order: 3;
    position: relative;
    box-sizing: border-box;
    padding: 16rpx 20rpx 14rpx 20rpx;
    // overflow: hidden;
    min-height: 30px;

    .talk-title {
      display: flex;
      align-items: center;
      margin-bottom: 6rpx;
      font-size: 24rpx;
      user-select: none;
      color: #bababa;
      opacity: 1;

      &.show {
        opacity: 1;
      }

      .nickname {
        color: var(--im-text-color);
        margin-right: 5rpx;

        .at {
          display: none;
        }

        &:hover {
          color: var(--im-primary-color);

          .at {
            display: inline-block;
          }
        }
      }

      span {
        transform: scale(0.88);
        transform-origin: left center;
      }
    }

    .talk-content {
      display: flex;
      justify-content: flex-start;
      align-items: flex-end;

      box-sizing: border-box;
      width: 100%;

      .talk-tools {
        display: flex;
        margin: 0 16rpx;
        color: #a79e9e;
        font-size: 24rpx;
        user-select: none;
        align-items: center;
        justify-content: space-around;

        .more-tools {
          visibility: hidden;
          margin-left: 5rpx;
        }
      }
    }

    .talk-reply {
      display: flex;
      align-items: flex-start;
      align-items: center;
      width: fit-content;
      padding: 8rpx;
      margin-top: 6rpx;
      margin-right: auto;
      font-size: 24rpx;
      color: #8f8f8f;
      word-break: break-all;
      background-color: var(--im-message-left-bg-color);
      border-radius: 10rpx;
      max-width: 450rpx;
      overflow: hidden;
      user-select: none;

      .icon-top {
        margin-right: 6rpx;
      }

      .ellipsis {
        display: -webkit-inline-box;
        text-overflow: ellipsis;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        overflow: hidden;
      }
    }

    &:hover {
      .talk-title {
        opacity: 1;
      }

      .more-tools {
        visibility: visible !important;
      }
    }
  }

  &.direction-rt {
    .avatar-column {
      order: 3;
    }

    .main-column {
      order: 2;

      .talk-title {
        justify-content: flex-end;

        span {
          transform-origin: right center;
        }
      }

      .talk-content {
        flex-direction: row-reverse;
      }

      .talk-reply {
        margin-right: 0;
        margin-left: auto;
      }
    }
  }

  &.multi-select {
    border-radius: 5px;

    &:hover,
    &.multi-select-check {
      background-color: var(--im-active-bg-color);
    }
  }
}

.content-placeholder {
  height: 58rpx;
}

.quillBox {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;

  :deep(.ql-clipboard) {
    position: relative;
    opacity: 0;
    height: 1rpx;
    overflow: auto;
  }

  :deep(.ql-editor) {
    padding: 14rpx 22rpx;
    background-color: #f9f9f9;
    border-radius: 8rpx;
    outline: none !important;
    max-height: 294rpx;
    overflow: auto;
    line-height: 44rpx;
    font-size: 32rpx;

    p {
      display: inline-flex;
      align-items: center;
      justify-content: flex-start;
      flex-wrap: wrap;
      white-space: normal;
      word-break: break-all;

      .ed-emoji {
        width: 44rpx;
        height: 44rpx;
        display: inline-block;
      }

      span {
        user-select: all;
      }
    }
  }
}

:deep(.wd-action-sheet) {
  background-color: #8b8b8b !important;
}

:deep(.wd-action-sheet__panel-title) {
  color: #fff !important;
}

.component-content {
  position: relative;
  z-index: 1;
  /* 确保 z-index 低于 deepBubble */
}

.divider {
  width: 100%;
  height: 1rpx;
  background-color: #e7e7e7;
}

.mention-select-drawer {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  padding: 36rpx 32rpx 0;

  .cancel-btns {
    flex-shrink: 0;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;

    .hide-btn {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      position: relative;

      text {
      }

      img {
        width: 18rpx;
        height: 10rpx;
      }
    }
  }

  .mention-done-btn {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding: 6rpx 24rpx;
    background-color: #f3f3f3;
    border-radius: 8rpx;
    flex-shrink: 0;

    span {
      color: #bababa;
      line-height: 40rpx;
      flex-shrink: 0;
    }
  }

  .mention-done-btn-can-do {
    background-color: #46299d;

    span {
      color: #fff;
    }
  }

  .mention-edit-btn {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    flex-shrink: 0;

    span {
      flex-shrink: 0;
    }
  }
}

:deep(.mention) {
  color: #1890ff;
}
</style>