feat: track wwwroot/ in git for simpler deployment

Remove wwwroot/ from .gitignore so production deployment is just git pull.

Changes:
- wwwroot/index.ui: Shell layout with sidebar and main content
- wwwroot/global_menu.ui: Global navigation menu (22 modules)
- wwwroot/dashboard_for_sage/: Dashboard widgets and stats
- wwwroot/product_management/: Product management pages
- Module symlinks (accounting, rbac, bricks, etc.)

Ignored: .DS_Store, *.bak, tmp/
This commit is contained in:
yumoqing 2026-05-27 19:00:46 +08:00
parent acb5eb29f9
commit 3481d80f24
80 changed files with 322 additions and 0 deletions

1
wwwroot/accounting Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/accounting/wwwroot

1
wwwroot/appbase Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/appbase/wwwroot

1
wwwroot/bricks Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/bricks/dist

1
wwwroot/charge Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/charge/wwwroot

17
wwwroot/check_rf.dspy Normal file
View File

@ -0,0 +1,17 @@
import json
from appPublic.registerfunction import RegisterFunction
from appPublic.log import debug
rf = RegisterFunction()
funcs = list(rf.registKW.keys())
debug(f'check_rf: Registered functions: {funcs}')
# Try to call password directly
pw_func = rf.get('password')
debug(f'check_rf: password function = {pw_func}')
result = {
'functions': funcs,
'has_password': pw_func is not None
}
return json.dumps(result, ensure_ascii=False)

1
wwwroot/dapi Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/dapi/wwwroot

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/accounting_errors.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/api/get_today_usage.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/api/get_top_models.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/api/get_user_stats.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/api/top_models.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/chart_top_models.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/concurrent_users.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/global_menu.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/index.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/menu.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/scripts/dashboard_refresh.js

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/shell.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/shell_theme.css

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/shell_theme.js

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/stat_active_users.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/stat_concurrent.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/stat_errors.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/stat_new_users_month.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/stat_today_amount.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/stat_today_usage.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/stat_total_orgs.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/stat_total_users.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/table_top_providers_amount.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/table_top_providers_count.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/table_top_users.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/table_top_users_amount.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/table_top_users_count.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/today_amount.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/today_usage.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/top_models_chart.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/top_users_amount.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/total_users.ui

1
wwwroot/discount Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/discount/wwwroot

44
wwwroot/exec_migrate.dspy Normal file
View File

@ -0,0 +1,44 @@
dbname = get_module_dbname('llmage')
db = DBPools()
async with db.sqlorContext(dbname) as sor:
# Create table
sql = """
CREATE TABLE IF NOT EXISTS llm_catalog_rel (
id VARCHAR(32) NOT NULL PRIMARY KEY,
llmid VARCHAR(32) NOT NULL,
llmcatelogid VARCHAR(32) NOT NULL,
INDEX idx_llm (llmid),
INDEX idx_catelog (llmcatelogid)
)
"""
try:
await sor.sqlExe(sql, {})
print("Table llm_catalog_rel created or exists.")
except Exception as e:
print(f"Create table error: {e}")
# Migrate data
sql = "select id, llmcatelogid from llm where llmcatelogid is not null and llmcatelogid != ''"
rows = await sor.sqlExe(sql, {})
print(f"Found {len(rows)} records to migrate.")
for r in rows:
data = {
'llmid': r['id'],
'llmcatelogid': r['llmcatelogid']
}
try:
await sor.C('llm_catalog_rel', data)
except Exception as e:
print(f"Insert error: {e}")
print("Migration complete.")
# Drop column
try:
await sor.sqlExe("alter table llm drop column llmcatelogid", {})
print("Column llmcatelogid dropped.")
except Exception as e:
print(f"Drop column error: {e}")
return {'status': 'ok'}

1
wwwroot/filemgr Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/filemgr/wwwroot

175
wwwroot/global_menu.ui Normal file
View File

