diff --git a/Tools/quickly/app.go b/Tools/quickly/app.go deleted file mode 100644 index af53038..0000000 --- a/Tools/quickly/app.go +++ /dev/null @@ -1,27 +0,0 @@ -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) -} diff --git a/Tools/quickly/backend/app.go b/Tools/quickly/backend/app.go new file mode 100644 index 0000000..d432973 --- /dev/null +++ b/Tools/quickly/backend/app.go @@ -0,0 +1,14 @@ +package backend + +import ( + "context" +) + +func NewApp() *App { + return &App{} +} + +func (a *App) Startup(ctx context.Context) { + a.ctx = ctx + a.loadSettings() +} diff --git a/Tools/quickly/backend/database.go b/Tools/quickly/backend/database.go new file mode 100644 index 0000000..a9d0e45 --- /dev/null +++ b/Tools/quickly/backend/database.go @@ -0,0 +1,56 @@ +package backend + +import ( + "fmt" +) + +func (a *App) AddDatabaseConfig(name string, targetPath string, modelPackagePath string) error { + if name == "" { + return fmt.Errorf("database name is empty") + } + if targetPath == "" { + return fmt.Errorf("target path is empty") + } + + for _, db := range a.settings.Databases { + if db.Name == name { + return fmt.Errorf("database with name '%s' already exists", name) + } + } + + a.settings.Databases = append(a.settings.Databases, DatabaseConfig{ + Name: name, + TargetPath: targetPath, + ModelPackagePath: modelPackagePath, + }) + return a.saveSettings() +} + +func (a *App) RemoveDatabaseConfig(name string) error { + for i, db := range a.settings.Databases { + if db.Name == name { + a.settings.Databases = append(a.settings.Databases[:i], a.settings.Databases[i+1:]...) + return a.saveSettings() + } + } + return fmt.Errorf("database with name '%s' not found", name) +} + +func (a *App) UpdateDatabaseConfig(oldName string, newName string, targetPath string, modelPackagePath string) error { + if newName == "" { + return fmt.Errorf("database name is empty") + } + if targetPath == "" { + return fmt.Errorf("target path is empty") + } + + for i, db := range a.settings.Databases { + if db.Name == oldName { + a.settings.Databases[i].Name = newName + a.settings.Databases[i].TargetPath = targetPath + a.settings.Databases[i].ModelPackagePath = modelPackagePath + return a.saveSettings() + } + } + return fmt.Errorf("database with name '%s' not found", oldName) +} diff --git a/Tools/quickly/backend/greet.go b/Tools/quickly/backend/greet.go new file mode 100644 index 0000000..2c7655a --- /dev/null +++ b/Tools/quickly/backend/greet.go @@ -0,0 +1,9 @@ +package backend + +import ( + "fmt" +) + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s, It's show time!", name) +} diff --git a/Tools/quickly/backend/helpers.go b/Tools/quickly/backend/helpers.go new file mode 100644 index 0000000..585ff38 --- /dev/null +++ b/Tools/quickly/backend/helpers.go @@ -0,0 +1,56 @@ +package backend + +import ( + "os" + "path/filepath" +) + +func copyDir(src string, dst string) error { + srcInfo, err := os.Stat(src) + if err != nil { + return err + } + + if err := os.MkdirAll(dst, srcInfo.Mode()); err != nil { + return err + } + + entries, err := os.ReadDir(src) + if err != nil { + return err + } + + for _, entry := range entries { + srcPath := filepath.Join(src, entry.Name()) + dstPath := filepath.Join(dst, entry.Name()) + + if entry.IsDir() { + if err := copyDir(srcPath, dstPath); err != nil { + return err + } + } else { + if err := copyFile(srcPath, dstPath); err != nil { + return err + } + } + } + + return nil +} + +func copyFile(src string, dst string) error { + source, err := os.Open(src) + if err != nil { + return err + } + defer source.Close() + + destination, err := os.Create(dst) + if err != nil { + return err + } + defer destination.Close() + + _, err = destination.ReadFrom(source) + return err +} diff --git a/Tools/quickly/backend/models.go b/Tools/quickly/backend/models.go new file mode 100644 index 0000000..e86f16f --- /dev/null +++ b/Tools/quickly/backend/models.go @@ -0,0 +1,34 @@ +package backend + +import ( + "context" +) + +type DatabaseConfig struct { + Name string `json:"name"` + TargetPath string `json:"targetPath"` + ModelPackagePath string `json:"modelPackagePath"` +} + +type ProjectConfig struct { + Name string `json:"name"` + Path string `json:"path"` +} + +type Settings struct { + Theme string `json:"theme"` + Language string `json:"language"` + Notifications bool `json:"notifications"` + AutoStart bool `json:"autoStart"` + MysqlModelPath string `json:"mysqlModelPath"` + DefaultQueryPackagePath string `json:"defaultQueryPackagePath"` + ModelBasePath string `json:"modelBasePath"` + SwaggerDir string `json:"swaggerDir"` + Databases []DatabaseConfig `json:"databases"` + Projects []ProjectConfig `json:"projects"` +} + +type App struct { + ctx context.Context + settings Settings +} diff --git a/Tools/quickly/backend/mysql_model.go b/Tools/quickly/backend/mysql_model.go new file mode 100644 index 0000000..cbbde13 --- /dev/null +++ b/Tools/quickly/backend/mysql_model.go @@ -0,0 +1,171 @@ +package backend + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/wailsapp/wails/v2/pkg/runtime" +) + +func (a *App) SelectFile(title string, defaultDir string, filter string) (string, error) { + return runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{ + Title: title, + DefaultDirectory: defaultDir, + Filters: []runtime.FileFilter{{Pattern: filter}}, + }) +} + +func (a *App) SelectDirectory(title string, defaultDir string) (string, error) { + return runtime.OpenDirectoryDialog(a.ctx, runtime.OpenDialogOptions{ + Title: title, + DefaultDirectory: defaultDir, + }) +} + +func (a *App) CheckGenPs1Exists(filePath string) (bool, error) { + if filePath == "" { + return false, fmt.Errorf("file path is empty") + } + + _, err := os.Stat(filePath) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } + return false, err + } + return true, nil +} + +func (a *App) ReadGoModModule(filePath string) (string, error) { + if filePath == "" { + return "", fmt.Errorf("file path is empty") + } + + dirPath := filepath.Dir(filePath) + goModPath := filepath.Join(dirPath, "go.mod") + + content, err := os.ReadFile(goModPath) + if err != nil { + return "", fmt.Errorf("go.mod not found: %w", err) + } + + lines := strings.Split(string(content), "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "module ") { + moduleName := strings.TrimPrefix(line, "module ") + moduleName = strings.TrimSpace(moduleName) + return moduleName, nil + } + } + + return "", fmt.Errorf("module declaration not found in go.mod") +} + +func (a *App) ExecuteGenPs1(genPs1Path string, dbName string, targetPath string, modelPackagePath string) (string, error) { + if genPs1Path == "" { + return "", fmt.Errorf("gen.ps1 path is empty") + } + if dbName == "" { + return "", fmt.Errorf("database name is empty") + } + + if _, err := os.Stat(genPs1Path); err != nil { + if os.IsNotExist(err) { + return "", fmt.Errorf("gen.ps1 not found") + } + return "", fmt.Errorf("error checking gen.ps1: %w", err) + } + + dirPath := filepath.Dir(genPs1Path) + + psPath, err := exec.LookPath("powershell.exe") + if err != nil { + return "", fmt.Errorf("PowerShell not found: %w", err) + } + + args := []string{ + "-NoProfile", + "-ExecutionPolicy", "Bypass", + "-Command", + fmt.Sprintf("Set-Location -Path '%s'; & .\\gen.ps1 -dbName '%s'", dirPath, dbName), + } + + cmd := exec.Command(psPath, args...) + + output, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("script execution failed: %w\nOutput: %s", err, string(output)) + } + + if targetPath != "" { + sourceDir := filepath.Join(dirPath, dbName) + if _, err := os.Stat(sourceDir); err == nil { + modelSource := filepath.Join(sourceDir, "model") + querySource := filepath.Join(sourceDir, "query") + + modelTarget := filepath.Join(targetPath, "model") + queryTarget := filepath.Join(targetPath, "query") + + if _, err := os.Stat(modelSource); err == nil { + if err := copyDir(modelSource, modelTarget); err != nil { + return string(output), fmt.Errorf("failed to copy model directory: %w", err) + } + } + + if _, err := os.Stat(querySource); err == nil { + if err := copyDir(querySource, queryTarget); err != nil { + return string(output), fmt.Errorf("failed to copy query directory: %w", err) + } + if modelPackagePath != "" { + if err := replaceImportPaths(queryTarget, dbName, modelPackagePath, a.settings.DefaultQueryPackagePath); err != nil { + return string(output), fmt.Errorf("failed to replace import paths: %w", err) + } + } + } + } + } + + return string(output), nil +} + +func replaceImportPaths(queryDir string, dbName string, newPackagePath string, basePath string) error { + err := filepath.Walk(queryDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if !info.IsDir() && strings.HasSuffix(path, ".gen.go") { + if err := replaceImportInFile(path, dbName, newPackagePath, basePath); err != nil { + return err + } + } + + return nil + }) + + return err +} + +func replaceImportInFile(filePath string, dbName string, newPackagePath string, basePath string) error { + content, err := os.ReadFile(filePath) + if err != nil { + return err + } + + if basePath == "" { + basePath = "git.hlsq.asia/mmorpg" + } + + oldImport := fmt.Sprintf(`"%s/%s/model"`, basePath, dbName) + newImport := fmt.Sprintf(`"%s"`, newPackagePath) + + newContent := bytes.ReplaceAll(content, []byte(oldImport), []byte(newImport)) + + return os.WriteFile(filePath, newContent, 0644) +} diff --git a/Tools/quickly/backend/project.go b/Tools/quickly/backend/project.go new file mode 100644 index 0000000..46bcb41 --- /dev/null +++ b/Tools/quickly/backend/project.go @@ -0,0 +1,73 @@ +package backend + +import ( + "fmt" + "os" + "path/filepath" +) + +func (a *App) AddProjectConfig(name string, path string) error { + if path == "" { + return fmt.Errorf("project path is empty") + } + + if name == "" { + name = filepath.Base(path) + } + + goModPath := filepath.Join(path, "go.mod") + if _, err := os.Stat(goModPath); err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("go.mod file not found in the specified path") + } + return fmt.Errorf("error checking go.mod file: %w", err) + } + + for _, project := range a.settings.Projects { + if project.Name == name { + return fmt.Errorf("project with name '%s' already exists", name) + } + } + + a.settings.Projects = append(a.settings.Projects, ProjectConfig{ + Name: name, + Path: path, + }) + return a.saveSettings() +} + +func (a *App) RemoveProjectConfig(name string) error { + for i, project := range a.settings.Projects { + if project.Name == name { + a.settings.Projects = append(a.settings.Projects[:i], a.settings.Projects[i+1:]...) + return a.saveSettings() + } + } + return fmt.Errorf("project with name '%s' not found", name) +} + +func (a *App) UpdateProjectConfig(oldName string, newName string, path string) error { + if newName == "" { + return fmt.Errorf("project name is empty") + } + if path == "" { + return fmt.Errorf("project path is empty") + } + + goModPath := filepath.Join(path, "go.mod") + if _, err := os.Stat(goModPath); err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("go.mod file not found in the specified path") + } + return fmt.Errorf("error checking go.mod file: %w", err) + } + + for i, project := range a.settings.Projects { + if project.Name == oldName { + a.settings.Projects[i].Name = newName + a.settings.Projects[i].Path = path + return a.saveSettings() + } + } + return fmt.Errorf("project with name '%s' not found", oldName) +} diff --git a/Tools/quickly/backend/settings.go b/Tools/quickly/backend/settings.go new file mode 100644 index 0000000..c1dd4f1 --- /dev/null +++ b/Tools/quickly/backend/settings.go @@ -0,0 +1,104 @@ +package backend + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" +) + +func (a *App) getSettingsPath() (string, error) { + configDir, err := os.UserConfigDir() + if err != nil { + return "", err + } + appConfigDir := filepath.Join(configDir, "quickly") + if err := os.MkdirAll(appConfigDir, 0755); err != nil { + return "", err + } + return filepath.Join(appConfigDir, "settings.json"), nil +} + +func (a *App) loadSettings() { + settingsPath, err := a.getSettingsPath() + if err != nil { + fmt.Println("Error getting settings path:", err) + a.settings = Settings{ + Theme: "light", + Language: "zh-CN", + Notifications: true, + AutoStart: false, + MysqlModelPath: "", + DefaultQueryPackagePath: "", + ModelBasePath: "", + SwaggerDir: "", + Databases: []DatabaseConfig{}, + Projects: []ProjectConfig{}, + } + return + } + + data, err := os.ReadFile(settingsPath) + if err != nil { + if os.IsNotExist(err) { + a.settings = Settings{ + Theme: "light", + Language: "zh-CN", + Notifications: true, + AutoStart: false, + MysqlModelPath: "", + DefaultQueryPackagePath: "", + ModelBasePath: "", + SwaggerDir: "", + Databases: []DatabaseConfig{}, + Projects: []ProjectConfig{}, + } + return + } + fmt.Println("Error reading settings file:", err) + return + } + + if err := json.Unmarshal(data, &a.settings); err != nil { + fmt.Println("Error parsing settings file:", err) + a.settings = Settings{ + Theme: "light", + Language: "zh-CN", + Notifications: true, + AutoStart: false, + MysqlModelPath: "", + DefaultQueryPackagePath: "", + ModelBasePath: "", + SwaggerDir: "", + Databases: []DatabaseConfig{}, + Projects: []ProjectConfig{}, + } + } +} + +func (a *App) saveSettings() error { + settingsPath, err := a.getSettingsPath() + if err != nil { + return fmt.Errorf("error getting settings path: %w", err) + } + + data, err := json.MarshalIndent(a.settings, "", " ") + if err != nil { + return fmt.Errorf("error marshaling settings: %w", err) + } + + if err := os.WriteFile(settingsPath, data, 0644); err != nil { + return fmt.Errorf("error writing settings file: %w", err) + } + + return nil +} + +func (a *App) GetSettings() Settings { + return a.settings +} + +func (a *App) SaveSettings(settings Settings) error { + a.settings = settings + return a.saveSettings() +} diff --git a/Tools/quickly/backend/swagger.go b/Tools/quickly/backend/swagger.go new file mode 100644 index 0000000..67da8e0 --- /dev/null +++ b/Tools/quickly/backend/swagger.go @@ -0,0 +1,239 @@ +package backend + +import ( + "fmt" + "net" + "net/http" + "os" + "path/filepath" + "strings" + "sync" + "time" +) + +type SwaggerFile struct { + Name string `json:"name"` + Path string `json:"path"` + Size int64 `json:"size"` + ModifiedTime string `json:"modifiedTime"` +} + +type SwaggerServer struct { + server *http.Server + port int + running bool + mu sync.Mutex +} + +var swaggerServer *SwaggerServer +var swaggerServerMu sync.Mutex + +func (a *App) GetSwaggerFiles(dirPath string) ([]SwaggerFile, error) { + if dirPath == "" { + return nil, fmt.Errorf("directory path is empty") + } + + var files []SwaggerFile + + err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + return nil + } + + if strings.HasSuffix(strings.ToLower(info.Name()), ".swagger.json") { + files = append(files, SwaggerFile{ + Name: info.Name(), + Path: path, + Size: info.Size(), + ModifiedTime: info.ModTime().Format("2006-01-02 15:04:05"), + }) + } + + return nil + }) + + if err != nil { + return nil, fmt.Errorf("failed to walk directory: %w", err) + } + + return files, nil +} + +func (a *App) ReadSwaggerFile(filePath string) (string, error) { + if filePath == "" { + return "", fmt.Errorf("file path is empty") + } + + content, err := os.ReadFile(filePath) + if err != nil { + return "", fmt.Errorf("failed to read file: %w", err) + } + + return string(content), nil +} + +func (a *App) StartSwaggerServer(dirPath string) (string, error) { + if dirPath == "" { + return "", fmt.Errorf("directory path is empty") + } + + swaggerServerMu.Lock() + defer swaggerServerMu.Unlock() + + if swaggerServer != nil && swaggerServer.running { + return fmt.Sprintf("http://localhost:%d", swaggerServer.port), nil + } + + port := 8080 + for i := 0; i < 100; i++ { + listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err == nil { + listener.Close() + break + } + port++ + } + + mux := http.NewServeMux() + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + swaggerHTML := ` + + + + + Swagger UI + + + + +
+ + + +` + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.Write([]byte(swaggerHTML)) + }) + + mux.HandleFunc("/swagger.json", func(w http.ResponseWriter, r *http.Request) { + files, err := a.GetSwaggerFiles(dirPath) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if len(files) == 0 { + http.Error(w, "No swagger files found", http.StatusNotFound) + return + } + + fileName := r.URL.Query().Get("file") + selectedFile := files[0] + if fileName != "" { + for _, file := range files { + if file.Name == fileName { + selectedFile = file + break + } + } + } + + content, err := os.ReadFile(selectedFile.Path) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.Write(content) + }) + + server := &http.Server{ + Addr: fmt.Sprintf(":%d", port), + Handler: mux, + ReadTimeout: 15 * time.Second, + WriteTimeout: 15 * time.Second, + } + + swaggerServer = &SwaggerServer{ + server: server, + port: port, + running: true, + } + + go func() { + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + fmt.Printf("Swagger server error: %v\n", err) + } + }() + + return fmt.Sprintf("http://localhost:%d", port), nil +} + +func (a *App) StopSwaggerServer() error { + swaggerServerMu.Lock() + defer swaggerServerMu.Unlock() + + if swaggerServer == nil || !swaggerServer.running { + return nil + } + + if err := swaggerServer.server.Close(); err != nil { + return fmt.Errorf("failed to stop server: %w", err) + } + + swaggerServer.running = false + return nil +} + +func (a *App) IsSwaggerServerRunning() bool { + swaggerServerMu.Lock() + defer swaggerServerMu.Unlock() + + if swaggerServer == nil { + return false + } + return swaggerServer.running +} + +func (a *App) GetSwaggerServerURL() string { + swaggerServerMu.Lock() + defer swaggerServerMu.Unlock() + + if swaggerServer == nil || !swaggerServer.running { + return "" + } + return fmt.Sprintf("http://localhost:%d", swaggerServer.port) +} diff --git a/Tools/quickly/backend/update_service_common.go b/Tools/quickly/backend/update_service_common.go new file mode 100644 index 0000000..fa5d7db --- /dev/null +++ b/Tools/quickly/backend/update_service_common.go @@ -0,0 +1,90 @@ +package backend + +import ( + "fmt" + "os/exec" + "strings" +) + +func (a *App) UpdateServiceCommon(commitId string, projectNames []string) (string, error) { + if commitId == "" { + return "", fmt.Errorf("commit id is empty") + } + + if len(projectNames) == 0 { + return "", fmt.Errorf("no projects selected") + } + + var results strings.Builder + results.WriteString(fmt.Sprintf("开始更新 Common 版本: %s\n", commitId)) + results.WriteString(fmt.Sprintf("共选择 %d 个项目\n\n", len(projectNames))) + + for _, projectName := range projectNames { + var projectPath string + found := false + for _, project := range a.settings.Projects { + if project.Name == projectName { + projectPath = project.Path + found = true + break + } + } + + if !found { + results.WriteString(fmt.Sprintf("❌ 项目 '%s' 未找到配置\n\n", projectName)) + continue + } + + results.WriteString(fmt.Sprintf("正在更新项目: %s\n", projectName)) + results.WriteString(fmt.Sprintf("路径: %s\n", projectPath)) + + if err := updateProjectCommonVersion(projectPath, commitId, &results, a.settings.ModelBasePath); err != nil { + results.WriteString(fmt.Sprintf("❌ 更新失败: %v\n\n", err)) + continue + } + + results.WriteString(fmt.Sprintf("✅ 更新成功\n\n")) + } + + results.WriteString("所有项目更新完成!") + return results.String(), nil +} + +func updateProjectCommonVersion(projectPath string, commitId string, results *strings.Builder, moduleName string) error { + goPath, err := exec.LookPath("go") + if err != nil { + return fmt.Errorf("Go not found: %w", err) + } + + if moduleName == "" { + return fmt.Errorf("Go Module Name 未配置,请在设置中填写") + } + + results.WriteString("执行: go get -u " + moduleName + "@" + commitId + "\n") + + cmd := exec.Command(goPath, "get", "-u", fmt.Sprintf("%s@%s", moduleName, commitId)) + cmd.Dir = projectPath + + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("go get failed: %w\nOutput: %s", err, string(output)) + } + + results.WriteString(string(output)) + results.WriteString("\n") + + results.WriteString("执行: go mod tidy\n") + + cmd = exec.Command(goPath, "mod", "tidy") + cmd.Dir = projectPath + + output, err = cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("go mod tidy failed: %w\nOutput: %s", err, string(output)) + } + + results.WriteString(string(output)) + results.WriteString("\n") + + return nil +} diff --git a/Tools/quickly/frontend/package-lock.json b/Tools/quickly/frontend/package-lock.json index d0f8e00..8f7596f 100644 --- a/Tools/quickly/frontend/package-lock.json +++ b/Tools/quickly/frontend/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "@element-plus/icons-vue": "^2.3.2", "element-plus": "^2.13.1", - "vue": "^3.2.37" + "vue": "^3.2.37", + "vue-router": "^4.6.4" }, "devDependencies": { "@babel/types": "^7.18.10", @@ -276,6 +277,12 @@ "@vue/shared": "3.5.26" } }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, "node_modules/@vue/language-core": { "version": "1.8.27", "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-1.8.27.tgz", @@ -1264,6 +1271,21 @@ } } }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, "node_modules/vue-template-compiler": { "version": "2.7.16", "resolved": "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", diff --git a/Tools/quickly/frontend/package.json b/Tools/quickly/frontend/package.json index aa4923b..7017d24 100644 --- a/Tools/quickly/frontend/package.json +++ b/Tools/quickly/frontend/package.json @@ -11,7 +11,8 @@ "dependencies": { "@element-plus/icons-vue": "^2.3.2", "element-plus": "^2.13.1", - "vue": "^3.2.37" + "vue": "^3.2.37", + "vue-router": "^4.6.4" }, "devDependencies": { "@babel/types": "^7.18.10", diff --git a/Tools/quickly/frontend/package.json.md5 b/Tools/quickly/frontend/package.json.md5 index fae5180..9c06045 100644 --- a/Tools/quickly/frontend/package.json.md5 +++ b/Tools/quickly/frontend/package.json.md5 @@ -1 +1 @@ -b777c503b422e1e0e3f70b49d2291cdc \ No newline at end of file +27251dcea746309433392e41407ed6c9 \ No newline at end of file diff --git a/Tools/quickly/frontend/src/App.vue b/Tools/quickly/frontend/src/App.vue index e3c8151..4d9ed1e 100644 --- a/Tools/quickly/frontend/src/App.vue +++ b/Tools/quickly/frontend/src/App.vue @@ -1,18 +1,88 @@ @@ -21,33 +91,74 @@ import HelloWorld from './components/HelloWorld.vue' height: 100vh; } -.el-header { +.app-aside { background-color: #1b2636; - color: #fff; display: flex; - align-items: center; - padding: 0 20px; + flex-direction: column; } -.header-content { +.logo-container { display: flex; align-items: center; - gap: 15px; + padding: 20px; + gap: 10px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); } .logo { - width: 40px; - height: 40px; + width: 32px; + height: 32px; } -.header-content h1 { - margin: 0; - font-size: 20px; +.app-title { + color: #fff; + font-size: 18px; + font-weight: 600; +} + +.el-menu-vertical { + border: none; + background-color: transparent; + flex: 1; +} + +.el-menu-vertical .el-menu-item { + color: rgba(255, 255, 255, 0.7); +} + +.el-menu-vertical .el-menu-item:hover { + background-color: rgba(255, 255, 255, 0.1); + color: #fff; +} + +.el-menu-vertical .el-menu-item.is-active { + background-color: #409eff; + color: #fff; +} + +.main-container { + display: flex; + flex-direction: column; +} + +.app-header { + background-color: #fff; + border-bottom: 1px solid #e4e7ed; + display: flex; + align-items: center; + padding: 0 20px; + height: 60px; +} + +.header-title { + font-size: 18px; font-weight: 500; + color: #303133; } -.el-main { +.app-main { background-color: #f5f7fa; - padding: 20px; + padding: 0; + overflow: auto; } diff --git a/Tools/quickly/frontend/src/components/HelloWorld.vue b/Tools/quickly/frontend/src/components/HelloWorld.vue deleted file mode 100644 index 807e577..0000000 --- a/Tools/quickly/frontend/src/components/HelloWorld.vue +++ /dev/null @@ -1,70 +0,0 @@ - - - - - diff --git a/Tools/quickly/frontend/src/main.ts b/Tools/quickly/frontend/src/main.ts index 2e9e738..3f46ef4 100644 --- a/Tools/quickly/frontend/src/main.ts +++ b/Tools/quickly/frontend/src/main.ts @@ -1,9 +1,17 @@ import {createApp} from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' import App from './App.vue' +import router from './router' import './style.css' const app = createApp(App) + +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} + app.use(ElementPlus) +app.use(router) app.mount('#app') diff --git a/Tools/quickly/frontend/src/router/index.ts b/Tools/quickly/frontend/src/router/index.ts new file mode 100644 index 0000000..3d94b5b --- /dev/null +++ b/Tools/quickly/frontend/src/router/index.ts @@ -0,0 +1,50 @@ +import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router' +import Home from '../views/Home.vue' +import Settings from '../views/Settings.vue' +import Swagger from '../views/Swagger.vue' +import MySQLModel from '../views/MySQLModel.vue' +import UpdateCommon from '../views/UpdateCommon.vue' + +const routes: RouteRecordRaw[] = [ + { + path: '/', + redirect: '/home' + }, + { + path: '/home', + name: 'Home', + component: Home, + meta: { title: '主页' } + }, + { + path: '/settings', + name: 'Settings', + component: Settings, + meta: { title: '设置' } + }, + { + path: '/swagger', + name: 'Swagger', + component: Swagger, + meta: { title: 'Swagger' } + }, + { + path: '/mysql-model', + name: 'MySQLModel', + component: MySQLModel, + meta: { title: 'MySQL Model' } + }, + { + path: '/update-common', + name: 'UpdateCommon', + component: UpdateCommon, + meta: { title: '更新 Common' } + } +] + +const router = createRouter({ + history: createWebHashHistory(), + routes +}) + +export default router diff --git a/Tools/quickly/frontend/src/views/Home.vue b/Tools/quickly/frontend/src/views/Home.vue new file mode 100644 index 0000000..8ba9252 --- /dev/null +++ b/Tools/quickly/frontend/src/views/Home.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/Tools/quickly/frontend/src/views/MySQLModel.vue b/Tools/quickly/frontend/src/views/MySQLModel.vue new file mode 100644 index 0000000..b6533c5 --- /dev/null +++ b/Tools/quickly/frontend/src/views/MySQLModel.vue @@ -0,0 +1,431 @@ + + + + + diff --git a/Tools/quickly/frontend/src/views/Settings.vue b/Tools/quickly/frontend/src/views/Settings.vue new file mode 100644 index 0000000..659b8b9 --- /dev/null +++ b/Tools/quickly/frontend/src/views/Settings.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/Tools/quickly/frontend/src/views/Swagger.vue b/Tools/quickly/frontend/src/views/Swagger.vue new file mode 100644 index 0000000..cc9469d --- /dev/null +++ b/Tools/quickly/frontend/src/views/Swagger.vue @@ -0,0 +1,349 @@ + + + + + diff --git a/Tools/quickly/frontend/src/views/UpdateCommon.vue b/Tools/quickly/frontend/src/views/UpdateCommon.vue new file mode 100644 index 0000000..e2c3a33 --- /dev/null +++ b/Tools/quickly/frontend/src/views/UpdateCommon.vue @@ -0,0 +1,327 @@ + + + + + diff --git a/Tools/quickly/frontend/tsconfig.json b/Tools/quickly/frontend/tsconfig.json index 3cc844d..df752c6 100644 --- a/Tools/quickly/frontend/tsconfig.json +++ b/Tools/quickly/frontend/tsconfig.json @@ -4,7 +4,7 @@ "useDefineForClassFields": true, "module": "ESNext", "moduleResolution": "Node", - "strict": true, + "strict": false, "jsx": "preserve", "sourceMap": true, "resolveJsonModule": true, diff --git a/Tools/quickly/frontend/wailsjs/go/backend/App.d.ts b/Tools/quickly/frontend/wailsjs/go/backend/App.d.ts new file mode 100644 index 0000000..618c177 --- /dev/null +++ b/Tools/quickly/frontend/wailsjs/go/backend/App.d.ts @@ -0,0 +1,45 @@ +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT +import {backend} from '../models'; + +export function AddDatabaseConfig(arg1:string,arg2:string,arg3:string):Promise; + +export function AddProjectConfig(arg1:string,arg2:string):Promise; + +export function CheckGenPs1Exists(arg1:string):Promise; + +export function ExecuteGenPs1(arg1:string,arg2:string,arg3:string,arg4:string):Promise; + +export function GetSettings():Promise; + +export function GetSwaggerFiles(arg1:string):Promise>; + +export function GetSwaggerServerURL():Promise; + +export function Greet(arg1:string):Promise; + +export function IsSwaggerServerRunning():Promise; + +export function ReadGoModModule(arg1:string):Promise; + +export function ReadSwaggerFile(arg1:string):Promise; + +export function RemoveDatabaseConfig(arg1:string):Promise; + +export function RemoveProjectConfig(arg1:string):Promise; + +export function SaveSettings(arg1:backend.Settings):Promise; + +export function SelectDirectory(arg1:string,arg2:string):Promise; + +export function SelectFile(arg1:string,arg2:string,arg3:string):Promise; + +export function StartSwaggerServer(arg1:string):Promise; + +export function StopSwaggerServer():Promise; + +export function UpdateDatabaseConfig(arg1:string,arg2:string,arg3:string,arg4:string):Promise; + +export function UpdateProjectConfig(arg1:string,arg2:string,arg3:string):Promise; + +export function UpdateServiceCommon(arg1:string,arg2:Array):Promise; diff --git a/Tools/quickly/frontend/wailsjs/go/backend/App.js b/Tools/quickly/frontend/wailsjs/go/backend/App.js new file mode 100644 index 0000000..6edcfbc --- /dev/null +++ b/Tools/quickly/frontend/wailsjs/go/backend/App.js @@ -0,0 +1,87 @@ +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +export function AddDatabaseConfig(arg1, arg2, arg3) { + return window['go']['backend']['App']['AddDatabaseConfig'](arg1, arg2, arg3); +} + +export function AddProjectConfig(arg1, arg2) { + return window['go']['backend']['App']['AddProjectConfig'](arg1, arg2); +} + +export function CheckGenPs1Exists(arg1) { + return window['go']['backend']['App']['CheckGenPs1Exists'](arg1); +} + +export function ExecuteGenPs1(arg1, arg2, arg3, arg4) { + return window['go']['backend']['App']['ExecuteGenPs1'](arg1, arg2, arg3, arg4); +} + +export function GetSettings() { + return window['go']['backend']['App']['GetSettings'](); +} + +export function GetSwaggerFiles(arg1) { + return window['go']['backend']['App']['GetSwaggerFiles'](arg1); +} + +export function GetSwaggerServerURL() { + return window['go']['backend']['App']['GetSwaggerServerURL'](); +} + +export function Greet(arg1) { + return window['go']['backend']['App']['Greet'](arg1); +} + +export function IsSwaggerServerRunning() { + return window['go']['backend']['App']['IsSwaggerServerRunning'](); +} + +export function ReadGoModModule(arg1) { + return window['go']['backend']['App']['ReadGoModModule'](arg1); +} + +export function ReadSwaggerFile(arg1) { + return window['go']['backend']['App']['ReadSwaggerFile'](arg1); +} + +export function RemoveDatabaseConfig(arg1) { + return window['go']['backend']['App']['RemoveDatabaseConfig'](arg1); +} + +export function RemoveProjectConfig(arg1) { + return window['go']['backend']['App']['RemoveProjectConfig'](arg1); +} + +export function SaveSettings(arg1) { + return window['go']['backend']['App']['SaveSettings'](arg1); +} + +export function SelectDirectory(arg1, arg2) { + return window['go']['backend']['App']['SelectDirectory'](arg1, arg2); +} + +export function SelectFile(arg1, arg2, arg3) { + return window['go']['backend']['App']['SelectFile'](arg1, arg2, arg3); +} + +export function StartSwaggerServer(arg1) { + return window['go']['backend']['App']['StartSwaggerServer'](arg1); +} + +export function StopSwaggerServer() { + return window['go']['backend']['App']['StopSwaggerServer'](); +} + +export function UpdateDatabaseConfig(arg1, arg2, arg3, arg4) { + return window['go']['backend']['App']['UpdateDatabaseConfig'](arg1, arg2, arg3, arg4); +} + +export function UpdateProjectConfig(arg1, arg2, arg3) { + return window['go']['backend']['App']['UpdateProjectConfig'](arg1, arg2, arg3); +} + +export function UpdateServiceCommon(arg1, arg2) { + return window['go']['backend']['App']['UpdateServiceCommon'](arg1, arg2); +} diff --git a/Tools/quickly/frontend/wailsjs/go/main/App.d.ts b/Tools/quickly/frontend/wailsjs/go/main/App.d.ts deleted file mode 100644 index 02a3bb9..0000000 --- a/Tools/quickly/frontend/wailsjs/go/main/App.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export function Greet(arg1:string):Promise; diff --git a/Tools/quickly/frontend/wailsjs/go/main/App.js b/Tools/quickly/frontend/wailsjs/go/main/App.js deleted file mode 100644 index c71ae77..0000000 --- a/Tools/quickly/frontend/wailsjs/go/main/App.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export function Greet(arg1) { - return window['go']['main']['App']['Greet'](arg1); -} diff --git a/Tools/quickly/frontend/wailsjs/go/models.ts b/Tools/quickly/frontend/wailsjs/go/models.ts new file mode 100644 index 0000000..16e716a --- /dev/null +++ b/Tools/quickly/frontend/wailsjs/go/models.ts @@ -0,0 +1,101 @@ +export namespace backend { + + export class DatabaseConfig { + name: string; + targetPath: string; + modelPackagePath: string; + + static createFrom(source: any = {}) { + return new DatabaseConfig(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.targetPath = source["targetPath"]; + this.modelPackagePath = source["modelPackagePath"]; + } + } + export class ProjectConfig { + name: string; + path: string; + + static createFrom(source: any = {}) { + return new ProjectConfig(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.path = source["path"]; + } + } + export class Settings { + theme: string; + language: string; + notifications: boolean; + autoStart: boolean; + mysqlModelPath: string; + defaultQueryPackagePath: string; + modelBasePath: string; + swaggerDir: string; + databases: DatabaseConfig[]; + projects: ProjectConfig[]; + + static createFrom(source: any = {}) { + return new Settings(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.theme = source["theme"]; + this.language = source["language"]; + this.notifications = source["notifications"]; + this.autoStart = source["autoStart"]; + this.mysqlModelPath = source["mysqlModelPath"]; + this.defaultQueryPackagePath = source["defaultQueryPackagePath"]; + this.modelBasePath = source["modelBasePath"]; + this.swaggerDir = source["swaggerDir"]; + this.databases = this.convertValues(source["databases"], DatabaseConfig); + this.projects = this.convertValues(source["projects"], ProjectConfig); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + export class SwaggerFile { + name: string; + path: string; + size: number; + modifiedTime: string; + + static createFrom(source: any = {}) { + return new SwaggerFile(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.path = source["path"]; + this.size = source["size"]; + this.modifiedTime = source["modifiedTime"]; + } + } + +} + diff --git a/Tools/quickly/main.go b/Tools/quickly/main.go index 116987f..3456b15 100644 --- a/Tools/quickly/main.go +++ b/Tools/quickly/main.go @@ -2,20 +2,17 @@ package main import ( "embed" - "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "quickly/backend" ) //go:embed all:frontend/dist var assets embed.FS func main() { - // Create an instance of the app structure - app := NewApp() - - // Create application with options + app := backend.NewApp() err := wails.Run(&options.App{ Title: "Quickly 金牌助手", Width: 1024, @@ -24,7 +21,7 @@ func main() { Assets: assets, }, BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, - OnStartup: app.startup, + OnStartup: app.Startup, Bind: []interface{}{ app, },