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