- ALL_TENANTS / session / seed / migrations 全部同步 - 新增 migrate_rename_tenant() 数据迁移,启动自动 UPDATE 所有表 - migrations/ 模式重构(参考 SalesManager)
122 lines
6.8 KiB
HTML
122 lines
6.8 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>科普(慰心斋)OPC 工作台</title>
|
||
<script src="{{ url_for('static', filename='vendor/tailwind.js') }}"></script>
|
||
<script>
|
||
tailwind.config = {
|
||
theme: {
|
||
extend: {
|
||
colors: {
|
||
brand: {
|
||
50: '#eff6ff',
|
||
600: '#2563eb',
|
||
700: '#1d4ed8'
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
||
<script src="{{ url_for('static', filename='vendor/chart.js') }}" defer></script>
|
||
<script src="{{ url_for('static', filename='vendor/squire.js') }}" defer></script>
|
||
<script src="{{ url_for('static', filename='vendor/lucide.js') }}" defer></script>
|
||
</head>
|
||
<body class="min-h-screen bg-slate-50 text-slate-950">
|
||
<div class="flex min-h-screen">
|
||
<!-- 左侧工作台切换栏 -->
|
||
<aside class="w-[72px] bg-slate-900 flex flex-col items-center py-6 gap-1 shrink-0 sticky top-0 h-screen overflow-y-auto" id="workspaceSidebar">
|
||
<div class="flex flex-col items-center mb-2 cursor-pointer" onclick="document.getElementById('userAvatar').click()">
|
||
<div class="w-10 h-10 rounded-full bg-slate-700 flex items-center justify-center text-white font-bold text-sm hover:ring-2 hover:ring-blue-400 transition-all" id="userAvatar" title=""></div>
|
||
<span class="text-[10px] text-slate-400 mt-1.5 max-w-[64px] truncate text-center" id="userDisplayName" title=""></span>
|
||
</div>
|
||
<!-- 分隔线 -->
|
||
<div class="w-8 h-px bg-slate-700 my-2"></div>
|
||
<!-- 工作台切换按钮 -->
|
||
<div class="flex flex-col items-center cursor-pointer hover:bg-slate-800 rounded-lg py-2 px-1 w-14 transition-colors" onclick="toggleTenantMenu(event)">
|
||
<i data-lucide="layout-grid" style="width:18px;height:18px;color:#94a3b8"></i>
|
||
<span class="text-[10px] text-slate-400 mt-1 max-w-[56px] truncate text-center" id="currentTenantLabel">工作台</span>
|
||
<i data-lucide="chevron-down" style="width:12px;height:12px;color:#64748b;margin-top:2px"></i>
|
||
</div>
|
||
<!-- 分隔线 -->
|
||
<div class="w-8 h-px bg-slate-700 my-2"></div>
|
||
<!-- 导航 Tab 图标 -->
|
||
<div class="flex flex-col items-center gap-1 w-14" id="sidebarTabs">
|
||
<div class="sidebar-tab active" data-tab="home" onclick="switchTab('home')" title="首页">
|
||
<i data-lucide="home" style="width:20px;height:20px"></i>
|
||
<span class="text-[10px] mt-1">首页</span>
|
||
</div>
|
||
<div class="sidebar-tab" data-tab="finance" onclick="switchTab('finance')" title="经营管理">
|
||
<i data-lucide="briefcase-business" style="width:20px;height:20px"></i>
|
||
<span class="text-[10px] mt-1">财务</span>
|
||
</div>
|
||
<div class="sidebar-tab" data-tab="projects" onclick="switchTab('projects')" title="重点工作与台账">
|
||
<i data-lucide="file-text" style="width:20px;height:20px"></i>
|
||
<span class="text-[10px] mt-1">台账</span>
|
||
</div>
|
||
<div class="sidebar-tab" data-tab="proposals" onclick="switchTab('proposals')" title="业务方案">
|
||
<i data-lucide="package" style="width:20px;height:20px"></i>
|
||
<span class="text-[10px] mt-1">方案</span>
|
||
</div>
|
||
<div class="sidebar-tab" data-tab="products" onclick="switchTab('products')" title="产品迭代">
|
||
<i data-lucide="wallet-cards" style="width:20px;height:20px"></i>
|
||
<span class="text-[10px] mt-1">产品</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
<!-- 主内容区 -->
|
||
<div class="flex-1 min-w-0">
|
||
<header class="topbar border-b border-slate-200 bg-white px-8 py-5">
|
||
<div class="flex items-center gap-3">
|
||
<div>
|
||
<p class="eyebrow text-xs font-semibold uppercase tracking-[0.18em] text-blue-700">OPC Manager</p>
|
||
<div class="flex items-center gap-3 mt-1">
|
||
<h1 class="text-2xl font-semibold" id="workspaceTitle">科普 OPC 工作台</h1>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="px-8 py-6">
|
||
<section id="home" class="panel active"></section>
|
||
<section id="projects" class="panel"></section>
|
||
<section id="proposals" class="panel"></section>
|
||
<section id="products" class="panel"></section>
|
||
<section id="finance" class="panel"></section>
|
||
</main>
|
||
</div><!-- 关闭主内容区 -->
|
||
</div><!-- 关闭 flex 容器 -->
|
||
<aside id="drawer" class="drawer" aria-hidden="true"></aside>
|
||
<div id="taskModal" class="task-modal"></div>
|
||
<!-- 新增项目模态框 -->
|
||
<div id="newProjectModal" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/40" onclick="closeNewProjectModal()">
|
||
<div class="bg-white rounded-2xl shadow-2xl w-full max-w-md mx-4" onclick="event.stopPropagation()">
|
||
<div class="flex items-center justify-between px-6 py-4 border-b border-slate-100">
|
||
<h3 class="text-lg font-semibold text-slate-800">新增项目</h3>
|
||
<button class="btn btn-ghost btn-sm rounded-full w-8 h-8 p-0" onclick="closeNewProjectModal()"><i data-lucide="x"></i></button>
|
||
</div>
|
||
<form onsubmit="createOperation(event)" class="p-6 grid gap-4">
|
||
<label class="block"><span class="text-xs font-medium text-slate-500">项目名称</span><input name="project_name" required class="form-ctrl mt-1"></label>
|
||
<label class="block"><span class="text-xs font-medium text-slate-500">项目备注</span><textarea name="notes" rows="3" class="form-ctrl mt-1" placeholder="可选"></textarea></label>
|
||
<div class="flex justify-end gap-3 pt-3 border-t border-slate-100">
|
||
<button type="button" class="btn btn-ghost btn-sm" onclick="closeNewProjectModal()">取消</button>
|
||
<button type="submit" class="btn btn-primary btn-sm">创建</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<script src="{{ url_for('static', filename='modules/utils.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='modules/home.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='modules/projects.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='modules/proposals.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='modules/products.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='modules/finance.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='modules/drawer.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='modules/admin.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='app.js') }}"></script>
|
||
</body>
|
||
</html>
|