Add dashboard_for_sage module: menu submenu, sage.py import/load, build.sh module list
This commit is contained in:
parent
c18c9113cc
commit
3cda907ba2
@ -25,6 +25,7 @@ from discount.init import load_discount
|
|||||||
from harnessed_agent.init import load_harnessed_agent
|
from harnessed_agent.init import load_harnessed_agent
|
||||||
from harnessed_reasoning.init import load_harnessed_reasoning
|
from harnessed_reasoning.init import load_harnessed_reasoning
|
||||||
from hermes_web_cli.init import load_hermes_web_cli
|
from hermes_web_cli.init import load_hermes_web_cli
|
||||||
|
from dashboard_for_sage.init import load_dashboard_for_sage
|
||||||
from global_func import set_globalvariable
|
from global_func import set_globalvariable
|
||||||
from unipay.init import load_unipay
|
from unipay.init import load_unipay
|
||||||
from platformbiz.init import load_platformbiz
|
from platformbiz.init import load_platformbiz
|
||||||
@ -56,6 +57,7 @@ def init():
|
|||||||
load_discount()
|
load_discount()
|
||||||
load_hermes_web_cli()
|
load_hermes_web_cli()
|
||||||
load_smssend()
|
load_smssend()
|
||||||
|
load_dashboard_for_sage()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
webapp(init)
|
webapp(init)
|
||||||
|
|||||||
2
build.sh
2
build.sh
@ -26,7 +26,7 @@ do
|
|||||||
cd $m
|
cd $m
|
||||||
$cdir/py3/bin/pip install .
|
$cdir/py3/bin/pip install .
|
||||||
done
|
done
|
||||||
for m in appbase rbac accounting llmage platformbiz msp cpcc unipay filemgr dapi uapi rag charge pricing discount harnessed_agent harnessed_reasoning
|
for m in appbase rbac accounting llmage platformbiz msp cpcc unipay filemgr dapi uapi rag charge pricing discount harnessed_agent harnessed_reasoning dashboard_for_sage
|
||||||
do
|
do
|
||||||
echo "install $m module..."
|
echo "install $m module..."
|
||||||
cd $cdir/pkgs
|
cd $cdir/pkgs
|
||||||
|
|||||||
@ -10,6 +10,11 @@
|
|||||||
"label": "主页",
|
"label": "主页",
|
||||||
"url": "{{entire_url('public')}}"
|
"url": "{{entire_url('public')}}"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "dashboard",
|
||||||
|
"label": "数据看板",
|
||||||
|
"submenu": "{{entire_url('/dashboard_for_sage/menu.ui')}}"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "agent",
|
"name": "agent",
|
||||||
"label": "代理",
|
"label": "代理",
|
||||||
|
|||||||
178
xlsx2json_models.py
Normal file
178
xlsx2json_models.py
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
将 Sage 相关模块 models/ 目录下的 .xlsx 文件转换为 .json 数据表定义文件。
|
||||||
|
|
||||||
|
用法(在 Sage 虚拟环境中运行):
|
||||||
|
python ~/repos/sage/xlsx2json_models.py # 转换所有模块
|
||||||
|
python ~/repos/sage/xlsx2json_models.py llmage # 只转换 llmage
|
||||||
|
python ~/repos/sage/xlsx2json_models.py --dry-run # 预览
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
# Sage 虚拟环境路径
|
||||||
|
sage_root = os.path.expanduser('~/repos/sage')
|
||||||
|
sys.path.insert(0, sage_root)
|
||||||
|
sys.path.insert(0, os.path.join(sage_root, 'py3/lib/python3.10/site-packages'))
|
||||||
|
|
||||||
|
from appPublic.folderUtils import listFile
|
||||||
|
from xls2ddl.xlsxData import xlsxFactory, CRUDData
|
||||||
|
|
||||||
|
# Sage 相关模块列表
|
||||||
|
SAGE_MODULES = [
|
||||||
|
'appbase', 'rbac', 'accounting', 'llmage', 'platformbiz',
|
||||||
|
'msp', 'cpcc', 'unipay', 'filemgr', 'dapi', 'uapi',
|
||||||
|
'rag', 'charge', 'pricing', 'discount', 'hermes-web-cli',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def xlsx_to_json_dict(xlsx_path):
|
||||||
|
"""将 xlsx 文件读取并转换为 json 格式的 dict。"""
|
||||||
|
d = xlsxFactory(xlsx_path)
|
||||||
|
if d is None:
|
||||||
|
return None
|
||||||
|
data = d.get_data()
|
||||||
|
|
||||||
|
# 只保留目标字段
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
# summary: 确保 primary 是 list
|
||||||
|
if 'summary' in data:
|
||||||
|
result['summary'] = []
|
||||||
|
for s in data['summary']:
|
||||||
|
entry = {'name': s.get('name'), 'title': s.get('title')}
|
||||||
|
primary = s.get('primary', '')
|
||||||
|
if isinstance(primary, list):
|
||||||
|
entry['primary'] = primary
|
||||||
|
elif primary:
|
||||||
|
entry['primary'] = [p.strip() for p in str(primary).split(',')]
|
||||||
|
else:
|
||||||
|
entry['primary'] = []
|
||||||
|
if s.get('catelog'):
|
||||||
|
entry['catelog'] = s['catelog']
|
||||||
|
result['summary'].append(entry)
|
||||||
|
|
||||||
|
# fields: 清理 None 值
|
||||||
|
if 'fields' in data:
|
||||||
|
result['fields'] = []
|
||||||
|
for f in data['fields']:
|
||||||
|
entry = {'name': f.get('name'), 'title': f.get('title'), 'type': f.get('type')}
|
||||||
|
if f.get('length') is not None:
|
||||||
|
entry['length'] = f['length']
|
||||||
|
if f.get('nullable') is not None:
|
||||||
|
entry['nullable'] = f['nullable']
|
||||||
|
if f.get('default') is not None:
|
||||||
|
entry['default'] = f['default']
|
||||||
|
result['fields'].append(entry)
|
||||||
|
|
||||||
|
# indexes: 从 validation 中的 idx 操作转换,或直接用 indexes sheet
|
||||||
|
if 'indexes' in data and data['indexes']:
|
||||||
|
result['indexes'] = data['indexes']
|
||||||
|
elif 'validation' in data:
|
||||||
|
indexes = []
|
||||||
|
for v in data['validation']:
|
||||||
|
if v.get('oper') == 'idx':
|
||||||
|
idx = {'name': v.get('name'), 'idxtype': 'index'}
|
||||||
|
val = v.get('value', '')
|
||||||
|
parts = val.split(':')
|
||||||
|
if len(parts) >= 2:
|
||||||
|
idx['idxtype'] = parts[0]
|
||||||
|
idx['idxfields'] = [f.strip() for f in parts[1].split(',')]
|
||||||
|
indexes.append(idx)
|
||||||
|
if indexes:
|
||||||
|
result['indexes'] = indexes
|
||||||
|
|
||||||
|
# codes
|
||||||
|
if 'codes' in data and data['codes']:
|
||||||
|
result['codes'] = data['codes']
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def convert_module(module_name, dry_run=False):
|
||||||
|
"""转换单个模块的 models 目录。"""
|
||||||
|
module_dir = os.path.expanduser(f'~/repos/{module_name}')
|
||||||
|
models_dir = os.path.join(module_dir, 'models')
|
||||||
|
|
||||||
|
if not os.path.isdir(models_dir):
|
||||||
|
print(f" [SKIP] {module_name}: models/ directory not found")
|
||||||
|
return 0, 0
|
||||||
|
|
||||||
|
xlsx_files = [f for f in listFile(models_dir) if f.endswith('.xlsx')]
|
||||||
|
if not xlsx_files:
|
||||||
|
print(f" [SKIP] {module_name}: no .xlsx files")
|
||||||
|
return 0, 0
|
||||||
|
|
||||||
|
converted = 0
|
||||||
|
skipped = 0
|
||||||
|
|
||||||
|
for xlsx_path in xlsx_files:
|
||||||
|
table_name = os.path.splitext(os.path.basename(xlsx_path))[0]
|
||||||
|
json_path = os.path.join(models_dir, f'{table_name}.json')
|
||||||
|
|
||||||
|
# 跳过已经是 json 的文件
|
||||||
|
if os.path.exists(json_path):
|
||||||
|
print(f" [EXIST] {table_name}.json already exists")
|
||||||
|
skipped += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = xlsx_to_json_dict(xlsx_path)
|
||||||
|
if result is None:
|
||||||
|
print(f" [FAIL] {table_name}: could not read xlsx")
|
||||||
|
skipped += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if dry_run:
|
||||||
|
print(f" [DRY] Would create {table_name}.json ({len(result.get('fields', []))} fields)")
|
||||||
|
converted += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open(json_path, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(result, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
print(f" [OK] {table_name}.json ({len(result.get('fields', []))} fields)")
|
||||||
|
converted += 1
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [FAIL] {table_name}: {e}")
|
||||||
|
skipped += 1
|
||||||
|
|
||||||
|
return converted, skipped
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Convert models/*.xlsx to models/*.json')
|
||||||
|
parser.add_argument('modules', nargs='*', help='Module names to convert (default: all)')
|
||||||
|
parser.add_argument('--dry-run', action='store_true', help='Preview without writing files')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
modules = args.modules if args.modules else SAGE_MODULES
|
||||||
|
dry_run = args.dry_run
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print(" Sage Models: xlsx -> json 转换")
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"Modules: {', '.join(modules)}")
|
||||||
|
print(f"Dry run: {dry_run}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
total_converted = 0
|
||||||
|
total_skipped = 0
|
||||||
|
|
||||||
|
for mod in modules:
|
||||||
|
print(f"[{mod}]")
|
||||||
|
c, s = convert_module(mod, dry_run=dry_run)
|
||||||
|
total_converted += c
|
||||||
|
total_skipped += s
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print(f" 完成: 转换 {total_converted}, 跳过 {total_skipped}")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Loading…
x
Reference in New Issue
Block a user