feat(web): 桌面登录页记住密码/自动登录与版本更新,首页版本更新入口与背景修复
- 登录页(仅桌面端)新增"记住密码/自动登录"勾选与"更新版本"按钮:登录成功持久化凭据 (base64 存桌面 localStorage),打开登录页恢复勾选并静默登录;显式登出/切号后关闭自动登录 - 新增 shared/composables/useVersionUpdate 统一版本检测:/api/version/latest 与本机版本比较, 通过 pywebview 桥 get_app_version 读本地 exe 版本,缺桥时降级为可手动更新 - 首页保留 ↻ 图标并加显式"更新版本"按钮,接入新检测逻辑 - 首页背景改画到 .home-root,避免被 SPA 全局样式时序覆盖导致图不显示
This commit is contained in:
@@ -10,18 +10,24 @@
|
||||
title="检测更新"
|
||||
@click="toggleUpdatePanel"
|
||||
>↻</button>
|
||||
<button
|
||||
v-if="isDesktopRuntime"
|
||||
type="button"
|
||||
class="header-update-text"
|
||||
@click="toggleUpdatePanel"
|
||||
>更新版本</button>
|
||||
<div class="header-update-panel" v-show="updatePanel">
|
||||
<div class="header-update-title"><span>↻</span> 软件更新</div>
|
||||
<div class="update-block">
|
||||
<span class="update-version-text">当前版本: {{ versionText }}</span>
|
||||
<button type="button" class="btn-check-update" @click="checkUpdate">
|
||||
<span>↻</span> 检测
|
||||
<span class="update-version-text">当前版本: {{ currentVersion || '未知' }}</span>
|
||||
<button type="button" class="btn-check-update" :disabled="checking" @click="runCheck">
|
||||
<span>↻</span> {{ checking ? '检测中...' : '检测' }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="update-hint">{{ updateHint }}</div>
|
||||
<div style="margin-top: 4px;">
|
||||
<button type="button" class="btn-download-update" v-if="updateReady" @click="doUpdate">
|
||||
立即更新
|
||||
<div class="update-hint">{{ hint }}</div>
|
||||
<div v-if="hasUpdate || canDownload" style="margin-top: 4px;">
|
||||
<button type="button" class="btn-download-update" :disabled="updating" @click="doUpdate">
|
||||
{{ updating ? '更新中...' : '立即更新' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,16 +70,15 @@
|
||||
import { computed, onMounted, ref, watch } from 'vue'
|
||||
import { restoreLoginUser } from '@/shared/auth/ensure-auth'
|
||||
import { getCurrentUserAppColumnRaw, type PermissionMenuItem } from '@/shared/api/permission'
|
||||
import { getPywebviewApi, isDesktopRuntime } from '@/shared/bridges/pywebview'
|
||||
import { isDesktopRuntime } from '@/shared/bridges/pywebview'
|
||||
import { useVersionUpdate } from '@/shared/composables/useVersionUpdate'
|
||||
import { resolvePageHref } from '@/shared/page-prefix'
|
||||
|
||||
const username = ref('')
|
||||
const versionText = ref('—')
|
||||
const updatePanel = ref(false)
|
||||
const updateHint = ref('')
|
||||
const updateReady = ref(false)
|
||||
const updateFileUrl = ref('')
|
||||
const toastText = ref('')
|
||||
const { checking, updating, currentVersion, hasUpdate, canDownload, hint, checked, runCheck, doUpdate } =
|
||||
useVersionUpdate()
|
||||
|
||||
// 桌面端原 Flask /logout 已随瘦身下线:统一跳登录页并清本地 token(/login?logout=1)
|
||||
const logoutHref = computed(() => `${resolvePageHref('/new_web_source/login.html')}?logout=1`)
|
||||
@@ -162,69 +167,21 @@ async function loadCurrentUser() {
|
||||
|
||||
function toggleUpdatePanel() {
|
||||
updatePanel.value = !updatePanel.value
|
||||
}
|
||||
|
||||
async function fetchVersion() {
|
||||
try {
|
||||
const resp = await window.fetch('/api/version', { credentials: 'same-origin' })
|
||||
const data = await resp.json().catch(() => ({}))
|
||||
const current = String((data && data.version) || '').replace(/^v/i, '')
|
||||
if (current) versionText.value = current || '—'
|
||||
return data || {}
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
async function checkUpdate() {
|
||||
updateHint.value = '正在检测更新...'
|
||||
updateReady.value = false
|
||||
try {
|
||||
const data = await fetchVersion()
|
||||
if (data.has_update && data.latest_version) {
|
||||
updateHint.value =
|
||||
`发现新版本 v${String(data.latest_version).replace(/^v/i, '')}` +
|
||||
(data.desc ? `:${data.desc}` : '')
|
||||
if (data.file_url) {
|
||||
updateReady.value = true
|
||||
updateFileUrl.value = data.file_url
|
||||
} else {
|
||||
updateHint.value = '暂无下载地址,请关注官方渠道。'
|
||||
}
|
||||
} else {
|
||||
updateHint.value = '已是最新版本'
|
||||
}
|
||||
} catch {
|
||||
updateHint.value = '检测更新失败'
|
||||
}
|
||||
}
|
||||
|
||||
async function doUpdate() {
|
||||
if (!updateFileUrl.value) return
|
||||
if (!window.confirm('有更新,是否现在更新?\n更新将下载安装包并重启程序。')) return
|
||||
updateHint.value = '正在下载并准备更新,程序将自动退出...'
|
||||
updateReady.value = false
|
||||
try {
|
||||
// 版本更新是桌面客户端专属动作:经浏览器桥调用本地 update 下载/启动(服务端化后无 /api/update/do)
|
||||
const bridge = getPywebviewApi()
|
||||
const result = bridge?.do_update_app ? await bridge.do_update_app(updateFileUrl.value) : undefined
|
||||
updateHint.value = result?.success
|
||||
? '更新已启动,程序即将退出...'
|
||||
: (result?.error || '当前环境不支持自动更新')
|
||||
} catch {
|
||||
updateHint.value = '请求更新失败,请重试'
|
||||
// 首次展开面板即触发一次检测(版本逻辑在 shared/composables/useVersionUpdate)
|
||||
if (updatePanel.value && !checked.value && !checking.value) {
|
||||
void runCheck()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void loadCurrentUser()
|
||||
void loadPermissions()
|
||||
// 版本检测/更新仅桌面客户端(本地 Flask image 蓝图)提供;桌面桥注入后立即拉取
|
||||
// 版本检测/更新仅桌面客户端:桌面桥注入后立即检测一次(逻辑见 useVersionUpdate)
|
||||
watch(
|
||||
isDesktopRuntime,
|
||||
(runtime) => {
|
||||
if (runtime) {
|
||||
void fetchVersion().catch(() => undefined)
|
||||
void runCheck()
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
@@ -247,7 +204,10 @@ body {
|
||||
}
|
||||
|
||||
.home-root {
|
||||
/* 背景直接落到根容器,避免依赖 body 被 SPA 全局样式覆盖导致图不显示 */
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5)),
|
||||
url("/bg.jpg") center/cover no-repeat;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@@ -316,6 +276,21 @@ body {
|
||||
background: rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.header-update-text {
|
||||
padding: 5px 12px;
|
||||
font-size: 13px;
|
||||
color: #4c5bd4;
|
||||
background: rgba(102, 126, 234, 0.12);
|
||||
border: 1px solid rgba(102, 126, 234, 0.35);
|
||||
border-radius: 14px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.header-update-text:hover {
|
||||
background: rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.header-update-panel {
|
||||
position: absolute;
|
||||
top: 44px;
|
||||
|
||||
Reference in New Issue
Block a user