feat quickly
This commit is contained in:
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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{},
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user