WXL (wul)
2025-11-13 de147dda682f8ac597bbcc8555b57acbdf45dba2
src/views/followvisit/discharge/ClickCall copy.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1258 @@
<template>
  <div class="websocket-demo">
    <div>
      <h3>Websocket接口测试DEMO</h3>
      <div class="config-area">
        <div class="input-group">
          <label>CTI_WS_URL</label>
          <input
            type="text"
            v-model="config.cti_ws_url"
            placeholder="ws://40.78.0.169:6688"
          />
          <label>坐席工号</label>
          <input type="text" v-model="config.seatname" placeholder="8000" />
          <label>坐席分机</label>
          <input type="text" v-model="config.seatnum" placeholder="8000" />
          <label>密码</label>
          <input type="text" v-model="config.password" placeholder="123456" />
        </div>
        <div class="input-group">
          <label>外线号码</label>
          <input type="text" v-model="config.phone" placeholder="10086" />
          <label>UUID</label>
          <input type="text" v-model="config.uuid" />
          <label>其他坐席</label>
          <input type="text" v-model="config.other" placeholder="8001" />
          <label>技能组</label>
          <input type="text" v-model="config.group" placeholder="a3" />
          <label>外呼参数id</label>
          <input type="text" v-model="config.paramid" placeholder="3" />
        </div>
      </div>
      <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
      <div class="button-area">
        <!-- ç¬¬ä¸€è¡ŒæŒ‰é’® -->
        <div class="button-row">
          <button @click="seatlogin">签入</button>
          <button @click="seatlogout">签出</button>
          <button @click="afk">示忙</button>
          <button @click="online">示闲</button>
          <button @click="pickup">代答</button>
        </div>
        <!-- ç¬¬äºŒè¡ŒæŒ‰é’® -->
        <div class="button-row">
          <button @click="hangup">挂机</button>
          <button @click="callout">外呼</button>
          <button @click="transfer">通话转移</button>
          <button @click="transferresume">通话转移收回</button>
          <button @click="hold">通话保持</button>
          <button @click="holdresume">通话保持收回</button>
          <button @click="remove">通话强拆</button>
          <button @click="insert">通话强插</button>
          <button @click="monitor">监听</button>
          <button @click="monitor_to_talk">监听转通话</button>
          <button @click="monitor_end">监听结束</button>
          <button @click="choosecall">选择</button>
          <button @click="replacecall">代接</button>
          <button @click="three">三方通话</button>
        </div>
        <!-- ç¬¬ä¸‰è¡ŒæŒ‰é’® -->
        <div class="button-row">
          <button @click="handoff_ready">咨询开始</button>
          <button @click="handoff_call">咨询呼叫</button>
          <button @click="handoff_resume">咨询收回</button>
          <button @click="handoff_transfer">咨询转移</button>
          <button @click="handoff_three">咨询三方</button>
          <button @click="record_start">开始通话录音</button>
          <button @click="record_stop">停止通话录音</button>
        </div>
        <!-- ç¬¬å››è¡ŒæŒ‰é’® -->
        <div class="button-row">
          <button @click="openseatlist">打开坐席状态</button>
          <button @click="closeseatlist">关闭坐席状态</button>
          <button @click="openqueues">打开队列信息</button>
          <button @click="closequeues">关闭队列信息</button>
          <button @click="opencalllist">打开通话信息</button>
          <button @click="closecalllist">关闭通话信息</button>
          <button @click="openroutelist">打开路由信息</button>
          <button @click="closeroutelist">关闭路由信息</button>
        </div>
        <!-- ç¬¬äº”行按钮 -->
        <div class="button-row">
          <button @click="seatlist">获取坐席信息</button>
          <button @click="queues">获取队列信息</button>
          <button @click="calllist">获取通话信息</button>
          <button @click="routelist">获取路由信息</button>
          <button @click="batch">获取外呼参数信息</button>
          <button @click="batch_start">开始外呼任务</button>
          <button @click="batch_stop">停止外呼任务</button>
        </div>
      </div>
      <!-- æ—¥å¿—显示区域 -->
      <h3>协议日志区<button @click="testclear">清除</button></h3>
      <div id="msg" class="log-area">{{ logs }}</div>
    </div>
  </div>
