refactor(ui): 优化客户端下载入口位置

- 将仪表盘页面的客户端下载链接移至右上角用户菜单
  - 登录页保留右下角客户端下载链接
  - 新增 clientDownloadUrl 全局状态,统一管理下载地址
  - AI 浮动按钮在登录页不显示
This commit is contained in:
kuaifan 2026-01-15 09:09:58 +00:00
parent 07360a8d2c
commit b794ba7a6b
4 changed files with 59 additions and 25 deletions

View File

@ -2,7 +2,7 @@
<div <div
v-show="visible" v-show="visible"
ref="floatBtn" ref="floatBtn"
class="ai-float-button" class="ai-float-button no-dark-content"
:style="btnStyle" :style="btnStyle"
@mousedown.stop.prevent="onMouseDown"> @mousedown.stop.prevent="onMouseDown">
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
@ -36,7 +36,10 @@ export default {
computed: { computed: {
visible() { visible() {
return this.userId > 0 && this.positionLoaded && !this.windowPortrait; return this.userId > 0 &&
this.positionLoaded &&
!this.windowPortrait &&
this.routeName !== 'login';
}, },
// left // left

View File

@ -3,16 +3,10 @@
<div v-if="showSSO" class="common-right-bottom-link" @click="useSSOLogin"> <div v-if="showSSO" class="common-right-bottom-link" @click="useSSOLogin">
{{ $L('使用 SSO 登录') }} {{ $L('使用 SSO 登录') }}
</div> </div>
<template v-if="showDown"> <a v-if="showDown && clientDownloadUrl" class="common-right-bottom-link" :href="clientDownloadUrl" target="_blank">
<a v-if="downloadUrl" class="common-right-bottom-link" :href="downloadUrl" target="_blank"> <Icon type="md-download"/>
<Icon type="md-download"/> {{ $L('客户端下载') }}
{{ $L('客户端下载') }} </a>
</a>
<div v-else-if="updateVersion && updateBottomShow && $Electron" class="common-right-bottom-link" @click="updateShow=true">
<Icon type="md-download"/>
{{ $L('更新客户端') }}
</div>
</template>
<a v-if="showPrivacy" class="common-right-bottom-link" target="_blank" :href="$A.apiUrl('privacy')"> <a v-if="showPrivacy" class="common-right-bottom-link" target="_blank" :href="$A.apiUrl('privacy')">
{{ $L('隐私政策') }} {{ $L('隐私政策') }}
</a> </a>
@ -43,6 +37,7 @@
const VMPreview = () => import('./VMEditor/preview'); const VMPreview = () => import('./VMEditor/preview');
import axios from "axios"; import axios from "axios";
import emitter from "../store/events"; import emitter from "../store/events";
import {mapState} from "vuex";
export default { export default {
name: 'RightBottom', name: 'RightBottom',
@ -59,8 +54,6 @@ export default {
updateShow: false, updateShow: false,
updateBottomShow: false, updateBottomShow: false,
updateIng: false, updateIng: false,
downloadUrl: '',
} }
}, },
@ -77,10 +70,12 @@ export default {
this.updateShow = !$A.strExists(this.updateNote, `[${this.updateVersion}-Silence]`); this.updateShow = !$A.strExists(this.updateNote, `[${this.updateVersion}-Silence]`);
}) })
} }
emitter.on('openDownloadClient', this.openDownloadClient);
}, },
beforeDestroy() { beforeDestroy() {
emitter.off('updateNotification', this.onUpdateShow); emitter.off('updateNotification', this.onUpdateShow);
emitter.off('openDownloadClient', this.openDownloadClient);
}, },
watch: { watch: {
@ -92,20 +87,17 @@ export default {
}, },
computed: { computed: {
...mapState(['clientDownloadUrl']),
showSSO() { showSSO() {
return this.$isSoftware && ['login'].includes(this.routeName) return this.$isSoftware && ['login'].includes(this.routeName)
}, },
showDown() { showDown() {
if (this.$isEEUIApp || this.windowTouch) { if (this.$Electron || this.$isEEUIApp || this.windowTouch) {
// app return false
return false;
} }
if (this.routeName == 'manage-dashboard' && this.windowPortrait) { return this.routeName === 'login'
//
return false;
}
return ['login', 'index', 'manage-dashboard'].includes(this.routeName)
}, },
showPrivacy() { showPrivacy() {
@ -118,6 +110,12 @@ export default {
this.updateShow = true this.updateShow = true
}, },
openDownloadClient() {
if (this.clientDownloadUrl) {
window.open(this.clientDownloadUrl, '_blank');
}
},
isNotServer() { isNotServer() {
let apiHome = $A.getDomain(window.systemInfo.apiUrl) let apiHome = $A.getDomain(window.systemInfo.apiUrl)
return this.$isSoftware && (apiHome == "" || apiHome == "public") return this.$isSoftware && (apiHome == "" || apiHome == "public")
@ -187,7 +185,7 @@ export default {
// //
switch (publish.provider) { switch (publish.provider) {
case 'generic': case 'generic':
this.downloadUrl = `${publish.url}/latest` this.$store.state.clientDownloadUrl = `${publish.url}/latest`
break; break;
case 'github': case 'github':
@ -196,7 +194,7 @@ export default {
let cache = await $A.IDBJson(key); let cache = await $A.IDBJson(key);
let timeout = 600; let timeout = 600;
if (cache.time && cache.time + timeout > $A.dayjs().unix()) { if (cache.time && cache.time + timeout > $A.dayjs().unix()) {
this.downloadUrl = cache.data.html_url; this.$store.state.clientDownloadUrl = cache.data.html_url;
return; return;
} }
// //
@ -210,7 +208,7 @@ export default {
cache.time = $A.dayjs().unix() cache.time = $A.dayjs().unix()
cache.data = data.find(({tag_name}) => this.compareVersion(this.tagVersion(tag_name), this.apiVersion) === 0) || {} cache.data = data.find(({tag_name}) => this.compareVersion(this.tagVersion(tag_name), this.apiVersion) === 0) || {}
$A.IDBSave(key, cache); $A.IDBSave(key, cache);
this.downloadUrl = cache.data.html_url; this.$store.state.clientDownloadUrl = cache.data.html_url;
} }
}).catch(() => { }).catch(() => {
this.loadIng--; this.loadIng--;

View File

@ -605,6 +605,7 @@ export default {
'columnTemplate', 'columnTemplate',
'clientNewVersion', 'clientNewVersion',
'clientDownloadUrl',
'reportUnreadNumber', 'reportUnreadNumber',
'approveUnreadNumber', 'approveUnreadNumber',
@ -712,6 +713,18 @@ export default {
} }
}, },
/**
* 是否显示客户端下载
* @returns {boolean}
*/
showDownloadClient() {
return !this.$Electron && !this.$isEEUIApp && !!this.clientDownloadUrl
},
/**
* 右上角菜单
* @returns {Array}
*/
menu() { menu() {
const {userIsAdmin} = this; const {userIsAdmin} = this;
const array = [ const array = [
@ -726,6 +739,7 @@ export default {
{path: 'system', name: '系统设置'}, {path: 'system', name: '系统设置'},
{path: 'license', name: 'License Key'}, {path: 'license', name: 'License Key'},
{path: 'downloadClient', name: '客户端下载', divided: true, visible: this.showDownloadClient},
{path: 'version', name: '更新版本', divided: true, visible: !!this.clientNewVersion}, {path: 'version', name: '更新版本', divided: true, visible: !!this.clientNewVersion},
{path: 'allProject', name: '所有项目', divided: true}, {path: 'allProject', name: '所有项目', divided: true},
@ -736,6 +750,7 @@ export default {
} else { } else {
array.push(...[ array.push(...[
{path: 'personal', name: '个人设置', divided: true}, {path: 'personal', name: '个人设置', divided: true},
{path: 'downloadClient', name: '客户端下载', divided: true, visible: this.showDownloadClient},
{path: 'version', name: '更新版本', divided: true, visible: !!this.clientNewVersion}, {path: 'version', name: '更新版本', divided: true, visible: !!this.clientNewVersion},
{path: 'workReport', name: '工作报告', divided: true}, {path: 'workReport', name: '工作报告', divided: true},
@ -749,6 +764,10 @@ export default {
return array return array
}, },
/**
* 项目模板列表
* @returns {Array}
*/
columns() { columns() {
const array = $A.cloneJSON(this.columnTemplate); const array = $A.cloneJSON(this.columnTemplate);
array.unshift({ array.unshift({
@ -758,6 +777,10 @@ export default {
return array return array
}, },
/**
* 项目列表
* @returns {Array}
*/
projectLists() { projectLists() {
const {projectKeyValue, cacheProjects} = this; const {projectKeyValue, cacheProjects} = this;
const data = $A.cloneJSON(cacheProjects).sort((a, b) => { const data = $A.cloneJSON(cacheProjects).sort((a, b) => {
@ -778,6 +801,10 @@ export default {
return data; return data;
}, },
/**
* 最近打开的任务列表
* @returns {Array}
*/
taskBrowseLists() { taskBrowseLists() {
// 使 // 使
return this.taskBrowseHistory.slice(0, 10); // 10 return this.taskBrowseHistory.slice(0, 10); // 10
@ -933,6 +960,9 @@ export default {
case 'version': case 'version':
emitter.emit('updateNotification', null); emitter.emit('updateNotification', null);
return; return;
case 'downloadClient':
emitter.emit('openDownloadClient');
return;
case 'clearCache': case 'clearCache':
$A.IDBSet("clearCache", "handle").then(_ => { $A.IDBSet("clearCache", "handle").then(_ => {
$A.reloadUrl() $A.reloadUrl()

View File

@ -234,6 +234,9 @@ export default {
// 客户端新版本号 // 客户端新版本号
clientNewVersion: null, clientNewVersion: null,
// 客户端下载地址(网页版)
clientDownloadUrl: '',
// 预览图片 // 预览图片
previewImageIndex: 0, previewImageIndex: 0,
previewImageList: [], previewImageList: [],