Golang Code
This commit is contained in:
		
							parent
							
								
									f016dc4676
								
							
						
					
					
						commit
						b364b06206
					
				
							
								
								
									
										27
									
								
								app.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"fmt" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // App struct
 | ||||||
|  | type App struct { | ||||||
|  | 	ctx context.Context | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewApp creates a new App application struct
 | ||||||
|  | func NewApp() *App { | ||||||
|  | 	return &App{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // startup is called when the app starts. The context is saved
 | ||||||
|  | // so we can call the runtime methods
 | ||||||
|  | func (a *App) startup(ctx context.Context) { | ||||||
|  | 	a.ctx = ctx | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Greet returns a greeting for the given name
 | ||||||
|  | func (a *App) Greet(name string) string { | ||||||
|  | 	return fmt.Sprintf("Hello %s, It's show time!", name) | ||||||
|  | } | ||||||
							
								
								
									
										120
									
								
								conf.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								conf.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type AppConf struct { | ||||||
|  | 	Path          string `json:"Path"` | ||||||
|  | 	LastWorkspace string `json:"lastWorkspace"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var appConf *AppConf | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	readConfig() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func readConfig() { | ||||||
|  | 	appConf = &AppConf{} | ||||||
|  | 	_, err := os.Stat("conf.json") | ||||||
|  | 	if os.IsNotExist(err) { | ||||||
|  | 		fmt.Println("创建conf.json") | ||||||
|  | 		file, err := os.Create("conf.json") | ||||||
|  | 		if err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 		defer file.Close() | ||||||
|  | 	} | ||||||
|  | 	file, err := os.ReadFile("conf.json") | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	json.Unmarshal(file, appConf) | ||||||
|  | 	fmt.Println("读取配置文件成功") | ||||||
|  | 	fmt.Println(appConf) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetConfig() *AppConf { | ||||||
|  | 	return appConf | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func SetPath(path string) { | ||||||
|  | 	appConf.Path = path | ||||||
|  | 	confJson, err := json.Marshal(appConf) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	os.WriteFile("conf.json", confJson, os.ModePerm) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func SetWorkSpace(workspace string) { | ||||||
|  | 	appConf.LastWorkspace = workspace | ||||||
|  | 	confJson, err := json.Marshal(appConf) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	os.WriteFile("conf.json", confJson, os.ModePerm) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type WorkspaceConf struct { | ||||||
|  | 	BrowserPath string `json:"browserPath"` | ||||||
|  | 	BrowserType string `json:"browserType"` | ||||||
|  | 	Workspace   string `json:"workspace"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func readWorkspaceConf(workspace string) (*WorkspaceConf, error) { | ||||||
|  | 	currWorkConf := &WorkspaceConf{} | ||||||
|  | 	dataDir := GetDataDir() | ||||||
|  | 	workDir := filepath.Join(dataDir, workspace) | ||||||
|  | 	_, err := os.Stat(workDir) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	confJson, err := os.ReadFile(filepath.Join(workDir, "workspace.json")) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	err = json.Unmarshal(confJson, currWorkConf) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return currWorkConf, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetCurrWorkspaceConf() *WorkspaceConf { | ||||||
|  | 	conf, err := readWorkspaceConf(GetConfig().LastWorkspace) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	return conf | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetCurrWorkspace() string { | ||||||
|  | 	return GetConfig().LastWorkspace | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func SetBrowserPath(browserPath string) { | ||||||
|  | 	conf := GetCurrWorkspaceConf() | ||||||
|  | 	conf.BrowserPath = browserPath | ||||||
|  | 	conf.WriteToFile() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func SetBrowserType(browserType string) { | ||||||
|  | 	conf := GetCurrWorkspaceConf() | ||||||
|  | 	conf.BrowserType = browserType | ||||||
|  | 	conf.WriteToFile() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (conf *WorkspaceConf) WriteToFile() { | ||||||
|  | 	confJson, _ := json.Marshal(conf) | ||||||
|  | 	jsonDir := filepath.Join(GetDataDir(), conf.Workspace, "workspace.json") | ||||||
|  | 	fmt.Printf("写出配置文件: %v -> %v\n", jsonDir, confJson) | ||||||
|  | 	err := os.WriteFile(jsonDir, confJson, os.ModePerm) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								dto.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								dto.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | type Dto struct { | ||||||
|  | 	Code int         `json:"code"` | ||||||
|  | 	Msg  string      `json:"msg"` | ||||||
|  | 	Data interface{} `json:"data"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewDto(code int, msg string, data interface{}) *Dto { | ||||||
|  | 	return &Dto{ | ||||||
|  | 		Code: code, | ||||||
|  | 		Msg:  msg, | ||||||
|  | 		Data: data, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func FailDto(msg string, data interface{}) *Dto { | ||||||
|  | 	return NewDto(1, msg, data) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func SuccessDto(data interface{}) *Dto { | ||||||
|  | 	return NewDto(200, "success", data) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Dto) IsSuccess() bool { | ||||||
|  | 	return d.Code == 200 | ||||||
|  | } | ||||||
							
								
								
									
										219
									
								
								event-home.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								event-home.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,219 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/wailsapp/wails/v2/pkg/runtime" | ||||||
|  | 	"golang.org/x/sys/windows/registry" | ||||||
|  | 	"os" | ||||||
|  | 	"os/exec" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type HomeEvent struct { | ||||||
|  | 	ctx context.Context | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewHomeEvent() *HomeEvent { | ||||||
|  | 	return &HomeEvent{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) startup(ctx context.Context) { | ||||||
|  | 	a.ctx = ctx | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) ListWorkspace() *Dto { | ||||||
|  | 	dirs := GetWorkspaceDirs() | ||||||
|  | 	return SuccessDto(dirs) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) AddWorkspace(name string) *Dto { | ||||||
|  | 	runtime.LogInfo(a.ctx, "创建工作空间: "+name) | ||||||
|  | 	dataDir := GetDataDir() | ||||||
|  | 	workspaceDir := filepath.Join(dataDir, name) | ||||||
|  | 	_, err := os.Stat(workspaceDir) | ||||||
|  | 	if os.IsExist(err) { | ||||||
|  | 		return FailDto("目录已存在", nil) | ||||||
|  | 	} | ||||||
|  | 	err = os.Mkdir(workspaceDir, os.ModePerm) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return FailDto("创建目录失败", err) | ||||||
|  | 	} | ||||||
|  | 	runtime.LogInfo(a.ctx, "创建工作空间成功: "+name) | ||||||
|  | 	runtime.LogInfo(a.ctx, "创建默认配置文件: "+name) | ||||||
|  | 	newConf := &WorkspaceConf{ | ||||||
|  | 		BrowserPath: "", | ||||||
|  | 		BrowserType: "", | ||||||
|  | 		Workspace:   name, | ||||||
|  | 	} | ||||||
|  | 	pathDto := a.GetDefaultBrowserPath() | ||||||
|  | 	if pathDto.IsSuccess() { | ||||||
|  | 		path := pathDto.Data.(string) | ||||||
|  | 		newConf.BrowserPath = path | ||||||
|  | 		// 通过路径是否为chrome.exe结尾
 | ||||||
|  | 		if strings.HasSuffix(path, "chrome.exe") { | ||||||
|  | 			newConf.BrowserType = "chrome" | ||||||
|  | 		} else if strings.HasSuffix(path, "firefox.exe") { | ||||||
|  | 			newConf.BrowserType = "firefox" | ||||||
|  | 		} else if strings.HasSuffix(path, "msedge.exe") { | ||||||
|  | 			newConf.BrowserType = "edge" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	newConfInfo := fmt.Sprintf("默认配置: BrowserPath -> %v, BrowserType -> %v, Workspace -> %v", newConf.BrowserPath, newConf.BrowserType, newConf.Workspace) | ||||||
|  | 	runtime.LogInfo(a.ctx, newConfInfo) | ||||||
|  | 	newConf.WriteToFile() | ||||||
|  | 	return SuccessDto(nil) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) GetCurrWorkspace() *Dto { | ||||||
|  | 	config := GetConfig() | ||||||
|  | 	workspace := config.LastWorkspace | ||||||
|  | 	return SuccessDto(workspace) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) SetCurrentWorkspace(workspace string) *Dto { | ||||||
|  | 	SetWorkSpace(workspace) | ||||||
|  | 	return SuccessDto("") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) LoadCurrWorkspaceConf() *Dto { | ||||||
|  | 	currWorkConf := GetCurrWorkspaceConf() | ||||||
|  | 	return SuccessDto(currWorkConf) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) LoadBrowserConf() *Dto { | ||||||
|  | 	config := GetConfig() | ||||||
|  | 	path := config.Path | ||||||
|  | 	if path != "" { | ||||||
|  | 		return SuccessDto(path) | ||||||
|  | 	} | ||||||
|  | 	dto := a.GetDefaultBrowserPath() | ||||||
|  | 	if !dto.IsSuccess() { | ||||||
|  | 		dto = a.SelectPath("") | ||||||
|  | 	} | ||||||
|  | 	if dto.IsSuccess() { | ||||||
|  | 		SetPath(dto.Data.(string)) | ||||||
|  | 	} | ||||||
|  | 	return dto | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) GetDefaultBrowserPath() *Dto { | ||||||
|  | 	keyPath := `Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice` | ||||||
|  | 	key, err := registry.OpenKey(registry.CURRENT_USER, keyPath, registry.QUERY_VALUE) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return FailDto("无法打开注册表项: "+keyPath, err) | ||||||
|  | 	} | ||||||
|  | 	defer key.Close() | ||||||
|  | 	progId, _, err := key.GetStringValue("Progid") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return FailDto("无法获取注册表值: "+progId, err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Println("获取注册表值成功, Progid -> {}", progId) | ||||||
|  | 	commandKeyPath := progId + `\shell\open\command` | ||||||
|  | 	commandKey, err := registry.OpenKey(registry.CLASSES_ROOT, commandKeyPath, registry.QUERY_VALUE) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return FailDto("无法打开注册表项: "+commandKeyPath, err) | ||||||
|  | 	} | ||||||
|  | 	defer commandKey.Close() | ||||||
|  | 	command, _, err := commandKey.GetStringValue("") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return FailDto("无法读取注册表值: "+command, err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Printf("读取注册表成功: 默认浏览器命令: %v\n", command) | ||||||
|  | 	args := splitCommandLine(command) | ||||||
|  | 	fmt.Println("命令解析结果: {}", args) | ||||||
|  | 	command = args[0] | ||||||
|  | 	command = strings.Trim(command, "\"") | ||||||
|  | 	return SuccessDto(command) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) SelectPath(curr string) *Dto { | ||||||
|  | 	currPath := "." | ||||||
|  | 	currName := "" | ||||||
|  | 	if curr != "" { | ||||||
|  | 		currPath = filepath.Dir(curr) | ||||||
|  | 		currName = filepath.Base(curr) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	path, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{ | ||||||
|  | 		DefaultDirectory: currPath, | ||||||
|  | 		DefaultFilename:  currName, | ||||||
|  | 		Filters: []runtime.FileFilter{ | ||||||
|  | 			{ | ||||||
|  | 				DisplayName: "可执行程序", | ||||||
|  | 				Pattern:     "*.exe", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return FailDto("选择文件失败", err) | ||||||
|  | 	} | ||||||
|  | 	SetBrowserPath(path) | ||||||
|  | 	return SuccessDto(path) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) ChangeBrowserType(browserType string) *Dto { | ||||||
|  | 	SetBrowserType(browserType) | ||||||
|  | 	return SuccessDto("") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) ListInstance() *Dto { | ||||||
|  | 	dirs := GetInstanceDirs() | ||||||
|  | 	return SuccessDto(dirs) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) AddInstance(name string) *Dto { | ||||||
|  | 	dataDir := GetDataDir() | ||||||
|  | 	workspace := GetCurrWorkspace() | ||||||
|  | 	_, err := os.Stat(filepath.Join(dataDir, workspace, name)) | ||||||
|  | 	if os.IsExist(err) { | ||||||
|  | 		return FailDto("实例已存在", nil) | ||||||
|  | 	} | ||||||
|  | 	err = os.Mkdir(filepath.Join(dataDir, workspace, name), os.ModePerm) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return FailDto("创建实例失败", err) | ||||||
|  | 	} | ||||||
|  | 	return SuccessDto(nil) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *HomeEvent) StartInstance(name string) *Dto { | ||||||
|  | 	conf := GetCurrWorkspaceConf() | ||||||
|  | 	browserPath := conf.BrowserPath | ||||||
|  | 	browserType := conf.BrowserType | ||||||
|  | 	if browserPath == "" { | ||||||
|  | 		return FailDto("请选择浏览器可执行路径", nil) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_, err := os.Stat(browserPath) | ||||||
|  | 	if os.IsNotExist(err) { | ||||||
|  | 		return FailDto("可执行程序不存在", nil) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	dataDir := GetDataDir() | ||||||
|  | 	workspace := GetCurrWorkspace() | ||||||
|  | 	instancePath := filepath.Join(dataDir, workspace, name) | ||||||
|  | 	var arg []string | ||||||
|  | 	if browserType == "chrome" { | ||||||
|  | 		arg = append(arg, "--user-data-dir="+instancePath) | ||||||
|  | 	} else if browserType == "edge" { | ||||||
|  | 		arg = append(arg, "--user-data-dir="+instancePath) | ||||||
|  | 	} else if browserType == "firefox" { | ||||||
|  | 		arg = append(arg, "--profile", instancePath) | ||||||
|  | 	} else { | ||||||
|  | 		return FailDto("不支持的浏览器类型", nil) | ||||||
|  | 	} | ||||||
|  | 	runInfo := fmt.Sprintf("浏览器路径: %s, 启动参数: %s", browserPath, arg) | ||||||
|  | 	runtime.LogInfo(a.ctx, runInfo) | ||||||
|  | 	cmd := exec.Command(browserPath, arg...) | ||||||
|  | 	//cmd.Stdout = os.Stdout
 | ||||||
|  | 	//cmd.Stderr = os.Stderr
 | ||||||
|  | 	//cmd.Stdin = os.Stdin
 | ||||||
|  | 	err = cmd.Start() | ||||||
|  | 	if err != nil { | ||||||
|  | 		runtime.LogError(a.ctx, "启动浏览器失败: "+err.Error()) | ||||||
|  | 		return FailDto("启动浏览器失败", err) | ||||||
|  | 	} | ||||||
|  | 	runtime.LogInfo(a.ctx, "启动浏览器成功") | ||||||
|  | 	return SuccessDto(nil) | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | module chrome-multi | ||||||
|  | 
 | ||||||
|  | go 1.23 | ||||||
|  | 
 | ||||||
|  | require ( | ||||||
|  | 	github.com/wailsapp/wails/v2 v2.10.1 | ||||||
|  | 	golang.org/x/sys v0.30.0 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | require ( | ||||||
|  | 	github.com/bep/debounce v1.2.1 // indirect | ||||||
|  | 	github.com/go-ole/go-ole v1.3.0 // indirect | ||||||
|  | 	github.com/godbus/dbus/v5 v5.1.0 // indirect | ||||||
|  | 	github.com/google/uuid v1.6.0 // indirect | ||||||
|  | 	github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect | ||||||
|  | 	github.com/labstack/echo/v4 v4.13.3 // indirect | ||||||
|  | 	github.com/labstack/gommon v0.4.2 // indirect | ||||||
|  | 	github.com/leaanthony/go-ansi-parser v1.6.1 // indirect | ||||||
|  | 	github.com/leaanthony/gosod v1.0.4 // indirect | ||||||
|  | 	github.com/leaanthony/slicer v1.6.0 // indirect | ||||||
|  | 	github.com/leaanthony/u v1.1.1 // indirect | ||||||
|  | 	github.com/mattn/go-colorable v0.1.13 // indirect | ||||||
|  | 	github.com/mattn/go-isatty v0.0.20 // indirect | ||||||
|  | 	github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect | ||||||
|  | 	github.com/pkg/errors v0.9.1 // indirect | ||||||
|  | 	github.com/rivo/uniseg v0.4.7 // indirect | ||||||
|  | 	github.com/samber/lo v1.49.1 // indirect | ||||||
|  | 	github.com/tkrajina/go-reflector v0.5.8 // indirect | ||||||
|  | 	github.com/valyala/bytebufferpool v1.0.0 // indirect | ||||||
|  | 	github.com/valyala/fasttemplate v1.2.2 // indirect | ||||||
|  | 	github.com/wailsapp/go-webview2 v1.0.19 // indirect | ||||||
|  | 	github.com/wailsapp/mimetype v1.4.1 // indirect | ||||||
|  | 	golang.org/x/crypto v0.33.0 // indirect | ||||||
|  | 	golang.org/x/net v0.35.0 // indirect | ||||||
|  | 	golang.org/x/text v0.22.0 // indirect | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // replace github.com/wailsapp/wails/v2 v2.10.1 => D:\Go\gopath\pkg\mod | ||||||
							
								
								
									
										79
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,79 @@ | ||||||
|  | github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= | ||||||
|  | github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= | ||||||
|  | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||||
|  | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
|  | github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= | ||||||
|  | github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= | ||||||
|  | github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= | ||||||
|  | github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | ||||||
|  | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= | ||||||
|  | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||||
|  | github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= | ||||||
|  | github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= | ||||||
|  | github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= | ||||||
|  | github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= | ||||||
|  | github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= | ||||||
|  | github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= | ||||||
|  | github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= | ||||||
|  | github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= | ||||||
|  | github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= | ||||||
|  | github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= | ||||||
|  | github.com/leaanthony/gosod v1.0.4 h1:YLAbVyd591MRffDgxUOU1NwLhT9T1/YiwjKZpkNFeaI= | ||||||
|  | github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw= | ||||||
|  | github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js= | ||||||
|  | github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8= | ||||||
|  | github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= | ||||||
|  | github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= | ||||||
|  | github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= | ||||||
|  | github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= | ||||||
|  | github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= | ||||||
|  | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= | ||||||
|  | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= | ||||||
|  | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= | ||||||
|  | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= | ||||||
|  | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | ||||||
|  | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= | ||||||
|  | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= | ||||||
|  | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||||||
|  | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||||
|  | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||||
|  | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||||
|  | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= | ||||||
|  | github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= | ||||||
|  | github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= | ||||||
|  | github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= | ||||||
|  | github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= | ||||||
|  | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | ||||||
|  | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||||
|  | github.com/tkrajina/go-reflector v0.5.8 h1:yPADHrwmUbMq4RGEyaOUpz2H90sRsETNVpjzo3DLVQQ= | ||||||
|  | github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4= | ||||||
|  | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | ||||||
|  | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | ||||||
|  | github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= | ||||||
|  | github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= | ||||||
|  | github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU= | ||||||
|  | github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= | ||||||
|  | github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= | ||||||
|  | github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= | ||||||
|  | github.com/wailsapp/wails/v2 v2.10.1 h1:QWHvWMXII2nI/nXz77gpPG8P3ehl6zKe+u4su5BWIns= | ||||||
|  | github.com/wailsapp/wails/v2 v2.10.1/go.mod h1:zrebnFV6MQf9kx8HI4iAv63vsR5v67oS7GTEZ7Pz1TY= | ||||||
|  | golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= | ||||||
|  | golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= | ||||||
|  | golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||||
|  | golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= | ||||||
|  | golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= | ||||||
|  | golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= | ||||||
|  | golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
|  | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||||
|  | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||||
|  | golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= | ||||||
|  | golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= | ||||||
|  | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|  | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||||
|  | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||||
							
								
								
									
										40
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"embed" | ||||||
|  | 
 | ||||||
|  | 	"github.com/wailsapp/wails/v2" | ||||||
|  | 	"github.com/wailsapp/wails/v2/pkg/options" | ||||||
|  | 	"github.com/wailsapp/wails/v2/pkg/options/assetserver" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | //go:embed all:frontend/dist
 | ||||||
|  | var assets embed.FS | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	app := NewApp() | ||||||
|  | 	homeEvent := NewHomeEvent() | ||||||
|  | 
 | ||||||
|  | 	err := wails.Run(&options.App{ | ||||||
|  | 		Title:  "浏览器多开工具", | ||||||
|  | 		Width:  800, | ||||||
|  | 		Height: 500, | ||||||
|  | 		AssetServer: &assetserver.Options{ | ||||||
|  | 			Assets: assets, | ||||||
|  | 		}, | ||||||
|  | 		BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, | ||||||
|  | 		OnStartup: func(ctx context.Context) { | ||||||
|  | 			app.startup(ctx) | ||||||
|  | 			homeEvent.startup(ctx) | ||||||
|  | 		}, | ||||||
|  | 		Bind: []interface{}{ | ||||||
|  | 			app, | ||||||
|  | 			homeEvent, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	if err != nil { | ||||||
|  | 		println("Error:", err.Error()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										91
									
								
								util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								util.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func splitCommandLine(commandLine string) []string { | ||||||
|  | 	var args []string | ||||||
|  | 	var currentArg strings.Builder | ||||||
|  | 	inQuotes := false | ||||||
|  | 
 | ||||||
|  | 	for _, char := range commandLine { | ||||||
|  | 		if char == '"' { | ||||||
|  | 			inQuotes = !inQuotes // 切换引号状态
 | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if char == ' ' && !inQuotes { | ||||||
|  | 			// 如果不在引号内且遇到空格,表示参数结束
 | ||||||
|  | 			if currentArg.Len() > 0 { | ||||||
|  | 				args = append(args, currentArg.String()) | ||||||
|  | 				currentArg.Reset() | ||||||
|  | 			} | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// 否则继续添加到当前参数
 | ||||||
|  | 		currentArg.WriteRune(char) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// 添加最后一个参数(如果有)
 | ||||||
|  | 	if currentArg.Len() > 0 { | ||||||
|  | 		args = append(args, currentArg.String()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return args | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetWorkDir() string { | ||||||
|  | 	workDir, err := os.Getwd() | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println(err) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 	return workDir | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetDataDir() string { | ||||||
|  | 	dataDir := filepath.Join(GetWorkDir(), "data") | ||||||
|  | 	stat, err := os.Stat(dataDir) | ||||||
|  | 	if os.IsNotExist(err) || !stat.IsDir() { | ||||||
|  | 		err := os.Mkdir(dataDir, os.ModePerm) | ||||||
|  | 		if err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return dataDir | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetWorkspaceDirs() []string { | ||||||
|  | 	dataDir := GetDataDir() | ||||||
|  | 	entries, err := os.ReadDir(dataDir) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	var workspaceArr []string | ||||||
|  | 	for _, entry := range entries { | ||||||
|  | 		if entry.IsDir() { | ||||||
|  | 			workspaceArr = append(workspaceArr, entry.Name()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return workspaceArr | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetInstanceDirs() []string { | ||||||
|  | 	workspaceDir := filepath.Join(GetDataDir(), GetCurrWorkspace()) | ||||||
|  | 	entries, err := os.ReadDir(workspaceDir) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	var instanceArr []string | ||||||
|  | 	for _, entry := range entries { | ||||||
|  | 		if entry.IsDir() { | ||||||
|  | 			instanceArr = append(instanceArr, entry.Name()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return instanceArr | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								wails.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								wails.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | { | ||||||
|  |   "$schema": "https://wails.io/schemas/config.v2.json", | ||||||
|  |   "name": "chrome-multi", | ||||||
|  |   "outputfilename": "chrome-multi", | ||||||
|  |   "frontend:install": "npm install", | ||||||
|  |   "frontend:build": "npm run build", | ||||||
|  |   "frontend:dev:watcher": "npm run dev", | ||||||
|  |   "frontend:dev:serverUrl": "auto", | ||||||
|  |   "author": { | ||||||
|  |     "name": "ZhuoQinghui", | ||||||
|  |     "email": "1302344380@qq.com" | ||||||
|  |   } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user