<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="用户ID" prop="fsUserId">
        <el-input
          v-model="queryParams.fsUserId"
          @input="queryParams.fsUserId = queryParams.fsUserId.replace(/[^\d]/g, '')"
          placeholder="请输入用户ID"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="客服" prop="customerRoles">
        <div @click="openCusSearchPage"
             style="cursor: pointer; border: 1px solid #e6e6e6; background-color: white; overflow: hidden; flex-grow: 1;width: 250px">
          <div style="min-height: 35px; max-height: 200px; overflow-y: auto;">
            <el-tag type="success"
                    closable
                    :disable-transitions="false"
                    v-for="list in this.customerRoleSearch.selected"
                    :key="list.id"
                    @close="handleCloseCus(list)"
                    style="margin: 3px;"
            >{{ list.roleName }}
            </el-tag>
          </div>
        </div>
      </el-form-item>
      <el-form-item label="类别" prop="type">
        <el-select v-model="queryParams.type" placeholder="请选择类别" clearable size="small">
          <el-option v-for="dict in typeOptions" :key="dict.dictValue" :label="dict.dictLabel"
                     :value="dict.dictValue" />
        </el-select>
      </el-form-item>

      <el-form-item label="处理状态" prop="trackType">
        <el-select v-model="queryParams.trackType" placeholder="处理状态" clearable size="small">
          <el-option v-for="dict in trackTypeOptions" :key="dict.dictValue" :label="dict.dictLabel"
                     :value="dict.dictValue" />
        </el-select>
      </el-form-item>
      <el-form-item label="sop编号" prop="sopId">
        <el-input v-model="queryParams.sopId" placeholder="请输入sopid" clearable size="small"
                  @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item label="标题" prop="title">
        <el-input v-model="queryParams.title" placeholder="请输入标题" clearable size="small"
                  @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item label="创建日期" prop="crtTime">
        <el-date-picker size="small" v-model="queryParams.crtTime"  type="date" placeholder="选择日期"
                        value-format="yyyy-MM-dd" format="yyyy-MM-dd" @change="handleQuery">
        </el-date-picker>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="isSM = !isSM">色盲模式</el-button>
      </el-form-item>
    </el-form>

    <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"/>

    <el-tabs type="card" v-model="actName" @tab-click="toggleTab">
      <el-tab-pane v-for="(item, index) in statusOptions" :label="item.dictLabel"
                   :name="item.dictValue"></el-tab-pane>
    </el-tabs>

    <el-table border v-loading="loading" :data="urgentClassTaskList">
      <el-table-column label="用户ID" align="center" prop="fsUserId" min-width="120"/>
      <el-table-column label="用户名称" align="center" prop="userName" min-width="120"/>
      <el-table-column label="客服名称" align="center" prop="customerRoleName" min-width="180">
        <template slot-scope="scope">
          <el-tag type="primary" style="margin: 3px;">{{ scope.row.customerRoleName }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="状态" align="center" prop="status" min-width="120">
        <template slot-scope="scope">
          <dict-tag :options="statusOptions" :value="scope.row.status != null ? scope.row.status.toString() : null" />
        </template>
      </el-table-column>
      <el-table-column label="类别" align="center" prop="type" min-width="120">
        <template slot-scope="scope">
          <dict-tag :options="typeOptions" :value="scope.row.type" />
        </template>
      </el-table-column>
      <el-table-column label="处理状态" align="center" prop="trackType" min-width="120">
        <template slot-scope="scope">
          <dict-tag :options="trackTypeOptions" :value="scope.row.trackType"/>
        </template>
      </el-table-column>
      <el-table-column label="标题" align="center" prop="title" min-width="150"/>
      <el-table-column label="描述" align="center" prop="remark" />
<!--      <el-table-column label="分值" align="center" prop="score" min-width="150">-->
<!--        <template slot-scope="scope">-->
<!--          <span :style="getScoreStyle(scope.row.score)">{{ scope.row.score }}</span>-->
<!--        </template>-->
<!--      </el-table-column>-->
      <el-table-column label="用户过往学习记录" align="center" min-width="200">
        <template slot-scope="scope">
          <div v-if="isSM" style="display: flex; gap: 4px; justify-content: center;">
                        <span v-for="(log, index) in scope.row.userWatchLogs" :key="index" :style="{
                            display: 'inline-block',
                            width: '16px',
                            height: '16px',
                            borderRadius: log == 2 ? '50%' : log == 4 ? '2px 8px' : '2px',
                            backgroundColor: log == 3 ? 'transparent' : '#f0f0f0',
                            border: log == 3 ? '2px solid #666' : '1px solid #ddd',
                            position: 'relative',
                            transform: log == 4 ? 'rotate(45deg)' : 'none'
                        }">
                            <!-- 已完成 - 圆形 + 对勾 -->
                            <span v-if="log == 2" style="
                                position: absolute;
                                top: 45%;
                                left: 50%;
                                width: 6px;
                                height: 3px;
                                border: solid #333;
                                border-width: 0 0 2px 2px;
                                transform: translate(-50%, -50%) rotate(-45deg);
                            "></span>

                          <!-- 待学习 - 方框 + 叉（与底部图例一致） -->
                            <span v-if="log == 3" style="
                                position: absolute;
                                top: 50%;
                                left: 50%;
                                width: 8px;
                                height: 2px;
                                background: #666;
                                transform: translate(-50%, -50%) rotate(45deg);">
                            </span>
                            <span v-if="log == 3" style="
                                position: absolute;
                                top: 50%;
                                left: 50%;
                                width: 8px;
                                height: 2px;
                                background: #666;
                                transform: translate(-50%, -50%) rotate(-45deg);">
                            </span>


                            <span v-if="log == 1" style="
                                position: absolute;
                                top: 50%;
                                left: 50%;
                                width: 8px;
                                height: 2px;
                                background: #666;
                                transform: translate(-50%, -10%) rotate(-15deg);
                            "></span>

                          <!-- 部分完成 - 菱形 -->
                            <span v-if="log == 4" style="
                                position: absolute;
                                top: 50%;
                                left: 50%;
                                width: 6px;
                                height: 6px;
                                border: 2px solid #333;
                                transform: translate(-50%, -50%) rotate(-45deg);
                            "></span>

                          <!-- 未开始 - 减号 -->
                            <span v-if="!log" style="
                                position: absolute;
                                top: 50%;
                                left: 50%;
                                width: 8px;
                                height: 2px;
                                background: #999;
                                transform: translate(-50%, -50%);
                            "></span>

                          <!-- 图像 - 使用img标签 -->
                            <img v-if="log == 5" src="/path/to/your-image.png" alt="Custom icon" style="
                                position: absolute;
                                top: 50%;
                                left: 50%;
                                width: 12px;
                                height: 12px;
                                transform: translate(-50%, -50%);
                            ">
                        </span>
          </div>

          <div v-else style="display: flex; gap: 4px; justify-content: center;">
                        <span v-for="(log, index) in scope.row.userWatchLogs" :key="index" :style="{
                            display: 'inline-block',
                            width: '16px',
                            height: '16px',
                            borderRadius: '2px',
                            backgroundColor:
                                log == 2 ? '#67C23A' :
                                    log == 3 ? '#f55a4f' :
                                        log == 4 ? '#FFD700' :
                                            log == 1 ? '#0bc6ff' :
                                                '#909399'
                        }"></span>
          </div>

        </template>
      </el-table-column>
      <el-table-column label="最近章节" align="center" min-width="150">
        <template slot-scope="scope">
          {{ scope.row.latestCourseName }}
        </template>
      </el-table-column>
      <el-table-column label="最晚学习时间" align="center" min-width="150">
        <template slot-scope="scope">
          {{ formatTime(scope.row.lastWatchDate) }}
        </template>
      </el-table-column>

      <el-table-column label="sopId" align="center" prop="sopId" min-width="160"/>
      <el-table-column label="创建时间" align="center" prop="createTime" min-width="150"/>
      <el-table-column label="修改时间" align="center" prop="updateTime" min-width="150"/>
      <el-table-column label="操作" align="center" fixed="right" min-width="150">
        <template slot-scope="scope">
          <el-button
            v-if="scope.row.status == 0"
            size="mini"
            type="text"
            @click="toggleStatus(scope.row, 1)"
            v-hasPermi="['app:urgentClass:handle']"
          >
            点击处理
          </el-button>
