From de147dda682f8ac597bbcc8555b57acbdf45dba2 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期四, 13 十一月 2025 16:55:51 +0800
Subject: [PATCH] 测试完成

---
 src/views/followvisit/discharge/ClickCall copy.vue | 1258 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,258 insertions(+), 0 deletions(-)

diff --git a/src/views/followvisit/discharge/ClickCall copy.vue b/src/views/followvisit/discharge/ClickCall copy.vue
new file mode 100644
index 0000000..bb2b2e0
--- /dev/null
+++ b/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">浠g瓟</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">浠f帴</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: {
+    // 鍒濆鍖朩ebSocket杩炴帴
+    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(`鍒濆鍖朩ebSocket閿欒: ${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;
+        // 姝g‘璁剧疆 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(`娑堟伅瑙f瀽閿欒: ${error.message}`);
+        }
+      };
+      reader.readAsText(event.data);
+    },
+
+    // 鏂紑WebSocket杩炴帴
+    disconnectWebSocket() {
+      if (this.ws) {
+        this.ws.close();
+        this.ws = null;
+        this.isConnected = false;
+        this.addLog("WebSocket宸叉柇寮�");
+      }
+    },
+
+    // 鍙戦�乄ebSocket娑堟伅
+    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);
+    },
+
+    // 浠g瓟
+    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);
+    },
+
+    // 浠f帴
+    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>

--
Gitblit v1.9.3