@ -0,0 +1,175 @@
{% set roles = get_user_roles(get_user()) %}
{
"widgettype": "Menu",
"id": "global_nav_menu",
"options": {
"width": "100%",
"height": "100%",
"bgcolor": "#111827",
"items": [
{
"name": "dashboard",
"label": "仪表盘",
"icon": "fa fa-dashboard",
"url": "{{entire_url('/dashboard_for_sage/index.ui')}}",
"target": "app.sage_main_content"
},
{% if get_user() %}
{
"name": "unified_dashboard",
"label": "统一仪表板",
"icon": "fa fa-chart-line",
"url": "{{entire_url('/unified_dashboard/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "integrated_crm_app",
"label": "CRM系统",
"icon": "fa fa-handshake",
"url": "{{entire_url('/integrated_crm_app/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "customer_management",
"label": "客户管理",
"icon": "fa fa-users",
"url": "{{entire_url('/customer_management/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "opportunity_management",
"label": "商机管理",
"icon": "fa fa-briefcase",
"url": "{{entire_url('/opportunity_management/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "contract_management",
"label": "合同管理",
"icon": "fa fa-file-contract",
"url": "{{entire_url('/contract_management/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "product_management",
"label": "产品管理",
"icon": "fa fa-cubes",
"url": "{{entire_url('/product_management/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "supplychain",
"label": "供销链管理",
"icon": "fa fa-truck",
"url": "{{entire_url('/supplychain/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "pricing",
"label": "定价管理",
"icon": "fa fa-money-bill",
"url": "{{entire_url('/pricing/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "discount",
"label": "折扣管理",
"icon": "fa fa-percent",
"url": "{{entire_url('/discount/promote.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "financial_management",
"label": "财务管理",
"icon": "fa fa-calculator",
"url": "{{entire_url('/financial_management/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "workflow_approval",
"label": "工作流审批",
"icon": "fa fa-tasks",
"url": "{{entire_url('/workflow_approval/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "llmage",
"label": "LLM 模型管理",
"icon": "fa fa-brain",
"url": "{{entire_url('/llmage/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "rag",
"label": "知识库管理",
"icon": "fa fa-database",
"url": "{{entire_url('/rag/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "cpcc",
"label": "算力中心管理",
"icon": "fa fa-server",
"url": "{{entire_url('/cpcc/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "msp",
"label": "运维管理",
"icon": "fa fa-tools",
"url": "{{entire_url('/msp/index.ui')}}",
"target": "app.sage_main_content"
},
{% endif %}
{% if 'reseller.operator' in roles or 'owner.superuser' in roles %}
{
"name": "platformbiz",
"label": "平台业务",
"icon": "fa fa-building",
"url": "{{entire_url('/platformbiz/index.ui')}}",
"target": "app.sage_main_content"
},
{% endif %}
{% if 'reseller.accountant' in roles or 'owner.superuser' in roles %}
{
"name": "accounting",
"label": "计费管理",
"icon": "fa fa-coins",
"url": "{{entire_url('/accounting/index.ui')}}",
"target": "app.sage_main_content"
},
{% endif %}
{% if get_user() %}
{
"name": "rbac",
"label": "用户与权限",
"icon": "fa fa-user-shield",
"url": "{{entire_url('/rbac/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "entcms",
"label": "内容管理",
"icon": "fa fa-newspaper",
"url": "{{entire_url('/cms/entcms/index.ui')}}",
"target": "app.sage_main_content"
},
{
"name": "dingdingflow",
"label": "钉钉审批",
"icon": "fa fa-mobile-alt",
"url": "{{entire_url('/cms/dingdingflow/index.ui')}}",
"target": "app.sage_main_content"
},
{% endif %}
{
"name": "hermes_web_cli",
"label": "AI Agent",
"icon": "fa fa-robot",
"url": "{{entire_url('/hermes-web-cli/index.ui')}}",
"target": "app.sage_main_content"
}
],
"menuitem_css": "menuitem"
}
}

1
wwwroot/harnessed_agent Symbolic link
View File

@ -0,0 +1 @@
../../harnessed_agent/wwwroot

1
wwwroot/harnessed_reasoning Symbolic link
View File

@ -0,0 +1 @@
../../harnessed_reasoning/wwwroot

1
wwwroot/hermes-web-cli Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/hermes-web-cli/wwwroot

1
wwwroot/llmage Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/llmage/wwwroot

1
wwwroot/msp Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/msp/wwwroot

1
wwwroot/platformbiz Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/platformbiz/wwwroot

1
wwwroot/pricing Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/pricing/wwwroot

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/category_options.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_brief.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_category_create.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_category_delete.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_category_update.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_create.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_delete.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_detail.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_purchase.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_type_config_create.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_type_config_delete.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_type_config_update.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_update.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/api/product_use.dspy

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/category_manage.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/index.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/menu.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/product_category_tree

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/product_list

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/product_manage.ui

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/product_type_config_list

View File

@ -0,0 +1 @@
/home/hermesai/repos/product_management/wwwroot/product_type_config_manage.ui

1
wwwroot/rag Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/rag/wwwroot

1
wwwroot/rbac Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/rbac/wwwroot

1
wwwroot/shell.ui Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/shell.ui

1
wwwroot/shell_theme.css Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/shell_theme.css

1
wwwroot/shell_theme.js Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/dashboard_for_sage/wwwroot/shell_theme.js

1
wwwroot/supplychain Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/supplychain/wwwroot

10
wwwroot/test_rf.dspy Normal file
View File

@ -0,0 +1,10 @@
import json
from appPublic.registerfunction import RegisterFunction
from appPublic.log import debug
rf = RegisterFunction()
funcs = list(rf.registKW.keys())
debug(f'Registered functions: {funcs}')
result = {'functions': funcs}
return json.dumps(result, ensure_ascii=False)

1
wwwroot/uapi Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/uapi/wwwroot

1
wwwroot/unipay Symbolic link
View File

@ -0,0 +1 @@
/home/hermesai/repos/sage/pkgs/unipay/wwwroot