82 lines
3.2 KiB
Vue
82 lines
3.2 KiB
Vue
<script setup lang="ts">
|
||
import { useDiskAnalysis } from "../composables/useDiskAnalysis";
|
||
import type { AlertOptions, FileNode } from "../types/cleaner";
|
||
|
||
const props = defineProps<{
|
||
showAlert: (options: AlertOptions) => void;
|
||
}>();
|
||
|
||
const emit = defineEmits<{
|
||
"open-context-menu": [event: MouseEvent, node: FileNode];
|
||
}>();
|
||
|
||
const { isFullScanning, fullScanProgress, treeData, startFullDiskScan, toggleNode } =
|
||
useDiskAnalysis(props.showAlert);
|
||
</script>
|
||
|
||
<template>
|
||
<section class="page-container full-width">
|
||
<div class="page-header">
|
||
<div class="header-info">
|
||
<h1>查找大目录</h1>
|
||
<p>查看 C 盘目录大小,适合技术人员细节分析空间占用情况。</p>
|
||
</div>
|
||
<div class="header-actions">
|
||
<button class="btn-primary btn-sm" :disabled="isFullScanning" @click="startFullDiskScan">
|
||
{{ isFullScanning ? "正在扫描..." : "开始扫描" }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-if="treeData.length > 0 || isFullScanning" class="tree-table-container shadow-card">
|
||
<div v-if="isFullScanning" class="scanning-overlay">
|
||
<div class="spinner"></div>
|
||
<div class="scanning-status">
|
||
<p class="scanning-main-text">正在扫描 C 盘文件...</p>
|
||
<div class="scanning-stats-row">
|
||
<span class="stat-badge">已扫描:{{ fullScanProgress.fileCount.toLocaleString() }} 个文件</span>
|
||
</div>
|
||
<p v-if="fullScanProgress.currentPath" class="scanning-current-path">
|
||
当前:{{ fullScanProgress.currentPath }}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-else class="tree-content-wrapper">
|
||
<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` }"
|
||
@contextmenu="emit('open-context-menu', $event, node)"
|
||
>
|
||
<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 svg-icon">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>
|
||
</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>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</template>
|