diff --git a/static/app.js b/static/app.js
index e8cbfea..6bd8d5e 100644
--- a/static/app.js
+++ b/static/app.js
@@ -1,26 +1,13 @@
// app.js — 入口文件(加载模块 + 初始化)
-// 所有业务逻辑已拆分到 modules/ 目录:
-// utils.js — 共享状态、工具函数、API 封装
-// home.js — 首页 + 财务趋势图
-// projects.js — 重点工作与台账(项目+任务+拖拽)
-// proposals.js — 业务方案 + 文件管理
-// products.js — 产品迭代
-// finance.js — 经营管理(财务)
-// drawer.js — 详情抽屉 + 评论 + 转移
-
-// Tab 点击委托
-document.querySelector("#tabs").addEventListener("click", (event) => {
- const button = event.target.closest("button[data-tab]");
- if (button) switchTab(button.dataset.tab);
-});
// 恢复上次的工作台和标签页
const savedTenant = localStorage.getItem("opc-active-tenant");
if (savedTenant) {
state.tenant = savedTenant;
- document.querySelectorAll(".workspace-nav-item").forEach(el => el.classList.toggle("active", el.dataset.tenant === savedTenant));
const label = savedTenant.replace("·无界", "");
document.querySelector("#workspaceTitle").textContent = label + " OPC 工作台";
+ const tLabel = document.querySelector("#currentTenantLabel");
+ if (tLabel) { tLabel.textContent = label || "工作台"; tLabel.title = savedTenant; }
}
const savedTab = localStorage.getItem("opc-active-tab");
diff --git a/static/modules/projects.js b/static/modules/projects.js
index 0f3ed4a..0ecafc6 100644
--- a/static/modules/projects.js
+++ b/static/modules/projects.js
@@ -13,13 +13,57 @@ function applyUserTenants() {
e.stopPropagation();
toggleUserMenu(user);
});
- const allowedTenants = data.tenants || [];
- document.querySelectorAll(".workspace-nav-item").forEach(el => {
- el.style.display = allowedTenants.includes(el.dataset.tenant) ? "" : "none";
- });
+ // 缓存可用工作台列表,供下拉菜单使用
+ state.allowedTenants = data.tenants || [];
+ updateTenantLabel();
});
}
+window.toggleTenantMenu = (event) => {
+ event.stopPropagation();
+ let menu = document.getElementById("tenantMenu");
+ if (menu) { menu.remove(); return; }
+ const btn = event.currentTarget;
+ const rect = btn.getBoundingClientRect();
+ const tenants = state.allowedTenants || [];
+ menu = document.createElement("div");
+ menu.id = "tenantMenu";
+ menu.className = "fixed bg-white rounded-lg shadow-xl border border-slate-200 py-1 min-w-[160px] z-[9999]";
+ menu.style.left = Math.min(rect.left - 8, window.innerWidth - 180) + "px";
+ menu.style.top = rect.bottom + 6 + "px";
+ menu.innerHTML = `
+
+ ${tenants.map(t => `
+
+ `).join('')}`;
+ document.body.appendChild(menu);
+ if (window.lucide) lucide.createIcons();
+ setTimeout(() => {
+ document.addEventListener("click", function closeMenu() {
+ menu.remove();
+ document.removeEventListener("click", closeMenu);
+ }, { once: true });
+ }, 10);
+};
+
+window.switchTenantFromMenu = (tenant) => {
+ document.getElementById("tenantMenu")?.remove();
+ switchTenant(tenant);
+};
+
+function updateTenantLabel() {
+ const label = document.querySelector("#currentTenantLabel");
+ if (label) {
+ label.textContent = state.tenant.replace("·无界", "") || "工作台";
+ label.title = state.tenant;
+ }
+}
+
window.toggleUserMenu = (user) => {
let menu = document.getElementById("userMenu");
if (menu) { menu.remove(); return; }
diff --git a/static/modules/utils.js b/static/modules/utils.js
index 74b495e..031df3c 100644
--- a/static/modules/utils.js
+++ b/static/modules/utils.js
@@ -123,7 +123,7 @@ async function load() {
function switchTab(tab) {
state.active = tab;
localStorage.setItem("opc-active-tab", tab);
- document.querySelectorAll("#tabs button").forEach((btn) => btn.classList.toggle("active", btn.dataset.tab === tab));
+ document.querySelectorAll(".sidebar-tab").forEach((btn) => btn.classList.toggle("active", btn.dataset.tab === tab));
document.querySelectorAll(".panel").forEach((panel) => panel.classList.toggle("active", panel.id === tab));
render();
}
@@ -179,7 +179,8 @@ window.switchTenant = (tenant) => {
state.selectedProject = null;
localStorage.setItem("opc-active-tenant", tenant);
document.querySelector("#workspaceTitle").textContent = tenant.replace("·无界", "") + " OPC 工作台";
- document.querySelectorAll(".workspace-nav-item").forEach((el) => el.classList.toggle("active", el.dataset.tenant === tenant));
+ const label = document.querySelector("#currentTenantLabel");
+ if (label) { label.textContent = tenant.replace("·无界", "") || "工作台"; label.title = tenant; }
load();
};
window.doLogout = async () => {
diff --git a/static/styles.css b/static/styles.css
index f81bb49..c136d74 100644
--- a/static/styles.css
+++ b/static/styles.css
@@ -32,25 +32,30 @@ body {
background: rgba(96,165,250,0.15);
}
-.tabs {
+.sidebar-tab {
display: flex;
- gap: 4px;
-}
-
-.tabs button {
+ flex-direction: column;
align-items: center;
- border-bottom: 2px solid transparent;
- color: #64748b;
- display: inline-flex;
- font-size: 14px;
- font-weight: 600;
- gap: 8px;
- padding: 14px 16px;
+ padding: 8px 4px;
+ border-radius: 8px;
+ cursor: pointer;
+ color: #94a3b8;
+ transition: all 0.15s ease;
+ width: 100%;
}
-.tabs button.active {
- border-bottom-color: #1d4ed8;
- color: #1d4ed8;
+.sidebar-tab:hover {
+ background: #1e293b;
+ color: #cbd5e1;
+}
+
+.sidebar-tab.active {
+ background: #1e293b;
+ color: #60a5fa;
+}
+
+.sidebar-tab.active i {
+ color: #60a5fa;
}
.panel {
diff --git a/templates/index.html b/templates/index.html
index 27d608f..7e078e7 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -29,29 +29,42 @@