mirror of
https://github.com/oneclickvirt/ecs.git
synced 2025-12-24 12:37:53 +08:00
fix:修复日志tab栏以及日志读取
This commit is contained in:
BIN
embedding/binaries/goecs-darwin-arm64
Executable file
BIN
embedding/binaries/goecs-darwin-arm64
Executable file
Binary file not shown.
@@ -69,70 +69,3 @@ cp ../ecs/goecs-linux-amd64 jniLibs/x86_64/libgoecs.so && \
|
||||
chmod 755 jniLibs/*/libgoecs.so && \
|
||||
ls -lh jniLibs/*/libgoecs.so
|
||||
```
|
||||
|
||||
## 测试验证
|
||||
|
||||
### 1. 验证 APK 包含 .so 文件
|
||||
|
||||
```bash
|
||||
unzip -l your-app.apk | grep "lib/"
|
||||
# 应该看到:
|
||||
# lib/arm64-v8a/libgoecs.so
|
||||
# lib/x86_64/libgoecs.so
|
||||
```
|
||||
|
||||
### 2. 在设备上验证安装位置
|
||||
|
||||
```bash
|
||||
# 安装 APK
|
||||
adb install your-app.apk
|
||||
|
||||
# 查看安装位置
|
||||
adb shell pm path com.oneclickvirt.goecs
|
||||
|
||||
# 查看 native library 目录
|
||||
adb shell ls -l /data/app/com.oneclickvirt.goecs-*/lib/arm64/
|
||||
|
||||
# 测试执行
|
||||
adb shell
|
||||
run-as com.oneclickvirt.goecs
|
||||
cd /data/app/com.oneclickvirt.goecs-*/lib/arm64/
|
||||
./libgoecs.so --help
|
||||
```
|
||||
|
||||
### 3. 查看应用日志
|
||||
|
||||
```bash
|
||||
# 实时查看日志
|
||||
adb logcat | grep -E "(goecs|oneclickvirt)"
|
||||
|
||||
# 只看错误
|
||||
adb logcat *:E | grep goecs
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
如果看到 "fork/exec" 错误:
|
||||
|
||||
1. **检查文件是否存在**
|
||||
```bash
|
||||
adb shell run-as com.oneclickvirt.goecs find /data/app -name "libgoecs.so"
|
||||
```
|
||||
|
||||
2. **检查编译架构是否匹配设备**
|
||||
```bash
|
||||
adb shell getprop ro.product.cpu.abi
|
||||
# arm64-v8a -> 需要 jniLibs/arm64-v8a/libgoecs.so
|
||||
# x86_64 -> 需要 jniLibs/x86_64/libgoecs.so
|
||||
```
|
||||
|
||||
3. **验证文件不是空的**
|
||||
```bash
|
||||
ls -lh jniLibs/*/libgoecs.so
|
||||
# 文件应该有合理的大小(几MB到几十MB)
|
||||
```
|
||||
|
||||
4. **检查应用日志中的详细错误信息**
|
||||
- embedding 代码会输出所有检查过的路径
|
||||
- 查看 logcat 获取详细信息
|
||||
|
||||
|
||||
3
main.go
3
main.go
@@ -42,6 +42,9 @@ func runGUIMode() {
|
||||
myApp := app.NewWithID("com.oneclickvirt.goecs")
|
||||
myApp.Settings().SetTheme(&ui.CustomTheme{})
|
||||
|
||||
// 设置为浅色主题
|
||||
myApp.Settings().SetTheme(&ui.CustomTheme{})
|
||||
|
||||
testUI := ui.NewTestUI(myApp)
|
||||
testUI.Window.ShowAndRun()
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ type CustomTheme struct{}
|
||||
var _ fyne.Theme = (*CustomTheme)(nil)
|
||||
|
||||
func (m *CustomTheme) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) color.Color {
|
||||
return theme.DefaultTheme().Color(name, variant)
|
||||
// 强制使用浅色主题
|
||||
return theme.DefaultTheme().Color(name, theme.VariantLight)
|
||||
}
|
||||
|
||||
func (m *CustomTheme) Icon(name fyne.ThemeIconName) fyne.Resource {
|
||||
|
||||
230
ui/ui_actions.go
230
ui/ui_actions.go
@@ -2,10 +2,8 @@ package ui
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
@@ -136,13 +134,6 @@ func (ui *TestUI) startTests() {
|
||||
ui.ProgressBar.Show()
|
||||
ui.StatusLabel.SetText("测试运行中...")
|
||||
|
||||
// 如果启用了日志,显示日志标签页
|
||||
if ui.LogCheck != nil && ui.LogCheck.Checked {
|
||||
ui.showLogTab()
|
||||
} else {
|
||||
ui.hideLogTab()
|
||||
}
|
||||
|
||||
// 清空终端输出
|
||||
if ui.Terminal != nil {
|
||||
ui.Terminal.Clear()
|
||||
@@ -204,119 +195,162 @@ func (ui *TestUI) exportResults() {
|
||||
}, ui.Window)
|
||||
}
|
||||
|
||||
// showLogTab 显示日志标签页
|
||||
func (ui *TestUI) showLogTab() {
|
||||
// 如果日志标签页还不存在,创建它
|
||||
if ui.LogTab == nil {
|
||||
ui.LogTab = ui.createLogTab()
|
||||
logTabItem := container.NewTabItem("日志查看", ui.LogTab)
|
||||
ui.MainTabs.Append(logTabItem)
|
||||
}
|
||||
|
||||
// 切换到日志标签页
|
||||
ui.MainTabs.SelectIndex(2) // 0=配置, 1=结果, 2=日志
|
||||
}
|
||||
|
||||
// hideLogTab 隐藏日志标签页
|
||||
func (ui *TestUI) hideLogTab() {
|
||||
// 如果有日志标签页,移除它
|
||||
if ui.LogTab != nil && len(ui.MainTabs.Items) > 2 {
|
||||
ui.MainTabs.Remove(ui.MainTabs.Items[2])
|
||||
ui.LogTab = nil
|
||||
ui.LogViewer = nil
|
||||
// onLogCheckChanged 当日志复选框状态改变时调用
|
||||
func (ui *TestUI) onLogCheckChanged(checked bool) {
|
||||
if checked {
|
||||
// 勾选时添加日志标签页
|
||||
ui.addLogTab()
|
||||
} else {
|
||||
// 取消勾选时移除日志标签页
|
||||
ui.removeLogTab()
|
||||
}
|
||||
}
|
||||
|
||||
// createLogTab 创建日志查看标签页
|
||||
func (ui *TestUI) createLogTab() *fyne.Container {
|
||||
// addLogTab 添加日志标签页
|
||||
func (ui *TestUI) addLogTab() {
|
||||
// 如果日志标签页已存在,不重复添加
|
||||
if ui.LogTab != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建日志查看器
|
||||
ui.LogViewer = widget.NewMultiLineEntry()
|
||||
ui.LogViewer.SetPlaceHolder("日志内容将在测试运行时显示...")
|
||||
ui.LogViewer.Wrapping = fyne.TextWrapWord
|
||||
ui.LogViewer.SetText("日志文件内容将在这里显示...")
|
||||
ui.LogViewer.Disable() // 只读
|
||||
|
||||
// 刷新按钮
|
||||
refreshButton := widget.NewButton("刷新日志", ui.refreshLog)
|
||||
|
||||
// 清空按钮
|
||||
clearLogButton := widget.NewButton("清空显示", func() {
|
||||
if ui.LogViewer != nil {
|
||||
ui.LogViewer.SetText("")
|
||||
}
|
||||
// 刷新日志按钮
|
||||
refreshButton := widget.NewButton("刷新日志", func() {
|
||||
ui.refreshLogFromFile()
|
||||
})
|
||||
|
||||
topBar := container.NewHBox(
|
||||
// 清空日志按钮
|
||||
clearLogButton := widget.NewButton("清空日志", func() {
|
||||
ui.LogContent = ""
|
||||
ui.LogViewer.SetText("")
|
||||
})
|
||||
|
||||
// 导出日志按钮
|
||||
exportLogButton := widget.NewButton("导出日志", ui.exportLogContent)
|
||||
|
||||
// 按钮栏
|
||||
buttonBar := container.NewHBox(
|
||||
refreshButton,
|
||||
clearLogButton,
|
||||
exportLogButton,
|
||||
)
|
||||
|
||||
// 日志内容区域
|
||||
logScroll := container.NewScroll(ui.LogViewer)
|
||||
|
||||
return container.NewBorder(
|
||||
topBar, // Top: 操作按钮
|
||||
// 组合布局
|
||||
logContent := container.NewBorder(
|
||||
buttonBar, // Top: 按钮栏
|
||||
nil, // Bottom
|
||||
nil, // Left
|
||||
nil, // Right
|
||||
logScroll, // Center: 日志内容
|
||||
)
|
||||
|
||||
// 创建并添加日志标签页
|
||||
ui.LogTab = container.NewTabItem("日志", logContent)
|
||||
ui.MainTabs.Append(ui.LogTab)
|
||||
|
||||
// 初始化日志内容
|
||||
ui.LogContent = ""
|
||||
}
|
||||
|
||||
// refreshLog 刷新日志内容
|
||||
func (ui *TestUI) refreshLog() {
|
||||
// removeLogTab 移除日志标签页
|
||||
func (ui *TestUI) removeLogTab() {
|
||||
if ui.LogTab == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 从标签页容器中移除
|
||||
ui.MainTabs.Remove(ui.LogTab)
|
||||
ui.LogTab = nil
|
||||
ui.LogViewer = nil
|
||||
ui.LogContent = ""
|
||||
}
|
||||
|
||||
// refreshLogContent 刷新日志内容
|
||||
func (ui *TestUI) refreshLogContent() {
|
||||
if ui.LogViewer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取当前目录
|
||||
currentDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
ui.LogViewer.SetText("错误: 无法获取当前目录\n" + err.Error())
|
||||
return
|
||||
// 显示存储的日志内容
|
||||
if ui.LogContent != "" {
|
||||
ui.LogViewer.SetText(ui.LogContent)
|
||||
} else {
|
||||
ui.LogViewer.SetText("暂无日志内容\n\n日志将在测试运行时自动更新。")
|
||||
}
|
||||
|
||||
// 查找所有 .log 文件
|
||||
logFiles, err := filepath.Glob(filepath.Join(currentDir, "*.log"))
|
||||
if err != nil {
|
||||
ui.LogViewer.SetText("错误: 无法搜索日志文件\n" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if len(logFiles) == 0 {
|
||||
ui.LogViewer.SetText("当前目录下没有找到 .log 文件\n\n请确保已启用日志记录并运行测试。")
|
||||
return
|
||||
}
|
||||
|
||||
// 找到最新的日志文件
|
||||
var latestLog string
|
||||
var latestTime time.Time
|
||||
|
||||
for _, logFile := range logFiles {
|
||||
info, err := os.Stat(logFile)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if latestLog == "" || info.ModTime().After(latestTime) {
|
||||
latestLog = logFile
|
||||
latestTime = info.ModTime()
|
||||
}
|
||||
}
|
||||
|
||||
if latestLog == "" {
|
||||
ui.LogViewer.SetText("没有找到有效的日志文件")
|
||||
return
|
||||
}
|
||||
|
||||
// 读取日志文件内容
|
||||
content, err := os.ReadFile(latestLog)
|
||||
if err != nil {
|
||||
ui.LogViewer.SetText("错误: 无法读取日志文件 " + latestLog + "\n" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 显示日志内容
|
||||
logContent := "日志文件: " + filepath.Base(latestLog) + "\n"
|
||||
logContent += "修改时间: " + latestTime.Format("2006-01-02 15:04:05") + "\n"
|
||||
logContent += strings.Repeat("=", 60) + "\n\n"
|
||||
logContent += string(content)
|
||||
|
||||
ui.LogViewer.SetText(logContent)
|
||||
}
|
||||
|
||||
// refreshLogFromFile 从 ecs.log 文件读取日志内容
|
||||
func (ui *TestUI) refreshLogFromFile() {
|
||||
if ui.LogViewer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// ecs.log 文件应该在当前工作目录下
|
||||
logFilePath := "ecs.log"
|
||||
|
||||
// 尝试读取日志文件
|
||||
content, err := os.ReadFile(logFilePath)
|
||||
if err != nil {
|
||||
// 如果文件不存在或无法读取,显示错误信息
|
||||
if os.IsNotExist(err) {
|
||||
ui.LogViewer.SetText("日志文件 ecs.log 不存在\n\n可能测试未生成日志文件,或文件已被删除。")
|
||||
} else {
|
||||
ui.LogViewer.SetText(fmt.Sprintf("无法读取日志文件: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 更新日志内容
|
||||
ui.LogContent = string(content)
|
||||
ui.LogViewer.SetText(ui.LogContent)
|
||||
}
|
||||
|
||||
// exportLogContent 导出日志内容
|
||||
func (ui *TestUI) exportLogContent() {
|
||||
if ui.LogViewer == nil || ui.LogViewer.Text == "" {
|
||||
dialog.ShowInformation("提示", "没有可导出的日志内容", ui.Window)
|
||||
return
|
||||
}
|
||||
|
||||
// 使用文件保存对话框
|
||||
dialog.ShowFileSave(func(writer fyne.URIWriteCloser, err error) {
|
||||
if err != nil {
|
||||
dialog.ShowError(err, ui.Window)
|
||||
return
|
||||
}
|
||||
if writer == nil {
|
||||
return
|
||||
}
|
||||
defer writer.Close()
|
||||
|
||||
// 写入日志内容
|
||||
_, err = writer.Write([]byte(ui.LogViewer.Text))
|
||||
if err != nil {
|
||||
dialog.ShowError(err, ui.Window)
|
||||
return
|
||||
}
|
||||
|
||||
dialog.ShowInformation("成功", "日志已成功导出", ui.Window)
|
||||
}, ui.Window)
|
||||
}
|
||||
|
||||
// AppendLog 向日志内容追加文本
|
||||
func (ui *TestUI) AppendLog(text string) {
|
||||
if !ui.LogCheck.Checked || ui.LogViewer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ui.Mu.Lock()
|
||||
defer ui.Mu.Unlock()
|
||||
|
||||
ui.LogContent += text
|
||||
ui.LogViewer.SetText(ui.LogContent)
|
||||
}
|
||||
|
||||
@@ -16,11 +16,6 @@ func (ui *TestUI) runTestsWithExecutor() {
|
||||
|
||||
startTime := time.Now()
|
||||
|
||||
// 清空终端并显示开始信息
|
||||
ui.Terminal.AppendText("==========================================\n")
|
||||
ui.Terminal.AppendText(" 融合怪测试 - 开始执行\n")
|
||||
ui.Terminal.AppendText("==========================================\n\n")
|
||||
|
||||
// 创建命令执行器
|
||||
executor, err := NewCommandExecutor(ui, ui.CancelCtx)
|
||||
if err != nil {
|
||||
@@ -32,8 +27,7 @@ func (ui *TestUI) runTestsWithExecutor() {
|
||||
|
||||
// 显示将要执行的命令
|
||||
cmdPreview := executor.GetCommandPreview()
|
||||
ui.Terminal.AppendText(fmt.Sprintf("执行命令: %s\n\n", cmdPreview))
|
||||
ui.Terminal.AppendText("==========================================\n\n")
|
||||
ui.Terminal.AppendText(fmt.Sprintf("执行命令: %s\n", cmdPreview))
|
||||
|
||||
// 更新进度
|
||||
ui.ProgressBar.SetValue(0.1)
|
||||
@@ -45,36 +39,22 @@ func (ui *TestUI) runTestsWithExecutor() {
|
||||
// 显示结束信息
|
||||
endTime := time.Now()
|
||||
duration := endTime.Sub(startTime)
|
||||
minutes := int(duration.Minutes())
|
||||
seconds := int(duration.Seconds()) % 60
|
||||
|
||||
ui.Terminal.AppendText("\n\n==========================================\n")
|
||||
_ = duration // 避免未使用警告
|
||||
|
||||
if err != nil {
|
||||
ui.Terminal.AppendText(fmt.Sprintf("错误: %v\n", err))
|
||||
ui.Terminal.AppendText(fmt.Sprintf("\n错误: %v\n", err))
|
||||
ui.StatusLabel.SetText("测试失败")
|
||||
} else if ui.isCancelled() {
|
||||
ui.Terminal.AppendText("测试被用户中断\n")
|
||||
ui.Terminal.AppendText("\n测试被用户中断\n")
|
||||
ui.StatusLabel.SetText("测试已停止")
|
||||
} else {
|
||||
language := "zh"
|
||||
if ui.LanguageSelect.Selected == "English" {
|
||||
language = "en"
|
||||
}
|
||||
|
||||
if language == "zh" {
|
||||
ui.Terminal.AppendText(fmt.Sprintf("花费时间: %d 分 %d 秒\n", minutes, seconds))
|
||||
} else {
|
||||
ui.Terminal.AppendText(fmt.Sprintf("Cost Time: %d min %d sec\n", minutes, seconds))
|
||||
}
|
||||
|
||||
ui.StatusLabel.SetText("测试完成")
|
||||
ui.ProgressBar.SetValue(1.0)
|
||||
|
||||
// 如果启用了日志,自动刷新日志内容
|
||||
if ui.LogCheck != nil && ui.LogCheck.Checked {
|
||||
time.Sleep(500 * time.Millisecond) // 等待日志文件写入完成
|
||||
ui.refreshLog()
|
||||
ui.refreshLogFromFile()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ func (ui *TestUI) createOptionsPanel() fyne.CanvasObject {
|
||||
ui.PingCheck = widget.NewCheck("三网PING值检测", nil)
|
||||
ui.PingCheck.Checked = false
|
||||
|
||||
ui.LogCheck = widget.NewCheck("启用日志记录", nil)
|
||||
ui.LogCheck = widget.NewCheck("启用日志记录", ui.onLogCheckChanged)
|
||||
ui.LogCheck.Checked = false
|
||||
|
||||
// 全选/取消全选按钮
|
||||
|
||||
@@ -54,9 +54,10 @@ type TestUI struct {
|
||||
StatusLabel *widget.Label
|
||||
|
||||
// 日志相关
|
||||
LogViewer *widget.Entry // 日志查看器
|
||||
LogTab *fyne.Container // 日志标签页内容
|
||||
MainTabs *container.AppTabs // 主标签页容器
|
||||
LogViewer *widget.Entry // 日志查看器
|
||||
LogTab *container.TabItem // 日志标签页
|
||||
MainTabs *container.AppTabs // 主标签页容器
|
||||
LogContent string // 日志内容存储
|
||||
|
||||
// 运行状态
|
||||
IsRunning bool
|
||||
|
||||
Reference in New Issue
Block a user