<!--          <el-button-->
<!--            v-if="scope.row.status == 0"-->
<!--            size="mini"-->
<!--            type="text"-->
<!--            @click="quickReply(scope.row)"-->
<!--            v-hasPermi="['app:urgentClass:quickReply']"-->
<!--          >-->
<!--            快速回复-->
<!--          </el-button>-->
<!--          <el-button-->
<!--            size="mini"-->
<!--            type="text"-->
<!--            :loading="imLoading && loadingRowId === scope.row.customerRoleId"-->
<!--            :disabled="imLoading"-->
<!--            @click="loginIm(scope.row)"-->
<!--            v-hasPermi="['app:urgentClass:talk']"-->
<!--          >-->
<!--            聊天-->
<!--          </el-button>-->
<!--          <el-button-->
<!--            v-if="scope.row.fsUserId && scope.row.fsUserId !== ''"-->
<!--            size="mini"-->
<!--            type="text"-->
<!--            @click="handleCallPhone(scope.row)"-->
<!--            v-hasPermi="['app:urgentClass:getFsUserPhone']"-->
<!--          >-->
<!--            外呼-->
<!--          </el-button>-->
<!--          <el-button-->
<!--            size="mini"-->
<!--            type="text"-->
<!--            @click="handledetails(scope.row)"-->
<!--          >详情</el-button>-->
        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
                @pagination="getList" />

    <!-- 新增的解释说明区域 -->
    <div v-if="isSM" style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;">
      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
        <div style="display: flex; align-items: center; gap: 8px;">
                    <span style="
                        display: inline-block;
                        width: 16px;
                        height: 16px;
                        border-radius: 50%;
                        background-color: #f0f0f0;
                        position: relative;
                    ">
                        <span style="
                            position: absolute;
                            top: 45%;
                            left: 50%;
                            width: 6px;
                            height: 3px;
                            border: solid #333;
                            border-width: 0 0 2px 2px;
                            transform: translate(-50%, -50%) rotate(-45deg);
                        "></span>
                    </span>
          <span>完课</span>
        </div>

        <div style="display: flex; align-items: center; gap: 8px;">
                    <span style="
                        display: inline-block;
                        width: 16px;
                        height: 16px;
                        border-radius: 2px;
                        border: 2px solid #666;
                        background-color: transparent;
                        position: relative;
                    ">
                        <span style="
                            position: absolute;
                            top: 50%;
                            left: 50%;
                            width: 8px;
                            height: 2px;
                            background: #666;
                            transform: translate(-50%, -50%) rotate(45deg);
                        "></span>
                        <span style="
                            position: absolute;
                            top: 50%;
                            left: 50%;
                            width: 8px;
                            height: 2px;
                            background: #666;
                            transform: translate(-50%, -50%) rotate(-45deg);
                        "></span>
                    </span>
          <span>待学习</span>
        </div>

        <div style="display: flex; align-items: center; gap: 8px;">
                    <span style="
                        display: inline-block;
                        width: 16px;
                        height: 16px;
                        border-radius: 2px 8px;
                        background-color: #f0f0f0;
                        border: 1px solid #ddd;
                        position: relative;
                        transform: rotate(45deg);
                    ">
                        <span style="
                            position: absolute;
                            top: 50%;
                            left: 50%;
                            width: 6px;
                            height: 6px;
                            border: 2px solid #333;
                            transform: translate(-50%, -50%) rotate(-45deg);
                        "></span>
                    </span>
          <span>学习中断</span>
        </div>

        <div style="display: flex; align-items: center; gap: 8px;">
                    <span style="
                        display: inline-block;
                        width: 16px;
                        height: 16px;
                        border-radius: 2px;
                        background-color: #f0f0f0;
                        border: 1px solid #ddd;
                        position: relative;
	                ">
                        <span style="
                            position: absolute;
                            top: 50%;
                            left: 50%;
                            width: 8px;
                            height: 2px;
                            background: #999;
                            transform: translate(-50%, -50%);
	                    "></span>
                    </span>
          <span>没发课</span>
        </div>

        <div style="display: flex; align-items: center; gap: 8px;">
                    <span style="
                        display: inline-block;
                        width: 16px;
                        height: 16px;
                        border-radius: 2px;
                        background-color: #f0f0f0;
                        border: 1px solid #ddd;
                        position: relative;
                    ">
                        <span style="
                            position: absolute;
                            top: 50%;
                            left: 50%;
                            width: 8px;
                            height: 2px;
                            background: #666;
                            transform: translate(-50%, -10%) rotate(-15deg);
                        "></span>
                    </span>
          <span>学习中</span>
        </div>

      </div>
    </div>

    <div v-else style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;">
      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
        <div style="display: flex; align-items: center; gap: 8px;">
                    <span
                      style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #67C23A;"></span>
          <span>完课</span>
        </div>
        <div style="display: flex; align-items: center; gap: 4px;">
                    <span
                      style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #f55a4f;"></span>
          <span>待学习</span>
        </div>
        <div style="display: flex; align-items: center; gap: 4px;">
                    <span
                      style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #FFD700;"></span>
          <span>学习中断</span>
        </div>
        <div style="display: flex; align-items: center; gap: 4px;">
                    <span
                      style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #909399;"></span>
          <span>没发课</span>
        </div>
        <div style="display: flex; align-items: center; gap: 4px;">
                    <span
                      style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #0bc6ff;"></span>
          <span>学习中</span>
        </div>
      </div>
    </div>

    <!-- app客服搜索 -->
    <el-dialog title="客服搜索" :visible.sync="customerRoleSearch.visible" width="1000px" append-to-body>
      <CusRoleList ref="customerSearchRef"
                   @confirm="customerSelectedConfirmCall"
                   @selectionChange="customerSelectionChangeCall"
                   :selected="customerRoleSearch.selected"
      />
    </el-dialog>

    <!--  -->
    <el-drawer
      :with-header="false"
      size="75%"
      title="用户详情"
      :visible.sync="userDetails.visible"
    >
      <userDetails
        ref="userDetails"
        :userInfo="userDetails.rowInfo"
        :refreshCount="userDetails.count"
        @chat="login"
        @toggleStatus="toggleStatus"
        :imLoading="imLoading"
      />
    </el-drawer>

    <!-- AI外呼对话框 -->
    <ai-sip-call-dialog
      :visible.sync="callDialogVisible"
      :phone-number="currentCallPhone"
      :dial-mode="currentDialMode"
      :record-id="currentRecordId"
      @close="handleCallDialogClose"
      @call-ended="handleCallEnded"
    />

    <!-- 查看详情 -->
    <el-dialog
      :title="quickReplyDialog.title"
      :visible.sync="quickReplyDialog.visible"
      width="1000px"
      append-to-body
      :close-on-click-modal="false"
      :before-close="closeQuickReply"
    >
      <div v-loading="quickReplyDialog.loading">
        <div style="height: 600px; overflow: auto;" ref="scrollWrap">
          <el-timeline>
            <el-timeline-item
              v-for="(chatLog, idx) in quickReplyDialog.chatLogs"
              :timestamp="chatLog.sendTime"
              placement="top"
              :type="chatLog.userType === 0 ? 'success' : 'primary'"
              :key="idx"
            >
              <el-card shadow="hover" :body-style="{'padding': '8px', 'background': (chatLog.userType === 0 ? '#9df29f' : 'eeeef0'), 'color': '#161616'}">
                  <!-- 原: v-html="nl2brDisplay(chatLog.sendContent) || '--'" -->
                  <div
                    :class="[chatLog.userType === 0 ? '' : 'no-copy1', 'chat-plain']"
                  >
                    {{ plainMultilineText(chatLog.sendContent) || '--' }}
                  </div>
              </el-card>
            </el-timeline-item>
          </el-timeline>
        </div>

        <div style="padding: 5px 0 0 44px;">
          <div class="quick-reply">
            <el-input type="textarea"
              :autosize="{ minRows: 3, maxRows: 3}"
              :resize="'none'"
              placeholder="请输入快捷回复"
              v-model="quickReplyDialog.replyContent"
              @keydown.native="handleKeyDown"
            />
            <div style="text-align: right;">
              <el-tooltip class="item" effect="dark" content="Enter发送，Ctrl+Enter换行" placement="top-start">
                <el-button
                  :type="quickReplyDialog.replyContent.trim() ? 'success' : 'info'"
                  :disabled="!quickReplyDialog.replyContent.trim() || quickReplyDialog.loading"
                  size="mini"
                  @click="sendReplyContent"
                >
                  发送
                </el-button>
              </el-tooltip>
            </div>
          </div>
        </div>

        <div slot="footer" class="dialog-footer" style="text-align: center">
          <el-button @click="closeQuickReplyDialog">关 闭</el-button>
        </div>
      </div>


    </el-dialog>
  </div>
