portal/init_data.py
Hermes Agent ae06dda9da feat: portal webapp - CMS独立Web应用壳
- app/portal.py: 主入口,通过from cms.init import load_cms加载业务模块
- conf/config.json: 应用配置(ocai_cms数据库, 端口9090, cms模块wwwroot挂载到/cms)
- wwwroot/: 公开页面(index/news/cases/products)和公开API
- build.sh: 构建脚本(安装基础设施包+pip install cms模块+DDL/CRUD生成)
- deploy.sh: 一键部署脚本(构建→建表→初始数据→权限→启动)
- init_data.py: 从cms模块init/data.yaml加载初始数据
- init_any/superuser_permissions.py: RBAC权限初始化
2026-06-15 11:06:10 +08:00

180 lines
7.1 KiB
Python

"""
Portal 一键部署 — 初始化数据
从 cms 模块的 init/data.yaml 加载所有初始数据:
- appcodes (枚举编码)
- appcodes_kv (枚举值)
- cms_categories (默认分类)
- cms_site_config (默认站点配置)
- cms_sections (默认栏目配置)
- dd_approval_configs (默认审批配置)
用法: cd ~/repos/portal && py3/bin/python init_data.py
"""
import os, sys, json
app_dir = os.path.dirname(os.path.abspath(__file__))
root_dir = app_dir
sys.path.insert(0, root_dir)
# 读取YAML
try:
import yaml
except ImportError:
# 简单YAML解析(fallback)
yaml = None
CMS_DIR = os.path.expanduser("~/repos/cms")
DATA_FILE = os.path.join(CMS_DIR, "init", "data.yaml")
def load_yaml_simple(path):
"""简单YAML加载(仅支持本文件用到的结构)"""
if yaml:
with open(path, 'r', encoding='utf-8') as f:
return yaml.safe_load(f)
else:
# 用json做fallback - 要求data文件也有json版本
json_path = path.replace('.yaml', '.json')
if os.path.exists(json_path):
with open(json_path, 'r', encoding='utf-8') as f:
return json.load(f)
raise ImportError("需要PyYAML: pip install pyyaml")
def main():
print("=== Portal 一键部署 — 初始化数据 ===")
print(f"CMS模块: {CMS_DIR}")
print(f"数据文件: {DATA_FILE}")
print()
if not os.path.exists(DATA_FILE):
print(f"ERROR: 数据文件不存在: {DATA_FILE}")
sys.exit(1)
# 加载YAML
data = load_yaml_simple(DATA_FILE)
# 连接数据库
from sqlor.dbpools import DBPools
from appPublic.uniqueID import getID
from ahserver.serverenv import ServerEnv
from appPublic.jsonConfig import getConfig
from appPublic.log import MyLogger
# 初始化日志和配置
MyLogger(getConfig())
db = DBPools()
dbname = 'ocai_cms'
import asyncio
async def insert_data():
async with db.sqlorContext(dbname) as sor:
# 1. appcodes
appcodes = data.get('appcodes', [])
if appcodes:
print(f"\n--- appcodes ({len(appcodes)} 条) ---")
for item in appcodes:
item.setdefault('id', getID())
item.setdefault('org_id', '0')
try:
# 检查是否已存在
existing = await sor.R('appcodes', {'id': item['id']})
if not existing:
await sor.C('appcodes', item)
print(f"{item['id']} - {item.get('name', '')}")
else:
print(f" · {item['id']} (已存在)")
except Exception as e:
print(f"{item.get('id', '?')}: {e}")
# 2. appcodes_kv
appcodes_kv = data.get('appcodes_kv', [])
if appcodes_kv:
print(f"\n--- appcodes_kv ({len(appcodes_kv)} 条) ---")
for item in appcodes_kv:
item.setdefault('id', getID())
item.setdefault('org_id', '0')
try:
existing = await sor.R('appcodes_kv', {'id': item['id']})
if not existing:
await sor.C('appcodes_kv', item)
print(f"{item['id']} ({item.get('parentid', '')}.{item.get('k', '')} = {item.get('v', '')})")
else:
print(f" · {item['id']} (已存在)")
except Exception as e:
print(f"{item.get('id', '?')}: {e}")
# 3. cms_categories
categories = data.get('cms_categories', [])
if categories:
print(f"\n--- cms_categories ({len(categories)} 条) ---")
for item in categories:
item.setdefault('id', getID())
try:
existing = await sor.R('cms_categories', {'id': item['id']})
if not existing:
await sor.C('cms_categories', item)
print(f"{item['id']} - {item.get('name', '')} [{item.get('content_type', '')}]")
else:
print(f" · {item['id']} (已存在)")
except Exception as e:
print(f"{item.get('id', '?')}: {e}")
# 4. cms_site_config
configs = data.get('cms_site_config', [])
if configs:
print(f"\n--- cms_site_config ({len(configs)} 条) ---")
for item in configs:
item.setdefault('id', getID())
try:
existing = await sor.R('cms_site_config', {'id': item['id']})
if not existing:
await sor.C('cms_site_config', item)
print(f"{item['id']} ({item.get('config_group', '')}.{item.get('config_key', '')})")
else:
print(f" · {item['id']} (已存在)")
except Exception as e:
print(f"{item.get('id', '?')}: {e}")
# 5. cms_sections
sections = data.get('cms_sections', [])
if sections:
print(f"\n--- cms_sections ({len(sections)} 条) ---")
for item in sections:
item.setdefault('id', getID())
try:
existing = await sor.R('cms_sections', {'id': item['id']})
if not existing:
await sor.C('cms_sections', item)
print(f"{item['id']} - {item.get('title', '')} [{item.get('section_type', '')}]")
else:
print(f" · {item['id']} (已存在)")
except Exception as e:
print(f"{item.get('id', '?')}: {e}")
# 6. dd_approval_configs
dd_configs = data.get('dd_approval_configs', [])
if dd_configs:
print(f"\n--- dd_approval_configs ({len(dd_configs)} 条) ---")
for item in dd_configs:
item.setdefault('id', getID())
try:
existing = await sor.R('dd_approval_configs', {'id': item['id']})
if not existing:
await sor.C('dd_approval_configs', item)
print(f"{item['id']} - {item.get('biz_type', '')}")
else:
print(f" · {item['id']} (已存在)")
except Exception as e:
print(f"{item.get('id', '?')}: {e}")
total = len(appcodes) + len(appcodes_kv) + len(categories) + len(configs) + len(sections) + len(dd_configs)
print(f"\n=== 完成: 处理 {total} 条初始数据 ===")
asyncio.run(insert_data())
if __name__ == '__main__':
main()