fix title area
This commit is contained in:
@@ -57,7 +57,7 @@
|
||||
width: 240px;
|
||||
background-color: var(--sidebar-bg);
|
||||
border-right: 1px solid var(--border-color);
|
||||
padding: 40px 20px;
|
||||
padding: 40px 20px 5px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@@ -1,69 +1,74 @@
|
||||
<template>
|
||||
<main class="content">
|
||||
<header class="content-header">
|
||||
<div class="header-left">
|
||||
<h1>装机必备</h1>
|
||||
<span v-if="store.essentialsVersion" class="version-badge">版本: {{ store.essentialsVersion }}</span>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button
|
||||
@click="store.syncDataIfNeeded(true)"
|
||||
class="secondary-btn action-btn"
|
||||
:disabled="store.loading || store.isBusy"
|
||||
>
|
||||
<span class="icon" :class="{ 'spinning': store.loading }">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 2v6h-6"></path>
|
||||
<path d="M3 12a9 9 0 0 1 15-6.7L21 8"></path>
|
||||
<path d="M3 22v-6h6"></path>
|
||||
<path d="M21 12a9 9 0 0 1-15 6.7L3 16"></path>
|
||||
</svg>
|
||||
</span>
|
||||
{{ store.loading ? '正在刷新...' : '刷新状态' }}
|
||||
</button>
|
||||
<button
|
||||
@click="installSelected"
|
||||
class="primary-btn action-btn"
|
||||
:disabled="store.loading || store.isBusy || store.selectedEssentialIds.length === 0"
|
||||
>
|
||||
安装所选 ({{ store.selectedEssentialIds.length }})
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<!-- 固定标头区域 -->
|
||||
<div class="sticky-header">
|
||||
<header class="content-header">
|
||||
<div class="header-left">
|
||||
<h1>装机必备</h1>
|
||||
<span v-if="store.essentialsVersion" class="version-badge">版本: {{ store.essentialsVersion }}</span>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button
|
||||
@click="store.syncDataIfNeeded(true)"
|
||||
class="secondary-btn action-btn"
|
||||
:disabled="store.loading || store.isBusy"
|
||||
>
|
||||
<span class="icon" :class="{ 'spinning': store.loading }">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 2v6h-6"></path>
|
||||
<path d="M3 12a9 9 0 0 1 15-6.7L21 8"></path>
|
||||
<path d="M3 22v-6h6"></path>
|
||||
<path d="M21 12a9 9 0 0 1-15 6.7L3 16"></path>
|
||||
</svg>
|
||||
</span>
|
||||
{{ store.loading ? '正在刷新...' : '刷新状态' }}
|
||||
</button>
|
||||
<button
|
||||
@click="installSelected"
|
||||
class="primary-btn action-btn"
|
||||
:disabled="store.loading || store.isBusy || store.selectedEssentialIds.length === 0"
|
||||
>
|
||||
安装所选 ({{ store.selectedEssentialIds.length }})
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 批量选择控制栏 -->
|
||||
<div class="selection-toolbar" v-if="selectableItems.length > 0">
|
||||
<div class="toolbar-left">
|
||||
<span class="selection-count">已选 {{ store.selectedEssentialIds.length }} / {{ selectableItems.length }} 项</span>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<button @click="store.selectAll('essential')" class="text-btn" :disabled="store.isBusy">全选</button>
|
||||
<div class="divider"></div>
|
||||
<button @click="store.deselectAll('essential')" class="text-btn" :disabled="store.isBusy">取消</button>
|
||||
<div class="divider"></div>
|
||||
<button @click="store.invertSelection('essential')" class="text-btn" :disabled="store.isBusy">反选</button>
|
||||
<!-- 批量选择控制栏 -->
|
||||
<div class="selection-toolbar" v-if="selectableItems.length > 0">
|
||||
<div class="toolbar-left">
|
||||
<span class="selection-count">已选 {{ store.selectedEssentialIds.length }} / {{ selectableItems.length }} 项</span>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<button @click="store.selectAll('essential')" class="text-btn" :disabled="store.isBusy">全选</button>
|
||||
<div class="divider"></div>
|
||||
<button @click="store.deselectAll('essential')" class="text-btn" :disabled="store.isBusy">取消</button>
|
||||
<div class="divider"></div>
|
||||
<button @click="store.invertSelection('essential')" class="text-btn" :disabled="store.isBusy">反选</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="store.loading && store.mergedEssentials.length === 0" class="loading-state">
|
||||
<div class="spinner"></div>
|
||||
<p>正在读取必备软件列表...</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="software-list">
|
||||
<SoftwareCard
|
||||
v-for="item in store.mergedEssentials"
|
||||
:key="item.id"
|
||||
:software="item"
|
||||
:action-label="item.actionLabel"
|
||||
:selectable="true"
|
||||
:is-selected="store.selectedEssentialIds.includes(item.id)"
|
||||
:disabled="store.isBusy"
|
||||
@install="store.install"
|
||||
@toggle-select="store.toggleSelection($event, 'essential')"
|
||||
@toggle-post-install="store.togglePostInstallPref"
|
||||
/>
|
||||
<!-- 可滚动内容区域 -->
|
||||
<div class="scroll-content">
|
||||
<div v-if="store.loading && store.mergedEssentials.length === 0" class="loading-state">
|
||||
<div class="spinner"></div>
|
||||
<p>正在读取必备软件列表...</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="software-list">
|
||||
<SoftwareCard
|
||||
v-for="item in store.mergedEssentials"
|
||||
:key="item.id"
|
||||
:software="item"
|
||||
:action-label="item.actionLabel"
|
||||
:selectable="true"
|
||||
:is-selected="store.selectedEssentialIds.includes(item.id)"
|
||||
:disabled="store.isBusy"
|
||||
@install="store.install"
|
||||
@toggle-select="store.toggleSelection($event, 'essential')"
|
||||
@toggle-post-install="store.togglePostInstallPref"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
@@ -99,8 +104,23 @@ onMounted(() => {
|
||||
<style scoped>
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 40px 60px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden; /* 关键:禁止最外层滚动 */
|
||||
}
|
||||
|
||||
.sticky-header {
|
||||
padding: 40px 60px 10px 60px;
|
||||
background-color: #F5F5F7; /* 与 App.vue 背景色保持一致 */
|
||||
z-index: 10;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.scroll-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px 60px 40px 60px;
|
||||
}
|
||||
|
||||
.content-header {
|
||||
@@ -138,16 +158,16 @@ onMounted(() => {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 批量选择工具栏 */
|
||||
.selection-toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 20px;
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
background-color: white; /* 这里的工具栏背景设为白色更清晰 */
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.03);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
.selection-count {
|
||||
|
||||
@@ -1,73 +1,78 @@
|
||||
<template>
|
||||
<main class="content">
|
||||
<header class="content-header">
|
||||
<div class="header-left">
|
||||
<h1>软件更新</h1>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button
|
||||
@click="store.fetchUpdates"
|
||||
class="secondary-btn action-btn"
|
||||
:disabled="store.loading || store.isBusy"
|
||||
>
|
||||
<span class="icon" :class="{ 'spinning': store.loading }">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 2v6h-6"></path>
|
||||
<path d="M3 12a9 9 0 0 1 15-6.7L21 8"></path>
|
||||
<path d="M3 22v-6h6"></path>
|
||||
<path d="M21 12a9 9 0 0 1-15 6.7L3 16"></path>
|
||||
</svg>
|
||||
</span>
|
||||
{{ store.loading ? '正在检查...' : '检查更新' }}
|
||||
</button>
|
||||
<button
|
||||
@click="updateSelected"
|
||||
class="primary-btn action-btn"
|
||||
:disabled="store.selectedUpdateIds.length === 0 || store.loading || store.isBusy"
|
||||
>
|
||||
更新所选 ({{ store.selectedUpdateIds.length }})
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<!-- 固定标头区域 -->
|
||||
<div class="sticky-header">
|
||||
<header class="content-header">
|
||||
<div class="header-left">
|
||||
<h1>软件更新</h1>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button
|
||||
@click="store.fetchUpdates"
|
||||
class="secondary-btn action-btn"
|
||||
:disabled="store.loading || store.isBusy"
|
||||
>
|
||||
<span class="icon" :class="{ 'spinning': store.loading }">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 2v6h-6"></path>
|
||||
<path d="M3 12a9 9 0 0 1 15-6.7L21 8"></path>
|
||||
<path d="M3 22v-6h6"></path>
|
||||
<path d="M21 12a9 9 0 0 1-15 6.7L3 16"></path>
|
||||
</svg>
|
||||
</span>
|
||||
{{ store.loading ? '正在检查...' : '检查更新' }}
|
||||
</button>
|
||||
<button
|
||||
@click="updateSelected"
|
||||
class="primary-btn action-btn"
|
||||
:disabled="store.selectedUpdateIds.length === 0 || store.loading || store.isBusy"
|
||||
>
|
||||
更新所选 ({{ store.selectedUpdateIds.length }})
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 批量选择控制栏 -->
|
||||
<div class="selection-toolbar" v-if="store.sortedUpdates.length > 0">
|
||||
<div class="toolbar-left">
|
||||
<span class="selection-count">已选 {{ store.selectedUpdateIds.length }} / {{ store.sortedUpdates.length }} 项</span>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<button @click="store.selectAll('update')" class="text-btn" :disabled="store.isBusy">全选</button>
|
||||
<div class="divider"></div>
|
||||
<button @click="store.deselectAll('update')" class="text-btn" :disabled="store.isBusy">取消</button>
|
||||
<div class="divider"></div>
|
||||
<button @click="store.invertSelection('update')" class="text-btn" :disabled="store.isBusy">反选</button>
|
||||
<!-- 批量选择控制栏 -->
|
||||
<div class="selection-toolbar" v-if="store.sortedUpdates.length > 0">
|
||||
<div class="toolbar-left">
|
||||
<span class="selection-count">已选 {{ store.selectedUpdateIds.length }} / {{ store.sortedUpdates.length }} 项</span>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<button @click="store.selectAll('update')" class="text-btn" :disabled="store.isBusy">全选</button>
|
||||
<div class="divider"></div>
|
||||
<button @click="store.deselectAll('update')" class="text-btn" :disabled="store.isBusy">取消</button>
|
||||
<div class="divider"></div>
|
||||
<button @click="store.invertSelection('update')" class="text-btn" :disabled="store.isBusy">反选</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="store.loading && store.updates.length === 0" class="loading-state">
|
||||
<div class="spinner"></div>
|
||||
<p>正在使用 Winget 扫描可用的更新...</p>
|
||||
</div>
|
||||
<!-- 可滚动内容区域 -->
|
||||
<div class="scroll-content">
|
||||
<div v-if="store.loading && store.updates.length === 0" class="loading-state">
|
||||
<div class="spinner"></div>
|
||||
<p>正在使用 Winget 扫描可用的更新...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="store.updates.length === 0 && !store.loading" class="empty-state">
|
||||
<span class="empty-icon">✅</span>
|
||||
<p>所有软件已是最新版本</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="software-list">
|
||||
<SoftwareCard
|
||||
v-for="item in store.sortedUpdates"
|
||||
:key="item.id"
|
||||
:software="item"
|
||||
:action-label="item.actionLabel"
|
||||
:selectable="true"
|
||||
:is-selected="store.selectedUpdateIds.includes(item.id)"
|
||||
:disabled="store.isBusy"
|
||||
@install="store.install"
|
||||
@toggle-select="store.toggleSelection($event, 'update')"
|
||||
@toggle-post-install="store.togglePostInstallPref"
|
||||
/>
|
||||
<div v-else-if="store.updates.length === 0 && !store.loading" class="empty-state">
|
||||
<span class="empty-icon">✅</span>
|
||||
<p>所有软件已是最新版本</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="software-list">
|
||||
<SoftwareCard
|
||||
v-for="item in store.sortedUpdates"
|
||||
:key="item.id"
|
||||
:software="item"
|
||||
:action-label="item.actionLabel"
|
||||
:selectable="true"
|
||||
:is-selected="store.selectedUpdateIds.includes(item.id)"
|
||||
:disabled="store.isBusy"
|
||||
@install="store.install"
|
||||
@toggle-select="store.toggleSelection($event, 'update')"
|
||||
@toggle-post-install="store.togglePostInstallPref"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
@@ -100,8 +105,23 @@ onMounted(() => {
|
||||
<style scoped>
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 40px 60px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden; /* 关键:禁止最外层滚动 */
|
||||
}
|
||||
|
||||
.sticky-header {
|
||||
padding: 40px 60px 10px 60px;
|
||||
background-color: #F5F5F7;
|
||||
z-index: 10;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.scroll-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px 60px 40px 60px;
|
||||
}
|
||||
|
||||
.content-header {
|
||||
@@ -123,16 +143,16 @@ onMounted(() => {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 批量选择工具栏 */
|
||||
.selection-toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 20px;
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
background-color: white;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.03);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
.selection-count {
|
||||
|
||||
Reference in New Issue
Block a user