chore: Initial clean commit

- Removed YuMi/Library/ (138 MB, not tracked)
- Removed YuMi/Resources/ (23 MB, not tracked)
- Removed old version assets (566 files, not tracked)
- Excluded Pods/, xcuserdata/ and other build artifacts
- Clean repository optimized for company server deployment
This commit is contained in:
edwinQQQ
2025-10-09 16:19:14 +08:00
commit a35a711be6
5582 changed files with 408913 additions and 0 deletions

336
issues/scripts/2_rename_assets.py Executable file
View File

@@ -0,0 +1,336 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
图片资源批量处理脚本
用法: python3 2_rename_assets.py
"""
import os
import json
import hashlib
import shutil
from pathlib import Path
from typing import Dict, List, Set
import re
# 颜色输出
class Colors:
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BLUE = '\033[94m'
END = '\033[0m'
# 配置
PROJECT_ROOT = "/Users/edwinqqq/Local/Company Projects/peko-ios"
ASSETS_DIR = os.path.join(PROJECT_ROOT, "YuMi/Assets.xcassets")
SOURCE_DIR = os.path.join(PROJECT_ROOT, "YuMi")
BACKUP_DIR = os.path.join(PROJECT_ROOT, "issues/temp_rename/assets_backup")
MAPPING_FILE = os.path.join(PROJECT_ROOT, "issues/temp_rename/asset_name_mapping.json")
# 存储映射关系
asset_mapping: Dict[str, str] = {}
def print_header(text):
"""打印标题"""
print(f"\n{Colors.GREEN}{'='*50}{Colors.END}")
print(f"{Colors.GREEN}{text}{Colors.END}")
print(f"{Colors.GREEN}{'='*50}{Colors.END}\n")
def print_info(text):
"""打印信息"""
print(f"{Colors.BLUE} {text}{Colors.END}")
def print_warning(text):
"""打印警告"""
print(f"{Colors.YELLOW}⚠️ {text}{Colors.END}")
def print_error(text):
"""打印错误"""
print(f"{Colors.RED}{text}{Colors.END}")
def print_success(text):
"""打印成功"""
print(f"{Colors.GREEN}{text}{Colors.END}")
def generate_new_name(old_name: str, index: int) -> str:
"""
生成新的资源名称
策略:使用语义化的随机名称,而不是完全随机
"""
# 提取原名称中的关键信息
parts = old_name.lower().split('_')
# 常见的UI元素映射
element_map = {
'icon': ['symbol', 'mark', 'sign', 'emblem'],
'button': ['btn', 'action', 'control', 'press'],
'background': ['bg', 'backdrop', 'layer', 'base'],
'avatar': ['profile', 'face', 'user', 'photo'],
'banner': ['header', 'top', 'promo', 'ad'],
'gift': ['present', 'reward', 'prize', 'bonus'],
'room': ['space', 'zone', 'area', 'hall'],
'home': ['main', 'index', 'start', 'feed'],
'message': ['msg', 'chat', 'talk', 'dialog'],
'mine': ['profile', 'me', 'personal', 'user'],
'login': ['signin', 'auth', 'entry', 'access'],
'arrow': ['pointer', 'indicator', 'direction', 'nav'],
'close': ['dismiss', 'exit', 'cancel', 'remove'],
'back': ['return', 'previous', 'prev', 'retreat'],
'next': ['forward', 'proceed', 'continue', 'advance'],
'play': ['start', 'run', 'launch', 'begin'],
'pause': ['stop', 'halt', 'freeze', 'wait'],
'more': ['additional', 'extra', 'plus', 'expand'],
}
# 尝试替换关键词
new_parts = []
for part in parts:
replaced = False
for key, alternatives in element_map.items():
if key in part:
# 使用 index 作为种子选择一个替代词
alt_index = (index + hash(part)) % len(alternatives)
new_part = part.replace(key, alternatives[alt_index])
new_parts.append(new_part)
replaced = True
break
if not replaced:
# 保留数字和常见后缀
if part.isdigit() or part in ['selected', 'normal', 'disabled', 'active', 'inactive']:
new_parts.append(part)
else:
# 使用简单的字符替换
new_part = ''.join([chr((ord(c) - 97 + 13) % 26 + 97) if c.isalpha() else c for c in part])
new_parts.append(new_part)
new_name = '_'.join(new_parts)
# 如果生成的名称和原名称一样,添加一个后缀
if new_name == old_name:
new_name = f"asset_{hashlib.md5(old_name.encode()).hexdigest()[:8]}"
return new_name
def backup_assets():
"""备份原始资源"""
print_header("第1步备份原始资源")
if os.path.exists(BACKUP_DIR):
print_warning("备份目录已存在,将覆盖...")
shutil.rmtree(BACKUP_DIR)
print_info(f"正在备份 {ASSETS_DIR}{BACKUP_DIR} ...")
shutil.copytree(ASSETS_DIR, BACKUP_DIR)
print_success(f"备份完成!")
def scan_imagesets() -> List[str]:
"""扫描所有 .imageset 目录"""
print_header("第2步扫描图片资源")
imagesets = []
for root, dirs, files in os.walk(ASSETS_DIR):
for dir_name in dirs:
if dir_name.endswith('.imageset'):
full_path = os.path.join(root, dir_name)
imagesets.append(full_path)
print_success(f"找到 {len(imagesets)} 个图片资源")
return imagesets
def rename_imageset(imageset_path: str, index: int) -> tuple:
"""
重命名单个 imageset
返回 (old_name, new_name)
"""
dir_name = os.path.basename(imageset_path)
old_name = dir_name.replace('.imageset', '')
# 跳过 AppIcon
if 'AppIcon' in old_name:
print_info(f"跳过 AppIcon: {old_name}")
return (old_name, old_name)
# 生成新名称
new_name = generate_new_name(old_name, index)
new_dir_name = f"{new_name}.imageset"
new_path = os.path.join(os.path.dirname(imageset_path), new_dir_name)
# 重命名目录
try:
os.rename(imageset_path, new_path)
# 更新 Contents.json
contents_json = os.path.join(new_path, 'Contents.json')
if os.path.exists(contents_json):
with open(contents_json, 'r', encoding='utf-8') as f:
data = json.load(f)
# 更新图片文件名引用
for image in data.get('images', []):
if 'filename' in image:
old_filename = image['filename']
if old_name in old_filename:
new_filename = old_filename.replace(old_name, new_name)
# 重命名实际的图片文件
old_file_path = os.path.join(new_path, old_filename)
new_file_path = os.path.join(new_path, new_filename)
if os.path.exists(old_file_path):
os.rename(old_file_path, new_file_path)
image['filename'] = new_filename
# 写回 Contents.json
with open(contents_json, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
return (old_name, new_name)
except Exception as e:
print_error(f"重命名失败 {old_name}: {str(e)}")
return (old_name, old_name)
def rename_all_imagesets():
"""批量重命名所有图片资源"""
print_header("第3步批量重命名图片资源")
imagesets = scan_imagesets()
total = len(imagesets)
success_count = 0
for index, imageset_path in enumerate(imagesets, 1):
old_name, new_name = rename_imageset(imageset_path, index)
if old_name != new_name:
asset_mapping[old_name] = new_name
success_count += 1
# 显示进度
if index % 100 == 0:
print_info(f"进度: {index}/{total} ({index*100//total}%)")
print_success(f"完成!成功重命名 {success_count} 个资源")
# 保存映射关系
os.makedirs(os.path.dirname(MAPPING_FILE), exist_ok=True)
with open(MAPPING_FILE, 'w', encoding='utf-8') as f:
json.dump(asset_mapping, f, indent=2, ensure_ascii=False)
print_success(f"映射关系已保存到: {MAPPING_FILE}")
def update_code_references():
"""更新代码中的图片资源引用"""
print_header("第4步更新代码引用")
print_warning("这一步需要手动处理,因为图片引用方式多样")
print_info("常见的引用方式:")
print(" 1. [UIImage imageNamed:@\"old_name\"]")
print(" 2. UIImage(named: \"old_name\")")
print(" 3. @\"old_name\"")
print("")
# 生成替换脚本
replace_script = os.path.join(PROJECT_ROOT, "issues/temp_rename/replace_image_refs.sh")
with open(replace_script, 'w') as f:
f.write("#!/bin/bash\n")
f.write("# 自动生成的图片引用替换脚本\n\n")
f.write(f"SOURCE_DIR=\"{SOURCE_DIR}\"\n\n")
for old_name, new_name in asset_mapping.items():
# 转义特殊字符
old_escaped = old_name.replace('"', '\\"')
new_escaped = new_name.replace('"', '\\"')
f.write(f"# {old_name}{new_name}\n")
f.write(f"find \"$SOURCE_DIR\" -type f \\( -name \"*.m\" -o -name \"*.h\" -o -name \"*.swift\" \\) -exec sed -i '' 's/@\"{old_escaped}\"/@\"{new_escaped}\"/g' {{}} +\n")
f.write(f"find \"$SOURCE_DIR\" -type f \\( -name \"*.m\" -o -name \"*.h\" -o -name \"*.swift\" \\) -exec sed -i '' 's/\"{old_escaped}\"/\"{new_escaped}\"/g' {{}} +\n\n")
os.chmod(replace_script, 0o755)
print_success(f"替换脚本已生成: {replace_script}")
print_warning("请手动执行该脚本进行代码替换")
def generate_report():
"""生成替换报告"""
print_header("第5步生成报告")
report_file = os.path.join(PROJECT_ROOT, "issues/temp_rename/assets_rename_report.txt")
with open(report_file, 'w', encoding='utf-8') as f:
f.write("=" * 60 + "\n")
f.write("图片资源批量重命名报告\n")
f.write("=" * 60 + "\n\n")
f.write(f"执行时间: {os.popen('date').read()}\n")
f.write(f"总共处理: {len(asset_mapping)} 个资源\n\n")
f.write("=" * 60 + "\n")
f.write("重命名映射前50个:\n")
f.write("=" * 60 + "\n\n")
count = 0
for old_name, new_name in asset_mapping.items():
f.write(f"{old_name:40}{new_name}\n")
count += 1
if count >= 50:
f.write(f"\n... 还有 {len(asset_mapping) - 50} 个资源\n")
break
f.write("\n" + "=" * 60 + "\n")
f.write("下一步操作:\n")
f.write("=" * 60 + "\n\n")
f.write("1. 执行生成的替换脚本更新代码引用\n")
f.write("2. 在 Xcode 中清理并重新构建项目\n")
f.write("3. 运行应用,检查所有图片是否正常显示\n")
f.write("4. 使用 UI 测试验证关键页面\n\n")
f.write("备份位置:\n")
f.write(f" {BACKUP_DIR}\n\n")
f.write("映射文件:\n")
f.write(f" {MAPPING_FILE}\n\n")
f.write("替换脚本:\n")
f.write(f" {os.path.join(PROJECT_ROOT, 'issues/temp_rename/replace_image_refs.sh')}\n\n")
print_success(f"报告已生成: {report_file}")
# 打印简要统计
print("")
print(f" 📊 总共重命名: {len(asset_mapping)} 个资源")
print(f" 📁 备份位置: {BACKUP_DIR}")
print(f" 📄 映射文件: {MAPPING_FILE}")
print("")
def main():
"""主函数"""
print_header("白牌项目 - 图片资源批量重命名工具")
# 确认操作
print_warning("此脚本将重命名所有图片资源!")
print_warning("请确保:")
print(" 1. 已经运行了类名替换脚本")
print(" 2. 已经提交了所有更改")
print(" 3. 已经创建了新的 Git 分支")
print("")
confirm = input("确认继续?(y/N): ")
if confirm.lower() != 'y':
print("已取消操作")
return
try:
# 执行步骤
backup_assets()
rename_all_imagesets()
update_code_references()
generate_report()
print_header("✅ 图片资源批量重命名完成!")
print_warning("记得执行生成的替换脚本更新代码引用!")
except Exception as e:
print_error(f"执行过程中出错: {str(e)}")
print_warning("你可以从备份恢复:")
print(f" rm -rf {ASSETS_DIR}")
print(f" cp -r {BACKUP_DIR} {ASSETS_DIR}")
if __name__ == "__main__":
main()