@@ -1,6 +1,7 @@
< script setup lang = "ts" >
import { ref } from "vue" ;
import { invoke } from "@tauri-apps/api/core" ;
import pkg from "../package.json" ;
// --- 导航状态 ---
type Tab = 'clean-c-fast' | 'clean-c-advanced' | 'clean-c-deep' | 'clean-browser' | 'clean-memory' ;
@@ -27,7 +28,7 @@ const fastScanResult = ref<FastScanResult | null>(null);
const treeData = ref < FileNode [ ] > ( [ ] ) ;
const cleanMessage = ref ( "" ) ;
// 高级模式展开状态
// 高级模式特有
const expandedAdvanced = ref < string | null > ( null ) ;
const advLoading = ref < Record < string , boolean > > ( { } ) ;
@@ -58,6 +59,8 @@ async function startFastClean() {
cleanMessage . value = msg ;
isCleanDone . value = true ;
fastScanResult . value = null ;
} catch ( err ) {
alert ( "清理失败: " + err ) ;
} finally { isCleaning . value = false ; }
}
@@ -79,7 +82,7 @@ async function runAdvancedTask(task: string) {
}
}
// --- 深度分析 (原高级模式 ) 逻辑 ---
// --- 深度分析 (TreeSize ) 逻辑 ---
async function startFullDiskScan ( ) {
isFullScanning . value = true ;
treeData . value = [ ] ;
@@ -112,6 +115,8 @@ async function toggleNode(index: number) {
const mapped = children . map ( c => ( { ... c , level : node . level + 1 , isOpen : false , isLoading : false } ) ) ;
treeData . value . splice ( index + 1 , 0 , ... mapped ) ;
node . isOpen = true ;
} catch ( err ) {
console . error ( err ) ;
} finally { node . isLoading = false ; }
}
}
@@ -134,70 +139,153 @@ function formatItemSize(bytes: number): string {
< template >
< div class = "app-container" >
<!-- 侧边栏 -- >
< aside class = "sidebar" >
< div class = "sidebar-header" > < h2 class = "brand" > WinCleaner < / h2 > < / div >
< div class = "sidebar-header" >
< h2 class = "brand" > Windows 清理工具 < / h2 >
< / div >
< nav class = "sidebar-nav" >
<!-- 清理 C 盘组 -- >
< div class = "nav-group" >
< div class = "nav-item-header" @click ="isCMenuOpen = !isCMenuOpen" >
< span class = "icon" > 💾 < / span > < span class = "label" > 清理 C 盘 < / span >
< span class = "icon" > 💾 < / span >
< span class = "label" > 清理 C 盘 < / span >
< span class = "arrow" : class = "{ open: isCMenuOpen }" > ▾ < / span >
< / div >
< div class = "nav-sub-items" v-show = "isCMenuOpen" >
< div class = "nav-sub-item" : class = "{ active: activeTab === 'clean-c-fast' }" @click ="activeTab = 'clean-c-fast'" > 快速模式 < / div >
< div class = "nav-sub-item" : class = "{ active: activeTab === 'clean-c-advanced' }" @click ="activeTab = 'clean-c-advanced'" > 高级模式 < / div >
< div class = "nav-sub-item" : class = "{ active: activeTab === 'clean-c-deep ' }" @click ="activeTab = 'clean-c-deep'" > 深度分析 < / div >
< div
class = "nav-sub-item"
: class = "{ active: activeTab === 'clean-c-fast ' }"
@click ="activeTab = 'clean-c-fast'"
>
快速模式
< / div >
< div
class = "nav-sub-item"
: class = "{ active: activeTab === 'clean-c-advanced' }"
@click ="activeTab = 'clean-c-advanced'"
>
高级模式
< / div >
< div
class = "nav-sub-item"
: class = "{ active: activeTab === 'clean-c-deep' }"
@click ="activeTab = 'clean-c-deep'"
>
深度分析
< / div >
< / div >
< / div >
< div class = "nav-item" : class = "{ active: activeTab === 'clean-browser' }" @click ="activeTab = 'clean-browser'" >
< span class = "icon" > 🌐 < / span > < span class = "label" > 清理浏览器 < / span >
<!-- 其它项 -- >
< div
class = "nav-item"
: class = "{ active: activeTab === 'clean-browser' }"
@click ="activeTab = 'clean-browser'"
>
< span class = "icon" > 🌐 < / span >
< span class = "label" > 清理浏览器 < / span >
< / div >
< div class = "nav-item" : class = "{ active: activeTab === 'clean-memory' }" @click ="activeTab = 'clean-memory'" >
< span class = "icon" > 🚀 < / span > < span class = "label" > 清理内存 < / span >
< div
class = "nav-item"
: class = "{ active: activeTab === 'clean-memory' }"
@click ="activeTab = 'clean-memory'"
>
< span class = "icon" > 🚀 < / span >
< span class = "label" > 清理内存 < / span >
< / div >
< / nav >
< div class = "sidebar-footer" > < span class = "version" > v1 .0 .0 < / span > < / div >
< div class = "sidebar-footer" >
< span class = "version" > v { { pkg . version } } < / span >
< / div >
< / aside >
<!-- 内容区 -- >
< main class = "content" >
<!-- 1. 快速清理 -- >
<!-- 1. 快速清理页面 -- >
< section v-if = "activeTab === 'clean-c-fast'" class="page-container" >
< div class = "page-header" > < h1 > 快速清理系统盘 < / h1 > < p > 一键释放 C 盘空间 , 不影响系统安全 。 < / p > < / div >
< div class = "page-header" >
< h1 > 快速清理系统盘 < / h1 >
< p > 一键释放 C 盘空间 , 不影响系统运行 。 < / p >
< / div >
< div class = "main-action" >
<!-- 扫描前 / 中 -- >
< div class = "scan-circle-container" v-if = "!fastScanResult && !isCleanDone" >
< div class = "scan-circle" : class = "{ scanning: isScanning }" >
< div class = "scan-inner" @click ="!isScanning && startFastScan()" > < span v-if = "!isScanning" class="scan-btn-text">开始扫描</span><span v-else class="scan-percent" > {{ scanProgress }} % < / span > < / div >
< div class = "scan-inner" @click ="!isScanning && startFastScan()" >
< span v-if = "!isScanning" class="scan-btn-text" > 开始扫描 < / span >
< span v-else class = "scan-percent" > { { scanProgress } } % < / span >
< / div >
< / div >
< / div >
<!-- 扫描完成 -- >
< div class = "result-card" v-else-if = "fastScanResult && !isCleanDone" >
< div class = "result-header" > < span class = "result-icon" > 📋 < / span > < h2 > 扫描完成 < / h2 > < / div >
< div class = "result-stats " >
< div class = "stat-item" > < span class = "stat-value" > { { fastScanResult . total _size } } < / span > < span class = "stat-label" > 预计释放 < / span > < / div >
< div class = "stat-divider" > < / div >
< div class = "stat-item" > < span class = "stat-value" > { { fastScanResult . total _count } } < / span > < span class = "stat-label" > 文件数量 < / span > < / div >
< div class = "result-header" >
< span class = "result-icon " > 📋 < / span >
< h2 > 扫描完成 < / h2 >
< / div >
< div class = "result-stats" >
< div class = "stat-item" >
< span class = "stat-value" > { { fastScanResult . total _size } } < / span >
< span class = "stat-label" > 预计释放 < / span >
< / div >
< div class = "stat-divider" > < / div >
< div class = "stat-item" >
< span class = "stat-value" > { { fastScanResult . total _count } } < / span >
< span class = "stat-label" > 文件数量 < / span >
< / div >
< / div >
< div class = "simulation-toggle" >
< label class = "switch" > < input type = "checkbox" v-model = "isSimulation"><span class="slider round" > < / span > < / label >
< label class = "switch" >
< input type = "checkbox" v-model = "isSimulation" >
< span class = "slider round" > < / span >
< / label >
< span class = "toggle-label" > 模拟清理 ( 不实际删除文件 ) < / span >
< / div >
< button class = "btn-primary main-btn" @click ="startFastClean" :disabled = "isCleaning" > { { isCleaning ? '正在清理...' : ( isSimulation ? '开始模拟清理' : '立即清理' ) } } < / button >
< button class = "btn-primary main-btn" @click ="startFastClean" :disabled = "isCleaning" >
{ { isCleaning ? '正在清理...' : ( isSimulation ? '开始模拟清理' : '立即清理' ) } }
< / button >
< / div >
<!-- 清理完成报告 -- >
< div class = "result-card done-card" v-else-if = "isCleanDone" >
< div class = "result-header" > < span class = "result-icon success" > ✅ < / span > < h2 > 清理完成 < / h2 > < p class = "clean-summary" > { { cleanMessage } } < / p > < / div >
< div class = "result-header" >
< span class = "result-icon success" > ✅ < / span >
< h2 > 清理完成 < / h2 >
< p class = "clean-summary" > { { cleanMessage } } < / p >
< / div >
< div class = "done-info" >
< p > 您的 C 盘现在更加清爽了 ! < / p >
< / div >
< button class = "btn-secondary" @click ="resetAll" > 返回首页 < / button >
< / div >
< / div >
< div class = "detail-list" v-if = "(isScanning || fastScanResult) && !isCleanDone" >
< h3 > 清理项详情 < / h3 >
< div class = "detail-item" v-for = "item in fastScanResult?.items || []" :key="item.path"><span>{{ item.name }}</span><span class="item-size" > {{ formatItemSize ( item.size ) }} < / span > < / div >
< div class = "detail-item" v-for = "item in fastScanResult?.items || []" :key="item.path" >
< span > { { item . name } } < / span >
< span class = "item-size" > { { formatItemSize ( item . size ) } } < / span >
< / div >
< div v-if = "isScanning" class="scanning-placeholder" > 正在深度扫描文件系统... < / div >
< / div >
< / section >
< ! - - 2. 高级模式 ( 新增 ) - - >
< ! - - 2. 高级模式页面 - - >
< section v-else-if = "activeTab === 'clean-c-advanced'" class="page-container" >
< div class = "page-header" > < h1 > 高级清理工具 < / h1 > < p > 执行深层系统优化 , 释放更多被占用的磁盘空间 。 < / p > < / div >
< div class = "page-header" >
< h1 > 高级清理工具 < / h1 >
< p > 执行深层系统优化 , 释放更多被占用的磁盘空间 。 < / p >
< / div >
< div class = "adv-card-list" >
<!-- 项 1 : DISM -- >
<!-- 系统组件 -- >
< div class = "adv-card" : class = "{ expanded: expandedAdvanced === 'dism' }" >
< div class = "adv-card-main" @click ="expandedAdvanced = expandedAdvanced === 'dism' ? null : 'dism'" >
< div class = "adv-card-info" >
@@ -225,7 +313,7 @@ function formatItemSize(bytes: number): string {
< / div >
< / div >
<!-- 项 2 : 缩略图 -- >
<!-- 缩略图 -- >
< div class = "adv-card" : class = "{ expanded: expandedAdvanced === 'thumb' }" >
< div class = "adv-card-main" @click ="expandedAdvanced = expandedAdvanced === 'thumb' ? null : 'thumb'" >
< div class = "adv-card-info" >
@@ -250,7 +338,7 @@ function formatItemSize(bytes: number): string {
< / div >
< / div >
<!-- 项 3 : 休眠文件 -- >
<!-- 休眠 -- >
< div class = "adv-card" : class = "{ expanded: expandedAdvanced === 'hiber' }" >
< div class = "adv-card-main" @click ="expandedAdvanced = expandedAdvanced === 'hiber' ? null : 'hiber'" >
< div class = "adv-card-info" >
@@ -277,21 +365,53 @@ function formatItemSize(bytes: number): string {
< / div >
< / section >
<!-- 3. 深度分析 ( 原高级模式 ) -- >
<!-- 3. 深度分析页面 -- >
< section v-else-if = "activeTab === 'clean-c-deep'" class="page-container advanced-page" >
< div class = "page-header" > < h1 > 磁盘树深度分析 < / h1 > < p > 层级化查看 C 盘占用 , 锁定空间大户 。 < / p > < / div >
< div class = "advanced-actions" > < button class = "btn-primary" @click ="startFullDiskScan" :disabled = "isFullScanning" > { { isFullScanning ? '正在建立索引...' : '开始深度分析' } } < / button > < / div >
< div class = "page-header" >
< h1 > 查找大目录 < / h1 >
< p > 层级化查看 C 盘占用 , 锁定空间大户 。 < / p >
< / div >
< div class = "advanced-actions" >
< button class = "btn-primary" @click ="startFullDiskScan" :disabled = "isFullScanning" >
{ { isFullScanning ? '正在建立全盘索引...' : '开始深度分析' } }
< / button >
< / div >
< div class = "tree-table-container shadow-card" v-if = "treeData.length > 0 || isFullScanning" >
< div v-if = "isFullScanning" class="scanning-overlay"><div class="spinner" > < / div > < p > 正在分析数百万个文件 ... < / p > < / div >
< div v-if = "isFullScanning" class="scanning-overlay" >
< div class = "spinner" > < / div >
< p > 正在分析数百万个文件 , 请稍候 ... < / p >
< / div >
< div v-else >
< div class = "tree-header" > < span class = "col-name" > 名称 < / span > < span class = "col-size" > 大小 < / span > < span class = "col-graph" > 占比 < / span > < / div >
< div class = "tree-header" >
< span class = "col-name" > 文件 / 文件夹名称 < / span >
< span class = "col-size" > 大小 < / span >
< span class = "col-graph" > 相对于父目录占比 < / span >
< / div >
< div class = "tree-body" >
< div v-for = "(node, index) in treeData" :key="node.path" class="tree-row" :class="{ 'is-file': !node.is_dir }" :style="{ paddingLeft: (node.level * 20 + 16) + 'px' }" >
< div
v-for = "(node, index) in treeData"
:key = "node.path"
class = "tree-row"
: class = "{ 'is-file': !node.is_dir }"
: style = "{ paddingLeft: (node.level * 20 + 16) + 'px' }"
>
< div class = "col-name" @click ="toggleNode(index)" >
< span v-if = "node.is_dir" class="node-toggle">{{ node.isLoading ? '⌛' : (node.isOpen ? '▼' : '▶') }}</span><span v-else class="node-icon">📄</span><span class="node-text" > {{ node.name }} < / span >
< span v-if = "node.is_dir" class="node-toggle" >
{{ node.isLoading ? ' ⌛ ' : ( node.isOpen ? ' ▼ ' : ' ▶ ' ) }}
< / span >
< span v-else class = "node-icon" > 📄 < / span >
< span class = "node-text" > { { node . name } } < / span >
< / div >
< div class = "col-size" > { { node . size _str } } < / div >
< div class = "col-graph" > < div class = "mini-bar-bg" > < div class = "mini-bar-fill" : style = "{ width: node.percent + '%' }" > < / div > < / div > < span class = "percent-text" > { { Math . round ( node . percent ) } } % < / span > < / div >
< div class = "col-graph" >
< div class = "mini-bar-bg" >
< div class = "mini-bar-fill" : style = "{ width: node.percent + '%' }" > < / div >
< / div >
< span class = "percent-text" > { { Math . round ( node . percent ) } } % < / span >
< / div >
< / div >
< / div >
< / div >
@@ -299,34 +419,206 @@ function formatItemSize(bytes: number): string {
< / section >
<!-- 4. 其他占位 -- >
< section v-else class = "placeholder-page" > < div class = "empty-state" > < h1 > 功能开发中 < / h1 > < p > 敬请期待 。 < / p > < / div > < / section >
< section v-else class = "placeholder-page" >
< div class = "empty-state" >
< span class = "empty-icon" > 🛠 ️ < / span >
< h1 > 功能开发中 < / h1 >
< p > 此模块正在逐步完善 , 敬请期待 。 < / p >
< / div >
< / section >
< / main >
< / div >
< / template >
< style >
/* --- 全局样式复用 --- */
: root { -- primary - color : # 007 AFF ; -- primary - hover : # 0063 CC ; -- bg - light : # F9FAFB ; -- sidebar - bg : # FFFFFF ; -- text - main : # 1 D1D1F ; -- text - sec : # 86868 B ; -- border - color : # E5E5E7 ; -- card - shadow : 0 8 px 24 px rgba ( 0 , 0 , 0 , 0.05 ) ; }
* { box - sizing : border - box ; margin : 0 ; padding : 0 ; }
body { font - family : - apple - system , BlinkMacSystemFont , sans - serif ; color : var ( -- text - main ) ; background - colo r: var ( -- bg - light ) ; height : 100 vh ; overflow : hidden ; }
. app - container { display : flex ; height : 100 % ; }
. sidebar { width : 260 px ; background : var ( -- sidebar - bg ) ; border - right : 1 px solid var ( -- border - color ) ; display : flex ; flex - direction : column ; padding : 24 px 0 ; }
. sidebar - header { padding : 0 24 px 32 px ; } . brand { font - size : 22 px ; font - weight : 800 ; color : var ( -- primary - color ) ; }
. sidebar - nav { flex : 1 ; }
. nav - item , . nav - item - header { padding : 12 px 24 px ; display : flex ; align - items : center ; cursor : pointer ; color : # 424245 ; font - size : 15 px ; font - weight : 500 ; }
. nav - item . active { background : # F0F7FF ; color : var ( -- prim ary - color ) ; font - weight : 600 ; border - right : 3 px solid var ( -- primary - color ) ; }
. nav - sub - item { padding : 10 px 24 px 10 px 54 px ; cursor : pointer ; font - size : 14 px ; color : # 6 E6E73 ; }
. nav - sub - item . active { color : var ( -- primary - color ) ; font - weight : 600 ; background : # F0F7FF ; }
. arrow { margin - left : auto ; transition : transform 0.3 s ; font - size : 12 px ; } . arrow . open { transform : rotate ( 180 deg ) ; }
. content { flex : 1 ; padding : 40 px ; overflow - y : auto ; }
. page - container { max - width : 900 px ; margin : 0 auto ; } . page - header { margin - bottom : 32 px ; } . page - header h1 { font - size : 32 px ; font - weight : 800 ; margin - bottom : 8 px ; }
/* --- 全局基础样式修复 --- */
: root {
-- primary - color : # 007 AFF ;
-- primary - hove r: # 0063 CC ;
-- bg - light : # F9FAFB ;
-- sidebar - bg : # FFFFFF ;
-- text - main : # 1 D1D1F ;
-- text - sec : # 86868 B ;
-- border - color : # E5E5E7 ;
-- c ard - shadow : 0 8 px 24 px rgba ( 0 , 0 , 0 , 0.05 ) ;
}
/* --- 按钮样式 --- */
. btn - primary { background : var ( -- primary - color ) ; color : # fff ; border : none ; padding : 14 px 32 px ; border - radius : 12 px ; font - size : 16 px ; font - weight : 600 ; cursor : pointer ; }
. btn - secondary { background : # fff ; border : 1 px solid var ( -- border - color ) ; padding : 12 px 32 px ; border - radius : 12 px ; font - size : 15 px ; cursor : pointer ; }
. btn - action { background : # F2F2F7 ; color : var ( -- primary - color ) ; border : none ; padding : 8 px 20 px ; border - radius : 8 px ; font - weight : 700 ; cursor : pointer ; tr ansition : all 0.2 s ; min - width : 80 px ; }
. btn - action : hover { background : var ( -- primary - color ) ; color : # fff ; }
. btn - action : disabled { opacity : 0.5 ; cursor : wait ; }
* { box - sizing : border - box ; margin : 0 ; padding : 0 ; }
body {
font - family : - apple - system , BlinkMacSystemFont , "Segoe UI" , Roboto , s ans- serif ;
color : var ( -- text - main ) ;
background - color : var ( -- bg - light ) ;
height : 100 vh ;
overflow : hidden ; /* 锁定主体,由 .content 滚动 */
}
# app { height : 100 % ; }
. app - container {
display : flex ;
height : 100 % ;
}
/* --- 侧边栏精确恢复 --- */
. sidebar {
width : 260 px ;
background - color : var ( -- sidebar - bg ) ;
border - right : 1 px solid var ( -- border - color ) ;
display : flex ;
flex - direction : column ;
padding : 24 px 0 ;
z - index : 10 ;
}
. sidebar - header { padding : 0 24 px 32 px ; }
. brand { font - size : 22 px ; font - weight : 800 ; color : var ( -- primary - color ) ; letter - spacing : - 0.5 px ; }
. sidebar - nav { flex : 1 ; }
. nav - item , . nav - item - header {
padding : 12 px 24 px ;
display : flex ;
align - items : center ;
cursor : pointer ;
transition : all 0.2 s ;
color : # 424245 ;
font - size : 15 px ;
font - weight : 500 ;
}
. nav - item : hover , . nav - item - header : hover {
background - color : # F5F5F7 ;
color : var ( -- primary - color ) ;
}
. nav - item . active {
background - color : # F0F7FF ;
color : var ( -- primary - color ) ;
font - weight : 600 ;
border - right : 3 px solid var ( -- primary - color ) ;
}
. icon { margin - right : 12 px ; font - size : 18 px ; }
. arrow {
margin - left : auto ;
transition : transform 0.3 s ;
font - size : 12 px ;
color : # C1C1C1 ;
}
. arrow . open { transform : rotate ( 180 deg ) ; }
. nav - sub - items { background - color : # FAFAFA ; }
. nav - sub - item {
padding : 10 px 24 px 10 px 54 px ;
cursor : pointer ;
font - size : 14 px ;
color : # 6 E6E73 ;
transition : all 0.2 s ;
}
. nav - sub - item : hover { color : var ( -- primary - color ) ; }
. nav - sub - item . active {
color : var ( -- primary - color ) ;
font - weight : 600 ;
background - color : # F0F7FF ;
}
. sidebar - footer { padding : 16 px 24 px ; border - top : 1 px solid var ( -- border - color ) ; }
. version { font - size : 12 px ; color : var ( -- text - sec ) ; }
/* --- 内容区滚动修复 --- */
. content {
flex : 1 ;
padding : 40 px ;
overflow - y : auto ; /* 关键:确保右侧滚动 */
height : 100 % ;
}
. page - container { max - width : 900 px ; margin : 0 auto ; padding - bottom : 60 px ; }
. page - header { margin - bottom : 32 px ; }
. page - header h1 { font - size : 32 px ; font - weight : 800 ; margin - bottom : 8 px ; letter - spacing : - 0.5 px ; }
. page - header p { color : var ( -- text - sec ) ; font - size : 16 px ; }
/* --- 按钮样式精确恢复 --- */
. btn - primary {
background - color : var ( -- primary - color ) ;
color : white ;
border : none ;
padding : 14 px 32 px ;
border - radius : 12 px ;
font - size : 16 px ;
font - weight : 600 ;
cursor : pointer ;
transition : all 0.2 s ;
}
. btn - primary : hover { background - color : var ( -- primary - hover ) ; transform : translateY ( - 1 px ) ; }
. btn - primary : active { transform : translateY ( 0 ) ; }
. btn - primary : disabled { background - color : # A5C7FF ; cursor : not - allowed ; transform : none ; }
. btn - secondary {
background - color : white ;
color : var ( -- text - main ) ;
border : 1 px solid var ( -- border - color ) ;
padding : 12 px 32 px ;
border - radius : 12 px ;
font - size : 15 px ;
font - weight : 600 ;
cursor : pointer ;
transition : all 0.2 s ;
}
. btn - secondary : hover { background - color : # F5F5F7 ; border - color : # D1D1D6 ; }
. btn - action {
background - color : # F2F2F7 ;
color : var ( -- primary - color ) ;
border : none ;
padding : 8 px 20 px ;
border - radius : 8 px ;
font - weight : 700 ;
cursor : pointer ;
transition : all 0.2 s ;
min - width : 80 px ;
}
. btn - action : hover { background - color : var ( -- primary - color ) ; color : # fff ; }
/* --- 快速清理特有 UI --- */
. main - action { margin : 60 px 0 ; display : flex ; justify - content : center ; }
. scan - circle - container { width : 220 px ; height : 220 px ; }
. scan - circle {
width : 100 % ; height : 100 % ; border - radius : 50 % ; border : 4 px solid var ( -- border - color ) ;
display : flex ; align - items : center ; justify - content : center ; position : relative ;
transition : all 0.5 s ;
}
. scan - circle . scanning { border - color : var ( -- primary - color ) ; box - shadow : 0 0 40 px rgba ( 0 , 122 , 255 , 0.15 ) ; animation : pulse 2 s infinite ; }
. scan - inner {
width : 190 px ; height : 190 px ; border - radius : 50 % ; background : white ;
display : flex ; align - items : center ; justify - content : center ;
cursor : pointer ; box - shadow : var ( -- card - shadow ) ; transition : transform 0.2 s ;
}
. scan - inner : hover { transform : scale ( 1.05 ) ; }
. scan - btn - text { font - size : 22 px ; font - weight : 700 ; color : var ( -- primary - color ) ; }
. scan - percent { font - size : 36 px ; font - weight : 800 ; color : var ( -- primary - color ) ; }
. result - card {
background : white ; border - radius : 24 px ; padding : 40 px ; width : 100 % ;
box - shadow : var ( -- card - shadow ) ; text - align : center ; border : 1 px solid rgba ( 0 , 0 , 0 , 0.03 ) ;
}
. result - stats { display : flex ; justify - content : center ; align - items : center ; margin - bottom : 32 px ; }
. stat - value { display : block ; font - size : 36 px ; font - weight : 800 ; color : var ( -- primary - color ) ; }
. stat - divider { width : 1 px ; height : 50 px ; background - color : var ( -- border - color ) ; margin : 0 40 px ; }
. simulation - toggle { display : flex ; align - items : center ; justify - content : center ; margin - bottom : 24 px ; gap : 12 px ; }
. switch { position : relative ; display : inline - block ; width : 44 px ; height : 24 px ; }
. switch input { opacity : 0 ; width : 0 ; height : 0 ; }
. slider { position : absolute ; cursor : pointer ; top : 0 ; left : 0 ; right : 0 ; bottom : 0 ; background - color : # E5E5E7 ; transition : .4 s ; border - radius : 24 px ; }
. slider : before { position : absolute ; content : "" ; height : 18 px ; width : 18 px ; left : 3 px ; bottom : 3 px ; background - color : white ; transition : .4 s ; border - radius : 50 % ; box - shadow : 0 2 px 4 px rgba ( 0 , 0 , 0 , 0.1 ) ; }
input : checked + . slider { background - color : var ( -- primary - color ) ; }
input : checked + . slider : before { transform : translateX ( 20 px ) ; }
. done - card { border : 2 px solid # E8F5E9 ; }
. result - icon . success { color : # 34 C759 ; font - size : 54 px ; margin - bottom : 16 px ; display : block ; }
. clean - summary { font - size : 20 px ; color : var ( -- text - main ) ; font - weight : 700 ; margin - top : 12 px ; }
/* --- 高级模式卡片 --- */
. adv - card - list { display : flex ; flex - direction : column ; gap : 20 px ; }
@@ -335,51 +627,42 @@ body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; color: var(--
. adv - card - main : hover { background : # FAFAFA ; }
. adv - card - info { display : flex ; align - items : center ; gap : 20 px ; }
. adv - card - icon { font - size : 32 px ; }
. adv - card - text h3 { font - size : 18 px ; margin - bottom : 4 px ; }
. adv - card - text h3 { font - size : 18 px ; margin - bottom : 4 px ; font - weight : 700 ; }
. adv - card - text p { color : var ( -- text - sec ) ; font - size : 14 px ; }
. adv - card - detail { padding : 0 24 px 24 px 76 px ; border - top : 1 px solid # F2F2F7 ; background : # FAFAFA ; }
. detail - content { padding - top : 20 px ; }
. detail - content h4 { font - size : 14 px ; margin - bottom : 8 px ; color : var ( -- text - main ) ; }
. detail - content h4 { font - size : 14 px ; margin - bottom : 8 px ; color : var ( -- text - main ) ; font - weight : 700 ; }
. detail - content p { font - size : 14 px ; color : var ( -- text - sec ) ; line - height : 1.6 ; margin - bottom : 16 px ; }
. warning - title { color : # FF9500 ! important ; margin - top : 16 px ; }
. detail - content ul { padding - left : 20 px ; color : var ( -- text - sec ) ; font - size : 13 px ; }
. detail - content li { margin - bottom : 6 px ; }
/* --- 原有 UI 样式恢复 --- */
. main - action { margin : 60 px 0 ; display : flex ; justify - content : center ; }
. scan - circle - container { width : 220 px ; height : 220 px ; }
. scan - circle { width : 100 % ; height : 100 % ; border - radius : 50 % ; border : 4 px solid var ( -- border - color ) ; display : flex ; align - items : center ; justify - content : center ; position : relative ; }
. scan - circle . scanning { border - color : var ( -- primary - color ) ; animation : pulse 2 s infinite ; }
. scan - inner { width : 190 px ; height : 190 px ; border - radius : 50 % ; background : white ; display : flex ; align - items : center ; justify - content : center ; cursor : pointer ; box - shadow : var ( -- card - shadow ) ; }
. scan - btn - text { font - size : 22 px ; font - weight : 700 ; color : var ( -- primary - color ) ; }
. scan - percent { font - size : 36 px ; font - weight : 800 ; color : var ( -- primary - color ) ; }
. result - card { background : white ; border - radius : 24 px ; padding : 40 px ; width : 100 % ; box - shadow : var ( -- card - shadow ) ; text - align : center ; }
. result - stats { display : flex ; justify - content : center ; align - items : center ; margin - bottom : 32 px ; }
. stat - value { font - size : 36 px ; font - weight : 800 ; color : var ( -- primary - color ) ; display : block ; }
. stat - divider { width : 1 px ; height : 50 px ; background : var ( -- border - color ) ; margin : 0 40 px ; }
. simulation - toggle { display : flex ; align - items : center ; justify - content : center ; margin - bottom : 24 px ; gap : 12 px ; }
. switch { position : relative ; width : 44 px ; height : 24 px ; }
. switch input { opacity : 0 ; width : 0 ; height : 0 ; }
. slider { position : absolute ; cursor : pointer ; top : 0 ; left : 0 ; right : 0 ; bottom : 0 ; background : # E5E5E7 ; transition : .4 s ; border - radius : 24 px ; }
. slider : before { position : absolute ; content : "" ; height : 18 px ; width : 18 px ; left : 3 px ; bottom : 3 px ; background : white ; transition : .4 s ; border - radius : 50 % ; }
input : checked + . slider { background : var ( -- primary - color ) ; }
input : checked + . slider : before { transform : translateX ( 20 px ) ; }
/* --- 磁盘树样式 --- */
. tree - table - container { background : # fff ; border - radius : 16 px ; overflow : hidden ; margin - top : 24 px ; min - height : 400 px ; box - shadow : var ( -- card - shadow ) ; }
. tree - table - container { background : # fff ; border - radius : 16 px ; overflow : hidden ; margin - top : 24 px ; min - height : 400 px ; box - shadow : var ( -- card - shadow ) ; border : 1 px solid rgba ( 0 , 0 , 0 , 0.03 ) ; }
. tree - header { display : flex ; background : # F5F5F7 ; padding : 14 px 20 px ; font - size : 13 px ; font - weight : 700 ; color : var ( -- text - sec ) ; border - bottom : 1 px solid var ( -- border - color ) ; }
. tree - row { display : flex ; align - items : center ; padding : 12 px 20 px ; border - bottom : 1 px solid # F2F2F7 ; font - size : 14 px ; }
. tree - body { max - height : 600 px ; overflow - y : auto ; }
. tree - row { display : flex ; align - items : center ; padding : 12 px 20 px ; border - bottom : 1 px solid # F2F2F7 ; font - size : 14 px ; transition : background 0.1 s ; }
. tree - row : hover { background : # F9FAFB ; }
. col - name { flex : 2 ; display : flex ; align - items : center ; overflow : hidden ; }
. col - size { width : 110 px ; text - align : right ; font - family : monospace ; font - weight : 600 ; }
. col - name { flex : 2 ; display : flex ; align - items : center ; white - space : nowrap ; overflow : hidden ; text - overflow : ellipsis ; }
. col - size { width : 110 px ; text - align : right ; }
. col - graph { width : 200 px ; display : flex ; align - items : center ; gap : 12 px ; padding - left : 30 px ; }
. mini - bar - bg { flex : 1 ; height : 6 px ; background : # F2F2F7 ; border - radius : 3 px ; overflow : hidden ; }
. mini - bar - fill { height : 100 % ; background : linear - gradient ( 90 deg , # 007 AFF , # 5856 D6 ) ; }
. percent - text { font - size : 11 px ; width : 35 px ; }
. node - toggle { width : 24 px ; cursor : pointer ; color : # C1C1C1 ; }
. mini - bar - fill { height : 100 % ; background : linear - gradient ( 90 deg , # 007 AFF , # 5856 D6 ) ; border - radius : 3 px ; }
. percent - text { font - size : 11 px ; color : var ( -- text - sec ) ; width : 35 px ; font - weight : 600 ; }
. node - toggle { width : 24 px ; cursor : pointer ; color : # C1C1C1 ; display : inline - block ; text - align : center ; }
. node - icon { width : 24 px ; font - size : 14 px ; }
. detail - list { background : white ; border - radius : 16 px ; padding : 24 px ; box - shadow : var ( -- card - shadow ) ; margin - top : 32 px ; }
. detail - item { display : flex ; justify - content : space - between ; padding : 14 px 0 ; border - bottom : 1 px s olid # F2F2F7 ; font - size : 14 px ; }
/* --- 通用状态 --- */
. scanning - loader , . scanning - overlay { padding : 80 px 40 px ; text - align : center ; c olor : var ( -- text - sec ) ; }
. spinner { width : 40 px ; height : 40 px ; border : 4 px solid # f3f3f3 ; border - top : 4 px solid var ( -- primary - color ) ; border - radius : 50 % ; animation : spin 1 s linear infinite ; margin : 0 auto 20 px ; }
. detail - list { background : white ; border - radius : 16 px ; padding : 24 px ; box - shadow : var ( -- card - shadow ) ; margin - top : 32 px ; border : 1 px solid rgba ( 0 , 0 , 0 , 0.02 ) ; }
. detail - list h3 { font - size : 17 px ; margin - bottom : 16 px ; font - weight : 700 ; }
. detail - item { display : flex ; justify - content : space - between ; padding : 14 px 0 ; border - bottom : 1 px solid # F2F2F7 ; font - size : 14 px ; color : # 424245 ; }
. item - size { font - weight : 600 ; color : var ( -- primary - color ) ; }
. placeholder - page { padding - top : 100 px ; text - align : center ; color : var ( -- text - sec ) ; }
. empty - icon { font - size : 64 px ; display : block ; margin - bottom : 24 px ; }
@ keyframes spin { 0 % { transform : rotate ( 0 deg ) ; } 100 % { transform : rotate ( 360 deg ) ; } }
@ keyframes pulse { 0 % { box - shadow : 0 0 0 0 rgba ( 0 , 122 , 255 , 0.3 ) ; } 70 % { box - shadow : 0 0 0 25 px rgba ( 0 , 122 , 255 , 0 ) ; } 100 % { box - shadow : 0 0 0 0 rgba ( 0 , 122 , 255 , 0 ) ; } }