refactor: 按模块重构项目结构

- 删除 vars 全局状态,按职责拆分 internal/ 包:scanner/probe/classify/organize/mover/store/digest
- 数据驱动归类规则替代图片/视频重复分支,store 改为结构体实例
- build.sh 按系统类型编译:Windows 用 upx 压缩,macOS/Linux 不压缩
- 忽略目录拆分:图片_已忽略 / 视频_已忽略
- 输出构建产物加入 .gitignore
This commit is contained in:
2025-03-26 21:08:12 +08:00
parent 26cbd5bb27
commit 4da4b738e6
36 changed files with 1016 additions and 2476 deletions
+72
View File
@@ -0,0 +1,72 @@
// Package classify 提供纯函数的分辨率归类规则,不依赖任何状态。
package classify
import "strings"
// Orientation 画面方向
type Orientation int
const (
OrientationSquare Orientation = iota
OrientationHorizontal
OrientationVertical
)
// OrientationOf 由宽高判定画面方向
func OrientationOf(width, height int) Orientation {
switch {
case width > height:
return OrientationHorizontal
case width < height:
return OrientationVertical
default:
return OrientationSquare
}
}
func (o Orientation) String() string {
switch o {
case OrientationHorizontal:
return "横屏"
case OrientationVertical:
return "竖屏"
default:
return "等比"
}
}
// ImageDir 返回图片归类子目录名,如 "图片_横屏_1080P" / "图片_GIF"
func ImageDir(ext string, width, height int) string {
if strings.EqualFold(ext, ".gif") {
return "图片_GIF"
}
return resolutionDir("图片", ext, width, height)
}
// VideoDir 返回视频归类子目录名,如 "视频_竖屏_4k" / "视频_横屏_GIF"
func VideoDir(ext string, width, height int) string {
return resolutionDir("视频", ext, width, height)
}
func resolutionDir(kind, ext string, width, height int) string {
ori := OrientationOf(width, height).String()
if strings.EqualFold(ext, ".gif") {
return kind + "_" + ori + "_GIF"
}
if suffix := matchStandard(width, height); suffix != "" {
return kind + "_" + ori + "_" + suffix
}
overflow := "原图"
if kind == "视频" {
overflow = "原画质"
}
return kind + "_" + ori + "_" + levelName(longEdge(width, height), overflow)
}
// longEdge 返回长边像素
func longEdge(w, h int) int {
if w > h {
return w
}
return h
}
+52
View File
@@ -0,0 +1,52 @@
package classify
import "fmt"
// standardResolution 标准分辨率规则:宽高精确匹配
type standardResolution struct {
width int
height int
suffix string
}
var standardResolutions = []standardResolution{
{1280, 720, "720P"}, // 720p 标准高清
{1600, 900, "1D5KP"}, // 介于 HD 与 FHD 之间
{1920, 1080, "1080P"}, // 1080p 全高清
{2048, 1080, "2DKP"}, // 影院 2K
{2560, 1440, "2D5KP"}, // 2.5K
{2560, 1080, "UltraWide2KP"}, // 带鱼屏
{3440, 1440, "UltraWide3KP"}, // 带鱼屏
{5120, 2160, "UltraWide4KP"}, // 带鱼屏
{3840, 2160, "4KP"}, // 主流 4K
{4096, 2160, "4KHP"}, // DCI 4K
{7680, 4320, "8KP"}, // 8K
}
// 非标分辨率分档参数
const (
bucketStep = 1024 // 每 1024px 一档
maxLevel = 19 // 1K ~ 19K 共 19 档(普通另算 1 档,合计 20 档)
)
// matchStandard 精确匹配标准分辨率,命中返回后缀,否则返回空串
func matchStandard(width, height int) string {
for _, r := range standardResolutions {
if r.width == width && r.height == height {
return r.suffix
}
}
return ""
}
// levelName 按长边分档:普通(<1024) / 1K~19K(每1024一档) / overflow(≥20480)
func levelName(longEdge int, overflow string) string {
if longEdge < bucketStep {
return "普通"
}
level := longEdge / bucketStep
if level > maxLevel {
return overflow
}
return fmt.Sprintf("%dK", level)
}