643 lines
22 KiB
Python
643 lines
22 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
用户管理系统 - 代码结构验证脚本
|
||
验证所有模块、接口、服务的完整性
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
from pathlib import Path
|
||
from typing import List, Dict, Tuple
|
||
import json
|
||
|
||
# 颜色输出
|
||
class Colors:
|
||
HEADER = '\033[95m'
|
||
OKBLUE = '\033[94m'
|
||
OKCYAN = '\033[96m'
|
||
OKGREEN = '\033[92m'
|
||
WARNING = '\033[93m'
|
||
FAIL = '\033[91m'
|
||
ENDC = '\033[0m'
|
||
BOLD = '\033[1m'
|
||
UNDERLINE = '\033[4m'
|
||
|
||
# 项目根目录
|
||
PROJECT_ROOT = Path(__file__).parent.absolute()
|
||
|
||
# 预期的文件结构
|
||
EXPECTED_STRUCTURE = {
|
||
"cmd/server/main.go": "主程序入口",
|
||
"go.mod": "Go模块依赖",
|
||
"Makefile": "构建脚本",
|
||
|
||
# Domain层
|
||
"internal/domain/user.go": "用户实体",
|
||
"internal/domain/role.go": "角色实体",
|
||
"internal/domain/permission.go": "权限实体",
|
||
"internal/domain/device.go": "设备实体",
|
||
"internal/domain/user_role.go": "用户角色关联",
|
||
"internal/domain/role_permission.go": "角色权限关联",
|
||
"internal/domain/login_log.go": "登录日志",
|
||
"internal/domain/operation_log.go": "操作日志",
|
||
|
||
# Repository层
|
||
"internal/repository/user.go": "用户数据访问",
|
||
"internal/repository/role.go": "角色数据访问",
|
||
"internal/repository/permission.go": "权限数据访问",
|
||
"internal/repository/device.go": "设备数据访问",
|
||
"internal/repository/user_role.go": "用户角色关联",
|
||
"internal/repository/role_permission.go": "角色权限关联",
|
||
|
||
# Service层
|
||
"internal/service/auth.go": "认证服务",
|
||
"internal/service/user.go": "用户服务",
|
||
"internal/service/role.go": "角色服务",
|
||
"internal/service/permission.go": "权限服务",
|
||
"internal/service/device.go": "设备服务",
|
||
|
||
# Handler层
|
||
"internal/api/handler/auth.go": "认证处理器",
|
||
"internal/api/handler/user.go": "用户处理器",
|
||
"internal/api/handler/role.go": "角色处理器",
|
||
"internal/api/handler/permission.go": "权限处理器",
|
||
"internal/api/handler/device.go": "设备处理器",
|
||
|
||
# Middleware层
|
||
"internal/api/middleware/auth.go": "认证中间件",
|
||
"internal/api/middleware/ratelimit.go": "限流中间件",
|
||
"internal/api/middleware/cors.go": "CORS中间件",
|
||
"internal/api/middleware/error.go": "错误处理中间件",
|
||
"internal/api/middleware/logger.go": "日志中间件",
|
||
|
||
# 路由
|
||
"internal/api/router/router.go": "路由配置",
|
||
|
||
# 缓存
|
||
"internal/cache/cache_manager.go": "缓存管理器",
|
||
"internal/cache/l1.go": "L1本地缓存",
|
||
"internal/cache/l2.go": "L2 Redis缓存",
|
||
|
||
# 监控
|
||
"internal/monitoring/metrics.go": "Prometheus指标",
|
||
"internal/monitoring/health.go": "健康检查",
|
||
"internal/monitoring/middleware.go": "监控中间件",
|
||
|
||
# 认证
|
||
"internal/auth/jwt.go": "JWT管理",
|
||
"internal/auth/oauth.go": "OAuth",
|
||
"internal/auth/password.go": "密码加密",
|
||
|
||
# 安全
|
||
"internal/security/ratelimit.go": "限流",
|
||
"internal/security/validator.go": "参数验证",
|
||
"internal/security/encryption.go": "加密工具",
|
||
|
||
# 数据库
|
||
"internal/database/db.go": "数据库初始化",
|
||
|
||
# 配置
|
||
"internal/config/config.go": "配置管理",
|
||
|
||
# 响应
|
||
"internal/response/response.go": "响应封装",
|
||
|
||
# 错误
|
||
"pkg/errors/errors.go": "错误定义",
|
||
"pkg/response/response.go": "响应定义",
|
||
}
|
||
|
||
# 预期的API接口
|
||
EXPECTED_API_ENDPOINTS = {
|
||
"认证接口": [
|
||
"POST /api/v1/auth/register",
|
||
"POST /api/v1/auth/login",
|
||
"POST /api/v1/auth/refresh",
|
||
"POST /api/v1/auth/logout",
|
||
"POST /api/v1/auth/login/code",
|
||
],
|
||
"用户接口": [
|
||
"GET /api/v1/users",
|
||
"GET /api/v1/users/me",
|
||
"GET /api/v1/users/:id",
|
||
"POST /api/v1/users",
|
||
"PUT /api/v1/users/:id",
|
||
"DELETE /api/v1/users/:id",
|
||
"PUT /api/v1/users/:id/password",
|
||
"PUT /api/v1/users/:id/status",
|
||
"GET /api/v1/users/:id/roles",
|
||
"PUT /api/v1/users/:id/roles",
|
||
],
|
||
"角色接口": [
|
||
"GET /api/v1/roles",
|
||
"GET /api/v1/roles/:id",
|
||
"POST /api/v1/roles",
|
||
"PUT /api/v1/roles/:id",
|
||
"DELETE /api/v1/roles/:id",
|
||
"PUT /api/v1/roles/:id/status",
|
||
"GET /api/v1/roles/:id/permissions",
|
||
"PUT /api/v1/roles/:id/permissions",
|
||
],
|
||
"权限接口": [
|
||
"GET /api/v1/permissions",
|
||
"GET /api/v1/permissions/tree",
|
||
"GET /api/v1/permissions/:id",
|
||
"POST /api/v1/permissions",
|
||
"PUT /api/v1/permissions/:id",
|
||
"DELETE /api/v1/permissions/:id",
|
||
"PUT /api/v1/permissions/:id/status",
|
||
],
|
||
"设备接口": [
|
||
"GET /api/v1/devices",
|
||
"GET /api/v1/devices/:id",
|
||
"POST /api/v1/devices",
|
||
"PUT /api/v1/devices/:id",
|
||
"DELETE /api/v1/devices/:id",
|
||
"PUT /api/v1/devices/:id/status",
|
||
"GET /api/v1/devices/users/:id",
|
||
],
|
||
}
|
||
|
||
def print_success(msg: str):
|
||
print(f"{Colors.OKGREEN}✓{Colors.ENDC} {msg}")
|
||
|
||
def print_error(msg: str):
|
||
print(f"{Colors.FAIL}✗{Colors.ENDC} {msg}")
|
||
|
||
def print_warning(msg: str):
|
||
print(f"{Colors.WARNING}⚠{Colors.ENDC} {msg}")
|
||
|
||
def print_info(msg: str):
|
||
print(f"{Colors.OKBLUE}ℹ{Colors.ENDC} {msg}")
|
||
|
||
def verify_file_structure() -> Tuple[int, int, List[str]]:
|
||
"""验证文件结构"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}1. 文件结构验证{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
total = len(EXPECTED_STRUCTURE)
|
||
exists = 0
|
||
missing_files = []
|
||
|
||
for file_path, description in EXPECTED_STRUCTURE.items():
|
||
full_path = PROJECT_ROOT / file_path
|
||
if full_path.exists():
|
||
exists += 1
|
||
size = full_path.stat().st_size
|
||
print_success(f"{file_path:<50} ({size} bytes) - {description}")
|
||
else:
|
||
missing_files.append(file_path)
|
||
print_error(f"{file_path:<50} - {description}")
|
||
|
||
print(f"\n{Colors.OKCYAN}文件结构完成度: {exists}/{total} ({exists/total*100:.1f}%){Colors.ENDC}")
|
||
|
||
return total, exists, missing_files
|
||
|
||
def verify_service_methods() -> Dict[str, List[str]]:
|
||
"""验证Service层方法"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}2. Service层方法验证{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
# Service文件及其预期方法
|
||
service_methods = {
|
||
"auth.go": [
|
||
"Register",
|
||
"Login",
|
||
"LoginByCode",
|
||
"SocialLogin",
|
||
"RefreshToken",
|
||
"Logout",
|
||
"GetUserInfo",
|
||
"SendVerificationCode",
|
||
],
|
||
"user.go": [
|
||
"GetUser",
|
||
"GetUserByID",
|
||
"ListUsers",
|
||
"CreateUser",
|
||
"UpdateUser",
|
||
"DeleteUser",
|
||
"UpdateUserStatus",
|
||
"UpdatePassword",
|
||
"GetUserRoles",
|
||
"AssignRoles",
|
||
],
|
||
"role.go": [
|
||
"GetRole",
|
||
"ListRoles",
|
||
"CreateRole",
|
||
"UpdateRole",
|
||
"DeleteRole",
|
||
"UpdateRoleStatus",
|
||
"GetRolePermissions",
|
||
"AssignPermissions",
|
||
],
|
||
"permission.go": [
|
||
"GetPermission",
|
||
"ListPermissions",
|
||
"GetPermissionTree",
|
||
"CreatePermission",
|
||
"UpdatePermission",
|
||
"DeletePermission",
|
||
"UpdatePermissionStatus",
|
||
"Search",
|
||
],
|
||
"device.go": [
|
||
"GetDevice",
|
||
"ListDevices",
|
||
"CreateDevice",
|
||
"UpdateDevice",
|
||
"DeleteDevice",
|
||
"UpdateDeviceStatus",
|
||
"GetUserDevices",
|
||
],
|
||
}
|
||
|
||
results = {}
|
||
|
||
for service_file, expected_methods in service_methods.items():
|
||
print(f"\n{Colors.OKCYAN}📁 internal/service/{service_file}{Colors.ENDC}")
|
||
|
||
file_path = PROJECT_ROOT / "internal/service" / service_file
|
||
if not file_path.exists():
|
||
print_error(f"文件不存在")
|
||
results[service_file] = {"exists": False, "methods": []}
|
||
continue
|
||
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
found_methods = []
|
||
missing_methods = []
|
||
|
||
for method in expected_methods:
|
||
if f"func.*{method}" in content:
|
||
found_methods.append(method)
|
||
print_success(f" ✓ {method}")
|
||
else:
|
||
missing_methods.append(method)
|
||
print_error(f" ✗ {method}")
|
||
|
||
print(f" {Colors.OKCYAN}完成度: {len(found_methods)}/{len(expected_methods)}{Colors.ENDC}")
|
||
|
||
results[service_file] = {
|
||
"exists": True,
|
||
"found": found_methods,
|
||
"missing": missing_methods,
|
||
"total": len(expected_methods),
|
||
}
|
||
|
||
return results
|
||
|
||
def verify_handler_methods() -> Dict[str, List[str]]:
|
||
"""验证Handler层方法"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}3. Handler层方法验证{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
handler_methods = {
|
||
"auth.go": [
|
||
"Register",
|
||
"Login",
|
||
"LoginByCode",
|
||
"SocialLogin",
|
||
"RefreshToken",
|
||
"Logout",
|
||
"SendVerificationCode",
|
||
],
|
||
"user.go": [
|
||
"GetUser",
|
||
"GetCurrentUser",
|
||
"ListUsers",
|
||
"CreateUser",
|
||
"UpdateUser",
|
||
"DeleteUser",
|
||
"UpdateUserStatus",
|
||
"UpdatePassword",
|
||
"GetUserRoles",
|
||
"AssignRoles",
|
||
],
|
||
"role.go": [
|
||
"CreateRole",
|
||
"ListRoles",
|
||
"GetRole",
|
||
"UpdateRole",
|
||
"DeleteRole",
|
||
"UpdateRoleStatus",
|
||
"GetRolePermissions",
|
||
"AssignPermissions",
|
||
],
|
||
"permission.go": [
|
||
"CreatePermission",
|
||
"ListPermissions",
|
||
"GetPermissionTree",
|
||
"GetPermission",
|
||
"UpdatePermission",
|
||
"DeletePermission",
|
||
"UpdatePermissionStatus",
|
||
],
|
||
"device.go": [
|
||
"GetMyDevices",
|
||
"CreateDevice",
|
||
"GetDevice",
|
||
"UpdateDevice",
|
||
"DeleteDevice",
|
||
"UpdateDeviceStatus",
|
||
"GetUserDevices",
|
||
],
|
||
}
|
||
|
||
results = {}
|
||
|
||
for handler_file, expected_methods in handler_methods.items():
|
||
print(f"\n{Colors.OKCYAN}📁 internal/api/handler/{handler_file}{Colors.ENDC}")
|
||
|
||
file_path = PROJECT_ROOT / "internal/api/handler" / handler_file
|
||
if not file_path.exists():
|
||
print_error(f"文件不存在")
|
||
results[handler_file] = {"exists": False, "methods": []}
|
||
continue
|
||
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
found_methods = []
|
||
missing_methods = []
|
||
|
||
for method in expected_methods:
|
||
if f"func.*{method}" in content:
|
||
found_methods.append(method)
|
||
print_success(f" ✓ {method}")
|
||
else:
|
||
missing_methods.append(method)
|
||
print_error(f" ✗ {method}")
|
||
|
||
print(f" {Colors.OKCYAN}完成度: {len(found_methods)}/{len(expected_methods)}{Colors.ENDC}")
|
||
|
||
results[handler_file] = {
|
||
"exists": True,
|
||
"found": found_methods,
|
||
"missing": missing_methods,
|
||
"total": len(expected_methods),
|
||
}
|
||
|
||
return results
|
||
|
||
def verify_middleware() -> None:
|
||
"""验证中间件"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}4. 中间件验证{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
middlewares = [
|
||
("auth.go", "认证中间件"),
|
||
("ratelimit.go", "限流中间件"),
|
||
("cors.go", "CORS中间件"),
|
||
("logger.go", "日志中间件"),
|
||
("error.go", "错误处理中间件"),
|
||
]
|
||
|
||
middleware_dir = PROJECT_ROOT / "internal/api/middleware"
|
||
|
||
for middleware_file, description in middlewares:
|
||
file_path = middleware_dir / middleware_file
|
||
if file_path.exists():
|
||
print_success(f"{middleware_file:<20} - {description}")
|
||
else:
|
||
print_error(f"{middleware_file:<20} - {description}")
|
||
|
||
def verify_cache() -> None:
|
||
"""验证缓存"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}5. 缓存模块验证{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
cache_files = [
|
||
("cache_manager.go", "缓存管理器 - L1+L2多级缓存"),
|
||
("l1.go", "L1本地缓存实现"),
|
||
("l2.go", "L2 Redis缓存实现"),
|
||
]
|
||
|
||
cache_dir = PROJECT_ROOT / "internal/cache"
|
||
|
||
for cache_file, description in cache_files:
|
||
file_path = cache_dir / cache_file
|
||
if file_path.exists():
|
||
print_success(f"{cache_file:<20} - {description}")
|
||
else:
|
||
print_error(f"{cache_file:<20} - {description}")
|
||
|
||
def verify_monitoring() -> None:
|
||
"""验证监控"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}6. 监控模块验证{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
monitoring_files = [
|
||
("metrics.go", "Prometheus指标采集"),
|
||
("health.go", "健康检查"),
|
||
("middleware.go", "监控中间件"),
|
||
]
|
||
|
||
monitoring_dir = PROJECT_ROOT / "internal/monitoring"
|
||
|
||
for monitoring_file, description in monitoring_files:
|
||
file_path = monitoring_dir / monitoring_file
|
||
if file_path.exists():
|
||
print_success(f"{monitoring_file:<20} - {description}")
|
||
else:
|
||
print_error(f"{monitoring_file:<20} - {description}")
|
||
|
||
def verify_database() -> None:
|
||
"""验证数据库"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}7. 数据库验证{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
# 检查迁移文件
|
||
migration_files = [
|
||
("migrations/sqlite/V1__init.sql", "SQLite数据库迁移文件"),
|
||
]
|
||
|
||
for migration_file, description in migration_files:
|
||
file_path = PROJECT_ROOT / migration_file
|
||
if file_path.exists():
|
||
print_success(f"{migration_file:<50} - {description}")
|
||
|
||
# 检查表定义
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
expected_tables = ["users", "roles", "permissions", "user_roles", "role_permissions", "devices", "login_logs", "operation_logs"]
|
||
print(f"\n {Colors.OKCYAN}数据表检查:{Colors.ENDC}")
|
||
for table in expected_tables:
|
||
if table in content:
|
||
print_success(f" ✓ {table}")
|
||
else:
|
||
print_error(f" ✗ {table}")
|
||
else:
|
||
print_error(f"{migration_file:<50} - {description}")
|
||
|
||
def verify_config() -> None:
|
||
"""验证配置"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}8. 配置文件验证{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
config_files = [
|
||
("configs/config.yaml", "应用配置文件"),
|
||
("deployment/docker-compose.yml", "Docker Compose配置"),
|
||
("deployment/alertmanager/alertmanager.yml", "AlertManager配置"),
|
||
("deployment/alertmanager/alerts.yml", "告警规则"),
|
||
("deployment/grafana/dashboards/user-management.json", "Grafana仪表板"),
|
||
]
|
||
|
||
for config_file, description in config_files:
|
||
file_path = PROJECT_ROOT / config_file
|
||
if file_path.exists():
|
||
print_success(f"{config_file:<50} - {description}")
|
||
else:
|
||
print_error(f"{config_file:<50} - {description}")
|
||
|
||
def count_lines_of_code() -> Dict[str, int]:
|
||
"""统计代码行数"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}9. 代码统计{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
stats = {
|
||
"total": 0,
|
||
"go": 0,
|
||
"sql": 0,
|
||
"yaml": 0,
|
||
"json": 0,
|
||
"md": 0,
|
||
}
|
||
|
||
for file_path in PROJECT_ROOT.rglob("*"):
|
||
if file_path.is_file():
|
||
# 跳过特定目录
|
||
if any(part in file_path.parts for part in [".git", "node_modules", "vendor", "__pycache__"]):
|
||
continue
|
||
|
||
ext = file_path.suffix.lower()
|
||
try:
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
lines = len(f.readlines())
|
||
|
||
stats["total"] += lines
|
||
|
||
if ext == ".go":
|
||
stats["go"] += lines
|
||
elif ext == ".sql":
|
||
stats["sql"] += lines
|
||
elif ext in [".yaml", ".yml"]:
|
||
stats["yaml"] += lines
|
||
elif ext == ".json":
|
||
stats["json"] += lines
|
||
elif ext == ".md":
|
||
stats["md"] += lines
|
||
except:
|
||
pass
|
||
|
||
print(f"{Colors.OKCYAN}总代码行数: {stats['total']:,}{Colors.ENDC}")
|
||
print(f" Go: {stats['go']:,} 行")
|
||
print(f" SQL: {stats['sql']:,} 行")
|
||
print(f" YAML: {stats['yaml']:,} 行")
|
||
print(f" JSON: {stats['json']:,} 行")
|
||
print(f" Markdown:{stats['md']:,} 行")
|
||
|
||
return stats
|
||
|
||
def generate_report() -> Dict:
|
||
"""生成验证报告"""
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}10. 生成验证报告{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
# 运行所有验证
|
||
total_files, exists_files, missing_files = verify_file_structure()
|
||
service_results = verify_service_methods()
|
||
handler_results = verify_handler_methods()
|
||
verify_middleware()
|
||
verify_cache()
|
||
verify_monitoring()
|
||
verify_database()
|
||
verify_config()
|
||
code_stats = count_lines_of_code()
|
||
|
||
# 计算完成度
|
||
file_completion = exists_files / total_files * 100
|
||
|
||
service_total = sum(r["total"] for r in service_results.values() if r.get("exists"))
|
||
service_found = sum(len(r.get("found", [])) for r in service_results.values() if r.get("exists"))
|
||
service_completion = service_found / service_total * 100 if service_total > 0 else 0
|
||
|
||
handler_total = sum(r["total"] for r in handler_results.values() if r.get("exists"))
|
||
handler_found = sum(len(r.get("found", [])) for r in handler_results.values() if r.get("exists"))
|
||
handler_completion = handler_found / handler_total * 100 if handler_total > 0 else 0
|
||
|
||
overall_completion = (file_completion + service_completion + handler_completion) / 3
|
||
|
||
# 打印总结
|
||
print(f"\n{Colors.HEADER}{'='*60}{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}📊 验证总结{Colors.ENDC}")
|
||
print(f"{Colors.HEADER}{'='*60}{Colors.ENDC}\n")
|
||
|
||
print(f"{Colors.OKCYAN}文件结构:{Colors.ENDC} {file_completion:.1f}% ({exists_files}/{total_files})")
|
||
print(f"{Colors.OKCYAN}Service层:{Colors.ENDC} {service_completion:.1f}% ({service_found}/{service_total})")
|
||
print(f"{Colors.OKCYAN}Handler层:{Colors.ENDC} {handler_completion:.1f}% ({handler_found}/{handler_total})")
|
||
print(f"{Colors.OKCYAN}代码总量:{Colors.ENDC} {code_stats['total']:,} 行")
|
||
print(f"\n{Colors.BOLD}{Colors.OKGREEN}总体完成度: {overall_completion:.1f}%{Colors.ENDC}")
|
||
|
||
if overall_completion >= 95:
|
||
print(f"{Colors.OKGREEN}✓ 项目完整度优秀,可以进行验收!{Colors.ENDC}")
|
||
elif overall_completion >= 80:
|
||
print(f"{Colors.WARNING}⚠ 项目基本完成,但还有部分功能需要补充{Colors.ENDC}")
|
||
else:
|
||
print(f"{Colors.FAIL}✗ 项目完成度较低,需要继续完善{Colors.ENDC}")
|
||
|
||
return {
|
||
"file_completion": file_completion,
|
||
"service_completion": service_completion,
|
||
"handler_completion": handler_completion,
|
||
"overall_completion": overall_completion,
|
||
"total_files": total_files,
|
||
"exists_files": exists_files,
|
||
"missing_files": missing_files,
|
||
"service_results": service_results,
|
||
"handler_results": handler_results,
|
||
"code_stats": code_stats,
|
||
}
|
||
|
||
if __name__ == "__main__":
|
||
print(f"{Colors.BOLD}{Colors.HEADER}")
|
||
print("╔════════════════════════════════════════════════════════╗")
|
||
print("║ 用户管理系统 - 代码结构验证工具 ║")
|
||
print("║ User Management System ║")
|
||
print("╚════════════════════════════════════════════════════════╝")
|
||
print(f"{Colors.ENDC}")
|
||
|
||
try:
|
||
report = generate_report()
|
||
|
||
# 保存报告到JSON
|
||
report_file = PROJECT_ROOT / "validation_report.json"
|
||
with open(report_file, 'w', encoding='utf-8') as f:
|
||
json.dump(report, f, indent=2, ensure_ascii=False)
|
||
|
||
print(f"\n{Colors.OKCYAN}✓ 验证报告已保存到: {report_file}{Colors.ENDC}")
|
||
|
||
# 退出码
|
||
if report["overall_completion"] >= 95:
|
||
sys.exit(0)
|
||
else:
|
||
sys.exit(1)
|
||
|
||
except Exception as e:
|
||
print(f"\n{Colors.FAIL}✗ 验证过程出错: {e}{Colors.ENDC}")
|
||
sys.exit(1)
|