Ver Fonte

feat(editor): 优化空白报告的编辑页提示样式

- 重新设计空白编辑器占位提示,采用 V2 风格
- 添加大图标和清晰的操作引导卡片
- 卡片支持 hover 交互效果
- 增加提示信息(选中文本可标记为要素)
何文松 há 3 semanas atrás
pai
commit
0e34d4002b

+ 81 - 31
frontend/vue-demo/src/views/Editor.vue

@@ -1268,17 +1268,27 @@ watch(documentContent, (newContent) => {
   })
 })
 
-// 空白模板时的占位提示
+// 空白模板时的占位提示 - V2 风格
 const emptyPlaceholder = `
   <div class="empty-editor-placeholder">
-    <h2>📝 开始编辑您的模板</h2>
-    <p>这是一个空白模板。您可以:</p>
-    <ul>
-      <li>在左侧添加来源文件定义</li>
-      <li>在右侧面板添加变量</li>
-      <li>直接在此处编辑模板内容</li>
-      <li>选中文本后右键将其标记为变量</li>
-    </ul>
+    <div class="empty-icon">📄</div>
+    <h2>开始编辑您的报告</h2>
+    <p class="empty-subtitle">当前报告还没有内容,您可以:</p>
+    <div class="empty-actions">
+      <div class="action-card">
+        <span class="action-icon">📁</span>
+        <span class="action-text">上传来源文件自动解析生成内容</span>
+      </div>
+      <div class="action-card">
+        <span class="action-icon">✏️</span>
+        <span class="action-text">直接在此处开始编辑</span>
+      </div>
+      <div class="action-card">
+        <span class="action-icon">🤖</span>
+        <span class="action-text">使用 AI 助手辅助撰写</span>
+      </div>
+    </div>
+    <p class="empty-hint">💡 提示:选中文本后右键可将其标记为要素</p>
   </div>
 `
 
@@ -4305,44 +4315,84 @@ onUnmounted(() => {
   }
 }
 
