feat(wordcloud): 收口在途开发(布局/存储/前端)+ R4 WCD 生产任务(jobs wcd_file)与生产订单列表

This commit is contained in:
2026-08-13 14:22:48 +08:00
parent 1d17b5e20d
commit e518540235
32 changed files with 3525 additions and 592 deletions
+74
View File
@@ -1,10 +1,17 @@
from __future__ import annotations
import os
import re
import shutil
import time
from pathlib import Path
from .schemas import JobPaths
_JOB_ID_RE = re.compile(r"^[0-9a-f]{32,}$")
class Storage:
def __init__(self, base_dir: Path) -> None:
self.base_dir = base_dir
@@ -25,3 +32,70 @@ class Storage:
excel_path=input_dir / "names.xlsx",
config_path=root / "config.json",
)
def job_root(self, job_id: str) -> Path:
return self.base_dir / job_id
def job_dir_size(self, job_id: str) -> int:
root = self.job_root(job_id)
if not root.exists():
return 0
total = 0
for dirpath, _, filenames in os.walk(root):
for filename in filenames:
try:
total += os.path.getsize(os.path.join(dirpath, filename))
except OSError:
continue
return total
def job_dir_info(self, job_id: str) -> dict | None:
root = self.job_root(job_id)
if not root.is_dir():
return None
try:
mtime = root.stat().st_mtime
except OSError:
return None
return {
"job_id": job_id,
"path": str(root),
"size_bytes": self.job_dir_size(job_id),
"age_days": round(max(0.0, time.time() - mtime) / 86400.0, 2),
}
def list_job_ids(self) -> list[str]:
if not self.base_dir.exists():
return []
return [
item.name
for item in self.base_dir.iterdir()
if item.is_dir() and _JOB_ID_RE.match(item.name)
]
def stale_job_dirs(
self,
referenced_job_ids: set[str],
exclude_job_ids: set[str] | None = None,
max_age_days: float | None = None,
) -> list[dict]:
exclude = exclude_job_ids or set()
result: list[dict] = []
for job_id in self.list_job_ids():
if job_id in referenced_job_ids or job_id in exclude:
continue
info = self.job_dir_info(job_id)
if not info:
continue
if max_age_days is not None and info["age_days"] < max_age_days:
continue
result.append(info)
return sorted(result, key=lambda item: item["size_bytes"], reverse=True)
def remove_job_dir(self, job_id: str) -> int:
root = self.job_root(job_id)
if not root.exists():
return 0
size = self.job_dir_size(job_id)
shutil.rmtree(root, ignore_errors=True)
return size