Files
spark-store/src/components/update-center/UpdateCenterList.vue
T
xiyidaiwa 0f62a7e36a feat(update-center): 支持被系统锁定(hold)包的强制安装与更新中心体验优化
- 标记 apt-mark hold 的 spark(aptss) 源包,默认禁用勾选并提示开启强制安装
- 更新中心发起更新时透传 forceHeld,后端 Spark 本地 deb 走 shell-caller
  force-ssinstall 分支(单次免密 pkexec:unhold→ssinstall→hold),避免二次提权
- 无可选项时禁用全选并提示"无可更新项";更新选中后从列表中移除已启动项
- DownloadDetail 紧凑布局避免整页滚动;Toolbar 全选与更新选中按钮同行
- 继承 PKGNAME_PATTERN 与 metalinkUrl 白名单(https+*.spark-app.store+拒..)纵深防御
- apm 源无 hold 概念,forceHeld 在 apm 分支忽略(正确行为)
2026-08-13 16:42:21 +08:00

77 lines
2.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div
class="min-h-0 flex-1 overflow-y-auto overscroll-contain scrollbar-muted border-r border-slate-200/70 p-6 dark:border-slate-800/70"
>
<div
v-if="items.length === 0"
class="rounded-2xl border border-dashed border-slate-200/80 px-4 py-10 text-center text-slate-500 dark:border-slate-800/80 dark:text-slate-400"
>
暂无可展示的更新任务
</div>
<div v-else class="space-y-3">
<UpdateCenterItem
v-for="item in enrichedItems"
:key="item.taskKey"
:item="item"
:task="taskMap.get(item.taskKey)"
:selected="selectedTaskKeys.has(item.taskKey)"
:forced="forcedTaskKeys.has(item.taskKey)"
@toggle-selection="$emit('toggle-selection', item.taskKey)"
@toggle-force="$emit('toggle-force', item.taskKey)"
@ignore-item="$emit('ignore-item', item.packageName, item.newVersion)"
@unignore-item="
$emit('unignore-item', item.packageName, item.newVersion)
"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from "vue";
import type {
App,
UpdateCenterItem as UpdateCenterItemModel,
UpdateCenterTaskState,
} from "@/global/typedefinition";
import UpdateCenterItem from "./UpdateCenterItem.vue";
const props = defineProps<{
items: UpdateCenterItemModel[];
tasks: UpdateCenterTaskState[];
selectedTaskKeys: Set<string>;
forcedTaskKeys: Set<string>;
apps: App[];
}>();
defineEmits<{
(e: "toggle-selection", taskKey: string): void;
(e: "toggle-force", taskKey: string): void;
(e: "ignore-item", packageName: string, newVersion: string): void;
(e: "unignore-item", packageName: string, newVersion: string): void;
}>();
// 从商店目录 apps 的 update 字段(app.json 的 Update,如 "2026-08-08"
// 推算更新发布时间,补全到更新列表项,用于显示「X天前」。匹配不到则保留原值(降级为「—」)。
const enrichedItems = computed<UpdateCenterItemModel[]>(() => {
const updateByPkg = new Map<string, number>();
for (const app of props.apps) {
if (app.pkgname && app.update) {
const t = Date.parse(app.update);
if (!Number.isNaN(t)) updateByPkg.set(app.pkgname, t);
}
}
return props.items.map((item) => {
if (item.updateTime && !Number.isNaN(item.updateTime)) return item;
const t = updateByPkg.get(item.packageName);
return t ? { ...item, updateTime: t } : item;
});
});
const taskMap = computed(() => {
return new Map(props.tasks.map((task) => [task.taskKey, task]));
});
</script>