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