feat quickly

This commit is contained in:
2026-01-24 11:14:31 +08:00
parent 83d722d2f1
commit 4aa48a822e
9 changed files with 80 additions and 134 deletions

View File

@@ -23,7 +23,7 @@ type Settings struct {
MysqlModelPath string `json:"mysqlModelPath"`
DefaultQueryPackagePath string `json:"defaultQueryPackagePath"`
ModelBasePath string `json:"modelBasePath"`
SwaggerDir string `json:"swaggerDir"`
SwaggerFilePath string `json:"swaggerFilePath"`
Databases []DatabaseConfig `json:"databases"`
Projects []ProjectConfig `json:"projects"`
}

View File

@@ -31,7 +31,7 @@ func (a *App) loadSettings() {
MysqlModelPath: "",
DefaultQueryPackagePath: "",
ModelBasePath: "",
SwaggerDir: "",
SwaggerFilePath: "",
Databases: []DatabaseConfig{},
Projects: []ProjectConfig{},
}
@@ -49,7 +49,7 @@ func (a *App) loadSettings() {
MysqlModelPath: "",
DefaultQueryPackagePath: "",
ModelBasePath: "",
SwaggerDir: "",
SwaggerFilePath: "",
Databases: []DatabaseConfig{},
Projects: []ProjectConfig{},
}
@@ -69,7 +69,7 @@ func (a *App) loadSettings() {
MysqlModelPath: "",
DefaultQueryPackagePath: "",
ModelBasePath: "",
SwaggerDir: "",
SwaggerFilePath: "",
Databases: []DatabaseConfig{},
Projects: []ProjectConfig{},
}

View File

