fix(更新日志): 面板随指定版本下拉联动;本机已是最新时展示本机条目
- 「指定版本更新」下拉选中版本时日志切到该版本自身的条目(升级/回退统一语义), 未收录显示"暂无更新说明"(区块不消失),选回空项回默认区间; 列表加载后自动默认选中第一条不触发切换 - 本机版本==线上最新时回退显示本机版本条目(原来整块消失),灰度/回滚仍隐藏 - 精简 4.0.20/4.0.21 超长文案,修复既有红测试(更新说明限 40 字)
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="update-hint">{{ hint }}</div>
|
||||
<UpdateLogList :entries="changelog" />
|
||||
<UpdateLogList :entries="changelog" :empty-text="changelogEmptyText" />
|
||||
<UpdateProgressBar :progress="progress" />
|
||||
<div v-if="hasUpdate || canDownload" style="margin-top: 4px;">
|
||||
<button type="button" class="btn-download-update" :disabled="updating" @click="doUpdate">
|
||||
@@ -38,6 +38,7 @@
|
||||
:updating="updating"
|
||||
@reload="loadVersions(true)"
|
||||
@update="doUpdateVersion"
|
||||
@select="setSelectedVersion"
|
||||
/>
|
||||
</div>
|
||||
<NotificationBell theme="light" />
|
||||
@@ -92,6 +93,8 @@ const {
|
||||
checked,
|
||||
progress,
|
||||
changelog,
|
||||
changelogEmptyText,
|
||||
setSelectedVersion,
|
||||
versions,
|
||||
versionListLoading,
|
||||
versionListError,
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="update-hint">{{ hint }}</div>
|
||||
<UpdateLogList :entries="changelog" />
|
||||
<UpdateLogList :entries="changelog" :empty-text="changelogEmptyText" />
|
||||
<UpdateProgressBar :progress="progress" />
|
||||
<VersionPicker
|
||||
:versions="versions"
|
||||
@@ -41,6 +41,7 @@
|
||||
:updating="updating"
|
||||
@reload="loadVersions(true)"
|
||||
@update="doUpdateVersion"
|
||||
@select="setSelectedVersion"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -148,6 +149,8 @@ const {
|
||||
checked,
|
||||
progress,
|
||||
changelog,
|
||||
changelogEmptyText,
|
||||
setSelectedVersion,
|
||||
versions,
|
||||
versionListLoading,
|
||||
versionListError,
|
||||
|
||||
@@ -28,14 +28,14 @@ export const CLIENT_CHANGELOG: ClientChangelogEntry[] = [
|
||||
version: '4.0.21',
|
||||
date: '2026-09-15',
|
||||
items: [
|
||||
'新增设备标识文件:客户端程序目录下会生成 code.txt,遇到问题时把文件里的标识发给客服,可快速查询本机日志',
|
||||
'客户端目录会生成 code.txt,遇到问题时把它发给客服,可快速查本机日志',
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '4.0.20',
|
||||
date: '2026-09-15',
|
||||
items: [
|
||||
'新增运行日志自动同步:本地日志会(压缩后)上传到云端后台,遇到问题客服可远程排查,不用再手动发日志文件(云端保留 7 天)',
|
||||
'本地日志会自动上传到云端(保留 7 天),遇到问题客服可远程排查,不用手动发日志',
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -214,12 +214,15 @@ export function newestChangelogVersion(entries: ClientChangelogEntry[] = CLIENT_
|
||||
*
|
||||
* - latestVersion 为空(检测未完成/失败)时按数据文件里最新版本兜底;
|
||||
* - currentVersion 为空(旧客户端无版本桥)时只给最新版本一条,不把整段历史倒给用户;
|
||||
* - 本机版本已高于线上(灰度/回滚)时返回空数组,由调用方隐藏该区块。
|
||||
* - 本机版本已高于线上(灰度/回滚)时返回空数组,由调用方隐藏该区块;
|
||||
* - includeCurrent 为 true(面板展示用)时,本机 == 线上(无更新可看)退回展示
|
||||
* 本机版本自身的条目——刚升级完的用户最想知道"这个版本改了什么"。
|
||||
*/
|
||||
export function selectChangelogEntries(options: {
|
||||
currentVersion?: string
|
||||
latestVersion?: string
|
||||
entries?: ClientChangelogEntry[]
|
||||
includeCurrent?: boolean
|
||||
} = {}): ClientChangelogEntry[] {
|
||||
const entries = options.entries ?? CLIENT_CHANGELOG
|
||||
if (!entries.length) return []
|
||||
@@ -231,5 +234,21 @@ export function selectChangelogEntries(options: {
|
||||
const newest = inRange.find((entry) => compareVersions(entry.version, upper) === 0)
|
||||
return [newest ?? inRange[0]]
|
||||
}
|
||||
return inRange.filter((entry) => compareVersions(entry.version, current) > 0)
|
||||
const newer = inRange.filter((entry) => compareVersions(entry.version, current) > 0)
|
||||
if (newer.length || !options.includeCurrent) return newer
|
||||
// 本机 == 线上:展示本机版本条目;本机高于线上时 inRange 里没有它,仍为空(不展示低版本日志)
|
||||
return inRange.filter((entry) => compareVersions(entry.version, current) === 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* 取指定版本自身的条目("指定版本更新"下拉选中时展示,升级/回退/同版统一语义)。
|
||||
* 版本未收录或版本号为空时返回空数组——不倒推相邻版本,避免张冠李戴。
|
||||
*/
|
||||
export function selectVersionEntry(
|
||||
version: string,
|
||||
entries: ClientChangelogEntry[] = CLIENT_CHANGELOG,
|
||||
): ClientChangelogEntry[] {
|
||||
const target = normVersion(version)
|
||||
if (!target) return []
|
||||
return entries.filter((entry) => compareVersions(entry.version, target) === 0)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div v-if="entries.length" class="update-log">
|
||||
<div v-if="entries.length || emptyText" class="update-log">
|
||||
<div class="update-log-title">更新日志</div>
|
||||
<div class="update-log-scroll">
|
||||
<div v-if="!entries.length" class="update-log-empty">{{ emptyText }}</div>
|
||||
<div v-else class="update-log-scroll">
|
||||
<div v-for="entry in entries" :key="entry.version" class="update-log-entry">
|
||||
<div class="update-log-head">
|
||||
<span class="update-log-version">v{{ entry.version }}</span>
|
||||
@@ -22,10 +23,11 @@
|
||||
* 内容来自 shared/client-changelog(发版时按 git 历史整理追加),
|
||||
* 由 useVersionUpdate 按"本机版本 → 最新版本"区间筛好后传入;
|
||||
* 条目多时区域内滚动,避免把面板撑长。
|
||||
* emptyText:选中版本未收录说明时的兜底文案(非空则保留标题与提示,避免区块整块消失)。
|
||||
*/
|
||||
import type { ClientChangelogEntry } from '@/shared/client-changelog'
|
||||
|
||||
defineProps<{ entries: ClientChangelogEntry[] }>()
|
||||
defineProps<{ entries: ClientChangelogEntry[]; emptyText?: string }>()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -43,6 +45,12 @@ defineProps<{ entries: ClientChangelogEntry[] }>()
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.update-log-empty {
|
||||
font-size: 12.5px;
|
||||
line-height: 1.6;
|
||||
color: #8293a5;
|
||||
}
|
||||
|
||||
.update-log-scroll {
|
||||
max-height: 176px;
|
||||
overflow-y: auto;
|
||||
|
||||
@@ -11,7 +11,12 @@
|
||||
</div>
|
||||
<div v-if="error" class="version-picker-error">{{ error }}</div>
|
||||
<template v-else>
|
||||
<select v-model="selected" class="version-picker-select" :disabled="loading || !versions.length">
|
||||
<select
|
||||
v-model="selected"
|
||||
class="version-picker-select"
|
||||
:disabled="loading || !versions.length"
|
||||
@change="emit('select', selected)"
|
||||
>
|
||||
<option value="">{{ versions.length ? '请选择要安装的版本' : '暂无可选版本' }}</option>
|
||||
<option v-for="item in versions" :key="item.version" :value="item.version">
|
||||
v{{ item.version }}
|
||||
@@ -35,6 +40,7 @@
|
||||
* 只负责选择与提示;版本列表加载、下载安装流程都在 useVersionUpdate 里
|
||||
* (列表项与判定文案见 shared/utils/version-picker)。
|
||||
* 选到低于本机的版本时给出"回退操作"提示,实际确认框由 doUpdateVersion 再提示一次。
|
||||
* 用户改选时 emit('select', version),页面转发给 useVersionUpdate 以切换更新日志。
|
||||
*/
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import {
|
||||
@@ -55,6 +61,8 @@ const props = defineProps<{
|
||||
const emit = defineEmits<{
|
||||
(e: 'update', item: ClientVersionItem): void
|
||||
(e: 'reload'): void
|
||||
/** 用户在下拉里改选版本(含选回空项):父组件据此把更新日志切到该版本 */
|
||||
(e: 'select', version: string): void
|
||||
}>()
|
||||
|
||||
const selected = ref('')
|
||||
@@ -70,13 +78,16 @@ const tip = computed(() =>
|
||||
selected.value ? describeTargetVersion(kind.value, props.currentVersion || '', selected.value) : '',
|
||||
)
|
||||
|
||||
// 列表刷新后选中项可能已不存在(版本被删除):清空选择,避免误装;
|
||||
// 无选中时默认选列表第一条(列表按版本号倒序,第一条即最新版)
|
||||
// 列表刷新后选中项可能已不存在(版本被删除):清空选择并通知父组件回退日志,
|
||||
// 避免日志还停留在已下架的版本上;
|
||||
// 无选中时默认选列表第一条(列表按版本号倒序,第一条即最新版)——这只是给「更新到此版本」
|
||||
// 一个默认目标,不触发 select 事件,更新日志保持默认视图(用户主动改选才切换)
|
||||
watch(
|
||||
() => props.versions,
|
||||
(list) => {
|
||||
if (selected.value && !list.some((item) => item.version === selected.value)) {
|
||||
selected.value = ''
|
||||
emit('select', '')
|
||||
}
|
||||
if (!selected.value && list.length) {
|
||||
selected.value = list[0].version
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import { computed, ref } from 'vue'
|
||||
import { getPywebviewApi } from '@/shared/bridges/pywebview'
|
||||
import { selectChangelogEntries, type ClientChangelogEntry } from '@/shared/client-changelog'
|
||||
import { selectChangelogEntries, selectVersionEntry, type ClientChangelogEntry } from '@/shared/client-changelog'
|
||||
import { compareVersions, normVersion } from '@/shared/utils/version-compare'
|
||||
import {
|
||||
classifyTargetVersion,
|
||||
@@ -261,9 +261,33 @@ export function useVersionUpdate() {
|
||||
// 进度条的百分比/文案由 UpdateProgressBar 组件从 progress 自行派生(见 shared/utils/update-progress)
|
||||
const progress = computed(() => updateProgress.value)
|
||||
|
||||
// 更新日志:本机版本之后到最新版本之间的条目(文案见 shared/client-changelog)
|
||||
const changelog = computed<ClientChangelogEntry[]>(() =>
|
||||
selectChangelogEntries({ currentVersion: currentVersion.value, latestVersion: latestVersion.value }),
|
||||
/**
|
||||
* 「指定版本更新」下拉里用户主动选中的版本(空串=未主动选,按默认区间展示)。
|
||||
* 只由下拉的用户交互驱动:列表加载后的默认选中不改变日志区块,保持默认视图稳定。
|
||||
*/
|
||||
const selectedVersion = ref('')
|
||||
|
||||
function setSelectedVersion(version: string) {
|
||||
selectedVersion.value = normVersion(version)
|
||||
}
|
||||
|
||||
// 更新日志:下拉选中了版本 → 显示该版本自身的条目(升级/回退统一语义);
|
||||
// 否则本机版本之后到最新版本之间的条目(本机已是最新时展示本机版本的条目),
|
||||
// 文案见 shared/client-changelog
|
||||
const changelog = computed<ClientChangelogEntry[]>(() => {
|
||||
if (selectedVersion.value) return selectVersionEntry(selectedVersion.value)
|
||||
return selectChangelogEntries({
|
||||
currentVersion: currentVersion.value,
|
||||
latestVersion: latestVersion.value,
|
||||
includeCurrent: true,
|
||||
})
|
||||
})
|
||||
|
||||
// 选中版本未收录更新说明时的兜底文案(区块保留标题,避免"选了版本日志反而整块消失")
|
||||
const changelogEmptyText = computed(() =>
|
||||
selectedVersion.value && !changelog.value.length
|
||||
? `v${selectedVersion.value} 暂无更新说明`
|
||||
: '',
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -291,6 +315,8 @@ export function useVersionUpdate() {
|
||||
checked,
|
||||
progress,
|
||||
changelog,
|
||||
changelogEmptyText,
|
||||
setSelectedVersion,
|
||||
versions,
|
||||
versionListLoading,
|
||||
versionListError,
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
CLIENT_CHANGELOG,
|
||||
newestChangelogVersion,
|
||||
selectChangelogEntries,
|
||||
selectVersionEntry,
|
||||
type ClientChangelogEntry,
|
||||
} from '../src/shared/client-changelog.ts'
|
||||
|
||||
@@ -62,13 +63,57 @@ test('更新日志:落后多个版本时逐版本列出(含中间版本)',
|
||||
assert.deepEqual(entries.map((entry) => entry.version), ['4.1.0', '4.0.11', '4.0.9'])
|
||||
})
|
||||
|
||||
test('更新日志:已是最新版本时没有条目(面板隐藏该区块)', () => {
|
||||
test('更新日志:已是最新版本且不带 includeCurrent 时没有条目(确认框语义)', () => {
|
||||
assert.deepEqual(
|
||||
selectChangelogEntries({ entries: FIXTURE, currentVersion: '4.0.11', latestVersion: '4.0.11' }),
|
||||
[],
|
||||
)
|
||||
})
|
||||
|
||||
test('更新日志:面板展示(includeCurrent)在本机已是最新时给出本机版本条目', () => {
|
||||
const entries = selectChangelogEntries({
|
||||
entries: FIXTURE,
|
||||
currentVersion: '4.0.11',
|
||||
latestVersion: '4.0.11',
|
||||
includeCurrent: true,
|
||||
})
|
||||
assert.deepEqual(entries.map((entry) => entry.version), ['4.0.11'])
|
||||
})
|
||||
|
||||
test('更新日志:面板展示在有更新时行为不变(只给本机之后的条目)', () => {
|
||||
const entries = selectChangelogEntries({
|
||||
entries: FIXTURE,
|
||||
currentVersion: '4.0.11',
|
||||
latestVersion: '4.1.0',
|
||||
includeCurrent: true,
|
||||
})
|
||||
assert.deepEqual(entries.map((entry) => entry.version), ['4.1.0'])
|
||||
})
|
||||
|
||||
test('更新日志:面板展示在本机高于线上(灰度/回滚)时仍不列条目', () => {
|
||||
assert.deepEqual(
|
||||
selectChangelogEntries({
|
||||
entries: FIXTURE,
|
||||
currentVersion: '4.1.0',
|
||||
latestVersion: '4.0.11',
|
||||
includeCurrent: true,
|
||||
}),
|
||||
[],
|
||||
)
|
||||
})
|
||||
|
||||
test('更新日志:面板展示在本机版本未被收录时不倒推旧条目', () => {
|
||||
assert.deepEqual(
|
||||
selectChangelogEntries({
|
||||
entries: FIXTURE,
|
||||
currentVersion: '4.0.10',
|
||||
latestVersion: '4.0.10',
|
||||
includeCurrent: true,
|
||||
}),
|
||||
[],
|
||||
)
|
||||
})
|
||||
|
||||
test('更新日志:本机版本高于线上(灰度/回滚)不列条目', () => {
|
||||
assert.deepEqual(
|
||||
selectChangelogEntries({ entries: FIXTURE, currentVersion: '4.1.0', latestVersion: '4.0.11' }),
|
||||
@@ -104,3 +149,23 @@ test('更新日志:版本号前缀 v 不影响筛选', () => {
|
||||
const entries = selectChangelogEntries({ entries: FIXTURE, currentVersion: 'v4.0.4', latestVersion: 'v4.0.11' })
|
||||
assert.deepEqual(entries.map((entry) => entry.version), ['4.0.11', '4.0.9'])
|
||||
})
|
||||
|
||||
test('指定版本日志:取选中版本自身的条目(升级/回退/同版统一语义)', () => {
|
||||
assert.deepEqual(
|
||||
selectVersionEntry('4.0.9', FIXTURE).map((entry) => entry.version),
|
||||
['4.0.9'],
|
||||
'回退到旧版本时也要能看到该版本的更新说明',
|
||||
)
|
||||
assert.deepEqual(selectVersionEntry('4.1.0', FIXTURE).map((entry) => entry.version), ['4.1.0'])
|
||||
})
|
||||
|
||||
test('指定版本日志:v 前缀与版本号为空', () => {
|
||||
assert.deepEqual(selectVersionEntry('v4.0.11', FIXTURE).map((entry) => entry.version), ['4.0.11'])
|
||||
assert.deepEqual(selectVersionEntry('', FIXTURE), [])
|
||||
assert.deepEqual(selectVersionEntry('v', FIXTURE), [])
|
||||
})
|
||||
|
||||
test('指定版本日志:未收录的版本不倒推相邻条目', () => {
|
||||
assert.deepEqual(selectVersionEntry('4.0.10', FIXTURE), [], '4.0.10 未收录,不能拿 4.0.9 的说明顶替')
|
||||
assert.deepEqual(selectVersionEntry('4.2.0', FIXTURE), [])
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user