| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- """
- 完整导入 daping 项目的所有模板
- 支持:
- 1. 提取 X11、Hplus、F2 Multi 的完整模板(包含关怀、健康、天气等)
- 2. 为 Ultra、Seeker、X11Ultra 创建复用关系(复用 X11 模板)
- """
- import json
- import re
- from pathlib import Path
- from datetime import datetime
- DAPING_PRE_DATA = Path(__file__).parent.parent.parent / "daping_rec_online_api" / "app" / "pre_data"
- def extract_templates_from_py(py_file: Path) -> list:
- """从 Python 文件中提取所有模板"""
- content = py_file.read_text(encoding='utf-8')
- templates = []
-
- # 匹配 value_xxx = """...""" 模式
- pattern = r'value_(\w+)\s*=\s*"""(.*?)"""'
- matches = re.findall(pattern, content, re.DOTALL)
-
- for template_type, template_body in matches:
- # 跳过不需要的模板
- if template_type in ['default', 'basic', 'w_basic', 'w_default', 'd_default']:
- continue
-
- # 提取 second_key
- key_pattern = rf'value_{template_type}_second_key\s*=\s*"([^"]+)"'
- key_match = re.search(key_pattern, content)
- redis_key = key_match.group(1) if key_match else ""
-
- # 清理模板类型名称
- clean_type = template_type
- if template_type.startswith('w_'):
- clean_type = template_type[2:]
- elif template_type.startswith('d_'):
- clean_type = template_type[2:]
-
- templates.append({
- "template_type": clean_type,
- "template_body": template_body.strip(),
- "redis_key": redis_key
- })
-
- return templates
- def generate_all_templates() -> list:
- """生成所有模板记录(包括复用关系)"""
- records = []
- template_id_counter = 1
-
- # 模板类型标准化映射
- TYPE_NORMALIZE = {
- "popular": "time_popular",
- "made": "time_custom",
- "custom": "time_custom",
- "season_in": "time_season",
- "season_storage": "time_season",
- "care": "time_care",
- "env": "time_environmental",
- "environmental": "time_environmental",
- "health": "time_health",
- "health2": "time_health_2",
- "weather": "time_weather",
- }
-
- # 模板类型描述
- TYPE_DESCRIPTIONS = {
- "common": "通用",
- "time_popular": "人气",
- "time_custom": "定制",
- "time_season": "季节",
- "time_care": "关怀",
- "time_environmental": "环保",
- "time_health": "健康",
- "time_health_2": "健康2-杀菌",
- "time_weather": "天气",
- }
-
- # 机型配置(与 daping 项目一致)
- MODEL_CONFIGS = [
- # X11 洗衣机
- {
- "model_name": "x11",
- "display_name": "X11",
- "model_id": "x11",
- "device_type": "wash",
- "zone_id": "2",
- "zone_name": "洗衣机",
- "file": "write_jinja_x11_down.py",
- },
- # X11 干衣机
- {
- "model_name": "x11",
- "display_name": "X11",
- "model_id": "x11",
- "device_type": "dry",
- "zone_id": "0",
- "zone_name": "干衣机",
- "file": "write_jinja_x11_up.py",
- },
- # Hplus 洗衣机
- {
- "model_name": "hplus",
- "display_name": "Hplus",
- "model_id": "hplus",
- "device_type": "wash",
- "zone_id": "3",
- "zone_name": "洗衣机",
- "file": "write_jinja_h_down.py",
- },
- # Hplus 干衣机
- {
- "model_name": "hplus",
- "display_name": "Hplus",
- "model_id": "hplus",
- "device_type": "dry",
- "zone_id": "0",
- "zone_name": "干衣机",
- "file": "write_jinja_h_up.py",
- },
- # F2 Multi 洗衣机
- {
- "model_name": "f2_multi",
- "display_name": "F2 Multi",
- "model_id": "f2_multi",
- "device_type": "wash",
- "zone_id": "1",
- "zone_name": "洗衣机",
- "file": "write_jinja_multi_down.py",
- },
- ]
-
- # 复用关系配置
- REUSE_CONFIGS = [
- # Ultra 洗衣机(复用 X11 洗涤)
- {
- "model_id": "ultra",
- "display_name": "Ultra",
- "device_type": "wash",
- "zone_id": "1",
- "zone_name": "洗衣机",
- "reuse_from_model": "x11",
- "reuse_from_device": "wash",
- },
- # Seeker 洗衣机(复用 X11 洗涤)
- {
- "model_id": "seeker",
- "display_name": "Seeker",
- "device_type": "wash",
- "zone_id": "2",
- "zone_name": "洗衣机",
- "reuse_from_model": "x11",
- "reuse_from_device": "wash",
- },
- # X11 Ultra 干衣机(复用 X11 干衣)
- {
- "model_id": "x11_ultra",
- "display_name": "X11 Ultra",
- "device_type": "dry",
- "zone_id": "24",
- "zone_name": "干衣机",
- "reuse_from_model": "x11",
- "reuse_from_device": "dry",
- },
- ]
-
- # 1. 处理独立模板(X11、Hplus、F2 Multi)
- print("\n" + "="*60)
- print("提取独立模板...")
- print("="*60)
-
- source_template_map = {} # 用于复用关系查找
-
- for config in MODEL_CONFIGS:
- file_path = DAPING_PRE_DATA / config["model_name"] / config["file"]
-
- if not file_path.exists():
- print(f"⚠ 文件不存在: {file_path}")
- continue
-
- print(f"\n处理: {config['display_name']} {config['zone_name']}")
- templates = extract_templates_from_py(file_path)
-
- if not templates:
- print(f" ⚠ 未找到模板")
- continue
-
- print(f" ✓ 找到 {len(templates)} 个模板")
-
- for tpl in templates:
- template_type = tpl["template_type"]
- # 标准化模板类型
- normalized_type = TYPE_NORMALIZE.get(template_type, template_type)
- if normalized_type.startswith("time_"):
- final_type = normalized_type
- else:
- final_type = f"time_{normalized_type}" if normalized_type != "common" else "common"
-
- description = TYPE_DESCRIPTIONS.get(final_type, final_type)
-
- # 生成模板ID
- tpl_id = f"{config['model_id']}_{config['device_type']}_{final_type}"
- template_id_counter += 1
-
- # 记录源模板位置(用于复用)
- source_key = f"{config['model_id']}_{config['device_type']}_{final_type}"
- source_template_map[source_key] = tpl_id
-
- record = {
- "id": tpl_id,
- "name": f"{config['display_name']}{config['zone_name']}-{description}",
- "category": f"{'洗涤' if config['device_type'] == 'wash' else '干衣'}",
- "device_type": config["device_type"],
- "machine_model": config["model_id"],
- "template_type": final_type,
- "reusable_from": "",
- "reuse_targets": [],
- "description": f"{config['display_name']} {config['zone_name']} {description}模板",
- "output_description": "语音播报脚本",
- "call_method": "",
- "input_variables": [
- {
- "name": "program_id",
- "label": "程序ID",
- "description": "洗涤/干衣程序ID",
- "data_type": "string",
- "required": True,
- "default": "15"
- }
- ],
- "template_body": tpl["template_body"],
- "created_at": datetime.utcnow().isoformat() + "Z",
- "updated_at": datetime.utcnow().isoformat() + "Z"
- }
-
- records.append(record)
- print(f" ✓ {record['name']} ({len(tpl['template_body'])} 字符)")
-
- # 2. 处理复用模板(Ultra、Seeker、X11Ultra)
- print("\n" + "="*60)
- print("创建复用模板...")
- print("="*60)
-
- for config in REUSE_CONFIGS:
- source_key = f"{config['reuse_from_model']}_{config['reuse_from_device']}"
-
- # 找出所有源模板
- source_tpl_ids = [
- tpl_id for key, tpl_id in source_template_map.items()
- if key.startswith(source_key)
- ]
-
- if not source_tpl_ids:
- print(f"⚠ 未找到 {config['display_name']} {config['zone_name']} 的源模板")
- continue
-
- print(f"\n处理: {config['display_name']} {config['zone_name']} (复用)")
-
- for source_tpl_id in source_tpl_ids:
- # 从源模板ID中提取模板类型
- parts = source_tpl_id.split("_")
- template_type = "_".join(parts[2:]) # 去掉 model_id 和 device_type
-
- description = TYPE_DESCRIPTIONS.get(template_type, template_type)
-
- # 生成复用模板ID
- tpl_id = f"{config['model_id']}_{config['device_type']}_{template_type}"
- template_id_counter += 1
-
- # 更新源模板的 reuse_targets
- for record in records:
- if record["id"] == source_tpl_id:
- if tpl_id not in record["reuse_targets"]:
- record["reuse_targets"].append(tpl_id)
-
- record = {
- "id": tpl_id,
- "name": f"{config['display_name']}{config['zone_name']}-{description}",
- "category": f"{'洗涤' if config['device_type'] == 'wash' else '干衣'}",
- "device_type": config["device_type"],
- "machine_model": config["model_id"],
- "template_type": template_type,
- "reusable_from": source_tpl_id,
- "reuse_targets": [],
- "description": f"{config['display_name']} {config['zone_name']} {description}模板(复用)",
- "output_description": "语音播报脚本",
- "call_method": "",
- "input_variables": [
- {
- "name": "program_id",
- "label": "程序ID",
- "description": "洗涤/干衣程序ID",
- "data_type": "string",
- "required": True,
- "default": "15"
- }
- ],
- "template_body": "", # 复用模板不需要存储正文
- "created_at": datetime.utcnow().isoformat() + "Z",
- "updated_at": datetime.utcnow().isoformat() + "Z"
- }
-
- records.append(record)
- print(f" ✓ {record['name']} (复用自 {source_tpl_id})")
-
- return records
- def main():
- output_file = Path(__file__).parent.parent / "backend" / "data" / "templates.json"
-
- print("="*60)
- print("开始从 daping 项目提取所有模板...")
- print("="*60)
-
- # 生成所有模板记录
- records = generate_all_templates()
-
- # 保存到 JSON
- output_file.parent.mkdir(parents=True, exist_ok=True)
- output_file.write_text(
- json.dumps(records, ensure_ascii=False, indent=2),
- encoding='utf-8'
- )
-
- # 统计信息
- type_stats = {}
- model_stats = {}
- reuse_count = sum(1 for r in records if r["reusable_from"])
-
- for r in records:
- type_stats[r["template_type"]] = type_stats.get(r["template_type"], 0) + 1
- model_stats[r["machine_model"]] = model_stats.get(r["machine_model"], 0) + 1
-
- print(f"\n" + "="*60)
- print(f"✓ 成功导入 {len(records)} 个模板")
- print(f" - 独立模板: {len(records) - reuse_count} 个")
- print(f" - 复用模板: {reuse_count} 个")
- print(f"\n按机型统计:")
- for model, count in sorted(model_stats.items()):
- print(f" - {model}: {count} 个")
- print(f"\n按模板类型统计:")
- for tpl_type, count in sorted(type_stats.items()):
- print(f" - {tpl_type}: {count} 个")
- print(f"\n输出文件: {output_file}")
- print("="*60)
- if __name__ == "__main__":
- main()
|