发布:v0.3.3 版本历史模块 + 域名迁移 + 站点版本信息修正
- 版本号更新至 0.3.3(version.go/wails.json/README.md) - 更新检查域名迁移 img.1216.top → c.1216.top - 新增 views/version 版本历史 Tab 页面(时间线 UI) - 设置面板新增版本历史入口按钮 - CHANGELOG 补全 0.3.3 全部 17 个提交记录 - 站点 HTML 修正(删除错误 v0.4.0,v0.3.3 为最新) - 生成 last-version.json / versions.json 发布数据
This commit is contained in:
@@ -67,8 +67,20 @@
|
||||
v-model="showSettings"
|
||||
:config="configStore.appConfig"
|
||||
@save="handleSaveConfig"
|
||||
@open-version-history="showVersionHistory = true"
|
||||
/>
|
||||
|
||||
<!-- 版本历史抽屉 -->
|
||||
<a-drawer
|
||||
v-model:visible="showVersionHistory"
|
||||
:width="720"
|
||||
:footer="false"
|
||||
:unmount-on-close="false"
|
||||
title="版本历史"
|
||||
>
|
||||
<VersionHistory />
|
||||
</a-drawer>
|
||||
|
||||
<!-- 升级提示弹窗 -->
|
||||
<UpdateNotification
|
||||
v-model="updateStore.showUpdate"
|
||||
@@ -83,6 +95,7 @@ import {computed, onMounted, onUnmounted, ref, watch} from 'vue'
|
||||
import {IconSettings, IconPushpin} from '@arco-design/web-vue/es/icon'
|
||||
import MarkdownEditor from './views/markdown-editor/index.vue'
|
||||
import DbCli from './views/db-cli/index.vue'
|
||||
import VersionHistory from './views/version/index.vue'
|
||||
import ThemeToggle from './components/ThemeToggle.vue'
|
||||
import FileSystem from './components/FileSystem/index.vue'
|
||||
import SettingsPanel from './components/SettingsPanel.vue'
|
||||
@@ -97,6 +110,7 @@ const ACTIVE_TAB_STORAGE_KEY = 'app-active-tab'
|
||||
const savedTab = localStorage.getItem(ACTIVE_TAB_STORAGE_KEY)
|
||||
const activeTab = ref((savedTab === 'user' ? 'file-system' : savedTab) || 'file-system')
|
||||
const showSettings = ref(false)
|
||||
const showVersionHistory = ref(false)
|
||||
const isMaximized = ref(false)
|
||||
const isPinned = ref(false)
|
||||
|
||||
@@ -219,10 +233,9 @@ watch(activeTab, (newTab) => {
|
||||
// 保存到 localStorage
|
||||
localStorage.setItem(ACTIVE_TAB_STORAGE_KEY, newTab)
|
||||
|
||||
// 检查 Tab 是否在可见列表中
|
||||
// 检查一级 Tab 是否在可见列表中
|
||||
const isVisible = appConfig.value.visibleTabs.includes(newTab)
|
||||
if (!isVisible && appConfig.value.visibleTabs.length > 0 && newTab !== appConfig.value.defaultTab) {
|
||||
// 切换到默认 Tab(避免重复触发)
|
||||
activeTab.value = appConfig.value.defaultTab
|
||||
}
|
||||
})
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
<!-- 版本更新 -->
|
||||
<a-tab-pane key="update" title="版本更新">
|
||||
<UpdatePanel />
|
||||
<UpdatePanel @open-version-history="handleOpenVersionHistory" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-drawer>
|
||||
@@ -122,7 +122,7 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits(['update:modelValue', 'save'])
|
||||
const emit = defineEmits(['update:modelValue', 'save', 'open-version-history'])
|
||||
|
||||
// 状态
|
||||
const visible = computed({
|
||||
@@ -291,6 +291,11 @@ const handleReset = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 打开版本历史
|
||||
const handleOpenVersionHistory = () => {
|
||||
emit('open-version-history')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
|
||||
<!-- 当前版本信息 -->
|
||||
<a-card title="版本信息" :bordered="false">
|
||||
<template #extra>
|
||||
<a-button type="text" size="small" @click="$emit('open-version-history')">
|
||||
<template #icon><icon-history /></template>
|
||||
版本历史
|
||||
</a-button>
|
||||
</template>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<div class="info-item">
|
||||
@@ -106,12 +112,16 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { Message, Modal } from '@arco-design/web-vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { IconHistory } from '@arco-design/web-vue/es/icon'
|
||||
import { useUpdateStore } from '../stores/update'
|
||||
|
||||
// Emits
|
||||
defineEmits(['open-version-history'])
|
||||
|
||||
// 使用更新管理 store
|
||||
const updateStore = useUpdateStore()
|
||||
|
||||
@@ -217,7 +227,12 @@ const handleInstall = async () => {
|
||||
|
||||
// 监听下载完成事件(本地覆盖:记录下载文件路径)
|
||||
const onDownloadComplete = (event) => {
|
||||
const data = typeof event === 'string' ? JSON.parse(event) : event
|
||||
let data: any
|
||||
try {
|
||||
data = typeof event === 'string' ? JSON.parse(event) : event
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
if (data.success && data.file_path) {
|
||||
downloadedFile.value = data.file_path
|
||||
|
||||
@@ -92,10 +92,18 @@ export const useConfigStore = defineStore('config', () => {
|
||||
|
||||
const { tabs = [], visibleTabs = [], defaultTab = 'file-system' } = result.data
|
||||
|
||||
// 一级 Tab 只有文件管理和数据库,其他功能(Markdown、版本历史)不作为独立 Tab
|
||||
const allKeys = ['file-system', 'db-cli']
|
||||
const tabTitles: Record<string, string> = { 'file-system': '文件管理', 'db-cli': '数据库' }
|
||||
const mergedTabs = allKeys.map(key => tabs.find(t => t.key === key) || { key, title: tabTitles[key] || key, enabled: true })
|
||||
const mergedVisible = visibleTabs.length
|
||||
? visibleTabs.filter(k => allKeys.includes(k))
|
||||
: allKeys
|
||||
|
||||
appConfig.value = {
|
||||
tabs: tabs.map(tab => ({ ...tab, visible: visibleTabs.includes(tab.key) })),
|
||||
visibleTabs,
|
||||
defaultTab
|
||||
tabs: mergedTabs.map(tab => ({ ...tab, visible: mergedVisible.includes(tab.key) })),
|
||||
visibleTabs: mergedVisible,
|
||||
defaultTab: defaultTab || 'file-system'
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载配置失败:', error)
|
||||
@@ -112,10 +120,9 @@ export const useConfigStore = defineStore('config', () => {
|
||||
appConfig.value = {
|
||||
tabs: [
|
||||
{ key: 'file-system', title: '文件管理', visible: true, enabled: true },
|
||||
{ key: 'db-cli', title: '数据库', visible: true, enhanced: true },
|
||||
{ key: 'markdown-editor', title: 'Markdown 编辑器', visible: true, enabled: true }
|
||||
{ key: 'db-cli', title: '数据库', visible: true, enhanced: true }
|
||||
],
|
||||
visibleTabs: ['file-system', 'db-cli', 'markdown-editor'],
|
||||
visibleTabs: ['file-system', 'db-cli'],
|
||||
defaultTab: 'file-system'
|
||||
}
|
||||
}
|
||||
|
||||
136
web/src/views/version/index.vue
Normal file
136
web/src/views/version/index.vue
Normal file
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div class="version-history">
|
||||
<!-- 顶部操作栏 -->
|
||||
<div class="version-header">
|
||||
<div class="header-right">
|
||||
<a-button type="text" size="small" @click="handleRefresh" :loading="refreshing">
|
||||
<template #icon><icon-refresh /></template>
|
||||
刷新
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="handleOpenExternal">
|
||||
<template #icon><icon-export /></template>
|
||||
在浏览器打开
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- iframe 嵌入远程页面 -->
|
||||
<div class="iframe-wrapper">
|
||||
<iframe
|
||||
ref="iframeRef"
|
||||
:src="iframeSrc"
|
||||
class="version-iframe"
|
||||
frameborder="0"
|
||||
@load="onIframeLoad"
|
||||
/>
|
||||
<div v-if="loading" class="iframe-loading">
|
||||
<a-spin size="32" />
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { IconRefresh, IconExport } from '@arco-design/web-vue/es/icon'
|
||||
|
||||
// ==================== 常量 ====================
|
||||
const BASE_URL = 'https://c.1216.top/u-desk/version.html'
|
||||
|
||||
// ==================== 状态 ====================
|
||||
const currentVersion = ref('')
|
||||
const loading = ref(true)
|
||||
const refreshing = ref(false)
|
||||
const iframeRef = ref<HTMLIFrameElement | null>(null)
|
||||
|
||||
// ==================== 计算属性 ====================
|
||||
const iframeSrc = computed(() => {
|
||||
if (currentVersion.value) {
|
||||
return `${BASE_URL}?v=${currentVersion.value}&vis=u-desk`
|
||||
}
|
||||
return `${BASE_URL}?vis=u-desk`
|
||||
})
|
||||
|
||||
// ==================== 操作 ====================
|
||||
function handleRefresh(): void {
|
||||
refreshing.value = true
|
||||
loading.value = true
|
||||
if (iframeRef.value) {
|
||||
iframeRef.value.src = iframeSrc.value
|
||||
}
|
||||
}
|
||||
|
||||
function handleOpenExternal(): void {
|
||||
window.open(iframeSrc.value, '_blank')
|
||||
}
|
||||
|
||||
function onIframeLoad(): void {
|
||||
loading.value = false
|
||||
refreshing.value = false
|
||||
}
|
||||
|
||||
// ==================== 生命周期 ====================
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const result = await window.go?.main?.App?.GetCurrentVersion?.()
|
||||
if (result?.success) {
|
||||
currentVersion.value = result.data?.version || ''
|
||||
}
|
||||
} catch {
|
||||
// Wails 未就绪时忽略
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.version-history {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
/* ====== 顶部栏 ====== */
|
||||
.version-header {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* ====== iframe ====== */
|
||||
.iframe-wrapper {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.version-iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: var(--color-bg-1);
|
||||
}
|
||||
|
||||
.iframe-loading {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
color: var(--color-text-3);
|
||||
background: var(--color-bg-1);
|
||||
border-radius: 8px;
|
||||
}
|
||||
</style>
|
||||
6
web/src/wailsjs/wailsjs/go/main/App.d.ts
vendored
6
web/src/wailsjs/wailsjs/go/main/App.d.ts
vendored
@@ -28,8 +28,6 @@ export function EmptyRecycleBin():Promise<void>;
|
||||
|
||||
export function ExecuteSQL(arg1:number,arg2:string,arg3:string):Promise<Record<string, any>>;
|
||||
|
||||
export function ExportMarkdownToPDF(arg1:string):Promise<string>;
|
||||
|
||||
export function ExportPDF(arg1:string,arg2:string,arg3:string,arg4:number,arg5:number,arg6:number):Promise<Record<string, any>>;
|
||||
|
||||
export function ExtractFileFromZip(arg1:string,arg2:string):Promise<string>;
|
||||
@@ -76,8 +74,6 @@ export function GetUpdateConfig():Promise<Record<string, any>>;
|
||||
|
||||
export function GetZipFileInfo(arg1:string,arg2:string):Promise<Record<string, any>>;
|
||||
|
||||
export function Greet(arg1:string):Promise<string>;
|
||||
|
||||
export function InstallUpdate(arg1:string,arg2:boolean):Promise<Record<string, any>>;
|
||||
|
||||
export function InstallUpdateWithHash(arg1:string,arg2:boolean,arg3:string,arg4:string):Promise<Record<string, any>>;
|
||||
@@ -96,8 +92,6 @@ export function OpenPath(arg1:string):Promise<void>;
|
||||
|
||||
export function PreviewTableStructure(arg1:number,arg2:string,arg3:string,arg4:Record<string, any>):Promise<Array<string>>;
|
||||
|
||||
export function QueryUsers(arg1:string,arg2:number,arg3:number,arg4:number,arg5:number,arg6:number,arg7:string,arg8:string):Promise<Record<string, any>>;
|
||||
|
||||
export function ReadFile(arg1:string):Promise<string>;
|
||||
|
||||
export function Reload():Promise<void>;
|
||||
|
||||
@@ -50,10 +50,6 @@ export function ExecuteSQL(arg1, arg2, arg3) {
|
||||
return window['go']['main']['App']['ExecuteSQL'](arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
export function ExportMarkdownToPDF(arg1) {
|
||||
return window['go']['main']['App']['ExportMarkdownToPDF'](arg1);
|
||||
}
|
||||
|
||||
export function ExportPDF(arg1, arg2, arg3, arg4, arg5, arg6) {
|
||||
return window['go']['main']['App']['ExportPDF'](arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
@@ -146,10 +142,6 @@ export function GetZipFileInfo(arg1, arg2) {
|
||||
return window['go']['main']['App']['GetZipFileInfo'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function Greet(arg1) {
|
||||
return window['go']['main']['App']['Greet'](arg1);
|
||||
}
|
||||
|
||||
export function InstallUpdate(arg1, arg2) {
|
||||
return window['go']['main']['App']['InstallUpdate'](arg1, arg2);
|
||||
}
|
||||
@@ -186,10 +178,6 @@ export function PreviewTableStructure(arg1, arg2, arg3, arg4) {
|
||||
return window['go']['main']['App']['PreviewTableStructure'](arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
export function QueryUsers(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) {
|
||||
return window['go']['main']['App']['QueryUsers'](arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
}
|
||||
|
||||
export function ReadFile(arg1) {
|
||||
return window['go']['main']['App']['ReadFile'](arg1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user