</template>
<script>
import { CallsetState, CallgetList } from "@/api/AiCentre/index";
export default {
  name: "WebsocketDemo",
  data() {
    return {
      config: {
        cti_ws_url: "wss://9.208.2.190:8092/cal-api/",
        seatname: "8000",
        seatnum: "8000",
        password: "123456",
        phone: "10086",
        uuid: "",
        other: "8001",
        group: "a3",
        paramid: "3",
      },
      randomNum: "",
      randomID: "",
      logs: "",
      ws: null,
      isConnected: false,
    };
  },
  mounted() {
    this.CallgetList();
    this.initializeWebSocket();
  },
  beforeUnmount() {
    this.disconnectWebSocket();
  },
  methods: {
    // åˆå§‹åŒ–WebSocket连接
    initializeWebSocket() {
      try {
        // æ ¹æ®å½“前页面协议自动选择WS协议
        const isHttps = window.location.protocol === "https:";
        this.config.cti_ws_url = isHttps
          ? "wss://9.208.2.190:8092/cal-api/"
          : "ws://40.78.0.169:6688";
        if (typeof window.WebSocket === "undefined") {
          this.addLog("错误: æµè§ˆå™¨ä¸æ”¯æŒWebSocket");
          return;
        }
        this.connectWebSocket();
      } catch (error) {
        this.addLog(`初始化WebSocket错误: ${error.message}`);
        // å°è¯•使用备用地址
        this.config.cti_ws_url = "wss://9.208.2.190:8092/cal-api/";
        setTimeout(() => this.connectWebSocket(), 2000);
      }
    },
    // æŸ¥è¯¢å¯ç”¨åˆ†æœºå·
    async CallgetList() {
      try {
        const res = await CallgetList();
        this.randomNum = res.data[0].tel;
        this.randomID = res.data[0].id;
        // æ­£ç¡®è®¾ç½® sipUri
        this.config.seatname = randomNum;
        this.config.seatnum = randomNum;
        this.startCallsetState();
      } catch (error) {
        console.error("获取座席号失败:", error);
        // this.updateStatus("failed", "获取座席号失败");
      }
    },
    //使用座席号
    async startCallsetState() {
      try {
        await CallsetState({ id: this.randomID, state: 1 });
        console.log("座席号状态更新为使用中");
      } catch (error) {
        console.error("更新座席号状态失败:", error);
      }
    },
    //释放座席号
    async overCallsetState() {
      try {
        if (this.randomID) {
          await CallsetState({ id: this.randomID, state: 0 });
          console.log("座席号状态更新为可用");
        }
      } catch (error) {
        console.error("释放座席号失败:", error);
      }
    },
    // è¿žæŽ¥WebSocket
    connectWebSocket() {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.addLog("WebSocket已连接");
        return;
      }
      try {
        let wsUrl = this.config.cti_ws_url;
        // ç¡®ä¿HTTPS页面使用WSS
        if (
          window.location.protocol === "https:" &&
          wsUrl.startsWith("ws://")
        ) {
          wsUrl = wsUrl.replace("ws://", "wss://");
        }
        this.ws = new WebSocket(wsUrl);
        this.ws.onopen = () => {
          this.isConnected = true;
          this.addLog("WebSocket连接成功");
        };
        this.ws.onmessage = (event) => {
          this.handleWebSocketMessage(event);
        };
        this.ws.onclose = (event) => {
          this.isConnected = false;
          this.addLog(`WebSocket连接关闭: ${event.code} ${event.reason}`);
          // è‡ªåŠ¨é‡è¿ž
          setTimeout(() => this.connectWebSocket(), 3000);
        };
        this.ws.onerror = (error) => {
          this.addLog(`WebSocket错误: ${error.message}`);
          // å°è¯•备用URL
          if (!wsUrl.includes("9.208.2.190")) {
            this.config.cti_ws_url = "wss://9.208.2.190:8092/cal-api/";
            setTimeout(() => this.connectWebSocket(), 3000);
          }
        };
      } catch (error) {
        this.addLog(`连接WebSocket失败: ${error.message}`);
        // å°è¯•备用URL
        this.config.cti_ws_url = "wss://9.208.2.190:8092/cal-api/";
        setTimeout(() => this.connectWebSocket(), 3000);
      }
    },
    // å¤„理WebSocket消息
    handleWebSocketMessage(event) {
      const reader = new FileReader();
      reader.onloadend = (e) => {
        const message = reader.result;
        this.addLog(`收到消息: ${message}`);
        try {
          const obj = JSON.parse(message);
          // å¤„理心跳包
          if (obj.cmd === "system" && obj.action === "keepalive") {
            this.keepalive(obj.seatname, obj.seatnum);
          }
          // è‡ªåŠ¨è®¾ç½®UUID
          if (obj.cmd === "control" && obj.action === "tp_callin") {
            this.config.uuid = obj.uuid;
            this.addLog(`自动设置UUID: ${obj.uuid}`);
          }
        } catch (error) {
          this.addLog(`消息解析错误: ${error.message}`);
        }
      };
      reader.readAsText(event.data);
    },
    // æ–­å¼€WebSocket连接
    disconnectWebSocket() {
      if (this.ws) {
        this.ws.close();
        this.ws = null;
        this.isConnected = false;
        this.addLog("WebSocket已断开");
      }
    },
    // å‘送WebSocket消息
    sendWebSocketMessage(message) {
      if (!this.isConnected || !this.ws) {
        this.addLog("错误: WebSocket未连接");
        return false;
      }
      try {
        const messageStr =
          typeof message === "string" ? message : JSON.stringify(message);
        this.ws.send(messageStr);
        this.addLog(`发送消息: ${messageStr}`);
        return true;
      } catch (error) {
        this.addLog(`发送消息失败: ${error.message}`);
        return false;
      }
    },
    // éªŒè¯å‚æ•°
    validateParams(params, requiredFields) {
      for (const field of requiredFields) {
        if (!params[field] || params[field].toString().trim() === "") {
          this.addLog(`错误: ${field} ä¸èƒ½ä¸ºç©º`);
          return false;
        }
      }
      return true;
    },
    // ==================== WebSocket.js åŠŸèƒ½æ•´åˆ ====================
    // ç­¾å…¥
    seatlogin() {
      const { seatname, seatnum, password, cti_ws_url } = this.config;
      if (
        !this.validateParams({ seatname, seatnum }, ["seatname", "seatnum"])
      ) {
        return;
      }
      // é‡æ–°è¿žæŽ¥WebSocket(原js文件中的逻辑)
      this.connectWebSocket();
      setTimeout(() => {
        const protocol = {
          cmd: "system",
          action: "seatlogin",
          seatname: seatname,
          seatnum: seatnum,
          password: password,
          timestamp: Date.now(),
        };
        this.sendWebSocketMessage(protocol);
      }, 1000);
    },
    // ç­¾å‡º
    seatlogout() {
      const { seatname, seatnum } = this.config;
      if (
        !this.validateParams({ seatname, seatnum }, ["seatname", "seatnum"])
      ) {
        return;
      }
      const protocol = {
        cmd: "system",
        action: "seatlogout",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
      this.ws.close();
    },
    // ç¤ºå¿™
    afk() {
      const { seatname, seatnum } = this.config;
      if (
        !this.validateParams({ seatname, seatnum }, ["seatname", "seatnum"])
      ) {
        return;
      }
      const protocol = {
        cmd: "system",
        action: "afk",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // ç¤ºé—²
    online() {
      const { seatname, seatnum } = this.config;
      if (
        !this.validateParams({ seatname, seatnum }, ["seatname", "seatnum"])
      ) {
        return;
      }
      const protocol = {
        cmd: "system",
        action: "online",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // ä»£ç­”
    pickup() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "pickup",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // æŒ‚机
    hangup() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "hangup",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å¤–呼
    callout() {
      const { seatname, seatnum, phone } = this.config;
      if (!this.validateParams({ seatnum, phone }, ["seatnum", "phone"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "callout",
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // é€šè¯è½¬ç§»
    transfer() {
      const { seatname, seatnum, phone, uuid } = this.config;
      if (
        !this.validateParams({ seatnum, phone, uuid }, [
          "seatnum",
          "phone",
          "uuid",
        ])
      ) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "transfer",
        uuid: uuid,
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // é€šè¯è½¬ç§»æ”¶å›ž
    transferresume() {
      const { seatname, seatnum, phone, uuid } = this.config;
      if (
        !this.validateParams({ seatnum, phone, uuid }, [
          "seatnum",
          "phone",
          "uuid",
        ])
      ) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "transferresume",
        uuid: uuid,
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // é€šè¯ä¿æŒ
    hold() {
      const { seatname, seatnum, uuid } = this.config;
      if (!this.validateParams({ seatnum, uuid }, ["seatnum", "uuid"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "hold",
        uuid: uuid,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // é€šè¯ä¿æŒæ”¶å›ž
    holdresume() {
      const { seatname, seatnum, uuid } = this.config;
      if (!this.validateParams({ seatnum, uuid }, ["seatnum", "uuid"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "holdresume",
        uuid: uuid,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // é€šè¯å¼ºæ‹†
    remove() {
      const { seatname, seatnum, phone } = this.config;
      if (!this.validateParams({ seatnum, phone }, ["seatnum", "phone"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "remove",
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // é€šè¯å¼ºæ’
    insert() {
      const { seatname, seatnum, phone } = this.config;
      if (!this.validateParams({ seatnum, phone }, ["seatnum", "phone"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "insert",
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // ç›‘听
    monitor() {
      const { seatname, seatnum, phone } = this.config;
      if (!this.validateParams({ seatnum, phone }, ["seatnum", "phone"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "monitor",
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // ç›‘听转通话
    monitor_to_talk() {
      const { seatname, seatnum, phone } = this.config;
      if (!this.validateParams({ seatnum, phone }, ["seatnum", "phone"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "monitor_to_talk",
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // ç›‘听结束
    monitor_end() {
      const { seatname, seatnum, phone } = this.config;
      if (!this.validateParams({ seatnum, phone }, ["seatnum", "phone"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "monitor_end",
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // é€‰æ‹©é€šè¯
    choosecall() {
      const { seatname, seatnum, uuid } = this.config;
      if (!this.validateParams({ seatnum, uuid }, ["seatnum", "uuid"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "choosecall",
        uuid: uuid,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // ä»£æŽ¥
    replacecall() {
      const { seatname, seatnum, phone } = this.config;
      if (!this.validateParams({ seatnum, phone }, ["seatnum", "phone"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "replacecall",
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // ä¸‰æ–¹é€šè¯
    three() {
      const { seatname, seatnum, phone } = this.config;
      if (!this.validateParams({ seatnum, phone }, ["seatnum", "phone"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "three",
        phone: phone,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å’¨è¯¢å¼€å§‹
    handoff_ready() {
      const { seatname, seatnum, uuid } = this.config;
      if (!this.validateParams({ seatnum, uuid }, ["seatnum", "uuid"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "handoff_ready",
        uuid: uuid,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å’¨è¯¢å‘¼å«
    handoff_call() {
      const { seatname, seatnum, other, uuid } = this.config;
      if (
        !this.validateParams({ seatnum, other, uuid }, [
          "seatnum",
          "other",
          "uuid",
        ])
      ) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "handoff_call",
        uuid: uuid,
        phone: other,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å’¨è¯¢æ”¶å›ž
    handoff_resume() {
      const { seatname, seatnum, uuid } = this.config;
      if (!this.validateParams({ seatnum, uuid }, ["seatnum", "uuid"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "handoff_resume",
        uuid: uuid,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å’¨è¯¢è½¬ç§»
    handoff_transfer() {
      const { seatname, seatnum, other, uuid } = this.config;
      if (
        !this.validateParams({ seatnum, other, uuid }, [
          "seatnum",
          "other",
          "uuid",
        ])
      ) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "handoff_transfer",
        uuid: uuid,
        phone: other,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å’¨è¯¢ä¸‰æ–¹
    handoff_three() {
      const { seatname, seatnum, uuid } = this.config;
      if (!this.validateParams({ seatnum, uuid }, ["seatnum", "uuid"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "handoff_three",
        uuid: uuid,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å¼€å§‹é€šè¯å½•音
    record_start() {
      const { seatname, seatnum, uuid } = this.config;
      if (!this.validateParams({ seatnum, uuid }, ["seatnum", "uuid"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "record_start",
        uuid: uuid,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // åœæ­¢é€šè¯å½•音
    record_stop() {
      const { seatname, seatnum, uuid } = this.config;
      if (!this.validateParams({ seatnum, uuid }, ["seatnum", "uuid"])) {
        return;
      }
      const protocol = {
        cmd: "control",
        action: "record_stop",
        uuid: uuid,
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // æ‰“开坐席状态
    openseatlist() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "openseatlist",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å…³é—­åå¸­çŠ¶æ€
    closeseatlist() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "closeseatlist",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // æ‰“开队列信息
    openqueues() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "openqueues",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å…³é—­é˜Ÿåˆ—信息
    closequeues() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "closequeues",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // æ‰“开通话信息
    opencalllist() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "opencalllist",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å…³é—­é€šè¯ä¿¡æ¯
    closecalllist() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "closecalllist",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // æ‰“开路由信息
    openroutelist() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "openroutelist",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å…³é—­è·¯ç”±ä¿¡æ¯
    closeroutelist() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "closeroutelist",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // èŽ·å–åå¸­ä¿¡æ¯
    seatlist() {
      const { group } = this.config;
      if (!this.validateParams({ group }, ["group"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "seatlist",
        group: group,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // èŽ·å–é˜Ÿåˆ—ä¿¡æ¯
    queues() {
      const protocol = {
        cmd: "status",
        action: "queues",
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // èŽ·å–é€šè¯ä¿¡æ¯
    calllist() {
      const protocol = {
        cmd: "status",
        action: "calllist",
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // èŽ·å–è·¯ç”±ä¿¡æ¯
    routelist() {
      const protocol = {
        cmd: "status",
        action: "routelist",
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // èŽ·å–å¤–å‘¼å‚æ•°ä¿¡æ¯
    batch() {
      const { paramid } = this.config;
      if (!this.validateParams({ paramid }, ["paramid"])) {
        return;
      }
      const protocol = {
        cmd: "status",
        action: "batch",
        paramid: paramid,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å¼€å§‹å¤–呼任务
    batch_start() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "system",
        action: "batch_start",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // åœæ­¢å¤–呼任务
    batch_stop() {
      const { seatname, seatnum } = this.config;
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "system",
        action: "batch_stop",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // å¿ƒè·³åŒ…
    keepalive(seatname, seatnum) {
      if (!this.validateParams({ seatnum }, ["seatnum"])) {
        return;
      }
      const protocol = {
        cmd: "system",
        action: "keepalive",
        seatname: seatname,
        seatnum: seatnum,
        timestamp: Date.now(),
      };
      this.sendWebSocketMessage(protocol);
    },
    // æ¸…除日志
    testclear() {
      this.logs = "";
      this.addLog("日志已清除");
    },
    // æ·»åŠ æ—¥å¿—
    addLog(message) {
      const timestamp = new Date().toLocaleTimeString();
      this.logs += `[${timestamp}] ${message}\n`;
      // é™åˆ¶æ—¥å¿—长度,防止内存溢出
      const logLines = this.logs.split("\n");
      if (logLines.length > 100) {
        this.logs = logLines.slice(-50).join("\n");
      }
    },
  },
};
</script>
<style scoped>
.websocket-demo {
  font-family: Arial, sans-serif;
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}
.config-area {
  margin-bottom: 20px;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background-color: #f9f9f9;
}
.input-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.input-group label {
  font-weight: bold;
  min-width: 80px;
}
.input-group input {
  padding: 5px 10px;
  border: 1px solid #ccc;
  border-radius: 3px;
  width: 120px;
}
.button-area {
  margin-bottom: 20px;
}
.button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-bottom: 10px;
}
.button-row button {
  padding: 8px 15px;
  border: 1px solid #ccc;
  border-radius: 3px;
  background-color: #f0f0f0;
  cursor: pointer;
  transition: background-color 0.3s;
  font-size: 12px;
}
.button-row button:hover {
  background-color: #e0e0e0;
}
.button-row button:active {
  background-color: #d0d0d0;
  transform: translateY(1px);
}
.log-area {
  height: 300px;
  overflow-y: auto;
  border: 1px solid #ccc;
  padding: 10px;
  background-color: #f5f5f5;
  white-space: pre-wrap;
  font-family: "Courier New", monospace;
  font-size: 12px;
  line-height: 1.4;
}
h3 {
  color: #333;
  border-bottom: 2px solid #eee;
  padding-bottom: 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
h3 button {
  padding: 5px 10px;
  font-size: 12px;
  background-color: #f0f0f0;
  border: 1px solid #ccc;
  border-radius: 3px;
  cursor: pointer;
}
/* å“åº”式设计 */
@media (max-width: 768px) {
  .websocket-demo {
    padding: 10px;
  }
  .input-group {
    flex-direction: column;
    align-items: flex-start;
  }
  .input-group input {
    width: 100%;
  }
  .button-row {
    flex-direction: column;
  }
  .button-row button {
    width: 100%;
    margin-bottom: 5px;
  }
}
</style>