Golang Code

This commit is contained in:
ZhuoQinghui 2025-06-11 14:42:45 +08:00
parent f016dc4676
commit b364b06206
9 changed files with 654 additions and 0 deletions

27
app.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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"
}
}