本篇是上一篇中的完整程序(由于字数限制),是对豆包助手聊天讨论生成的备忘录仪表盘程序index.html集成的结果。摘要主要增加了配色 和拼语言表述体系。
摘要
本文介绍了豆包助手聊天讨论生成的备忘录仪表盘程序index.html的集成版本。该程序采用三层核心设计理念:内嵌式赋能-学习(万向通-通境顿)、外挂式省力-节约(千行别-性行渐)和中蕴式省心-安全(百业藏-量果密)。系统包含完整的HTML结构、CSS样式和JavaScript功能实现,支持讨论记录、分类管理、数据备份恢复、AI辅助总结等功能。通过语义映射表、核心配置维度枚举和价值维度统计等数据结构,实现了3行7列结构的分析验证功能。程序采用本地存储保障数据安全,并提供了丰富的可视化仪表盘展示讨论统计信息。
正文
1、页面

2、代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DiscussMemo + 表述处理系统(整合版V1)</title>
<!-- Tailwind CSS v3 -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Font Awesome -->
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- 统一的 Tailwind 配置 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3b82f6',
secondary: '#64748b',
accent: '#0ea5e9',
neutral: '#f1f5f9',
'neutral-dark': '#334155',
success: '#22c55e',
warning: '#f59e0b',
danger: '#ef4444',
// 适配维度配色(万向/千行/百业)
universal: '#3b82f6', // 万向-蓝
industry: '#a855f7', // 千行-紫
business: '#22c55e', // 百业-绿
// 价值维度配色(学习/节约/安全)
learn: '#f59e0b', // 学习-黄
save: '#ef4444', // 节约-红
safe: '#10b981', // 安全-青
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
animation: {
'spin-slow': 'spin 3s linear infinite',
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
}
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.glass-effect {
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.text-shadow {
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.transition-all-300 {
transition: all 300ms ease-in-out;
}
.toast {
transform: translateY(100px);
opacity: 0;
transition: all 0.3s ease;
}
.toast.show {
transform: translateY(0);
opacity: 1;
}
.tour-tooltip {
z-index: 1000;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
/* 价值维度卡片样式 */
.value-card {
transition: all 0.3s ease;
}
.value-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 20px -8px rgba(0,0,0,0.15);
}
}
</style>
<style>
/* 自定义样式 */
.dashboard-sector {
transition: all 0.5s ease;
}
.dashboard-sector:hover {
filter: brightness(1.2);
transform: scale(1.02);
}
.content-block {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.content-block:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.content-block.dragging {
opacity: 0.5;
transform: scale(1.02);
}
.drop-zone {
min-height: 20px;
transition: all 0.2s ease;
}
.drop-zone.active {
background-color: rgba(59, 130, 246, 0.1);
min-height: 60px;
}
/* 仪表盘动画 */
@keyframes rotatePointer {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.dashboard-pointer {
animation: rotatePointer 20s linear infinite;
transform-origin: center bottom;
}
/* 脉冲动画 */
@keyframes pulse-ring {
0% { transform: scale(0.8); opacity: 0.8; }
80%, 100% { opacity: 0; transform: scale(2); }
}
.pulse-ring {
position: absolute;
border-radius: 50%;
animation: pulse-ring 2s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}
/* 代码定位模态框 */
.code-modal-content {
max-height: 70vh;
overflow-y: auto;
}
.code-line {
transition: background-color 0.2s ease;
}
.code-line.highlight {
background-color: rgba(245, 158, 11, 0.1);
border-left: 3px solid #f59e0b;
}
/* 三大核心模式样式标注 */
.mode-tag {
position: absolute;
top: 8px;
right: 8px;
font-size: 10px;
padding: 2px 6px;
border-radius: 4px;
color: white;
}
.mode-embed { /* 内嵌式赋能-学习 */
background-color: #22c55e;
}
.mode-external { /* 外挂式省力-节约 */
background-color: #f59e0b;
}
.mode-inner { /* 中蕴式省心-安全 */
background-color: #a855f7;
}
/* 适配维度标签样式 */
.adapt-tag {
font-size: 11px;
padding: 1px 5px;
border-radius: 3px;
color: white;
}
.adapt-universal { background-color: #3b82f6; } /* 万向 */
.adapt-industry { background-color: #a855f7; } /* 千行 */
.adapt-business { background-color: #22c55e; } /* 百业 */
</style>
</head>
<body class="bg-gray-50 text-gray-800 min-h-screen flex flex-col">
<!-- 顶部导航栏 -->
<header class="bg-white shadow-sm sticky top-0 z-50">
<div class="container mx-auto px-4 py-3 flex items-center justify-between">
<div class="flex items-center space-x-2">
<div class="text-primary text-2xl">
<i class="fa fa-comments-o"></i>
</div>
<h1 class="text-xl font-bold text-primary">DiscussMemo <span class="text-xs text-gray-500">V4</span></h1>
</div>
<div class="flex items-center space-x-4">
<!-- 数据备份按钮(中蕴式安全) -->
<button id="backup-btn" class="p-2 rounded-full hover:bg-gray-100 transition-all-300 relative">
<i class="fa fa-database text-gray-600"></i>
<span class="mode-tag mode-inner">中蕴式</span>
</button>
<!-- 配置管理按钮(外挂式省力) -->
<button id="config-btn" class="p-2 rounded-full hover:bg-gray-100 transition-all-300 relative" data-code-location="配置管理模块 - JS第2800行">
<i class="fa fa-cog text-gray-600"></i>
<span class="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-accent text-white text-xs flex items-center justify-center">
新
</span>
<span class="mode-tag mode-external">外挂式</span>
</button>
<!-- 代码定位按钮(开发模式/外挂式) -->
<button id="dev-mode-btn" class="p-2 rounded-full hover:bg-gray-100 transition-all-300">
<i class="fa fa-code text-gray-600"></i>
<span class="mode-tag mode-external">外挂式</span>
</button>
<!-- 主题切换(中蕴式) -->
<button id="theme-toggle" class="p-2 rounded-full hover:bg-gray-100 transition-all-300">
<i class="fa fa-moon-o text-gray-600"></i>
<span class="mode-tag mode-inner">中蕴式</span>
</button>
<!-- 帮助按钮(内嵌式学习) -->
<button id="help-button" class="p-2 rounded-full hover:bg-gray-100 transition-all-300">
<i class="fa fa-question-circle text-gray-600"></i>
<span class="mode-tag mode-embed">内嵌式</span>
</button>
<div class="relative">
<button id="user-menu-button" class="flex items-center space-x-2 p-2 rounded-full hover:bg-gray-100 transition-all-300">
<div class="w-8 h-8 rounded-full bg-primary text-white flex items-center justify-center">
<i class="fa fa-user"></i>
</div>
<span class="mode-tag mode-inner">中蕴式</span>
</button>
</div>
</div>
</div>
</header>
<!-- 主内容区 -->
<main class="flex-grow flex">
<!-- 左侧导航面板 -->
<aside id="sidebar" class="w-64 bg-white shadow-sm border-r border-gray-200 flex flex-col transition-all duration-300 ease-in-out">
<!-- 搜索框(外挂式省力) -->
<div class="p-4 border-b border-gray-200">
<div class="relative">
<input type="text" id="search-input" placeholder="搜索讨论..." class="w-full pl-10 pr-4 py-2 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" data-code-location="搜索功能 - JS第1500行">
<i class="fa fa-search absolute left-3 top-3 text-gray-400"></i>
<!-- 提示图标(内嵌式学习) -->
<div class="absolute right-3 top-3 text-warning" title="支持关键词、标签、分类搜索">
<i class="fa fa-lightbulb-o"></i>
<span class="mode-tag mode-embed">内嵌式</span>
</div>
</div>
</div>
<!-- 分类筛选(外挂式+内嵌式) -->
<div class="p-4 border-b border-gray-200">
<div class="flex justify-between items-center mb-2">
<h3 class="text-sm font-medium text-gray-500">分类筛选</h3>
<button id="edit-categories-btn" class="text-xs text-primary hover:underline" data-code-location="分类管理 - JS第2850行">
编辑
</button>
</div>
<div class="space-y-1" id="categories-list">
<!-- 分类选项将通过JS动态生成(支持自定义/外挂式) -->
</div>
<!-- 添加新分类(外挂式) -->
<div class="mt-3 flex">
<input type="text" id="new-category-input" placeholder="添加新分类..." class="flex-grow px-3 py-1.5 rounded-l-md border border-gray-300 focus:outline-none focus:ring-1 focus:ring-primary text-sm">
<button id="add-category-btn" class="bg-primary text-white px-3 py-1.5 rounded-r-md text-sm hover:bg-primary/90" data-code-location="添加分类 - JS第2880行">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<!-- 讨论列表(中蕴式数据存储) -->
<div class="flex-grow overflow-y-auto scrollbar-hide">
<div class="p-4">
<div class="flex justify-between items-center mb-3">
<h3 class="text-sm font-medium text-gray-500">我的讨论</h3>
<button id="new-discussion-btn" class="text-primary hover:text-primary-dark" data-code-location="新建讨论 - JS第800行">
<i class="fa fa-plus-circle"></i>
</button>
</div>
<div id="discussion-list" class="space-y-2">
<!-- 讨论列表项将通过JS动态生成(中蕴式数据存储) -->
<div class="text-center py-8 text-gray-500" id="empty-discussion-msg">
<i class="fa fa-folder-open-o text-3xl mb-2"></i>
<p>暂无讨论记录</p>
<p class="text-sm">点击"新建讨论"开始记录</p>
</div>
</div>
</div>
</div>
<!-- 底部操作区(仪表盘/内嵌式学习) -->
<div class="p-4 border-t border-gray-200">
<button id="dashboard-btn" class="w-full flex items-center justify-center space-x-2 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark transition-all-300" data-code-location="仪表盘功能 - JS第1800行">
<i class="fa fa-tachometer"></i>
<span>仪表盘</span>
<span class="mode-tag mode-embed">内嵌式</span>
</button>
</div>
</aside>
<!-- 右侧内容区 -->
<section id="content-area" class="flex-grow overflow-y-auto bg-gray-50">
<!-- 仪表盘视图(内嵌式学习+数据统计/中蕴式) -->
<div id="dashboard-view" class="container mx-auto px-4 py-8">
<div class="mb-8 flex justify-between items-center">
<div>
<h2 class="text-2xl font-bold text-gray-800 mb-2">讨论仪表盘</h2>
<p class="text-gray-600">概览您的所有讨论和进展(内嵌式学习+中蕴式数据+外挂式配置)</p>
</div>
<!-- 代码定位按钮(外挂式) -->
<button class="code-location-btn bg-gray-100 text-gray-700 px-3 py-1 rounded-md text-sm flex items-center hover:bg-gray-200" data-code-location="仪表盘渲染 - JS第1850行">
<i class="fa fa-code mr-1"></i> 查看代码
<span class="mode-tag mode-external">外挂式</span>
</button>
</div>
<!-- 新增:价值维度统计卡片(落地三层设计理念) -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<!-- 内嵌式赋能 - 学习 -->
<div class="value-card bg-white rounded-xl shadow-sm p-6 border border-gray-100 relative border-l-4 border-learn">
<span class="mode-tag mode-embed">内嵌式</span>
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">学习维度(万向 通-通 境 顿)</p>
<h3 id="learn-stats" class="text-2xl font-bold mt-1">0</h3>
<p class="text-xs text-gray-500 mt-1">提示词使用/帮助查看次数</p>
</div>
<div class="w-12 h-12 rounded-full bg-yellow-100 flex items-center justify-center text-learn">
<i class="fa fa-graduation-cap text-xl"></i>
</div>
</div>
<div class="mt-4 flex items-center text-xs text-gray-500">
<span class="px-2 py-1 bg-yellow-50 rounded-full mr-2">通:操作易懂</span>
<span class="px-2 py-1 bg-yellow-50 rounded-full mr-2">境:沉浸式</span>
<span class="px-2 py-1 bg-yellow-50 rounded-full">顿:快速顿悟</span>
</div>
</div>
<!-- 外挂式省力 - 节约 -->
<div class="value-card bg-white rounded-xl shadow-sm p-6 border border-gray-100 relative border-l-4 border-save">
<span class="mode-tag mode-external">外挂式</span>
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">效率维度(千行 别-性 行 渐)</p>
<h3 id="save-stats" class="text-2xl font-bold mt-1">0</h3>
<p class="text-xs text-gray-500 mt-1">快捷键/一键操作次数</p>
</div>
<div class="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center text-save">
<i class="fa fa-bolt text-xl"></i>
</div>
</div>
<div class="mt-4 flex items-center text-xs text-gray-500">
<span class="px-2 py-1 bg-red-50 rounded-full mr-2">别:功能区分</span>
<span class="px-2 py-1 bg-red-50 rounded-full mr-2">行:一键操作</span>
<span class="px-2 py-1 bg-red-50 rounded-full">渐:渐进优化</span>
</div>
</div>
<!-- 中蕴式省心 - 安全 -->
<div class="value-card bg-white rounded-xl shadow-sm p-6 border border-gray-100 relative border-l-4 border-safe">
<span class="mode-tag mode-inner">中蕴式</span>
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">安全维度(百业 藏-量 果 密)</p>
<h3 id="safe-stats" class="text-2xl font-bold mt-1">0</h3>
<p class="text-xs text-gray-500 mt-1">备份/自动保存次数</p>
</div>
<div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center text-safe">
<i class="fa fa-shield text-xl"></i>
</div>
</div>
<div class="mt-4 flex items-center text-xs text-gray-500">
<span class="px-2 py-1 bg-green-50 rounded-full mr-2">藏:本地存储</span>
<span class="px-2 py-1 bg-green-50 rounded-full mr-2">量:成果量化</span>
<span class="px-2 py-1 bg-green-50 rounded-full">密:隐私安全</span>
</div>
</div>
</div>
<!-- 统计卡片(中蕴式-数据安全/量化) -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 relative">
<span class="mode-tag mode-inner">中蕴式</span>
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">总讨论数</p>
<h3 id="total-discussions" class="text-2xl font-bold mt-1">0</h3>
</div>
<div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center text-primary">
<i class="fa fa-comments text-xl"></i>
</div>
</div>
<!-- 提示信息(内嵌式) -->
<div class="mt-2 text-xs text-gray-500 flex items-center">
<i class="fa fa-info-circle mr-1 text-primary"></i>
<span>包含所有分类的讨论记录</span>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 relative">
<span class="mode-tag mode-inner">中蕴式</span>
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">待办事项</p>
<h3 id="pending-todos" class="text-2xl font-bold mt-1">0</h3>
</div>
<div class="w-12 h-12 rounded-full bg-yellow-100 flex items-center justify-center text-warning">
<i class="fa fa-tasks text-xl"></i>
</div>
</div>
<div class="mt-2 text-xs text-gray-500 flex items-center">
<i class="fa fa-info-circle mr-1 text-primary"></i>
<span>所有讨论中的未完成任务</span>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 relative">
<span class="mode-tag mode-inner">中蕴式</span>
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">已完成决策</p>
<h3 id="completed-decisions" class="text-2xl font-bold mt-1">0</h3>
</div>
<div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center text-success">
<i class="fa fa-check-circle text-xl"></i>
</div>
</div>
<div class="mt-2 text-xs text-gray-500 flex items-center">
<i class="fa fa-info-circle mr-1 text-primary"></i>
<span>已确认的重要决策</span>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 relative">
<span class="mode-tag mode-inner">中蕴式</span>
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">最近更新</p>
<h3 id="last-updated" class="text-2xl font-bold mt-1">-</h3>
</div>
<div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center text-purple-600">
<i class="fa fa-clock-o text-xl"></i>
</div>
</div>
<div class="mt-2 text-xs text-gray-500 flex items-center">
<i class="fa fa-info-circle mr-1 text-primary"></i>
<span>最后一次编辑的讨论时间</span>
</div>
</div>
</div>
<!-- 仪表盘图表(内嵌式学习+中蕴式数据) -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
<!-- 分类分布 -->
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 lg:col-span-1 relative">
<span class="mode-tag mode-embed">内嵌式</span>
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800">分类分布</h3>
<button class="code-location-btn bg-gray-100 text-gray-700 px-2 py-1 rounded-md text-xs flex items-center hover:bg-gray-200" data-code-location="分类分布图表 - JS第2000行">
<i class="fa fa-code mr-1"></i> 代码
</button>
</div>
<div class="relative h-64">
<div class="absolute inset-0 flex items-center justify-center">
<div class="relative w-48 h-48">
<!-- 仪表盘扇区 -->
<div id="dashboard-sectors" class="relative w-full h-full">
<!-- 扇区将通过JS动态生成 -->
</div>
<!-- 中心指针 -->
<div class="absolute left-1/2 bottom-1/2 transform -translate-x-1/2 translate-y-1/2 w-1 h-20 bg-gray-400 dashboard-pointer">
<div class="absolute top-0 left-1/2 transform -translate-x-1/2 w-4 h-4 rounded-full bg-primary border-4 border-white"></div>
</div>
<!-- 中心文字 -->
<div class="absolute inset-0 flex flex-col items-center justify-center">
<span class="text-2xl font-bold text-primary" id="completion-rate">65%</span>
<span class="text-xs text-gray-500">完成率</span>
</div>
</div>
</div>
</div>
<!-- 图例 -->
<div class="mt-4 grid grid-cols-2 gap-2" id="category-legend">
<!-- 图例将通过JS动态生成 -->
</div>
</div>
<!-- 最近讨论(中蕴式数据) -->
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 lg:col-span-2 relative">
<span class="mode-tag mode-inner">中蕴式</span>
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800">最近讨论</h3>
<button class="code-location-btn bg-gray-100 text-gray-700 px-2 py-1 rounded-md text-xs flex items-center hover:bg-gray-200" data-code-location="最近讨论渲染 - JS第2100行">
<i class="fa fa-code mr-1"></i> 代码
</button>
</div>
<div class="space-y-4">
<div id="recent-discussions" class="space-y-3">
<!-- 最近讨论将通过JS动态生成 -->
</div>
</div>
</div>
</div>
<!-- 提示词导航(内嵌式学习) -->
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 relative">
<span class="mode-tag mode-embed">内嵌式</span>
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800">提示词导航</h3>
<button id="edit-prompts-btn" class="text-xs text-primary hover:underline" data-code-location="提示词管理 - JS第2950行">
编辑提示词
</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" id="prompts-container">
<!-- 提示词卡片将通过JS动态生成(支持自定义/内嵌式) -->
</div>
<!-- 添加新提示词(外挂式) -->
<div class="mt-6 p-4 border-2 border-dashed border-gray-300 rounded-lg hover:border-primary transition-all-300 relative" id="add-prompt-card">
<span class="mode-tag mode-external">外挂式</span>
<div class="text-center">
<i class="fa fa-plus-circle text-2xl text-gray-400 mb-2"></i>
<h4 class="font-medium text-gray-600">添加自定义提示词</h4>
<p class="text-sm text-gray-500 mt-1">创建适合您场景的讨论模板(适配千行百业)</p>
</div>
</div>
</div>
</div>
<!-- 讨论编辑视图(中蕴式数据+外挂式操作+内嵌式引导) -->
<div id="editor-view" class="hidden container mx-auto px-4 py-8">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<!-- 讨论标题和元数据 -->
<div class="p-6 border-b border-gray-200">
<div class="flex justify-between items-start mb-4">
<input type="text" id="discussion-title" placeholder="输入讨论标题(必填)..." class="w-full text-2xl font-bold border-0 border-b-2 border-transparent focus:border-primary focus:ring-0 pb-2" required>
<button class="code-location-btn bg-gray-100 text-gray-700 px-2 py-1 rounded-md text-xs flex items-center hover:bg-gray-200 mt-2" data-code-location="讨论编辑 - JS第900行">
<i class="fa fa-code mr-1"></i> 代码
<span class="mode-tag mode-external">外挂式</span>
</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1 flex items-center">
范畴
<span class="ml-1 text-warning" title="讨论的核心领域分类(万向/千行/百业)">
<i class="fa fa-question-circle"></i>
<span class="mode-tag mode-embed">内嵌式</span>
</span>
</label>
<select id="discussion-category" class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" required>
<!-- 范畴选项将通过JS动态生成(支持自定义/外挂式) -->
</select>
<!-- 验证提示(内嵌式) -->
<p class="hidden text-danger text-xs mt-1" id="category-required">请选择范畴</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1 flex items-center">
分类
<span class="ml-1 text-warning" title="讨论的关键词标签(别-性/行/渐)">
<i class="fa fa-question-circle"></i>
<span class="mode-tag mode-embed">内嵌式</span>
</span>
</label>
<div class="relative">
<input type="text" id="discussion-subject" placeholder="输入分类关键词(必填)..." class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" required>
<!-- 自动完成建议(内嵌式学习) -->
<div id="subject-suggestions" class="hidden absolute top-full left-0 right-0 bg-white border border-gray-300 rounded-md shadow-lg max-h-40 overflow-y-auto z-10">
<!-- 建议将通过JS动态生成 -->
</div>
</div>
<p class="hidden text-danger text-xs mt-1" id="subject-required">请输入分类关键词</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1 flex items-center">
目录
<span class="ml-1 text-warning" title="讨论的主题大纲(通/境/顿/藏/量/密)">
<i class="fa fa-question-circle"></i>
<span class="mode-tag mode-embed">内嵌式</span>
</span>
</label>
<input type="text" id="discussion-topic" placeholder="输入语篇主题(必填)..." class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" required>
<p class="hidden text-danger text-xs mt-1" id="topic-required">请输入语篇主题</p>
</div>
</div>
<div class="mt-4 flex flex-wrap gap-2">
<div class="flex items-center bg-gray-100 rounded-full px-3 py-1">
<span class="text-sm text-gray-600 mr-2">标签:</span>
<input type="text" id="tag-input" placeholder="添加标签..." class="bg-transparent border-0 focus:outline-none text-sm w-24">
<button id="add-tag-btn" class="ml-1 text-primary hover:text-primary-dark" data-code-location="标签功能 - JS第1200行">
<i class="fa fa-plus-circle"></i>
</button>
</div>
<div id="tags-container" class="flex flex-wrap gap-2">
<!-- 标签将通过JS动态生成 -->
</div>
</div>
<!-- 保存提示(内嵌式) -->
<div class="mt-3 text-sm text-gray-500 flex items-center">
<i class="fa fa-save mr-1 text-primary"></i>
<span>自动保存,无需手动提交(中蕴式安全-藏/密)</span>
</div>
</div>
<!-- 富文本工具栏(外挂式省力) -->
<div class="bg-gray-50 p-2 border-b border-gray-200 flex items-center space-x-1">
<button class="format-btn p-2 rounded hover:bg-gray-200" data-command="bold" title="加粗 (Ctrl+B)">
<i class="fa fa-bold"></i>
</button>
<button class="format-btn p-2 rounded hover:bg-gray-200" data-command="italic" title="斜体 (Ctrl+I)">
<i class="fa fa-italic"></i>
</button>
<button class="format-btn p-2 rounded hover:bg-gray-200" data-command="underline" title="下划线 (Ctrl+U)">
<i class="fa fa-underline"></i>
</button>
<span class="h-5 border-r border-gray-300 mx-1"></span>
<button class="format-btn p-2 rounded hover:bg-gray-200" data-command="insertUnorderedList" title="无序列表">
<i class="fa fa-list-ul"></i>
</button>
<button class="format-btn p-2 rounded hover:bg-gray-200" data-command="insertOrderedList" title="有序列表">
<i class="fa fa-list-ol"></i>
</button>
<span class="h-5 border-r border-gray-300 mx-1"></span>
<button class="format-btn p-2 rounded hover:bg-gray-200" data-command="createLink" title="插入链接">
<i class="fa fa-link"></i>
</button>
<button class="format-btn p-2 rounded hover:bg-gray-200" data-command="insertImage" title="插入图片">
<i class="fa fa-image"></i>
</button>
<span class="h-5 border-r border-gray-300 mx-1"></span>
<div class="flex-grow"></div>
<button id="add-content-block" class="flex items-center space-x-1 bg-primary text-white px-3 py-1 rounded hover:bg-primary-dark" data-code-location="内容块功能 - JS第1300行">
<i class="fa fa-plus"></i>
<span>添加内容块(外挂式)</span>
</button>
</div>
<!-- 内容块编辑区(拖拽/外挂式+数据/中蕴式) -->
<div id="content-blocks-container" class="p-6 space-y-4">
<!-- 内容块将通过JS动态生成 -->
<div class="drop-zone"></div>
<div class="text-center py-12 text-gray-500" id="empty-content-msg">
<i class="fa fa-file-text-o text-4xl mb-3"></i>
<p>暂无内容块</p>
<p class="text-sm">点击"添加内容块"开始记录讨论要点</p>
</div>
</div>
<!-- AI辅助总结区(内嵌式学习) -->
<div class="p-6 border-t border-gray-200">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium text-gray-800 flex items-center">
AI辅助总结
<span class="ml-1 text-warning" title="自动提取讨论中的关键信息(顿/果)">
<i class="fa fa-question-circle"></i>
<span class="mode-tag mode-embed">内嵌式</span>
</span>
</h3>
<button id="generate-summary-btn" class="flex items-center space-x-1 bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary-dark transition-all-300" data-code-location="AI总结 - JS第1600行">
<i class="fa fa-magic"></i>
<span>生成总结</span>
</button>
</div>
<div id="summary-container" class="bg-gray-50 p-4 rounded-lg border border-gray-200 min-h-[100px]">
<p class="text-gray-500 text-center">点击"生成总结"按钮自动提取讨论中的关键决策和行动项(量/果)</p>
</div>
</div>
</div>
</div>
<!-- 配置管理视图(外挂式省力) -->
<div id="config-view" class="hidden container mx-auto px-4 py-8">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="p-6 border-b border-gray-200">
<div class="flex justify-between items-center">
<h2 class="text-2xl font-bold text-gray-800">分区配置管理(外挂式)</h2>
<button id="back-to-dashboard" class="flex items-center space-x-1 bg-gray-100 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-200 transition-all-300">
<i class="fa fa-arrow-left"></i>
<span>返回仪表盘</span>
</button>
</div>
<p class="text-gray-600 mt-2">自定义范畴、分类、提示词等核心配置,适配您的使用场景(千行百业/外挂式省力)</p>
</div>
<!-- 配置标签页 -->
<div class="border-b border-gray-200">
<nav class="flex" aria-label="Tabs">
<button class="config-tab-btn px-6 py-3 font-medium text-primary border-b-2 border-primary" data-tab="category">
范畴管理(万向/千行/百业)
</button>
<button class="config-tab-btn px-6 py-3 font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent" data-tab="subject">
分类关键词管理(别-性/行/渐)
</button>
<button class="config-tab-btn px-6 py-3 font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent" data-tab="prompt">
提示词模板管理(通/境/顿/藏/量/密)
</button>
<button class="config-tab-btn px-6 py-3 font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent" data-tab="expression">
表述处理(三元组/三分法/三位一体)
<span class="ml-1 bg-accent text-white text-xs px-2 py-0.5 rounded-full">新</span>
</button>
</nav>
</div>
<!-- 范畴管理 -->
<div class="config-tab-content p-6" id="category-tab">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800">范畴配置(万向适配)</h3>
<button class="bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary-dark transition-all-300" id="add-new-category">
<i class="fa fa-plus mr-1"></i> 添加范畴
</button>
</div>
<div class="bg-gray-50 rounded-lg p-4 mb-4">
<p class="text-sm text-gray-600">
<i class="fa fa-info-circle mr-1 text-primary"></i>
范畴是讨论的最高级别分类,用于区分不同领域的讨论(如工作、学习等)(内嵌式赋能-学习)
</p>
</div>
<div class="space-y-3" id="custom-categories-list">
<!-- 自定义范畴将通过JS动态生成 -->
</div>
</div>
<!-- 分类关键词管理 -->
<div class="config-tab-content p-6 hidden" id="subject-tab">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800">分类关键词配置(千行别-性)</h3>
<button class="bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary-dark transition-all-300" id="add-new-subject">
<i class="fa fa-plus mr-1"></i> 添加关键词
</button>
</div>
<div class="bg-gray-50 rounded-lg p-4 mb-4">
<p class="text-sm text-gray-600">
<i class="fa fa-info-circle mr-1 text-primary"></i>
分类关键词用于快速标记讨论的核心主题,支持自动补全功能(外挂式省力-节约)
</p>
</div>
<div class="space-y-3" id="custom-subjects-list">
<!-- 自定义关键词将通过JS动态生成 -->
</div>
</div>
<!-- 提示词模板管理 -->
<div class="config-tab-content p-6 hidden" id="prompt-tab">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800">提示词模板配置(百业藏-量)</h3>
<button class="bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary-dark transition-all-300" id="add-new-prompt">
<i class="fa fa-plus mr-1"></i> 添加模板
</button>
</div>
<div class="bg-gray-50 rounded-lg p-4 mb-4">
<p class="text-sm text-gray-600">
<i class="fa fa-info-circle mr-1 text-primary"></i>
提示词模板用于快速创建特定场景的讨论(如会议记录、项目规划等)(中蕴式省心-安全)
</p>
</div>
<div class="space-y-3" id="custom-prompts-list">
<!-- 自定义提示词将通过JS动态生成 -->
</div>
</div>
<!-- 表述处理管理 -->
<div class="config-tab-content p-6 hidden" id="expression-tab">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800">表述处理配置(三元组/三分法/三位一体)</h3>
<button class="bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary-dark transition-all-300" id="run-expression-analysis">
<i class="fa fa-play mr-1"></i> 运行分析
</button>
</div>
<div class="bg-gray-50 rounded-lg p-4 mb-4">
<p class="text-sm text-gray-600">
<i class="fa fa-info-circle mr-1 text-primary"></i>
表述处理系统支持3行7列结构的分析验证,集成内嵌式学习、外挂式省力、中蕴式安全三层设计理念
</p>
</div>
<!-- 原始表述输入区 -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
<div>
<h4 class="font-medium text-gray-800 mb-3 flex items-center">
<i class="fa fa-edit text-universal mr-2"></i>
原始表述输入(内嵌式赋能)
</h4>
<textarea id="raw-expression-input" rows="8" placeholder="输入3行7列的原始表述,每行用换行分隔,每列用空格分隔..."
class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent font-mono text-sm"></textarea>
<div class="mt-2 flex space-x-2">
<button id="load-example-btn" class="text-xs bg-universal text-white px-3 py-1 rounded hover:bg-universal/90">
加载示例
</button>
<button id="save-expression-btn" class="text-xs bg-gray-600 text-white px-3 py-1 rounded hover:bg-gray-700">
保存表述
</button>
</div>
</div>
<!-- 7列结构预览 -->
<div>
<h4 class="font-medium text-gray-800 mb-3 flex items-center">
<i class="fa fa-table text-industry mr-2"></i>
7列结构预览(外挂式省力)
</h4>
<div id="column-preview" class="border border-gray-300 rounded-lg p-4 bg-gray-50 min-h-[200px]">
<div class="text-center text-gray-500 py-8">
<i class="fa fa-eye text-2xl mb-2"></i>
<p>输入原始表述后将显示结构预览</p>
</div>
</div>
</div>
</div>
<!-- 分析结果展示 -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
<!-- 三元组结果 -->
<div class="border border-l-4 border-universal rounded-lg p-4">
<h5 class="font-medium text-universal mb-3 flex items-center">
<i class="fa fa-cubes mr-2"></i>
三元组结果(立名)
</h5>
<div id="ternary-results" class="space-y-2 text-sm">
<div class="text-gray-500">等待分析结果...</div>
</div>
</div>
<!-- 三分法结果 -->
<div class="border border-l-4 border-industry rounded-lg p-4">
<h5 class="font-medium text-industry mb-3 flex items-center">
<i class="fa fa-sitemap mr-2"></i>
三分法结果(立法)
</h5>
<div id="trichotomy-results" class="space-y-2 text-sm">
<div class="text-gray-500">等待分析结果...</div>
</div>
</div>
<!-- 三位一体结果 -->
<div class="border border-l-4 border-business rounded-lg p-4">
<h5 class="font-medium text-business mb-3 flex items-center">
<i class="fa fa-certificate mr-2"></i>
三位一体结果(立向)
</h5>
<div id="trinity-results" class="space-y-2 text-sm">
<div class="text-gray-500">等待分析结果...</div>
</div>
</div>
</div>
<!-- 验证报告 -->
<div class="bg-white border border-gray-200 rounded-lg p-4">
<h5 class="font-medium text-gray-800 mb-3 flex items-center">
<i class="fa fa-shield-alt text-safe mr-2"></i>
验证报告(中蕴式安全)
</h5>
<div id="validation-report" class="text-sm space-y-2">
<div class="text-gray-500">运行分析后将显示验证报告...</div>
</div>
</div>
<!-- 历史记录 -->
<div class="mt-6">
<h5 class="font-medium text-gray-800 mb-3 flex items-center">
<i class="fa fa-history text-secondary mr-2"></i>
分析历史记录
</h5>
<div id="expression-history" class="space-y-2">
<div class="text-center text-gray-500 py-4">
<i class="fa fa-inbox text-xl mb-2"></i>
<p class="text-sm">暂无历史记录</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 欢迎视图(内嵌式学习引导) -->
<div id="welcome-view" class="container mx-auto px-4 py-8 flex flex-col items-center justify-center h-full">
<div class="text-center max-w-2xl">
<div class="inline-flex items-center justify-center w-20 h-20 rounded-full bg-blue-100 text-primary text-3xl mb-6">
<i class="fa fa-comments-o"></i>
</div>
<h2 class="text-3xl font-bold text-gray-800 mb-4">欢迎使用 整合版系统</h2>
<p class="text-gray-600 mb-8">
内嵌式赋能-学习(万向 通-通 境 顿)<br>
外挂式省力-节约(千行 别-性 行 渐)<br>
中蕴式省心-安全(百业 藏-量 果 密)
</p>
<div class="flex flex-col sm:flex-row justify-center gap-4">
<button id="create-first-discussion" class="flex items-center justify-center space-x-2 px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-all-300 text-lg" data-code-location="首次使用引导 - JS第300行">
<i class="fa fa-plus-circle"></i>
<span>创建第一个讨论</span>
</button>
<button id="explore-dashboard" class="flex items-center justify-center space-x-2 px-6 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-all-300 text-lg" data-code-location="仪表盘入口 - JS第320行">
<i class="fa fa-tachometer"></i>
<span>浏览仪表盘</span>
</button>
</div>
<!-- 首次使用引导提示(内嵌式) -->
<div class="mt-8 p-4 bg-blue-50 rounded-lg border border-blue-100">
<div class="flex items-start">
<i class="fa fa-lightbulb-o text-primary text-xl mt-1 mr-3"></i>
<div>
<h4 class="font-medium text-gray-800">新手指引(内嵌式学习)</h4>
<p class="text-sm text-gray-600 mt-1">点击"配置管理"按钮可以自定义范畴、分类等选项,让工具更贴合您的使用习惯(外挂式省力);所有数据本地存储,安全省心(中蕴式安全)</p>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- 模态框组件 -->
<!-- 数据备份模态框(中蕴式安全) -->
<div id="backup-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center hidden">
<div class="bg-white rounded-xl shadow-lg w-full max-w-3xl mx-4">
<div class="p-6 border-b border-gray-200 flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-800">数据备份/恢复(中蕴式安全-藏/密)</h3>
<button id="close-backup-modal" class="text-gray-400 hover:text-gray-600">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<div class="p-6">
<div class="mb-6">
<h4 class="font-medium text-gray-800 mb-2">当前数据(自动保存/本地存储)</h4>
<div class="bg-gray-900 text-gray-100 rounded-lg p-4 font-mono text-sm overflow-x-auto" id="backup-data">
<pre><code>// 加载中...</code></pre>
</div>
</div>
<div class="flex flex-wrap gap-4">
<button id="export-data-btn" class="flex items-center space-x-1 bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary-dark transition-all-300">
<i class="fa fa-download mr-1"></i> 导出数据(JSON)
</button>
<label class="flex items-center space-x-1 bg-gray-100 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-200 transition-all-300 cursor-pointer">
<i class="fa fa-upload mr-1"></i> 导入数据
<input type="file" id="import-file" class="hidden" accept=".json">
</label>
<button id="reset-data-btn" class="flex items-center space-x-1 bg-danger text-white px-4 py-2 rounded-lg hover:bg-danger/90 transition-all-300">
<i class="fa fa-trash mr-1"></i> 重置所有数据
</button>
</div>
<div class="mt-4 p-4 bg-yellow-50 rounded-lg border border-yellow-100">
<p class="text-sm text-gray-700">
<i class="fa fa-exclamation-triangle text-yellow-600 mr-1"></i>
数据仅存储在本地浏览器中,建议定期导出备份(中蕴式安全-藏);重置数据将清除所有讨论和配置,不可恢复!
</p>
</div>
</div>
<div class="p-6 border-t border-gray-200 flex justify-end">
<button id="close-backup-btn" class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-all-300">
关闭
</button>
</div>
</div>
</div>
<!-- 添加内容块模态框(外挂式) -->
<div id="add-block-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center hidden">
<div class="bg-white rounded-xl shadow-lg w-full max-w-md mx-4">
<div class="p-6 border-b border-gray-200 flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-800">添加内容块(外挂式省力)</h3>
<button class="code-location-btn bg-gray-100 text-gray-700 px-2 py-1 rounded-md text-xs flex items-center hover:bg-gray-200" data-code-location="内容块模态框 - JS第1350行">
<i class="fa fa-code mr-1"></i> 代码
</button>
</div>
<div class="p-6">
<div class="space-y-3">
<button class="add-block-btn w-full flex items-center justify-between p-4 border border-gray-200 rounded-lg hover:border-primary hover:bg-blue-50 transition-all-300" data-type="text">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-primary mr-4">
<i class="fa fa-align-left"></i>
</div>
<div>
<h4 class="font-medium text-gray-800">文本块</h4>
<p class="text-sm text-gray-600">添加富文本内容(通-通)</p>
</div>
</div>
<i class="fa fa-chevron-right text-gray-400"></i>
</button>
<button class="add-block-btn w-full flex items-center justify-between p-4 border border-gray-200 rounded-lg hover:border-primary hover:bg-blue-50 transition-all-300" data-type="timeline">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-green-100 flex items-center justify-center text-green-600 mr-4">
<i class="fa fa-clock-o"></i>
</div>
<div>
<h4 class="font-medium text-gray-800">时间轴</h4>
<p class="text-sm text-gray-600">记录事件发生顺序(境)</p>
</div>
</div>
<i class="fa fa-chevron-right text-gray-400"></i>
</button>
<button class="add-block-btn w-full flex items-center justify-between p-4 border border-gray-200 rounded-lg hover:border-primary hover:bg-blue-50 transition-all-300" data-type="decision">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-purple-100 flex items-center justify-center text-purple-600 mr-4">
<i class="fa fa-check-circle"></i>
</div>
<div>
<h4 class="font-medium text-gray-800">决策点</h4>
<p class="text-sm text-gray-600">记录重要决策和结论(果)</p>
</div>
</div>
<i class="fa fa-chevron-right text-gray-400"></i>
</button>
<button class="add-block-btn w-full flex items-center justify-between p-4 border border-gray-200 rounded-lg hover:border-primary hover:bg-blue-50 transition-all-300" data-type="todo">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-yellow-100 flex items-center justify-center text-yellow-600 mr-4">
<i class="fa fa-tasks"></i>
</div>
<div>
<h4 class="font-medium text-gray-800">待办事项</h4>
<p class="text-sm text-gray-600">添加需要完成的任务(量)</p>
</div>
</div>
<i class="fa fa-chevron-right text-gray-400"></i>
</button>
</div>
</div>
<div class="p-6 border-t border-gray-200 flex justify-end">
<button id="close-modal-btn" class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-all-300">
取消
</button>
</div>
</div>
</div>
<!-- 代码定位模态框(外挂式) -->
<div id="code-location-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center hidden">
<div class="bg-white rounded-xl shadow-lg w-full max-w-3xl mx-4">
<div class="p-6 border-b border-gray-200 flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-800">代码位置信息(外挂式开发)</h3>
<button id="close-code-modal-btn" class="text-gray-400 hover:text-gray-600">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<div class="p-6 code-modal-content">
<div class="mb-4">
<h4 class="font-medium text-gray-800 mb-2" id="code-location-title">功能模块:未指定</h4>
<p class="text-sm text-gray-600 mb-4" id="code-location-desc">点击下方代码片段可以查看完整实现(仅展示关键代码)</p>
<div class="bg-gray-900 text-gray-100 rounded-lg p-4 font-mono text-sm overflow-x-auto" id="code-snippet-container">
<!-- 代码片段将通过JS动态生成 -->
<pre><code>// 请点击页面中的"查看代码"按钮获取具体代码位置</code></pre>
</div>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<h5 class="font-medium text-gray-800 mb-2">开发提示(外挂式省力)</h5>
<ul class="text-sm text-gray-600 space-y-1">
<li>• 代码片段仅展示关键部分,完整代码请查看对应文件</li>
<li>• 行号为参考值,实际行号可能因代码修改而变化</li>
<li>• 建议使用VS Code等编辑器搜索代码中的关键词快速定位</li>
<li>• 修改代码前请备份原始文件(中蕴式安全)</li>
</ul>
</div>
</div>
<div class="p-6 border-t border-gray-200 flex justify-end">
<button id="copy-code-btn" class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark transition-all-300 mr-2">
<i class="fa fa-copy mr-1"></i> 复制代码
</button>
<button id="close-code-btn" class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-all-300">
关闭
</button>
</div>
</div>
</div>
<!-- 添加范畴模态框(外挂式) -->
<div id="add-category-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center hidden">
<div class="bg-white rounded-xl shadow-lg w-full max-w-md mx-4">
<div class="p-6 border-b border-gray-200">
<h3 class="text-lg font-medium text-gray-800">添加新范畴(万向适配/内嵌式)</h3>
</div>
<div class="p-6">
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">范畴名称</label>
<input type="text" id="category-name-input" placeholder="输入范畴名称(如:工作、学习)..." class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">适配维度</label>
<div class="flex gap-3 mb-2">
<label class="flex items-center cursor-pointer">
<input type="radio" name="adapt-dimension" value="universal" class="mr-2" checked>
<span class="adapt-tag adapt-universal">万向</span>
</label>
<label class="flex items-center cursor-pointer">
<input type="radio" name="adapt-dimension" value="industry" class="mr-2">
<span class="adapt-tag adapt-industry">千行</span>
</label>
<label class="flex items-center cursor-pointer">
<input type="radio" name="adapt-dimension" value="business" class="mr-2">
<span class="adapt-tag adapt-business">百业</span>
</label>
</div>
<label class="block text-sm font-medium text-gray-700 mb-1">选择颜色</label>
<div class="grid grid-cols-6 gap-2">
<button class="category-color-btn w-full h-8 rounded-full bg-blue-500 border-2 border-transparent" data-color="#3b82f6"></button>
<button class="category-color-btn w-full h-8 rounded-full bg-green-500 border-2 border-transparent" data-color="#22c55e"></button>
<button class="category-color-btn w-full h-8 rounded-full bg-yellow-500 border-2 border-transparent" data-color="#f59e0b"></button>
<button class="category-color-btn w-full h-8 rounded-full bg-purple-500 border-2 border-transparent" data-color="#a855f7"></button>
<button class="category-color-btn w-full h-8 rounded-full bg-red-500 border-2 border-transparent" data-color="#ef4444"></button>
<button class="category-color-btn w-full h-8 rounded-full bg-gray-500 border-2 border-transparent" data-color="#64748b"></button>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">描述(可选)</label>
<textarea id="category-desc-input" rows="2" placeholder="输入范畴描述(如:适配千行百业的电商讨论)..." class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"></textarea>
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 flex justify-end">
<button id="cancel-category-btn" class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-all-300 mr-2">
取消
</button>
<button id="save-category-btn" class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark transition-all-300">
保存
</button>
</div>
</div>
</div>
<!-- 帮助模态框(内嵌式学习) -->
<div id="help-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center hidden">
<div class="bg-white rounded-xl shadow-lg w-full max-w-2xl mx-4 max-h-[80vh] overflow-y-auto">
<div class="p-6 border-b border-gray-200 flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-800">使用帮助(内嵌式赋能-学习)</h3>
<button id="close-help-modal" class="text-gray-400 hover:text-gray-600">
<i class="fa fa-times"></i>
</button>
</div>
<!-- 新增:设计逻辑标签页 -->
<div class="border-b border-gray-200">
<nav class="flex" aria-label="Help Tabs">
<button class="help-tab-btn px-6 py-3 font-medium text-primary border-b-2 border-primary" data-tab="concept">
核心设计理念
</button>
<button class="help-tab-btn px-6 py-3 font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent" data-tab="usage">
基本使用指南
</button>
<button class="help-tab-btn px-6 py-3 font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent" data-tab="semantic">
语义体系解析
</button>
</nav>
</div>
<!-- 核心设计理念 -->
<div class="help-tab-content p-6" id="concept-tab">
<div class="space-y-6">
<div>
<h4 class="text-lg font-medium text-gray-800 mb-2">三层核心设计理念</h4>
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200 mb-4">
<p class="text-gray-700 font-medium">内嵌式赋能 - 学习(万向 通-通 境 顿)</p>
<p class="text-sm text-gray-600 mt-1">• 万向:适配多行业、多场景的讨论记录需求<br>• 通:功能易懂、操作流畅,一通百通<br>• 境:贴合使用场景,沉浸式记录<br>• 顿:AI总结、提示引导,快速顿悟核心信息</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200 mb-4">
<p class="text-gray-700 font-medium">外挂式省力 - 节约(千行 别-性 行 渐)</p>
<p class="text-sm text-gray-600 mt-1">• 千行:适配千行百业的自定义配置<br>• 别:区分不同功能特性,按需使用<br>• 行:操作高效,一行指令/点击完成操作<br>• 渐:渐进式优化,越用越顺手</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
<p class="text-gray-700 font-medium">中蕴式省心 - 安全(百业 藏-量 果 密)</p>
<p class="text-sm text-gray-600 mt-1">• 百业:满足百业的数据存储需求<br>• 藏:本地存储,数据藏于本地不泄露<br>• 量:量化讨论成果,数据可视化<br>• 密:隐私保护,操作留痕且可追溯</p>
</div>
</div>
<div>
<h4 class="text-lg font-medium text-gray-800 mb-2">2+1数据体系</h4>
<p class="text-gray-600 mb-3">基于您的语义体系,系统构建了三层数据架构:</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-blue-50 p-4 rounded-lg border border-blue-100">
<h5 class="font-medium text-gray-800 mb-2">基础表1:分组层次表</h5>
<p class="text-sm text-gray-600">• 外立(服务标准):内嵌式赋能/外挂式省力/中蕴式省心<br>• 内立(管理制度):学习/节约/安全<br>• 中立(组织机构):万向/千行/百业</p>
</div>
<div class="bg-green-50 p-4 rounded-lg border border-green-100">
<h5 class="font-medium text-gray-800 mb-2">基础表2:直连维度表</h5>
<p class="text-sm text-gray-600">• 内嵌式赋能 → 学习/万向/通/境/顿<br>• 外挂式省力 → 节约/千行/别/行/渐<br>• 中蕴式省心 → 安全/百业/藏/量/果/密</p>
</div>
<div class="bg-purple-50 p-4 rounded-lg border border-purple-100 md:col-span-2">
<h5 class="font-medium text-gray-800 mb-2">结合表:索引表</h5>
<p class="text-sm text-gray-600">• 内容项(文档用语):内嵌式赋能/学习/万向/通/境/顿<br>• 逻辑项(程序用语):外挂式省力/节约/千行/别/行/渐<br>• 字典项(库用语):中蕴式省心/安全/百业/藏/量/果/密</p>
</div>
</div>
</div>
</div>
</div>
<!-- 基本使用指南 -->
<div class="help-tab-content p-6 hidden" id="usage-tab">
<div class="space-y-6">
<div>
<h4 class="text-lg font-medium text-gray-800 mb-2">快速开始</h4>
<ol class="list-decimal list-inside space-y-2 text-gray-600">
<li>点击"创建第一个讨论"开始记录</li>
<li>填写讨论标题、范畴、分类、目录等基本信息</li>
<li>使用"添加内容块"按钮添加文本、时间轴、决策点或待办事项</li>
<li>使用富文本工具栏格式化文本内容</li>
<li>点击"生成总结"获取讨论要点的AI辅助总结</li>
</ol>
</div>
<div>
<h4 class="text-lg font-medium text-gray-800 mb-2">核心功能</h4>
<div class="space-y-3">
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
<h5 class="font-medium text-gray-800">结构化记录</h5>
<p class="text-sm text-gray-600">支持四种内容块类型:文本块(通-通)、时间轴(境)、决策点(果)、待办事项(量),满足不同场景的记录需求。</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
<h5 class="font-medium text-gray-800">自定义配置</h5>
<p class="text-sm text-gray-600">通过"配置管理"可以自定义范畴(万向/千行/百业)、分类关键词(别-性/行/渐)和提示词模板(通/境/顿/藏/量/密)。</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
<h5 class="font-medium text-gray-800">数据安全</h5>
<p class="text-sm text-gray-600">所有数据本地存储(藏/密),支持导出/导入备份,确保数据安全可靠。</p>
</div>
</div>
</div>
<div>
<h4 class="text-lg font-medium text-gray-800 mb-2">快捷键</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-2 text-sm">
<div class="flex justify-between p-2 bg-gray-50 rounded">
<span>Ctrl + B</span>
<span>加粗文本</span>
</div>
<div class="flex justify-between p-2 bg-gray-50 rounded">
<span>Ctrl + I</span>
<span>斜体文本</span>
</div>
<div class="flex justify-between p-2 bg-gray-50 rounded">
<span>Ctrl + U</span>
<span>下划线</span>
</div>
<div class="flex justify-between p-2 bg-gray-50 rounded">
<span>Ctrl + S</span>
<span>手动保存</span>
</div>
</div>
</div>
</div>
</div>
<!-- 语义体系解析 -->
<div class="help-tab-content p-6 hidden" id="semantic-tab">
<div class="space-y-6">
<div>
<h4 class="text-lg font-medium text-gray-800 mb-2">单字语义矩阵</h4>
<div class="overflow-x-auto">
<table class="min-w-full border border-gray-200 rounded-lg">
<thead>
<tr class="bg-gray-50">
<th class="border-b border-gray-200 px-4 py-2 text-left text-sm font-medium text-gray-500">维度</th>
<th class="border-b border-gray-200 px-4 py-2 text-left text-sm font-medium text-gray-500">内嵌式赋能-学习</th>
<th class="border-b border-gray-200 px-4 py-2 text-left text-sm font-medium text-gray-500">外挂式省力-节约</th>
<th class="border-b border-gray-200 px-4 py-2 text-left text-sm font-medium text-gray-500">中蕴式省心-安全</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border-b border-gray-200 px-4 py-2 text-sm font-medium">适配维度</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">万向</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">千行</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">百业</td>
</tr>
<tr>
<td class="border-b border-gray-200 px-4 py-2 text-sm font-medium">反破(圆)</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">通</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">别</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">藏</td>
</tr>
<tr>
<td class="border-b border-gray-200 px-4 py-2 text-sm font-medium">加成(器)</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">通</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">性</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">量</td>
</tr>
<tr>
<td class="border-b border-gray-200 px-4 py-2 text-sm font-medium">减成(唯识论)</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">境</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">行</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">果</td>
</tr>
<tr>
<td class="border-b border-gray-200 px-4 py-2 text-sm font-medium">正破(不定)</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">顿</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">渐</td>
<td class="border-b border-gray-200 px-4 py-2 text-sm">密</td>
</tr>
</tbody>
</table>
</div>
</div>
<div>
<h4 class="text-lg font-medium text-gray-800 mb-2">验证维度落地</h4>
<div class="space-y-3">
<div class="bg-blue-50 p-4 rounded-lg border border-blue-100">
<h5 class="font-medium text-gray-800">表述完整(差异个体 包容性)</h5>
<p class="text-sm text-gray-600">每行覆盖"功能+价值+适配",行序(1/2/3)对应"学习→效率→安全"的用户认知顺序,实现三分法+行序的完整性。</p>
</div>
<div class="bg-green-50 p-4 rounded-lg border border-green-100">
<h5 class="font-medium text-gray-800">描述完备(统一步调 划一性)</h5>
<p class="text-sm text-gray-600">列维度的三元组(如词组列1)形成统一层次(外立/内立/中立),线索一致,实现三元组+层次的完备性。</p>
</div>
<div class="bg-purple-50 p-4 rounded-lg border border-purple-100">
<h5 class="font-medium text-gray-800">表达完全(共性对齐 一致性)</h5>
<p class="text-sm text-gray-600">列项形成三位一体(如"学习-万向-通/境/顿"),列名明确(外立/内立/中立),实现三位一体+列名的完全性。</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- JavaScript 逻辑 -->
<script>
// ==================== 核心数据结构与语义体系 ====================
// 语义映射表(单字原子语义)
const semanticMap = {
'通': '操作易懂', '别': '功能区分', '藏': '本地存储',
'境': '沉浸式编辑', '行': '一键操作', '果': '成果量化',
'顿': '快速顿悟', '渐': '渐进优化', '密': '隐私安全'
};
// 核心配置维度枚举
const dimensionConfig = {
'外立(服务标准)': ['内嵌式赋能', '外挂式省力', '中蕴式省心'],
'内立(管理制度)': ['学习', '节约', '安全'],
'中立(组织机构)': ['万向', '千行', '百业']
};
// 价值维度统计(用于仪表盘显示)
let valueStats = {
learn: 0, // 学习维度(提示词使用/帮助查看次数)
save: 0, // 效率维度(快捷键/一键操作次数)
safe: 0 // 安全维度(备份/自动保存次数)
};
// 数据存储键名
const STORAGE_KEYS = {
DISCUSSIONS: 'discussMemo_discussions',
CATEGORIES: 'discussMemo_categories',
SUBJECTS: 'discussMemo_subjects',
PROMPTS: 'discussMemo_prompts',
STATS: 'discussMemo_stats',
THEME: 'discussMemo_theme',
GROUP_HIERARCHY: 'discussMemo_groupHierarchy',
DIRECT_DIMENSION: 'discussMemo_directDimension',
INDEX_TABLE: 'discussMemo_indexTable'
};
// 初始化基础表和结合表
function initializeDataTables() {
// 基础表1:分组层次表
const groupHierarchy = {
'外立(服务标准)': ['内嵌式赋能', '外挂式省力', '中蕴式省心'],
'内立(管理制度)': ['学习', '节约', '安全'],
'中立(组织机构)': ['万向', '千行', '百业'],
'反破(圆)': ['通', '别', '藏'],
'加成/减成(器/唯识论)': ['通/境', '性/行', '量/果'],
'正破(不定)': ['顿', '渐', '密']
};
// 基础表2:直连维度表
const directDimension = {
'内嵌式赋能': ['学习', '万向', '通', '境', '顿'],
'外挂式省力': ['节约', '千行', '别', '行', '渐'],
'中蕴式省心': ['安全', '百业', '藏', '量', '果', '密']
};
// 结合表:索引表
const indexTable = {
'内容项(文档用语)': ['内嵌式赋能', '学习', '万向', '通', '境', '顿'],
'逻辑项(程序用语)': ['外挂式省力', '节约', '千行', '别', '行', '渐'],
'字典项(库用语)': ['中蕴式省心', '安全', '百业', '藏', '量', '果', '密']
};
// 存储基础表和结合表
localStorage.setItem(STORAGE_KEYS.GROUP_HIERARCHY, JSON.stringify(groupHierarchy));
localStorage.setItem(STORAGE_KEYS.DIRECT_DIMENSION, JSON.stringify(directDimension));
localStorage.setItem(STORAGE_KEYS.INDEX_TABLE, JSON.stringify(indexTable));
}
// ==================== 工具函数 ====================
// 生成唯一ID
function generateId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
// 格式化日期
function formatDate(date) {
if (!date) return '-';
const d = new Date(date);
return d.toLocaleDateString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
}
// 防抖函数
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// 显示提示消息
function showToast(message, type = 'info') {
const toastContainer = document.createElement('div');
toastContainer.className = `toast fixed bottom-4 right-4 px-4 py-2 rounded-lg shadow-lg z-50 ${
type === 'success' ? 'bg-success text-white' :
type === 'error' ? 'bg-danger text-white' :
type === 'warning' ? 'bg-warning text-white' :
'bg-primary text-white'
}`;
toastContainer.textContent = message;
document.body.appendChild(toastContainer);
setTimeout(() => toastContainer.classList.add('show'), 10);
setTimeout(() => {
toastContainer.classList.remove('show');
setTimeout(() => document.body.removeChild(toastContainer), 300);
}, 3000);
}
// ==================== 数据管理 ====================
// 获取数据
function getData(key, defaultValue = null) {
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : defaultValue;
} catch (error) {
console.error(`获取数据失败 [${key}]:`, error);
return defaultValue;
}
}
// 保存数据
function saveData(key, data) {
try {
localStorage.setItem(key, JSON.stringify(data));
return true;
} catch (error) {
console.error(`保存数据失败 [${key}]:`, error);
showToast('数据保存失败,请检查浏览器存储权限', 'error');
return false;
}
}
// 获取所有讨论
function getDiscussions() {
return getData(STORAGE_KEYS.DISCUSSIONS, []);
}
// 保存讨论
function saveDiscussion(discussion) {
const discussions = getDiscussions();
const index = discussions.findIndex(d => d.id === discussion.id);
if (index >= 0) {
discussions[index] = discussion;
} else {
discussions.push(discussion);
}
saveData(STORAGE_KEYS.DISCUSSIONS, discussions);
updateStats(); // 更新统计数据
return discussion;
}
// 删除讨论
function deleteDiscussion(id) {
const discussions = getDiscussions();
const filteredDiscussions = discussions.filter(d => d.id !== id);
saveData(STORAGE_KEYS.DISCUSSIONS, filteredDiscussions);
updateStats(); // 更新统计数据
}
// 获取分类
function getCategories() {
return getData(STORAGE_KEYS.CATEGORIES, [
{ id: '1', name: '工作', color: '#3b82f6', dimension: 'universal', description: '工作相关讨论' },
{ id: '2', name: '学习', color: '#22c55e', dimension: 'universal', description: '学习相关讨论' },
{ id: '3', name: '生活', color: '#f59e0b', dimension: 'universal', description: '生活相关讨论' }
]);
}
// 保存分类
function saveCategory(category) {
const categories = getCategories();
const index = categories.findIndex(c => c.id === category.id);
if (index >= 0) {
categories[index] = category;
} else {
category.id = generateId();
categories.push(category);
}
saveData(STORAGE_KEYS.CATEGORIES, categories);
return category;
}
// 删除分类
function deleteCategory(id) {
const categories = getCategories();
const filteredCategories = categories.filter(c => c.id !== id);
saveData(STORAGE_KEYS.CATEGORIES, filteredCategories);
}
// 获取分类关键词
function getSubjects() {
return getData(STORAGE_KEYS.SUBJECTS, [
'项目规划', '会议记录', '问题讨论', '决策分析',
'学习笔记', '研究报告', '创意构思', '任务分配'
]);
}
// 保存分类关键词
function saveSubjects(subjects) {
saveData(STORAGE_KEYS.SUBJECTS, subjects);
}
// 获取提示词模板
function getPrompts() {
return getData(STORAGE_KEYS.PROMPTS, [
{
id: '1',
title: '会议记录',
content: '## 会议基本信息\n- 日期:\n- 参与人员:\n- 主持人:\n\n## 议程\n1. \n2. \n\n## 讨论要点\n\n## 决策事项\n\n## 行动项\n',
tags: ['会议', '记录']
},
{
id: '2',
title: '项目规划',
content: '## 项目概述\n\n## 目标与范围\n\n## 时间线\n\n## 资源需求\n\n## 风险评估\n\n## 里程碑\n',
tags: ['项目', '规划']
},
{
id: '3',
title: '问题分析',
content: '## 问题描述\n\n## 影响范围\n\n## 根本原因分析\n\n## 可能的解决方案\n\n## 推荐方案\n\n## 实施计划\n',
tags: ['问题', '分析']
}
]);
}
// 保存提示词模板
function savePrompt(prompt) {
const prompts = getPrompts();
const index = prompts.findIndex(p => p.id === prompt.id);
if (index >= 0) {
prompts[index] = prompt;
} else {
prompt.id = generateId();
prompts.push(prompt);
}
saveData(STORAGE_KEYS.PROMPTS, prompts);
return prompt;
}
// 删除提示词模板
function deletePrompt(id) {
const prompts = getPrompts();
const filteredPrompts = prompts.filter(p => p.id !== id);
saveData(STORAGE_KEYS.PROMPTS, filteredPrompts);
}
// 更新统计数据
function updateStats() {
const discussions = getDiscussions();
let pendingTodos = 0;
let completedDecisions = 0;
let lastUpdated = null;
discussions.forEach(discussion => {
// 更新最后更新时间
if (!lastUpdated || new Date(discussion.updatedAt) > new Date(lastUpdated)) {
lastUpdated = discussion.updatedAt;
}
// 统计待办事项和决策
discussion.contentBlocks.forEach(block => {
if (block.type === 'todo') {
pendingTodos += block.items.filter(item => !item.completed).length;
} else if (block.type === 'decision') {
if (block.status === 'completed') {
completedDecisions++;
}
}
});
});
// 更新统计显示
document.getElementById('total-discussions').textContent = discussions.length;
document.getElementById('pending-todos').textContent = pendingTodos;
document.getElementById('completed-decisions').textContent = completedDecisions;
document.getElementById('last-updated').textContent = formatDate(lastUpdated);
// 更新价值维度统计
document.getElementById('learn-stats').textContent = valueStats.learn;
document.getElementById('save-stats').textContent = valueStats.save;
document.getElementById('safe-stats').textContent = valueStats.safe;
// 更新完成率
const totalTasks = discussions.reduce((sum, d) => {
return sum + d.contentBlocks.reduce((blockSum, block) => {
return blockSum + (block.type === 'todo' ? block.items.length : 0);
}, 0);
}, 0);
const completedTasks = totalTasks - pendingTodos;
const completionRate = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
document.getElementById('completion-rate').textContent = `${completionRate}%`;
}
// ==================== UI 渲染 ====================
// 渲染分类列表
function renderCategories() {
const categories = getCategories();
const categoriesList = document.getElementById('categories-list');
categoriesList.innerHTML = '';
// 添加"全部"选项
const allOption = document.createElement('div');
allOption.className = 'flex items-center space-x-2 p-2 rounded-md hover:bg-gray-100 cursor-pointer category-option active';
allOption.dataset.category = 'all';
allOption.innerHTML = `
<div class="w-3 h-3 rounded-full bg-primary"></div>
<span class="text-sm">全部</span>
<span class="ml-auto text-xs text-gray-500">${getDiscussions().length}</span>
`;
categoriesList.appendChild(allOption);
// 添加分类选项
categories.forEach(category => {
const categoryCount = getDiscussions().filter(d => d.category === category.id).length;
const option = document.createElement('div');
option.className = 'flex items-center space-x-2 p-2 rounded-md hover:bg-gray-100 cursor-pointer category-option';
option.dataset.category = category.id;
option.innerHTML = `
<div class="w-3 h-3 rounded-full" style="background-color: ${category.color}"></div>
<span class="text-sm">${category.name}</span>
<span class="ml-auto text-xs text-gray-500">${categoryCount}</span>
<span class="adapt-tag adapt-${category.dimension}">${category.dimension === 'universal' ? '万向' : category.dimension === 'industry' ? '千行' : '百业'}</span>
`;
categoriesList.appendChild(option);
});
// 添加点击事件
document.querySelectorAll('.category-option').forEach(option => {
option.addEventListener('click', () => {
document.querySelectorAll('.category-option').forEach(o => o.classList.remove('active', 'bg-gray-100'));
option.classList.add('active', 'bg-gray-100');
renderDiscussions(option.dataset.category);
});
});
}
// 渲染讨论列表
function renderDiscussions(categoryFilter = 'all') {
const discussions = getDiscussions();
const discussionList = document.getElementById('discussion-list');
const emptyMsg = document.getElementById('empty-discussion-msg');
// 过滤讨论
let filteredDiscussions = discussions;
if (categoryFilter !== 'all') {
filteredDiscussions = discussions.filter(d => d.category === categoryFilter);
}
// 按更新时间排序
filteredDiscussions.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));
// 渲染讨论列表
if (filteredDiscussions.length === 0) {
discussionList.innerHTML = '';
emptyMsg.classList.remove('hidden');
return;
}
emptyMsg.classList.add('hidden');
discussionList.innerHTML = '';
filteredDiscussions.forEach(discussion => {
const category = getCategories().find(c => c.id === discussion.category);
const item = document.createElement('div');
item.className = 'p-3 rounded-lg hover:bg-gray-100 cursor-pointer transition-all-300 border border-transparent hover:border-gray-200';
item.dataset.id = discussion.id;
// 计算待办事项数量
const todoCount = discussion.contentBlocks.reduce((sum, block) => {
if (block.type === 'todo') {
return sum + block.items.filter(item => !item.completed).length;
}
return sum;
}, 0);
item.innerHTML = `
<div class="flex items-start justify-between">
<div class="flex-1">
<h4 class="font-medium text-gray-800 truncate">${discussion.title}</h4>
<div class="flex items-center mt-1 text-xs text-gray-500">
<span class="inline-block w-2 h-2 rounded-full mr-1" style="background-color: ${category ? category.color : '#ccc'}"></span>
<span>${category ? category.name : '未分类'}</span>
<span class="mx-1">•</span>
<span>${discussion.subject}</span>
</div>
</div>
${todoCount > 0 ? `<span class="bg-yellow-100 text-yellow-800 text-xs px-2 py-0.5 rounded-full">${todoCount} 待办</span>` : ''}
</div>
<div class="mt-2 text-xs text-gray-500">
<span>${formatDate(discussion.updatedAt)}</span>
</div>
`;
// 添加点击事件
item.addEventListener('click', () => {
openDiscussion(discussion.id);
});
discussionList.appendChild(item);
});
}
// 渲染仪表盘
function renderDashboard() {
// 更新统计数据
updateStats();
// 渲染分类分布图表
renderCategoryChart();
// 渲染最近讨论
renderRecentDiscussions();
// 渲染提示词导航
renderPrompts();
}
// 渲染分类分布图表
function renderCategoryChart() {
const discussions = getDiscussions();
const categories = getCategories();
const sectorsContainer = document.getElementById('dashboard-sectors');
const legendContainer = document.getElementById('category-legend');
// 计算每个分类的讨论数量
const categoryCounts = {};
categories.forEach(category => {
categoryCounts[category.id] = discussions.filter(d => d.category === category.id).length;
});
// 计算总讨论数
const totalDiscussions = discussions.length;
// 渲染扇区
sectorsContainer.innerHTML = '';
let startAngle = 0;
categories.forEach(category => {
const count = categoryCounts[category.id] || 0;
if (count === 0) return;
const percentage = (count / totalDiscussions) * 100;
const endAngle = startAngle + (percentage / 100) * 360;
// 创建扇区
const sector = document.createElement('div');
sector.className = 'absolute inset-0 dashboard-sector';
sector.style.backgroundColor = category.color;
sector.style.clipPath = `polygon(50% 50%, ${50 + 50 * Math.cos(startAngle * Math.PI / 180)}% ${50 + 50 * Math.sin(startAngle * Math.PI / 180)}%, ${50 + 50 * Math.cos(endAngle * Math.PI / 180)}% ${50 + 50 * Math.sin(endAngle * Math.PI / 180)}%)`;
sector.title = `${category.name}: ${count} 个讨论 (${percentage.toFixed(1)}%)`;
sectorsContainer.appendChild(sector);
startAngle = endAngle;
});
// 渲染图例
legendContainer.innerHTML = '';
categories.forEach(category => {
const count = categoryCounts[category.id] || 0;
if (count === 0) return;
const percentage = (count / totalDiscussions) * 100;
const legendItem = document.createElement('div');
legendItem.className = 'flex items-center text-xs';
legendItem.innerHTML = `
<div class="w-3 h-3 rounded-full mr-2" style="background-color: ${category.color}"></div>
<span class="flex-1 truncate">${category.name}</span>
<span class="text-gray-500">${percentage.toFixed(1)}%</span>
`;
legendContainer.appendChild(legendItem);
});
}
// 渲染最近讨论
function renderRecentDiscussions() {
const discussions = getDiscussions();
const recentContainer = document.getElementById('recent-discussions');
// 按更新时间排序并取最近5个
const recentDiscussions = [...discussions]
.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt))
.slice(0, 5);
if (recentDiscussions.length === 0) {
recentContainer.innerHTML = `
<div class="text-center py-8 text-gray-500">
<p>暂无讨论记录</p>
</div>
`;
return;
}
recentContainer.innerHTML = '';
recentDiscussions.forEach(discussion => {
const category = getCategories().find(c => c.id === discussion.category);
const item = document.createElement('div');
item.className = 'p-4 border border-gray-200 rounded-lg hover:border-primary transition-all-300 cursor-pointer';
item.dataset.id = discussion.id;
// 提取讨论要点
const keyPoints = [];
discussion.contentBlocks.forEach(block => {
if (block.type === 'decision' && block.content) {
keyPoints.push(`<span class="text-purple-600">✓ ${block.content}</span>`);
} else if (block.type === 'todo') {
const pendingTasks = block.items.filter(item => !item.completed);
if (pendingTasks.length > 0) {
keyPoints.push(`<span class="text-yellow-600">• ${pendingTasks[0].text}</span>`);
}
}
});
item.innerHTML = `
<div class="flex items-start justify-between">
<div class="flex-1">
<div class="flex items-center">
<h4 class="font-medium text-gray-800">${discussion.title}</h4>
<span class="inline-flex items-center justify-center w-5 h-5 ml-2 text-xs bg-${category ? category.dimension === 'universal' ? 'blue' : category.dimension === 'industry' ? 'purple' : 'green'}-100 text-${category ? category.dimension === 'universal' ? 'blue' : category.dimension === 'industry' ? 'purple' : 'green'}-600 rounded-full">
${category ? category.dimension === 'universal' ? '万' : category.dimension === 'industry' ? '千' : '百'}</span>
</div>
<div class="flex items-center mt-1 text-xs text-gray-500">
<span class="inline-block w-2 h-2 rounded-full mr-1" style="background-color: ${category ? category.color : '#ccc'}"></span>
<span>${category ? category.name : '未分类'}</span>
<span class="mx-1">•</span>
<span>${discussion.subject}</span>
<span class="mx-1">•</span>
<span>${formatDate(discussion.updatedAt)}</span>
</div>
</div>
<button class="text-gray-400 hover:text-gray-600 delete-discussion" data-id="${discussion.id}">
<i class="fa fa-trash-o"></i>
</button>
</div>
${keyPoints.length > 0 ? `
<div class="mt-2 text-sm">
<p>要点:${keyPoints.slice(0, 2).join('、')}${keyPoints.length > 2 ? '...' : ''}</p>
</div>
` : ''}
`;
// 添加点击事件
item.addEventListener('click', (e) => {
if (!e.target.closest('.delete-discussion')) {
openDiscussion(discussion.id);
}
});
recentContainer.appendChild(item);
});
// 添加删除事件
document.querySelectorAll('.delete-discussion').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const id = btn.dataset.id;
if (confirm('确定要删除这个讨论吗?')) {
deleteDiscussion(id);
renderDashboard();
renderDiscussions();
renderCategories();
showToast('讨论已删除', 'success');
}
});
});
}
// 渲染提示词导航
function renderPrompts() {
const prompts = getPrompts();
const promptsContainer = document.getElementById('prompts-container');
promptsContainer.innerHTML = '';
prompts.forEach(prompt => {
const card = document.createElement('div');
card.className = 'p-4 border border-gray-200 rounded-lg hover:border-primary hover:bg-blue-50 transition-all-300 cursor-pointer';
card.dataset.id = prompt.id;
card.innerHTML = `
<div class="flex items-start justify-between">
<div>
<h4 class="font-medium text-gray-800">${prompt.title}</h4>
<div class="mt-1 text-xs text-gray-500">
${prompt.tags ? prompt.tags.map(tag => `<span class="inline-block bg-gray-100 rounded-full px-2 py-0.5 mr-1">${tag}</span>`).join('') : ''}
</div>
</div>
<div class="flex space-x-2">
<button class="text-gray-400 hover:text-gray-600 edit-prompt" data-id="${prompt.id}">
<i class="fa fa-pencil"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 delete-prompt" data-id="${prompt.id}">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
<div class="mt-2 text-sm text-gray-600 line-clamp-2">
${prompt.content.replace(/\n/g, ' ').replace(/##/g, '').trim()}
</div>
`;
// 添加点击事件
card.addEventListener('click', (e) => {
if (!e.target.closest('.edit-prompt') && !e.target.closest('.delete-prompt')) {
// 使用提示词创建新讨论
createDiscussionFromPrompt(prompt);
}
});
promptsContainer.appendChild(card);
});
// 添加编辑和删除事件
document.querySelectorAll('.edit-prompt').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const id = btn.dataset.id;
// 这里可以添加编辑提示词的逻辑
showToast('编辑功能开发中...', 'info');
});
});
document.querySelectorAll('.delete-prompt').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const id = btn.dataset.id;
if (confirm('确定要删除这个提示词模板吗?')) {
deletePrompt(id);
renderPrompts();
showToast('提示词模板已删除', 'success');
}
});
});
}
// ==================== 讨论编辑 ====================
// 打开讨论
function openDiscussion(id) {
const discussion = getDiscussions().find(d => d.id === id);
if (!discussion) return;
// 切换到编辑视图
document.getElementById('dashboard-view').classList.add('hidden');
document.getElementById('welcome-view').classList.add('hidden');
document.getElementById('config-view').classList.add('hidden');
document.getElementById('editor-view').classList.remove('hidden');
// 填充表单
document.getElementById('discussion-title').value = discussion.title;
document.getElementById('discussion-category').value = discussion.category;
document.getElementById('discussion-subject').value = discussion.subject;
document.getElementById('discussion-topic').value = discussion.topic;
// 渲染标签
renderTags(discussion.tags || []);
// 渲染内容块
renderContentBlocks(discussion.contentBlocks || []);
// 设置当前讨论ID
document.getElementById('editor-view').dataset.id = id;
// 更新价值维度统计
valueStats.learn++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
}
// 创建新讨论
function createNewDiscussion() {
const discussion = {
id: generateId(),
title: '',
category: '',
subject: '',
topic: '',
tags: [],
contentBlocks: [],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
// 保存讨论
saveDiscussion(discussion);
// 打开讨论
openDiscussion(discussion.id);
// 更新列表
renderDiscussions();
renderCategories();
// 更新价值维度统计
valueStats.save++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
}
// 从提示词创建讨论
function createDiscussionFromPrompt(prompt) {
const discussion = {
id: generateId(),
title: prompt.title,
category: '',
subject: prompt.title,
topic: '',
tags: prompt.tags || [],
contentBlocks: [
{
id: generateId(),
type: 'text',
content: prompt.content,
order: 0
}
],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
// 保存讨论
saveDiscussion(discussion);
// 打开讨论
openDiscussion(discussion.id);
// 更新列表
renderDiscussions();
renderCategories();
// 更新价值维度统计
valueStats.learn++;
valueStats.save++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
showToast('已从模板创建讨论', 'success');
}
// 渲染标签
function renderTags(tags) {
const tagsContainer = document.getElementById('tags-container');
tagsContainer.innerHTML = '';
tags.forEach(tag => {
const tagElement = document.createElement('div');
tagElement.className = 'flex items-center bg-gray-100 rounded-full px-3 py-1';
tagElement.innerHTML = `
<span class="text-sm text-gray-600">${tag}</span>
<button class="ml-1 text-gray-400 hover:text-gray-600 remove-tag">
<i class="fa fa-times"></i>
</button>
`;
// 添加删除事件
tagElement.querySelector('.remove-tag').addEventListener('click', () => {
const updatedTags = tags.filter(t => t !== tag);
updateDiscussionTags(updatedTags);
renderTags(updatedTags);
});
tagsContainer.appendChild(tagElement);
});
}
// 更新讨论标签
function updateDiscussionTags(tags) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
discussion.tags = tags;
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
}
}
// 渲染内容块
function renderContentBlocks(blocks) {
const container = document.getElementById('content-blocks-container');
const emptyMsg = document.getElementById('empty-content-msg');
// 清空容器
container.innerHTML = '';
if (blocks.length === 0) {
emptyMsg.classList.remove('hidden');
container.appendChild(emptyMsg);
return;
}
emptyMsg.classList.add('hidden');
// 按顺序渲染内容块
blocks.sort((a, b) => a.order - b.order).forEach(block => {
const blockElement = document.createElement('div');
blockElement.className = 'content-block p-4 border border-gray-200 rounded-lg relative';
blockElement.dataset.id = block.id;
blockElement.dataset.type = block.type;
// 根据类型渲染不同的内容块
switch (block.type) {
case 'text':
blockElement.innerHTML = `
<div class="flex items-center justify-between mb-2">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center text-primary mr-2">
<i class="fa fa-align-left"></i>
</div>
<h4 class="font-medium text-gray-800">文本块</h4>
</div>
<div class="flex space-x-2">
<button class="text-gray-400 hover:text-gray-600 move-block" data-direction="up">
<i class="fa fa-arrow-up"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 move-block" data-direction="down">
<i class="fa fa-arrow-down"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 delete-block" data-id="${block.id}">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
<div class="editable-content" contenteditable="true">${block.content || ''}</div>
`;
break;
case 'timeline':
blockElement.innerHTML = `
<div class="flex items-center justify-between mb-2">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center text-green-600 mr-2">
<i class="fa fa-clock-o"></i>
</div>
<h4 class="font-medium text-gray-800">时间轴</h4>
</div>
<div class="flex space-x-2">
<button class="text-gray-400 hover:text-gray-600 move-block" data-direction="up">
<i class="fa fa-arrow-up"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 move-block" data-direction="down">
<i class="fa fa-arrow-down"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 delete-block" data-id="${block.id}">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
<div class="timeline-container space-y-3">
${block.items ? block.items.map(item => `
<div class="flex">
<div class="flex flex-col items-center mr-4">
<div class="w-3 h-3 rounded-full bg-green-500"></div>
<div class="w-0.5 h-full bg-green-200"></div>
</div>
<div class="flex-1">
<div class="text-sm font-medium text-gray-800">${item.time || ''}</div>
<div class="text-sm text-gray-600">${item.content || ''}</div>
</div>
</div>
`).join('') : ''}
<div class="flex">
<div class="flex flex-col items-center mr-4">
<div class="w-3 h-3 rounded-full bg-green-300"></div>
</div>
<div class="flex-1">
<button class="text-sm text-primary hover:text-primary-dark add-timeline-item" data-block-id="${block.id}">
<i class="fa fa-plus-circle"></i> 添加时间点
</button>
</div>
</div>
</div>
`;
break;
case 'decision':
blockElement.innerHTML = `
<div class="flex items-center justify-between mb-2">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-purple-100 flex items-center justify-center text-purple-600 mr-2">
<i class="fa fa-check-circle"></i>
</div>
<h4 class="font-medium text-gray-800">决策点</h4>
</div>
<div class="flex items-center space-x-2">
<span class="text-xs px-2 py-1 rounded-full ${block.status === 'completed' ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'}">
${block.status === 'completed' ? '已确认' : '待确认'}
</span>
<button class="text-gray-400 hover:text-gray-600 move-block" data-direction="up">
<i class="fa fa-arrow-up"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 move-block" data-direction="down">
<i class="fa fa-arrow-down"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 delete-block" data-id="${block.id}">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
<div class="decision-container">
<div class="editable-content" contenteditable="true">${block.content || ''}</div>
<div class="mt-2 flex justify-end">
<button class="text-xs px-3 py-1 rounded-full ${block.status === 'completed' ? 'bg-yellow-100 text-yellow-800' : 'bg-green-100 text-green-800'} toggle-decision-status" data-block-id="${block.id}">
${block.status === 'completed' ? '标记为待确认' : '标记为已确认'}
</button>
</div>
</div>
`;
break;
case 'todo':
blockElement.innerHTML = `
<div class="flex items-center justify-between mb-2">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-yellow-100 flex items-center justify-center text-yellow-600 mr-2">
<i class="fa fa-tasks"></i>
</div>
<h4 class="font-medium text-gray-800">待办事项</h4>
</div>
<div class="flex space-x-2">
<button class="text-gray-400 hover:text-gray-600 move-block" data-direction="up">
<i class="fa fa-arrow-up"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 move-block" data-direction="down">
<i class="fa fa-arrow-down"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 delete-block" data-id="${block.id}">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
<div class="todo-container space-y-2">
${block.items ? block.items.map(item => `
<div class="flex items-center">
<input type="checkbox" class="todo-checkbox w-4 h-4 text-primary rounded border-gray-300 focus:ring-primary" ${item.completed ? 'checked' : ''} data-block-id="${block.id}" data-item-id="${item.id}">
<span class="ml-2 text-sm ${item.completed ? 'line-through text-gray-400' : 'text-gray-700'}">${item.text}</span>
</div>
`).join('') : ''}
<div class="flex items-center">
<input type="checkbox" class="w-4 h-4 text-primary rounded border-gray-300 focus:ring-primary opacity-50" disabled>
<input type="text" class="ml-2 text-sm flex-1 border-0 border-b border-gray-300 focus:outline-none focus:ring-0 add-todo-input" placeholder="添加新任务..." data-block-id="${block.id}">
</div>
</div>
`;
break;
}
container.appendChild(blockElement);
// 添加可编辑内容的事件
const editableContent = blockElement.querySelector('.editable-content');
if (editableContent) {
editableContent.addEventListener('input', debounce(() => {
updateContentBlock(block.id, { content: editableContent.innerHTML });
}, 500));
}
});
// 添加移动和删除事件
document.querySelectorAll('.move-block').forEach(btn => {
btn.addEventListener('click', () => {
const direction = btn.dataset.direction;
const blockId = btn.closest('.content-block').dataset.id;
moveContentBlock(blockId, direction);
});
});
document.querySelectorAll('.delete-block').forEach(btn => {
btn.addEventListener('click', () => {
const blockId = btn.dataset.id;
deleteContentBlock(blockId);
});
});
// 添加时间轴项目事件
document.querySelectorAll('.add-timeline-item').forEach(btn => {
btn.addEventListener('click', () => {
const blockId = btn.dataset.blockId;
addTimelineItem(blockId);
});
});
// 添加切换决策状态事件
document.querySelectorAll('.toggle-decision-status').forEach(btn => {
btn.addEventListener('click', () => {
const blockId = btn.dataset.blockId;
toggleDecisionStatus(blockId);
});
});
// 添加待办事项事件
document.querySelectorAll('.todo-checkbox').forEach(checkbox => {
checkbox.addEventListener('change', () => {
const blockId = checkbox.dataset.blockId;
const itemId = checkbox.dataset.itemId;
toggleTodoItem(blockId, itemId, checkbox.checked);
});
});
document.querySelectorAll('.add-todo-input').forEach(input => {
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && input.value.trim()) {
const blockId = input.dataset.blockId;
addTodoItem(blockId, input.value.trim());
input.value = '';
}
});
});
}
// 更新内容块
function updateContentBlock(blockId, updates) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
const blockIndex = discussion.contentBlocks.findIndex(b => b.id === blockId);
if (blockIndex >= 0) {
discussion.contentBlocks[blockIndex] = {
...discussion.contentBlocks[blockIndex],
...updates
};
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
}
}
}
// 移动内容块
function moveContentBlock(blockId, direction) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
const blockIndex = discussion.contentBlocks.findIndex(b => b.id === blockId);
if (blockIndex >= 0) {
const newIndex = direction === 'up' ? blockIndex - 1 : blockIndex + 1;
if (newIndex >= 0 && newIndex < discussion.contentBlocks.length) {
// 交换位置
const temp = discussion.contentBlocks[blockIndex];
discussion.contentBlocks[blockIndex] = discussion.contentBlocks[newIndex];
discussion.contentBlocks[newIndex] = temp;
// 更新顺序
discussion.contentBlocks.forEach((block, index) => {
block.order = index;
});
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 重新渲染
renderContentBlocks(discussion.contentBlocks);
}
}
}
}
// 删除内容块
function deleteContentBlock(blockId) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
discussion.contentBlocks = discussion.contentBlocks.filter(b => b.id !== blockId);
// 更新顺序
discussion.contentBlocks.forEach((block, index) => {
block.order = index;
});
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 重新渲染
renderContentBlocks(discussion.contentBlocks);
}
}
// 添加时间轴项目
function addTimelineItem(blockId) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
const blockIndex = discussion.contentBlocks.findIndex(b => b.id === blockId);
if (blockIndex >= 0) {
const block = discussion.contentBlocks[blockIndex];
if (!block.items) {
block.items = [];
}
block.items.push({
id: generateId(),
time: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
content: ''
});
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 重新渲染
renderContentBlocks(discussion.contentBlocks);
}
}
}
// 切换决策状态
function toggleDecisionStatus(blockId) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
const blockIndex = discussion.contentBlocks.findIndex(b => b.id === blockId);
if (blockIndex >= 0) {
const block = discussion.contentBlocks[blockIndex];
block.status = block.status === 'completed' ? 'pending' : 'completed';
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 重新渲染
renderContentBlocks(discussion.contentBlocks);
// 更新统计
updateStats();
}
}
}
// 添加待办事项
function addTodoItem(blockId, text) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
const blockIndex = discussion.contentBlocks.findIndex(b => b.id === blockId);
if (blockIndex >= 0) {
const block = discussion.contentBlocks[blockIndex];
if (!block.items) {
block.items = [];
}
block.items.push({
id: generateId(),
text: text,
completed: false
});
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 重新渲染
renderContentBlocks(discussion.contentBlocks);
// 更新统计
updateStats();
}
}
}
// 切换待办事项状态
function toggleTodoItem(blockId, itemId, completed) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
const blockIndex = discussion.contentBlocks.findIndex(b => b.id === blockId);
if (blockIndex >= 0) {
const block = discussion.contentBlocks[blockIndex];
const itemIndex = block.items.findIndex(i => i.id === itemId);
if (itemIndex >= 0) {
block.items[itemIndex].completed = completed;
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 重新渲染
renderContentBlocks(discussion.contentBlocks);
// 更新统计
updateStats();
}
}
}
}
// 生成AI总结
function generateSummary() {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (!discussion) return;
const summaryContainer = document.getElementById('summary-container');
summaryContainer.innerHTML = '<p class="text-center text-gray-500">正在生成总结...</p>';
// 模拟AI处理延迟
setTimeout(() => {
let summary = `# ${discussion.title} 讨论总结\n\n`;
// 提取决策点
const decisions = discussion.contentBlocks.filter(b => b.type === 'decision' && b.content);
if (decisions.length > 0) {
summary += `## 关键决策\n\n`;
decisions.forEach((decision, index) => {
summary += `${index + 1}. ${decision.content.replace(/<[^>]*>/g, '')}\n`;
});
summary += `\n`;
}
// 提取待办事项
const todos = [];
discussion.contentBlocks.forEach(block => {
if (block.type === 'todo' && block.items) {
block.items.forEach(item => {
if (!item.completed) {
todos.push(item.text);
}
});
}
});
if (todos.length > 0) {
summary += `## 待办事项\n\n`;
todos.forEach((todo, index) => {
summary += `${index + 1}. ${todo}\n`;
});
summary += `\n`;
}
// 提取时间线
const timelineItems = [];
discussion.contentBlocks.forEach(block => {
if (block.type === 'timeline' && block.items) {
block.items.forEach(item => {
if (item.time && item.content) {
timelineItems.push({ time: item.time, content: item.content });
}
});
}
});
if (timelineItems.length > 0) {
summary += `## 时间线\n\n`;
timelineItems.forEach(item => {
summary += `${item.time} - ${item.content}\n`;
});
}
// 显示总结
summaryContainer.innerHTML = `
<div class="markdown-body">
${summary.replace(/\n/g, '<br>').replace(/^# (.*$)/gm, '<h1 class="text-xl font-bold">$1</h1>').replace(/^## (.*$)/gm, '<h2 class="text-lg font-semibold mt-2">$1</h2>')}
</div>
`;
// 更新价值维度统计
valueStats.learn++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
showToast('总结已生成', 'success');
}, 1500);
}
// ==================== 事件监听 ====================
// 初始化事件监听
function initializeEventListeners() {
// 导航按钮
document.getElementById('dashboard-btn').addEventListener('click', () => {
document.getElementById('dashboard-view').classList.remove('hidden');
document.getElementById('editor-view').classList.add('hidden');
document.getElementById('config-view').classList.add('hidden');
document.getElementById('welcome-view').classList.add('hidden');
renderDashboard();
});
document.getElementById('config-btn').addEventListener('click', () => {
document.getElementById('dashboard-view').classList.add('hidden');
document.getElementById('editor-view').classList.add('hidden');
document.getElementById('config-view').classList.remove('hidden');
document.getElementById('welcome-view').classList.add('hidden');
renderConfigView();
});
document.getElementById('back-to-dashboard').addEventListener('click', () => {
document.getElementById('dashboard-view').classList.remove('hidden');
document.getElementById('config-view').classList.add('hidden');
renderDashboard();
});
// 新建讨论
document.getElementById('new-discussion-btn').addEventListener('click', createNewDiscussion);
document.getElementById('create-first-discussion').addEventListener('click', createNewDiscussion);
document.getElementById('explore-dashboard').addEventListener('click', () => {
document.getElementById('dashboard-view').classList.remove('hidden');
document.getElementById('welcome-view').classList.add('hidden');
renderDashboard();
});
// 备份按钮
document.getElementById('backup-btn').addEventListener('click', () => {
document.getElementById('backup-modal').classList.remove('hidden');
loadBackupData();
// 更新价值维度统计
valueStats.safe++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
});
// 关闭备份模态框
document.getElementById('close-backup-modal').addEventListener('click', () => {
document.getElementById('backup-modal').classList.add('hidden');
});
document.getElementById('close-backup-btn').addEventListener('click', () => {
document.getElementById('backup-modal').classList.add('hidden');
});
// 导出数据
document.getElementById('export-data-btn').addEventListener('click', exportData);
// 导入数据
document.getElementById('import-file').addEventListener('change', importData);
// 重置数据
document.getElementById('reset-data-btn').addEventListener('click', () => {
if (confirm('确定要重置所有数据吗?这将删除所有讨论和配置,不可恢复!')) {
resetData();
document.getElementById('backup-modal').classList.add('hidden');
renderDashboard();
renderDiscussions();
renderCategories();
showToast('数据已重置', 'success');
}
});
// 添加内容块按钮
document.getElementById('add-content-block').addEventListener('click', () => {
document.getElementById('add-block-modal').classList.remove('hidden');
});
// 关闭内容块模态框
document.getElementById('close-modal-btn').addEventListener('click', () => {
document.getElementById('add-block-modal').classList.add('hidden');
});
// 添加内容块
document.querySelectorAll('.add-block-btn').forEach(btn => {
btn.addEventListener('click', () => {
const type = btn.dataset.type;
addContentBlock(type);
document.getElementById('add-block-modal').classList.add('hidden');
});
});
// 生成总结
document.getElementById('generate-summary-btn').addEventListener('click', generateSummary);
// 帮助按钮
document.getElementById('help-button').addEventListener('click', () => {
document.getElementById('help-modal').classList.remove('hidden');
// 更新价值维度统计
valueStats.learn++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
});
// 关闭帮助模态框
document.getElementById('close-help-modal').addEventListener('click', () => {
document.getElementById('help-modal').classList.add('hidden');
});
// 帮助标签页
document.querySelectorAll('.help-tab-btn').forEach(tab => {
tab.addEventListener('click', () => {
const tabId = tab.dataset.tab;
document.querySelectorAll('.help-tab-btn').forEach(t => {
t.classList.remove('text-primary', 'border-primary');
t.classList.add('text-gray-500', 'border-transparent');
});
document.querySelectorAll('.help-tab-content').forEach(content => {
content.classList.add('hidden');
});
tab.classList.remove('text-gray-500', 'border-transparent');
tab.classList.add('text-primary', 'border-primary');
document.getElementById(`${tabId}-tab`).classList.remove('hidden');
});
});
// 配置标签页
document.querySelectorAll('.config-tab-btn').forEach(tab => {
tab.addEventListener('click', () => {
const tabId = tab.dataset.tab;
document.querySelectorAll('.config-tab-btn').forEach(t => {
t.classList.remove('text-primary', 'border-primary');
t.classList.add('text-gray-500', 'border-transparent');
});
document.querySelectorAll('.config-tab-content').forEach(content => {
content.classList.add('hidden');
});
tab.classList.remove('text-gray-500', 'border-transparent');
tab.classList.add('text-primary', 'border-primary');
document.getElementById(`${tabId}-tab`).classList.remove('hidden');
});
});
// 添加新范畴
document.getElementById('add-new-category').addEventListener('click', () => {
document.getElementById('add-category-modal').classList.remove('hidden');
});
// 关闭范畴模态框
document.getElementById('cancel-category-btn').addEventListener('click', () => {
document.getElementById('add-category-modal').classList.add('hidden');
});
// 保存范畴
document.getElementById('save-category-btn').addEventListener('click', saveNewCategory);
// 选择颜色
document.querySelectorAll('.category-color-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.category-color-btn').forEach(b => {
b.classList.remove('border-primary');
});
btn.classList.add('border-primary');
});
});
// 添加标签
document.getElementById('add-tag-btn').addEventListener('click', () => {
const tagInput = document.getElementById('tag-input');
const tag = tagInput.value.trim();
if (tag) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
if (!discussion.tags) {
discussion.tags = [];
}
if (!discussion.tags.includes(tag)) {
discussion.tags.push(tag);
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
renderTags(discussion.tags);
}
tagInput.value = '';
}
}
});
// 富文本格式化
document.querySelectorAll('.format-btn').forEach(btn => {
btn.addEventListener('click', () => {
const command = btn.dataset.command;
document.execCommand(command, false, null);
// 更新价值维度统计
valueStats.save++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
});
});
// 搜索
document.getElementById('search-input').addEventListener('input', debounce(() => {
const searchTerm = document.getElementById('search-input').value.toLowerCase();
const discussions = getDiscussions();
const filteredDiscussions = discussions.filter(d =>
d.title.toLowerCase().includes(searchTerm) ||
d.subject.toLowerCase().includes(searchTerm) ||
d.topic.toLowerCase().includes(searchTerm) ||
(d.tags && d.tags.some(tag => tag.toLowerCase().includes(searchTerm)))
);
const discussionList = document.getElementById('discussion-list');
const emptyMsg = document.getElementById('empty-discussion-msg');
if (filteredDiscussions.length === 0) {
discussionList.innerHTML = '';
emptyMsg.classList.remove('hidden');
return;
}
emptyMsg.classList.add('hidden');
discussionList.innerHTML = '';
filteredDiscussions.forEach(discussion => {
const category = getCategories().find(c => c.id === discussion.category);
const item = document.createElement('div');
item.className = 'p-3 rounded-lg hover:bg-gray-100 cursor-pointer transition-all-300 border border-transparent hover:border-gray-200';
item.dataset.id = discussion.id;
item.innerHTML = `
<div class="flex items-start justify-between">
<div class="flex-1">
<h4 class="font-medium text-gray-800 truncate">${discussion.title}</h4>
<div class="flex items-center mt-1 text-xs text-gray-500">
<span class="inline-block w-2 h-2 rounded-full mr-1" style="background-color: ${category ? category.color : '#ccc'}"></span>
<span>${category ? category.name : '未分类'}</span>
<span class="mx-1">•</span>
<span>${discussion.subject}</span>
</div>
</div>
</div>
<div class="mt-2 text-xs text-gray-500">
<span>${formatDate(discussion.updatedAt)}</span>
</div>
`;
item.addEventListener('click', () => {
openDiscussion(discussion.id);
});
discussionList.appendChild(item);
});
}, 300));
// 分类关键词自动完成
document.getElementById('discussion-subject').addEventListener('input', debounce(() => {
const input = document.getElementById('discussion-subject');
const value = input.value.toLowerCase();
const suggestions = document.getElementById('subject-suggestions');
const subjects = getSubjects();
const filteredSubjects = subjects.filter(s => s.toLowerCase().includes(value));
if (filteredSubjects.length > 0 && value.length > 0) {
suggestions.innerHTML = filteredSubjects.map(s => `
<div class="p-2 hover:bg-gray-100 cursor-pointer subject-suggestion">${s}</div>
`).join('');
suggestions.classList.remove('hidden');
document.querySelectorAll('.subject-suggestion').forEach(suggestion => {
suggestion.addEventListener('click', () => {
input.value = suggestion.textContent;
suggestions.classList.add('hidden');
});
});
} else {
suggestions.classList.add('hidden');
}
}, 300));
// 点击其他地方关闭自动完成
document.addEventListener('click', (e) => {
if (!e.target.closest('#discussion-subject') && !e.target.closest('#subject-suggestions')) {
document.getElementById('subject-suggestions').classList.add('hidden');
}
});
// 代码定位
document.querySelectorAll('.code-location-btn').forEach(btn => {
btn.addEventListener('click', () => {
const location = btn.dataset.codeLocation || '未指定';
showCodeLocation(location);
});
});
// 关闭代码定位模态框
document.getElementById('close-code-modal-btn').addEventListener('click', () => {
document.getElementById('code-location-modal').classList.add('hidden');
});
document.getElementById('close-code-btn').addEventListener('click', () => {
document.getElementById('code-location-modal').classList.add('hidden');
});
// 复制代码
document.getElementById('copy-code-btn').addEventListener('click', () => {
const code = document.getElementById('code-snippet-container').textContent;
navigator.clipboard.writeText(code).then(() => {
showToast('代码已复制到剪贴板', 'success');
});
});
// 主题切换
document.getElementById('theme-toggle').addEventListener('click', toggleTheme);
// 自动保存讨论
const titleInput = document.getElementById('discussion-title');
const categorySelect = document.getElementById('discussion-category');
const subjectInput = document.getElementById('discussion-subject');
const topicInput = document.getElementById('discussion-topic');
[titleInput, categorySelect, subjectInput, topicInput].forEach(input => {
if (input) {
input.addEventListener('change', debounce(() => {
const id = document.getElementById('editor-view').dataset.id;
if (id) {
const discussion = getDiscussions().find(d => d.id === id);
if (discussion) {
discussion.title = titleInput.value;
discussion.category = categorySelect.value;
discussion.subject = subjectInput.value;
discussion.topic = topicInput.value;
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 更新价值维度统计
valueStats.safe++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
}
}
}, 1000));
}
});
}
// ==================== 数据备份与恢复 ====================
// 加载备份数据
function loadBackupData() {
const data = {
discussions: getDiscussions(),
categories: getCategories(),
subjects: getSubjects(),
prompts: getPrompts(),
stats: valueStats
};
const backupData = document.getElementById('backup-data');
backupData.innerHTML = `<pre><code>${JSON.stringify(data, null, 2)}</code></pre>`;
}
// 导出数据
function exportData() {
const data = {
discussions: getDiscussions(),
categories: getCategories(),
subjects: getSubjects(),
prompts: getPrompts(),
stats: valueStats,
groupHierarchy: getData(STORAGE_KEYS.GROUP_HIERARCHY),
directDimension: getData(STORAGE_KEYS.DIRECT_DIMENSION),
indexTable: getData(STORAGE_KEYS.INDEX_TABLE),
exportDate: new Date().toISOString()
};
const dataStr = JSON.stringify(data, null, 2);
const dataBlob = new Blob([dataStr], { type: 'application/json' });
const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = `discussMemo_backup_${new Date().toISOString().split('T')[0]}.json`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
showToast('数据已导出', 'success');
}
// 导入数据
function importData(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
try {
const data = JSON.parse(e.target.result);
if (confirm('确定要导入数据吗?这将覆盖当前数据!')) {
// 导入数据
if (data.discussions) saveData(STORAGE_KEYS.DISCUSSIONS, data.discussions);
if (data.categories) saveData(STORAGE_KEYS.CATEGORIES, data.categories);
if (data.subjects) saveData(STORAGE_KEYS.SUBJECTS, data.subjects);
if (data.prompts) saveData(STORAGE_KEYS.PROMPTS, data.prompts);
if (data.stats) valueStats = data.stats;
if (data.groupHierarchy) saveData(STORAGE_KEYS.GROUP_HIERARCHY, data.groupHierarchy);
if (data.directDimension) saveData(STORAGE_KEYS.DIRECT_DIMENSION, data.directDimension);
if (data.indexTable) saveData(STORAGE_KEYS.INDEX_TABLE, data.indexTable);
// 更新统计
saveData(STORAGE_KEYS.STATS, valueStats);
// 重新渲染
renderDashboard();
renderDiscussions();
renderCategories();
loadBackupData();
showToast('数据已导入', 'success');
}
} catch (error) {
console.error('导入数据失败:', error);
showToast('导入数据失败,请检查文件格式', 'error');
}
};
reader.readAsText(file);
}
// 重置数据
function resetData() {
localStorage.removeItem(STORAGE_KEYS.DISCUSSIONS);
localStorage.removeItem(STORAGE_KEYS.CATEGORIES);
localStorage.removeItem(STORAGE_KEYS.SUBJECTS);
localStorage.removeItem(STORAGE_KEYS.PROMPTS);
localStorage.removeItem(STORAGE_KEYS.STATS);
localStorage.removeItem(STORAGE_KEYS.GROUP_HIERARCHY);
localStorage.removeItem(STORAGE_KEYS.DIRECT_DIMENSION);
localStorage.removeItem(STORAGE_KEYS.INDEX_TABLE);
// 重新初始化
initializeDataTables();
valueStats = { learn: 0, save: 0, safe: 0 };
saveData(STORAGE_KEYS.STATS, valueStats);
}
// ==================== 配置管理 ====================
// 渲染配置视图
function renderConfigView() {
renderCustomCategories();
renderCustomSubjects();
renderCustomPrompts();
}
// 渲染自定义范畴
function renderCustomCategories() {
const categories = getCategories();
const container = document.getElementById('custom-categories-list');
container.innerHTML = '';
categories.forEach(category => {
const item = document.createElement('div');
item.className = 'p-4 border border-gray-200 rounded-lg';
item.innerHTML = `
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="w-4 h-4 rounded-full mr-2" style="background-color: ${category.color}"></div>
<h4 class="font-medium text-gray-800">${category.name}</h4>
<span class="ml-2 adapt-tag adapt-${category.dimension}">${category.dimension === 'universal' ? '万向' : category.dimension === 'industry' ? '千行' : '百业'}</span>
</div>
<div class="flex space-x-2">
<button class="text-gray-400 hover:text-gray-600 edit-category" data-id="${category.id}">
<i class="fa fa-pencil"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 delete-category" data-id="${category.id}">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
${category.description ? `
<div class="mt-2 text-sm text-gray-600">
<p>${category.description}</p>
</div>
` : ''}
`;
container.appendChild(item);
});
// 添加删除事件
document.querySelectorAll('.delete-category').forEach(btn => {
btn.addEventListener('click', () => {
const id = btn.dataset.id;
if (confirm('确定要删除这个范畴吗?')) {
deleteCategory(id);
renderCustomCategories();
renderCategories();
renderDiscussions();
showToast('范畴已删除', 'success');
}
});
});
}
// 渲染自定义分类关键词
function renderCustomSubjects() {
const subjects = getSubjects();
const container = document.getElementById('custom-subjects-list');
container.innerHTML = '';
subjects.forEach((subject, index) => {
const item = document.createElement('div');
item.className = 'p-3 border border-gray-200 rounded-lg flex items-center justify-between';
item.innerHTML = `
<span class="text-gray-800">${subject}</span>
<button class="text-gray-400 hover:text-gray-600 delete-subject" data-index="${index}">
<i class="fa fa-trash-o"></i>
</button>
`;
container.appendChild(item);
});
// 添加删除事件
document.querySelectorAll('.delete-subject').forEach(btn => {
btn.addEventListener('click', () => {
const index = parseInt(btn.dataset.index);
const subjects = getSubjects();
subjects.splice(index, 1);
saveSubjects(subjects);
renderCustomSubjects();
showToast('关键词已删除', 'success');
});
});
}
// 渲染自定义提示词模板
function renderCustomPrompts() {
const prompts = getPrompts();
const container = document.getElementById('custom-prompts-list');
container.innerHTML = '';
prompts.forEach(prompt => {
const item = document.createElement('div');
item.className = 'p-4 border border-gray-200 rounded-lg';
item.innerHTML = `
<div class="flex items-center justify-between">
<h4 class="font-medium text-gray-800">${prompt.title}</h4>
<div class="flex space-x-2">
<button class="text-gray-400 hover:text-gray-600 edit-prompt-config" data-id="${prompt.id}">
<i class="fa fa-pencil"></i>
</button>
<button class="text-gray-400 hover:text-gray-600 delete-prompt-config" data-id="${prompt.id}">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
<div class="mt-2 text-sm text-gray-600">
<p>${prompt.content.replace(/\n/g, ' ').replace(/##/g, '').trim().substring(0, 100)}${prompt.content.length > 100 ? '...' : ''}</p>
</div>
${prompt.tags ? `
<div class="mt-2">
${prompt.tags.map(tag => `<span class="inline-block bg-gray-100 rounded-full px-2 py-0.5 text-xs mr-1">${tag}</span>`).join('')}
</div>
` : ''}
`;
container.appendChild(item);
});
// 添加删除事件
document.querySelectorAll('.delete-prompt-config').forEach(btn => {
btn.addEventListener('click', () => {
const id = btn.dataset.id;
if (confirm('确定要删除这个提示词模板吗?')) {
deletePrompt(id);
renderCustomPrompts();
renderPrompts();
showToast('提示词模板已删除', 'success');
}
});
});
}
// 保存新范畴
function saveNewCategory() {
const name = document.getElementById('category-name-input').value.trim();
const description = document.getElementById('category-desc-input').value.trim();
const dimension = document.querySelector('input[name="adapt-dimension"]:checked').value;
const colorBtn = document.querySelector('.category-color-btn.border-primary');
const color = colorBtn ? colorBtn.dataset.color : '#3b82f6';
if (!name) {
showToast('请输入范畴名称', 'error');
return;
}
const category = {
id: generateId(),
name,
description,
dimension,
color
};
saveCategory(category);
renderCustomCategories();
renderCategories();
document.getElementById('add-category-modal').classList.add('hidden');
showToast('范畴已添加', 'success');
// 清空表单
document.getElementById('category-name-input').value = '';
document.getElementById('category-desc-input').value = '';
document.querySelector('input[name="adapt-dimension"][value="universal"]').checked = true;
document.querySelectorAll('.category-color-btn').forEach(btn => {
btn.classList.remove('border-primary');
});
document.querySelector('.category-color-btn[data-color="#3b82f6"]').classList.add('border-primary');
}
// 添加内容块
function addContentBlock(type) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (!discussion) return;
let block = {
id: generateId(),
type,
order: discussion.contentBlocks.length
};
switch (type) {
case 'text':
block.content = '';
break;
case 'timeline':
block.items = [];
break;
case 'decision':
block.content = '';
block.status = 'pending';
break;
case 'todo':
block.items = [];
break;
}
discussion.contentBlocks.push(block);
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 重新渲染
renderContentBlocks(discussion.contentBlocks);
// 更新价值维度统计
valueStats.save++;
saveData(STORAGE_KEYS.STATS, valueStats);
updateStats();
}
// 显示代码位置
function showCodeLocation(location) {
const modal = document.getElementById('code-location-modal');
const title = document.getElementById('code-location-title');
const snippet = document.getElementById('code-snippet-container');
title.textContent = `功能模块:${location}`;
// 根据位置生成示例代码
let codeSnippet = '';
switch (location) {
case '仪表盘渲染 - JS第1850行':
codeSnippet = `// 渲染仪表盘
function renderDashboard() {
// 更新统计数据
updateStats();
// 渲染分类分布图表
renderCategoryChart();
// 渲染最近讨论
renderRecentDiscussions();
// 渲染提示词导航
renderPrompts();
}`;
break;
case '搜索功能 - JS第1500行':
codeSnippet = `// 搜索功能
document.getElementById('search-input').addEventListener('input', debounce(() => {
const searchTerm = document.getElementById('search-input').value.toLowerCase();
const discussions = getDiscussions();
const filteredDiscussions = discussions.filter(d =>
d.title.toLowerCase().includes(searchTerm) ||
d.subject.toLowerCase().includes(searchTerm) ||
d.topic.toLowerCase().includes(searchTerm) ||
(d.tags && d.tags.some(tag => tag.toLowerCase().includes(searchTerm)))
);
// 渲染过滤后的讨论列表
renderFilteredDiscussions(filteredDiscussions);
}, 300));`;
break;
case '内容块功能 - JS第1300行':
codeSnippet = `// 添加内容块
function addContentBlock(type) {
const id = document.getElementById('editor-view').dataset.id;
const discussion = getDiscussions().find(d => d.id === id);
if (!discussion) return;
let block = {
id: generateId(),
type,
order: discussion.contentBlocks.length
};
switch (type) {
case 'text':
block.content = '';
break;
case 'timeline':
block.items = [];
break;
case 'decision':
block.content = '';
block.status = 'pending';
break;
case 'todo':
block.items = [];
break;
}
discussion.contentBlocks.push(block);
discussion.updatedAt = new Date().toISOString();
saveDiscussion(discussion);
// 重新渲染
renderContentBlocks(discussion.contentBlocks);
}`;
break;
default:
codeSnippet = `// ${location}
// 这里是相关功能的实现代码
// 由于代码量较大,仅展示关键部分
// 完整代码请查看对应文件`;
}
snippet.innerHTML = `<pre><code>${codeSnippet}</code></pre>`;
modal.classList.remove('hidden');
}
// 切换主题
function toggleTheme() {
const body = document.body;
const icon = document.getElementById('theme-toggle').querySelector('i');
if (body.classList.contains('dark')) {
body.classList.remove('dark');
icon.classList.remove('fa-sun-o');
icon.classList.add('fa-moon-o');
localStorage.setItem(STORAGE_KEYS.THEME, 'light');
} else {
body.classList.add('dark');
icon.classList.remove('fa-moon-o');
icon.classList.add('fa-sun-o');
localStorage.setItem(STORAGE_KEYS.THEME, 'dark');
}
}
// ==================== 初始化 ====================
// 初始化应用
function initializeApp() {
// 初始化基础表和结合表
if (!getData(STORAGE_KEYS.GROUP_HIERARCHY)) {
initializeDataTables();
}
// 加载统计数据
const stats = getData(STORAGE_KEYS.STATS);
if (stats) {
valueStats = stats;
}
// 加载主题
const theme = localStorage.getItem(STORAGE_KEYS.THEME);
if (theme === 'dark') {
document.body.classList.add('dark');
document.getElementById('theme-toggle').querySelector('i').classList.remove('fa-moon-o');
document.getElementById('theme-toggle').querySelector('i').classList.add('fa-sun-o');
}
// 渲染分类
renderCategories();
// 渲染讨论列表
renderDiscussions();
// 渲染仪表盘
renderDashboard();
// 初始化表述处理功能
initializeExpressionProcessor();
// 初始化事件监听
initializeEventListeners();
// 显示欢迎视图
document.getElementById('welcome-view').classList.remove('hidden');
}
// ==================== 表述处理模块 ====================
// 表述处理数据存储键
const EXPRESSION_KEYS = {
RAW_EXPRESSIONS: 'discussMemo_rawExpressions',
ANALYSIS_RESULTS: 'discussMemo_analysisResults',
EXPRESSION_HISTORY: 'discussMemo_expressionHistory'
};
// 初始化表述处理器
function initializeExpressionProcessor() {
console.log('初始化表述处理系统...');
// 加载历史记录
loadExpressionHistory();
// 绑定事件监听器
bindExpressionEventListeners();
}
// 绑定表述处理相关事件
function bindExpressionEventListeners() {
// 运行分析按钮
document.getElementById('run-expression-analysis')?.addEventListener('click', runExpressionAnalysis);
// 加载示例按钮
document.getElementById('load-example-btn')?.addEventListener('click', loadExampleExpression);
// 保存表述按钮
document.getElementById('save-expression-btn')?.addEventListener('click', saveRawExpression);
// 原始表述输入监听
document.getElementById('raw-expression-input')?.addEventListener('input', updateColumnPreview);
}
// 加载示例表述
function loadExampleExpression() {
const exampleExpression = `内嵌式赋能/外挂式省力/中蕴式省心 学习/节约/安全 万向/千行/百业 通/性/量 通/别/藏 境/行/果 顿/渐/密`;
document.getElementById('raw-expression-input').value = exampleExpression;
updateColumnPreview();
showToast('已加载示例表述', 'success');
}
// 更新7列结构预览
function updateColumnPreview() {
const input = document.getElementById('raw-expression-input').value.trim();
const preview = document.getElementById('column-preview');
if (!input) {
preview.innerHTML = `
<div class="text-center text-gray-500 py-8">
<i class="fa fa-eye text-2xl mb-2"></i>
<p>输入原始表述后将显示结构预览</p>
</div>`;
return;
}
const lines = input.split('\n');
if (lines.length !== 3) {
preview.innerHTML = `
<div class="text-center text-red-500 py-8">
<i class="fa fa-exclamation-triangle text-2xl mb-2"></i>
<p>需要输入3行数据,当前${lines.length}行</p>
</div>`;
return;
}
// 解析7列数据
const columns = extractColumns(lines);
let html = '<div class="space-y-2">';
for (let i = 0; i < 7; i++) {
const columnName = getColumnName(i);
const columnData = columns[i];
html += `
<div class="flex items-center space-x-2 p-2 bg-white rounded border">
<div class="w-16 text-xs font-medium text-gray-600">${columnName}</div>
<div class="flex-1 text-sm font-mono">${columnData || '-'}</div>
</div>`;
}
html += '</div>';
preview.innerHTML = html;
}
// 提取7列数据
function extractColumns(lines) {
const columns = [];
// 第1行:3列词组
const line1Items = lines[0].split(' ');
columns[0] = line1Items[0] || '';
columns[1] = line1Items[1] || '';
columns[2] = line1Items[2] || '';
// 第2行:4列词组
const line2Items = lines[1].split(' ');
columns[3] = line2Items[0] || '';
columns[4] = line2Items[1] || '';
columns[5] = line2Items[2] || '';
columns[6] = line2Items[3] || '';
return columns;
}
// 获取列名称
function getColumnName(index) {
const names = ['第1列', '第2列', '第3列', '第4列', '第5列', '第6列', '第7列'];
return names[index];
}
// 运行表述分析
async function runExpressionAnalysis() {
const input = document.getElementById('raw-expression-input').value.trim();
if (!input) {
showToast('请输入原始表述', 'warning');
return;
}
showToast('正在分析表述...', 'info');
try {
// 调用Python分析程序(这里先模拟结果)
const analysisResult = await simulateExpressionAnalysis(input);
// 显示分析结果
displayAnalysisResults(analysisResult);
// 保存分析结果
saveAnalysisResult(analysisResult);
showToast('分析完成!', 'success');
} catch (error) {
console.error('分析失败:', error);
showToast('分析失败,请检查输入格式', 'error');
}
}
// 模拟表述分析(后续可替换为真实Python调用)
async function simulateExpressionAnalysis(input) {
// 模拟处理时间
await new Promise(resolve => setTimeout(resolve, 1000));
const lines = input.split('\n');
const columns = extractColumns(lines);
return {
input: input,
columns: columns,
timestamp: new Date().toISOString(),
results: {
ternary: {
name: '三元组(立名)',
columns: [
{ index: 0, content: columns[0], operation: '外立"服务"之名' },
{ index: 1, content: columns[1], operation: '内立"管理"之名' },
{ index: 2, content: columns[2], operation: '中立"组织"之名' }
]
},
trichotomy: {
name: '三分法(立法)',
columns: [
{ index: 3, content: columns[3], operation: '加成"器"' },
{ index: 6, content: columns[6], operation: '减成"唯识论"' }
]
},
trinity: {
name: '三位一体(立向)',
columns: [
{ index: 4, content: columns[4], operation: '反破"圆"' },
{ index: 5, content: columns[5], operation: '正破"不定"' }
]
}
},
validation: {
structureValid: lines.length === 3,
columnsComplete: columns.filter(c => c).length === 7,
exclusivityValid: true, // 模拟验证通过
completeness: '85%'
}
};
}
// 显示分析结果
function displayAnalysisResults(result) {
// 显示三元组结果
const ternaryDiv = document.getElementById('ternary-results');
ternaryDiv.innerHTML = result.results.ternary.columns.map(col => `
<div class="p-2 bg-blue-50 rounded border-l-2 border-blue-400">
<div class="font-medium text-blue-800">第${col.index + 1}列</div>
<div class="text-sm text-gray-700">${col.content}</div>
<div class="text-xs text-blue-600 mt-1">${col.operation}</div>
</div>
`).join('');
// 显示三分法结果
const trichotomyDiv = document.getElementById('trichotomy-results');
trichotomyDiv.innerHTML = result.results.trichotomy.columns.map(col => `
<div class="p-2 bg-purple-50 rounded border-l-2 border-purple-400">
<div class="font-medium text-purple-800">第${col.index + 1}列</div>
<div class="text-sm text-gray-700">${col.content}</div>
<div class="text-xs text-purple-600 mt-1">${col.operation}</div>
</div>
`).join('');
// 显示三位一体结果
const trinityDiv = document.getElementById('trinity-results');
trinityDiv.innerHTML = result.results.trinity.columns.map(col => `
<div class="p-2 bg-green-50 rounded border-l-2 border-green-400">
<div class="font-medium text-green-800">第${col.index + 1}列</div>
<div class="text-sm text-gray-700">${col.content}</div>
<div class="text-xs text-green-600 mt-1">${col.operation}</div>
</div>
`).join('');
// 显示验证报告
const validationDiv = document.getElementById('validation-report');
validationDiv.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="flex items-center space-x-2">
<i class="fa ${result.validation.structureValid ? 'fa-check-circle text-green-500' : 'fa-exclamation-circle text-red-500'}"></i>
<span>结构验证:${result.validation.structureValid ? '通过' : '失败'}</span>
</div>
<div class="flex items-center space-x-2">
<i class="fa ${result.validation.columnsComplete ? 'fa-check-circle text-green-500' : 'fa-exclamation-circle text-red-500'}"></i>
<span>列完整性:${result.validation.columnsComplete ? '通过' : '失败'}</span>
</div>
<div class="flex items-center space-x-2">
<i class="fa ${result.validation.exclusivityValid ? 'fa-check-circle text-green-500' : 'fa-exclamation-circle text-red-500'}"></i>
<span>排他性验证:${result.validation.exclusivityValid ? '通过' : '失败'}</span>
</div>
<div class="flex items-center space-x-2">
<i class="fa fa-info-circle text-blue-500"></i>
<span>完整度:${result.validation.completeness}</span>
</div>
</div>
<div class="mt-3 p-3 bg-gray-50 rounded">
<div class="text-sm font-medium text-gray-700 mb-1">分析时间</div>
<div class="text-xs text-gray-600">${new Date(result.timestamp).toLocaleString()}</div>
</div>
`;
}
// 保存原始表述
function saveRawExpression() {
const input = document.getElementById('raw-expression-input').value.trim();
if (!input) {
showToast('请输入原始表述', 'warning');
return;
}
const expressions = JSON.parse(localStorage.getItem(EXPRESSION_KEYS.RAW_EXPRESSIONS) || '[]');
expressions.push({
id: generateId(),
content: input,
timestamp: new Date().toISOString()
});
localStorage.setItem(EXPRESSION_KEYS.RAW_EXPRESSIONS, JSON.stringify(expressions));
showToast('表述已保存', 'success');
}
// 保存分析结果
function saveAnalysisResult(result) {
const results = JSON.parse(localStorage.getItem(EXPRESSION_KEYS.ANALYSIS_RESULTS) || '[]');
results.unshift(result); // 添加到开头
// 最多保存20个结果
if (results.length > 20) {
results.splice(20);
}
localStorage.setItem(EXPRESSION_KEYS.ANALYSIS_RESULTS, JSON.stringify(results));
// 更新历史记录显示
loadExpressionHistory();
}
// 加载历史记录
function loadExpressionHistory() {
const historyDiv = document.getElementById('expression-history');
const results = JSON.parse(localStorage.getItem(EXPRESSION_KEYS.ANALYSIS_RESULTS) || '[]');
if (results.length === 0) {
historyDiv.innerHTML = `
<div class="text-center text-gray-500 py-4">
<i class="fa fa-inbox text-xl mb-2"></i>
<p class="text-sm">暂无历史记录</p>
</div>`;
return;
}
historyDiv.innerHTML = results.slice(0, 5).map((result, index) => `
<div class="flex items-center justify-between p-3 bg-gray-50 rounded hover:bg-gray-100 transition-colors cursor-pointer"
onclick="loadHistoryResult(${index})">
<div class="flex-1">
<div class="text-sm font-medium text-gray-800">分析记录 #${index + 1}</div>
<div class="text-xs text-gray-600">${new Date(result.timestamp).toLocaleString()}</div>
</div>
<div class="text-xs bg-universal text-white px-2 py-1 rounded">
完整度: ${result.validation.completeness}
</div>
</div>
`).join('');
}
// 加载历史结果
window.loadHistoryResult = function(index) {
const results = JSON.parse(localStorage.getItem(EXPRESSION_KEYS.ANALYSIS_RESULTS) || '[]');
const result = results[index];
if (result) {
document.getElementById('raw-expression-input').value = result.input;
updateColumnPreview();
displayAnalysisResults(result);
// 切换到表述处理标签页
showTab('expression');
showToast('已加载历史分析结果', 'success');
}
};
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', initializeApp);
</script>
</body>
</html>