B2B网络软件

标题: AIWROK软件支持悬浮窗自由定位和拖拽功能 [打印本页]

作者: YYPOST群发软件    时间: 前天 08:10
标题: AIWROK软件支持悬浮窗自由定位和拖拽功能
AIWROK软件支持悬浮窗自由定位和拖拽功能
AIWROK软件支持悬浮窗自由定位和拖拽功能 B2B网络软件

AIWROK软件支持悬浮窗自由定位和拖拽功能 B2B网络软件

  1. //通过floatUI创建悬浮窗
  2. //适用于ES5系统安卓 JavaScript引擎Rhino
  3. //基于AIWROK软件安卓开发框架
  4. //支持悬浮窗自由定位和拖拽功能
  5. //🍎交流QQ群711841924群一,苹果内测群,528816639


  6. if (!String.prototype.repeat) {
  7.     String.prototype.repeat = function(count) {
  8.         'use strict';
  9.         if (this == null) {
  10.             throw new TypeError('can\'t convert ' + this + ' to object');
  11.         }
  12.         var str = String(this);
  13.         count = +count;
  14.         if (count != count) {
  15.             count = 0;
  16.         }
  17.         if (count < 0) {
  18.             throw new RangeError('repeat count must be non-negative');
  19.         }
  20.         if (count == Infinity) {
  21.             throw new RangeError('repeat count must be less than infinity');
  22.         }
  23.         count = Math.floor(count);
  24.         if (str.length == 0 || count == 0) {
  25.             return '';
  26.         }
  27.         // 确保重复的字符串不会超出字符串长度限制
  28.         if (str.length * count >= 1 << 28) {
  29.             throw new RangeError('repeat count must not overflow maximum string size');
  30.         }
  31.         var rpt = '';
  32.         for (var i = 0; i < count; i++) {
  33.             rpt += str;
  34.         }
  35.         return rpt;
  36.     };
  37. }

  38. // ES5兼容的String.prototype.padStart polyfill
  39. if (!String.prototype.padStart) {
  40.     String.prototype.padStart = function(targetLength, padString) {
  41.         targetLength = targetLength >> 0; // 转换为整数
  42.         padString = String((typeof padString !== 'undefined' ? padString : ' '));
  43.         if (this.length > targetLength) {
  44.             return String(this);
  45.         } else {
  46.             targetLength = targetLength - this.length;
  47.             if (targetLength > padString.length) {
  48.                 padString += padString.repeat(targetLength / padString.length); // 截断或重复填充字符串
  49.             }
  50.             return padString.slice(0, targetLength) + String(this);
  51.         }
  52.     };
  53. }

  54. /*
  55.    安卓可移动侧栏日志吐司
  56.    功能:
  57.    1. 可拖拽移动的侧栏悬浮窗
  58.    2. 支持日志信息实时显示
  59.    3. 支持展开/收起功能
  60.    4. 支持自定义日志颜色
  61. */

  62. // 定义侧栏日志悬浮窗构造函数
  63. function 侧栏日志() {
  64.     this.screenHeight = 1920; // 默认屏幕高度
  65.     this.screenWidth = 1080;  // 默认屏幕宽度
  66.     this.isExpanded = false;  // 展开状态标志
  67.     this.logs = [];           // 日志数组
  68.     this.maxLogs = 50;        // 最大日志条数
  69.     this.dragging = false;    // 拖拽状态标志
  70.     this.lastX = 0;           // 上次触摸X坐标
  71.     this.lastY = 0;           // 上次触摸Y坐标
  72. }

  73. // 创建侧栏日志悬浮窗
  74. 侧栏日志.prototype.create = function() {
  75.     try {
  76.         // 检查floatUI是否可用
  77.         if (typeof floatUI === 'undefined') {
  78.             printl("❌ 错误:未找到floatUI库");
  79.             return false;
  80.         }
  81.         
  82.         // 创建floatUI实例
  83.         var fui = new floatUI();
  84.         
  85.         // 获取实际屏幕尺寸
  86.         try {
  87.             if (context && context.getResources && context.getResources().getDisplayMetrics) {
  88.                 var metrics = context.getResources().getDisplayMetrics();
  89.                 this.screenHeight = metrics.heightPixels || 1920;
  90.                 this.screenWidth = metrics.widthPixels || 1080;
  91.                 printl("✅ 获取屏幕尺寸: " + this.screenWidth + "x" + this.screenHeight);
  92.             } else {
  93.                 printl("⚠️ 无法获取屏幕尺寸,使用默认值");
  94.                 this.screenHeight = 1920; // 默认屏幕高度
  95.                 this.screenWidth = 1080;  // 默认屏幕宽度
  96.             }
  97.         } catch(e) {
  98.             printl("⚠️ 获取屏幕尺寸失败,使用默认值: " + e);
  99.             this.screenHeight = 1920;
  100.             this.screenWidth = 1080;
  101.         }
  102.         
  103.         // 定义侧边栏宽度和高度
  104.         var sidebarWidth = 100;  // 更窄的侧边栏宽度
  105.         var sidebarMinWidth = 30; // 更窄的收起时最小宽度
  106.         var sidebarHeight = 100; // 固定小高度,不再依赖屏幕比例
  107.         
  108.         // 加载XML布局
  109.         try {
  110.             fui.loadXML(`
  111.                 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  112.                     android:layout_width="${sidebarWidth}dp"
  113.                     android:layout_height="${sidebarHeight}dp"
  114.                     android:background="#CC000000"
  115.                     android:orientation="vertical"
  116.                     android:id="main_container">
  117.                     
  118.                     <!-- 可拖动的标题栏 -->
  119.                     <LinearLayout
  120.                         android:id="title_bar"
  121.                         android:layout_width="match_parent"
  122.                         android:layout_height="35dp"
  123.                         android:background="#666666"
  124.                         android:orientation="horizontal"
  125.                         android:gravity="center_vertical">
  126.                         
  127.                         <!-- 拖动区域 -->
  128.                         <View
  129.                             android:layout_width="${sidebarMinWidth}dp"
  130.                             android:layout_height="match_parent"
  131.                             android:background="#444444"/>
  132.                         
  133.                         <!-- 标题文字(仅在展开时可见) -->
  134.                         <TextView
  135.                             android:id="title_text"
  136.                             android:layout_width="0dp"
  137.                             android:layout_height="match_parent"
  138.                             android:layout_weight="1"
  139.                             android:text="运行日志"
  140.                             android:textColor="#FFFFFF"
  141.                             android:gravity="center"
  142.                             android:textSize="14sp"/>
  143.                            
  144.                         <!-- 关闭按钮(仅在展开时可见) -->
  145.                             <Button
  146.                                 android:id="close_button"
  147.                                 android:layout_width="30dp"
  148.                                 android:layout_height="30dp"
  149.                                 android:text="✕"
  150.                                 android:textColor="#FFFFFF"
  151.                                 android:background="#FF4444"
  152.                                 android:textSize="14sp"
  153.                                 android:padding="0dp"
  154.                                 android:gravity="center"/>
  155.                     </LinearLayout>
  156.                     
  157.                     <!-- 日志显示区域(仅在展开时可见) -->
  158.                     <ScrollView
  159.                         android:id="log_container"
  160.                         android:layout_width="match_parent"
  161.                         android:layout_height="match_parent"
  162.                         android:background="#111111">
  163.                         
  164.                         <TextView
  165.                             android:id="log_text"
  166.                             android:layout_width="match_parent"
  167.                             android:layout_height="wrap_content"
  168.                             android:textColor="#00FF00"
  169.                             android:textSize="11sp"
  170.                             android:padding="3dp"
  171.                             android:lineSpacingExtra="1dp"/>
  172.                     </ScrollView>
  173.                     
  174.                     <!-- 展开/收起按钮 -->
  175.                     <Button
  176.                         android:id="toggle_button"
  177.                         android:layout_width="match_parent"
  178.                         android:layout_height="25dp"
  179.                         android:text="≡"
  180.                         android:textColor="#FFFFFF"
  181.                         android:background="#555555"
  182.                         android:textSize="16sp"/>
  183.                 </LinearLayout>
  184.             `);
  185.             printl("✅ XML布局加载成功");
  186.         } catch (xmlError) {
  187.             printl("❌ XML布局加载失败: " + xmlError);
  188.             return false;
  189.         }
  190.         
  191.         // 保存UI实例
  192.         this.ui = fui;
  193.         
  194.         // 保存宽度设置供toggleExpand方法使用
  195.         this.sidebarWidth = sidebarWidth;
  196.         this.sidebarMinWidth = sidebarMinWidth;
  197.         
  198.         // 获取UI元素
  199.         try {
  200.             this.titleBar = fui.findViewById("title_bar");
  201.             this.titleText = fui.findViewById("title_text");
  202.             this.logContainer = fui.findViewById("log_container");
  203.             this.logText = fui.findViewById("log_text");
  204.             this.toggleButton = fui.findViewById("toggle_button");
  205.             this.closeButton = fui.findViewById("close_button"); // 获取关闭按钮
  206.             this.mainContainer = fui.findViewById("main_container");
  207.             
  208.             // 检查关键元素是否存在
  209.             var missingElements = [];
  210.             if (!this.titleBar) missingElements.push("titleBar");
  211.             if (!this.logText) missingElements.push("logText");
  212.             if (!this.toggleButton) missingElements.push("toggleButton");
  213.             if (!this.mainContainer) missingElements.push("mainContainer");
  214.             
  215.             if (missingElements.length > 0) {
  216.                 printl("⚠️ 缺失关键UI元素: " + missingElements.join(", "));
  217.             } else {
  218.                 printl("✅ 所有UI元素获取成功");
  219.             }
  220.         } catch (findError) {
  221.             printl("❌ 获取UI元素失败: " + findError);
  222.         }
  223.         
  224.         // 设置初始位置(屏幕左侧)
  225.         try {
  226.             this.setPos(0, (this.screenHeight - 100) / 2);
  227.             printl("✅ 初始位置设置成功");
  228.         } catch (posError) {
  229.             printl("❌ 设置初始位置失败: " + posError);
  230.         }
  231.         
  232.         // 初始化事件
  233.         try {
  234.             this.initEvents();
  235.             printl("✅ 事件初始化成功");
  236.         } catch (eventError) {
  237.             printl("❌ 事件初始化失败: " + eventError);
  238.         }
  239.         
  240.         // 显示初始化日志
  241.         this.log("✅ 侧栏日志已启动", "#00FF00");
  242.         
  243.         return true;
  244.     } catch (e) {
  245.         printl("❌ 创建侧栏日志失败: " + e);
  246.         return false;
  247.     }
  248. };

  249. // 初始化事件
  250. 侧栏日志.prototype.initEvents = function() {
  251.     var self = this;
  252.    
  253.     // 设置拖拽事件 - 添加更完善的错误处理
  254.     try {
  255.         if (typeof View !== 'undefined' && typeof MotionEvent !== 'undefined' && this.titleBar && this.titleBar.setOnTouchListener) {
  256.             this.titleBar.setOnTouchListener(new View.OnTouchListener({
  257.                 onTouch: function(view, event) {
  258.                     try {
  259.                         switch (event.getAction()) {
  260.                             case MotionEvent.ACTION_DOWN:
  261.                                 self.dragging = true;
  262.                                 self.lastX = event.getRawX();
  263.                                 self.lastY = event.getRawY();
  264.                                 break;
  265.                             case MotionEvent.ACTION_MOVE:
  266.                                 if (self.dragging) {
  267.                                     var dx = event.getRawX() - self.lastX;
  268.                                     var dy = event.getRawY() - self.lastY;
  269.                                     
  270.                                     // 获取当前位置
  271.                                     var currentX = view.getX();
  272.                                     var currentY = view.getY();
  273.                                     
  274.                                     // 计算新位置(考虑整个容器的位置)
  275.                                     var newX = currentX + dx;
  276.                                     var newY = currentY + dy;
  277.                                     
  278.                                     // 边界检查
  279.                                     if (newX < 0) newX = 0;
  280.                                     if (newY < 0) newY = 0;
  281.                                     if (newX > self.screenWidth - (self.isExpanded ? self.sidebarWidth : self.sidebarMinWidth))
  282.                                         newX = self.screenWidth - (self.isExpanded ? self.sidebarWidth : self.sidebarMinWidth);
  283.                                     if (newY > self.screenHeight - 100)
  284.                                         newY = self.screenHeight - 100;
  285.                                     
  286.                                     // 设置新位置
  287.                                     self.setPos(newX, newY);
  288.                                     
  289.                                     // 更新上次触摸位置
  290.                                     self.lastX = event.getRawX();
  291.                                     self.lastY = event.getRawY();
  292.                                 }
  293.                                 break;
  294.                             case MotionEvent.ACTION_UP:
  295.                                 self.dragging = false;
  296.                                 break;
  297.                         }
  298.                         return true;
  299.                     } catch (touchError) {
  300.                         // 静默处理触摸事件错误,避免崩溃
  301.                         return false;
  302.                     }
  303.                 }
  304.             }));
  305.         } else {
  306.             printl("⚠️ 无法设置拖拽事件,缺少必要组件");
  307.         }
  308.     } catch (touchSetupError) {
  309.         printl("❌ 设置拖拽事件失败: " + touchSetupError);
  310.     }
  311.    
  312.     // 展开/收起按钮点击事件
  313.     try {
  314.         if (this.toggleButton && this.toggleButton.setOnClickListener) {
  315.             this.toggleButton.setOnClickListener(function() {
  316.                 try {
  317.                     self.toggleExpand();
  318.                 } catch (toggleError) {
  319.                     printl("❌ 执行展开/收起操作失败: " + toggleError);
  320.                 }
  321.             });
  322.         }
  323.     } catch (toggleSetupError) {
  324.         printl("❌ 设置展开/收起事件失败: " + toggleSetupError);
  325.     }
  326.    
  327.     // 关闭按钮点击事件
  328.     try {
  329.         if (this.closeButton && this.closeButton.setOnClickListener) {
  330.             this.closeButton.setOnClickListener(function() {
  331.                 try {
  332.                     self.close();
  333.                 } catch (closeError) {
  334.                     printl("❌ 执行关闭操作失败: " + closeError);
  335.                 }
  336.             });
  337.         }
  338.     } catch (closeSetupError) {
  339.         printl("❌ 设置关闭事件失败: " + closeSetupError);
  340.     }
  341. };

  342. // 获取当前时间用于日志
  343. 侧栏日志.prototype.getCurrentTime = function() {
  344.     var now = new Date();
  345.     var hours = now.getHours().toString().padStart(2, '0');
  346.     var minutes = now.getMinutes().toString().padStart(2, '0');
  347.     var seconds = now.getSeconds().toString().padStart(2, '0');
  348.     return hours + ':' + minutes + ':' + seconds;
  349. };

  350. // 切换展开/收起状态
  351. 侧栏日志.prototype.toggleExpand = function() {
  352.     try {
  353.         var self = this;
  354.         
  355.         // 记录当前状态变更(使用printl避免递归)
  356.         printl("[" + self.getCurrentTime() + "] " + (self.isExpanded ? "&#128317; 侧栏正在收起" : "&#128316; 侧栏正在展开"));
  357.         // 定义要设置的目标宽度 - 修复逻辑:当前展开时应该设置为收起宽度,当前收起时应该设置为展开宽度
  358.         var targetWidth = this.isExpanded ? this.sidebarMinWidth : this.sidebarWidth;
  359.         
  360.         // 切换展开状态标志
  361.         this.isExpanded = !this.isExpanded;
  362.         
  363.         // 确保在主线程中执行UI操作
  364.         var uiOperation = function() {
  365.             self.performToggleExpand(targetWidth);
  366.         };
  367.         
  368.         // 尝试多种UI线程调度方案
  369.         var threadScheduled = false;
  370.         
  371.         // 方案1: 使用context.runOnUiThread
  372.         try {
  373.             if (context && context.runOnUiThread) {
  374.                 // 使用ES5兼容的方式创建Runnable对象
  375.                 var runnable = {
  376.                     run: function() {
  377.                         try {
  378.                             uiOperation();
  379.                         } catch (e) {
  380.                             printl("❌ UI线程执行失败: " + e);
  381.                         }
  382.                     }
  383.                 };
  384.                 context.runOnUiThread(runnable);
  385.                 threadScheduled = true;
  386.                 printl("✅ 使用context.runOnUiThread调度UI线程");
  387.             }
  388.         } catch (e) {
  389.             printl("❌ 方案1: context.runOnUiThread失败: " + e);
  390.         }
  391.         
  392.         // 方案2: 使用View.post (如果有任何View对象可用)
  393.         if (!threadScheduled) {
  394.             try {
  395.                 var viewToUse = self.mainContainer || self.titleBar || self.toggleButton;
  396.                 if (viewToUse && viewToUse.post) {
  397.                     viewToUse.post(function() {
  398.                         try {
  399.                             uiOperation();
  400.                         } catch (e) {
  401.                             printl("❌ View.post执行失败: " + e);
  402.                         }
  403.                     });
  404.                     threadScheduled = true;
  405.                     printl("✅ 使用View.post调度UI线程");
  406.                 }
  407.             } catch (e) {
  408.                 printl("❌ 方案2: View.post失败: " + e);
  409.             }
  410.         }
  411.         
  412.         // 方案3: 尝试使用Handler (如果可用)
  413.         if (!threadScheduled) {
  414.             try {
  415.                 if (typeof Handler !== 'undefined' && typeof Looper !== 'undefined' && Looper.getMainLooper) {
  416.                     var handler = new Handler(Looper.getMainLooper());
  417.                     handler.post(function() {
  418.                         try {
  419.                             uiOperation();
  420.                         } catch (e) {
  421.                             printl("❌ Handler执行失败: " + e);
  422.                         }
  423.                     });
  424.                     threadScheduled = true;
  425.                     printl("✅ 使用Handler调度UI线程");
  426.                 }
  427.             } catch (e) {
  428.                 printl("❌ 方案3: Handler失败: " + e);
  429.             }
  430.         }
  431.         
  432.         // 方案4: 直接执行作为最后备选 (可能会失败但提供降级方案)
  433.         if (!threadScheduled) {
  434.             printl("⚠️ 所有线程调度方案失败,尝试直接执行UI操作");
  435.             try {
  436.                 uiOperation();
  437.             } catch (directError) {
  438.                 printl("❌ 直接执行UI操作失败: " + directError);
  439.             }
  440.         }
  441.     } catch (e) {
  442.         printl("❌ 切换展开状态失败: " + e);
  443.     }
  444. };
  445. // 执行UI操作的核心方法(应在主线程中调用)
  446. 侧栏日志.prototype.performToggleExpand = function(targetWidth) {
  447.     try {
  448.         var self = this;
  449.         
  450.         // 切换UI元素可见性
  451.         if (!this.isExpanded) {
  452.             // 收起状态
  453.             if (this.titleText && typeof this.titleText.setVisibility === 'function') {
  454.                 try {
  455.                     this.titleText.setVisibility(View.GONE);
  456.                 } catch (e) {
  457.                     printl("❌ 设置titleText可见性失败: " + e);
  458.                 }
  459.             }
  460.             if (this.logContainer && typeof this.logContainer.setVisibility === 'function') {
  461.                 try {
  462.                     this.logContainer.setVisibility(View.GONE);
  463.                 } catch (e) {
  464.                     printl("❌ 设置logContainer可见性失败: " + e);
  465.                 }
  466.             }
  467.             if (this.closeButton && typeof this.closeButton.setVisibility === 'function') {
  468.                 try {
  469.                     this.closeButton.setVisibility(View.GONE); // 收起时隐藏关闭按钮
  470.                 } catch (e) {
  471.                     printl("❌ 设置closeButton可见性失败: " + e);
  472.                 }
  473.             }
  474.         } else {
  475.             // 展开状态
  476.             if (this.titleText && typeof this.titleText.setVisibility === 'function') {
  477.                 try {
  478.                     this.titleText.setVisibility(View.VISIBLE);
  479.                 } catch (e) {
  480.                     printl("❌ 设置titleText可见性失败: " + e);
  481.                 }
  482.             }
  483.             if (this.logContainer && typeof this.logContainer.setVisibility === 'function') {
  484.                 try {
  485.                     this.logContainer.setVisibility(View.VISIBLE);
  486.                 } catch (e) {
  487.                     printl("❌ 设置logContainer可见性失败: " + e);
  488.                 }
  489.             }
  490.             if (this.closeButton && typeof this.closeButton.setVisibility === 'function') {
  491.                 try {
  492.                     this.closeButton.setVisibility(View.VISIBLE); // 展开时显示关闭按钮
  493.                 } catch (e) {
  494.                     printl("❌ 设置closeButton可见性失败: " + e);
  495.                 }
  496.             }
  497.         }
  498.         
  499.         // 尝试多种方法来设置宽度,增加更多的备选方案
  500.         var widthSetSuccessfully = false;
  501.         var errorMessages = [];
  502.         
  503.         // 获取屏幕密度
  504.         var getDensity = function() {
  505.             try {
  506.                 if (context && context.getResources && context.getResources().getDisplayMetrics) {
  507.                     return context.getResources().getDisplayMetrics().density;
  508.                 }
  509.             } catch (e) {
  510.                 printl("⚠️ 获取屏幕密度失败: " + e);
  511.             }
  512.             return 3; // 默认密度
  513.         };
  514.         
  515.         // 方法1: 尝试通过FloatUI对象的可能方法
  516.         try {
  517.             if (this.ui && typeof this.ui.setLayoutWidth === 'function') {
  518.                 this.ui.setLayoutWidth(targetWidth);
  519.                 widthSetSuccessfully = true;
  520.                 printl("方法1: 使用setLayoutWidth设置宽度成功");
  521.             }
  522.         } catch (e) {
  523.             errorMessages.push("方法1: " + (e.message || String(e)));
  524.         }
  525.         
  526.         // 方法2: 尝试通过LayoutParams设置宽度
  527.         if (!widthSetSuccessfully) {
  528.             try {
  529.                 if (this.mainContainer && typeof this.mainContainer.getLayoutParams === 'function' &&
  530.                     typeof this.mainContainer.setLayoutParams === 'function') {
  531.                     var params = this.mainContainer.getLayoutParams();
  532.                     if (params) {
  533.                         // 尝试将dp转换为像素
  534.                         var pixelWidth = Math.round(targetWidth * getDensity());
  535.                         
  536.                         // 安全地设置宽度
  537.                         try {
  538.                             params.width = pixelWidth;
  539.                             this.mainContainer.setLayoutParams(params);
  540.                             widthSetSuccessfully = true;
  541.                             printl("方法2: 使用LayoutParams设置宽度成功");
  542.                         } catch (setParamsError) {
  543.                             errorMessages.push("方法2: " + (setParamsError.message || String(setParamsError)));
  544.                         }
  545.                     }
  546.                 }
  547.             } catch (e) {
  548.                 errorMessages.push("方法2: " + (e.message || String(e)));
  549.             }
  550.         }
  551.         
  552.         // 方法3: 尝试直接设置视图宽度
  553.         if (!widthSetSuccessfully) {
  554.             try {
  555.                 if (this.mainContainer && typeof this.mainContainer.setWidth === 'function') {
  556.                     // 使用已经计算好的像素宽度
  557.                     var pixelWidth = Math.round(targetWidth * getDensity());
  558.                     this.mainContainer.setWidth(pixelWidth);
  559.                     widthSetSuccessfully = true;
  560.                     printl("方法3: 使用setWidth设置宽度成功");
  561.                 }
  562.             } catch (e) {
  563.                 errorMessages.push("方法3: " + (e.message || String(e)));
  564.             }
  565.         }
  566.         
  567.         // 方法4: 尝试修改XML布局参数
  568.         if (!widthSetSuccessfully) {
  569.             try {
  570.                 if (this.ui && typeof this.ui.setLayoutParams === 'function') {
  571.                     // 尝试获取并修改FloatUI的布局参数
  572.                     var floatParams = (typeof this.ui.getLayoutParams === 'function') ? this.ui.getLayoutParams() : null;
  573.                     if (floatParams) {
  574.                         floatParams.width = Math.round(targetWidth * getDensity());
  575.                         this.ui.setLayoutParams(floatParams);
  576.                         widthSetSuccessfully = true;
  577.                         printl("方法4: 使用FloatUI.setLayoutParams设置宽度成功");
  578.                     }
  579.                 }
  580.             } catch (e) {
  581.                 errorMessages.push("方法4: " + (e.message || String(e)));
  582.             }
  583.         }
  584.         
  585.         // 方法5: 尝试使用layout方法直接设置位置和大小
  586.         if (!widthSetSuccessfully) {
  587.             try {
  588.                 if (this.mainContainer && typeof this.mainContainer.layout === 'function') {
  589.                     var left = 0;
  590.                     var top = 0;
  591.                     try {
  592.                         left = this.mainContainer.getLeft();
  593.                         top = this.mainContainer.getTop();
  594.                     } catch (positionError) {
  595.                         // 使用默认位置
  596.                     }
  597.                     var pixelWidth = Math.round(targetWidth * getDensity());
  598.                     var height = 0;
  599.                     try {
  600.                         height = this.mainContainer.getHeight();
  601.                     } catch (heightError) {
  602.                         height = 100; // 默认高度
  603.                     }
  604.                     this.mainContainer.layout(left, top, left + pixelWidth, top + height);
  605.                     widthSetSuccessfully = true;
  606.                     printl("方法5: 使用layout方法设置宽度成功");
  607.                 }
  608.             } catch (e) {
  609.                 errorMessages.push("方法5: " + (e.message || String(e)));
  610.             }
  611.         }
  612.         
  613.         // 尝试UI刷新方法
  614.         if (widthSetSuccessfully) {
  615.             try {
  616.                 if (this.ui && typeof this.ui.updateLayout === 'function') {
  617.                     this.ui.updateLayout();
  618.                     printl("UI布局已更新");
  619.                 } else if (this.mainContainer && typeof this.mainContainer.requestLayout === 'function') {
  620.                     this.mainContainer.requestLayout();
  621.                     printl("请求重新布局");
  622.                 } else if (this.mainContainer && typeof this.mainContainer.invalidate === 'function') {
  623.                     this.mainContainer.invalidate();
  624.                     printl("视图已刷新");
  625.                 }
  626.             } catch (e) {
  627.                 printl("刷新布局失败: " + e);
  628.             }
  629.         }
  630.         
  631.         // 设置按钮文本
  632.         if (this.toggleButton && typeof this.toggleButton.setText === 'function') {
  633.             try {
  634.                 this.toggleButton.setText("≡");
  635.             } catch (e) {
  636.                 printl("❌ 设置按钮文本失败: " + e);
  637.             }
  638.         }
  639.         
  640.         // 延迟100ms后记录状态更新,确保UI已更新
  641.         setTimeout(function() {
  642.             try {
  643.                 if (widthSetSuccessfully) {
  644.                     printl("✅ " + (self.isExpanded ? "侧栏已展开" : "侧栏已收起"));
  645.                 } else {
  646.                     // 只记录第一个错误信息,避免日志过多
  647.                     var mainError = errorMessages.length > 0 ? errorMessages[0] : "未知错误";
  648.                     printl(mainError);
  649.                     printl("⚠️ 侧栏" + (self.isExpanded ? "展开" : "收起") + "但宽度调整失败");
  650.                 }
  651.             } catch (e) {
  652.                 // 静默处理日志错误
  653.             }
  654.         }, 100);
  655.         
  656.         return widthSetSuccessfully;
  657.     } catch (e) {
  658.         printl("❌ 执行切换展开/收起操作失败: " + e);
  659.         return false;
  660.     }
  661. };

  662. // 添加日志
  663. 侧栏日志.prototype.log = function(message, color) {
  664.     try {
  665.         // 生成时间戳
  666.         var now = new Date();
  667.         var timeStr = now.getHours().toString().padStart(2, '0') + ":" +
  668.                       now.getMinutes().toString().padStart(2, '0') + ":" +
  669.                       now.getSeconds().toString().padStart(2, '0');
  670.         
  671.         // 格式化日志条目
  672.         var logEntry = "[" + timeStr + "] " + message;
  673.         
  674.         // 添加到日志数组
  675.         this.logs.push({text: logEntry, color: color || "#00FF00"});
  676.         
  677.         // 限制日志数量
  678.         if (this.logs.length > this.maxLogs) {
  679.             this.logs.shift(); // 移除最早的日志
  680.         }
  681.         
  682.         // 更新显示
  683.         this.updateLogDisplay();
  684.         
  685.         // 同时打印到控制台
  686.         printl(logEntry);
  687.     } catch (e) {
  688.         printl("❌ 添加日志失败: " + e);
  689.     }
  690. };

  691. // 更新日志显示
  692. 侧栏日志.prototype.updateLogDisplay = function() {
  693.     try {
  694.         var self = this;
  695.         var uiOperation = function() {
  696.             self.performUpdateLogDisplay();
  697.         };
  698.         
  699.         // 尝试多种UI线程调度方案
  700.         var threadScheduled = false;
  701.         
  702.         // 方案1: 使用context.runOnUiThread
  703.         try {
  704.             if (context && context.runOnUiThread) {
  705.                 var runnable = {
  706.                     run: function() {
  707.                         try {
  708.                             uiOperation();
  709.                         } catch (e) {
  710.                             printl("❌ UI线程执行日志更新失败: " + e);
  711.                         }
  712.                     }
  713.                 };
  714.                 context.runOnUiThread(runnable);
  715.                 threadScheduled = true;
  716.             }
  717.         } catch (e) {
  718.             printl("❌ 方案1: context.runOnUiThread调度日志更新失败: " + e);
  719.         }
  720.         
  721.         // 方案2: 使用View.post
  722.         if (!threadScheduled) {
  723.             try {
  724.                 var viewToUse = self.logText || self.logContainer || self.mainContainer;
  725.                 if (viewToUse && viewToUse.post) {
  726.                     viewToUse.post(function() {
  727.                         try {
  728.                             uiOperation();
  729.                         } catch (e) {
  730.                             printl("❌ View.post执行日志更新失败: " + e);
  731.                         }
  732.                     });
  733.                     threadScheduled = true;
  734.                 }
  735.             } catch (e) {
  736.                 printl("❌ 方案2: View.post调度日志更新失败: " + e);
  737.             }
  738.         }
  739.         
  740.         // 方案3: 尝试使用Handler
  741.         if (!threadScheduled) {
  742.             try {
  743.                 if (typeof Handler !== 'undefined' && typeof Looper !== 'undefined' && Looper.getMainLooper) {
  744.                     var handler = new Handler(Looper.getMainLooper());
  745.                     handler.post(function() {
  746.                         try {
  747.                             uiOperation();
  748.                         } catch (e) {
  749.                             printl("❌ Handler执行日志更新失败: " + e);
  750.                         }
  751.                     });
  752.                     threadScheduled = true;
  753.                 }
  754.             } catch (e) {
  755.                 printl("❌ 方案3: Handler调度日志更新失败: " + e);
  756.             }
  757.         }
  758.         
  759.         // 方案4: 直接执行作为最后备选
  760.         if (!threadScheduled) {
  761.             try {
  762.                 uiOperation();
  763.             } catch (directError) {
  764.                 printl("❌ 直接执行日志更新失败: " + directError);
  765.             }
  766.         }
  767.     } catch (e) {
  768.         printl("❌ 更新日志显示失败: " + e);
  769.     }
  770. };

  771. // 执行日志显示更新的核心方法(应在主线程中调用)
  772. 侧栏日志.prototype.performUpdateLogDisplay = function() {
  773.     try {
  774.         // 检查logText是否存在
  775.         if (!this.logText || typeof this.logText.setText !== 'function') {
  776.             printl("⚠️ 日志显示组件不可用");
  777.             return;
  778.         }
  779.         
  780.         // 构建日志文本
  781.         var logText = "";
  782.         var useHtml = false;
  783.         
  784.         // 尝试HTML格式
  785.         try {
  786.             if (typeof android.text.Html !== 'undefined' && typeof android.text.Html.fromHtml === 'function') {
  787.                 var htmlText = "";
  788.                 for (var i = 0; i < this.logs.length; i++) {
  789.                     var log = this.logs[i];
  790.                     var color = log.color || "#00FF00";
  791.                     htmlText += "<font color=\"" + color + "\">" + log.text + "</font><br/>";
  792.                 }
  793.                
  794.                 try {
  795.                     var spanned = android.text.Html.fromHtml(htmlText);
  796.                     this.logText.setText(spanned);
  797.                     useHtml = true;
  798.                     printl("✅ 日志使用HTML格式显示");
  799.                 } catch (htmlError) {
  800.                     printl("⚠️ HTML格式化失败,回退到纯文本: " + htmlError);
  801.                 }
  802.             }
  803.         } catch (e) {
  804.             printl("⚠️ HTML支持不可用: " + e);
  805.         }
  806.         
  807.         // 如果HTML格式失败,使用纯文本格式
  808.         if (!useHtml) {
  809.             for (var i = 0; i < this.logs.length; i++) {
  810.                 logText += this.logs[i].text + "\n";
  811.             }
  812.             
  813.             try {
  814.                 this.logText.setText(logText);
  815.                 printl("✅ 日志使用纯文本格式显示");
  816.             } catch (textError) {
  817.                 printl("❌ 设置日志文本失败: " + textError);
  818.             }
  819.         }
  820.         
  821.         // 尝试滚动到底部
  822.         var self = this;
  823.         try {
  824.             if (this.logContainer && typeof this.logContainer.post === 'function') {
  825.                 this.logContainer.post(function() {
  826.                     try {
  827.                         if (self.logContainer && typeof self.logContainer.fullScroll === 'function') {
  828.                             self.logContainer.fullScroll(android.widget.ScrollView.FOCUS_DOWN);
  829.                         }
  830.                     } catch (scrollError) {
  831.                         // 静默处理滚动错误
  832.                     }
  833.                 });
  834.             } else if (this.logContainer && typeof this.logContainer.fullScroll === 'function') {
  835.                 this.logContainer.fullScroll(android.widget.ScrollView.FOCUS_DOWN);
  836.             }
  837.         } catch (e) {
  838.             // 静默处理滚动错误
  839.         }
  840.     } catch (e) {
  841.         printl("❌ 执行日志显示更新失败: " + e);
  842.     }
  843. };

  844. // 设置悬浮窗位置
  845. 侧栏日志.prototype.setPos = function(x, y) {
  846.     try {
  847.         var self = this;
  848.         
  849.         // 参数验证
  850.         if (typeof x !== 'number' || typeof y !== 'number') {
  851.             printl("❌ setPos参数错误: x和y必须是数字");
  852.             return false;
  853.         }
  854.         
  855.         // 边界检查
  856.         var currentWidth = this.isExpanded ? this.sidebarWidth : this.sidebarMinWidth;
  857.         try {
  858.             if (context && context.getResources && context.getResources().getDisplayMetrics) {
  859.                 var density = context.getResources().getDisplayMetrics().density;
  860.                 currentWidth *= density;
  861.             }
  862.         } catch (e) {
  863.             currentWidth *= 3; // 使用默认密度倍数
  864.         }
  865.         
  866.         if (x < 0) x = 0;
  867.         if (y < 0) y = 0;
  868.         if (x > this.screenWidth - currentWidth) x = this.screenWidth - currentWidth;
  869.         if (y > this.screenHeight - 100) y = this.screenHeight - 100;
  870.         
  871.         // 使用printl避免递归调用
  872.         printl("&#128260; 设置悬浮窗位置: x=" + x + ", y=" + y);
  873.         
  874.         // 定义UI操作函数
  875.         var uiOperation = function() {
  876.             self.performSetPos(x, y);
  877.         };
  878.         
  879.         // 尝试多种UI线程调度方案
  880.         var threadScheduled = false;
  881.         
  882.         // 方案1: 使用context.runOnUiThread
  883.         try {
  884.             if (context && context.runOnUiThread) {
  885.                 var runnable = {
  886.                     run: function() {
  887.                         try {
  888.                             uiOperation();
  889.                         } catch (e) {
  890.                             printl("❌ UI线程执行位置设置失败: " + e);
  891.                         }
  892.                     }
  893.                 };
  894.                 context.runOnUiThread(runnable);
  895.                 threadScheduled = true;
  896.                 printl("✅ 使用context.runOnUiThread调度位置设置");
  897.             }
  898.         } catch (e) {
  899.             printl("❌ 方案1: context.runOnUiThread调度位置设置失败: " + e);
  900.         }
  901.         
  902.         // 方案2: 使用View.post
  903.         if (!threadScheduled) {
  904.             try {
  905.                 var viewToUse = self.mainContainer || self.titleBar || self.toggleButton;
  906.                 if (viewToUse && typeof viewToUse.post === 'function') {
  907.                     viewToUse.post(function() {
  908.                         try {
  909.                             uiOperation();
  910.                         } catch (e) {
  911.                             printl("❌ View.post执行位置设置失败: " + e);
  912.                         }
  913.                     });
  914.                     threadScheduled = true;
  915.                     printl("✅ 使用View.post调度位置设置");
  916.                 }
  917.             } catch (e) {
  918.                 printl("❌ 方案2: View.post调度位置设置失败: " + e);
  919.             }
  920.         }
  921.         
  922.         // 方案3: 尝试使用Handler
  923.         if (!threadScheduled) {
  924.             try {
  925.                 if (typeof Handler !== 'undefined' && typeof Looper !== 'undefined' && Looper.getMainLooper) {
  926.                     var handler = new Handler(Looper.getMainLooper());
  927.                     handler.post(function() {
  928.                         try {
  929.                             uiOperation();
  930.                         } catch (e) {
  931.                             printl("❌ Handler执行位置设置失败: " + e);
  932.                         }
  933.                     });
  934.                     threadScheduled = true;
  935.                     printl("✅ 使用Handler调度位置设置");
  936.                 }
  937.             } catch (e) {
  938.                 printl("❌ 方案3: Handler调度位置设置失败: " + e);
  939.             }
  940.         }
  941.         
  942.         // 方案4: 直接执行作为最后备选
  943.         if (!threadScheduled) {
  944.             printl("⚠️ 所有线程调度方案失败,尝试直接执行位置设置");
  945.             try {
  946.                 uiOperation();
  947.             } catch (directError) {
  948.                 printl("❌ 直接执行位置设置失败: " + directError);
  949.             }
  950.         }
  951.         
  952.         return true;
  953.     } catch (e) {
  954.         printl("❌ 设置位置失败: " + e);
  955.         return false;
  956.     }
  957. };

  958. // 执行设置位置的核心方法(应在主线程中调用)
  959. 侧栏日志.prototype.performSetPos = function(x, y) {
  960.     try {
  961.         var posSetSuccess = false;
  962.         
  963.         // 方案1: 尝试使用floatUI的setPos方法
  964.         try {
  965.             if (this.ui && this.ui.setPos) {
  966.                 this.ui.setPos(x, y);
  967.                 posSetSuccess = true;
  968.                 printl("✅ 方案1: 使用floatUI.setPos设置位置成功");
  969.             }
  970.         } catch (e) {
  971.             printl("❌ 方案1: floatUI.setPos失败: " + e);
  972.         }
  973.         
  974.         // 方案2: 尝试使用floatUI的setPosition方法
  975.         if (!posSetSuccess) {
  976.             try {
  977.                 if (this.ui && this.ui.setPosition) {
  978.                     this.ui.setPosition(x, y);
  979.                     posSetSuccess = true;
  980.                     printl("✅ 方案2: 使用floatUI.setPosition设置位置成功");
  981.                 }
  982.             } catch (e) {
  983.                 printl("❌ 方案2: floatUI.setPosition失败: " + e);
  984.             }
  985.         }
  986.         
  987.         // 方案3: 尝试使用setX和setY方法(如果可用)
  988.         if (!posSetSuccess) {
  989.             try {
  990.                 if (this.ui && typeof this.ui.setX === 'function' && typeof this.ui.setY === 'function') {
  991.                     this.ui.setX(x);
  992.                     this.ui.setY(y);
  993.                     posSetSuccess = true;
  994.                     printl("✅ 方案3: 使用ui.setX/setY设置位置成功");
  995.                 }
  996.             } catch (e) {
  997.                 printl("❌ 方案3: ui.setX/setY失败: " + e);
  998.             }
  999.         }
  1000.         
  1001.         // 方案4: 尝试通过mainContainer设置位置
  1002.         if (!posSetSuccess) {
  1003.             try {
  1004.                 if (this.mainContainer && typeof this.mainContainer.setX === 'function' && typeof this.mainContainer.setY === 'function') {
  1005.                     this.mainContainer.setX(x);
  1006.                     this.mainContainer.setY(y);
  1007.                     posSetSuccess = true;
  1008.                     printl("✅ 方案4: 使用mainContainer.setX/setY设置位置成功");
  1009.                 }
  1010.             } catch (e) {
  1011.                 printl("❌ 方案4: mainContainer.setX/setY失败: " + e);
  1012.             }
  1013.         }
  1014.         
  1015.         // 方案5: 尝试通过直接访问mainContainer设置位置
  1016.         if (!posSetSuccess) {
  1017.             try {
  1018.                 if (this.mainContainer && typeof this.mainContainer.layout === 'function' && typeof this.mainContainer.getWidth === 'function' && typeof this.mainContainer.getHeight === 'function') {
  1019.                     this.mainContainer.layout(x, y, x + this.mainContainer.getWidth(), y + this.mainContainer.getHeight());
  1020.                     posSetSuccess = true;
  1021.                     printl("✅ 方案5: 使用layout方法设置位置成功");
  1022.                 }
  1023.             } catch (e) {
  1024.                 printl("❌ 方案5: layout方法失败: " + e);
  1025.             }
  1026.         }
  1027.         
  1028.         // 刷新UI确保位置更新生效
  1029.         if (posSetSuccess) {
  1030.             try {
  1031.                 // 尝试多种刷新方法
  1032.                 if (this.mainContainer) {
  1033.                     if (typeof this.mainContainer.invalidate === 'function') {
  1034.                         this.mainContainer.invalidate();
  1035.                     }
  1036.                     if (typeof this.mainContainer.requestLayout === 'function') {
  1037.                         this.mainContainer.requestLayout();
  1038.                     }
  1039.                 }
  1040.                 printl("✅ 位置设置刷新完成");
  1041.             } catch (refreshError) {
  1042.                 printl("⚠️ 刷新位置时出错: " + refreshError);
  1043.             }
  1044.         } else {
  1045.             printl("⚠️ 位置设置完成但可能未生效");
  1046.         }
  1047.         
  1048.         return posSetSuccess;
  1049.     } catch (e) {
  1050.         printl("❌ 执行位置设置失败: " + e);
  1051.         return false;
  1052.     }
  1053. };

  1054. // 清空日志
  1055. 侧栏日志.prototype.clearLogs = function() {
  1056.     try {
  1057.         // 清空日志数组
  1058.         this.logs = [];
  1059.         
  1060.         // 清空日志显示
  1061.         if (this.logText && this.logText.setText) {
  1062.             try {
  1063.                 this.logText.setText("");
  1064.             } catch (setTextError) {
  1065.                 printl("⚠️ 清空日志显示失败: " + setTextError);
  1066.             }
  1067.         }
  1068.         
  1069.         // 记录清空操作
  1070.         this.log("&#128465;️ 日志已清空", "#FF0000");
  1071.         return true;
  1072.     } catch (e) {
  1073.         printl("❌ 清空日志失败: " + e);
  1074.         return false;
  1075.     }
  1076. };

  1077. // 关闭悬浮窗
  1078. 侧栏日志.prototype.close = function() {
  1079.     try {
  1080.         var self = this;
  1081.         
  1082.         // 使用printl避免递归调用
  1083.         printl("&#128260; 正在关闭侧栏日志悬浮窗...");
  1084.         
  1085.         // 定义UI操作函数
  1086.         var uiOperation = function() {
  1087.             self.performClose();
  1088.         };
  1089.         
  1090.         // 尝试多种UI线程调度方案
  1091.         var threadScheduled = false;
  1092.         
  1093.         // 方案1: 使用context.runOnUiThread
  1094.         try {
  1095.             if (context && context.runOnUiThread) {
  1096.                 var runnable = {
  1097.                     run: function() {
  1098.                         try {
  1099.                             uiOperation();
  1100.                         } catch (e) {
  1101.                             printl("❌ UI线程执行关闭操作失败: " + e);
  1102.                         }
  1103.                     }
  1104.                 };
  1105.                 context.runOnUiThread(runnable);
  1106.                 threadScheduled = true;
  1107.                 printl("✅ 使用context.runOnUiThread调度关闭操作");
  1108.             }
  1109.         } catch (e) {
  1110.             printl("❌ 方案1: context.runOnUiThread调度关闭操作失败: " + e);
  1111.         }
  1112.         
  1113.         // 方案2: 使用View.post
  1114.         if (!threadScheduled) {
  1115.             try {
  1116.                 var viewToUse = self.mainContainer || self.titleBar || self.toggleButton;
  1117.                 if (viewToUse && typeof viewToUse.post === 'function') {
  1118.                     viewToUse.post(function() {
  1119.                         try {
  1120.                             uiOperation();
  1121.                         } catch (e) {
  1122.                             printl("❌ View.post执行关闭操作失败: " + e);
  1123.                         }
  1124.                     });
  1125.                     threadScheduled = true;
  1126.                     printl("✅ 使用View.post调度关闭操作");
  1127.                 }
  1128.             } catch (e) {
  1129.                 printl("❌ 方案2: View.post调度关闭操作失败: " + e);
  1130.             }
  1131.         }
  1132.         
  1133.         // 方案3: 尝试使用Handler
  1134.         if (!threadScheduled) {
  1135.             try {
  1136.                 if (typeof Handler !== 'undefined' && typeof Looper !== 'undefined' && Looper.getMainLooper) {
  1137.                     var handler = new Handler(Looper.getMainLooper());
  1138.                     handler.post(function() {
  1139.                         try {
  1140.                             uiOperation();
  1141.                         } catch (e) {
  1142.                             printl("❌ Handler执行关闭操作失败: " + e);
  1143.                         }
  1144.                     });
  1145.                     threadScheduled = true;
  1146.                     printl("✅ 使用Handler调度关闭操作");
  1147.                 }
  1148.             } catch (e) {
  1149.                 printl("❌ 方案3: Handler调度关闭操作失败: " + e);
  1150.             }
  1151.         }
  1152.         
  1153.         // 方案4: 直接执行作为最后备选
  1154.         if (!threadScheduled) {
  1155.             printl("⚠️ 所有线程调度方案失败,尝试直接执行关闭操作");
  1156.             try {
  1157.                 uiOperation();
  1158.             } catch (directError) {
  1159.                 printl("❌ 直接执行关闭操作失败: " + directError);
  1160.             }
  1161.         }
  1162.     } catch (e) {
  1163.         printl("❌ 关闭侧栏日志悬浮窗失败: " + e);
  1164.     }
  1165. };

  1166. // 执行关闭操作的核心方法(应在主线程中调用)
  1167. 侧栏日志.prototype.performClose = function() {
  1168.     try {
  1169.         printl("&#128260; 执行悬浮窗关闭操作...");
  1170.         
  1171.         // 尝试多种关闭方案
  1172.         var closeSuccess = false;
  1173.         
  1174.         // 方案1: 尝试使用close方法
  1175.         try {
  1176.             if (this.ui && typeof this.ui.close === 'function') {
  1177.                 this.ui.close();
  1178.                 closeSuccess = true;
  1179.                 printl("✅ 方案1: 使用ui.close()成功关闭");
  1180.             }
  1181.         } catch (e) {
  1182.             printl("❌ 方案1: 使用ui.close()关闭失败: " + e);
  1183.         }
  1184.         
  1185.         // 方案2: 尝试使用destroy方法
  1186.         if (!closeSuccess) {
  1187.             try {
  1188.                 if (this.ui && typeof this.ui.destroy === 'function') {
  1189.                     this.ui.destroy();
  1190.                     closeSuccess = true;
  1191.                     printl("✅ 方案2: 使用ui.destroy()成功关闭");
  1192.                 }
  1193.             } catch (e) {
  1194.                 printl("❌ 方案2: 使用ui.destroy()关闭失败: " + e);
  1195.             }
  1196.         }
  1197.         
  1198.         // 方案3: 尝试从父容器移除
  1199.         if (!closeSuccess) {
  1200.             try {
  1201.                 if (this.mainContainer && typeof this.mainContainer.getParent === 'function') {
  1202.                     var parent = this.mainContainer.getParent();
  1203.                     if (parent && typeof parent.removeView === 'function') {
  1204.                         parent.removeView(this.mainContainer);
  1205.                         closeSuccess = true;
  1206.                         printl("✅ 方案3: 从父容器移除成功");
  1207.                     }
  1208.                 }
  1209.             } catch (e) {
  1210.                 printl("❌ 方案3: 从父容器移除失败: " + e);
  1211.             }
  1212.         }
  1213.         
  1214.         // 方案4: 尝试隐藏视图
  1215.         if (!closeSuccess) {
  1216.             try {
  1217.                 if (this.mainContainer && typeof this.mainContainer.setVisibility === 'function') {
  1218.                     this.mainContainer.setVisibility(View.GONE);
  1219.                     closeSuccess = true;
  1220.                     printl("✅ 方案4: 隐藏视图成功");
  1221.                 }
  1222.             } catch (e) {
  1223.                 printl("❌ 方案4: 隐藏视图失败: " + e);
  1224.             }
  1225.         }
  1226.         
  1227.         // 清理资源
  1228.         try {
  1229.             // 清除事件监听器
  1230.             if (this.titleBar && typeof this.titleBar.setOnTouchListener === 'function') {
  1231.                 this.titleBar.setOnTouchListener(null);
  1232.             }
  1233.             if (this.toggleButton && typeof this.toggleButton.setOnClickListener === 'function') {
  1234.                 this.toggleButton.setOnClickListener(null);
  1235.             }
  1236.             if (this.closeButton && typeof this.closeButton.setOnClickListener === 'function') {
  1237.                 this.closeButton.setOnClickListener(null);
  1238.             }
  1239.             
  1240.             // 清除引用,帮助垃圾回收
  1241.             this.ui = null;
  1242.             this.mainContainer = null;
  1243.             this.titleBar = null;
  1244.             this.toggleButton = null;
  1245.             this.closeButton = null;
  1246.             this.titleText = null;
  1247.             this.logContainer = null;
  1248.             this.logText = null;
  1249.             this.logs = null;
  1250.             
  1251.             printl("✅ 资源清理完成");
  1252.         } catch (cleanupError) {
  1253.             printl("⚠️ 资源清理时出错: " + cleanupError);
  1254.         }
  1255.         
  1256.         // 更新状态
  1257.         sidebarLogger = null;
  1258.         
  1259.         // 记录关闭结果
  1260.         if (closeSuccess) {
  1261.             printl("✅ 侧栏日志悬浮窗已成功关闭");
  1262.         } else {
  1263.             printl("⚠️ 侧栏日志悬浮窗尝试关闭,但可能未完全成功");
  1264.         }
  1265.         
  1266.         return closeSuccess;
  1267.     } catch (e) {
  1268.         printl("❌ 执行关闭操作失败: " + e);
  1269.         return false;
  1270.     }
  1271. };

  1272. // 创建并启动侧栏日志悬浮窗
  1273. var sidebarLogger = null;

  1274. // 版本信息
  1275. const SIDEBAR_LOGGER_VERSION = "1.2.0";

  1276. // 初始化悬浮窗
  1277. function initSidebarLogger(options) {
  1278.     try {
  1279.         // 防止重复初始化
  1280.         if (sidebarLogger) {
  1281.             printl("⚠️ 侧栏日志已经初始化,无需重复创建");
  1282.             return sidebarLogger;
  1283.         }
  1284.         
  1285.         // 合并默认选项和用户选项
  1286.         options = options || {};
  1287.         
  1288.         // 环境检查
  1289.         if (typeof floatUI === 'undefined') {
  1290.             printl("❌ 错误:未找到floatUI库,请确保在AIWROK环境中运行!");
  1291.             return null;
  1292.         }
  1293.         
  1294.         // 打印启动信息
  1295.         printl("====================================");
  1296.         printl("&#128260; 侧栏日志悬浮窗初始化中...");
  1297.         printl("&#128241; 版本: " + SIDEBAR_LOGGER_VERSION);
  1298.         printl("====================================");
  1299.         
  1300.         // 创建悬浮窗实例
  1301.         sidebarLogger = new 侧栏日志();
  1302.         
  1303.         // 创建悬浮窗
  1304.         if (sidebarLogger.create()) {
  1305.             printl("✅ 侧栏日志悬浮窗已创建成功!");
  1306.             
  1307.             // 添加欢迎日志
  1308.             sidebarLogger.log("&#127881; 欢迎使用侧栏日志工具", "#00FFFF");
  1309.             sidebarLogger.log("&#128241; 版本: " + SIDEBAR_LOGGER_VERSION, "#00FFFF");
  1310.             sidebarLogger.log("&#128161; 点击≡按钮展开/收起侧栏", "#FFFF00");
  1311.             sidebarLogger.log("&#128260; 拖动标题栏可移动悬浮窗", "#FFFF00");
  1312.             sidebarLogger.log("&#128465;️ 右上角关闭按钮可关闭悬浮窗", "#FFFF00");
  1313.             sidebarLogger.log("&#128161; 可使用sidebarLogger.log()添加自定义日志", "#00FF00");
  1314.             
  1315.             // 自动展开悬浮窗,让用户看到关闭按钮
  1316.             try {
  1317.                 setTimeout(function() {
  1318.                     if (sidebarLogger && typeof sidebarLogger.toggleExpand === 'function') {
  1319.                         sidebarLogger.toggleExpand();
  1320.                     }
  1321.                 }, 500);
  1322.             } catch (autoExpandError) {
  1323.                 printl("⚠️ 自动展开失败: " + autoExpandError);
  1324.             }
  1325.             
  1326.             return sidebarLogger;
  1327.         } else {
  1328.             printl("❌ 侧栏日志悬浮窗创建失败!");
  1329.             sidebarLogger = null;
  1330.             return null;
  1331.         }
  1332.     } catch (e) {
  1333.         printl("❌ 初始化侧栏日志失败: " + e);
  1334.         sidebarLogger = null;
  1335.         return null;
  1336.     }
  1337. }

  1338. // 安全获取侧栏日志实例
  1339. function getSidebarLogger() {
  1340.     return sidebarLogger;
  1341. }

  1342. // 安全地记录日志(即使悬浮窗未初始化也不会报错)
  1343. function safeLog(message, color) {
  1344.     if (sidebarLogger && typeof sidebarLogger.log === 'function') {
  1345.         try {
  1346.             sidebarLogger.log(message, color);
  1347.             return true;
  1348.         } catch (e) {
  1349.             printl("⚠️ 记录日志失败: " + e);
  1350.         }
  1351.     }
  1352.     // 降级到console.log
  1353.     printl(message || "");
  1354.     return false;
  1355. }

  1356. // 启动悬浮窗
  1357. try {
  1358.     // 延迟初始化,确保环境准备就绪
  1359.     setTimeout(function() {
  1360.         initSidebarLogger();
  1361.     }, 100);
  1362. } catch (startupError) {
  1363.     printl("❌ 启动悬浮窗失败: " + startupError);
  1364.     // 作为最后的备选,尝试直接初始化
  1365.     try {
  1366.         initSidebarLogger();
  1367.     } catch (finalError) {
  1368.         printl("❌ 直接初始化也失败: " + finalError);
  1369.     }
  1370. }
复制代码







欢迎光临 B2B网络软件 (http://bbs.niubt.cn/) Powered by Discuz! X3.2