Files
whale-town-front/Utils/StringUtils.gd
王浩 0b533189ec refactor:重构项目架构为分层结构
## 🏗️ 主要变更

### 目录结构重构
- 将 core/ 迁移到 _Core/(框架层)
- 将 scenes/ 重构为 Scenes/(玩法层)和 UI/(界面层)
- 将 data/ 迁移到 Config/(配置层)
- 添加 Assets/ 资源层和 Utils/ 工具层
- 将 scripts/ 迁移到 tools/(开发工具)

### 架构分层
- **_Core/**: 框架层 - 全局单例和管理器
- **Scenes/**: 玩法层 - 游戏场景和实体
- **UI/**: 界面层 - HUD、窗口、对话系统
- **Assets/**: 资源层 - 精灵图、音频、字体
- **Config/**: 配置层 - 游戏配置和本地化
- **Utils/**: 工具层 - 通用辅助脚本

### 文件更新
- 更新 project.godot 中的所有路径引用
- 更新自动加载脚本路径
- 更新测试文件的引用路径
- 添加 REFACTORING.md 详细说明
- 添加 MIGRATION_COMPLETE.md 迁移完成标记
- 更新 README.md 反映新架构

### 设计原则
-  清晰的分层(框架/玩法/界面)
-  场景内聚(脚本紧邻场景文件)
-  组件化设计(可复用组件)
-  职责单一(每个目录职责明确)

## 📋 详细信息
查看 REFACTORING.md 了解完整的重构说明和迁移映射表

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-31 11:36:01 +08:00

200 lines
5.4 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class_name StringUtils
# 字符串工具类 - 提供常用的字符串处理功能
# 验证邮箱格式
static func is_valid_email(email: String) -> bool:
var regex = RegEx.new()
regex.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")
return regex.search(email) != null
# 验证用户名格式(字母、数字、下划线)
static func is_valid_username(username: String) -> bool:
if username.is_empty() or username.length() > 50:
return false
var regex = RegEx.new()
regex.compile("^[a-zA-Z0-9_]+$")
return regex.search(username) != null
# 验证密码强度
static func validate_password_strength(password: String) -> Dictionary:
var result = {"valid": false, "message": "", "strength": 0}
if password.length() < 8:
result.message = "密码长度至少8位"
return result
if password.length() > 128:
result.message = "密码长度不能超过128位"
return result
var has_letter = false
var has_digit = false
var has_special = false
for i in range(password.length()):
var char = password[i]
if char >= 'a' and char <= 'z' or char >= 'A' and char <= 'Z':
has_letter = true
elif char >= '0' and char <= '9':
has_digit = true
elif char in "!@#$%^&*()_+-=[]{}|;:,.<>?":
has_special = true
var strength = 0
if has_letter:
strength += 1
if has_digit:
strength += 1
if has_special:
strength += 1
if password.length() >= 12:
strength += 1
result.strength = strength
if not (has_letter and has_digit):
result.message = "密码必须包含字母和数字"
return result
result.valid = true
result.message = "密码强度: " + ["", "", "", "很强"][min(strength - 1, 3)]
return result
# 截断字符串
static func truncate(text: String, max_length: int, suffix: String = "...") -> String:
if text.length() <= max_length:
return text
return text.substr(0, max_length - suffix.length()) + suffix
# 首字母大写
static func capitalize_first(text: String) -> String:
if text.is_empty():
return text
return text[0].to_upper() + text.substr(1)
# 转换为标题格式(每个单词首字母大写)
static func to_title_case(text: String) -> String:
var words = text.split(" ")
var result = []
for word in words:
if not word.is_empty():
result.append(capitalize_first(word.to_lower()))
return " ".join(result)
# 移除HTML标签
static func strip_html_tags(html: String) -> String:
var regex = RegEx.new()
regex.compile("<[^>]*>")
return regex.sub(html, "", true)
# 格式化文件大小
static func format_file_size(bytes: int) -> String:
var units = ["B", "KB", "MB", "GB", "TB"]
var size = float(bytes)
var unit_index = 0
while size >= 1024.0 and unit_index < units.size() - 1:
size /= 1024.0
unit_index += 1
if unit_index == 0:
return str(int(size)) + " " + units[unit_index]
else:
return "%.1f %s" % [size, units[unit_index]]
# 将UTC时间字符串转换为本地时间显示
static func format_utc_to_local_time(utc_time_str: String) -> String:
# 解析UTC时间字符串 (格式: 2025-12-25T11:23:52.175Z)
var regex = RegEx.new()
regex.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})")
var result = regex.search(utc_time_str)
if result == null:
return utc_time_str # 如果解析失败,返回原字符串
# 提取时间组件
var year = int(result.get_string(1))
var month = int(result.get_string(2))
var day = int(result.get_string(3))
var hour = int(result.get_string(4))
var minute = int(result.get_string(5))
var second = int(result.get_string(6))
# 创建UTC时间字典
var utc_dict = {
"year": year,
"month": month,
"day": day,
"hour": hour,
"minute": minute,
"second": second
}
# 转换为Unix时间戳UTC
var utc_timestamp = Time.get_unix_time_from_datetime_dict(utc_dict)
# 获取本地时间Godot会自动处理时区转换
var local_dict = Time.get_datetime_dict_from_unix_time(utc_timestamp)
# 格式化为易读的本地时间
return "%04d%02d%02d%02d:%02d:%02d" % [
local_dict.year,
local_dict.month,
local_dict.day,
local_dict.hour,
local_dict.minute,
local_dict.second
]
# 获取相对时间描述(多少分钟后)
static func get_relative_time_until(utc_time_str: String) -> String:
# 解析UTC时间字符串
var regex = RegEx.new()
regex.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})")
var result = regex.search(utc_time_str)
if result == null:
return "时间格式错误"
# 提取时间组件
var year = int(result.get_string(1))
var month = int(result.get_string(2))
var day = int(result.get_string(3))
var hour = int(result.get_string(4))
var minute = int(result.get_string(5))
var second = int(result.get_string(6))
# 创建UTC时间字典
var utc_dict = {
"year": year,
"month": month,
"day": day,
"hour": hour,
"minute": minute,
"second": second
}
# 转换为Unix时间戳
var target_timestamp = Time.get_unix_time_from_datetime_dict(utc_dict)
var current_timestamp = Time.get_unix_time_from_system()
# 计算时间差(秒)
var diff_seconds = target_timestamp - current_timestamp
if diff_seconds <= 0:
return "现在可以重试"
elif diff_seconds < 60:
return "%d秒后" % diff_seconds
elif diff_seconds < 3600:
var minutes = int(diff_seconds / 60)
return "%d分钟后" % minutes
else:
var hours = int(diff_seconds / 3600)
var minutes = int((diff_seconds % 3600) / 60)
if minutes > 0:
return "%d小时%d分钟后" % [hours, minutes]
else:
return "%d小时后" % hours