@@ -63,6 +63,24 @@ func (a *App) GetSwaggerFiles(dirPath string) ([]SwaggerFile, error) {
return files, nil
}
func (a *App) GetSwaggerFileInfo(filePath string) (SwaggerFile, error) {
if filePath == "" {
return SwaggerFile{}, fmt.Errorf("file path is empty")
}
info, err := os.Stat(filePath)
if err != nil {
return SwaggerFile{}, fmt.Errorf("failed to get file info: %w", err)
}
return SwaggerFile{
Name: info.Name(),
Path: filePath,
Size: info.Size(),
ModifiedTime: info.ModTime().Format("2006-01-02 15:04:05"),
}, nil
}
func (a *App) ReadSwaggerFile(filePath string) (string, error) {
if filePath == "" {
return "", fmt.Errorf("file path is empty")
@@ -76,9 +94,9 @@ func (a *App) ReadSwaggerFile(filePath string) (string, error) {
return string(content), nil
}
func (a *App) StartSwaggerServer(dirPath string) (string, error) {
if dirPath == "" {
return "", fmt.Errorf("directory path is empty")
func (a *App) StartSwaggerServer(filePath string) (string, error) {
if filePath == "" {
return "", fmt.Errorf("file path is empty")
}
swaggerServerMu.Lock()
@@ -121,11 +139,8 @@ func (a *App) StartSwaggerServer(dirPath string) (string, error) {
<script src="https://unpkg.com/swagger-ui-dist@5.10.5/swagger-ui-bundle.js"></script>
<script>
window.onload = function() {
const urlParams = new URLSearchParams(window.location.search);
const fileParam = urlParams.get('file');
const swaggerUrl = fileParam ? '/swagger.json?file=' + encodeURIComponent(fileParam) : '/swagger.json';
const ui = SwaggerUIBundle({
url: swaggerUrl,
url: '/swagger.json',
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
@@ -148,29 +163,7 @@ func (a *App) StartSwaggerServer(dirPath string) (string, error) {
})
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)
content, err := os.ReadFile(filePath)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return

View File

@@ -38,7 +38,6 @@ const features = reactive([
</div>
<div class="features-section">
<h2 class="section-title">功能介绍</h2>
<div class="features-grid">
<el-card v-for="(feature, index) in features" :key="index" class="feature-card">
<div class="feature-icon">{{ feature.icon }}</div>
@@ -82,13 +81,6 @@ const features = reactive([
margin: 40px 0;
}
.section-title {
font-size: 28px;
font-weight: 600;
color: #333;
margin: 0 0 30px 0;
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));

View File

@@ -3,17 +3,17 @@ import {onMounted, reactive, ref} from 'vue'
import {ElMessage} from 'element-plus'
import {
GetSettings,
GetSwaggerFiles,
GetSwaggerFileInfo,
GetSwaggerServerURL,
IsSwaggerServerRunning,
ReadSwaggerFile,
SaveSettings,
SelectDirectory,
SelectFile,
StartSwaggerServer,
StopSwaggerServer
} from '../../wailsjs/go/backend/App'
interface SwaggerFile {
interface SwaggerFileInfo {
name: string
path: string
size: number
@@ -25,7 +25,7 @@ interface AppSettings {
language: string
notifications: boolean
autoStart: boolean
swaggerDir: string
swaggerFilePath: string
}
const settings = reactive<AppSettings>({
@@ -33,51 +33,39 @@ const settings = reactive<AppSettings>({
language: 'zh-CN',
notifications: true,
autoStart: false,
swaggerDir: ''
swaggerFilePath: ''
})
const swaggerFiles = ref<SwaggerFile[]>([])
const selectedFile = ref<SwaggerFile | null>(null)
const selectedSwaggerFile = ref<SwaggerFile | null>(null)
const swaggerFileInfo = ref<SwaggerFileInfo | null>(null)
const fileContent = ref('')
const isLoading = ref(false)
const serverURL = ref('')
const isServerRunning = ref(false)
async function selectSwaggerDir() {
async function selectSwaggerFile() {
try {
const path = await SelectDirectory('选择 Swagger 目录', settings.swaggerDir)
const path = await SelectFile('选择 Swagger 文件', settings.swaggerFilePath, '*.json')
if (path) {
settings.swaggerDir = path
await loadSwaggerFiles()
settings.swaggerFilePath = path
const fileInfo = await GetSwaggerFileInfo(path)
if (fileInfo) {
swaggerFileInfo.value = fileInfo
}
await saveSettings()
}
} catch (error) {
console.error('Failed to select directory:', error)
console.error('Failed to select swagger file:', error)
}
}
async function loadSwaggerFiles() {
if (!settings.swaggerDir) {
return
}
isLoading.value = true
try {
const files = await GetSwaggerFiles(settings.swaggerDir)
swaggerFiles.value = files
} catch (error) {
console.error('Failed to load swagger files:', error)
ElMessage.error('加载 Swagger 文件失败')
} finally {
isLoading.value = false
}
return
}
async function saveSettings() {
try {
const currentSettings = await GetSettings() as any
currentSettings.swaggerDir = settings.swaggerDir
currentSettings.swaggerFilePath = settings.swaggerFilePath
await SaveSettings(currentSettings)
ElMessage.success('设置保存成功')
} catch (error) {
@@ -86,8 +74,8 @@ async function saveSettings() {
}
}
async function viewFile(file: SwaggerFile) {
selectedFile.value = file
async function viewFile(file: SwaggerFileInfo) {
swaggerFileInfo.value = file
isLoading.value = true
try {
const content = await ReadSwaggerFile(file.path)
@@ -111,18 +99,15 @@ function formatFileSize(bytes: number): string {
}
async function startSwaggerServer() {
if (!settings.swaggerDir) {
ElMessage.warning('请先配置 Swagger 目录')
if (!settings.swaggerFilePath) {
ElMessage.warning('请先配置 Swagger 文件')
return
}
try {
const url = await StartSwaggerServer(settings.swaggerDir)
const url = await StartSwaggerServer(settings.swaggerFilePath)
serverURL.value = url
isServerRunning.value = true
if (swaggerFiles.value.length > 0) {
selectedSwaggerFile.value = swaggerFiles.value[0]
}
ElMessage.success(`Swagger 服务已启动: ${url}`)
} catch (error) {
console.error('Failed to start swagger server:', error)
@@ -162,9 +147,9 @@ function openSwaggerURL() {
}
function updateServerURL() {
if (serverURL.value && selectedSwaggerFile.value) {
if (serverURL.value && swaggerFileInfo.value) {
const baseUrl = serverURL.value.split('?')[0]
serverURL.value = `${baseUrl}?file=${encodeURIComponent(selectedSwaggerFile.value.name)}`
serverURL.value = `${baseUrl}?file=${encodeURIComponent(swaggerFileInfo.value.name)}`
}
}
@@ -175,9 +160,12 @@ onMounted(async () => {
settings.language = loadedSettings.language
settings.notifications = loadedSettings.notifications
settings.autoStart = loadedSettings.autoStart
settings.swaggerDir = loadedSettings.swaggerDir || ''
if (settings.swaggerDir) {
await loadSwaggerFiles()
settings.swaggerFilePath = loadedSettings.swaggerFilePath || ''
if (settings.swaggerFilePath) {
const fileInfo = await GetSwaggerFileInfo(settings.swaggerFilePath)
if (fileInfo) {
swaggerFileInfo.value = fileInfo
}
}
await checkServerStatus()
} catch (error) {
@@ -195,14 +183,14 @@ onMounted(async () => {
</div>
</template>
<el-form label-width="140px" class="settings-form">
<el-form-item label="Swagger 目录">
<el-form-item label="Swagger 文件">
<el-input
v-model="settings.swaggerDir"
placeholder="请输入或选择 Swagger 文件目录"
v-model="settings.swaggerFilePath"
placeholder="请输入或选择 Swagger 文件"
clearable
>
<template #append>
<el-button @click="selectSwaggerDir">选择文件</el-button>
<el-button @click="selectSwaggerFile">选择文件</el-button>
</template>
</el-input>
</el-form-item>
@@ -222,20 +210,6 @@ onMounted(async () => {
>
停止服务
</el-button>
<el-select
v-if="isServerRunning && swaggerFiles.length > 1"
v-model="selectedSwaggerFile"
placeholder="选择 Swagger 文件"
class="file-select"
@change="updateServerURL"
>
<el-option
v-for="file in swaggerFiles"
:key="file.name"
:label="file.name"
:value="file"
/>
</el-select>
<el-input
v-if="serverURL"
v-model="serverURL"
@@ -251,39 +225,19 @@ onMounted(async () => {
</el-form>
</el-card>
<el-card class="files-card">
<el-card class="content-card" v-if="swaggerFileInfo">
<template #header>
<div class="card-header">
<span>Swagger 文件列表</span>
<el-button type="primary" size="small" @click="loadSwaggerFiles" :loading="isLoading">刷新</el-button>
<span>{{ swaggerFileInfo.name }}</span>
<el-button size="small" @click="swaggerFileInfo = null">关闭</el-button>
</div>
</template>
<el-table :data="swaggerFiles" style="width: 100%" v-loading="isLoading">
<el-table-column prop="name" label="文件名" show-overflow-tooltip/>
<el-table-column prop="size" label="大小" width="120">
<template #default="scope">
{{ formatFileSize(scope.row.size) }}
</template>
</el-table-column>
<el-table-column prop="modifiedTime" label="修改时间" width="180"/>
<el-table-column label="操作" width="150">
<template #default="scope">
<el-button size="small" @click="viewFile(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<el-empty v-if="swaggerFiles.length === 0 && !isLoading" description="暂无 Swagger 文件"/>
</el-card>
<el-card class="content-card" v-if="selectedFile">
<template #header>
<div class="card-header">
<span>{{ selectedFile.name }}</span>
<el-button size="small" @click="selectedFile = null">关闭</el-button>
<div class="info-content">
<div class="file-info">
<p><strong>文件路径</strong>{{ swaggerFileInfo.path }}</p>
<p><strong>文件大小</strong>{{ formatFileSize(swaggerFileInfo.size) }}</p>
<p><strong>修改时间</strong>{{ swaggerFileInfo.modifiedTime }}</p>
</div>
</template>
<div class="file-content" v-loading="isLoading">
<pre>{{ fileContent }}</pre>
</div>
</el-card>
</div>

View File

@@ -12,6 +12,8 @@ export function ExecuteGenPs1(arg1:string,arg2:string,arg3:string,arg4:string):P
export function GetSettings():Promise<backend.Settings>;
export function GetSwaggerFileInfo(arg1:string):Promise<backend.SwaggerFile>;
export function GetSwaggerFiles(arg1:string):Promise<Array<backend.SwaggerFile>>;
export function GetSwaggerServerURL():Promise<string>;

View File

@@ -22,6 +22,10 @@ export function GetSettings() {
return window['go']['backend']['App']['GetSettings']();
}
export function GetSwaggerFileInfo(arg1) {
return window['go']['backend']['App']['GetSwaggerFileInfo'](arg1);
}
export function GetSwaggerFiles(arg1) {
return window['go']['backend']['App']['GetSwaggerFiles'](arg1);
}

View File

@@ -38,7 +38,7 @@ export namespace backend {
mysqlModelPath: string;
defaultQueryPackagePath: string;
modelBasePath: string;
swaggerDir: string;
swaggerFilePath: string;
databases: DatabaseConfig[];
projects: ProjectConfig[];
@@ -55,7 +55,7 @@ export namespace backend {
this.mysqlModelPath = source["mysqlModelPath"];
this.defaultQueryPackagePath = source["defaultQueryPackagePath"];
this.modelBasePath = source["modelBasePath"];
this.swaggerDir = source["swaggerDir"];
this.swaggerFilePath = source["swaggerFilePath"];
this.databases = this.convertValues(source["databases"], DatabaseConfig);
this.projects = this.convertValues(source["projects"], ProjectConfig);
}

View File

@@ -2,10 +2,11 @@ package main
import (
"embed"
"quickly/backend"
"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
@@ -15,8 +16,8 @@ func main() {
app := backend.NewApp()
err := wails.Run(&options.App{
Title: "Quickly 金牌助手",
Width: 1024,
Height: 768,
Width: 1280,
Height: 720,
AssetServer: &assetserver.Options{
Assets: assets,
},