</template>

<script>
import { listUrgentClassTask, setStatus,getFsUserPhone } from "@/api/app/urgentClass";
import CusRoleList from '@/views/app/user/CusRoleList.vue';
import { getOpenIM, getCbEvents } from '@/utils/openIM';
import { debounce } from '@/utils';
import { accountCheck } from '@/api/app/user/userList.js';
import { findChatLogsByUserIdAndCustomerId, editUserChatLogs, } from "@/api/app/userChatLogs";
import userDetails from './CustomerDetail.vue';
import {mapGetters, mapState} from "vuex";
import { plainMultilineText } from "@/utils/nl2br";
// import AiSipCallDialog from '@/components/AiSipCallDialog.vue';
export default {
  name: "UrgentClass",
  components: { CusRoleList, userDetails
    // , AiSipCallDialog
  },
  data() {
    return {
      hasBindReadyEvent : false,
      imLoading: false,
      isSDKReady: false,
      OpenIM: null,
      tokenCache: {},
      loadingRowId: null,
      actName: "0",
      // 遮罩层
      loading: true,
      // 导出遮罩层
      exportLoading: false,
      companyUserOptionsParams: {
        name: undefined,
        hasNextPage: false,
        pageNum: 1,
        pageSize: 10
      },
      isSM: false,//是否色盲模式
      companyUserOptionsLoading: false,
      companyUserOptions: [],
      myQwUserList: [],
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 提醒任务看板表格数据
      urgentClassTaskList: [],
      // 状态 0 待处理 1 已处理 3 过期字典
      statusOptions: [],
      // 类别 1先导 2 科普 3 节点 4 转人工字典
      typeOptions: [],
      trackTypeOptions: [],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        fsUserId: null,
        customerRoles: null,
        crtTime: this.formatDateToYMD(new Date()),
        status: 0,
        type: null,
        title: null,
        score: null,
        sopId: null,
      },
      customerRoleSearch: {
        visible: false,
        selected: [],
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {},
      userDetails: {
        visible: false,
        rowInfo: null,
        count: 0,
      },
      // AI外呼相关
      callDialogVisible: false,
      currentCallPhone: '',
      currentDialMode: 'encrypted', // plaintext-明文, encrypted-密文
      currentRecordId: '', // 当前外呼的记录ID
      quickReplyDialog: {
        visible: false,
        rowInfo: null,
        loading: false,
        chatInfo: {},
        chatLogs: [],
        title: '',
        replyContent: '',
      },
    };
  },
  computed: {
    ...mapState({
      userID: state => state.imuser.userID,
      applicationUnreadCount: state => state.friend.unreadCount,
      fsUserId: state => state.imuser.fsUserId,
      currentConversation: state => state.conversation.currentConversation
    }),
  },
  watch: {
    '$store.state.imuser.isLogin'(val) {
      if (!val) this.hasBindReadyEvent = false; // 退出后允许下次登录重新绑定 OnConnectSuccess
    }
  },
  created() {

    this.getDicts("app_urgent_class_task_status").then(response => {
      this.statusOptions = response.data;
    });
    this.getDicts("app_urgent_class_task_type").then(response => {
      this.typeOptions = response.data;
    });
    this.getDicts("app_urgent_class_task_track_type").then(response => {
      this.trackTypeOptions = response.data;
    });
    this.getList();
    this.OpenIM = getOpenIM();
    this.initListener();
    // 防抖：收到新消息时避免频繁调用 getOneConversation，减少 SDK 日志与请求
    this._debouncedRefreshConversation = debounce(() => {
      if (this.fsUserId) {
        this.OpenIM.getOneConversation({ sourceID: this.fsUserId, sessionType: 1 })
          .then(({ data }) => this.$store.commit('updateConversationList', data))
          .catch(() => {})
      }
    }, 500)

  },
  methods: {
    plainMultilineText,
    handleCloseCus(cus) {
      this.customerRoleSearch.selected = this.customerRoleSearch.selected.filter(item => item.id != cus.id);
    },
    loginIm(row) {
      this.login(row)
    },
    initListener() {
      // 登录成功后会触发 SDK_READY 事件，该事件触发后，可正常使用 SDK 接口
      this.OpenIM.on(getCbEvents().OnConnectSuccess, () => {
         // 调试日志
        this.$store.commit('toggleIsSDKReady', true);
      });
      this.OpenIM.on(getCbEvents().OnConnectFailed, this.onError);
      this.OpenIM.on(getCbEvents().OnKickedOffline, this.onKickOut);
      this.OpenIM.on(getCbEvents().OnSelfInfoUpdated, this.onSelfInfoUpdated);
      /*this.OpenIM.on(getCbEvents().OnRecvNewMessage, (message) => {
        this.onReceiveMessage({data: [message]}); // 包装成数组形式
      });*/

      this.OpenIM.on(getCbEvents().OnRecvNewMessages, (data) => {
        const msgList = []
        data.data.forEach(msg =>{
          if (msg.contentType!==113){
            msgList.push(msg)
          }
        })
        if (msgList.length>0){
          this.onReceiveMessage({data: msgList});

        }
      });
    },
    login(row) {
      this.imLoading = true;
      this.loadingRowId = row.customerRoleId;
      const cacheKey = 'C' + row.customerRoleId;
      const cached = this.tokenCache?.[cacheKey];
      const tokenPromise = cached && (Date.now() - cached.ts) < 5 * 60 * 1000
        ? Promise.resolve({ token: cached.token })
        : accountCheck(cacheKey).then(res => {
          if (!this.tokenCache) this.tokenCache = {};
          this.tokenCache[cacheKey] = { token: res.token, ts: Date.now() };
          return res;
        });
      tokenPromise.then(response => {
        const userToken = response.token;
        const config = {
          userID: cacheKey,
          token:userToken,
          logLevel: 6,
          platformID: 5,
          apiAddr: 'https://web.im.cdwjyyh.com/api',
          wsAddr: 'wss://web.im.cdwjyyh.com/msg_gateway',
          dataDir: '/imdata'
        };
        this.checkSDKReadyState(row.fsUserId);
        this.doLogin(config, row);
      }).catch(err => {
        this.imLoading = false;
        this.loadingRowId = null;
        this.$store.commit('showMessage', { message: `获取 IM Token 失败：${err?.message || '未知错误'}`, type: 'error' });
      });
    },
    doLogin(config, row, isRetry = false) {
      // 登录前先设置 fsUserId、cacheFsUserName，确保 OnConnectSuccess 回调时能拿到当前用户
      this.$store.commit('setUserId', 'C'+row.customerRoleId);
      this.$store.commit('setFsUserId', 'U'+row.fsUserId);
      this.$store.commit('setCacheFsUserName', row.userName || '');
      this.OpenIM.login(config).then(() => {
        this.imLoading = false;
        this.loadingRowId = null;
        this.$store.commit('setImChatVisible', true)
        this.$store.commit('toggleIsLogin', true);
        this.$store.commit('startComputeCurrent');
        this.$store.commit('showMessage', { type: 'success', message: 'IM 登录成功' });
      }).catch(async (error) => {
        const is10102 = error?.errCode === 10102 || String(error?.errMsg || '').includes('10102')
        if (is10102 && !isRetry) {
          try {
            await this.OpenIM.logout()
            await new Promise(r => setTimeout(r, 300))
            this.doLogin(config, row, true)
          } catch (e) {
            this.imLoading = false;
            this.loadingRowId = null;
            this.$store.commit('showMessage', { message: `IM 登录失败：${error.message || error.errMsg || '未知错误'}`, type: 'error' })
          }
        } else {
          this.imLoading = false;
          this.loadingRowId = null;
          console.error('登录失败:', error)
          this.$store.commit('showMessage', {
            message: `IM 登录失败：${error.message || error.errMsg || '未知错误'}`,
            type: 'error',
          })
        }
      })
    },
    // 添加SDK就绪状态检查
    checkSDKReadyState(fsUserId) {
      if (this.hasBindReadyEvent) return;
      this.hasBindReadyEvent = true;

      let isReady = false;

      const timeout = setTimeout(() => {
        if (!isReady) {
          this.imLoading = false;
          this.loadingRowId = null;
          this.$store.commit('toggleIsSDKReady', false);
          // this.$store.commit('showMessage', { message: 'SDK初始化超时', type: 'error' });
        }
      }, 10000);

      this.OpenIM.on(getCbEvents().OnConnectSuccess, () => {
        clearTimeout(timeout);
        isReady = true;
        this.OpenIM.getSelfUserInfo().then(({ data }) => {
          this.$store.commit('updateCurrentUserProfile', data)
        })
        this.$store.commit('toggleIsSDKReady', true);
        this.isSDKReady = true
        // 已关闭 SDK 初始化成功提示，避免重复弹窗
        // 触发获取用户信息等操作，使用 store 中的 fsUserId（避免切换用户时 closure 仍为旧值）
        const currentFsUserId = this.$store.state.imuser.fsUserId;
        if (currentFsUserId) {
          const fsUserIdRaw = String(currentFsUserId).replace(/^U/, '');
          this.loadUserData(fsUserIdRaw);
        }
      });

      this.OpenIM.on(getCbEvents().OnConnectFailed, (error) => {
        clearTimeout(timeout);
        this.imLoading = false;
        this.loadingRowId = null;
        this.$store.commit('toggleIsSDKReady', false);
        this.$store.commit('showMessage', { message: `SDK 连接失败: ${error.message}`, type: 'error' });
      });
    },
    onKickOut(event) {
      // event.data.type 是踢出原因
      //const reason = this.kickedOutReason(event.data.type);

      // 弹窗提示用户
      this.$alert(`即时通账号在其他设备登录，请重新登录。`, '提示', {
        confirmButtonText: '确定',
        type: 'error',
        callback: () => {
          // 用户确认后执行退出操作
          this.$store.commit('toggleIsLogin', false);
          this.$store.commit('reset');
        }
      });
    },

    // 返回踢出原因
    kickedOutReason(type) {
      switch(type) {
        case 1: return '被管理员踢出';
        case 2: return '账号在其他设备登录';
        default: return '未知原因';
      }
    },
    onReceiveMessage({ data: messageList }) {
      const fsUserId = this.$store.state.imuser.fsUserId
      const isCurrentSessionMsg = fsUserId && messageList.some(
        m => m.sendID === fsUserId || m.recvID === fsUserId
      )
      if (isCurrentSessionMsg) {
        this._debouncedRefreshConversation?.()
      }
      this.$store.commit('pushCurrentMessageList', messageList)
      // this.$store.commit('pushAvChatRoomMessageList', messageList)
    },

    // 添加加载用户数据方法（获取单个会话）
    loadUserData(fsUserId) {
      if (this._loadUserDataGuard === fsUserId) return
      this._loadUserDataGuard = fsUserId
      // 切换用户时先清空会话列表，避免展示上一用户的数据
      this.$store.commit('updateConversationList', [])
      this.$store.commit('setConversationListLoading', true)
      this.OpenIM.getOneConversation({
        sourceID: 'U' + fsUserId,
        sessionType: 1,
      })
        .then(({ data }) => {
          this.conversationList = data ? [data] : []
          this.$store.commit('updateConversationList', data)
          if (data) {
            this.$store.dispatch('checkoutConversation', {
              conversation: data,
              skipRefreshConversationList: true
            })
          }
        })
        .catch(({ errCode, errMsg }) => {
          // 调用失败
        })
        .finally(() => {
          this.$store.commit('setConversationListLoading', false)
          this._loadUserDataGuard = null
        })
      //查询好友列表
      // this.OpenIM.getFriendListPage({ offset:0, count:100 })
      //   .then(({ data }) => {
      //     // 调用成功
      //     console.log("获取到好友列表",data)
      //     //this.conversationList= data
      //     this.$store.commit('updateFriendList', data)
      //   })
      //   .catch(({ errCode, errMsg }) => {
      //     // 调用失败
      //   })
      // //查询群列表
      // this.OpenIM.getJoinedGroupList()
      //   .then(({ data }) => {
      //     // 调用成功
      //     console.log("获取到群聊列表",data)
      //     //this.conversationList= data
      //     this.$store.commit('updateGroupList', data)
      //   })
      //   .catch(({ errCode, errMsg }) => {
      //     // 调用失败
      //   });
    },
    /**
     * 分数对应背景颜色
     * @param score
     */
    getScoreStyle(score) {
      let backgroundColor = '';
      if (score >= 15) {
        backgroundColor = '#ff4d4f';    // 红色
      } else if (score >= 9) {
        backgroundColor = '#ff7d45';    // 橘红
      } else if (score >= 4) {
        backgroundColor = '#ffec3d';    // 黄色
      } else {
        backgroundColor = '#ffffff';    // 白色
      }
      return {
        'background-color': backgroundColor,
        'padding': '5px 10px',
        'border-radius': '4px'
      };
    },
    openCusSearchPage() {
      this.customerRoleSearch.visible = true;
    },
    customerSelectedConfirmCall() {
      this.customerRoleSearch.visible = false;
    },
    /**
     * 选中元素改变回调
     * @param selected
     */
    customerSelectionChangeCall(config) {
      let selected = config.selected;
      //单行操作
      if (config.mode === 0) {
        let row = config.row;
        if (selected) {
          this.customerRoleSearch.selected.push(row)
        } else {
          this.customerRoleSearch.selected = this.customerRoleSearch.selected.filter(m => m.id != row.id);
        }
      }
      //操作当前页所有行
      else {
        let list = config.rows;
        if (selected) {
          list.map(l => this.customerRoleSearch.selected.push(l));
        } else {
          list.map(l => {
            for (let i = 0; i < this.customerRoleSearch.selected.length; i++) {
              if (l.id == this.customerRoleSearch.selected[i].id) {
                this.customerRoleSearch.selected.splice(i, 1);
              }
            }
          })
        }
      }
    },
    formatTime(timeStr) {
      if (!timeStr && timeStr !== 0) return '';
      // 处理数字和字符串输入
      const str = String(timeStr).padStart(4, '0');
      // 提取有效部分
      const hours = str.substring(0, 2);
      const minutes = str.substring(2, 4);
      // 简单验证
      if (hours > 23 || minutes > 59) return '无效时间';
      return `${hours}:${minutes}`;
    },
    /**
     * 查询任务看板列表
     */
    async getList() {
      this.loading = true;
      let rp = JSON.parse(JSON.stringify(this.queryParams));
      rp['customerRoleIds'] = this.customerRoleSearch.selected.map(s => s.id);
      let res = await listUrgentClassTask(rp);
      // console.log(res.rows)
      this.urgentClassTaskList = res.rows;
      this.total = res.total;
      this.loading = false;
    },
    formatDateToYMD(date) {
      const year = date.getFullYear(); // 年（4位，如 2026）
      const month = date.getMonth() + 1; // 月（+1 修正 0 开始的问题）
      const day = date.getDate(); // 日
      const formattedMonth = month.toString().padStart(2, '0');
      const formattedDay = day.toString().padStart(2, '0');
      return `${year}-${formattedMonth}-${formattedDay}`;
    },
    /**
     * 切换选项卡
     * @param tab
     * @param event
     */
    toggleTab(tab, event) {
      this.queryParams.status = tab.name;
      this.handleQuery();
    },
    /**
     * 搜索按钮操作
     */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /**
     * 重置按钮操作
     */
    resetQuery() {
      this.customerRoleSearch.selected = [];
      this.resetForm("queryForm");
      this.handleQuery();
    },
    /**
     * 切换状态
     * @param row
     */
    toggleStatus(row, status) {
      let ids = [row.id];
      this.$confirm('是否确认切换状态?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(async () => {
        let res = await setStatus({ids, status});
        this.msgSuccess('切换状态成功！');
        this.getList();
      }).catch(() => { });
    },
    /**
     * 快速回复
     */
    async quickReply(row) {
      this.quickReplyDialog.visible = true;
      this.quickReplyDialog.loading = true;
      this.quickReplyDialog.rowInfo = row;
      if (!(row.customerRoleId && row.fsUserId)) {
        this.quickReplyDialog.loading = false;
        return this.$message.error('当前记录不满足快速回复条件，用户或客服为空！');
      }
      this.quickReplyDialog.title = `对话详情(${row.fsUserId}-${row.customerRoleId})`;
      let info = await findChatLogsByUserIdAndCustomerId({
        userId: row.fsUserId,
        customerId: row.customerRoleId,
      });
      if (!this.isEmpty(info.data)) {
        this.quickReplyDialog.chatInfo = info.data;
        let data = info.data;
        let chatLogs = [];
        // 存原文；展示用 {{ }} + pre-wrap（兼容历史已含 <br> 的数据由 plainMultilineText 还原）
        chatLogs.push({
          userType: 0,
          sendTime: data.userAskTime,
          sendContent: !this.isEmpty(data.userAskFullContent) ? data.userAskFullContent : '--',
        });
        chatLogs.push({
          userType: 1,
          sendTime: data.customerReplyTime,
          sendContent: !this.isEmpty(data.customerReplyFullContent) ? data.customerReplyFullContent : '--',
        });
        if (!this.isEmpty(data.extend)) {
          let extend = JSON.parse(data.extend);
          if (!this.isEmpty(extend.chats)) {
            chatLogs.push(...extend.chats);
          }
        }
        this.quickReplyDialog.chatLogs = chatLogs;
      }
      this.quickReplyDialog.loading = false;
    },
    isEmpty(value) {
      return value === null || value === undefined || value.length === 0;
    },
    /**
     * 关闭快速回复对话框
     */
    closeQuickReplyDialog() {
      this.quickReplyDialog.visible = false;
      this.quickReplyDialog.rowInfo = null;
      this.quickReplyDialog.loading = false;
      this.quickReplyDialog.chatInfo = false;
      this.quickReplyDialog.title = '';
      this.quickReplyDialog.chatLogs = [];
      this.quickReplyDialog.replyContent = '';
    },
    handledetails(row) {
      this.userDetails.visible = true;
      this.userDetails.rowInfo = row;
      this.userDetails.count++;
    },

    /**
     * 外呼电话
     */
    handleCallPhone(row) {
      if (!row.fsUserId) {
        this.$message.warning('该记录无fsUserId');
        return;
      }
      getFsUserPhone(row.fsUserId).then(response => {
        if(response.code === 200){
          // 设置当前拨打的电话号码
          this.currentCallPhone = response.data;
          // 默认使用明文模式plaintext，如果需要密文模式可以改为 'encrypted'
          this.currentDialMode = 'encrypted';
          // 保存当前外呼的记录ID
          this.currentRecordId = row.id;

          // 显示外呼对话框，会自动拨号
          this.callDialogVisible = true;
        }else{
          this.$message.warning(response.message);
        }
      });
    },
    /**
     * 外呼对话框关闭处理
     */
    handleCallDialogClose() {
      this.callDialogVisible = false;
      this.currentCallPhone = '';
      this.currentRecordId = '';
    },
    /**
     * 外呼结束处理
     */
    handleCallEnded(recordId) {

      if (!recordId) {
        console.warn('[外呼] 未收到recordId，无法更新状态');
        return;
      }

      // 查找当前列表中对应的记录
      const row = this.urgentClassTaskList.find(item => item.id === recordId);

      if (!row) {
        console.warn('[外呼] 未找到对应的记录，recordId:', recordId);
        return;
      }

      // 只有当status为0时才更新为1
      if (row.status === 0) {

        let ids = [row.id];
        setStatus({ids, status: 1}).then(res => {
          this.msgSuccess('外呼结束，状态已更新为已处理！');
          this.getList(); // 刷新列表
        }).catch(err => {
          this.$message.error('状态更新失败：' + (err.message || '未知错误'));
        });
      } else {
        this.msgSuccess('外呼结束，当前状态无需更新！');
      }
    },
    handleKeyDown(e) {
       // 只处理回车键
      if (e.keyCode !== 13) {
        return;
      }
      if (e.ctrlKey || e.metaKey) {
        e.preventDefault();
        // 手动在光标位置插入换行符
        let textarea = e.target;
        let start = textarea.selectionStart;
        let end = textarea.selectionEnd;
        // 插入换行
        this.quickReplyDialog.replyContent =
          this.quickReplyDialog.replyContent.substring(0, start) +
          "\n" +
          this.quickReplyDialog.replyContent.substring(end);

        // 光标定位到换行后
        this.$nextTick(() => {
          textarea.selectionStart = textarea.selectionEnd = start + 1;
        });
        return;
      }
      e.preventDefault();
      this.sendReplyContent();
    },
    /**
     * 发送回复内容
     */
    async sendReplyContent() {
      this.quickReplyDialog.loading = true;
      if (this.isEmpty(this.quickReplyDialog.replyContent.trim())) {
        this.quickReplyDialog.loading = false;
        return this.$message.error('请输入回复内容！');
      }
      let res = await editUserChatLogs({
        id: this.quickReplyDialog.chatInfo.id,
        replyContent: this.quickReplyDialog.replyContent,
      });
      if (res.code == 200) {
        this.quickReplyDialog.chatLogs.push({
          userType: 1,
          sendTime: res.data,
          sendContent: this.quickReplyDialog.replyContent,
        });
        this.quickReplyDialog.replyContent = '';
        const el = this.$refs.scrollWrap;
        if (el) {
          el.scrollTo({
            top: el.scrollHeight + 50,
            behavior: 'auto'
          });
        }
        this.$message.success('发送成功！');
      } else {
        this.$message.error('发送失败：' + res.msg);
      }
      this.quickReplyDialog.loading = false;
    },
    closeQuickReply() {
      this.quickReplyDialog.visible = false;
      this.quickReplyDialog.rowInfo = null;
      this.quickReplyDialog.loading = false;
      this.quickReplyDialog.chatInfo = false;
      this.quickReplyDialog.chatLogs = [];
      this.quickReplyDialog.title = '';
      this.quickReplyDialog.replyContent = '';
    },
  }
};
</script>
<style scoped lang="scss">
::v-deep .el-card .is-always-shadow {
    padding: 8px;
}

.no-copy {
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

.chat-plain {
  white-space: pre-wrap;
  word-break: break-word;
}

::v-deep  .quick-reply {
  height: 115px;
  border: 1px solid #DCDFE6;
  padding: 5px;
  border-radius: 10px;

   .el-textarea__inner {
    border: none !important;
  }
}
</style>