-// 空白编辑器占位提示样式
+// ==========================================
+// 空白编辑器占位提示样式 - V2 风格
+// ==========================================
 :deep(.empty-editor-placeholder) {
-  padding: 60px 40px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 80px 40px;
   text-align: center;
-  color: var(--text-2);
+  min-height: 400px;
+
+  .empty-icon {
+    font-size: 64px;
+    margin-bottom: 24px;
+    opacity: 0.8;
+  }
 
   h2 {
     font-size: 24px;
-    margin-bottom: 20px;
+    font-weight: 600;
+    margin-bottom: 12px;
     color: var(--text-1);
   }
 
-  p {
+  .empty-subtitle {
     font-size: 15px;
-    margin-bottom: 16px;
+    color: var(--text-3);
+    margin-bottom: 32px;
   }
 
-  ul {
-    list-style: none;
-    padding: 0;
+  .empty-actions {
+    display: flex;
+    flex-direction: column;
+    gap: 12px;
+    margin-bottom: 32px;
+    width: 100%;
+    max-width: 400px;
+  }
+
+  .action-card {
+    display: flex;
+    align-items: center;
+    gap: 12px;
+    padding: 16px 20px;
+    background: var(--bg);
+    border: 1px solid var(--border);
+    border-radius: var(--radius-md);
+    cursor: pointer;
+    transition: all 0.2s;
     text-align: left;
-    max-width: 300px;
-    margin: 0 auto;
 
-    li {
-      padding: 8px 0;
-      padding-left: 24px;
-      position: relative;
-      font-size: 14px;
+    &:hover {
+      border-color: var(--primary);
+      background: var(--primary-light);
+      transform: translateX(4px);
+    }
 
-      &::before {
-        content: '✓';
-        position: absolute;
-        left: 0;
-        color: var(--primary);
-      }
+    .action-icon {
+      font-size: 24px;
+      flex-shrink: 0;
+    }
+
+    .action-text {
+      font-size: 14px;
+      color: var(--text-1);
+      font-weight: 500;
     }
   }
+
+  .empty-hint {
+    font-size: 13px;
+    color: var(--text-3);
+    padding: 12px 20px;
+    background: var(--bg);
+    border-radius: var(--radius-md);
+    border-left: 3px solid var(--primary);
+  }
 }
 
 // 高亮块动画

+ 4139 - 0
frontend/灵越智报_完整交互版_v2.html

@@ -0,0 +1,4139 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>灵越智报 - 智能报告生成平台</title>
+    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;600;700&display=swap" rel="stylesheet">
+    <!-- 引入 iconfont 项目(已替换) -->
+    <link rel="stylesheet" href="http://at.alicdn.com/t/c/font_2630279_pgouo6fulk.css">
+    <style>
+        :root {
+            --primary: #1890ff;
+            --primary-dark: #096dd9;
+            --primary-light: #e6f7ff;
+            --primary-gradient: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
+            --white: #ffffff;
+            --bg: #f5f7fa;
+            --border: #e8e8e8;
+            --text1: #262626;
+            --text2: #595959;
+            --text3: #8c8c8c;
+            --success: #52c41a;
+            --warning: #faad14;
+            --danger: #ff4d4f;
+            --ai-gradient: linear-gradient(135deg, #1890ff 0%, #722ed1 100%);
+            --data-gradient: linear-gradient(135deg, #52c41a 0%, #13c2c2 100%);
+        }
+
+        /* JavaScript for syncing editor title was moved out of the style block to avoid invalid CSS. */
+
+        * { margin: 0; padding: 0; box-sizing: border-box; }
+        body { font-family: 'Noto Sans SC', sans-serif; background: var(--bg); color: var(--text1); font-size: 14px; line-height: 1.6; height: 100vh; overflow: hidden; }
+
+        /* 全局头部 */
+        .header { position: fixed; top: 0; left: 0; right: 0; height: 56px; background: var(--white); border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; padding: 0 20px; z-index: 1000; }
+        .header-left { display: flex; align-items: center; gap: 20px; }
+        .logo { display: flex; align-items: center; gap: 8px; font-size: 17px; font-weight: 600; color: var(--primary); cursor: pointer; }
+        .logo-icon { width: 32px; height: 32px; background: var(--primary-gradient); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; font-size: 18px; }
+        .search-box { position: relative; width: 320px; }
+        .search-input { width: 100%; height: 36px; padding: 0 14px 0 36px; border: 1px solid var(--border); border-radius: 18px; font-size: 13px; background: var(--bg); outline: none; transition: all 0.2s; }
+        .search-input:focus { background: var(--white); border-color: var(--primary); }
+        .search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: #8c8c8c; font-size: 14px; }
+        .header-right { display: flex; align-items: center; gap: 10px; }
+        .hd-btn { position: relative; width: 36px; height: 36px; border: none; background: transparent; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 18px; color: var(--text2); transition: all 0.2s; }
+        .hd-btn:hover { background: var(--bg); color: var(--primary); }
+        .badge { position: absolute; top: 2px; right: 2px; min-width: 16px; height: 16px; background: var(--danger); color: white; border-radius: 8px; font-size: 10px; display: flex; align-items: center; justify-content: center; }
+        .user-menu { display: flex; align-items: center; gap: 6px; padding: 4px 8px 4px 4px; border-radius: 20px; cursor: pointer; }
+        .user-menu:hover { background: var(--bg); }
+        .avatar { width: 30px; height: 30px; border-radius: 50%; background: var(--primary-gradient); color: white; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 12px; }
+        .user-name { font-size: 13px; font-weight: 500; }
+
+        /* 侧边栏 */
+        .sidebar { position: fixed; top: 56px; left: 0; width: 240px; height: calc(100vh - 56px); background: var(--white); border-right: none; display: flex; flex-direction: column; transition: width 0.3s; z-index: 900; overflow-y: auto; }
+        .sidebar.hidden { display: none; }
+        .sidebar-menu { flex: 1; padding: 10px; overflow-y: auto; }
+        .menu-item { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 8px; cursor: pointer; transition: all 0.2s; margin-bottom: 2px; position: relative; }
+        .menu-item:hover { background: var(--primary-light); color: var(--primary); }
+        .menu-item.active { background: var(--primary-light); color: var(--primary); }
+        .menu-item.active::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 3px; height: 18px; background: var(--primary); border-radius: 0 2px 2px 0; }
+        .menu-icon { font-size: 16px; }
+        .menu-text { font-size: 13px; font-weight: 500; }
+        .menu-badge { min-width: 18px; height: 18px; padding: 0 5px; background: var(--primary); color: white; border-radius: 9px; font-size: 10px; display: flex; align-items: center; justify-content: center; }
+
+        /* 主内容 */
+        .main { margin-left: 300px; margin-top: 56px; height: calc(100vh - 56px); overflow-y: auto; display:flex; flex-direction:column; }
+        .page { display: none; padding: 20px; }
+        .page.active { display: block; }
+
+        /* 通用组件 */
+        .card { background: var(--white); border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
+        .btn { display: inline-flex; align-items: center; gap: 4px; padding: 7px 14px; border: 1px solid var(--border); background: var(--white); border-radius: 6px; cursor: pointer; font-size: 12px; transition: all 0.2s; }
+        .btn:hover { border-color: var(--primary); color: var(--primary); }
+        .btn-primary { background: var(--primary-gradient); color: white; border: none; }
+        .btn-primary:hover { box-shadow: 0 4px 12px rgba(24,144,255,0.4); }
+
+        /* 首页样式 */
+        .welcome h1 { font-size: 24px; font-weight: 600; margin-bottom: 4px; }
+        .welcome h1 span { background: var(--ai-gradient); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
+        .welcome p { color: var(--text2); }
+        .stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin: 20px 0; }
+        .stat-card { padding: 18px; cursor: pointer; transition: all 0.3s; }
+        .stat-card:hover { transform: translateY(-4px); box-shadow: 0 8px 20px rgba(0,0,0,0.1); }
+        .stat-icon { width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 20px; margin-bottom: 10px; }
+        .stat-icon.blue { background: linear-gradient(135deg, #e6f7ff, #bae7ff); }
+        .stat-icon.purple { background: linear-gradient(135deg, #f9f0ff, #efdbff); }
+        .stat-icon.green { background: linear-gradient(135deg, #f6ffed, #d9f7be); }
+        .stat-icon.orange { background: linear-gradient(135deg, #fff7e6, #ffe7ba); }
+        .stat-value { font-size: 26px; font-weight: 700; }
+        .stat-label { font-size: 13px; color: var(--text2); margin-bottom: 6px; }
+        .stat-trend { font-size: 12px; }
+        .stat-trend.up { color: var(--success); }
+
+        /* AI对话入口 */
+        .ai-card { padding: 20px; margin-bottom: 20px; }
+        .ai-welcome { background: linear-gradient(135deg, #f0f7ff, #f5f0ff); border-radius: 10px; padding: 16px; margin-bottom: 16px; }
+        .ai-avatar { width: 44px; height: 44px; background: var(--ai-gradient); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 22px; margin-bottom: 10px; }
+        .ai-title { font-size: 14px; font-weight: 600; margin-bottom: 8px; }
+        .ai-list { list-style: none; margin-bottom: 10px; }
+        .ai-list li { color: var(--text2); padding: 3px 0; font-size: 13px; }
+        .ai-list li::before { content: '•'; color: var(--primary); margin-right: 8px; }
+        .ai-tip { font-size: 12px; color: var(--text3); padding: 8px 12px; background: rgba(255,255,255,0.7); border-radius: 6px; border-left: 3px solid var(--primary); }
+        .ai-input-wrap { position: relative; margin-bottom: 14px; }
+        .ai-input { width: 100%; height: 46px; padding: 0 100px 0 18px; border: 2px solid var(--border); border-radius: 23px; font-size: 14px; outline: none; transition: all 0.3s; }
+        .ai-input:focus { border-color: var(--primary); }
+        .ai-input-btns { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); display: flex; gap: 4px; }
+        .ai-input-btn { width: 32px; height: 32px; border: none; background: transparent; border-radius: 50%; cursor: pointer; font-size: 16px; color: var(--text3); }
+        .ai-input-btn:hover { background: var(--bg); color: var(--primary); }
+        .ai-input-btn.send { background: var(--primary-gradient); color: white; display: none; }
+        .ai-input-btn.send.show { display: flex; align-items: center; justify-content: center; }
+        .thinking-modes { display: flex; gap: 8px; flex-wrap: wrap; }
+        .mode-btn { padding: 6px 12px; background: var(--bg); border: 1px solid var(--border); border-radius: 18px; font-size: 12px; cursor: pointer; }
+        .mode-btn:hover { border-color: var(--primary); background: var(--primary-light); }
+        .mode-btn.active { background: var(--primary-light); border-color: var(--primary); color: var(--primary); }
+
+        /* 模板区 */
+        .section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
+        .section-title { font-size: 15px; font-weight: 600; }
+        .section-link { font-size: 13px; color: var(--primary); cursor: pointer; }
+        .tpl-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 14px; }
+        .tpl-card { overflow: hidden; cursor: pointer; transition: all 0.3s; }
+        .tpl-card:hover { transform: translateY(-4px); box-shadow: 0 8px 20px rgba(0,0,0,0.1); }
+        .tpl-preview { height: 100px; background: linear-gradient(135deg, #f5f7fa, #e8ecf0); display: flex; align-items: center; justify-content: center; font-size: 36px; }
+        .tpl-info { padding: 14px; }
+        .tpl-name { font-weight: 600; margin-bottom: 6px; }
+        .tpl-meta { display: flex; gap: 12px; font-size: 11px; color: var(--text3); margin-bottom: 10px; }
+        .tpl-tags { display: flex; gap: 4px; margin-bottom: 10px; }
+        .tpl-tag { padding: 2px 6px; background: var(--primary-light); color: var(--primary); border-radius: 3px; font-size: 10px; }
+        .tpl-tag.hot { background: #fff1f0; color: var(--danger); }
+        .tpl-btn { width: 100%; padding: 8px; background: var(--primary-gradient); color: white; border: none; border-radius: 6px; font-size: 12px; cursor: pointer; }
+        .quick-actions { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
+        .quick-action { display: flex; align-items: center; gap: 12px; padding: 16px; border: 2px dashed var(--border); border-radius: 10px; cursor: pointer; }
+        .quick-action:hover { border-color: var(--primary); background: var(--primary-light); }
+        .quick-action-icon { width: 40px; height: 40px; background: var(--bg); border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 20px; }
+
+        /* 编辑器专用样式 */
+        .editor-page { display: none; position: fixed; top: 56px; left: 0; right: 0; bottom: 0; background: var(--bg); z-index: 800; overflow: hidden; }
+        .editor-page.active { display: block; }
+
+        /* 编辑器工具栏 */
+        .editor-toolbar { height: 56px; background: var(--white); border-bottom: 1px solid var(--border); display: flex; align-items: center; padding: 0 16px; gap: 16px; flex-shrink: 0; }
+        .back-btn { display: flex; align-items: center; gap: 4px; padding: 8px 12px; border: none; background: transparent; border-radius: 6px; cursor: pointer; font-size: 13px; color: var(--text2); }
+        .back-btn:hover { background: var(--bg); color: var(--primary); }
+        .report-title-input { border: none; background: transparent; font-size: 15px; font-weight: 600; padding: 8px 12px; border-radius: 6px; min-width: 300px; outline: none; }
+        .report-title-input:hover { background: var(--bg); }
+        .report-title-input:focus { background: var(--white); box-shadow: 0 0 0 2px var(--primary-light); }
+        .save-status { display: flex; align-items: center; gap: 4px; font-size: 13px; color: var(--success); }
+        .toolbar-right { margin-left: auto; display: flex; gap: 10px; align-items: center; }
+        .toolbar-btn { display: flex; align-items: center; gap: 6px; padding: 8px 16px; border: 1px solid var(--border); background: var(--white); border-radius: 6px; cursor: pointer; font-size: 13px; color: var(--text1); transition: all 0.2s; }
+        .toolbar-btn:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-light); }
+        .toolbar-btn.primary { background: var(--primary); color: white; border: none; }
+        .toolbar-btn.primary:hover { background: var(--primary-dark); }
+        .toolbar-btn .icon { font-size: 14px; }
+        .toolbar-divider { width: 1px; height: 24px; background: var(--border); }
+
+        /* 编辑器主体 */
+        .editor-body { flex: 1; display: flex; overflow: hidden; min-height: 0; }
+
+        /* 当编辑器激活时,使用三列布局:左侧资源、中心编辑、右侧AI助手(与示例一致) */
+        .editor-page.active .editor-body {
+            display: grid;
+            grid-template-columns: 300px 1fr 300px;
+            gap: 16px;
+            padding: 16px;
+            /* ensure each column stretches to the full grid height */
+            align-items: stretch;
+            align-content: stretch;
+            box-sizing: border-box;
+            height: calc(100vh - 56px);
+            /* ensure grid row(s) fill available space so children can stretch */
+            grid-auto-rows: 1fr;
+        }
+
+        /* 左侧项目文件面板 */
+        .left-panel { width: 300px; background: var(--white); border-right: 1px solid var(--border); display: flex; flex-direction: column; min-height: 0; overflow: hidden; height: 100%; }
+        .panel-header { padding: 14px 16px; border-bottom: 1px solid var(--border); font-size: 13px; font-weight: 600; color: var(--text1); display: flex; align-items: center; justify-content: space-between; }
+        .panel-header-tabs .tabs-left { display:flex; gap:8px; align-items:center; }
+        .panel-tab { padding:8px 14px; border-radius:12px; border:1px solid transparent; background:transparent; cursor:pointer; font-weight:700; font-size:14px; }
+        .panel-tab.active { background: var(--primary); color: #fff; border-color: rgba(0,0,0,0.04); box-shadow: 0 6px 18px rgba(17,24,39,0.06); }
+        .panel-header .file-count { margin-left:8px; font-weight:500; color:var(--text3); }
+        .file-count { font-size: 12px; color: var(--text3); font-weight: normal; }
+        .panel-body { flex: 1; padding: 12px; display: flex; flex-direction: column; min-height: 0; }
+        /* docs / recent split: top 40% docs (scrollable), bottom 60% recent (scrollable) */
+        .docs-area { flex: 4; overflow-y: auto; min-height: 0; }
+        .recent-area { flex: 6; overflow-y: auto; min-height: 0; margin-top: 8px; }
+
+        /* 上传区 */
+        .upload-zone { border: 2px dashed var(--border); border-radius: 12px; height:40px; padding: 0 12px; text-align: center; cursor: pointer; margin-bottom: 16px; transition: all 0.18s; display:flex; align-items:center; justify-content:center; background: var(--white); }
+        .upload-zone:hover { border-color: var(--primary); background: var(--primary-light); }
+        /* 文本式添加资源(居中、大按钮感) */
+        .upload-zone .add-resource-text { font-size:16px; font-weight:600; color:var(--text1); padding:0 12px; line-height:40px; }
+        .upload-hint { font-size: 11px; color: var(--text3); display:block; margin-top:8px; text-align:center; }
+
+        /* 左侧面板折叠按钮 */
+        .panel-toggle-btn { background: transparent; border: 1px solid var(--border); border-radius: 8px; padding:6px 8px; cursor:pointer; font-size:14px; color:var(--text2); }
+        .panel-toggle-btn:hover { border-color: var(--primary); color:var(--primary); }
+        /* 小浮动展开按钮(当面板折叠时显示) */
+        .resource-expand-btn { position: fixed; left: 8px; top: 100px; width:40px; height:40px; border-radius:8px; background:var(--white); border:1px solid var(--border); display:flex; align-items:center; justify-content:center; z-index:1400; box-shadow:0 6px 18px rgba(0,0,0,0.08); cursor:pointer; }
+
+        /* 在正文中隐藏来源徽章(仅编辑区不显示来源文件标识) */
+        .editor-content .source-badge { display: none !important; }
+
+        /* 新:左侧文档列表样式(图片示例风格) - 内部旧 tab 样式已清理 */
+        .doc-section-header { display:flex; align-items:center; justify-content:space-between; padding:6px 4px 10px; font-size:13px; font-weight:600; color:var(--text1); }
+        .badge-count { background: var(--bg); padding:2px 8px; border-radius:12px; font-size:12px; color:var(--primary); }
+        .doc-list { display:flex; flex-direction:column; gap:10px; padding:4px 0 12px; }
+        .doc-card { display:flex; gap:10px; align-items:center; padding:10px; background:var(--white); border-radius:10px; border:1px solid var(--border); cursor:pointer; }
+        .doc-card .doc-thumb { width:40px; height:40px; border-radius:6px; background:var(--bg); display:flex; align-items:center; justify-content:center; font-size:18px; color:var(--text3); }
+        /* file badge styles for attachment icons (PDF/DOC/XLS/MD) */
+        .file-badge { display:inline-flex; width:40px; height:40px; border-radius:8px; align-items:center; justify-content:center; color:#fff; font-weight:700; font-size:13px; flex:0 0 40px; }
+        .file-badge.pdf { background: #ff6b6b; }
+        .file-badge.doc { background: #4dabf7; }
+        .file-badge.xls { background: #73d13d; }
+        .file-badge.md { background: #9254de; }
+        .doc-card .doc-meta { display:flex; flex-direction:column; }
+        .doc-card .doc-title { font-weight:600; font-size:13px; color:var(--text1); }
+        .doc-card .doc-time { font-size:11px; color:var(--text3); margin-top:4px; }
+        .recent-section { margin-top:12px; padding-top:8px; border-top:1px dashed var(--border); }
+        .recent-list { display:flex; flex-direction:column; padding-top:8px; }
+        .recent-item { padding:8px 10px; background:transparent; border:none; font-size:12px; color:var(--text2); border-radius:4px; transition: all 0.2s ease; }
+        .recent-item:hover { background:#f5f5f5; }
+
+        /* 文件预览模态(大弹窗) */
+        .file-preview-modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.45); display: flex; align-items: center; justify-content: center; z-index: 1600; }
+        .file-preview-modal { width: 90%; max-width: 1000px; max-height: 90vh; overflow: auto; background: var(--white); border-radius: 14px; box-shadow: 0 30px 80px rgba(10,30,60,0.35); padding: 20px; position: relative; }
+        .file-preview-modal .modal-header { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:12px; }
+        .file-preview-modal .modal-title { font-weight:700; font-size:16px; color:var(--text1); }
+        .file-preview-modal .modal-body { color:var(--text1); line-height:1.7; white-space:pre-wrap; font-size:14px; }
+        .file-preview-close { position:absolute; right:12px; top:12px; background:transparent;border:none;font-size:18px;cursor:pointer;color:var(--text3); }
+
+        /* 文件项操作按钮(悬浮显示) */
+        .file-item { position: relative; }
+        .file-actions { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); display: none; gap:6px; align-items:center; }
+        .file-item:hover .file-actions { display: flex; }
+        .file-actions .action-btn { background: var(--white); border: 1px solid var(--border); padding:6px; border-radius:6px; font-size:13px; cursor:pointer; display:flex; align-items:center; justify-content:center; width:34px; height:34px; box-shadow: 0 2px 6px rgba(0,0,0,0.06); }
+        .file-actions .action-btn:hover { border-color: var(--primary); color: var(--primary); }
+
+        /* 解析过程弹出框(更接近示例:大圆角、渐变背景、分段进度) */
+        .parsing-popover { position: fixed; width: 360px; background: linear-gradient(135deg, #f7fbff 0%, #e6f7ff 100%); border: 1px solid rgba(24,144,255,0.12); border-radius: 14px; box-shadow: 0 18px 48px rgba(15,35,70,0.18); z-index: 1500; padding: 14px; }
+        .parsing-popover .title { font-weight:700; margin-bottom:10px; color:var(--text1); display:flex; align-items:center; justify-content:space-between; }
+        .parsing-popover .parsing-progress { display:flex; gap:6px; margin-bottom:12px; }
+        .parsing-popover .parsing-progress .seg { flex:1; height:8px; background: rgba(255,255,255,0.6); border-radius:6px; transition: all 0.4s; box-shadow: inset 0 -2px 4px rgba(0,0,0,0.03); }
+        .parsing-popover .parsing-progress .seg.active { background: linear-gradient(90deg, rgba(24,144,255,0.95), rgba(58,150,255,0.8)); box-shadow: 0 6px 14px rgba(24,144,255,0.12); transform: translateY(-2px); }
+        .parsing-popover .steps-list { display:flex; flex-direction:column; gap:8px; margin-bottom:8px; }
+        .parsing-popover .step { display:flex; align-items:center; gap:12px; padding:10px 12px; border-radius:10px; background: rgba(255,255,255,0.6); }
+        .parsing-popover .step .dot { width:14px;height:14px;border-radius:50%;background:var(--bg); border:2px solid rgba(0,0,0,0.06); flex-shrink:0; }
+        .parsing-popover .step.completed { background: rgba(246,255,238,0.9); }
+        .parsing-popover .step.completed .dot { background: var(--success); border-color: transparent; box-shadow: 0 6px 20px rgba(82,200,26,0.12); }
+        .parsing-popover .step.active { background: rgba(240,248,255,0.95); }
+        .parsing-popover .step.active .dot { background: var(--primary); border-color: transparent; box-shadow: 0 6px 20px rgba(24,144,255,0.12); }
+        .parsing-popover .step.pending { background: rgba(250,250,250,0.9); }
+        .parsing-popover .step.pending .dot { background: #f0f0f0; border-color: rgba(0,0,0,0.06); }
+        .parsing-popover .step .label { font-size:13px; color:var(--text1); }
+        .parsing-popover .close-btn { position:absolute; right:10px; top:8px; cursor:pointer; font-size:14px; color:var(--text3); }
+
+        /* 文件分组 */
+        .file-group { margin-bottom: 16px; }
+        .file-group-header { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text3); margin-bottom: 8px; padding: 0 4px; }
+        .file-group-header .count { background: var(--bg); padding: 1px 6px; border-radius: 8px; font-size: 10px; }
+
+        /* 文件项 */
+        .file-item { display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: var(--white); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 8px; cursor: pointer; transition: all 0.2s; }
+        .file-item:hover { border-color: var(--primary); background: var(--primary-light); }
+        .file-item.active { border-color: var(--primary); background: var(--primary-light); }
+        .file-icon { font-size: 28px; flex-shrink: 0; }
+        .file-icon.pdf { color: #ff4d4f; }
+        .file-icon.docx { color: #1890ff; }
+        .file-icon.xlsx { color: #52c41a; }
+        .file-icon.md { color: #8c8c8c; }
+        .file-info { flex: 1; min-width: 0; }
+        .file-name { font-size: 12px; font-weight: 500; margin-bottom: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+        .file-meta { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--text3); }
+        .file-status { font-size: 11px; white-space: nowrap; }
+        .file-status.parsing { color: var(--primary); }
+        .file-status.done { color: var(--success); }
+
+        /* 中间编辑区 */
+        .center-panel { flex: 1; display: flex; flex-direction: column; background: var(--white); overflow: hidden; min-height: 0; height: 100%; }
+
+        /* 编辑器顶部标题栏 */
+        .editor-title-bar { padding: 16px 24px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 12px; }
+        .editor-main-title { font-size: 18px; font-weight: 600; flex: 1; cursor: pointer; }
+        /* 调整:圆角 4px,固定高度 24px,水平内边距保持 8px,垂直居中 */
+        .report-status { display:inline-block; margin-left:0; padding:0 8px; height:24px; line-height:24px; background:var(--primary-light); color:var(--primary); border-radius:4px; font-size:12px; font-weight:600; }
+        /* Icon hover tooltip */
+        .icon-tooltip {
+            position: fixed;
+            z-index: 4000;
+            background: rgba(0,0,0,0.78);
+            color: #fff;
+            padding: 6px 8px;
+            border-radius: 6px;
+            font-size: 12px;
+            pointer-events: none;
+            white-space: nowrap;
+            opacity: 0;
+            transition: opacity 120ms ease;
+        }
+        .view-toggle { display: flex; align-items: center; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
+        .view-btn { padding: 8px 16px; border: none; background: var(--white); font-size: 13px; cursor: pointer; color: var(--text2); display: flex; align-items: center; gap: 6px; transition: all 0.2s; }
+        .view-btn:first-child { border-right: 1px solid var(--border); }
+        .view-btn:hover { background: var(--bg); }
+        .view-btn.active { background: var(--primary-light); color: var(--primary); font-weight: 500; }
+        .graph-btn { width: 36px; height: 36px; border: 1px solid var(--border); background: var(--white); border-radius: 6px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 18px; margin-left: 8px; transition: all 0.2s; }
+        .graph-btn:hover { border-color: var(--primary); background: var(--primary-light); }
+        .graph-btn.active { border-color: var(--primary); background: var(--primary-light); color: var(--primary); }
+
+        /* 编辑器内容区 */
+        .editor-scroll { flex: 1; overflow-y: auto; padding: 40px 48px; }
+        .editor-content { max-width: 1000px; margin: 0 auto; }
+        .editor-content h1 { font-size: 24px; font-weight: 700; margin-bottom: 24px; color: var(--text1); }
+        .editor-content h2 { font-size: 18px; font-weight: 600; margin: 28px 0 16px; color: var(--text1); }
+        .editor-content h3 { font-size: 15px; font-weight: 600; margin: 20px 0 12px; color: var(--text1); }
+        .editor-content p { margin-bottom: 16px; line-height: 1.8; color: var(--text1); }
+
+        /* 实体高亮标记 */
+        .entity-highlight { display: inline; padding: 2px 6px; border: 1px solid var(--primary); border-radius: 4px; color: var(--primary); background: var(--primary-light); cursor: pointer; transition: all 0.2s; position: relative; }
+        .entity-highlight:hover { background: var(--primary); color: white; }
+
+        /* 不同类型实体的颜色样式,与右侧栏element-tag保持一致 */
+        .entity-highlight.entity { border-color: var(--primary); background: var(--primary-light); color: var(--primary); }
+        .entity-highlight.entity:hover { background: var(--primary); color: white; }
+
+        .entity-highlight.concept { border-color: #722ed1; background: #f9f0ff; color: #722ed1; }
+        .entity-highlight.concept:hover { background: #722ed1; color: white; }
+
+        .entity-highlight.data { border-color: var(--success); background: #f6ffed; color: var(--success); }
+        .entity-highlight.data:hover { background: var(--success); color: white; }
+
+        .entity-highlight.location { border-color: var(--warning); background: #fff7e6; color: var(--warning); }
+        .entity-highlight.location:hover { background: var(--warning); color: white; }
+
+        .entity-highlight.asset { border-color: #eb2f96; background: #fff0f6; color: #eb2f96; }
+        .entity-highlight.asset:hover { background: #eb2f96; color: white; }
+        /* 来源标识小徽章(AI / 附件 / 人工) */
+        .source-badge { display:inline-flex; align-items:center; justify-content:center; font-size:10px; padding:2px 6px; margin-left:6px; border-radius:10px; border:1px solid rgba(0,0,0,0.06); background:#fff; color:var(--text2); cursor:pointer; box-shadow:0 1px 2px rgba(0,0,0,0.04); }
+        .source-badge.ai { background: #fff7e6; color: var(--warning); border-color: rgba(255, 216, 128, 0.4); }
+        .source-badge.file { background: #f6ffed; color: var(--success); border-color: rgba(166, 230, 149, 0.45); }
+        .source-badge.manual { background: #f0f5ff; color: var(--primary); border-color: rgba(173, 199, 255, 0.45); }
+        .source-badge:hover { transform: translateY(-1px); }
+
+        /* AI优化建议卡片 */
+        .ai-suggestion-card { background: #fffbf0; border: 1px solid #ffe7ba; border-radius: 10px; padding: 16px; margin: 16px 0; }
+        .ai-suggestion-header { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
+        .ai-suggestion-title { font-size: 13px; font-weight: 600; color: var(--warning); }
+        .ai-suggestion-content { font-size: 12px; line-height: 1.7; color: var(--text1); margin-bottom: 12px; }
+        .ai-suggestion-list { list-style: none; margin-bottom: 12px; }
+        .ai-suggestion-list li { padding: 4px 0; font-size: 12px; color: var(--text2); }
+        .ai-suggestion-list li::before { content: '•'; color: var(--primary); margin-right: 8px; }
+        .ai-suggestion-actions { display: flex; gap: 8px; }
+
+        /* 数据表格 */
+        .data-table-card { background: var(--white); border: 1px solid var(--border); border-radius: 10px; margin: 16px 0; overflow: hidden; }
+        .data-table-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--border); }
+        .data-table-title { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; }
+        .data-table-source { font-size: 11px; color: var(--text3); }
+        .data-table { width: 100%; border-collapse: collapse; }
+        .data-table th { background: var(--bg); padding: 10px 16px; text-align: left; font-size: 12px; font-weight: 600; color: var(--text2); border-bottom: 1px solid var(--border); }
+        .data-table td { padding: 10px 16px; font-size: 13px; border-bottom: 1px solid var(--border); }
+        .data-table tr:last-child td { border-bottom: none; }
+        .data-table tr:hover td { background: var(--primary-light); }
+
+        /* 数据引用卡片 */
+        .data-reference-card { background: linear-gradient(135deg, #f0f9ff, #e6f7ff); border: 1px solid #bae7ff; border-radius: 10px; padding: 16px; margin: 16px 0; }
+        .reference-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
+        .reference-icon { font-size: 16px; }
+        .reference-title { font-size: 13px; font-weight: 600; color: var(--primary); }
+        .reference-content { display: flex; flex-direction: column; gap: 6px; }
+        .reference-item { display: flex; align-items: center; gap: 8px; font-size: 12px; }
+        .reference-label { color: var(--text3); font-weight: 500; min-width: 70px; }
+        .reference-value { color: var(--text1); }
+        .reference-value.success { color: var(--success); font-weight: 600; }
+
+        /* 竞争分析卡片 */
+        .competition-card { background: linear-gradient(135deg, #fffbe6, #fff7e6); border: 1px solid #ffe7ba; border-radius: 10px; padding: 16px; margin: 16px 0; }
+        .competition-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
+        .competition-icon { font-size: 16px; }
+        .competition-title { font-size: 13px; font-weight: 600; color: var(--warning); }
+        .competition-content { display: flex; flex-direction: column; gap: 10px; }
+        .competition-item { padding: 12px; background: rgba(255,255,255,0.7); border-radius: 8px; border-left: 3px solid var(--warning); }
+        .competitor-name { font-weight: 600; margin-bottom: 4px; }
+        .competitor-share { font-size: 12px; color: var(--text2); margin-bottom: 2px; }
+        .competitor-strength { font-size: 12px; color: var(--text3); }
+
+        /* AI生成内容卡片 */
+        .ai-generated-card { background: linear-gradient(135deg, #f9f0ff, #f5f0ff); border: 1px solid #efdbff; border-radius: 10px; padding: 16px; margin: 16px 0; }
+        .ai-generated-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
+        .ai-generated-icon { font-size: 16px; }
+        .ai-generated-title { font-size: 13px; font-weight: 600; color: var(--primary); }
+        .ai-generated-content { font-size: 13px; line-height: 1.6; }
+        .ai-generated-content ul { margin: 8px 0; padding-left: 20px; }
+        .ai-generated-content li { margin: 4px 0; }
+        .ai-generated-actions { display: flex; gap: 8px; margin-top: 12px; }
+
+        /* 右侧AI助手面板 */
+        .right-panel { width: 300px; background: var(--white); border-left: 1px solid var(--border); display: flex; flex-direction: column; min-height: 0; overflow: hidden; height: 100%; }
+        /* split right panel: top = report elements (~40%), bottom = AI assistant (~60%) */
+        .right-panel .element-section { flex: 4; overflow-y: auto; min-height: 0; }
+        .right-panel .ai-assistant { flex: 6; overflow-y: auto; min-height: 0; display: flex; flex-direction: column; }
+
+        /* 要素管理区 */
+        .element-section { padding: 16px; border-bottom: 1px dashed var(--border); padding-bottom: 16px !important; }
+        .element-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
+        .element-title { font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
+        .element-count { font-size: 11px; color: var(--text3); font-weight: normal; }
+
+        /* 要素标签容器 */
+        .element-tags-wrap { display: flex; flex-wrap: wrap; gap: 8px; max-height: 200px; overflow-y: auto; padding-right: 4px; padding-bottom: 16px; }
+        .element-tags-wrap::-webkit-scrollbar { width: 4px; }
+        .element-tags-wrap::-webkit-scrollbar-track { background: var(--bg); border-radius: 2px; }
+        .element-tags-wrap::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
+        .element-tags-wrap::-webkit-scrollbar-thumb:hover { background: var(--text3); }
+
+        /* 要素标签样式 */
+        .element-tag { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; background: var(--bg); border: 1px solid var(--border); border-radius: 16px; font-size: 12px; cursor: grab; transition: all 0.2s; user-select: none; }
+        .element-tag:hover { border-color: var(--primary); background: var(--primary-light); transform: translateY(-1px); }
+        .element-tag:active { cursor: grabbing; }
+        .element-tag.dragging { opacity: 0.5; }
+        .element-tag .tag-icon { font-size: 12px; }
+        .element-tag .tag-name { font-weight: 500; }
+        .element-tag.entity { border-left: 3px solid var(--primary); }
+        .element-tag.concept { border-left: 3px solid #722ed1; }
+        /* Tabs for elements */
+        .element-tabs { display:flex; gap:8px; }
+        .element-tab { padding:6px 12px; border-radius:12px; background:transparent; border:1px solid transparent; font-size:13px; cursor:pointer; color:var(--text2); }
+        .element-tab.active { background: var(--primary); color:#fff; border-color: rgba(0,0,0,0.04); box-shadow: 0 6px 18px rgba(17,24,39,0.06); }
+
+        /* Tag shape / size rules */
+        .element-tag { height:28px; padding:0 12px; border-radius:2px; display:inline-flex; align-items:center; }
+        .element-tag .tag-name { line-height:28px; }
+        .element-tag.dynamic { border-radius:14px; } /* rounded for dynamic */
+        .element-tag.static { border-radius:2px; }   /* slightly rounded for static */
+        /* module title style (icon + text), placed above header */
+        .module-title { display:flex; align-items:center; gap:10px; font-size:15px; font-weight:700; color:var(--text1); padding:0; margin-bottom:10px; }
+        .module-title .module-icon { width:36px; height:36px; border-radius:8px; background: var(--primary-gradient); display:flex; align-items:center; justify-content:center; font-size:18px; color:white; box-shadow: 0 6px 18px rgba(0,0,0,0.06); }
+        .element-tag.data { border-left: 3px solid var(--success); }
+        .element-tag.location { border-left: 3px solid var(--warning); }
+        .element-tag.asset { border-left: 3px solid #eb2f96; }
+
+        .element-hint { font-size: 11px; color: var(--text3); margin-top: 10px; text-align: center; }
+
+        /* 要素详情弹出框 */
+        .element-popover { position: fixed; width: 280px; background: var(--white); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.15); z-index: 2000; display: none; }
+        .element-popover.show { display: block; }
+        .popover-header { padding: 12px 14px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 10px; }
+        .popover-icon { width: 32px; height: 32px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 16px; }
+        .popover-icon.entity { background: linear-gradient(135deg, #e6f7ff, #bae7ff); }
+        .popover-icon.data { background: linear-gradient(135deg, #f6ffed, #d9f7be); }
+        .popover-icon.location { background: linear-gradient(135deg, #fff7e6, #ffe7ba); }
+        .popover-icon.asset { background: linear-gradient(135deg, #fff0f6, #ffd6e7); }
+        .popover-title { font-size: 14px; font-weight: 600; flex: 1; }
+        .popover-close { width: 24px; height: 24px; border: none; background: var(--bg); border-radius: 50%; cursor: pointer; font-size: 12px; }
+        .popover-close:hover { background: var(--danger); color: white; }
+        .popover-body { padding: 14px; }
+        .popover-section { margin-bottom: 10px; }
+        .popover-section:last-child { margin-bottom: 0; }
+        .popover-label { font-size: 10px; color: var(--text3); margin-bottom: 4px; text-transform: uppercase; }
+        .popover-value { font-size: 12px; color: var(--text1); }
+        .popover-relations { display: flex; flex-wrap: wrap; gap: 6px; }
+        .popover-relation { padding: 4px 8px; background: var(--bg); border-radius: 4px; font-size: 11px; cursor: pointer; }
+        .popover-relation:hover { background: var(--primary-light); color: var(--primary); }
+        .popover-actions { display: flex; gap: 8px; margin-top: 12px; }
+        .popover-actions .btn { flex: 1; justify-content: center; font-size: 12px; }
+
+        /* AI助手区 */
+        .ai-assistant { position: relative; flex: 1; display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
+        .ai-header { padding: 12px 16px; border-bottom: none; display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
+        .ai-avatar-sm { width: 36px; height: 36px; background: var(--ai-gradient); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
+        .ai-info { flex: 1; }
+        .ai-name { font-size: 15px; font-weight: 600; }
+        .ai-status { font-size: 11px; color: var(--success); }
+        /* Hide AI subtitle and tabs per user request */
+        .ai-info .ai-status { display: none; }
+        .ai-tabs { display: none !important; }
+
+        /* AI Tab切换 */
+        .ai-tabs { display: flex; border-bottom: 1px solid var(--border); flex-shrink: 0; }
+        .ai-tab { flex: 1; padding: 10px; text-align: center; font-size: 12px; cursor: pointer; color: var(--text2); border-bottom: 2px solid transparent; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 4px; }
+        .ai-tab:hover { color: var(--primary); }
+        .ai-tab.active { color: var(--primary); border-bottom-color: var(--primary); }
+
+        /* AI消息区 */
+        /* 消息区:为固定在底部的输入区预留底部空间,避免遮挡最后一条消息 */
+        .ai-messages { flex: 1; overflow-y: auto; padding: 16px; padding-bottom: 96px; min-height: 0; }
+        .msg { display: flex; gap: 10px; margin-bottom: 16px; }
+        .msg.user { flex-direction: row-reverse; }
+        .msg-avatar { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; flex-shrink: 0; }
+        .msg.ai .msg-avatar { background: var(--ai-gradient); color: white; }
+        .msg.user .msg-avatar { background: var(--primary); color: white; }
+        .msg-bubble { max-width: 85%; padding: 10px 14px; border-radius: 12px; font-size: 13px; line-height: 1.6; }
+        .msg.ai .msg-bubble { background: var(--bg); border-radius: 4px 12px 12px 12px; }
+        .msg.user .msg-bubble { background: var(--primary); color: white; border-radius: 12px 4px 12px 12px; }
+
+        /* AI输入区 */
+        /* 输入区固定在 AI 面板底部,不随消息滚动 */
+        .ai-input-area { padding: 12px 16px; border-top: none; background: var(--white); flex-shrink: 0; position: absolute; left: 0; right: 0; bottom: 0; z-index: 4; }
+        .ai-input-box { background: var(--bg); border: 1px solid var(--border); border-radius: 20px; transition: all 0.2s; }
+        .ai-input-box:focus-within { border-color: var(--primary); background: var(--white); box-shadow: 0 0 0 3px rgba(24,144,255,0.1); }
+        .ai-input-box textarea { width: 100%; border: none; background: transparent; resize: none; outline: none; font-size: 13px; line-height: 1.5; padding: 10px 16px; min-height: 40px; max-height: 80px; font-family: inherit; border-radius: 20px; display: block; }
+        .ai-input-box textarea::placeholder { color: var(--text3); font-size: 14px; }
+        /* 输入区内布局:左侧图标、中心输入、右侧操作(语音/发送) */
+        /* Cursor-like AI input: larger rounded, subtle shadow, inline icons */
+        .ai-input-inner { display:flex; align-items:center; gap:8px; }
+        .ai-input-left, .ai-input-right { display:flex; gap:6px; align-items:center; flex-shrink:0; }
+        .ai-input-box { flex:1; background:var(--white); border:1px solid var(--border); border-radius:8px; padding:8px 10px; box-shadow: 0 6px 18px rgba(16,24,40,0.06); display:flex; flex-direction:column; gap:6px; }
+        .ai-input-label { font-size:12px; color:var(--text3); }
+        .ai-input-row { display:flex; flex-direction:column; gap:6px; }
+        .ai-input-row .ai-input-top { display:flex; align-items:center; gap:8px; }
+        .ai-input-row textarea { flex:1; width:100%; border:none; outline:none; resize:none; font-size:14px; color:var(--text1); background:transparent; line-height:1.4; padding:6px 12px; min-height:20px; max-height:160px; }
+        .ai-input-toolbar { display:flex; align-items:center; justify-content:space-between; gap:8px; height:28px; }
+        .ai-input-toolbar .left, .ai-input-toolbar .right { display:flex; gap:12px; align-items:center; }
+        .ai-input-box textarea::placeholder { color:var(--text3); }
+        .ai-input-left .ai-icon-btn, .ai-input-right .ai-icon-btn { width:24px; height:24px; border-radius:4px; border:none; background:transparent; display:flex; align-items:center; justify-content:center; cursor:pointer; font-size:12px; color:#8c8c8c; padding:0; transition: all 0.2s ease; }
+        .ai-input-left .ai-icon-btn:hover, .ai-input-right .ai-icon-btn:hover { background:#f0f0f0; border-color:transparent; color:#555555; }
+        .ai-send-btn { width:24px; height:24px; border-radius:4px; border:none; background:#f0f0f0; display:flex; align-items:center; justify-content:center; cursor:pointer; font-size:12px; color:#555555; transition: all 0.18s; box-shadow:none; padding:0; }
+        .ai-send-btn:hover { background:#1890ff; color:#ffffff; }
+        .ai-send-btn.active { background: var(--primary); color: white; box-shadow: 0 6px 18px rgba(24,144,255,0.16); transform: translateY(-1px); }
+        .ai-input-caption { font-size:13px; color:var(--text3); margin-bottom:6px; padding-left:6px; }
+        .ai-input-caption .ai-highlight { color: var(--primary); font-weight:600; margin-left:6px; }
+        .ai-input-hint { display: flex; align-items: center; justify-content: space-between; padding: 8px 4px 0; font-size: 10px; color: var(--text3); }
+
+        /* 动画 */
+        @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
+        .parsing-anim { animation: pulse 1.5s infinite; }
+
+        /* 可编辑内容区 */
+        .editor-content[contenteditable="true"] { outline: none; }
+        .editor-content[contenteditable="true"]:focus { background: #fafbfc; box-shadow: inset 0 0 0 2px var(--primary-light); }
+        .editor-content[contenteditable="true"] ::selection { background: rgba(24,144,255,0.3); border-radius: 2px; }
+
+        /* 文本编辑选中效果 */
+        .editor-content[contenteditable="true"]:focus p { position: relative; }
+        .editor-content[contenteditable="true"]:focus p::before {
+            content: '';
+            position: absolute;
+            left: -20px;
+            top: 0;
+            bottom: 0;
+            width: 3px;
+            background: var(--primary);
+            border-radius: 2px;
+            opacity: 0;
+            transition: opacity 0.2s;
+        }
+        .editor-content[contenteditable="true"]:focus p:hover::before {
+            opacity: 0.5;
+        }
+        .editor-content[contenteditable="true"]:focus p.selected::before {
+            opacity: 1;
+        }
+
+        /* 右键菜单 */
+        .context-menu { position: fixed; min-width: 180px; background: var(--white); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.15); z-index: 3000; display: none; overflow: hidden; }
+        .context-menu.show { display: block; }
+        .context-menu-item { display: flex; align-items: center; gap: 10px; padding: 10px 14px; font-size: 13px; cursor: pointer; transition: all 0.15s; }
+        .context-menu-item:hover { background: var(--primary-light); color: var(--primary); }
+        .context-menu-item .icon { font-size: 14px; width: 20px; text-align: center; }
+        .context-menu-item .shortcut { margin-left: auto; font-size: 11px; color: var(--text3); }
+        .context-menu-divider { height: 1px; background: var(--border); margin: 4px 0; }
+
+        /* 数据关系表弹窗 */
+        .data-relation-modal { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: none; align-items: center; justify-content: center; z-index: 1300; }
+        .data-relation-modal.show { display: flex; }
+        .data-relation-card { width: 600px; max-width: 90vw; background: var(--white); border-radius: 16px; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,0.3); }
+        .data-relation-header { padding: 20px; background: linear-gradient(135deg, #f0f7ff, #f5f0ff); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 15px; }
+        .data-relation-icon { width: 48px; height: 48px; background: var(--white); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 24px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
+        .data-relation-title { flex: 1; }
+        .data-relation-title h3 { font-size: 16px; font-weight: 600; margin-bottom: 4px; }
+        .data-relation-title span { font-size: 12px; color: var(--text3); }
+        .data-relation-close { width: 32px; height: 32px; border: none; background: rgba(0,0,0,0.05); border-radius: 50%; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; }
+        .data-relation-close:hover { background: var(--danger); color: white; }
+
+        .data-relation-body { padding: 20px; max-height: 60vh; overflow-y: auto; }
+        .relation-section { margin-bottom: 24px; }
+        .relation-section:last-child { margin-bottom: 0; }
+        .relation-label { font-size: 14px; font-weight: 600; margin-bottom: 12px; color: var(--text1); display: flex; align-items: center; gap: 6px; }
+
+        .relation-table { width: 100%; border-collapse: collapse; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
+        .relation-table th { background: var(--bg); padding: 12px; text-align: left; font-size: 12px; font-weight: 600; color: var(--text2); border-bottom: 1px solid var(--border); }
+        .relation-table td { padding: 12px; border-bottom: 1px solid var(--border); font-size: 13px; }
+        .relation-table tr:last-child td { border-bottom: none; }
+        .relation-table tr:hover td { background: var(--primary-light); }
+
+        .relation-input { width: 100%; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; font-size: 12px; outline: none; }
+        .relation-input:focus { border-color: var(--primary); }
+
+        .relation-tags { display: flex; flex-wrap: wrap; gap: 8px; }
+        .relation-tag { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; font-size: 11px; cursor: pointer; transition: all 0.2s; }
+        .relation-tag:hover { background: var(--primary-light); border-color: var(--primary); }
+
+        .data-relation-footer { padding: 16px 20px; background: var(--bg); border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 10px; }
+
+        /* 拖拽提示 */
+        .editor-content.drag-over { background: linear-gradient(135deg, rgba(24,144,255,0.05), rgba(24,144,255,0.1)); }
+        .editor-content.drag-over::after { content: '释放鼠标插入要素'; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 12px 24px; background: var(--primary); color: white; border-radius: 8px; font-size: 14px; z-index: 100; }
+        /* 报告要素弹窗样式 */
+        .report-elements-modal { position: fixed; inset: 0; display: none; align-items: center; justify-content: center; z-index: 2200; }
+        .report-elements-modal.show { display: flex; }
+        .report-elements-card { width: 960px; max-width: 96vw; max-height: 80vh; background: var(--white); border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); overflow: hidden; display:flex; flex-direction:column; }
+        .report-elements-header { padding: 12px 16px; border-bottom: 1px solid var(--border); display:flex; align-items:center; gap:12px; }
+        .report-elements-title { font-size: 16px; font-weight:700; flex:1; }
+        .report-elements-body { padding: 12px 16px; overflow:auto; flex:1; }
+        .report-elements-footer { padding: 12px 16px; border-top:1px solid var(--border); display:flex; gap:8px; justify-content:flex-end; background:var(--bg); }
+        .elements-table { width:100%; border-collapse: collapse; }
+        .elements-table th, .elements-table td { padding:8px 10px; text-align:left; border-bottom:1px solid var(--border); font-size:13px; vertical-align:middle; }
+        .elements-table th { background: var(--bg); font-weight:600; font-size:12px; color:var(--text2); }
+        .elements-search { display:flex; gap:8px; align-items:center; }
+        .elements-search input { padding:8px 10px; border:1px solid var(--border); border-radius:6px; width:260px; }
+        .elements-actions .icon-btn { padding: 0; border-radius: 4px; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; }
+        /* pager styles */
+        .pager { display:flex; gap:6px; align-items:center; }
+        .pager-btn { padding:6px 10px; border:1px solid var(--border); background:var(--white); border-radius:6px; cursor:pointer; font-size:13px; }
+        .pager-btn.active { background:var(--primary); color:white; border-color:var(--primary); }
+        .page-size-select { padding:6px 8px; border:1px solid var(--border); border-radius:6px; background:var(--white); }
+
+        /* Toast容器 */
+        .toast-container { position: fixed; top: 70px; right: 24px; z-index: 3000; display: flex; flex-direction: column; gap: 8px; }
+        .toast { display: flex; align-items: center; gap: 10px; padding: 12px 18px; background: var(--white); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.15); transform: translateX(120%); transition: transform 0.3s; min-width: 240px; }
+        .toast.show { transform: translateX(0); }
+        .toast.success { border-left: 4px solid var(--success); }
+        .toast.error { border-left: 4px solid var(--danger); }
+        .toast.warning { border-left: 4px solid var(--warning); }
+        .toast.info { border-left: 4px solid var(--primary); }
+
+        /* 通知面板 */
+        .notif-panel { position: fixed; top: 56px; right: 0; width: 360px; height: calc(100vh - 56px); background: var(--white); box-shadow: -4px 0 16px rgba(0,0,0,0.1); transform: translateX(100%); transition: transform 0.3s; z-index: 999; display: flex; flex-direction: column; }
+
+        /* 遮罩 */
+        .overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.3); z-index: 998; display: none; }
+        .kg-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 1199; display: none; }
+
+        /* 导出菜单 */
+        .export-menu { position: fixed; background: var(--white); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.15); min-width: 180px; display: none; z-index: 2001; overflow: hidden; }
+
+        /* 要素关系图谱弹窗 */
+        .knowledge-graph-modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 1200px; height: 80%; max-height: 700px; background: var(--white); border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); display: none; flex-direction: column; z-index: 1200; overflow: hidden; }
+        .knowledge-graph-modal.show { display: flex; }
+
+        .kg-header { padding: 16px 20px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; background: linear-gradient(135deg, #f0f7ff, #f5f0ff); }
+        .kg-title { display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 600; color: var(--primary); }
+        .kg-icon { font-size: 20px; }
+        .kg-controls { display: flex; align-items: center; gap: 12px; }
+        .kg-view-toggle { display: flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
+        .kg-view-btn { padding: 6px 12px; border: none; background: var(--white); font-size: 12px; cursor: pointer; color: var(--text2); display: flex; align-items: center; gap: 4px; transition: all 0.2s; }
+        .kg-view-btn:first-child { border-right: 1px solid var(--border); }
+        .kg-view-btn:hover { background: var(--bg); }
+        .kg-view-btn.active { background: var(--primary-light); color: var(--primary); }
+        .kg-close { width: 28px; height: 28px; border: none; background: rgba(0,0,0,0.05); border-radius: 50%; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; }
+        .kg-close:hover { background: var(--danger); color: white; }
+
+        .kg-content { flex: 1; overflow: hidden; }
+
+        /* 图谱视图 */
+        .kg-graph-view { height: 100%; display: flex; flex-direction: column; }
+        .graph-canvas { flex: 1; position: relative; background: linear-gradient(45deg, #f8f9fa 25%, transparent 25%), linear-gradient(-45deg, #f8f9fa 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f8f9fa 75%), linear-gradient(-45deg, transparent 75%, #f8f8f8 75%); background-size: 20px 20px; background-position: 0 0, 0 10px, 10px -10px, -10px 0px; }
+        .graph-node { position: absolute; width: 120px; padding: 12px; background: var(--white); border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); cursor: pointer; transition: all 0.3s; border: 2px solid transparent; text-align: center; }
+        .graph-node:hover { transform: scale(1.05); box-shadow: 0 8px 24px rgba(0,0,0,0.2); }
+        .graph-node.core { border-color: var(--primary); background: linear-gradient(135deg, #f0f7ff, #e6f7ff); }
+        .graph-node.concept { border-color: #722ed1; background: linear-gradient(135deg, #f9f0ff, #efdbff); }
+        .graph-node.data { border-color: var(--success); background: linear-gradient(135deg, #f6ffed, #d9f7be); }
+        .graph-node.location { border-color: var(--warning); background: linear-gradient(135deg, #fff7e6, #ffe7ba); }
+        .graph-node.highlighted { border-color: var(--danger); box-shadow: 0 0 20px rgba(255,77,79,0.4); transform: scale(1.1); }
+        .node-icon { font-size: 24px; margin-bottom: 6px; }
+        .node-label { font-size: 12px; font-weight: 600; margin-bottom: 4px; }
+        .node-type { font-size: 10px; color: var(--text3); }
+        .graph-lines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
+
+        .graph-legend { padding: 12px 16px; background: var(--bg); border-top: 1px solid var(--border); display: flex; gap: 16px; justify-content: center; }
+        .legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text2); }
+        .legend-dot { width: 12px; height: 12px; border-radius: 50%; }
+        .legend-dot.core { background: var(--primary); }
+        .legend-dot.concept { background: #722ed1; }
+        .legend-dot.data { background: var(--success); }
+        .legend-dot.location { background: var(--warning); }
+
+        /* 列表视图 */
+        .kg-list-view { height: 100%; display: flex; flex-direction: column; }
+        .list-search { padding: 16px; border-bottom: 1px solid var(--border); }
+        .list-search-input { width: 100%; padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px; outline: none; }
+        .list-search-input:focus { border-color: var(--primary); }
+
+        .entity-categories { flex: 1; overflow-y: auto; }
+        .category-section { margin-bottom: 16px; }
+        .category-header { padding: 12px 16px; background: var(--bg); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--text1); }
+        .category-icon { font-size: 16px; }
+        .entity-item { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--border); cursor: pointer; transition: all 0.2s; }
+        .entity-item:hover { background: var(--primary-light); }
+        .entity-item:last-child { border-bottom: none; }
+        .entity-icon { width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
+        .entity-info { flex: 1; }
+        .entity-name { font-size: 13px; font-weight: 600; margin-bottom: 4px; }
+        .entity-meta { font-size: 11px; color: var(--text3); }
+        .entity-actions { display: flex; gap: 4px; }
+        .entity-action-btn { width: 24px; height: 24px; border: none; background: transparent; border-radius: 4px; cursor: pointer; font-size: 12px; display: flex; align-items: center; justify-content: center; transition: all 0.2s; }
+        .entity-action-btn:hover { background: var(--bg); }
+
+        /* 确认对话框 */
+        .confirm-dialog { position: fixed; inset: 0; background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; z-index: 1400; opacity: 0; transition: opacity 0.3s; }
+        .confirm-dialog.show { opacity: 1; }
+        .confirm-content { background: var(--white); border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); min-width: 400px; max-width: 500px; overflow: hidden; transform: scale(0.9); transition: transform 0.3s; }
+        .confirm-dialog.show .confirm-content { transform: scale(1); }
+        .confirm-header { padding: 20px; background: linear-gradient(135deg, #f0f7ff, #f5f0ff); border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
+        .confirm-header h3 { font-size: 16px; font-weight: 600; margin: 0; }
+        .confirm-close { width: 32px; height: 32px; border: none; background: rgba(0,0,0,0.05); border-radius: 50%; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; }
+        .confirm-close:hover { background: var(--danger); color: white; }
+        .confirm-body { padding: 20px; font-size: 14px; line-height: 1.6; color: var(--text1); }
+        .confirm-footer { padding: 16px 20px; background: var(--bg); border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 10px; }
+
+        /* 响应式 */
+        @media (max-width: 1024px) {
+            .sidebar { width: 200px; }
+            .main { margin-left: 200px; }
+            .editor-body { flex-direction: column; }
+            .left-panel, .right-panel { width: 100%; height: auto; max-height: 300px; }
+            .knowledge-graph-modal { width: 100%; }
+            .data-relation-modal { width: 95%; }
+            .confirm-content { min-width: 320px; }
+        }
+    </style>
+    <script>
+        // === 标题同步:将正文 H1 的文字同步到编辑器顶部小标题与输入中 ===
+        function syncEditorTitleFromContent() {
+            try {
+                const h1 = document.querySelector('.editor-content h1');
+                const toolbarTitle = document.querySelector('.editor-main-title');
+                const titleInput = document.querySelector('.report-title-input');
+                if (h1 && toolbarTitle) {
+                    const txt = h1.textContent.trim();
+                    toolbarTitle.textContent = txt;
+                    if (titleInput) titleInput.value = txt;
+                }
+            } catch (e) {
+                console.warn('syncEditorTitleFromContent error', e);
+            }
+        }
+
+        // 同步一次并监听内容变化(以 H1 变动为触发器)
+        document.addEventListener('DOMContentLoaded', function() {
+            syncEditorTitleFromContent();
+            const h1 = document.querySelector('.editor-content h1');
+            if (h1) {
+                const ro = new MutationObserver(() => syncEditorTitleFromContent());
+                ro.observe(h1, { characterData: true, childList: true, subtree: true });
+            }
+        });
+    </script>
+</head>
+<body>
+    <!-- 全局头部 -->
+    <header class="topbar" id="topbar">
+        <div class="topbar-left">
+            <div class="logo">灵</div>
+            <div class="brand">灵越智报</div>
+        </div>
+        <div class="topbar-right">
+            <button class="icon-btn" title="搜索"><i class="iconfont icon-SEARCH"></i></button>
+            <button class="icon-btn notif-btn" title="通知"><i class="iconfont icon-MESSAGE_NOTIFICATION_L"></i><span class="badge">3</span></button>
+            <div class="avatar">张</div>
+            <div class="username">张三</div>
+        </div>
+    </header>
+    <style>
+        .topbar {
+            height: 56px;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            padding: 0 18px;
+            background: var(--white);
+            border-bottom: 1px solid var(--border);
+            gap: 12px;
+            position: sticky;
+            top: 0;
+            z-index: 50;
+        }
+        .topbar-left { display:flex;align-items:center;gap:10px;min-width:180px; }
+        .logo {
+            width:36px;height:36px;border-radius:8px;background:linear-gradient(135deg,var(--primary) 0%, #69c0ff 100%);display:flex;align-items:center;justify-content:center;color:white;font-weight:700;font-size:18px;
+        }
+        .brand { font-weight:600;color:var(--text); font-size:16px; }
+        .topbar-center { display:none; }
+        .topbar-right { display:flex; align-items:center; gap:8px; min-width:auto; justify-content:flex-end; }
+        .topbar-right .notif-btn { margin-right: 8px; }
+        .avatar { width:28px;height:28px;border-radius:50%;background:var(--primary);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px; margin-right: 0; }
+        .username { color:var(--text); font-size:13px; margin-left: -4px; }
+        .icon-btn {
+            background: transparent;
+            border: none;
+            cursor: pointer;
+            font-size: 16px;
+            position: relative;
+            color: #8c8c8c;
+            width: 24px;
+            height: 24px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            border-radius: 4px;
+            transition: all 0.2s ease;
+        }
+        .icon-btn:hover {
+            background: #f0f0f0;
+            color: #555555;
+        }
+        .icon-btn .badge { position:absolute; top:-6px; right:-6px; background:var(--danger); color:white; border-radius:10px; font-size:11px; padding:2px 6px; }
+        @media (max-width: 900px) {
+            .brand { display:none; }
+        }
+    </style>
+
+    <!-- 侧边栏 -->
+    <aside class="sidebar" id="sidebar">
+        <nav class="sidebar-menu">
+            <!-- 报告编辑入口已移除,页面打开时直接进入编辑器 -->
+        </nav>
+    </aside>
+
+    <!-- 主内容区 -->
+    <main class="main" id="mainContent" style="display:none;">
+        <!-- 首页 -->
+        <div class="page" id="page-home">
+            <div class="welcome">
+                <h1>早上好,张三!<span>智能报告,洞察未来。</span></h1>
+                <p>今天是个创作的好日子,开始您的智能报告之旅吧</p>
+            </div>
+
+            <div class="stats-grid">
+                <div class="stat-card card" onclick="void(0)">
+                    <div class="stat-icon blue">📄</div>
+                    <div class="stat-value">12</div>
+                    <div class="stat-label">我的报告</div>
+                    <div class="stat-trend up">↑ 3 本周新增</div>
+                </div>
+                <div class="stat-card card" onclick="void(0)">
+                    <div class="stat-icon purple">🎨</div>
+                    <div class="stat-value">15</div>
+                    <div class="stat-label">可用模板</div>
+                    <div class="stat-trend up">↑ 2 新增</div>
+                </div>
+                <div class="stat-card card">
+                    <div class="stat-icon green">📚</div>
+                    <div class="stat-value">48</div>
+                    <div class="stat-label">知识文档</div>
+                    <div class="stat-trend">📁 1.2GB</div>
+                </div>
+                <div class="stat-card card" onclick="toggleFab()">
+                    <div class="stat-icon orange">💰</div>
+                    <div class="stat-value">¥127.50</div>
+                    <div class="stat-label">本月消耗</div>
+                    <div class="stat-trend">↓ 12%</div>
+                </div>
+            </div>
+
+            <!-- AI对话入口 -->
+            <div class="ai-card card">
+                <div class="ai-welcome">
+                    <div class="ai-avatar">🤖</div>
+                    <div class="ai-title">你好!我是灵越AI助手,可以帮你:</div>
+                    <ul class="ai-list">
+                        <li>快速生成各类报告</li>
+                        <li>分析和解读数据</li>
+                        <li>回答业务相关问题</li>
+                    </ul>
+                    <div class="ai-tip">试试输入:"帮我生成一份智慧园区建设项目可行性研究报告"</div>
+                </div>
+                <div class="ai-input-wrap">
+                    <input type="text" class="ai-input" placeholder="输入您的需求,或 @知识库 引用资料..." id="homeAiInput" oninput="toggleSendBtn()">
+                    <div class="ai-input-btns">
+                        <button class="ai-input-btn">🎤</button>
+                        <button class="ai-input-btn">📎</button>
+                        <button class="ai-input-btn send" id="homeSendBtn" onclick="handleHomeAi()">➤</button>
+                    </div>
+                </div>
+                <div class="thinking-modes">
+                    <div class="mode-btn active" onclick="setMode(this)">🧠 深度思考</div>
+                    <div class="mode-btn" onclick="setMode(this)">⚡ 快速回答</div>
+                    <div class="mode-btn" onclick="setMode(this)">🌐 联网搜索</div>
+                    <div class="mode-btn" onclick="setMode(this)">📊 数据分析</div>
+                </div>
+            </div>
+
+            <!-- 模板推荐区 -->
+            <div class="section-header">
+                <h2 class="section-title">📋 推荐模板</h2>
+                <span class="section-link" onclick="void(0)">查看全部 →</span>
+            </div>
+            <div class="tpl-grid">
+                <div class="tpl-card card" onclick="void(0)">
+                    <div class="tpl-preview">📊</div>
+                    <div class="tpl-info">
+                        <div class="tpl-name">市场分析报告</div>
+                        <div class="tpl-meta"><span>📊 128次</span><span>⭐ 4.8</span></div>
+                        <div class="tpl-tags"><span class="tpl-tag">官方</span><span class="tpl-tag hot">热门</span></div>
+                        <button class="tpl-btn">使用此模板</button>
+                    </div>
+                </div>
+                <div class="tpl-card card" onclick="void(0)">
+                    <div class="tpl-preview">🏢</div>
+                    <div class="tpl-info">
+                        <div class="tpl-name">可行性研究报告</div>
+                        <div class="tpl-meta"><span>📊 96次</span><span>⭐ 4.9</span></div>
+                        <div class="tpl-tags"><span class="tpl-tag">官方</span><span class="tpl-tag hot">热门</span></div>
+                        <button class="tpl-btn">使用此模板</button>
+                    </div>
+                </div>
+                <div class="tpl-card card" onclick="void(0)">
+                    <div class="tpl-preview">📅</div>
+                    <div class="tpl-info">
+                        <div class="tpl-name">项目周报</div>
+                        <div class="tpl-meta"><span>📊 256次</span><span>⭐ 4.9</span></div>
+                        <div class="tpl-tags"><span class="tpl-tag">官方</span></div>
+                        <button class="tpl-btn">使用此模板</button>
+                    </div>
+                </div>
+            </div>
+
+            <div class="quick-actions">
+                <div class="quick-action" onclick="showToast('上传模板', 'info')">
+                    <div class="quick-action-icon">📤</div>
+                    <span>上传新模板</span>
+                </div>
+                <div class="quick-action" onclick="showToast('创建模板', 'info')">
+                    <div class="quick-action-icon">🛠️</div>
+                    <span>创建新模板</span>
+                </div>
+            </div>
+        </div>
+
+        <!-- 报告记录页 -->
+        <div class="page" id="page-reports">
+            <h2>📋 报告记录</h2>
+            <div style="display:flex;gap:12px;margin:16px 0;">
+                <select style="padding:8px 12px;border:1px solid var(--border);border-radius:6px;font-size:13px;background:var(--white);"><option>全部状态</option><option>初稿</option><option>审核中</option><option>已定稿</option></select>
+                <input type="text" placeholder="🔍 搜索报告..." style="flex:1;max-width:280px;padding:8px 12px;border:1px solid var(--border);border-radius:6px;font-size:13px;">
+                <div style="margin-left:auto;display:flex;gap:6px;">
+                    <button class="btn" style="background:var(--primary-light);border-color:var(--primary);color:var(--primary)">全部</button>
+                    <button class="btn">本周</button>
+                    <button class="btn">本月</button>
+                </div>
+            </div>
+            <div style="display:flex;flex-direction:column;gap:12px;">
+                <div class="card" style="padding:18px;">
+                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:10px;">
+                        <span style="font-size:22px;">📄</span>
+                        <span style="flex:1;font-size:15px;font-weight:600;">智慧园区建设项目可行性研究报告</span>
+                        <span style="padding:4px 10px;background:#f6ffed;color:var(--success);border-radius:12px;font-size:11px;">已定稿</span>
+                    </div>
+                    <div style="display:flex;gap:20px;font-size:12px;color:var(--text2);margin-bottom:12px;">
+                        <span>📅 2025-12-30</span><span>👤 张三</span><span>🏢 华南事业部</span>
+                    </div>
+                <div style="display:flex;gap:8px;">
+                        <button class="btn btn-primary" onclick="void(0)">查看</button>
+                        <button class="btn" onclick="void(0)">编辑</button>
+                        <button class="btn" onclick="showToast('导出PDF成功', 'success')">导出</button>
+                    </div>
+                </div>
+                <div class="card" style="padding:18px;">
+                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:10px;">
+                        <span style="font-size:22px;">📄</span>
+                        <span style="flex:1;font-size:15px;font-weight:600;">Q4市场分析报告</span>
+                        <span style="padding:4px 10px;background:#fffbe6;color:var(--warning);border-radius:12px;font-size:11px;">审核中</span>
+                    </div>
+                    <div style="display:flex;gap:20px;font-size:12px;color:var(--text2);margin-bottom:12px;">
+                        <span>📅 2025-12-28</span><span>👤 张三</span>
+                    </div>
+                    <div style="display:flex;gap:8px;">
+                        <button class="btn btn-primary" onclick="void(0)">查看</button>
+                        <button class="btn" onclick="showToast('已发送催办', 'success')">催办</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <!-- 模板管理页 -->
+        <div class="page" id="page-templates">
+            <h2>🎨 模板管理</h2>
+            <div style="display:flex;gap:12px;margin:16px 0;">
+                <input type="text" placeholder="🔍 搜索模板..." style="width:280px;padding:8px 12px;border:1px solid var(--border);border-radius:6px;font-size:13px;">
+                <div style="display:flex;gap:6px;">
+                    <span style="padding:8px 16px;background:var(--primary);color:white;border-radius:18px;font-size:12px;cursor:pointer;">全部</span>
+                    <span style="padding:8px 16px;background:var(--bg);border-radius:18px;font-size:12px;cursor:pointer;" onclick="showToast('官方模板', 'info')">官方模板</span>
+                    <span style="padding:8px 16px;background:var(--bg);border-radius:18px;font-size:12px;cursor:pointer;" onclick="showToast('我的模板', 'info')">我的模板</span>
+                </div>
+                <button class="btn btn-primary" style="margin-left:auto;">➕ 创建模板</button>
+            </div>
+            <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:14px;">
+                <div class="tpl-card card" onclick="void(0)"><div class="tpl-preview">📊</div><div class="tpl-info"><div class="tpl-name">市场分析报告</div><div class="tpl-meta"><span>📊 128次</span></div><div class="tpl-tags"><span class="tpl-tag">官方</span><span class="tpl-tag hot">热门</span></div><button class="tpl-btn">使用</button></div></div>
+                <div class="tpl-card card" onclick="void(0)"><div class="tpl-preview">🏢</div><div class="tpl-info"><div class="tpl-name">可行性研究报告</div><div class="tpl-meta"><span>📊 96次</span></div><div class="tpl-tags"><span class="tpl-tag">官方</span></div><button class="tpl-btn">使用</button></div></div>
+                <div class="tpl-card card" onclick="void(0)"><div class="tpl-preview">📅</div><div class="tpl-info"><div class="tpl-name">项目周报</div><div class="tpl-meta"><span>📊 256次</span></div><div class="tpl-tags"><span class="tpl-tag">官方</span></div><button class="tpl-btn">使用</button></div></div>
+                <div class="tpl-card card" onclick="void(0)"><div class="tpl-preview">💼</div><div class="tpl-info"><div class="tpl-name">尽职调查报告</div><div class="tpl-meta"><span>📊 45次</span></div><div class="tpl-tags"><span class="tpl-tag">行业</span></div><button class="tpl-btn">使用</button></div></div>
+            </div>
+        </div>
+
+        <!-- 数据源管理页 -->
+        <div class="page" id="page-datasources">
+            <h2>🔗 数据源管理</h2>
+            <div style="display:flex;gap:12px;margin:16px 0;">
+                <input type="text" placeholder="🔍 搜索数据源..." style="width:280px;padding:8px 12px;border:1px solid var(--border);border-radius:6px;font-size:13px;">
+                <button class="btn btn-primary" style="margin-left:auto;">➕ 添加数据源</button>
+            </div>
+            <div style="display:flex;flex-direction:column;gap:12px;">
+                <div class="card" style="padding:18px;">
+                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
+                        <div style="width:44px;height:44px;background:var(--primary-light);border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:22px;">🗄️</div>
+                        <div style="flex:1;"><div style="font-size:15px;font-weight:600;">销售数据库</div><div style="font-size:12px;color:var(--text3);">MySQL · db.company.com:3306</div></div>
+                        <div style="font-size:12px;color:var(--success);">● 已连接</div>
+                    </div>
+                    <div style="display:flex;gap:8px;"><button class="btn">测试连接</button><button class="btn">同步数据</button><button class="btn">查看数据表</button></div>
+                </div>
+                <div class="card" style="padding:18px;">
+                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
+                        <div style="width:44px;height:44px;background:#f6ffed;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:22px;">🌐</div>
+                        <div style="flex:1;"><div style="font-size:15px;font-weight:600;">市场数据API</div><div style="font-size:12px;color:var(--text3);">REST API · api.marketdata.com</div></div>
+                        <div style="font-size:12px;color:var(--success);">● 已连接</div>
+                    </div>
+                    <div style="display:flex;gap:8px;"><button class="btn">测试接口</button><button class="btn">查看文档</button></div>
+                </div>
+            </div>
+        </div>
+    </main>
+
+    <!-- 编辑器页面 -->
+    <div class="editor-page active" id="page-editor">
+
+        <!-- 编辑器主体 -->
+        <div class="editor-body">
+            <!-- 左侧项目文件面板 -->
+            <div class="left-panel">
+                <div class="panel-header panel-header-tabs">
+                    <div class="tabs-left">
+                        <button class="panel-tab active" id="tabDocsTop" onclick="switchLeftTab('docs')">我的文档</button>
+                        <button class="panel-tab" id="tabFilesTop" onclick="switchLeftTab('files')">我的附件</button>
+                    </div>
+                    <div style="display:flex;align-items:center;gap:8px;">
+                        <button class="panel-toggle-btn" title="折叠资源面板" onclick="toggleResourcePanel(this)" style="margin-left:8px;">❮</button>
+                    </div>
+                </div>
+                <div class="panel-body">
+                    <!-- 内部旧 tabs 已移除 -->
+
+                    <div class="doc-section" id="leftDocsSection">
+                        <div class="doc-section-header" id="reportsHeader">
+                            <div id="reportsTitle">报告记录 <span id="reportsCount" style="font-weight:600">· 3</span></div>
+                            <div style="display:flex;align-items:center;gap:8px;">
+                                <button class="icon-btn" id="leftSearchBtn" title="搜索"><i class="iconfont icon-SEARCH"></i></button>
+                                <button class="icon-btn" id="newReportBtn" title="新建报告"><i class="iconfont icon-CREATE"></i></button>
+                            </div>
+                        </div>
+                        <div class="docs-area">
+                            <div class="doc-list">
+                                <div class="doc-card file-item" onclick="showFilePreview(this)" data-content="智慧园区建设项目可行性研究报告 原文预览..." data-name="智慧园区建设项目可行性研究报告">
+                                    <div class="doc-thumb">📄</div>
+                                    <div class="file-actions">
+                                        <button class="action-btn" onclick="downloadReport(this)" title="下载">⬇️</button>
+                                        <button class="action-btn" onclick="archiveReport(this)" title="归档">🗂️</button>
+                                        <button class="action-btn" onclick="deleteReport(this)" title="删除">🗑️</button>
+                                    </div>
+                                    <div class="doc-meta">
+                                        <div class="doc-title">智慧园区建设项目可行性研究报告</div>
+                                        <div class="doc-time">2025/12/30 00:00:00</div>
+                                    </div>
+                                </div>
+
+                                <div class="doc-card file-item" onclick="showFilePreview(this)" data-content="华东市场分析 原文预览..." data-name="华东市场分析">
+                                    <div class="doc-thumb">📄</div>
+                                    <div class="file-actions">
+                                        <button class="action-btn" onclick="downloadReport(this)" title="下载">⬇️</button>
+                                        <button class="action-btn" onclick="archiveReport(this)" title="归档">🗂️</button>
+                                        <button class="action-btn" onclick="deleteReport(this)" title="删除">🗑️</button>
+                                    </div>
+                                    <div class="doc-meta">
+                                        <div class="doc-title">华东市场分析</div>
+                                        <div class="doc-time">2026/1/26 01:51:44</div>
+                                    </div>
+                                </div>
+
+                                <div class="doc-card file-item" onclick="showFilePreview(this)" data-content="季度销售简报 原文预览..." data-name="季度销售简报">
+                                    <div class="doc-thumb">📄</div>
+                                    <div class="file-actions">
+                                        <button class="action-btn" onclick="downloadReport(this)" title="下载">⬇️</button>
+                                        <button class="action-btn" onclick="archiveReport(this)" title="归档">🗂️</button>
+                                        <button class="action-btn" onclick="deleteReport(this)" title="删除">🗑️</button>
+                                    </div>
+                                    <div class="doc-meta">
+                                        <div class="doc-title">季度销售简报</div>
+                                        <div class="doc-time">2026/1/24 13:51:44</div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="recent-area">
+                            <div class="recent-section">
+                                <div class="section-title small">最近操作</div>
+                                <div class="recent-list" id="recentList">
+                                    <div class="recent-item" title="AI 已生成报告初稿:季度销售简报..."><span class="recent-text">AI 已生成报告初稿:季度销售简报...</span></div>
+                                    <div class="recent-item" title="文件 '市场调研数据.pdf' 解析完成"><span class="recent-text">文件 '市场调研数据.pdf' 解析完成</span></div>
+                                    <div class="recent-item" title="附件 '财务预测表.xlsx' 解析完成"><span class="recent-text">附件 '财务预测表.xlsx' 解析完成</span></div>
+                                    <div class="recent-item" title="用户 张三 上传文件 '公司报表.xlsx'"><span class="recent-text">用户 张三 上传文件 '公司报表.xlsx'</span></div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="doc-section" id="leftFilesSection" style="display:none;">
+                        <div class="doc-section-header">
+                            <div>我的附件</div>
+                            <div class="badge-count" id="leftFilesCount">0</div>
+                        </div>
+                        <div class="doc-list">
+                            <!-- Attachments will be listed here -->
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- 中间编辑区 -->
+            <div class="center-panel">
+                <div class="editor-title-bar" style="display:flex;justify-content:space-between;align-items:center;gap:12px;">
+                    <div style="display:flex;align-items:center;gap:12px;">
+                        <div class="editor-main-title" id="editorMainTitle" role="button" tabindex="0" title="报告标题">智慧园区建设项目可行性研究报告</div>
+                        <span id="reportStatusTag" class="report-status" title="点击切换状态">草稿</span>
+                    </div>
+                    <div class="editor-actions" style="display:flex;align-items:center;gap:8px;">
+                        <button class="icon-btn" id="toggleViewBtn" title="切换:原文/标记" onclick="toggleView()"><i class="iconfont icon-BIG_PROMOTION"></i></button>
+                        <button class="icon-btn" id="reportElementsTopBtn" title="报告要素" onclick="openReportElementsModal()"><i class="iconfont icon-COMPONENTS"></i></button>
+                        <button class="icon-btn" id="exportBtn" title="导出" onclick="showExportMenu(this)"><i class="iconfont icon-UPLOAD"></i></button>
+                        <button class="icon-btn" id="moreBtn" title="更多" onclick="showMoreMenu(this)">⋯</button>
+                    </div>
+                </div>
+
+                <div class="editor-scroll">
+                    <!-- 原文视图 -->
+                    <div class="editor-content" id="contentOriginal" contenteditable="true" oncontextmenu="showContextMenu(event)">
+                        <h1>智慧园区建设项目可行性研究报告</h1>
+
+                        <h2>一、项目背景</h2>
+                        <p>随着数字经济的快速发展,智慧园区已成为推动产业升级和城市现代化的重要载体。本项目旨在构建集智能化管理、低碳绿色、产业协同于一体的新型智慧园区。</p>
+
+                        <h3>1.1 行业现状</h3>
+                        <p>根据最新市场调研数据显示,2024年中国智慧园区市场规模已达到1,789亿元,同比增长18%,预计2025年将突破2,100亿元。</p>
+
+                        <!-- 数据表格 -->
+                        <div class="data-table-card">
+                            <div class="data-table-header">
+                                <div class="data-table-title">
+                                    <span>📊</span>
+                                    <span>市场规模数据</span>
+                                </div>
+                                <div class="data-table-source">来源: 市场调研数据.pdf</div>
+                            </div>
+                            <table class="data-table">
+                                <thead>
+                                    <tr>
+                                        <th>年份</th>
+                                        <th>市场规模(亿元)</th>
+                                        <th>同比增长</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr><td>2022</td><td>1,280</td><td>15.2%</td></tr>
+                                    <tr><td>2023</td><td>1,516</td><td>18.4%</td></tr>
+                                    <tr><td>2024</td><td>1,789</td><td>18.0%</td></tr>
+                                    <tr><td>2025E</td><td>2,100</td><td>17.4%</td></tr>
+                                </tbody>
+                            </table>
+                        </div>
+
+                        <h2>二、项目概述</h2>
+                        <p>本项目位于华南地区核心区域,规划总面积约50万平方米,预计总投资12.5亿元。项目将分三期建设,首期重点打造智能制造产业集群和数字服务中心。</p>
+
+                        <h3>2.1 项目定位</h3>
+                        <p>本项目致力于打造粤港澳大湾区最具代表性的智慧园区标杆项目,通过引入先进的信息技术和管理理念,实现产业数字化转型和高质量发展。</p>
+
+                        <h3>2.2 建设内容</h3>
+                        <p>项目建设内容主要包括智慧基础设施建设、产业服务平台搭建、数字化管理平台开发等三大方面,总建筑面积约35万平方米。</p>
+
+                        <h2>三、投资估算</h2>
+                        <p>项目总投资为12.5亿元,其中建设投资10.2亿元,流动资金2.3亿元。资金来源包括政府投资4亿元、企业自筹6.5亿元、银行贷款2亿元。</p>
+
+                        <h2>四、市场分析</h2>
+                        <p>当前智慧园区市场需求旺盛,随着产业数字化转型的加速推进,预计未来5年内智慧园区市场规模将保持20%以上的年增长率。</p>
+
+                        <h2>五、经济效益分析</h2>
+                        <p>项目建设期预计3年,运营期20年。项目建成后预计年营业收入8.6亿元,年利润总额2.4亿元,投资回收期约为6.2年。</p>
+                    </div>
+
+                    <!-- 标记视图 -->
+                    <div class="editor-content" id="contentMarked" style="display:none;" contenteditable="true" oncontextmenu="showContextMenu(event)">
+                        <h1>智慧园区建设项目可行性研究报告</h1>
+
+                        <h2>一、项目背景</h2>
+                        <p>随着<span class="entity-highlight" onclick="showDataRelationModal('数字经济', '产业趋势', 'concept', '技术方案说明.pdf')" contenteditable="false">数字经济</span>的快速发展,<span class="entity-highlight" onclick="showDataRelationModal('智慧园区', '核心实体', 'entity', '项目可行性研究报告.docx')" contenteditable="false">智慧园区</span>已成为推动<span class="entity-highlight" onclick="showDataRelationModal('产业升级', '概念', 'concept', '项目可行性研究报告.docx')" contenteditable="false">产业升级</span>和<span class="entity-highlight" onclick="showDataRelationModal('城市现代化', '概念', 'concept', '项目可行性研究报告.docx')" contenteditable="false">城市现代化</span>的重要载体。本项目旨在构建集<span class="entity-highlight" onclick="showDataRelationModal('智能化管理', '技术', 'concept', '技术方案说明.pdf')" contenteditable="false">智能化管理</span>、<span class="entity-highlight" onclick="showDataRelationModal('低碳绿色', '概念', 'concept', '项目可行性研究报告.docx')" contenteditable="false">低碳绿色</span>、<span class="entity-highlight" onclick="showDataRelationModal('产业协同', '模式', 'concept', '项目可行性研究报告.docx')" contenteditable="false">产业协同</span>于一体的新型智慧园区。</p>
+
+                        <!-- AI优化建议卡片 -->
+                        <div class="ai-suggestion-card" id="aiSuggestionCard" contenteditable="false">
+                            <div class="ai-suggestion-header">
+                                <span class="ai-suggestion-icon">💡</span>
+                                <span class="ai-suggestion-title">AI 优化建议</span>
+                            </div>
+                            <div class="ai-suggestion-content">
+                                此处可补充具体的政策文件引用,增强论述的权威性。已从《市场调研数据.pdf》中提取到《"十四五"数字经济发展规划》等相关政策信息。
+                            </div>
+                            <div class="ai-suggestion-actions">
+                                <button class="suggest-btn accept" onclick="acceptSuggestion()">✓ 采纳建议</button>
+                                <button class="suggest-btn ignore" onclick="ignoreSuggestion()">✕ 忽略</button>
+                            </div>
+                        </div>
+
+                        <h3>1.1 行业现状</h3>
+                        <p>根据最新市场调研数据显示,2024年中国<span class="entity-highlight" onclick="showDataRelationModal('智慧园区', '核心实体', 'entity', '市场调研数据.pdf')" contenteditable="false">智慧园区</span>市场规模已达到<span class="entity-highlight" onclick="showDataRelationModal('1,789亿元', '市场规模数据', 'data', '市场调研数据.pdf')" contenteditable="false">1,789亿元</span>,同比增长<span class="entity-highlight" onclick="showDataRelationModal('18%', '增长率数据', 'data', '市场调研数据.pdf')" contenteditable="false">18%</span>,预计2025年将突破<span class="entity-highlight" onclick="showDataRelationModal('2,100亿元', '预测数据', 'data', '市场调研数据.pdf')" contenteditable="false">2,100亿元</span>。</p>
+
+                        <!-- 数据表格 -->
+                        <div class="data-table-card" contenteditable="false">
+                            <div class="data-table-header">
+                                <div class="data-table-title">
+                                    <span>📊</span>
+                                    <span>市场规模数据</span>
+                                </div>
+                                <div class="data-table-source">来源: 市场调研数据.pdf</div>
+                            </div>
+                            <table class="data-table">
+                                <thead>
+                                    <tr>
+                                        <th>年份</th>
+                                        <th>市场规模(亿元)</th>
+                                        <th>同比增长</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr><td>2022</td><td><span class="entity-highlight" onclick="showDataRelationModal('1,280亿元', '历史数据', 'data', '市场调研数据.pdf')" contenteditable="false">1,280</span></td><td><span class="entity-highlight" onclick="showDataRelationModal('15.2%', '增长率', 'data', '市场调研数据.pdf')" contenteditable="false">15.2%</span></td></tr>
+                                    <tr><td>2023</td><td><span class="entity-highlight" onclick="showDataRelationModal('1,516亿元', '历史数据', 'data', '市场调研数据.pdf')" contenteditable="false">1,516</span></td><td><span class="entity-highlight" onclick="showDataRelationModal('18.4%', '增长率', 'data', '市场调研数据.pdf')" contenteditable="false">18.4%</span></td></tr>
+                                    <tr><td>2024</td><td><span class="entity-highlight" onclick="showDataRelationModal('1,789亿元', '当前数据', 'data', '市场调研数据.pdf')" contenteditable="false">1,789</span></td><td><span class="entity-highlight" onclick="showDataRelationModal('18.0%', '增长率', 'data', '市场调研数据.pdf')" contenteditable="false">18.0%</span></td></tr>
+                                    <tr><td><span class="entity-highlight" onclick="showDataRelationModal('2025E', '预测年份', 'data', '市场调研数据.pdf')" contenteditable="false">2025E</span></td><td><span class="entity-highlight" onclick="showDataRelationModal('2,100亿元', '预测数据', 'data', '市场调研数据.pdf')" contenteditable="false">2,100</span></td><td><span class="entity-highlight" onclick="showDataRelationModal('17.4%', '预测增长率', 'data', '市场调研数据.pdf')" contenteditable="false">17.4%</span></td></tr>
+                                </tbody>
+                            </table>
+                        </div>
+
+                        <h2>二、项目概述</h2>
+                        <p>本项目位于<span class="entity-highlight" onclick="showDataRelationModal('华南地区', '地理位置', 'location', '项目可行性研究报告.docx')" contenteditable="false">华南地区</span>核心区域,规划总面积约<span class="entity-highlight" onclick="showDataRelationModal('50万平方米', '面积数据', 'data', '项目可行性研究报告.docx')" contenteditable="false">50万平方米</span>,预计总投资<span class="entity-highlight" onclick="showDataRelationModal('12.5亿元', '投资额', 'data', '项目可行性研究报告.docx')" contenteditable="false">12.5亿元</span>。项目将分<span class="entity-highlight" onclick="showDataRelationModal('三期', '建设周期', 'data', '项目可行性研究报告.docx')" contenteditable="false">三期</span>建设,首期重点打造<span class="entity-highlight" onclick="showDataRelationModal('智能制造产业集群', '产业类型', 'concept', '项目可行性研究报告.docx')" contenteditable="false">智能制造产业集群</span>和<span class="entity-highlight" onclick="showDataRelationModal('数字服务中心', '基础设施', 'concept', '项目可行性研究报告.docx')" contenteditable="false">数字服务中心</span>。</p>
+
+                        <h3>2.1 项目定位</h3>
+                        <p>本项目致力于打造<span class="entity-highlight" onclick="showDataRelationModal('粤港澳大湾区', '区域', 'location', '项目可行性研究报告.docx')" contenteditable="false">粤港澳大湾区</span>最具代表性的<span class="entity-highlight" onclick="showDataRelationModal('智慧园区标杆项目', '项目类型', 'concept', '项目可行性研究报告.docx')" contenteditable="false">智慧园区标杆项目</span>,通过引入先进的信息技术和管理理念,实现<span class="entity-highlight" onclick="showDataRelationModal('产业数字化转型', '转型目标', 'concept', '项目可行性研究报告.docx')" contenteditable="false">产业数字化转型</span>和<span class="entity-highlight" onclick="showDataRelationModal('高质量发展', '发展目标', 'concept', '项目可行性研究报告.docx')" contenteditable="false">高质量发展</span>。</p>
+
+                        <h3>2.2 建设内容</h3>
+                        <p>项目建设内容主要包括<span class="entity-highlight" onclick="showDataRelationModal('智慧基础设施', '建设内容', 'concept', '项目可行性研究报告.docx')" contenteditable="false">智慧基础设施</span>建设、<span class="entity-highlight" onclick="showDataRelationModal('产业服务平台', '建设内容', 'concept', '项目可行性研究报告.docx')" contenteditable="false">产业服务平台</span>搭建、<span class="entity-highlight" onclick="showDataRelationModal('数字化管理平台', '建设内容', 'concept', '项目可行性研究报告.docx')" contenteditable="false">数字化管理平台</span>开发等三大方面,总建筑面积约<span class="entity-highlight" onclick="showDataRelationModal('35万平方米', '建筑面积', 'data', '项目可行性研究报告.docx')" contenteditable="false">35万平方米</span>。</p>
+
+                        <!-- 数据引用卡片 -->
+                        <div class="data-reference-card" contenteditable="false">
+                            <div class="reference-header">
+                                <span class="reference-icon">🔗</span>
+                                <span class="reference-title">数据引用验证</span>
+                            </div>
+                            <div class="reference-content">
+                                <div class="reference-item">
+                                    <span class="reference-label">来源文档:</span>
+                                    <span class="reference-value">技术方案说明.pdf (第3页)</span>
+                                </div>
+                                <div class="reference-item">
+                                    <span class="reference-label">验证状态:</span>
+                                    <span class="reference-value success">✓ 已验证</span>
+                                </div>
+                                <div class="reference-item">
+                                    <span class="reference-label">置信度:</span>
+                                    <span class="reference-value">95.8%</span>
+                                </div>
+                            </div>
+                        </div>
+
+                        <h2>三、投资估算</h2>
+                        <p>项目总投资为<span class="entity-highlight" onclick="showDataRelationModal('12.5亿元', '总投资', 'data', '财务预测表.xlsx')" contenteditable="false">12.5亿元</span>,其中建设投资<span class="entity-highlight" onclick="showDataRelationModal('10.2亿元', '建设投资', 'data', '财务预测表.xlsx')" contenteditable="false">10.2亿元</span>,流动资金<span class="entity-highlight" onclick="showDataRelationModal('2.3亿元', '流动资金', 'data', '财务预测表.xlsx')" contenteditable="false">2.3亿元</span>。资金来源包括政府投资<span class="entity-highlight" onclick="showDataRelationModal('4亿元', '政府投资', 'data', '财务预测表.xlsx')" contenteditable="false">4亿元</span>、企业自筹<span class="entity-highlight" onclick="showDataRelationModal('6.5亿元', '自筹资金', 'data', '财务预测表.xlsx')" contenteditable="false">6.5亿元</span>、银行贷款<span class="entity-highlight" onclick="showDataRelationModal('2亿元', '贷款资金', 'data', '财务预测表.xlsx')" contenteditable="false">2亿元</span>。</p>
+
+                        <h2>四、市场分析</h2>
+                        <p>当前<span class="entity-highlight" onclick="showDataRelationModal('智慧园区', '产品', 'entity', '市场调研数据.pdf')" contenteditable="false">智慧园区</span>市场需求旺盛,随着<span class="entity-highlight" onclick="showDataRelationModal('产业数字化转型', '趋势', 'concept', '市场调研数据.pdf')" contenteditable="false">产业数字化转型</span>的加速推进,预计未来<span class="entity-highlight" onclick="showDataRelationModal('5年', '时间周期', 'data', '市场调研数据.pdf')" contenteditable="false">5年</span>内智慧园区市场规模将保持<span class="entity-highlight" onclick="showDataRelationModal('20%', '增长率预测', 'data', '市场调研数据.pdf')" contenteditable="false">20%</span>以上的年增长率。</p>
+
+                        <!-- 竞争分析卡片 -->
+                        <div class="competition-card" contenteditable="false">
+                            <div class="competition-header">
+                                <span class="competition-icon">🏆</span>
+                                <span class="competition-title">竞争格局分析</span>
+                            </div>
+                            <div class="competition-content">
+                                <div class="competition-item">
+                                    <div class="competitor-name">领先企业A</div>
+                                    <div class="competitor-share">市场份额: 28%</div>
+                                    <div class="competitor-strength">优势: 技术领先</div>
+                                </div>
+                                <div class="competition-item">
+                                    <div class="competitor-name">新兴企业B</div>
+                                    <div class="competitor-share">市场份额: 18%</div>
+                                    <div class="competitor-strength">优势: 服务创新</div>
+                                </div>
+                                <div class="competition-item">
+                                    <div class="competitor-name">本项目</div>
+                                    <div class="competitor-share">目标份额: 15%</div>
+                                    <div class="competitor-strength">优势: 区域特色</div>
+                                </div>
+                            </div>
+                        </div>
+
+                        <h2>五、经济效益分析</h2>
+                        <p>项目建设期预计<span class="entity-highlight" onclick="showDataRelationModal('3年', '建设期', 'data', '财务预测表.xlsx')" contenteditable="false">3年</span>,运营期<span class="entity-highlight" onclick="showDataRelationModal('20年', '运营期', 'data', '财务预测表.xlsx')" contenteditable="false">20年</span>。项目建成后预计年营业收入<span class="entity-highlight" onclick="showDataRelationModal('8.6亿元', '年收入', 'data', '财务预测表.xlsx')" contenteditable="false">8.6亿元</span>,年利润总额<span class="entity-highlight" onclick="showDataRelationModal('2.4亿元', '年利润', 'data', '财务预测表.xlsx')" contenteditable="false">2.4亿元</span>,投资回收期约为<span class="entity-highlight" onclick="showDataRelationModal('6.2年', '回收期', 'data', '财务预测表.xlsx')" contenteditable="false">6.2年</span>。</p>
+
+                        <!-- 财务预测表格 -->
+                        <div class="data-table-card" contenteditable="false">
+                            <div class="data-table-header">
+                                <div class="data-table-title">
+                                    <span>💰</span>
+                                    <span>财务预测数据</span>
+                                </div>
+                                <div class="data-table-source">来源: 财务预测表.xlsx</div>
+                            </div>
+                            <table class="data-table">
+                                <thead>
+                                    <tr>
+                                        <th>年份</th>
+                                        <th>营业收入(亿元)</th>
+                                        <th>利润总额(亿元)</th>
+                                        <th>投资回收</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr><td>第1年</td><td><span class="entity-highlight" onclick="showDataRelationModal('6.2亿元', '第1年收入', 'data', '财务预测表.xlsx')" contenteditable="false">6.2</span></td><td><span class="entity-highlight" onclick="showDataRelationModal('1.8亿元', '第1年利润', 'data', '财务预测表.xlsx')" contenteditable="false">1.8</span></td><td>运营初期</td></tr>
+                                    <tr><td>第2年</td><td><span class="entity-highlight" onclick="showDataRelationModal('7.4亿元', '第2年收入', 'data', '财务预测表.xlsx')" contenteditable="false">7.4</span></td><td><span class="entity-highlight" onclick="showDataRelationModal('2.1亿元', '第2年利润', 'data', '财务预测表.xlsx')" contenteditable="false">2.1</span></td><td>快速增长</td></tr>
+                                    <tr><td>第3年</td><td><span class="entity-highlight" onclick="showDataRelationModal('8.6亿元', '第3年收入', 'data', '财务预测表.xlsx')" contenteditable="false">8.6</span></td><td><span class="entity-highlight" onclick="showDataRelationModal('2.4亿元', '第3年利润', 'data', '财务预测表.xlsx')" contenteditable="false">2.4</span></td><td>达产年份</td></tr>
+                                </tbody>
+                            </table>
+                        </div>
+
+                        <!-- AI生成内容建议 -->
+                        <div class="ai-generated-card" contenteditable="false">
+                            <div class="ai-generated-header">
+                                <span class="ai-generated-icon">✨</span>
+                                <span class="ai-generated-title">AI 生成内容</span>
+                            </div>
+                            <div class="ai-generated-content">
+                                <p><strong>风险分析:</strong></p>
+                                <ul>
+                                    <li>技术风险:新兴技术应用的不确定性</li>
+                                    <li>市场风险:需求变化和竞争加剧</li>
+                                    <li>运营风险:团队建设和管理挑战</li>
+                                    <li>财务风险:资金链和投资回收压力</li>
+                                </ul>
+                                <div class="ai-generated-actions">
+                                    <button class="btn btn-primary" onclick="insertGeneratedContent()">➕ 应用内容</button>
+                                    <button class="btn" onclick="showToast('已忽略AI建议', 'info')">✕ 忽略</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- 右侧AI助手面板 -->
+            <div class="right-panel">
+                <!-- 报告要素区(上半) -->
+                <div class="element-section">
+                    <div class="module-title" role="button" aria-label="打开报告要素列表">
+                        <div class="module-icon">📋</div>
+                        <div class="module-text">报告要素</div>
+                        <div class="elements-actions" style="display:flex;align-items:center;gap:8px;margin-left:8px;">
+                            <!-- report elements opener moved to editor actions -->
+                        </div>
+                    </div>
+                    <div class="element-header" style="display:flex;align-items:center;justify-content:space-between;padding-top:4px;border-top:1px solid transparent;">
+                        <div class="element-tabs" style="display:flex;align-items:center;gap:8px;">
+                            <div class="element-tab active" id="tabDynamic" onclick="switchElementTab('dynamic')">动态要素</div>
+                            <div class="element-tab" id="tabStatic" onclick="switchElementTab('static')">静态要素</div>
+                        </div>
+                        <div>
+                            <button class="icon-btn" id="elementSearchBtn" title="搜索" style="margin-left:8px;"><i class="iconfont icon-SEARCH"></i></button>
+                        </div>
+                    </div>
+
+                    <!-- 要素标签容器:动态 / 静态 两个面板,使用 tab 切换 -->
+                    <div id="dynamicTags" class="element-tags-wrap">
+                        <!-- 动态要素(AI 规则计算产生)示例 -->
+                        <span class="element-tag dynamic" draggable="true" ondragstart="handleTagDragStart(event, '市场上升信号')" ondragend="handleTagDragEnd(event)" onclick="showTagPopover(event, 'dynamic1')">
+                            <span class="tag-icon">📈</span>
+                            <span class="tag-name">市场上升信号</span>
+                        </span>
+                        <span class="element-tag dynamic" draggable="true" ondragstart="handleTagDragStart(event, '增长偏好')" ondragend="handleTagDragEnd(event)" onclick="showTagPopover(event, 'dynamic2')">
+                            <span class="tag-icon">⚡</span>
+                            <span class="tag-name">增长偏好</span>
+                        </span>
+                    </div>
+                    <div id="staticTags" class="element-tags-wrap" style="display:none;">
+                        <!-- 静态要素:直接来自原文采集(保留原有示例) -->
+                        <span class="element-tag static entity" draggable="true" ondragstart="handleTagDragStart(event, '智慧园区')" ondragend="handleTagDragEnd(event)" onclick="showTagPopover(event, 'smartpark')">
+                            <span class="tag-icon">🏢</span>
+                            <span class="tag-name">智慧园区</span>
+                        </span>
+                        <span class="element-tag static concept" draggable="true" ondragstart="handleTagDragStart(event, '产业升级')" ondragend="handleTagDragEnd(event)" onclick="showTagPopover(event, 'upgrade')">
+                            <span class="tag-icon">📈</span>
+                            <span class="tag-name">产业升级</span>
+                        </span>
+                        <span class="element-tag static concept" draggable="true" ondragstart="handleTagDragStart(event, '城市现代化')" ondragend="handleTagDragEnd(event)" onclick="showTagPopover(event, 'modern')">
+                            <span class="tag-icon">🌆</span>
+                            <span class="tag-name">城市现代化</span>
+                        </span>
+                        <span class="element-tag static concept" draggable="true" ondragstart="handleTagDragStart(event, '智能化管理')" ondragend="handleTagDragEnd(event)" onclick="showTagPopover(event, 'ai')">
+                            <span class="tag-icon">🤖</span>
+                            <span class="tag-name">智能化管理</span>
+                        </span>
+                        <span class="element-tag static data" draggable="true" ondragstart="handleTagDragStart(event, '1,789亿元')" ondragend="handleTagDragEnd(event)" onclick="showTagPopover(event, 'data1')">
+                            <span class="tag-icon">💰</span>
+                            <span class="tag-name">1,789亿元</span>
+                        </span>
+                        <span class="element-tag static data" draggable="true" ondragstart="handleTagDragStart(event, '18%')" ondragend="handleTagDragEnd(event)" onclick="showTagPopover(event, 'data2')">
+                            <span class="tag-icon">📊</span>
+                            <span class="tag-name">18%</span>
+                        </span>
+                    </div>
+                </div>
+
+                <!-- 要素详情弹出框 -->
+                <div class="element-popover" id="elementPopover">
+                    <div class="popover-header">
+                        <div class="popover-icon entity" id="popoverIcon">🏢</div>
+                        <div class="popover-title" id="popoverTitle">智慧园区</div>
+                        <button class="popover-close" onclick="hideTagPopover()">×</button>
+                    </div>
+                    <div class="popover-body">
+                        <div class="popover-section">
+                            <div class="popover-label">类型</div>
+                            <div class="popover-value" id="popoverType">核心实体</div>
+                        </div>
+                        <div class="popover-section">
+                            <div class="popover-label">来源</div>
+                            <div class="popover-value" id="popoverSource">项目可行性研究报告.docx</div>
+                        </div>
+                        <div class="popover-section">
+                            <div class="popover-label">关联要素</div>
+                            <div class="popover-relations" id="popoverRelations">
+                                <span class="popover-relation">→ 产业升级</span>
+                                <span class="popover-relation">→ 城市现代化</span>
+                            </div>
+                        </div>
+                        <div class="popover-actions">
+                            <button class="btn" onclick="showToast('已定位到文档', 'info');hideTagPopover();">📍 定位</button>
+                            <button class="btn btn-primary" onclick="insertTagToEditor();hideTagPopover();">➕ 插入</button>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- AI助手区 -->
+                <div class="ai-assistant">
+                    <div class="ai-header">
+                        <div class="ai-avatar-sm">🤖</div>
+                    <div class="ai-info">
+                        <div class="ai-name">AI助手</div>
+                        <div class="ai-status">● 已加载项目上下文</div>
+                    </div>
+                    </div>
+
+                    <!-- AI Tab切换 -->
+                    <div class="ai-tabs">
+                        <div class="ai-tab active" onclick="switchAiTab(this, 'chat')">💬 对话</div>
+                        <div class="ai-tab" onclick="switchAiTab(this, 'suggest')">💡 建议</div>
+                        <div class="ai-tab" onclick="switchAiTab(this, 'memory')">🧠 记忆</div>
+                    </div>
+
+                    <!-- AI消息区 -->
+                    <div class="ai-messages" id="aiMessages">
+                        <div class="msg ai">
+                            <div class="msg-avatar">🤖</div>
+                            <div class="msg-bubble">您好!我已分析上传的5份文档,构建了项目知识图谱。有什么可以帮您的?</div>
+                        </div>
+                        <div class="msg user">
+                            <div class="msg-avatar">张</div>
+                            <div class="msg-bubble">帮我补充市场分析部分的竞争格局内容</div>
+                        </div>
+                        <div class="msg ai">
+                            <div class="msg-avatar">🤖</div>
+                            <div class="msg-bubble">好的,我已从《市场调研数据.pdf》中提取了竞争格局相关数据。建议如下:</div>
+                        </div>
+
+                    <!-- AI输入区 -->
+                    <div class="ai-input-area">
+                        <div class="ai-input-inner">
+                            <div class="ai-input-box">
+                                <div class="ai-input-row">
+                                    <div class="ai-input-top">
+                                        <textarea id="aiTextarea" placeholder="发消息给AI助手" rows="1" onkeydown="handleAiKey(event)" oninput="autoResizeTextarea(this)"></textarea>
+                                    </div>
+                                    <div class="ai-input-toolbar">
+                                        <div class="left">
+                                            <!-- 1: 自定义图标(icon-CREATE) -->
+                                            <button class="ai-icon-btn" id="aiIconCreateBtn" title="上传"><i class="iconfont icon-CREATE"></i></button>
+                                            <!-- 2: 将原来的 '@' 替换为 icon-a-SYMBOLS_ -->
+                                            <button class="ai-icon-btn" title="@" onclick="showToast('@', 'info')"><i class="iconfont icon-a-SYMBOLS_"></i></button>
+                                            <!-- 3: 将 '联网' 替换为 icon-hulianwangoff -->
+                                            <button class="ai-icon-btn" title="联网" onclick="showToast('联网搜索(示意)', 'info')"><i class="iconfont icon-hulianwangoff"></i></button>
+                                        </div>
+                                        <div class="right">
+                                            <!-- 4: 将语音输入图标替换为 icon-01 -->
+                                            <button class="ai-icon-btn" title="语音输入" onclick="showToast('语音输入(示意)', 'info')"><i class="iconfont icon-01"></i></button>
+                                            <button class="ai-send-btn" id="aiSendBtn" title="发送" onclick="sendAiMsg()">⬆</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <!-- hint removed as requested -->
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 报告要素弹窗 -->
+    <div class="report-elements-modal" id="reportElementsModal" aria-hidden="true">
+        <div class="report-elements-card" role="dialog" aria-modal="true" aria-labelledby="reportElementsTitle">
+            <div class="report-elements-header">
+                <div class="report-elements-title" id="reportElementsTitle">报告要素</div>
+                <div class="elements-search">
+                    <input type="text" id="elementsSearchInput" placeholder="搜索要素名称 / 类型..." />
+                </div>
+            </div>
+            <div class="report-elements-body">
+                <table class="elements-table" id="elementsTable">
+                    <thead>
+                        <tr>
+                            <th style="width:14%;">名称</th>
+                            <th style="width:18%;">描述</th>
+                            <th style="width:8%;">类型</th>
+                            <th style="width:10%;">要素类型</th>
+                            <th style="width:12%;">原值</th>
+                            <th style="width:12%;">新值</th>
+                            <th style="width:12%;">填充源</th>
+                            <th style="width:8%;">操作</th>
+                        </tr>
+                    </thead>
+                    <tbody id="elementsTbody">
+                        <!-- 动态生成 -->
+                    </tbody>
+                </table>
+            </div>
+            <div class="report-elements-footer">
+                <div style="margin-right:auto;display:flex;gap:12px;align-items:center;">
+                    <!-- 翻页控件已移除:改由分页数字按钮显示(默认显示最多 5 个页码) -->
+                    <div class="pagination" id="elementsPaginationInfo" style="font-size:12px;color:var(--text3);"></div>
+                    <div style="display:flex;align-items:center;gap:8px;margin-left:12px;">
+                        <label style="font-size:12px;color:var(--text3);">每页显示:</label>
+                        <select id="elementsPageSize" class="page-size-select">
+                            <option value="10">10</option>
+                            <option value="20">20</option>
+                            <option value="50">50</option>
+                        </select>
+                    </div>
+                </div>
+                <button class="btn" onclick="closeReportElementsModal()">取消</button>
+                <button class="btn btn-primary" id="saveElementsBtn">保存全部</button>
+            </div>
+        </div>
+    </div>
+
+    <!-- 右键菜单 -->
+    <div class="context-menu" id="contextMenu">
+        <div class="context-menu-item" onclick="execContextAction('copy')">
+            <span class="icon">📋</span>
+            <span>复制</span>
+            <span class="shortcut">Ctrl+C</span>
+        </div>
+        <div class="context-menu-item" onclick="execContextAction('cut')">
+            <span class="icon">✂️</span>
+            <span>剪切</span>
+            <span class="shortcut">Ctrl+X</span>
+        </div>
+        <div class="context-menu-item" onclick="execContextAction('paste')">
+            <span class="icon">📄</span>
+            <span>粘贴</span>
+            <span class="shortcut">Ctrl+V</span>
+        </div>
+        <div class="context-menu-divider"></div>
+        <div class="context-menu-item" onclick="execContextAction('polish')">
+            <span class="icon">✨</span>
+            <span>AI 润色</span>
+        </div>
+        <div class="context-menu-item" onclick="execContextAction('spell')">
+            <span class="icon">📝</span>
+            <span>检查拼写</span>
+        </div>
+        <div class="context-menu-divider"></div>
+        <div class="context-menu-item" onclick="execContextAction('mark')">
+            <span class="icon">🏷️</span>
+            <span>标记为要素</span>
+        </div>
+        <div class="context-menu-item" onclick="execContextAction('quote')">
+            <span class="icon">💬</span>
+            <span>引用到AI助手</span>
+        </div>
+    </div>
+
+    <!-- 数据关系表弹窗 -->
+    <div class="data-relation-modal" id="dataRelationModal">
+        <div class="data-relation-card">
+            <div class="data-relation-header">
+                <div class="data-relation-icon" id="relationIcon">🏷️</div>
+                <div class="data-relation-title">
+                    <h3 id="relationEntityName">标签数据关系</h3>
+                    <span id="relationEntityType">实体类型 · 数据来源</span>
+                </div>
+                <button class="data-relation-close" onclick="closeDataRelationModal()">×</button>
+            </div>
+            <div class="data-relation-body">
+                <div class="relation-section">
+                    <div class="relation-label">📊 数据关系表</div>
+                    <table class="relation-table">
+                        <thead>
+                            <tr>
+                                <th style="width:25%">属性</th>
+                                <th style="width:30%">原始值</th>
+                                <th style="width:30%">当前标签值</th>
+                                <th style="width:15%">操作</th>
+                            </tr>
+                        </thead>
+                        <tbody id="relationTableBody">
+                            <!-- 动态生成 -->
+                        </tbody>
+                    </table>
+                </div>
+                <div class="relation-section">
+                    <div class="relation-label">🔗 关联要素</div>
+                    <div class="relation-tags" id="relationTags">
+                        <!-- 动态生成关联标签 -->
+                    </div>
+                </div>
+            </div>
+            <div class="data-relation-footer">
+                <button class="btn" onclick="showToast('已删除标记', 'info');closeDataRelationModal();">🗑️ 删除标记</button>
+                <button class="btn" onclick="closeDataRelationModal()">取消</button>
+                <button class="btn btn-primary" onclick="saveDataRelationChanges()">保存更改</button>
+            </div>
+        </div>
+    </div>
+
+    <!-- 导出菜单 -->
+    <div class="export-menu" id="exportMenu" style="position:fixed;background:var(--white);border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,0.15);min-width:180px;display:none;z-index:2001;overflow:hidden;">
+        <div style="padding:12px 16px;cursor:pointer;font-size:13px;display:flex;align-items:center;gap:10px;transition:background 0.15s;" onmouseover="this.style.background='var(--primary-light)'" onmouseout="this.style.background=''" onclick="showToast('导出PDF成功', 'success');hideExportMenu()">
+            <span>📕</span><span>导出为 PDF</span>
+        </div>
+        <div style="padding:12px 16px;cursor:pointer;font-size:13px;display:flex;align-items:center;gap:10px;transition:background 0.15s;" onmouseover="this.style.background='var(--primary-light)'" onmouseout="this.style.background=''" onclick="showToast('导出Word成功', 'success');hideExportMenu()">
+            <span>📘</span><span>导出为 Word</span>
+        </div>
+    </div>
+
+    <!-- 要素关系图谱弹窗 -->
+    <div class="knowledge-graph-modal" id="knowledgeGraphModal">
+        <div class="kg-header">
+            <div class="kg-title">
+                <span class="kg-icon">🔗</span>
+                <span>要素关系图谱</span>
+            </div>
+            <div class="kg-controls">
+                <div class="kg-view-toggle">
+                    <button class="kg-view-btn active" onclick="switchGraphView('graph')" id="graphViewBtn">
+                        <span>🕸️</span>
+                        <span>图谱视图</span>
+                    </button>
+                    <button class="kg-view-btn" onclick="switchGraphView('list')" id="listViewBtn">
+                        <span>📋</span>
+                        <span>列表视图</span>
+                    </button>
+                </div>
+                <button class="kg-close" onclick="closeKnowledgeGraph()">×</button>
+            </div>
+        </div>
+
+        <div class="kg-content">
+            <!-- 图谱视图 -->
+            <div class="kg-graph-view" id="graphView">
+                <div class="graph-canvas" id="graphCanvas">
+                    <div class="graph-node core" style="left: 50%; top: 50%; transform: translate(-50%, -50%);" data-entity="智慧园区">
+                        <div class="node-icon">🏢</div>
+                        <div class="node-label">智慧园区</div>
+                        <div class="node-type">核心实体</div>
+                    </div>
+
+                    <div class="graph-node concept" style="left: 25%; top: 30%;" data-entity="产业升级">
+                        <div class="node-icon">📈</div>
+                        <div class="node-label">产业升级</div>
+                        <div class="node-type">概念</div>
+                    </div>
+
+                    <div class="graph-node concept" style="left: 75%; top: 30%;" data-entity="城市现代化">
+                        <div class="node-icon">🌆</div>
+                        <div class="node-label">城市现代化</div>
+                        <div class="node-type">概念</div>
+                    </div>
+
+                    <div class="graph-node concept" style="left: 15%; top: 70%;" data-entity="智能化管理">
+                        <div class="node-icon">🤖</div>
+                        <div class="node-label">智能化管理</div>
+                        <div class="node-type">技术</div>
+                    </div>
+
+                    <div class="graph-node data" style="left: 40%; top: 20%;" data-entity="1,789亿元">
+                        <div class="node-icon">💰</div>
+                        <div class="node-label">1,789亿元</div>
+                        <div class="node-type">市场规模</div>
+                    </div>
+
+                    <div class="graph-node data" style="left: 60%; top: 80%;" data-entity="12.5亿元">
+                        <div class="node-icon">💵</div>
+                        <div class="node-label">12.5亿元</div>
+                        <div class="node-type">投资额</div>
+                    </div>
+
+                    <div class="graph-node location" style="left: 85%; top: 70%;" data-entity="华南地区">
+                        <div class="node-icon">📍</div>
+                        <div class="node-label">华南地区</div>
+                        <div class="node-type">地理位置</div>
+                    </div>
+
+                    <!-- 关系连线 -->
+                    <svg class="graph-lines" width="100%" height="100%">
+                        <defs>
+                            <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
+                                <polygon points="0 0, 10 3.5, 0 7" fill="#1890ff" opacity="0.6"/>
+                            </marker>
+                        </defs>
+                        <!-- 核心关系 -->
+                        <line x1="50%" y1="50%" x2="25%" y2="30%" stroke="#1890ff" stroke-width="2" opacity="0.6" marker-end="url(#arrowhead)"/>
+                        <line x1="50%" y1="50%" x2="75%" y2="30%" stroke="#1890ff" stroke-width="2" opacity="0.6" marker-end="url(#arrowhead)"/>
+                        <line x1="50%" y1="50%" x2="15%" y2="70%" stroke="#1890ff" stroke-width="2" opacity="0.6" marker-end="url(#arrowhead)"/>
+                        <line x1="50%" y1="50%" x2="40%" y2="20%" stroke="#1890ff" stroke-width="2" opacity="0.6" marker-end="url(#arrowhead)"/>
+                        <line x1="50%" y1="50%" x2="60%" y2="80%" stroke="#1890ff" stroke-width="2" opacity="0.6" marker-end="url(#arrowhead)"/>
+                        <line x1="50%" y1="50%" x2="85%" y2="70%" stroke="#1890ff" stroke-width="2" opacity="0.6" marker-end="url(#arrowhead)"/>
+                    </svg>
+                </div>
+                <div class="graph-legend">
+                    <div class="legend-item"><span class="legend-dot core"></span><span>核心实体</span></div>
+                    <div class="legend-item"><span class="legend-dot concept"></span><span>概念</span></div>
+                    <div class="legend-item"><span class="legend-dot data"></span><span>数据</span></div>
+                    <div class="legend-item"><span class="legend-dot location"></span><span>地点</span></div>
+                </div>
+            </div>
+
+            <!-- 列表视图 -->
+            <div class="kg-list-view" id="listView" style="display: none;">
+                <div class="list-search">
+                    <input type="text" placeholder="🔍 搜索要素..." class="list-search-input" oninput="filterEntities(this.value)">
+                </div>
+                <div class="entity-categories">
+                    <div class="category-section">
+                        <div class="category-header">
+                            <span class="category-icon">🏢</span>
+                            <span class="category-title">核心实体 (1)</span>
+                        </div>
+                        <div class="entity-items">
+                            <div class="entity-item" onclick="highlightEntity('智慧园区')">
+                                <div class="entity-icon">🏢</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">智慧园区</div>
+                                    <div class="entity-meta">6个关联 • 3个来源文档</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('智慧园区')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('智慧园区')">✏️</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="category-section">
+                        <div class="category-header">
+                            <span class="category-icon">💡</span>
+                            <span class="category-title">概念 (4)</span>
+                        </div>
+                        <div class="entity-items">
+                            <div class="entity-item" onclick="highlightEntity('产业升级')">
+                                <div class="entity-icon">📈</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">产业升级</div>
+                                    <div class="entity-meta">2个关联 • 2个来源文档</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('产业升级')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('产业升级')">✏️</button>
+                                </div>
+                            </div>
+                            <div class="entity-item" onclick="highlightEntity('城市现代化')">
+                                <div class="entity-icon">🌆</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">城市现代化</div>
+                                    <div class="entity-meta">2个关联 • 1个来源文档</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('城市现代化')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('城市现代化')">✏️</button>
+                                </div>
+                            </div>
+                            <div class="entity-item" onclick="highlightEntity('智能化管理')">
+                                <div class="entity-icon">🤖</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">智能化管理</div>
+                                    <div class="entity-meta">1个关联 • 1个来源文档</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('智能化管理')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('智能化管理')">✏️</button>
+                                </div>
+                            </div>
+                            <div class="entity-item" onclick="highlightEntity('低碳绿色')">
+                                <div class="entity-icon">🌱</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">低碳绿色</div>
+                                    <div class="entity-meta">1个关联 • 1个来源文档</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('低碳绿色')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('低碳绿色')">✏️</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="category-section">
+                        <div class="category-header">
+                            <span class="category-icon">📊</span>
+                            <span class="category-title">数据 (8)</span>
+                        </div>
+                        <div class="entity-items">
+                            <div class="entity-item" onclick="highlightEntity('1,789亿元')">
+                                <div class="entity-icon">💰</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">1,789亿元</div>
+                                    <div class="entity-meta">市场规模数据 • 1个来源</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('1,789亿元')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('1,789亿元')">✏️</button>
+                                </div>
+                            </div>
+                            <div class="entity-item" onclick="highlightEntity('18%')">
+                                <div class="entity-icon">📊</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">18%</div>
+                                    <div class="entity-meta">增长率数据 • 1个来源</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('18%')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('18%')">✏️</button>
+                                </div>
+                            </div>
+                            <div class="entity-item" onclick="highlightEntity('50万平方米')">
+                                <div class="entity-icon">📐</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">50万平方米</div>
+                                    <div class="entity-meta">面积数据 • 1个来源</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('50万平方米')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('50万平方米')">✏️</button>
+                                </div>
+                            </div>
+                            <div class="entity-item" onclick="highlightEntity('12.5亿元')">
+                                <div class="entity-icon">💵</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">12.5亿元</div>
+                                    <div class="entity-meta">投资额数据 • 1个来源</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('12.5亿元')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('12.5亿元')">✏️</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="category-section">
+                        <div class="category-header">
+                            <span class="category-icon">📍</span>
+                            <span class="category-title">地点 (1)</span>
+                        </div>
+                        <div class="entity-items">
+                            <div class="entity-item" onclick="highlightEntity('华南地区')">
+                                <div class="entity-icon">📍</div>
+                                <div class="entity-info">
+                                    <div class="entity-name">华南地区</div>
+                                    <div class="entity-meta">地理位置 • 1个来源</div>
+                                </div>
+                                <div class="entity-actions">
+                                    <button class="entity-action-btn" onclick="locateEntity('华南地区')">📍</button>
+                                    <button class="entity-action-btn" onclick="editEntity('华南地区')">✏️</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- FAB资源监控 -->
+    <div style="position:fixed;bottom:24px;right:24px;z-index:1000;" id="fabContainer">
+        <div id="fabPanel" style="position:absolute;bottom:60px;right:0;width:260px;background:var(--white);border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.15);display:none;overflow:hidden;">
+            <div style="padding:14px 16px;background:linear-gradient(135deg, #52c41a 0%, #13c2c2 100%);color:white;font-weight:600;font-size:13px;">📊 资源监控</div>
+            <div style="padding:14px 16px;">
+                <div style="margin-bottom:12px;">
+                    <div style="display:flex;justify-content:space-between;margin-bottom:4px;font-size:12px;"><span>Token 消耗</span><span style="font-weight:500;">15.6K / 20K</span></div>
+                    <div style="height:6px;background:var(--bg);border-radius:3px;"><div style="height:100%;width:78%;background:var(--warning);border-radius:3px;"></div></div>
+                </div>
+                <div style="margin-bottom:12px;">
+                    <div style="display:flex;justify-content:space-between;margin-bottom:4px;font-size:12px;"><span>GPU 显存</span><span style="font-weight:500;">3.6G / 8G</span></div>
+                    <div style="height:6px;background:var(--bg);border-radius:3px;"><div style="height:100%;width:45%;background:var(--success);border-radius:3px;"></div></div>
+                </div>
+                <div style="display:flex;justify-content:space-between;padding:10px;background:var(--bg);border-radius:8px;">
+                    <div style="text-align:center;"><div style="font-size:16px;font-weight:600;color:var(--primary);">¥3.12</div><div style="font-size:10px;color:var(--text3);">本次会话</div></div>
+                    <div style="text-align:center;"><div style="font-size:16px;font-weight:600;color:var(--primary);">¥127.50</div><div style="font-size:10px;color:var(--text3);">本月累计</div></div>
+                </div>
+            </div>
+        </div>
+        <button id="fabBtn" style="width:50px;height:50px;border-radius:50%;background:linear-gradient(135deg, #52c41a 0%, #13c2c2 100%);border:none;cursor:grab;display:flex;align-items:center;justify-content:center;font-size:20px;color:white;box-shadow:0 6px 20px rgba(82,196,26,0.35);">📊</button>
+    </div>
+    <script>
+    (function(){
+        const container = document.getElementById('fabContainer');
+        const btn = document.getElementById('fabBtn');
+        if (!container || !btn) return;
+
+        let dragging = false;
+        let moved = false;
+        let startX = 0, startY = 0, origLeft = 0, origTop = 0;
+
+        // 默认位置:固定在右下角(24px 间距)
+        container.style.right = '24px';
+        container.style.bottom = '24px';
+        container.style.left = '';
+        container.style.top = '';
+
+        function start(e) {
+            const evt = e.touches ? e.touches[0] : e;
+            dragging = true;
+            moved = false;
+            startX = evt.clientX;
+            startY = evt.clientY;
+            const rect = container.getBoundingClientRect();
+            origLeft = rect.left;
+            origTop = rect.top;
+            document.addEventListener('mousemove', onMove);
+            document.addEventListener('mouseup', end);
+            document.addEventListener('touchmove', onMove, { passive: false });
+            document.addEventListener('touchend', end);
+            container.style.transition = 'none';
+            btn.style.cursor = 'grabbing';
+            e.preventDefault();
+        }
+
+        function onMove(e) {
+            if (!dragging) return;
+            const evt = e.touches ? e.touches[0] : e;
+            const dx = evt.clientX - startX;
+            const dy = evt.clientY - startY;
+            if (Math.abs(dx) > 4 || Math.abs(dy) > 4) moved = true;
+            const vw = window.innerWidth, vh = window.innerHeight;
+            const rect = container.getBoundingClientRect();
+            const w = rect.width, h = rect.height;
+            let newLeft = origLeft + dx;
+            let newTop = origTop + dy;
+            newLeft = Math.max(8, Math.min(vw - w - 8, newLeft));
+            newTop = Math.max(8, Math.min(vh - h - 8, newTop));
+            container.style.left = newLeft + 'px';
+            container.style.top = newTop + 'px';
+            container.style.right = '';
+            container.style.bottom = '';
+            e.preventDefault();
+        }
+
+        function end() {
+            if (!dragging) return;
+            dragging = false;
+            document.removeEventListener('mousemove', onMove);
+            document.removeEventListener('mouseup', end);
+            document.removeEventListener('touchmove', onMove);
+            document.removeEventListener('touchend', end);
+            container.style.transition = '';
+            btn.style.cursor = 'grab';
+            // 不持久化位置:拖动仅在当前会话有效,刷新/重新登录后恢复到默认右下角
+            // if moved, prevent the immediate click from toggling the panel
+            if (moved) {
+                const preventer = function(ev) { ev.stopImmediatePropagation(); ev.preventDefault(); btn.removeEventListener('click', preventer, true); };
+                btn.addEventListener('click', preventer, true);
+            }
+        }
+
+        // replace inline onclick by controlled click handler
+        btn.addEventListener('click', function(e){
+            if (dragging || moved) { e.preventDefault(); e.stopPropagation(); return; }
+            try { toggleFab(); } catch (err) { console.warn('toggleFab not available', err); }
+        });
+
+        // init and ensure position stays in viewport on resize
+        window.addEventListener('resize', function(){
+            try {
+                const rect = container.getBoundingClientRect();
+                const vw = window.innerWidth, vh = window.innerHeight;
+                let left = rect.left, top = rect.top;
+                const w = rect.width, h = rect.height;
+                if (left > vw - 8) left = Math.max(8, vw - w - 8);
+                if (top > vh - 8) top = Math.max(8, vh - h - 8);
+                container.style.left = left + 'px';
+                container.style.top = top + 'px';
+            } catch (e) {}
+        });
+
+        btn.addEventListener('mousedown', start);
+        btn.addEventListener('touchstart', start, { passive: false });
+
+        loadPos();
+    })();
+    </script>
+
+    <!-- 通知面板 -->
+    <div class="notif-panel" id="notifPanel">
+        <div style="padding:18px;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center;">
+            <span style="font-size:15px;font-weight:600;">消息通知</span>
+            <span style="font-size:12px;color:var(--primary);cursor:pointer;" onclick="showToast('已全部标为已读', 'success')">全部已读</span>
+        </div>
+        <div style="flex:1;overflow-y:auto;">
+            <div style="padding:14px 18px;border-bottom:1px solid var(--border);background:var(--primary-light);cursor:pointer;" onclick="void(0)">
+                <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px;">
+                    <span style="width:22px;height:22px;background:#f6ffed;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;">✅</span>
+                    <span style="flex:1;font-weight:500;font-size:13px;">文档解析完成</span>
+                    <span style="font-size:10px;color:var(--text3);">刚刚</span>
+                </div>
+                <div style="font-size:12px;color:var(--text2);">《市场调研数据.pdf》已解析完成,提取到35个实体</div>
+            </div>
+            <div style="padding:14px 18px;border-bottom:1px solid var(--border);cursor:pointer;">
+                <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px;">
+                    <span style="width:22px;height:22px;background:#fffbe6;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;">💬</span>
+                    <span style="flex:1;font-weight:500;font-size:13px;">李四评论了您的报告</span>
+                    <span style="font-size:10px;color:var(--text3);">2小时前</span>
+                </div>
+                <div style="font-size:12px;color:var(--text2);">建议补充竞争格局分析...</div>
+            </div>
+        </div>
+    </div>
+
+    <!-- Toast容器 -->
+    <div class="toast-container" id="toastContainer"></div>
+
+    <!-- 遮罩 -->
+    <div class="overlay" id="overlay" onclick="closeAll()"></div>
+
+    <!-- 要素关系图谱遮罩 -->
+    <div class="kg-overlay" id="kgOverlay" onclick="closeKnowledgeGraph()"></div>
+
+    <script>
+        // === 导航 ===
+        document.addEventListener('DOMContentLoaded', function(){
+            try {
+                const ta = document.getElementById('aiTextarea');
+                const send = document.getElementById('aiSendBtn');
+                if (ta && send) {
+                    const update = () => {
+                        if (ta.value.trim().length > 0) send.classList.add('active');
+                        else send.classList.remove('active');
+                    };
+                    ta.addEventListener('input', update);
+                    update();
+                }
+            } catch (e) { console.warn('ai input init err', e); }
+        });
+        function navTo(page) {
+            document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
+            document.querySelectorAll('.menu-item').forEach(m => m.classList.remove('active'));
+            document.getElementById('page-' + page)?.classList.add('active');
+            document.querySelector('[data-page="' + page + '"]')?.classList.add('active');
+            document.getElementById('page-editor').classList.remove('active');
+            document.getElementById('sidebar').classList.remove('hidden');
+            document.getElementById('mainContent').style.display = '';
+            closeAll();
+        }
+
+        function goHome() { navTo('home'); }
+
+        // === 编辑器 ===
+        function openEditor() {
+            document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
+            document.getElementById('page-editor').classList.add('active');
+            document.getElementById('sidebar').classList.add('hidden');
+            document.getElementById('mainContent').style.display = 'none';
+            closeAll();
+        }
+
+        function closeEditor() { navTo('home'); }
+
+        // === 通知 ===
+        function toggleNotif() {
+            const panel = document.getElementById('notifPanel');
+            const overlay = document.getElementById('overlay');
+            const isOpen = panel.style.transform === 'translateX(0%)';
+            panel.style.transform = isOpen ? 'translateX(100%)' : 'translateX(0%)';
+            overlay.style.display = isOpen ? 'none' : 'block';
+        }
+
+        // === FAB ===
+        function toggleFab() {
+            const panel = document.getElementById('fabPanel');
+            panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
+        }
+
+        // === 思考模式 ===
+        function setMode(el) {
+            document.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active'));
+            el.classList.add('active');
+            showToast('已切换到 ' + el.textContent.trim(), 'success');
+        }
+
+        // === 首页AI输入 ===
+        function toggleSendBtn() {
+            const input = document.getElementById('homeAiInput');
+            const btn = document.getElementById('homeSendBtn');
+            btn.classList.toggle('show', input.value.trim().length > 0);
+        }
+
+        function handleHomeAi() {
+            const input = document.getElementById('homeAiInput');
+            if (input.value.trim()) {
+                showToast('AI正在处理...', 'info');
+                setTimeout(() => openEditor(), 1000);
+                input.value = '';
+                document.getElementById('homeSendBtn').classList.remove('show');
+            }
+        }
+
+        // === 要素管理 ===
+        const tagData = {
+            smartpark: { icon: '🏢', type: 'entity', name: '智慧园区', typeText: '核心实体', source: '项目可行性研究报告.docx', relations: ['产业升级', '城市现代化', '智能化管理'] },
+            upgrade: { icon: '📈', type: 'concept', name: '产业升级', typeText: '概念', source: '项目可行性研究报告.docx', relations: ['智慧园区', '城市现代化'] },
+            modern: { icon: '🌆', type: 'concept', name: '城市现代化', typeText: '概念', source: '项目可行性研究报告.docx', relations: ['智慧园区', '产业升级'] },
+            ai: { icon: '🤖', type: 'concept', name: '智能化管理', typeText: '技术', source: '技术方案说明.pdf', relations: ['智慧园区', '低碳绿色'] },
+            green: { icon: '🌱', type: 'concept', name: '低碳绿色', typeText: '概念', source: '项目可行性研究报告.docx', relations: ['智慧园区'] },
+            location: { icon: '📍', type: 'location', name: '华南地区', typeText: '地点', source: '项目可行性研究报告.docx', relations: ['智慧园区', '50万m²'] },
+            data1: { icon: '💰', type: 'data', name: '1,789亿元', typeText: '市场规模数据', source: '市场调研数据.pdf', relations: ['智慧园区', '18%'] },
+            data2: { icon: '📊', type: 'data', name: '18%', typeText: '增长率数据', source: '市场调研数据.pdf', relations: ['1,789亿元'] },
+            data3: { icon: '📐', type: 'data', name: '50万平方米', typeText: '面积数据', source: '项目可行性研究报告.docx', relations: ['华南地区'] },
+            data4: { icon: '💵', type: 'data', name: '12.5亿元', typeText: '投资额', source: '财务预测表.xlsx', relations: ['智慧园区'] },
+            chart: { icon: '📊', type: 'asset', name: '趋势图', typeText: '图表资产', source: '资产库', relations: ['柱状图'] },
+            template: { icon: '📝', type: 'asset', name: '结论模板', typeText: '文本模板', source: '资产库', relations: ['结论'] }
+        };
+
+        let currentTagName = '';
+
+        function showTagPopover(event, tagId) {
+            event.stopPropagation();
+            const popover = document.getElementById('elementPopover');
+            const data = tagData[tagId];
+            if (!data) return;
+
+            currentTagName = data.name;
+            document.getElementById('popoverIcon').className = 'popover-icon ' + data.type;
+            document.getElementById('popoverIcon').textContent = data.icon;
+            document.getElementById('popoverTitle').textContent = data.name;
+            document.getElementById('popoverType').textContent = data.typeText;
+            document.getElementById('popoverSource').textContent = data.source;
+
+            const relationsEl = document.getElementById('popoverRelations');
+            relationsEl.innerHTML = data.relations.map(r =>
+                `<span class="popover-relation" onclick="showToast('跳转到: ${r}', 'info')">${r}</span>`
+            ).join('');
+
+            const rect = event.currentTarget.getBoundingClientRect();
+            popover.style.top = Math.min(rect.bottom + 8, window.innerHeight - 300) + 'px';
+            popover.style.left = Math.min(rect.left, window.innerWidth - 300) + 'px';
+            popover.classList.add('show');
+        }
+
+        function hideTagPopover() {
+            document.getElementById('elementPopover').classList.remove('show');
+        }
+
+        // === Sync tags from editor content to right-panel lists ===
+        function sanitizeId(name) {
+            return 'tag_' + name.replace(/\s+/g, '_').replace(/[^\w\-]/g, '').toLowerCase();
+        }
+
+        function rgbToHex(rgb) {
+            if (!rgb) return '';
+            const m = rgb.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i);
+            if (!m) return '';
+            const r = parseInt(m[1]), g = parseInt(m[2]), b = parseInt(m[3]);
+            return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
+        }
+
+        function isColorRed(rgb) {
+            if (!rgb) return false;
+            const m = rgb.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i);
+            if (!m) return false;
+            const r = parseInt(m[1]), g = parseInt(m[2]), b = parseInt(m[3]);
+            return (r > 200 && g < 130 && b < 130);
+        }
+
+        function syncTagsFromContent() {
+            try {
+                console.debug('[debug] syncTagsFromContent start');
+                const nodes = document.querySelectorAll('.editor-content .entity-highlight');
+                const dynContainer = document.getElementById('dynamicTags');
+                const statContainer = document.getElementById('staticTags');
+                if (!dynContainer || !statContainer) return;
+
+                // clear containers
+                dynContainer.innerHTML = '';
+                statContainer.innerHTML = '';
+
+                nodes.forEach(node => {
+                    try {
+                        // extract visible text only (exclude badge/span text)
+                        let rawText = '';
+                        node.childNodes.forEach(n => {
+                            if (n.nodeType === Node.TEXT_NODE) rawText += n.textContent;
+                            else if (n.nodeType === Node.ELEMENT_NODE && n.classList && n.classList.contains('tag-name')) rawText += n.textContent;
+                        });
+                        rawText = (rawText || node.textContent || '').trim();
+                        if (!rawText) {
+                            console.debug('[debug] syncTagsFromContent: skipping empty node', node);
+                            return;
+                        }
+
+                        const computed = window.getComputedStyle(node);
+                        let bg = computed.backgroundColor || '';
+                        const border = computed.borderColor || '';
+                        const color = computed.color || '';
+
+                        console.debug('[debug] tag', rawText, { background: bg, border: border, color: color });
+                        // prefer background if not transparent
+                        if (!bg || bg === 'transparent' || bg.indexOf('0, 0, 0, 0') !== -1) {
+                            bg = border || color || '';
+                        }
+
+                        // Improved dynamic detection:
+                        // 1) explicit data-source indicating AI/generated
+                        // 2) presence of a .source-badge.ai inside the node
+                        // 3) existing color-based heuristic (fallback)
+                        let isDynamic = false;
+                        try {
+                            const ds = (node.dataset && node.dataset.source) ? String(node.dataset.source) : '';
+                            const category = (node.dataset && node.dataset.category) ? String(node.dataset.category) : '';
+                            if (ds && /ai|生成|AI/i.test(ds)) {
+                                isDynamic = true;
+                            } else if (category && /市场规模数据|data|AI/i.test(category)) {
+                                isDynamic = true;
+                            } else if (node.querySelector && node.querySelector('.source-badge.ai')) {
+                                isDynamic = true;
+                            } else {
+                                isDynamic = isColorRed(bg) || isColorRed(border) || /#ff4d4f/i.test((bg || '') + (border || ''));
+                            }
+                        } catch (sigErr) {
+                            console.warn('dynamic detection fallback err', sigErr);
+                            isDynamic = isColorRed(bg) || isColorRed(border) || /#ff4d4f/i.test((bg || '') + (border || ''));
+                        }
+
+                        console.debug('[debug] determined isDynamic=', isDynamic, 'for', rawText);
+                        const id = sanitizeId(rawText);
+                        if (!tagData[id]) {
+                            tagData[id] = { icon: '🏷️', type: 'entity', name: rawText, typeText: '来源: 文本', source: '文档', relations: [] };
+                        }
+
+                        const span = document.createElement('span');
+                        span.className = 'element-tag ' + (isDynamic ? 'dynamic' : 'static') + ' mapped';
+                        span.setAttribute('draggable', 'true');
+                        span.onclick = function (e) { e.stopPropagation(); showTagPopover(e, id); };
+                        span.ondragstart = (e) => handleTagDragStart(e, rawText);
+                        span.ondragend = (e) => handleTagDragEnd(e);
+
+                        // apply color styling to match source highlight (if available)
+                        const fill = rgbToHex(bg);
+                        if (fill) {
+                            span.style.background = fill;
+                            // choose light or dark text based on luminance
+                            const hex = fill.replace('#','');
+                            const r = parseInt(hex.substring(0,2),16), g = parseInt(hex.substring(2,4),16), b = parseInt(hex.substring(4,6),16);
+                            const luminance = (0.299*r + 0.587*g + 0.114*b);
+                            span.style.color = luminance > 160 ? '#000' : '#fff';
+                            span.style.border = '1px solid rgba(0,0,0,0.06)';
+                        }
+
+                        span.innerHTML = `<span class="tag-icon">${tagData[id].icon || '🏷️'}</span><span class="tag-name">${rawText}</span>`;
+
+                        if (isDynamic) {
+                            dynContainer.appendChild(span);
+                        }
+                        else statContainer.appendChild(span);
+                    } catch (e) { console.warn('syncTagsFromContent node err', e); }
+                });
+                // post-process: relocate any static tags that are actually red in the editor
+                try { relocateRedStaticTags(dynContainer, statContainer); } catch (e) { console.warn('relocateRedStaticTags err', e); }
+                console.debug('[debug] syncTagsFromContent done', { dynamicCount: dynContainer.children.length, staticCount: statContainer.children.length });
+            } catch (e) { console.warn('syncTagsFromContent err', e); }
+        }
+
+        // Move any tags currently in static container that are red in the editor into dynamic container
+        function relocateRedStaticTags(dynContainer, statContainer) {
+            try {
+                const staticChildren = Array.from(statContainer.children);
+                if (staticChildren.length === 0) return;
+
+                const editorNodes = Array.from(document.querySelectorAll('.editor-content .entity-highlight'));
+
+                staticChildren.forEach(child => {
+                    try {
+                        const nameEl = child.querySelector('.tag-name');
+                        const tagName = nameEl ? nameEl.textContent.trim() : (child.textContent || '').trim();
+                        if (!tagName) return;
+
+                        // find corresponding editor node by exact text match (prefer full match)
+                        const sourceNode = editorNodes.find(n => {
+                            const text = (n.textContent || '').trim();
+                            return text === tagName || text.includes(tagName);
+                        });
+                        if (!sourceNode) return;
+
+                        const cs = window.getComputedStyle(sourceNode);
+                        const bg = cs.backgroundColor || cs.borderColor || cs.color || '';
+                        if (isColorRed(bg)) {
+                            // move element
+                            child.classList.remove('static');
+                            child.classList.add('dynamic');
+                            dynContainer.appendChild(child);
+                            console.debug('[debug] relocated tag to dynamic:', tagName);
+                        }
+                    } catch (e) { console.warn('relocate child err', e); }
+                });
+            } catch (e) { console.warn('relocateRedStaticTags overall err', e); }
+        }
+        // observe editor content changes and sync tags (debounced)
+        (function() {
+            let t = null;
+            document.addEventListener('selectionchange', () => { /* no-op keep event loop active */ });
+            document.addEventListener('DOMContentLoaded', () => {
+                document.querySelectorAll('.editor-content').forEach(editor => {
+                    try {
+                        const mo = new MutationObserver(() => {
+                            clearTimeout(t);
+                            t = setTimeout(() => {
+                                try { syncTagsFromContent(); } catch(e) { console.warn('debounced sync err', e); }
+                            }, 150);
+                        });
+                        mo.observe(editor, { characterData: true, childList: true, subtree: true });
+                    } catch (e) { console.warn('attach mutation observer err', e); }
+                });
+                // initial sync after load
+                try { syncTagsFromContent(); } catch(e) { console.warn('initial syncTagsFromContent err', e); }
+                // ensure tabs trigger a sync when clicked
+                try {
+                    const td = document.getElementById('tabDynamic');
+                    const ts = document.getElementById('tabStatic');
+                    if (td) { td.addEventListener('click', () => { try { syncTagsFromContent(); } catch(e){} }); }
+                    if (ts) { ts.addEventListener('click', () => { try { syncTagsFromContent(); } catch(e){} }); }
+                } catch (e) { console.warn('attach tab click sync err', e); }
+            });
+        })();
+        // 切换动态/静态要素 Tab
+        function switchElementTab(tab) {
+            try {
+                const tabDyn = document.getElementById('tabDynamic');
+                const tabStat = document.getElementById('tabStatic');
+                const dyn = document.getElementById('dynamicTags');
+                const stat = document.getElementById('staticTags');
+
+                if (tab === 'dynamic') {
+                    if (tabDyn) tabDyn.classList.add('active');
+                    if (tabStat) tabStat.classList.remove('active');
+                    if (dyn) dyn.style.display = '';
+                    if (stat) stat.style.display = 'none';
+                    try { syncTagsFromContent(); } catch(e){ console.warn('sync on tab switch err', e); }
+                } else {
+                    if (tabDyn) tabDyn.classList.remove('active');
+                    if (tabStat) tabStat.classList.add('active');
+                    if (dyn) dyn.style.display = 'none';
+                    if (stat) stat.style.display = '';
+                    try { syncTagsFromContent(); } catch(e){ console.warn('sync on tab switch err', e); }
+                }
+            } catch (e) { console.warn('switchElementTab err', e); }
+        }
+
+        function insertTagToEditor() {
+            if (currentTagName) {
+                showToast('已插入要素: ' + currentTagName, 'success');
+            }
+        }
+
+        document.addEventListener('click', function(e) {
+            if (!e.target.closest('.element-popover') && !e.target.closest('.element-tag')) {
+                hideTagPopover();
+            }
+        });
+
+        // === 标签拖拽功能 ===
+        function handleTagDragStart(event, tagName) {
+            currentTagName = tagName;
+            event.currentTarget.classList.add('dragging');
+            event.dataTransfer.setData('text/plain', tagName);
+            event.dataTransfer.effectAllowed = 'copy';
+
+            setTimeout(() => {
+                document.querySelectorAll('.editor-content').forEach(el => {
+                    el.classList.add('drag-over');
+                });
+            }, 0);
+        }
+
+        function handleTagDragEnd(event) {
+            event.currentTarget.classList.remove('dragging');
+            document.querySelectorAll('.editor-content').forEach(el => {
+                el.classList.remove('drag-over');
+            });
+        }
+
+        // 编辑区放置事件
+        document.addEventListener('DOMContentLoaded', function() {
+            const editorContents = document.querySelectorAll('.editor-content');
+            editorContents.forEach(editor => {
+                editor.addEventListener('dragover', function(e) {
+                    e.preventDefault();
+                    e.dataTransfer.dropEffect = 'copy';
+                });
+
+                editor.addEventListener('drop', function(e) {
+                    e.preventDefault();
+                    const tagName = e.dataTransfer.getData('text/plain');
+                    if (tagName) {
+                        showToast('✓ 已插入要素: ' + tagName, 'success');
+                    }
+                    this.classList.remove('drag-over');
+                });
+
+                editor.addEventListener('dragleave', function(e) {
+                    if (!this.contains(e.relatedTarget)) {
+                        this.classList.remove('drag-over');
+                    }
+                });
+            });
+        });
+
+        // === 右键菜单 ===
+        let selectedText = '';
+        let selectedRange = null;
+
+        function showContextMenu(event) {
+            const selection = window.getSelection();
+            selectedText = selection.toString().trim();
+            selectedRange = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
+
+            if (selectedText.length > 0) {
+                event.preventDefault();
+                const menu = document.getElementById('contextMenu');
+                menu.style.top = event.clientY + 'px';
+                menu.style.left = event.clientX + 'px';
+                menu.classList.add('show');
+            }
+        }
+
+        function hideContextMenu() {
+            document.getElementById('contextMenu').classList.remove('show');
+        }
+
+        function execContextAction(action) {
+            hideContextMenu();
+
+            switch(action) {
+                case 'copy':
+                    document.execCommand('copy');
+                    showToast('已复制到剪贴板', 'success');
+                    break;
+                case 'cut':
+                    document.execCommand('cut');
+                    showToast('已剪切', 'success');
+                    break;
+                case 'paste':
+                    document.execCommand('paste');
+                    break;
+                case 'polish':
+                    showAiPolishConfirm();
+                    break;
+                case 'spell':
+                    showSpellCheckConfirm();
+                    break;
+                case 'mark':
+                    markAsEntity();
+                    break;
+                case 'quote':
+                    const aiMessages = document.getElementById('aiMessages');
+                    const quotedText = selectedText.length > 50 ? selectedText.substring(0, 50) + '...' : selectedText;
+                    aiMessages.innerHTML += `
+                        <div class="msg user">
+                            <div class="msg-avatar">张</div>
+                            <div class="msg-bubble">
+                                <div style="padding:8px;background:rgba(255,255,255,0.5);border-radius:6px;margin-bottom:8px;font-size:12px;border-left:3px solid rgba(255,255,255,0.8);">
+                                    📝 引用: "${quotedText}"
+                                </div>
+                                请基于这段内容帮我分析
+                            </div>
+                        </div>
+                    `;
+                    aiMessages.scrollTop = aiMessages.scrollHeight;
+                    showToast('已引用到AI助手', 'success');
+                    break;
+            }
+        }
+
+        // === AI润色确认 ===
+        function showAiPolishConfirm() {
+            const polishedText = `经过AI润色优化:${selectedText.replace(/的/g, '的').replace(/了/g, '了').replace(/和/g, '与')}`;
+            showConfirmDialog(
+                'AI润色确认',
+                `原文: "${selectedText}"<br><br>润色后: "${polishedText}"`,
+                () => applyTextReplacement(polishedText),
+                () => showToast('已取消润色', 'info')
+            );
+        }
+
+        // === 拼写检查确认 ===
+        function showSpellCheckConfirm() {
+            // 模拟拼写检查结果
+            const correctedText = selectedText.replace(/园区/g, '园区').replace(/智慧/g, '智慧');
+            const hasErrors = correctedText !== selectedText;
+
+            if (hasErrors) {
+                showConfirmDialog(
+                    '拼写检查结果',
+                    `发现拼写问题:<br>原文: "${selectedText}"<br>更正后: "${correctedText}"`,
+                    () => applyTextReplacement(correctedText),
+                    () => showToast('已忽略拼写建议', 'info')
+                );
+            } else {
+                showToast('✓ 拼写检查完成,未发现错误', 'success');
+            }
+        }
+
+        // === 标记为要素 ===
+        function markAsEntity() {
+            if (!selectedRange) return;
+
+            const span = document.createElement('span');
+            span.className = 'entity-highlight entity'; // 默认标记为entity类型
+            span.contentEditable = 'false';
+            // 标记来源为人工
+            span.dataset.source = '人工标记';
+            span.dataset.category = 'entity';
+            span.onclick = function(e) { e.stopPropagation(); showDataRelationModal(selectedText, '自定义要素', 'entity', span.dataset.source); };
+            span.textContent = selectedText;
+
+            // 添加来源徽章
+            const badge = document.createElement('span');
+            badge.className = 'source-badge manual';
+            badge.title = '来源:人工标记(点击查看详情)';
+            badge.textContent = '人工';
+            badge.onclick = function(e) { e.stopPropagation(); showDataRelationModal(selectedText, '自定义要素', 'entity', span.dataset.source); };
+            span.appendChild(badge);
+
+            selectedRange.deleteContents();
+            selectedRange.insertNode(span);
+
+            showToast(`✓ 已将"${selectedText}"标记为要素`, 'success');
+        }
+
+        // === 初始化:为已有实体标注添加来源徽章和类型样式(从 onclick 参数或 data-source 推断)===
+        function initializeSourceBadges() {
+            const nodes = document.querySelectorAll('.entity-highlight');
+            nodes.forEach(node => {
+                try {
+                    // 如果已经有 badge,就跳过
+                    if (node.querySelector && node.querySelector('.source-badge')) return;
+
+                    // 优先读取 data-source 和 data-category
+                    let source = node.dataset && node.dataset.source;
+                    let category = node.dataset && node.dataset.category;
+
+                    // 如果没有 data-source或data-category,从 onclick 属性解析参数
+                    if ((!source || !category) && node.getAttribute('onclick')) {
+                        const onclick = node.getAttribute('onclick');
+                        // 解析 showDataRelationModal('name','type','category','sourceFile')
+                        const m = onclick.match(/showDataRelationModal\(([^)]+)\)/);
+                        if (m && m[1]) {
+                            const parts = m[1].split(',').map(s => s.trim());
+                            if (parts.length >= 4) {
+                                if (!category) category = parts[2].replace(/^['"]|['"]$/g, '');
+                                if (!source) source = parts[3].replace(/^['"]|['"]$/g, '');
+                            }
+                        }
+                    }
+
+                    // 为元素添加类型类名(如果还没有的话)
+                    if (category && !node.classList.contains(category)) {
+                        node.classList.add(category);
+                    }
+
+                    // 标记类和徽章文字
+                    let cls = 'file', txt = '文件';
+                    if (!source) { cls = 'manual'; txt = '人工'; source = '未知'; }
+                    else if (/ai/i.test(source) || /生成/.test(source) || source === 'AI') { cls = 'ai'; txt = 'AI'; }
+                    else if (/人工|人工标记/.test(source)) { cls = 'manual'; txt = '人工'; }
+                    else { cls = 'file'; txt = source.split('/').pop(); if (txt.length > 10) txt = txt.slice(0,10) + '…'; }
+
+                    // 保存到dataset
+                    node.dataset.source = source;
+                    node.dataset.category = category || 'entity';
+
+                    const badge = document.createElement('span');
+                    badge.className = `source-badge ${cls}`;
+                    badge.title = `来源:${source}`;
+                    badge.textContent = txt;
+                    badge.onclick = function(e) { e.stopPropagation(); showDataRelationModal(node.textContent, '自定义要素', category || 'entity', source); };
+                    node.appendChild(badge);
+                } catch (err) {
+                    console.error('initializeSourceBadges error', err);
+                }
+            });
+        }
+
+        // === 通用确认对话框 ===
+        function showConfirmDialog(title, content, onConfirm, onCancel) {
+            // 创建确认对话框
+            const dialog = document.createElement('div');
+            dialog.className = 'confirm-dialog';
+            dialog.innerHTML = `
+                <div class="confirm-content">
+                    <div class="confirm-header">
+                        <h3>${title}</h3>
+                        <button class="confirm-close" onclick="closeConfirmDialog(this)">×</button>
+                    </div>
+                    <div class="confirm-body">${content}</div>
+                    <div class="confirm-footer">
+                        <button class="btn" onclick="closeConfirmDialog(this); ${onCancel ? 'setTimeout(() => {' + onCancel.toString().replace(/^function\s*\(\)\s*\{/, '').replace(/}$/, '') + '}, 100)' : ''}">取消</button>
+                        <button class="btn btn-primary" onclick="closeConfirmDialog(this); ${onConfirm ? 'setTimeout(() => {' + onConfirm.toString().replace(/^function\s*\(\)\s*\{/, '').replace(/}$/, '') + '}, 100)' : ''}">确认应用</button>
+                    </div>
+                </div>
+            `;
+            document.body.appendChild(dialog);
+            setTimeout(() => dialog.classList.add('show'), 10);
+        }
+
+        function closeConfirmDialog(btn) {
+            const dialog = btn.closest('.confirm-dialog');
+            dialog.classList.remove('show');
+            setTimeout(() => dialog.remove(), 300);
+        }
+
+        // === 文本替换功能 ===
+        function applyTextReplacement(newText) {
+            if (selectedRange) {
+                selectedRange.deleteContents();
+                selectedRange.insertNode(document.createTextNode(newText));
+                showToast('✓ 内容已更新', 'success');
+            }
+        }
+
+        // 点击其他地方关闭右键菜单
+        document.addEventListener('click', function(e) {
+            if (!e.target.closest('.context-menu')) {
+                hideContextMenu();
+            }
+        });
+
+        // === 实体标签编辑弹窗 ===
+        const entityEditData = {
+            smartpark: {
+                icon: '🏢', name: '智慧园区', type: 'entity', typeText: '核心实体',
+                source: '项目可行性研究报告.docx', originalValue: '智慧园区',
+                relations: ['产业升级', '城市现代化', '智能化管理', '1,789亿元']
+            }
+        };
+
+        let currentEditEntityId = null;
+
+        function showEntityEditModal(event, entityId) {
+            event.preventDefault();
+            event.stopPropagation();
+
+            const data = entityEditData[entityId];
+            if (!data) return;
+
+            currentEditEntityId = entityId;
+
+            document.getElementById('editEntityIcon').textContent = data.icon;
+            document.getElementById('editEntityName').textContent = data.name;
+            document.getElementById('editEntityType').textContent = data.typeText + ' · 来自 ' + data.source;
+            document.getElementById('editEntityValue').value = data.name;
+            document.getElementById('editEntityCategory').value = data.type;
+
+            const relationsEl = document.getElementById('editEntityRelations');
+            relationsEl.innerHTML = data.relations.map(r =>
+                `<span class="popover-relation" onclick="showToast('跳转到: ${r}', 'info')">${r}</span>`
+            ).join('') + `<span style="padding:3px 8px;background:var(--primary-light);border-radius:4px;font-size:11px;color:var(--primary);cursor:pointer;" onclick="showToast('添加关联', 'info')">+ 添加</span>`;
+
+            document.getElementById('entityEditModal').classList.add('show');
+        }
+
+        function closeEntityEditModal() {
+            document.getElementById('entityEditModal').classList.remove('show');
+            currentEditEntityId = null;
+        }
+
+        function saveEntityEdit() {
+            const newValue = document.getElementById('editEntityValue').value;
+            const newCategory = document.getElementById('editEntityCategory').value;
+
+            if (currentEditEntityId && entityEditData[currentEditEntityId]) {
+                entityEditData[currentEditEntityId].name = newValue;
+                entityEditData[currentEditEntityId].type = newCategory;
+                showToast('✓ 标签已更新: ' + newValue, 'success');
+            }
+
+            closeEntityEditModal();
+        }
+
+        // === AI对话 ===
+        function handleAiKey(e) {
+            if (e.key === 'Enter' && !e.shiftKey) {
+                e.preventDefault();
+                sendAiMsg();
+            }
+        }
+
+        function autoResizeTextarea(el) {
+            el.style.height = 'auto';
+            el.style.height = Math.min(el.scrollHeight, 80) + 'px';
+        }
+
+        function sendAiMsg() {
+            const textarea = document.getElementById('aiTextarea');
+            const msg = textarea.value.trim();
+            if (!msg) return;
+
+            const container = document.getElementById('aiMessages');
+            container.innerHTML += '<div class="msg user"><div class="msg-avatar">张</div><div class="msg-bubble">' + msg + '</div></div>';
+            textarea.value = '';
+            textarea.style.height = 'auto';
+            container.scrollTop = container.scrollHeight;
+
+            setTimeout(() => {
+                container.innerHTML += '<div class="msg ai"><div class="msg-avatar">🤖</div><div class="msg-bubble">好的,我来帮您处理这个请求。基于已解析的文档,我找到了相关内容可以补充到报告中。</div></div>';
+                container.scrollTop = container.scrollHeight;
+            }, 1000);
+        }
+
+        // === 视图切换 ===
+        function switchView(view) {
+            const originalBtn = document.getElementById('viewOriginal');
+            const markedBtn = document.getElementById('viewMarked');
+            const originalContent = document.getElementById('contentOriginal');
+            const markedContent = document.getElementById('contentMarked');
+
+            if (view === 'original') {
+                if (originalBtn) originalBtn.classList.add('active');
+                if (markedBtn) markedBtn.classList.remove('active');
+                if (originalContent) originalContent.style.display = 'block';
+                if (markedContent) markedContent.style.display = 'none';
+                showToast('已切换到原文视图 - 显示纯净文档内容', 'info');
+            } else {
+                if (originalBtn) originalBtn.classList.remove('active');
+                if (markedBtn) markedBtn.classList.add('active');
+                if (originalContent) originalContent.style.display = 'none';
+                if (markedContent) markedContent.style.display = 'block';
+                showToast('已切换到标记视图 - 显示AI提取的实体标记和分析内容', 'info');
+            }
+        }
+
+        // === 文件高亮 ===
+        function highlightFile(el) {
+            document.querySelectorAll('.file-item').forEach(f => f.classList.remove('active'));
+            el.classList.add('active');
+        }
+
+        // === 上传模拟 ===
+        function simulateUpload() {
+            showToast('请选择要上传的文件', 'info');
+        }
+
+        // === 导出菜单 ===
+        function showExportMenu(btn) {
+            const menu = document.getElementById('exportMenu');
+            const rect = btn.getBoundingClientRect();
+            menu.style.top = (rect.bottom + 8) + 'px';
+            menu.style.right = (window.innerWidth - rect.right) + 'px';
+            menu.style.display = 'block';
+        }
+
+        function hideExportMenu() {
+            document.getElementById('exportMenu').style.display = 'none';
+        }
+
+        document.addEventListener('click', function(e) {
+            if (!e.target.closest('[onclick*="showExportMenu"]') && !e.target.closest('#exportMenu')) {
+                hideExportMenu();
+            }
+        });
+
+        // === AI Tab切换 ===
+        function switchAiTab(el, tab) {
+            document.querySelectorAll('.ai-tab').forEach(t => t.classList.remove('active'));
+            el.classList.add('active');
+            showToast('切换到 ' + el.textContent.trim(), 'info');
+        }
+
+        // === AI建议 ===
+        function acceptSuggestion() {
+            try {
+                const aiMessages = document.getElementById('aiMessages');
+                if (aiMessages) {
+                    aiMessages.innerHTML += `<div class="msg user"><div class="msg-avatar">张</div><div class="msg-bubble">✓ 我已采纳建议</div></div>`;
+                    aiMessages.innerHTML += `<div class="msg ai"><div class="msg-avatar">🤖</div><div class="msg-bubble">已根据您的采纳更新内容并插入到文档中。</div></div>`;
+                    aiMessages.scrollTop = aiMessages.scrollHeight;
+                }
+                showToast && showToast('✓ 已采纳建议,已发送对话通知', 'success');
+                const card = document.getElementById('aiSuggestionCard');
+                if (card) try { card.remove(); } catch (e) {}
+            } catch (e) { console.warn('acceptSuggestion err', e); }
+        }
+
+        function ignoreSuggestion() {
+            try {
+                const aiMessages = document.getElementById('aiMessages');
+                if (aiMessages) {
+                    aiMessages.innerHTML += `<div class="msg user"><div class="msg-avatar">张</div><div class="msg-bubble">✕ 我已忽略该建议</div></div>`;
+                    aiMessages.innerHTML += `<div class="msg ai"><div class="msg-avatar">🤖</div><div class="msg-bubble">已忽略建议。如需恢复,请在“建议”中查找历史记录。</div></div>`;
+                    aiMessages.scrollTop = aiMessages.scrollHeight;
+                }
+                showToast && showToast('已忽略建议(已转为对话)', 'info');
+                const card = document.getElementById('aiSuggestionCard');
+                if (card) try { card.remove(); } catch (e) {}
+            } catch (e) { console.warn('ignoreSuggestion err', e); }
+        }
+
+        function acceptContentSuggestion() {
+            try {
+                const aiMessages = document.getElementById('aiMessages');
+                if (aiMessages) {
+                    aiMessages.innerHTML += `<div class="msg user"><div class="msg-avatar">张</div><div class="msg-bubble">✓ 请添加建议内容</div></div>`;
+                    aiMessages.innerHTML += `<div class="msg ai"><div class="msg-avatar">🤖</div><div class="msg-bubble">已插入竞争格局分析章节,您可以在文档中查看并编辑。</div></div>`;
+                    aiMessages.scrollTop = aiMessages.scrollHeight;
+                }
+                showToast && showToast('✓ 已添加建议内容(对话形式)', 'success');
+            } catch (e) { console.warn('acceptContentSuggestion err', e); }
+        }
+
+        function insertGeneratedContent() {
+            try {
+                const aiMessages = document.getElementById('aiMessages');
+                if (aiMessages) {
+                    aiMessages.innerHTML += `<div class="msg user"><div class="msg-avatar">张</div><div class="msg-bubble">➕ 插入 AI 生成内容</div></div>`;
+                    aiMessages.innerHTML += `<div class="msg ai"><div class="msg-avatar">🤖</div><div class="msg-bubble">已将 AI 生成的风险分析章节插入到报告中。</div></div>`;
+                    aiMessages.scrollTop = aiMessages.scrollHeight;
+                }
+                showToast && showToast('✓ 已插入 AI 生成内容(对话形式)', 'success');
+                const card = document.querySelector('.ai-generated-card');
+                if (card) try { card.remove(); } catch (e) {}
+            } catch (e) { console.warn('insertGeneratedContent err', e); }
+        }
+
+        // 将 AI 建议卡片移动到 AI 聊天区(以对话形式呈现),避免页面布局错位
+        (function(){
+            function moveCardToChat(cardEl) {
+                if (!cardEl) return false;
+                const aiMessages = document.getElementById('aiMessages');
+                if (!aiMessages) return false;
+                const title = cardEl.querySelector('.ai-suggestion-title') ? cardEl.querySelector('.ai-suggestion-title').textContent : '';
+                const contentEl = cardEl.querySelector('.ai-suggestion-content') || cardEl;
+                const contentHtml = contentEl.innerHTML || cardEl.innerHTML;
+                const wrapper = document.createElement('div');
+                wrapper.className = 'msg ai';
+                wrapper.innerHTML = `<div class="msg-avatar">🤖</div><div class="msg-bubble"><strong>${title}</strong><div style="margin-top:8px;">${contentHtml}</div></div>`;
+                aiMessages.appendChild(wrapper);
+                aiMessages.scrollTop = aiMessages.scrollHeight;
+                return true;
+            }
+
+            document.addEventListener('DOMContentLoaded', function(){
+                try {
+                    const suggest = document.getElementById('aiSuggestionCard');
+                    if (suggest) {
+                        moveCardToChat(suggest);
+                        try { suggest.remove(); } catch(e){}
+                    }
+                    const gen = document.querySelector('.ai-generated-card');
+                    if (gen) {
+                        moveCardToChat(gen);
+                        try { gen.remove(); } catch(e){}
+                    }
+                } catch (e) { console.warn('move AI suggestion to chat err', e); }
+            });
+        })();
+
+        // === Toast ===
+        function showToast(msg, type) {
+            const box = document.getElementById('toastContainer');
+            const icons = { success: '✅', error: '❌', info: 'ℹ️', warning: '⚠️' };
+            const colors = { success: '#f6ffed', error: '#fff1f0', info: 'var(--primary-light)', warning: '#fffbe6' };
+            const textColors = { success: 'var(--success)', error: 'var(--danger)', info: 'var(--primary)', warning: 'var(--warning)' };
+            const toast = document.createElement('div');
+            toast.className = `toast show ${type}`;
+            toast.innerHTML = '<span style="width:24px;height:24px;border-radius:50%;background:' + colors[type] + ';color:' + textColors[type] + ';display:flex;align-items:center;justify-content:center;font-size:12px;">' + icons[type] + '</span><span style="font-size:13px;margin-left:10px;">' + msg + '</span>';
+            box.appendChild(toast);
+            setTimeout(() => {
+                toast.classList.remove('show');
+                setTimeout(() => toast.remove(), 300);
+            }, 3000);
+        }
+
+        // === 关闭所有 ===
+        function closeAll() {
+            document.getElementById('notifPanel').style.transform = 'translateX(100%)';
+            document.getElementById('overlay').style.display = 'none';
+            document.getElementById('fabPanel').style.display = 'none';
+        }
+
+        // === 数据关系表弹窗 ===
+        let currentEntityData = {};
+
+        function showDataRelationModal(entityName, entityType, entityCategory, sourceFile) {
+            currentEntityData = {
+                name: entityName,
+                type: entityType,
+                category: entityCategory,
+                source: sourceFile,
+                originalValue: entityName,
+                currentValue: entityName
+            };
+
+            // 设置弹窗内容
+            document.getElementById('relationEntityName').textContent = entityName;
+            document.getElementById('relationEntityType').textContent = entityType + ' · 来自 ' + (sourceFile || '未知来源');
+
+            // 动态创建或更新来源信息区域(如果 modal HTML 中不存在)
+            let sourceInfoEl = document.getElementById('relationSourceInfo');
+            if (!sourceInfoEl) {
+                const titleEl = document.querySelector('.data-relation-title');
+                if (titleEl) {
+                    sourceInfoEl = document.createElement('div');
+                    sourceInfoEl.id = 'relationSourceInfo';
+                    sourceInfoEl.className = 'relation-source';
+                    sourceInfoEl.style = 'margin-top:6px;font-size:12px;color:var(--text3);';
+                    titleEl.appendChild(sourceInfoEl);
+                }
+            }
+            if (sourceInfoEl) {
+                const safeSource = sourceFile || '未知来源';
+                sourceInfoEl.innerHTML = `来源:<a href="#" id="relationSourceLink" onclick="openSourceFile(event, '${safeSource.replace(/'/g, "\\'")}')">查看来源文件</a>`;
+            }
+
+            // 设置图标
+            const iconEl = document.getElementById('relationIcon');
+            const icons = { entity: '🏢', concept: '💡', data: '📊', location: '📍' };
+            iconEl.textContent = icons[entityCategory] || '🏷️';
+
+            // 生成关系表
+            generateRelationTable(entityName, entityType, entityCategory, sourceFile);
+
+            // 显示弹窗
+            document.getElementById('dataRelationModal').classList.add('show');
+        }
+
+        function generateRelationTable(entityName, entityType, entityCategory, sourceFile) {
+            const tableBody = document.getElementById('relationTableBody');
+            const relationTags = document.getElementById('relationTags');
+
+            // 模拟关系数据
+            const relationData = {
+                '智慧园区': [
+                    { property: '实体名称', original: '智慧园区', current: '智慧园区', canEdit: true },
+                    { property: '实体类型', original: '核心实体', current: '核心实体', canEdit: false },
+                    { property: '数据来源', original: '项目可行性研究报告.docx', current: '项目可行性研究报告.docx', canEdit: false },
+                    { property: '出现次数', original: '8次', current: '8次', canEdit: false }
+                ],
+                '产业升级': [
+                    { property: '概念名称', original: '产业升级', current: '产业升级', canEdit: true },
+                    { property: '概念类型', original: '发展概念', current: '发展概念', canEdit: false },
+                    { property: '数据来源', original: '项目可行性研究报告.docx', current: '项目可行性研究报告.docx', canEdit: false },
+                    { property: '关联强度', original: '高', current: '高', canEdit: false }
+                ],
+                '1,789亿元': [
+                    { property: '数值', original: '1,789亿元', current: '1,789亿元', canEdit: true },
+                    { property: '数据类型', original: '市场规模', current: '市场规模', canEdit: false },
+                    { property: '数据来源', original: '市场调研数据.pdf', current: '市场调研数据.pdf', canEdit: false },
+                    { property: '置信度', original: '95%', current: '95%', canEdit: false }
+                ]
+            };
+
+            const data = relationData[entityName] ? relationData[entityName].slice() : [
+                { property: '标签名称', original: entityName, current: entityName, canEdit: true },
+                { property: '标签类型', original: entityType, current: entityType, canEdit: false },
+                { property: '数据来源', original: sourceFile || '未知来源', current: sourceFile || '未知来源', canEdit: false }
+            ];
+
+            // 确保展示来源文件(优先使用传入的 sourceFile)
+            const hasSourceRow = data.some(r => /来源|数据来源/.test(r.property));
+            if (!hasSourceRow) {
+                data.unshift({ property: '来源文件', original: sourceFile || '未知来源', current: sourceFile || '未知来源', canEdit: false });
+            } else if (sourceFile) {
+                data.forEach(r => {
+                    if (/来源|数据来源/.test(r.property)) {
+                        r.original = sourceFile;
+                        r.current = sourceFile;
+                    }
+                });
+            }
+
+            tableBody.innerHTML = data.map(row => `
+                <tr>
+                    <td>${row.property}</td>
+                    <td class="original">${row.original}</td>
+                    <td class="current">
+                        ${row.canEdit ?
+                            `<input type="text" class="relation-input" value="${row.current}" onchange="updateEntityValue('${row.property}', this.value)">` :
+                            row.current
+                        }
+                    </td>
+                    <td>
+                        ${row.canEdit ? '<button class="btn" onclick="resetEntityValue(this)" style="font-size:11px;padding:4px 8px;">重置</button>' : '-'}
+                    </td>
+                </tr>
+            `).join('');
+
+            // 生成关联标签
+            const relatedEntities = ['产业升级', '城市现代化', '智能化管理', '1,789亿元', '华南地区'];
+            relationTags.innerHTML = relatedEntities.map(entity => `
+                <span class="relation-tag" onclick="showDataRelationModal('${entity}', '关联实体', 'entity', '关联文档')">${entity}</span>
+            `).join('');
+        }
+
+        function updateEntityValue(property, newValue) {
+            currentEntityData.currentValue = newValue;
+            showToast(`已更新 ${property}: ${newValue}`, 'success');
+        }
+
+        function resetEntityValue(btn) {
+            const input = btn.closest('tr').querySelector('.relation-input');
+            input.value = currentEntityData.originalValue;
+            currentEntityData.currentValue = currentEntityData.originalValue;
+            showToast('已重置为原始值', 'info');
+        }
+
+        function saveDataRelationChanges() {
+            if (currentEntityData.currentValue !== currentEntityData.originalValue) {
+                showToast(`标签已更新: ${currentEntityData.originalValue} → ${currentEntityData.currentValue}`, 'success');
+                // 这里可以添加实际的保存逻辑
+            }
+            closeDataRelationModal();
+        }
+
+        function closeDataRelationModal() {
+            document.getElementById('dataRelationModal').classList.remove('show');
+        }
+
+        // === 要素关系图谱 ===
+        function toggleKnowledgeGraph() {
+            const modal = document.getElementById('knowledgeGraphModal');
+            const overlay = document.getElementById('kgOverlay');
+            const btn = document.getElementById('graphBtn');
+            const isOpen = modal.classList.contains('show');
+
+            if (isOpen) {
+                modal.classList.remove('show');
+                overlay.style.display = 'none';
+                if (btn) btn.classList.remove('active');
+            } else {
+                modal.classList.add('show');
+                overlay.style.display = 'block';
+                if (btn) btn.classList.add('active');
+                showToast('已打开要素关系图谱', 'info');
+            }
+        }
+
+        function closeKnowledgeGraph() {
+            const modal = document.getElementById('knowledgeGraphModal');
+            const overlay = document.getElementById('kgOverlay');
+            const btn = document.getElementById('graphBtn');
+            modal.classList.remove('show');
+            overlay.style.display = 'none';
+            if (btn) btn.classList.remove('active');
+        }
+
+        function switchGraphView(view) {
+            const graphView = document.getElementById('graphView');
+            const listView = document.getElementById('listView');
+            const graphBtn = document.getElementById('graphViewBtn');
+            const listBtn = document.getElementById('listViewBtn');
+
+            if (view === 'graph') {
+                graphView.style.display = 'block';
+                listView.style.display = 'none';
+                graphBtn.classList.add('active');
+                listBtn.classList.remove('active');
+                showToast('切换到图谱视图', 'info');
+            } else {
+                graphView.style.display = 'none';
+                listView.style.display = 'block';
+                graphBtn.classList.remove('active');
+                listBtn.classList.add('active');
+                showToast('切换到列表视图', 'info');
+            }
+        }
+
+        function filterEntities(query) {
+            const items = document.querySelectorAll('.entity-item');
+            const lowerQuery = query.toLowerCase();
+
+            items.forEach(item => {
+                const name = item.querySelector('.entity-name').textContent.toLowerCase();
+                if (name.includes(lowerQuery) || query === '') {
+                    item.style.display = 'flex';
+                } else {
+                    item.style.display = 'none';
+                }
+            });
+        }
+
+        function highlightEntity(entityName) {
+            // 高亮图谱中的节点
+            document.querySelectorAll('.graph-node').forEach(node => {
+                node.classList.remove('highlighted');
+                if (node.dataset.entity === entityName) {
+                    node.classList.add('highlighted');
+                    node.scrollIntoView({ behavior: 'smooth', block: 'center' });
+                }
+            });
+            showToast('已高亮要素: ' + entityName, 'info');
+        }
+
+        function locateEntity(entityName) {
+            closeKnowledgeGraph();
+            // 切换到标记视图
+            switchView('marked');
+            // 滚动到对应位置(这里可以根据实际情况调整)
+            showToast('已定位到要素: ' + entityName, 'success');
+        }
+
+        function editEntity(entityName) {
+            showToast('编辑要素: ' + entityName, 'info');
+            // 这里可以打开要素编辑弹窗
+        }
+
+        // 图谱节点点击事件
+        document.addEventListener('DOMContentLoaded', function() {
+            document.querySelectorAll('.graph-node').forEach(node => {
+                node.addEventListener('click', function() {
+                    const entityName = this.dataset.entity;
+                    highlightEntity(entityName);
+                });
+            });
+        });
+        
+        // 页面加载后初始化来源徽章
+        document.addEventListener('DOMContentLoaded', function() {
+            try {
+                if (typeof initializeSourceBadges === 'function') initializeSourceBadges();
+            } catch (e) {
+                console.warn('initializeSourceBadges error', e);
+            }
+        });
+
+        // === 段落选中与交互控制 ===
+        // 将光标所在段落标记为 selected,仅高亮该段
+        function updateSelectedParagraph() {
+            try {
+                const sel = window.getSelection();
+                if (!sel || sel.rangeCount === 0) return;
+                const anchor = sel.anchorNode;
+                if (!anchor) return;
+
+                // 找到包含光标的段落元素(p 或 div 作段落)
+                let paragraph = null;
+                if (anchor.nodeType === Node.TEXT_NODE) paragraph = anchor.parentElement.closest('p, div');
+                else if (anchor.nodeType === Node.ELEMENT_NODE) paragraph = anchor.closest('p, div');
+
+                // 仅在编辑区内生效
+                document.querySelectorAll('.editor-content p, .editor-content div').forEach(el => el.classList.remove('selected'));
+                if (paragraph && paragraph.closest('.editor-content')) {
+                    paragraph.classList.add('selected');
+                }
+            } catch (e) {
+                console.warn('updateSelectedParagraph error', e);
+            }
+        }
+
+        // 监听选择变化、点击、键盘输入以更新段落选中状态
+        document.addEventListener('selectionchange', () => {
+            const active = document.activeElement;
+            if (active && active.classList && active.classList.contains('editor-content')) {
+                updateSelectedParagraph();
+            }
+        });
+
+        // 点击编辑区也触发更新(兼容鼠标点击)
+        document.querySelectorAll('.editor-content').forEach(editor => {
+            editor.addEventListener('click', updateSelectedParagraph);
+            editor.addEventListener('keyup', updateSelectedParagraph);
+            editor.addEventListener('input', updateSelectedParagraph);
+        });
+
+        // 点击页面其它区域时清除段落选中样式
+        document.addEventListener('click', (e) => {
+            if (!e.target.closest('.editor-content')) {
+                document.querySelectorAll('.editor-content p.selected, .editor-content div.selected').forEach(p => p.classList.remove('selected'));
+            }
+        });
+
+        // === AI润色/拼写确认与文本替换(右键) ===
+        // showAiPolishConfirm / showSpellCheckConfirm / applyTextReplacement 已定义于右键逻辑区域
+
+        // === 初始化 ===
+        setTimeout(() => showToast('欢迎使用灵越智报平台 🎉', 'success'), 500);
+
+        // 更新欢迎语
+        (function() {
+            const hour = new Date().getHours();
+            let greeting = '早上好';
+            if (hour >= 12 && hour < 18) greeting = '下午好';
+            else if (hour >= 18) greeting = '晚上好';
+            const el = document.querySelector('.welcome h1');
+            if (el) el.innerHTML = greeting + ',张三!<span>智能报告,洞察未来。</span>';
+        })();
+
+        // 模拟解析进度
+        let progress1 = 65;
+        setInterval(() => {
+            progress1 += Math.random() * 3;
+            if (progress1 >= 100) {
+                progress1 = 100;
+                const el = document.querySelector('#parsingFile1 .file-status');
+                if (el) {
+                    el.textContent = '✓ 已完成';
+                    el.className = 'file-status done';
+                }
+            } else {
+                const el = document.querySelector('#parsingFile1 .file-status');
+                if (el && el.classList.contains('parsing')) {
+                    el.textContent = '📊 解析中 ' + Math.floor(progress1) + '%';
+                }
+            }
+        }, 2000);
+
+        // === 文件项交互(悬浮图标、解析弹窗、查看/引用/删除) ===
+        function initializeFileActions() {
+            document.querySelectorAll('.file-item').forEach(item => {
+                try {
+                    const statusEl = item.querySelector('.file-status');
+                    const statusParsing = statusEl && statusEl.classList.contains('parsing');
+                    const statusDone = statusEl && statusEl.classList.contains('done');
+
+                    // store demo content for viewing/引用
+                    if (!item.dataset.content) {
+                        item.dataset.content = `【${item.querySelector('.file-name') ? item.querySelector('.file-name').textContent : '文档'}】原文预览:这是用于演示的文档内容片段。`;
+                    }
+
+                    // create actions container
+                    let actions = item.querySelector('.file-actions');
+                    if (!actions) {
+                        actions = document.createElement('div');
+                        actions.className = 'file-actions';
+                        item.appendChild(actions);
+                    }
+
+                    actions.innerHTML = '';
+
+                    if (statusParsing) {
+                        // parsing: show delete icon on hover
+                        const delBtn = document.createElement('div');
+                        delBtn.className = 'action-btn';
+                        delBtn.title = '删除';
+                        delBtn.innerHTML = '🗑️';
+                        delBtn.onclick = (e) => { e.stopPropagation(); deleteFile(item); };
+                        actions.appendChild(delBtn);
+
+                        // clicking the file shows parsing popover
+                        item.onclick = (e) => { e.stopPropagation(); showParsingPopover(item); };
+                    } else {
+                        // done: show view, quote, delete
+                        const viewBtn = document.createElement('div');
+                        viewBtn.className = 'action-btn';
+                        viewBtn.title = '查看';
+                        viewBtn.innerHTML = '👁️';
+                        viewBtn.onclick = (e) => { e.stopPropagation(); showFilePreview(item); };
+                        actions.appendChild(viewBtn);
+
+                        const quoteBtn = document.createElement('div');
+                        quoteBtn.className = 'action-btn';
+                        quoteBtn.title = '引用到AI助手';
+                        quoteBtn.innerHTML = '🔗';
+                        quoteBtn.onclick = (e) => { e.stopPropagation(); quoteFileToAI(item); };
+                        actions.appendChild(quoteBtn);
+
+                        const delBtn = document.createElement('div');
+                        delBtn.className = 'action-btn';
+                        delBtn.title = '删除';
+                        delBtn.innerHTML = '🗑️';
+                        delBtn.onclick = (e) => { e.stopPropagation(); deleteFile(item); };
+                        actions.appendChild(delBtn);
+
+                        // clicking file selects it (preview)
+                        item.onclick = (e) => { e.stopPropagation(); showFilePreview(item); };
+                    }
+                } catch (err) { console.error('init file action', err); }
+            });
+        }
+
+        // 左侧 tabs 切换
+        function switchLeftTab(tab) {
+            const docs = document.getElementById('leftDocsSection');
+            const files = document.getElementById('leftFilesSection');
+
+            // safely toggle primary tab elements (some templates may use different ids)
+            const tabDocsEl = document.getElementById('tabDocs');
+            const tabFilesEl = document.getElementById('tabFiles');
+            if (tabDocsEl) tabDocsEl.classList.toggle('active', tab === 'docs');
+            if (tabFilesEl) tabFilesEl.classList.toggle('active', tab === 'files');
+
+            // sync top header tabs if present (these IDs exist in the DOM)
+            const topDocs = document.getElementById('tabDocsTop');
+            const topFiles = document.getElementById('tabFilesTop');
+            if (topDocs) topDocs.classList.toggle('active', tab === 'docs');
+            if (topFiles) topFiles.classList.toggle('active', tab === 'files');
+            // Keep the left panel split into two parts:
+            //  - top: dynamic area (.docs-area) that shows either "我的文档" or "我的附件"
+            //  - bottom: .recent-area (always visible)
+            const docsArea = docs ? docs.querySelector('.docs-area') : null;
+            const recentArea = docs ? docs.querySelector('.recent-area') : null;
+
+            // Ensure the leftDocsSection is visible (we render top content into docsArea)
+            if (docs) docs.style.display = '';
+            if (files) files.style.display = 'none'; // keep files section unused visually
+            if (recentArea) recentArea.style.display = '';
+
+            if (tab === 'docs') {
+                // show documents list in the top area
+                if (docsArea) {
+                    docsArea.style.display = '';
+                    // re-render / sort documents if function exists
+                    try { if (typeof updateReportsCountAndSort === 'function') updateReportsCountAndSort(); } catch (e) { console.warn('updateReportsCountAndSort err', e); }
+                    // restore header title to "报告记录"
+                    try {
+                        const reportsTitleEl = document.getElementById('reportsTitle');
+                        const reportsCountEl = document.getElementById('reportsCount');
+                        if (reportsTitleEl && reportsTitleEl.firstChild) reportsTitleEl.firstChild.nodeValue = '报告记录 ';
+                        if (reportsCountEl) {
+                            // updateReportsCountAndSort already sets count, but ensure display format
+                            reportsCountEl.textContent = reportsCountEl.textContent || '· ' + (document.querySelectorAll('#leftDocsSection .doc-card').length || 0);
+                        }
+                    } catch (ee) { console.warn('restore reports title err', ee); }
+                }
+            } else {
+                // show attachments list in the same top area
+                if (docsArea) {
+                    docsArea.style.display = '';
+                    try { if (typeof renderAttachments === 'function') renderAttachments(); } catch (e) { console.warn('renderAttachments err', e); }
+                }
+            }
+        }
+
+        // 更新报告计数并按时间倒序排列列表
+        function updateReportsCountAndSort() {
+            try {
+                const list = document.querySelector('#leftDocsSection .doc-list');
+                if (!list) return;
+                const items = Array.from(list.querySelectorAll('.doc-card'));
+                // parse date from .doc-time like "2026/1/26 11:51:44"
+                items.sort((a, b) => {
+                    const ta = a.querySelector('.doc-time') ? new Date(a.querySelector('.doc-time').textContent.replace(/-/g, '/')) : new Date(0);
+                    const tb = b.querySelector('.doc-time') ? new Date(b.querySelector('.doc-time').textContent.replace(/-/g, '/')) : new Date(0);
+                    return tb - ta;
+                });
+                // re-append in sorted order
+                items.forEach(it => list.appendChild(it));
+                // update count
+                const count = items.length;
+                const rc = document.getElementById('reportsCount');
+                if (rc) rc.textContent = '· ' + count;
+                const leftBadge = document.getElementById('leftDocsCount');
+                if (leftBadge) leftBadge.textContent = count;
+            } catch (e) { console.warn('updateReportsCountAndSort err', e); }
+        }
+
+        document.addEventListener('DOMContentLoaded', function() {
+            try { updateReportsCountAndSort(); } catch (e) {}
+            // wire up search/new buttons (placeholders)
+            const searchBtn = document.getElementById('leftSearchBtn');
+            if (searchBtn) searchBtn.onclick = () => { const q = prompt('搜索报告:'); if (q) alert('搜索: ' + q); };
+            const newBtn = document.getElementById('newReportBtn');
+            if (newBtn) newBtn.onclick = () => { alert('新建报告(示意)'); };
+        });
+
+        let currentParsingPopover = null;
+        function showParsingPopover(item) {
+            closeParsingPopover();
+            const rect = item.getBoundingClientRect();
+            const pop = document.createElement('div');
+            pop.className = 'parsing-popover';
+            pop.style.left = Math.min(rect.right + 12, window.innerWidth - 340) + 'px';
+            pop.style.top = Math.max(rect.top, 80) + 'px';
+            pop.innerHTML = `<div class="close-btn" onclick="closeParsingPopover()">×</div>
+                <div class="title"><div>解析过程 — ${item.querySelector('.file-name') ? item.querySelector('.file-name').textContent : ''}</div></div>
+                <div class="parsing-progress">
+                    <span class="seg active"></span>
+                    <span class="seg"></span>
+                    <span class="seg"></span>
+                    <span class="seg"></span>
+                    <span class="seg"></span>
+                </div>
+                <div class="steps-list">
+                    <div class="step active"><div class="dot"></div><div class="label">文档读取</div></div>
+                    <div class="step pending"><div class="dot"></div><div class="label">结构解析</div></div>
+                    <div class="step pending"><div class="dot"></div><div class="label">实体提取</div></div>
+                    <div class="step pending"><div class="dot"></div><div class="label">关系分析</div></div>
+                    <div class="step pending"><div class="dot"></div><div class="label">图谱构建</div></div>
+                </div>
+                <div style="margin-top:10px;font-size:12px;color:var(--text3);">注:此为演示流程,实际解析时间取决于文档大小与系统性能。</div>`;
+            document.body.appendChild(pop);
+            currentParsingPopover = pop;
+
+            // simulate progress steps (vertical, completed=green, active=blue, pending=gray)
+            let idx = 0;
+            const steps = pop.querySelectorAll('.step');
+            const segs = pop.querySelectorAll('.parsing-progress .seg');
+            // ensure initial classes: first active, others pending
+            steps.forEach((s, i) => {
+                if (i === 0) { s.classList.remove('pending'); s.classList.add('active'); }
+                else { s.classList.remove('active'); s.classList.add('pending'); }
+            });
+            const t = setInterval(() => {
+                // mark previous as completed
+                if (idx > 0 && steps[idx-1]) {
+                    steps[idx-1].classList.remove('active');
+                    steps[idx-1].classList.remove('pending');
+                    steps[idx-1].classList.add('completed');
+                }
+                // set current as active
+                if (idx < steps.length && steps[idx]) {
+                    steps[idx].classList.remove('pending');
+                    steps[idx].classList.remove('completed');
+                    steps[idx].classList.add('active');
+                }
+                // update segs
+                segs.forEach((s, i) => {
+                    if (i < idx) s.classList.add('active');
+                    else s.classList.remove('active');
+                });
+                idx++;
+                if (idx > steps.length) {
+                    clearInterval(t);
+                    // mark last as completed
+                    if (steps[steps.length-1]) {
+                        steps[steps.length-1].classList.remove('active');
+                        steps[steps.length-1].classList.remove('pending');
+                        steps[steps.length-1].classList.add('completed');
+                    }
+                    showToast('解析完成:已生成要素与图谱', 'success');
+                    // update status to done for demo
+                    const statusEl = item.querySelector('.file-status');
+                    if (statusEl) { statusEl.textContent = '✓ 已完成'; statusEl.className = 'file-status done'; }
+                    initializeFileActions();
+                    closeParsingPopover();
+                }
+            }, 900);
+        }
+
+        function closeParsingPopover() {
+            if (currentParsingPopover) { currentParsingPopover.remove(); currentParsingPopover = null; }
+        }
+        // === 本地文件预览映射与本地上下文存储(演示 / 可替换为后端接口) ===
+        const fileContentsMap = {
+            '市场调研数据.pdf': '【市场调研数据.pdf】\\n摘要:本报告基于2024年全国范围抽样调研,市场规模、增长率、细分行业表现等关键指标已整理。',
+            '技术方案说明.pdf': '【技术方案说明.pdf】\\n摘要:本文档描述了平台架构、数据接入与解析流程、实体抽取模型与接口。',
+            '项目可行性研究报告.docx': '【项目可行性研究报告.docx】\\n原文节选:本项目位于华南地区,规划总面积约50万平方米,预计总投资12.5亿元。',
+            '财务预测表.xlsx': '【财务预测表.xlsx】\\n表格摘要:收入、利润、投资回收期与分年度预测数据(见表格)。'
+        };
+
+        const localKnowledgeContext = {
+            files: {},
+            addFile(fileName, content) { this.files[fileName] = content; },
+            removeFile(fileName) { delete this.files[fileName]; },
+            listFiles() { return Object.keys(this.files); },
+            getCombinedContext() { return Object.values(this.files).join('\\n\\n'); }
+        };
+
+        function showFilePreview(item) {
+            // 使用大弹窗模态展示文件预览(不再在右侧显示)
+            closeFilePreview();
+            const nameEl = item.querySelector('.file-name');
+            const fileName = nameEl ? nameEl.textContent.trim() : null;
+            const content = (fileName && fileContentsMap[fileName]) ? fileContentsMap[fileName] : (item.dataset.content || (fileName ? `原文:${fileName}` : '无预览内容'));
+
+            const overlay = document.createElement('div');
+            overlay.className = 'file-preview-modal-overlay';
+
+            const modal = document.createElement('div');
+            modal.className = 'file-preview-modal';
+            modal.innerHTML = `
+                <div class="modal-header">
+                    <div class="modal-title">${fileName || '文件预览'}</div>
+                    <div style="font-size:12px;color:var(--text3)">${new Date().toLocaleString()}</div>
+                </div>
+                <button class="file-preview-close" onclick="closeFilePreview()">×</button>
+                <div class="modal-body" id="filePreviewContent">${content}</div>
+            `;
+
+            overlay.appendChild(modal);
+            document.body.appendChild(overlay);
+            // prevent scrolling behind modal
+            document.body.style.overflow = 'hidden';
+            showToast('已打开文件预览弹窗', 'info');
+        }
+
+        function closeFilePreview() {
+            const overlay = document.querySelector('.file-preview-modal-overlay');
+            if (overlay) overlay.remove();
+            document.body.style.overflow = '';
+        }
+
+        // 将文件内容加入本地上下文(用于模拟后端检索/聊天上下文)
+        function quoteFileToAI(item) {
+            const nameEl = item.querySelector('.file-name');
+            const fileName = nameEl ? nameEl.textContent.trim() : ('文件_' + Date.now());
+            const content = (fileName && fileContentsMap[fileName]) ? fileContentsMap[fileName] : (item.dataset.content || fileName);
+
+            localKnowledgeContext.addFile(fileName, content);
+
+            const aiMessages = document.getElementById('aiMessages');
+            const msg = `[知识背景引用] 已将 ${fileName} 的内容加入本地上下文。当前上下文文件:${localKnowledgeContext.listFiles().join(', ')}`;
+            if (aiMessages) {
+                aiMessages.innerHTML += `
+                    <div class="msg user">
+                        <div class="msg-avatar">张</div>
+                        <div class="msg-bubble">${msg}</div>
+                    </div>
+                `;
+                aiMessages.scrollTop = aiMessages.scrollHeight;
+            }
+            showToast('已把文件内容加入本地上下文,用于AI检索/问答(模拟)', 'success');
+        }
+
+        function deleteFile(item) {
+            const name = item.querySelector('.file-name') ? item.querySelector('.file-name').textContent : '文件';
+            if (!confirm(`确认删除 "${name}" 吗?`)) return;
+            item.remove();
+            showToast(`已删除 ${name}`, 'info');
+        }
+
+        // === 我的附件(左侧)渲染与操作 ===
+        // 附件示例数据(显示为样例截图中的文件名与大小,parsedAt 用于排序)
+        let attachmentsData = [
+            { name: '市场调研数据.pdf', size: '5.8 MB', parsedAt: '2026-01-27T10:00:00' },
+            { name: '技术方案说明.pdf', size: '3.6 MB', parsedAt: '2026-01-26T16:00:00' },
+            { name: '项目可行性研究报告.docx', size: '2.4 MB', parsedAt: '2026-01-25T09:00:00' },
+            { name: '财务预测表.xlsx', size: '1.2 MB', parsedAt: '2026-01-24T11:30:00' },
+            { name: '会议纪要.md', size: '48 KB', parsedAt: '2026-01-23T08:00:00' }
+        ];
+
+        function formatParsedAt(iso) {
+            const d = new Date(iso);
+            if (isNaN(d)) return iso;
+            const pad = n => n.toString().padStart(2, '0');
+            return `${d.getFullYear()}/${d.getMonth()+1}/${d.getDate()} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
+        }
+
+        function getIconForName(name) {
+            const ext = (name.split('.').pop() || '').toLowerCase();
+            if (ext === 'xlsx') return '<span class="file-badge xls">XLS</span>';
+            if (ext === 'docx' || ext === 'doc') return '<span class="file-badge doc">DOC</span>';
+            if (ext === 'pdf') return '<span class="file-badge pdf">PDF</span>';
+            if (ext === 'md' || ext === 'txt') return '<span class="file-badge md">MD</span>';
+            return '<span class="file-badge">FILE</span>';
+        }
+
+        function renderAttachments() {
+            // Render into the left files top area by default (original behavior).
+            // Fallback to leftDocsSection top area only if files area is missing.
+            let container = document.querySelector('#leftFilesSection .doc-list');
+            if (!container) container = document.querySelector('#leftDocsSection .docs-area .doc-list');
+            if (!container) return;
+
+            // sort by parsedAt desc
+            attachmentsData.sort((a, b) => new Date(b.parsedAt) - new Date(a.parsedAt));
+
+            container.innerHTML = attachmentsData.map(att => {
+                return `
+                    <div class="doc-card file-item" data-name="${att.name}" data-parsedat="${att.parsedAt}">
+                        <div class="doc-thumb">${getIconForName(att.name)}</div>
+                        <div class="file-actions" style="display:flex;gap:6px;">
+                            <button class="action-btn" title="查看" onclick="showFilePreview(this.closest('.file-item'))">👁️</button>
+                            <button class="action-btn" title="引用到AI助手" onclick="quoteFileToAI(this.closest('.file-item'))">🔗</button>
+                            <button class="action-btn" title="删除" onclick="deleteAttachment(this.closest('.file-item'))">🗑️</button>
+                        </div>
+                        <div class="doc-meta">
+                            <div class="file-name">${att.name}</div>
+                            <div class="file-time">${att.size} · <span style="color:var(--success);font-weight:600;">✓ 已完成</span></div>
+                        </div>
+                    </div>
+                `;
+            }).join('');
+
+            // update header title/count to "全部附件"
+            try {
+                const reportsTitleEl = document.getElementById('reportsTitle');
+                const reportsCountEl = document.getElementById('reportsCount');
+                if (reportsTitleEl && reportsTitleEl.firstChild) reportsTitleEl.firstChild.nodeValue = '全部附件 ';
+                if (reportsCountEl) reportsCountEl.textContent = '· ' + attachmentsData.length;
+            } catch (e) { console.warn('update reports title err', e); }
+
+            // ensure hover/action wiring consistent
+            initializeFileActions();
+        }
+
+        function deleteAttachment(item) {
+            const name = item.querySelector('.file-name') ? item.querySelector('.file-name').textContent : '文件';
+            if (!confirm(`确认删除 "${name}" 吗?`)) return;
+            // remove from DOM
+            item.remove();
+            // remove from data model
+            attachmentsData = attachmentsData.filter(a => a.name !== name);
+            showToast(`已删除 ${name}`, 'info');
+        }
+
+        // 自动在 DOM 加载后渲染附件列表
+        document.addEventListener('DOMContentLoaded', function() {
+            try { 
+                console.debug('[debug] DOMContentLoaded: calling renderAttachments()');
+                renderAttachments(); 
+            } catch (e) { console.warn('renderAttachments err', e); }
+        });
+
+        // 安全绑定:确保顶部左右 tab 按钮可用并在页面刷新后渲染附件(防止浏览器缓存/执行顺序问题)
+        document.addEventListener('DOMContentLoaded', function() {
+            try {
+                const tabDocsTop = document.getElementById('tabDocsTop');
+                const tabFilesTop = document.getElementById('tabFilesTop');
+                if (tabDocsTop) {
+                    try { tabDocsTop.removeAttribute('onclick'); } catch(e){}
+                    tabDocsTop.addEventListener('click', () => { console.debug('[debug] tabDocsTop clicked'); switchLeftTab('docs'); });
+                }
+                if (tabFilesTop) {
+                    try { tabFilesTop.removeAttribute('onclick'); } catch(e){}
+                    tabFilesTop.addEventListener('click', () => { console.debug('[debug] tabFilesTop clicked'); switchLeftTab('files'); });
+                }
+
+                // Force a re-render after a short delay to work around stale caches or race conditions
+                setTimeout(() => {
+                    try { console.debug('[debug] delayed renderAttachments() executing'); if (typeof renderAttachments === 'function') renderAttachments(); } catch (e) { console.warn('delayed renderAttachments err', e); }
+                }, 200);
+            } catch (err) { console.warn('init tabs binding err', err); }
+        });
+
+        // call initializer after DOM ready
+        document.addEventListener('DOMContentLoaded', function() {
+            try { initializeFileActions(); } catch (e) { console.warn('init file actions err', e); }
+            try { openEditor(); } catch (e) { console.warn('openEditor init err', e); }
+        });
+        // 确保左侧资源默认不选中任何文件
+        document.addEventListener('DOMContentLoaded', function() {
+            try {
+                document.querySelectorAll('.left-panel .file-item.active').forEach(el => el.classList.remove('active'));
+            } catch (e) { console.warn('clear active', e); }
+        });
+
+        // === 左侧资源面板 折叠/展开 控制 ===
+        function toggleResourcePanel(btn) {
+            const panel = document.querySelector('.left-panel');
+            if (!panel) return;
+            const isHidden = panel.dataset && panel.dataset.collapsed === 'true';
+            if (!isHidden) {
+                // collapse
+                panel.dataset.collapsed = 'true';
+                panel.style.display = 'none';
+                if (btn) btn.textContent = '❯';
+                // create small floating expand button
+                let expand = document.getElementById('resourceExpandBtn');
+                if (!expand) {
+                    expand = document.createElement('button');
+                    expand.id = 'resourceExpandBtn';
+                    expand.className = 'resource-expand-btn';
+                    expand.title = '展开资源面板';
+                    expand.innerHTML = '≡';
+                    expand.onclick = () => {
+                        expand.remove();
+                        panel.dataset.collapsed = 'false';
+                        panel.style.display = '';
+                        const pbtn = document.querySelector('.panel-toggle-btn');
+                        if (pbtn) pbtn.textContent = '❮';
+                    };
+                    document.body.appendChild(expand);
+                }
+            } else {
+                // expand
+                panel.dataset.collapsed = 'false';
+                panel.style.display = '';
+                if (btn) btn.textContent = '❮';
+                const expand = document.getElementById('resourceExpandBtn');
+                if (expand) expand.remove();
+            }
+        }
+    </script>
+    <script>
+        // 页面级别强制:所有导航重定向到编辑器,并确保编辑器在初次打开时是可见的
+        try {
+            // 覆盖 navTo,以防止任何后续脚本或事件跳回首页/模板等
+            window.navTo = function(page) {
+                try { if (typeof openEditor === 'function') openEditor(); } catch (e) { console.warn('navTo override err', e); }
+                return;
+            };
+
+            // 隐藏主内容并显示编辑器(双保险,防止样式闪烁)
+            try {
+                const mc = document.getElementById('mainContent');
+                if (mc) mc.style.display = 'none';
+                const pe = document.getElementById('page-editor');
+                if (pe) pe.classList.add('active');
+                // remove active state from other pages
+                document.querySelectorAll('.page.active').forEach(p => { if (p.id !== 'page-editor') p.classList.remove('active'); });
+            } catch (e) { console.warn('editor show err', e); }
+        } catch (e) {
+            console.warn('page-level override init err', e);
+        }
+    </script>
+    <script>
+        // 扫描并禁用所有内联 onclick 中的 openEditor/navTo(最终保障)
+        try {
+            document.querySelectorAll('[onclick]').forEach(el => {
+                try {
+                    const v = el.getAttribute('onclick') || '';
+                    if (/\bopenEditor\s*\(|\bnavTo\s*\(/.test(v)) {
+                        el.setAttribute('onclick', 'void(0)');
+                        if (el.style) el.style.cursor = 'default';
+                    }
+                } catch (e) {}
+            });
+        } catch (e) { console.warn('final disable onclicks err', e); }
+    </script>
+    <script>
+        // 切换原文/标记(函数)
+        function toggleView() {
+          try {
+            const ori = document.getElementById('contentOriginal');
+            const mk  = document.getElementById('contentMarked');
+            const btn = document.getElementById('toggleViewBtn');
+            if (!ori || !mk || !btn) return;
+
+            // 切换视图显示
+            if (ori.style.display === 'none') {
+              ori.style.display = '';
+              mk.style.display = 'none';
+            } else {
+              ori.style.display = 'none';
+              mk.style.display = '';
+            }
+
+            // 切换按钮内的 icon(在两种 icon 之间切换)
+            try {
+              const hasBig = btn.querySelector && btn.querySelector('.icon-BIG_PROMOTION');
+              if (hasBig) {
+                btn.innerHTML = '<i class="iconfont icon-BASE_INFO"></i>';
+              } else {
+                btn.innerHTML = '<i class="iconfont icon-BIG_PROMOTION"></i>';
+              }
+            } catch (iconErr) {
+              console.warn('toggleView icon swap err', iconErr);
+            }
+          } catch (e) { console.warn('toggleView err', e); }
+        }
+      
+        // 绑定(以防内联 onclick 被覆写)
+        document.addEventListener('DOMContentLoaded', function () {
+          const tv = document.getElementById('toggleViewBtn');
+          if (tv) {
+            // remove any broken inline onclick and attach a robust listener
+            try { tv.removeAttribute('onclick'); } catch(e) {}
+            tv.addEventListener('click', toggleView);
+          }
+      
+          // 搜索按钮 -> 聚焦顶部搜索框
+          const searchBtn = document.getElementById('leftSearchBtn');
+          if (searchBtn) {
+            searchBtn.removeAttribute('onclick');
+            searchBtn.addEventListener('click', () => {
+              const topSearch = document.querySelector('.top-search') || document.querySelector('.search-input') || document.querySelector('.top-search-input');
+              if (topSearch) { topSearch.focus(); if (typeof topSearch.select === 'function') topSearch.select(); }
+            });
+          }
+      
+          // 新建报告按钮 -> 在左侧插入示例新报告并进入编辑
+          const newBtn = document.getElementById('newReportBtn');
+          if (newBtn) {
+            newBtn.removeAttribute('onclick');
+            newBtn.addEventListener('click', () => {
+              try {
+                const list = document.querySelector('#leftDocsSection .doc-list');
+                if (!list) return;
+                const now = new Date();
+                const pad = n => n.toString().padStart(2,'0');
+                const fmt = `${now.getFullYear()}/${now.getMonth()+1}/${now.getDate()} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
+                const card = document.createElement('div');
+                card.className = 'doc-card file-item';
+                card.setAttribute('data-name', '新建报告 - 未命名');
+                card.innerHTML = `<div class="doc-thumb">📄</div>
+                  <div class="doc-meta" style="width:100%;">
+                    <div class="doc-title">新建报告 - 未命名</div>
+                    <div style="display:flex;gap:10px;margin-top:8px;font-size:13px;color:var(--text2);">
+                      <span>📅 ${fmt}</span><span>👤 我</span>
+                    </div>
+                  </div>`;
+                card.addEventListener('click', function(e){ e.stopPropagation(); showFilePreview(this); });
+                list.insertBefore(card, list.firstChild);
+                // update count/sort if function exists
+                if (typeof updateReportsCountAndSort === 'function') updateReportsCountAndSort();
+                // open editor if available
+                try { if (typeof openEditor === 'function') openEditor(); } catch(e){}
+              } catch (e) { console.warn('new report err', e); }
+            });
+          }
+      
+          // 安全绑定:给每个悬浮操作按钮(若存在)绑定实现(防止 inline 被清空)
+          document.querySelectorAll('.action-btn').forEach(btn => {
+            // if already has onclick via attribute, keep; else attach noop handlers for clarity
+            if (!btn.onclick) {
+              const t = btn.title || btn.getAttribute('title') || '';
+              if (t.includes('下载') || t.includes('下载')) btn.addEventListener('click', () => { downloadReport(btn); });
+              else if (t.includes('归档')) btn.addEventListener('click', () => { archiveReport(btn); });
+              else if (t.includes('删除')) btn.addEventListener('click', () => { deleteReport(btn); });
+            }
+          });
+        });
+      
+        // 占位:下载/归档/删除(若页面已定义则不覆盖)
+        window.downloadReport = window.downloadReport || function(btn){
+          try{ const card = btn.closest('.doc-card'); const name = card?.getAttribute('data-name')||'报告'; alert('下载:'+name); }catch(e){console.warn(e);}
+        };
+        window.archiveReport = window.archiveReport || function(btn){
+          try{ const card = btn.closest('.doc-card'); if(card) card.classList.toggle('archived'); alert('已切换归档状态'); }catch(e){console.warn(e);}
+        };
+        window.deleteReport = window.deleteReport || function(btn){
+          try{ const card = btn.closest('.doc-card'); const name = card?.getAttribute('data-name')||'报告'; if(!confirm('确认删除 "'+name+'"?')) return; card.remove(); if(typeof updateReportsCountAndSort==='function') updateReportsCountAndSort(); alert('已删除:'+name); }catch(e){console.warn(e);}
+        };
+      </script>
+
+    <script>
+    (function(){
+        let pageSize = 10;
+        let elements = [], filtered = [], currentPage = 1;
+
+        function extractRawText(node) {
+            let txt = '';
+            node.childNodes.forEach(n => {
+                if (n.nodeType === Node.TEXT_NODE) txt += n.textContent;
+                else if (n.nodeType === Node.ELEMENT_NODE && !n.classList.contains('source-badge')) txt += n.textContent;
+            });
+            return (txt || node.textContent || '').trim();
+        }
+
+        function detectValueType(val) {
+            if (!val) return '文本';
+            if (/[¥¥元]|亿元|万/.test(val)) return '金额';
+            const v = val.replace(/[,,\s]/g,'');
+            if (/^\d+(\.\d+)?$/.test(v)) return '数字';
+            return '文本';
+        }
+
+        function buildElementsFromContent() {
+            elements = [];
+            const nodes = document.querySelectorAll('.editor-content .entity-highlight');
+            let idx = 0;
+            nodes.forEach(node => {
+                try {
+                    const name = extractRawText(node);
+                    if (!name) return;
+                    const desc = node.getAttribute('title') || '';
+                    const srcBadge = node.querySelector && node.querySelector('.source-badge');
+                    const src = (node.dataset && node.dataset.source) ? node.dataset.source : (srcBadge ? srcBadge.textContent : '未知');
+                    let elemType = '变量';
+                    try {
+                        const ds = (node.dataset && node.dataset.source) ? String(node.dataset.source) : '';
+                        if (ds && /ai|生成|AI/i.test(ds)) elemType = 'AI生成';
+                        else if (node.querySelector && node.querySelector('.source-badge.ai')) elemType = 'AI生成';
+                    } catch(e){}
+                    const valType = detectValueType(name);
+                    const id = 'el_' + (++idx) + '_' + sanitizeId(name);
+                    elements.push({ id, name, description: desc, type: valType, elementType: elemType, originalValue: name, newValue: name, source: src, node });
+                } catch (e) { console.warn('buildElementsFromContent err', e); }
+            });
+            filtered = elements.slice();
+            currentPage = 1;
+        }
+
+        function renderElementsList() {
+            const tbody = document.getElementById('elementsTbody');
+            const info = document.getElementById('elementsPaginationInfo');
+            if (!tbody) return;
+            const start = (currentPage-1)*pageSize;
+            const pageItems = filtered.slice(start, start+pageSize);
+            tbody.innerHTML = pageItems.map(it => `
+                <tr data-id="${it.id}">
+                    <td>${it.name}</td>
+                    <td>${it.description || '-'}</td>
+                    <td>${it.type}</td>
+                    <td>${it.elementType}</td>
+                    <td class="orig">${it.originalValue}</td>
+                    <td class="new"><input type="text" value="${it.newValue}" style="width:100%;padding:6px;border:1px solid var(--border);border-radius:6px;" data-id="${it.id}" /></td>
+                    <td>${it.source}</td>
+                    <td><button class="icon-btn edit-btn" title="编辑" data-id="${it.id}"><i class="iconfont icon-EDIT"></i></button></td>
+                </tr>
+            `).join('');
+            const total = filtered.length;
+            const totalPages = Math.max(1, Math.ceil(total/pageSize));
+            info.textContent = `第 ${currentPage} / ${totalPages} 页 • 共 ${total} 条`;
+            renderPager();
+            tbody.querySelectorAll('.edit-btn').forEach(btn=>{
+                btn.addEventListener('click', ()=> {
+                    const id = btn.dataset.id;
+                    const input = tbody.querySelector('input[data-id="'+id+'"]');
+                    if (input) { input.focus(); input.select(); }
+                });
+            });
+        }
+
+        function renderPager() {
+            const pagerContainer = document.getElementById('elementsPaginationInfo');
+            if (!pagerContainer) return;
+            const total = filtered.length;
+            const totalPages = Math.max(1, Math.ceil(total/pageSize));
+            // build numeric pager with up to 5 buttons (显示中间区域最多 5 个页码)
+            const maxButtons = 5;
+            let start = Math.max(1, currentPage - Math.floor(maxButtons/2));
+            let end = start + maxButtons - 1;
+            if (end > totalPages) { end = totalPages; start = Math.max(1, end - maxButtons + 1); }
+            let html = `<div class="pager">`;
+            // 恢复小型上一页 / 下一页 按钮(位于数字页码两侧)
+            html += `<button class="pager-btn" data-action="prev" title="上一页">‹</button>`;
+            for (let p = start; p <= end; p++) {
+                html += `<button class="pager-btn ${p===currentPage?'active':''}" data-page="${p}">${p}</button>`;
+            }
+            html += `<button class="pager-btn" data-action="next" title="下一页">›</button>`;
+            html += `</div>`;
+            pagerContainer.innerHTML = html;
+            // wire events
+            pagerContainer.querySelectorAll('.pager-btn').forEach(btn=>{
+                btn.addEventListener('click', (e)=>{
+                    const action = btn.dataset.action;
+                    if (action === 'first') { currentPage = 1; }
+                    else if (action === 'prev') { currentPage = Math.max(1, currentPage - 1); }
+                    else if (action === 'next') { currentPage = Math.min(totalPages, currentPage + 1); }
+                    else if (action === 'last') { currentPage = totalPages; }
+                    else if (btn.dataset.page) { currentPage = parseInt(btn.dataset.page, 10); }
+                    renderElementsList();
+                });
+            });
+            // update page size select to current value
+            const sel = document.getElementById('elementsPageSize');
+            if (sel) sel.value = String(pageSize);
+        }
+
+        function openReportElementsModal() {
+            try {
+                buildElementsFromContent();
+                renderElementsList();
+                document.getElementById('reportElementsModal').classList.add('show');
+                document.getElementById('reportElementsModal').setAttribute('aria-hidden','false');
+            } catch (e) { console.warn('openReportElementsModal err', e); }
+        }
+
+        function closeReportElementsModal() {
+            const el = document.getElementById('reportElementsModal');
+            if (el) { el.classList.remove('show'); el.setAttribute('aria-hidden','true'); }
+        }
+
+        function applySearch() {
+            const q = (document.getElementById('elementsSearchInput').value || '').toLowerCase().trim();
+            if (!q) filtered = elements.slice();
+            else filtered = elements.filter(it => (it.name||'').toLowerCase().includes(q) || (it.type||'').toLowerCase().includes(q) || (it.elementType||'').toLowerCase().includes(q));
+            currentPage = 1;
+            renderElementsList();
+        }
+
+        function changePage(delta) {
+            const total = filtered.length;
+            const totalPages = Math.max(1, Math.ceil(total/pageSize));
+            currentPage = Math.min(Math.max(1, currentPage + delta), totalPages);
+            renderElementsList();
+        }
+
+        function saveAllElements() {
+            const tbody = document.getElementById('elementsTbody');
+            if (!tbody) return;
+            tbody.querySelectorAll('input[data-id]').forEach(inp => {
+                const id = inp.dataset.id;
+                const item = elements.find(e=>e.id===id);
+                if (!item) return;
+                item.newValue = inp.value;
+            });
+            elements.forEach(item => {
+                try {
+                    if (item.newValue !== item.originalValue && item.node) {
+                        const badge = item.node.querySelector && item.node.querySelector('.source-badge');
+                        while (item.node.firstChild) item.node.removeChild(item.node.firstChild);
+                        item.node.appendChild(document.createTextNode(item.newValue));
+                        if (badge) item.node.appendChild(badge);
+                        item.node.dataset.currentValue = item.newValue;
+                    }
+                } catch (e) { console.warn('apply element change err', e); }
+            });
+            showToast('✓ 要素已保存', 'success');
+            closeReportElementsModal();
+        }
+
+        document.addEventListener('DOMContentLoaded', function(){
+            const search = document.getElementById('elementsSearchInput');
+            if (search) search.addEventListener('input', applySearch);
+            const prev = document.getElementById('elementsPrevBtn');
+            const next = document.getElementById('elementsNextBtn');
+            if (prev) prev.addEventListener('click', ()=> changePage(-1));
+            if (next) next.addEventListener('click', ()=> changePage(1));
+            const saveBtn = document.getElementById('saveElementsBtn');
+            if (saveBtn) saveBtn.addEventListener('click', saveAllElements);
+            const openTopBtn = document.getElementById('reportElementsTopBtn');
+            if (openTopBtn) openTopBtn.addEventListener('click', openReportElementsModal);
+            const pageSizeSel = document.getElementById('elementsPageSize');
+            if (pageSizeSel) {
+                pageSizeSel.addEventListener('change', function(){
+                    const v = parseInt(this.value, 10) || 10;
+                    pageSize = v;
+                    currentPage = 1;
+                    renderElementsList();
+                });
+            }
+        });
+
+        window.openReportElementsModal = openReportElementsModal;
+        window.closeReportElementsModal = closeReportElementsModal;
+    })();
+    </script>
+    <script>
+        // report status quick toggle
+        (function(){
+            const tag = document.getElementById('reportStatusTag');
+            if (!tag) return;
+            const statuses = ['草稿','审核中','已定稿'];
+            let idx = 0;
+            tag.addEventListener('click', function(){
+                idx = (idx + 1) % statuses.length;
+                tag.textContent = statuses[idx];
+                showToast && showToast('状态已切换:' + statuses[idx], 'info');
+            });
+        })();
+    </script>
+    <script>
+    (function(){
+        let tooltip = null;
+        function createTooltip() {
+            tooltip = document.createElement('div');
+            tooltip.className = 'icon-tooltip';
+            document.body.appendChild(tooltip);
+            return tooltip;
+        }
+        function showTooltip(el, text) {
+            if (!tooltip) createTooltip();
+            tooltip.textContent = text;
+            tooltip.style.opacity = '1';
+            const rect = el.getBoundingClientRect();
+            const top = Math.max(8, rect.top - 36);
+            const left = rect.left + (rect.width/2) - (tooltip.offsetWidth/2);
+            tooltip.style.top = top + 'px';
+            tooltip.style.left = Math.max(8, left) + 'px';
+        }
+        function hideTooltip() {
+            if (!tooltip) return;
+            tooltip.style.opacity = '0';
+        }
+
+        document.addEventListener('DOMContentLoaded', function(){
+            document.querySelectorAll('.icon-btn, .ai-icon-btn').forEach(btn => {
+                btn.addEventListener('mouseenter', function(){
+                    const txt = btn.dataset.tooltip || btn.getAttribute('title') || btn.getAttribute('aria-label') || '';
+                    if (txt) {
+                        showTooltip(btn, txt);
+                    }
+                });
+                btn.addEventListener('mouseleave', function(){ hideTooltip(); });
+            });
+        });
+    })();
+    </script>
+    </body>
+<script>
+    // 切换原文 / 标记(同时切换按钮内 icon)
+    function toggleView() {
+      try {
+        const ori = document.getElementById('contentOriginal');
+        const mk = document.getElementById('contentMarked');
+        const btn = document.getElementById('toggleViewBtn');
+        if (!ori || !mk || !btn) return;
+
+        if (ori.style.display === 'none') {
+          ori.style.display = '';
+          mk.style.display = 'none';
+        } else {
+          ori.style.display = 'none';
+          mk.style.display = '';
+        }
+
+        try {
+          const hasBig = btn.querySelector && btn.querySelector('.icon-BIG_PROMOTION');
+          if (hasBig) {
+            btn.innerHTML = '<i class="iconfont icon-BASE_INFO"></i>';
+          } else {
+            btn.innerHTML = '<i class="iconfont icon-BIG_PROMOTION"></i>';
+          }
+        } catch (iconErr) {
+          console.warn('toggleView icon swap err', iconErr);
+        }
+      } catch (e) { console.warn('toggleView err', e); }
+    }
+  
+    // 更多菜单(示意)
+    function showMoreMenu(btn) { try { showToast && showToast('更多菜单(示意)', 'info'); } catch(e){} }
+  
+    // 报告操作(占位实现)
+    window.downloadReport = window.downloadReport || function(btn) {
+      try {
+        const card = btn.closest('.doc-card');
+        const name = card?.getAttribute('data-name') || '报告';
+        showToast && showToast('开始下载:' + name, 'info');
+      } catch (e) { console.warn(e); }
+    };
+    window.archiveReport = window.archiveReport || function(btn) {
+      try {
+        const card = btn.closest('.doc-card');
+        if (card) card.classList.toggle('archived');
+        showToast && showToast('已切换归档状态', 'success');
+      } catch (e) { console.warn(e); }
+    };
+    window.deleteReport = window.deleteReport || function(btn) {
+      try {
+        const card = btn.closest('.doc-card');
+        const name = card?.getAttribute('data-name') || '报告';
+        if (!confirm('确认删除 "' + name + '" 吗?')) return;
+        card.remove();
+        if (typeof updateReportsCountAndSort === 'function') updateReportsCountAndSort();
+        showToast && showToast('已删除:' + name, 'success');
+      } catch (e) { console.warn(e); }
+    };
+  </script>
+</html>