XinXiKuaiBaoYuan/信息情报员.html

6054 lines
385 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>信息快报员</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#f5f3ff',
100: '#ede9fe',
200: '#ddd6fe',
300: '#c4b5fd',
400: '#a78bfa',
500: '#8b5cf6',
600: '#660874',
700: '#5b21b6',
800: '#4c1d95',
900: '#3c1a7a',
}
}
}
}
}
</script>
<style>
.sidebar-item {
@apply flex items-center gap-3 px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer;
display: flex !important;
align-items: center !important;
}
.sidebar-item.active {
@apply bg-primary-600 text-white;
}
.sidebar-item.active svg {
@apply text-white;
}
.sidebar-collapsed {
@apply w-14;
}
.sidebar-collapsed .sidebar-text {
display: none;
}
.sidebar-collapsed .main-content {
margin-left: 3.5rem;
}
.sidebar-toggle {
@apply p-1 rounded hover:bg-gray-100 transition-colors;
}
/* 侧边栏滚动条样式 */
#sidebar::-webkit-scrollbar {
width: 6px;
}
#sidebar::-webkit-scrollbar-track {
background: transparent;
}
#sidebar::-webkit-scrollbar-thumb {
background: rgba(156, 163, 175, 0.2);
border-radius: 3px;
}
#sidebar::-webkit-scrollbar-thumb:hover {
background: rgba(156, 163, 175, 0.4);
}
/* 历史对话区域滚动条样式 */
#recent-chats::-webkit-scrollbar {
width: 4px;
}
#recent-chats::-webkit-scrollbar-track {
background: transparent;
}
#recent-chats::-webkit-scrollbar-thumb {
background: rgba(156, 163, 175, 0.2);
border-radius: 2px;
}
#recent-chats::-webkit-scrollbar-thumb:hover {
background: rgba(156, 163, 175, 0.4);
}
#recent-chats::-webkit-scrollbar-button {
display: none;
}
/* Firefox滚动条样式 */
#sidebar {
scrollbar-width: thin;
scrollbar-color: rgba(156, 163, 175, 0.2) transparent;
}
#recent-chats {
scrollbar-width: thin;
scrollbar-color: rgba(156, 163, 175, 0.2) transparent;
}
/* 移动端侧边栏 */
@media (max-width: 1023px) {
#sidebar {
transform: translateX(-100%);
transition: transform 0.3s ease-in-out;
}
#sidebar.show {
transform: translateX(0);
}
}
/* 报告查看器动画效果 */
.report-card-transitioning {
transform: scale(0.8);
opacity: 0.7;
transition: all 0.3s ease-in-out;
}
/* 报告卡片向左收缩动画 */
.report-cards-shrinking {
animation: shrinkToLeft 0.6s ease-in-out forwards;
}
@keyframes shrinkToLeft {
0% {
transform: translateX(0) scale(1);
opacity: 1;
}
50% {
transform: translateX(-100px) scale(0.7);
opacity: 0.5;
}
100% {
transform: translateX(-300px) scale(0.4);
opacity: 0;
}
}
/* 报告查看器从右侧滑入 */
.report-viewer-entering {
transform: translateX(100%);
opacity: 0;
animation: slideInFromRight 0.6s ease-out forwards;
animation-delay: 0.3s;
}
@keyframes slideInFromRight {
to {
transform: translateX(0);
opacity: 1;
}
}
/* 左侧报告列表项逐个出现 */
.report-list-item-morphing {
transform: translateX(-50px) scale(0.8);
opacity: 0;
animation: morphIntoList 0.5s ease-out forwards;
}
/* 精确隐藏残留的重复报告卡片 */
.report-card:not(#reports-content .report-card):not(#unified-report-view .report-card) {
display: none !important;
}
/* 报告查看器转换动画 */
.report-viewer-container {
transition: all 0.5s ease-in-out;
}
.report-viewer-list-mode {
display: block;
}
.report-viewer-sidebar-mode {
display: flex;
height: 600px;
}
.report-sidebar {
width: 300px;
background: #f8fafc;
border-right: 1px solid #e2e8f0;
display: flex;
flex-direction: column;
}
.report-sidebar-header {
padding: 1rem;
border-bottom: 1px solid #e2e8f0;
background: #f8fafc;
flex-shrink: 0;
}
.report-sidebar-content {
flex: 1;
padding: 1rem;
overflow-y: auto;
}
.report-content {
flex: 1;
padding: 1.5rem;
overflow-y: auto;
background: white;
}
.report-list-item-compact {
padding: 0.75rem;
margin-bottom: 0.5rem;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.2s ease;
border: 1px solid transparent;
}
.report-list-item-compact:hover {
background: white;
border-color: #e2e8f0;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.report-list-item-compact.active {
background: #3b82f6;
color: white;
border-color: #2563eb;
}
.report-list-item-compact.active h4 {
color: white;
}
.report-list-item-compact.active .text-gray-500 {
color: #e2e8f0;
}
/* 卡片收缩动画 */
.report-card-shrinking {
transform: scale(0.95);
opacity: 0.7;
transition: all 0.3s ease;
}
/* 侧边栏项目出现动画 */
.sidebar-item-appearing {
transform: translateX(-20px);
opacity: 0;
animation: slideInFromLeft 0.4s ease forwards;
}
@keyframes slideInFromLeft {
to {
transform: translateX(0);
opacity: 1;
}
}
/* 任务侧边栏模式样式 */
.task-viewer-container {
transition: all 0.5s ease-in-out;
}
.task-viewer-list-mode {
display: block;
}
.task-viewer-sidebar-mode {
display: flex;
height: 600px;
}
.task-sidebar {
width: 300px;
background: #f8fafc;
border-right: 1px solid #e2e8f0;
display: flex;
flex-direction: column;
}
.task-sidebar-header {
padding: 1rem;
border-bottom: 1px solid #e2e8f0;
background: #f8fafc;
flex-shrink: 0;
}
.task-sidebar-content {
flex: 1;
padding: 1rem;
overflow-y: auto;
}
.task-content {
flex: 1;
padding: 1.5rem;
overflow-y: auto;
background: white;
}
.task-list-item-compact {
padding: 0.75rem;
margin-bottom: 0.5rem;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.2s ease;
border: 1px solid transparent;
}
.task-list-item-compact:hover {
background: white;
border-color: #e2e8f0;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.task-list-item-compact.active {
background: #3b82f6;
color: white;
border-color: #2563eb;
}
.task-list-item-compact.active h4 {
color: white;
}
.task-list-item-compact.active .text-gray-500 {
color: #e2e8f0;
}
.task-card-shrinking {
transform: scale(0.95);
opacity: 0.7;
transition: all 0.3s ease;
}
.task-sidebar-item-appearing {
transform: translateX(-20px);
opacity: 0;
animation: slideInFromLeft 0.4s ease forwards;
}
/* 对话消息样式 */
.message-item {
margin-bottom: 1rem;
padding: 1rem;
border-radius: 0.75rem;
background: #f8fafc;
border-left: 4px solid #3b82f6;
}
.message-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.message-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: #3b82f6;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 0.875rem;
font-weight: 600;
}
.message-meta {
flex: 1;
}
.message-title {
font-weight: 600;
color: #1f2937;
font-size: 0.875rem;
}
.message-time {
font-size: 0.75rem;
color: #6b7280;
}
.message-content {
color: #374151;
line-height: 1.5;
font-size: 0.875rem;
}
/* 报告抽屉样式 */
.report-drawer {
position: fixed;
top: 0;
right: -500px;
width: 500px;
height: 100vh;
background: white;
box-shadow: -4px 0 20px rgba(0, 0, 0, 0.1);
transition: right 0.3s ease-in-out;
z-index: 1000;
display: flex;
flex-direction: column;
}
.report-drawer.open {
right: 0;
}
.report-drawer-header {
padding: 1.5rem;
border-bottom: 1px solid #e5e7eb;
background: #f9fafb;
}
.report-drawer-content {
flex: 1;
padding: 1.5rem;
overflow-y: auto;
}
.report-drawer-footer {
padding: 1rem 1.5rem;
border-top: 1px solid #e5e7eb;
background: #f9fafb;
display: flex;
gap: 0.75rem;
}
.drawer-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease-in-out;
}
.drawer-overlay.show {
opacity: 1;
visibility: visible;
}
.message-item {
cursor: pointer;
transition: all 0.2s ease;
}
.message-item:hover {
background: #f1f5f9;
border-left-color: #2563eb;
}
@keyframes morphIntoList {
0% {
transform: translateX(-50px) scale(0.8);
opacity: 0;
}
100% {
transform: translateX(0) scale(1);
opacity: 1;
}
}
/* 报告查看器响应式布局 */
@media (max-width: 1024px) {
#unified-report-view {
left: 0;
}
}
</style>
</head>
<body class="bg-gray-50">
<div class="flex h-screen">
<!-- 侧边栏 -->
<div id="sidebar" class="w-56 bg-white shadow-sm border-r border-gray-200 flex flex-col transition-all duration-300 lg:translate-x-0 overflow-y-auto relative z-30">
<!-- Logo区域 -->
<div class="p-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="w-8 h-8 bg-primary-600 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-white" viewBox="0 0 74 80" xmlns="http://www.w3.org/2000/svg">
<path d="M 17.00 60.50 L 16.00 60.50 L 15.00 60.50 L 14.50 60.00 L 14.00 59.50 L 13.50 59.00 L 13.50 58.00 L 13.50 57.00 L 13.50 56.00 L 13.50 55.00 L 13.50 54.00 L 13.50 53.00 L 13.50 52.00 L 13.50 51.00 L 13.50 50.00 L 13.50 49.00 L 13.50 48.00 L 13.50 47.00 L 13.50 46.00 L 13.50 45.00 L 13.50 44.00 L 13.50 43.00 L 13.50 42.00 L 13.50 41.00 L 13.50 40.00 L 13.50 39.00 L 13.50 38.00 L 13.50 37.00 L 13.50 36.00 L 13.50 35.00 L 13.50 34.00 L 13.50 33.00 L 13.50 32.00 L 13.50 31.00 L 14.00 30.50 L 14.50 30.00 L 15.00 29.50 L 15.50 29.00 L 16.00 28.50 L 17.00 28.50 L 17.50 28.00 L 18.00 27.50 L 19.00 27.50 L 19.50 27.00 L 20.00 26.50 L 20.50 26.00 L 21.00 25.50 L 22.00 25.50 L 22.50 25.00 L 23.00 24.50 L 24.00 24.50 L 24.50 24.00 L 25.00 23.50 L 26.00 23.50 L 26.50 23.00 L 27.00 22.50 L 28.00 22.50 L 28.50 22.00 L 29.00 21.50 L 29.50 21.00 L 30.00 20.50 L 31.00 20.50 L 31.50 20.00 L 32.00 19.50 L 33.00 19.50 L 33.50 19.00 L 34.00 18.50 L 34.50 18.00 L 35.00 17.50 L 36.00 17.50 L 36.50 17.00 L 37.00 16.50 L 38.00 16.50 L 39.00 16.50 L 40.00 16.50 L 41.00 16.50 L 41.50 17.00 L 42.00 17.50 L 42.50 18.00 L 42.50 19.00 L 42.50 20.00 L 42.00 20.50 L 41.50 21.00 L 41.00 21.50 L 40.00 21.50 L 39.50 22.00 L 39.00 22.50 L 38.00 22.50 L 37.50 23.00 L 37.00 23.50 L 36.00 23.50 L 35.50 24.00 L 35.00 24.50 L 34.50 25.00 L 34.00 25.50 L 33.00 25.50 L 32.50 26.00 L 32.00 26.50 L 31.00 26.50 L 30.50 27.00 L 30.00 27.50 L 29.00 27.50 L 28.50 28.00 L 28.00 28.50 L 27.00 28.50 L 26.50 29.00 L 26.00 29.50 L 25.50 30.00 L 25.00 30.50 L 24.00 30.50 L 23.50 31.00 L 23.00 31.50 L 22.00 31.50 L 21.50 32.00 L 21.50 33.00 L 21.50 34.00 L 21.50 35.00 L 21.50 36.00 L 21.50 37.00 L 21.50 38.00 L 21.50 39.00 L 21.50 40.00 L 21.50 41.00 L 21.50 42.00 L 21.50 43.00 L 21.50 44.00 L 21.50 45.00 L 21.50 46.00 L 21.50 47.00 L 21.50 48.00 L 21.00 48.50 L 20.50 49.00 L 20.50 50.00 L 20.50 51.00 L 20.50 52.00 L 21.00 52.50 L 21.50 53.00 L 22.00 53.50 L 23.00 53.50 L 23.50 53.00 L 24.00 52.50 L 24.50 52.00 L 25.00 51.50 L 25.50 51.00 L 25.50 50.00 L 25.50 49.00 L 25.00 48.50 L 24.50 48.00 L 24.50 47.00 L 24.50 46.00 L 24.50 45.00 L 24.50 44.00 L 24.50 43.00 L 24.50 42.00 L 24.50 41.00 L 24.50 40.00 L 24.50 39.00 L 24.50 38.00 L 24.50 37.00 L 24.50 36.00 L 24.50 35.00 L 24.50 34.00 L 24.50 33.00 L 25.00 32.50 L 26.00 32.50 L 26.50 32.00 L 27.00 31.50 L 28.00 31.50 L 28.50 31.00 L 29.00 30.50 L 30.00 30.50 L 30.50 30.00 L 31.00 29.50 L 32.00 29.50 L 32.50 29.00 L 33.00 28.50 L 34.00 28.50 L 34.50 28.00 L 35.00 27.50 L 35.50 27.00 L 36.00 26.50 L 37.00 26.50 L 37.50 26.00 L 38.00 25.50 L 39.00 25.50 L 39.50 25.00 L 40.00 24.50 L 41.00 24.50 L 41.50 24.00 L 42.00 23.50 L 42.50 23.00 L 43.00 22.50 L 44.00 22.50 L 44.50 22.00 L 45.00 21.50 L 46.00 21.50 L 46.50 21.00 L 47.00 20.50 L 48.00 20.50 L 48.50 21.00 L 49.00 21.50 L 49.50 22.00 L 50.00 22.50 L 50.50 23.00 L 50.50 24.00 L 50.00 24.50 L 49.00 24.50 L 48.50 25.00 L 48.00 25.50 L 47.00 25.50 L 46.50 26.00 L 46.00 26.50 L 45.50 27.00 L 45.00 27.50 L 44.00 27.50 L 43.50 28.00 L 43.00 28.50 L 42.00 28.50 L 41.50 29.00 L 41.00 29.50 L 40.00 29.50 L 39.50 30.00 L 39.00 30.50 L 38.50 31.00 L 38.00 31.50 L 37.00 31.50 L 36.50 32.00 L 36.00 32.50 L 35.00 32.50 L 34.50 33.00 L 34.00 33.50 L 33.50 34.00 L 33.00 34.50 L 32.50 35.00 L 32.50 36.00 L 32.50 37.00 L 32.50 38.00 L 32.50 39.00 L 32.50 40.00 L 32.50 41.00 L 32.50 42.00 L 32.50 43.00 L 32.50 44.00 L 32.50 45.00 L 32.50 46.00 L 32.50 47.00 L 32.50 48.00 L 32.50 49.00 L 32.50 50.00 L 32.50 51.00 L 32.00 51.50 L 31.50 52.00 L 31.00 52.50 L 30.00 52.50 L 29.50 53.00 L 29.00 53.50 L 28.00 53.50 L 27.50 54.00 L 27.00 54.50 L 26.50 55.00 L 26.00 55.50 L 25.00 55.50 L 24.50 56.00 L 24.00 56.50 L 23.00 56.50 L 22.50 57.00 L 22.00 57.50 L 21.00 57.50 L 20.50 58.00 L 20.00 58.50 L 19.50 59.00 L 19.00 59.50 L 18.00 59.50 L 17.50 60.00 L 17.00 60.50 Z" fill="currentColor"/>
<path d="M 25.00 64.50 L 24.00 64.50 L 23.00 64.50 L 22.00 64.50 L 21.50 64.00 L 21.00 63.50 L 20.50 63.00 L 20.50 62.00 L 21.00 61.50 L 21.50 61.00 L 22.00 60.50 L 22.50 60.00 L 23.00 59.50 L 24.00 59.50 L 24.50 59.00 L 25.00 58.50 L 26.00 58.50 L 26.50 58.00 L 27.00 57.50 L 27.50 57.00 L 28.00 56.50 L 29.00 56.50 L 29.50 56.00 L 30.00 55.50 L 31.00 55.50 L 31.50 55.00 L 32.00 54.50 L 33.00 54.50 L 33.50 54.00 L 34.00 53.50 L 34.50 53.00 L 34.50 52.00 L 34.50 51.00 L 34.50 50.00 L 34.50 49.00 L 34.50 48.00 L 34.50 47.00 L 34.50 46.00 L 34.50 45.00 L 34.50 44.00 L 34.50 43.00 L 34.50 42.00 L 34.50 41.00 L 34.50 40.00 L 34.50 39.00 L 34.50 38.00 L 34.50 37.00 L 35.00 36.50 L 35.50 36.00 L 36.00 35.50 L 36.50 35.00 L 37.00 34.50 L 38.00 34.50 L 38.50 34.00 L 39.00 33.50 L 39.50 33.00 L 40.00 32.50 L 41.00 32.50 L 41.50 32.00 L 42.00 31.50 L 43.00 31.50 L 43.50 31.00 L 44.00 30.50 L 45.00 30.50 L 45.50 30.00 L 46.00 29.50 L 46.50 29.00 L 47.00 28.50 L 48.00 28.50 L 48.50 28.00 L 49.00 27.50 L 50.00 27.50 L 50.50 27.00 L 51.00 26.50 L 52.00 26.50 L 52.50 26.00 L 53.00 25.50 L 54.00 25.50 L 55.00 25.50 L 56.00 25.50 L 56.50 26.00 L 57.00 26.50 L 57.50 27.00 L 57.50 28.00 L 57.00 28.50 L 56.00 28.50 L 55.50 29.00 L 55.00 29.50 L 54.50 30.00 L 54.00 30.50 L 53.00 30.50 L 52.50 31.00 L 52.00 31.50 L 51.00 31.50 L 50.50 32.00 L 50.00 32.50 L 49.50 33.00 L 49.00 33.50 L 48.00 33.50 L 47.50 34.00 L 47.00 34.50 L 46.00 34.50 L 45.50 35.00 L 45.00 35.50 L 44.00 35.50 L 43.50 36.00 L 43.50 37.00 L 43.50 38.00 L 43.50 39.00 L 43.50 40.00 L 43.50 41.00 L 43.50 42.00 L 43.50 43.00 L 43.50 44.00 L 43.50 45.00 L 43.50 46.00 L 43.50 47.00 L 43.50 48.00 L 43.50 49.00 L 43.50 50.00 L 43.50 51.00 L 43.50 52.00 L 43.50 53.00 L 43.00 53.50 L 42.50 54.00 L 42.00 54.50 L 41.00 54.50 L 40.50 55.00 L 40.00 55.50 L 39.00 55.50 L 38.50 56.00 L 38.00 56.50 L 37.50 57.00 L 37.00 57.50 L 36.00 57.50 L 35.50 58.00 L 35.00 58.50 L 34.00 58.50 L 33.50 59.00 L 33.00 59.50 L 32.00 59.50 L 31.50 60.00 L 31.00 60.50 L 30.50 61.00 L 30.00 61.50 L 29.00 61.50 L 28.50 62.00 L 28.00 62.50 L 27.00 62.50 L 26.50 63.00 L 26.00 63.50 L 25.50 64.00 L 25.00 64.50 Z" fill="currentColor"/>
<path d="M 40.00 73.50 L 39.00 73.50 L 38.00 73.50 L 37.50 73.00 L 37.00 72.50 L 36.00 72.50 L 35.50 72.00 L 35.00 71.50 L 34.50 71.00 L 34.50 70.00 L 35.00 69.50 L 35.50 69.00 L 36.00 68.50 L 37.00 68.50 L 37.50 68.00 L 38.00 67.50 L 39.00 67.50 L 39.50 67.00 L 40.00 66.50 L 41.00 66.50 L 41.50 66.00 L 42.00 65.50 L 43.00 65.50 L 43.50 65.00 L 44.00 64.50 L 44.50 64.00 L 45.00 63.50 L 46.00 63.50 L 46.50 63.00 L 47.00 62.50 L 48.00 62.50 L 48.50 62.00 L 49.00 61.50 L 49.50 61.00 L 50.00 60.50 L 51.00 60.50 L 51.50 60.00 L 52.00 59.50 L 53.00 59.50 L 53.50 59.00 L 54.00 58.50 L 55.00 58.50 L 55.50 58.00 L 56.00 57.50 L 56.50 57.00 L 56.50 56.00 L 56.50 55.00 L 56.50 54.00 L 56.50 53.00 L 56.50 52.00 L 56.50 51.00 L 56.50 50.00 L 56.50 49.00 L 56.50 48.00 L 56.50 47.00 L 56.50 46.00 L 56.50 45.00 L 56.50 44.00 L 56.50 43.00 L 56.50 42.00 L 57.00 41.50 L 57.50 41.00 L 57.50 40.00 L 57.50 39.00 L 57.50 38.00 L 57.00 37.50 L 56.50 37.00 L 56.00 36.50 L 55.00 36.50 L 54.00 36.50 L 53.50 37.00 L 53.00 37.50 L 52.50 38.00 L 52.50 39.00 L 52.50 40.00 L 53.00 40.50 L 53.50 41.00 L 53.50 42.00 L 53.50 43.00 L 53.50 44.00 L 53.50 45.00 L 53.50 46.00 L 53.50 47.00 L 53.50 48.00 L 53.50 49.00 L 53.50 50.00 L 53.50 51.00 L 53.50 52.00 L 53.50 53.00 L 53.50 54.00 L 53.50 55.00 L 53.50 56.00 L 53.00 56.50 L 52.00 56.50 L 51.50 57.00 L 51.00 57.50 L 50.50 58.00 L 50.00 58.50 L 49.00 58.50 L 48.50 59.00 L 48.00 59.50 L 47.00 59.50 L 46.50 60.00 L 46.00 60.50 L 45.00 60.50 L 44.50 61.00 L 44.00 61.50 L 43.00 61.50 L 42.50 62.00 L 42.00 62.50 L 41.50 63.00 L 41.00 63.50 L 40.00 63.50 L 39.50 64.00 L 39.00 64.50 L 38.00 64.50 L 37.50 65.00 L 37.00 65.50 L 36.00 65.50 L 35.50 66.00 L 35.00 66.50 L 34.50 67.00 L 34.00 67.50 L 33.00 67.50 L 32.50 68.00 L 32.00 68.50 L 31.00 68.50 L 30.00 68.50 L 29.00 68.50 L 28.50 68.00 L 28.00 67.50 L 27.50 67.00 L 27.50 66.00 L 28.00 65.50 L 28.50 65.00 L 29.00 64.50 L 30.00 64.50 L 30.50 64.00 L 31.00 63.50 L 31.50 63.00 L 32.00 62.50 L 33.00 62.50 L 33.50 62.00 L 34.00 61.50 L 35.00 61.50 L 35.50 61.00 L 36.00 60.50 L 37.00 60.50 L 37.50 60.00 L 38.00 59.50 L 38.50 59.00 L 39.00 58.50 L 40.00 58.50 L 40.50 58.00 L 41.00 57.50 L 42.00 57.50 L 42.50 57.00 L 43.00 56.50 L 44.00 56.50 L 44.50 56.00 L 45.00 55.50 L 45.50 55.00 L 45.50 54.00 L 45.50 53.00 L 45.50 52.00 L 45.50 51.00 L 45.50 50.00 L 45.50 49.00 L 45.50 48.00 L 45.50 47.00 L 45.50 46.00 L 45.50 45.00 L 45.50 44.00 L 45.50 43.00 L 45.50 42.00 L 45.50 41.00 L 45.50 40.00 L 45.50 39.00 L 45.50 38.00 L 46.00 37.50 L 47.00 37.50 L 47.50 37.00 L 48.00 36.50 L 49.00 36.50 L 49.50 36.00 L 50.00 35.50 L 51.00 35.50 L 51.50 35.00 L 52.00 34.50 L 52.50 34.00 L 53.00 33.50 L 54.00 33.50 L 54.50 33.00 L 55.00 32.50 L 56.00 32.50 L 56.50 32.00 L 57.00 31.50 L 57.50 31.00 L 58.00 30.50 L 59.00 30.50 L 59.50 30.00 L 60.00 29.50 L 61.00 29.50 L 62.00 29.50 L 63.00 29.50 L 63.50 30.00 L 64.00 30.50 L 64.50 31.00 L 64.50 32.00 L 64.50 33.00 L 64.50 34.00 L 64.50 35.00 L 64.50 36.00 L 64.50 37.00 L 64.50 38.00 L 64.50 39.00 L 64.50 40.00 L 64.50 41.00 L 64.50 42.00 L 64.50 43.00 L 64.50 44.00 L 64.50 45.00 L 64.50 46.00 L 64.50 47.00 L 64.50 48.00 L 64.50 49.00 L 64.50 50.00 L 64.50 51.00 L 64.50 52.00 L 64.50 53.00 L 64.50 54.00 L 64.50 55.00 L 64.50 56.00 L 64.50 57.00 L 64.50 58.00 L 64.50 59.00 L 64.00 59.50 L 63.50 60.00 L 63.00 60.50 L 62.00 60.50 L 61.50 61.00 L 61.00 61.50 L 60.00 61.50 L 59.50 62.00 L 59.00 62.50 L 58.00 62.50 L 57.50 63.00 L 57.00 63.50 L 56.50 64.00 L 56.00 64.50 L 55.00 64.50 L 54.50 65.00 L 54.00 65.50 L 53.00 65.50 L 52.50 66.00 L 52.00 66.50 L 51.00 66.50 L 50.50 67.00 L 50.00 67.50 L 49.50 68.00 L 49.00 68.50 L 48.00 68.50 L 47.50 69.00 L 47.00 69.50 L 46.00 69.50 L 45.50 70.00 L 45.00 70.50 L 44.00 70.50 L 43.50 71.00 L 43.00 71.50 L 42.50 72.00 L 42.00 72.50 L 41.00 72.50 L 40.50 73.00 L 40.00 73.50 Z" fill="currentColor"/>
</svg>
</div>
<span class="text-xl font-bold text-primary-600 sidebar-text">清研</span>
</div>
<button id="sidebar-toggle" class="sidebar-toggle text-gray-400 hover:text-gray-600">
<svg class="w-5 h-5" viewBox="0 0 1126 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M62 917h990v45H62v-45z m990-405v45H557v-45h495z m0-405v45H557V107h495zM125 354.5L377 614.51 345.5 647 62 354.5 345.5 62l31.5 32.49z" fill="currentColor"/>
</svg>
</button>
</div>
</div>
<!-- 导航菜单 -->
<div class="p-4 space-y-2 flex-shrink-0">
<!-- 个人空间 -->
<a href="#" class="sidebar-item">
<div class="w-5 h-5 flex-shrink-0 bg-purple-600 rounded-md flex items-center justify-center">
<span class="text-white text-xs font-medium"></span>
</div>
<span class="sidebar-text">个人空间</span>
<svg class="w-4 h-4 text-gray-400 ml-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</a>
<!-- 主页 -->
<button onclick="showStartPage()" class="sidebar-item">
<svg class="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<span class="sidebar-text">主页</span>
</button>
<!-- 知识采集 -->
<a href="info-collection.html" class="sidebar-item">
<svg class="w-5 h-5 flex-shrink-0" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M862.656 609.92a97.92 97.92 0 0 0-91.52 61.184 14.08 14.08 0 0 1-12.992 8.832H736a56.064 56.064 0 0 1-56-56v-55.04c100.48-8.32 179.584-94.464 179.584-199.424 0-106.496-85.824-193.28-193.984-199.488A195.968 195.968 0 0 0 490.24 64C387.2 64 302.912 141.504 295.552 239.808c-75.84 20.992-131.072 85.184-131.072 161.28 0 89.6 76.8 163.264 173.824 168.448h5.76v54.4a56.064 56.064 0 0 1-56 56h-22.144a14.08 14.08 0 0 1-13.056-8.832 98.048 98.048 0 1 0 0.128 73.536 13.888 13.888 0 0 1 12.928-8.704H288a112 112 0 0 0 112-112v-47.36c0-3.84 3.2-7.04 7.04-7.04h69.952c3.84 0 7.04 3.2 7.04 7.04v181.632a14.08 14.08 0 0 1-8.896 12.992c-36.032 14.656-61.44 50.176-61.12 91.456a97.92 97.92 0 1 0 134.656-91.52 13.888 13.888 0 0 1-8.64-12.928V576.512c0-3.84 3.136-6.976 6.976-6.976H616.96c3.84 0 7.04 3.2 7.04 7.04v47.36c0 61.888 50.112 112 112 112h22.08c5.696 0 10.88 3.456 12.928 8.704a97.984 97.984 0 1 0 91.52-134.656zM161.92 750.016a41.984 41.984 0 1 1 0-84.032 41.984 41.984 0 0 1 0 84.032z m392 112a41.984 41.984 0 1 1-84.032 0 41.984 41.984 0 0 1 84.032 0zM339.84 513.536a135.168 135.168 0 0 1-85.888-36.8 104.896 104.896 0 0 1-33.472-75.712c0-23.68 8.448-46.336 24.256-65.6A129.792 129.792 0 0 1 310.4 293.76l37.952-10.496 2.88-39.296c2.496-33.28 17.92-64.32 43.264-87.424a142.08 142.08 0 0 1 95.808-36.544c26.752 0 52.736 7.232 75.072 21.12 21.632 13.248 38.912 32 50.24 54.208l14.592 28.608 32.128 1.856a152.96 152.96 0 0 1 100.8 45.44c26.112 26.624 40.512 61.568 40.512 98.24 0 79.36-62.528 144.064-139.52 144.064H339.84z m522.24 236.416a41.984 41.984 0 1 1 0-84.032 41.984 41.984 0 0 1 0 84.032z" fill="currentColor"/>
</svg>
<span class="sidebar-text">知识采集</span>
</a>
<!-- 知识库 -->
<a href="knowledge-base.html" class="sidebar-item">
<svg class="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z"/>
</svg>
<span class="sidebar-text">知识库</span>
</a>
<!-- 智能体菜单 -->
<div class="sidebar-item group relative" id="agent-menu">
<div class="flex items-center justify-between w-full">
<div class="flex items-center gap-2">
<svg class="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
</svg>
<span class="sidebar-text">智能体</span>
</div>
<svg class="w-4 h-4 sidebar-text transition-transform group-hover:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</div>
<!-- 智能体子菜单 -->
<div class="absolute left-full top-0 ml-2 bg-white border border-gray-200 rounded-lg shadow-xl py-2 min-w-48 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-[9999]">
<div class="space-y-1">
<a href="ai-assistant.html" class="flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 transition-colors">
<svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/>
</svg>
<span>AI 助手</span>
</a>
<a href="word-generator.html" class="flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 transition-colors">
<svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
<span>Word 生成</span>
</a>
<a href="ppt-generator.html" class="flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 transition-colors">
<svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
<span>PPT 生成</span>
</a>
<a href="清研智参谋-新版.html" class="flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 transition-colors">
<svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
</svg>
<span>信息快报员</span>
</a>
</div>
</div>
</div>
</div>
<!-- 历史对话 -->
<div class="p-2 border-t border-gray-200 flex-1 flex flex-col min-h-0">
<div class="flex items-center justify-between mb-2">
<h3 class="text-sm font-medium text-gray-700 sidebar-text">历史对话</h3>
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<div class="space-y-0.5 flex-1 overflow-y-auto min-h-0" id="recent-chats">
<!-- 对话项示例 -->
<div class="flex items-center justify-between py-1 px-2 rounded-md bg-gray-100 cursor-pointer w-[215px] relative group" onclick="openRecentChat({id: 'chat1', title: '客户需求分析报告'})">
<div class="flex items-center gap-2 min-w-0 flex-1">
<svg class="w-3.5 h-3.5 text-gray-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/>
</svg>
<span class="text-sm font-medium text-gray-900 sidebar-text truncate">客户需求分析报告</span>
</div>
</div>
<div class="flex items-center justify-between py-1 px-2 rounded-md hover:bg-gray-50 cursor-pointer w-[215px] relative group" onclick="openRecentChat({id: 'chat2', title: '销售策略优化建议'})">
<div class="flex items-center gap-2 min-w-0 flex-1">
<svg class="w-3.5 h-3.5 text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/>
</svg>
<span class="text-sm text-gray-700 sidebar-text truncate">销售策略优化建议</span>
</div>
</div>
<div class="flex items-center justify-between py-1 px-2 rounded-md hover:bg-gray-50 cursor-pointer w-[215px] relative group" onclick="openRecentChat({id: 'chat3', title: '竞品动态监控'})">
<div class="flex items-center gap-2 min-w-0 flex-1">
<svg class="w-3.5 h-3.5 text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/>
</svg>
<span class="text-sm text-gray-700 sidebar-text truncate">竞品动态监控</span>
</div>
</div>
</div>
</div>
</div>
<!-- 主内容区域 -->
<div class="flex-1 flex flex-col min-h-0">
<!-- 顶部导航栏 -->
<div class="bg-white shadow-sm border-b border-gray-200 px-4 py-2 relative z-20">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<button id="mobile-menu-toggle" class="lg:hidden text-gray-600 hover:text-gray-800">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
</button>
<div class="flex items-center gap-3">
<div class="w-8 h-8 bg-primary-600 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
</svg>
</div>
<span id="page-title" class="text-xl font-bold text-primary-600">信息快报员</span>
</div>
</div>
<div class="flex items-center gap-3">
<div class="relative hidden sm:block">
<input type="text" placeholder="AI搜索" class="pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent w-48 lg:w-64">
<svg class="w-5 h-5 text-gray-400 absolute left-3 top-2.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</svg>
</div>
<button class="text-gray-600 hover:text-gray-800 hidden sm:block">EN</button>
<button class="text-gray-600 hover:text-gray-800">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-5 5v-5z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 7h6m0 10v-3m-3 3h.01M9 17h.01M9 14h.01M9 11h.01M9 8h.01M9 5h.01"/>
</svg>
</button>
<div class="relative">
<button class="w-8 h-8 bg-gray-200 rounded-full flex items-center justify-center hover:bg-gray-300 transition-colors">
<span class="text-sm font-medium text-gray-700"></span>
</button>
</div>
</div>
</div>
</div>
<!-- 页面内容区域 -->
<div id="main-content" class="flex-1 overflow-auto relative z-10">
<div class="max-w-7xl mx-auto p-6">
<!-- 页面标题区域 -->
<!-- 任务列表和今日报告合并区域 -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
<!-- 切换按钮组 -->
<div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-2">
<div class="flex items-center bg-gray-100 rounded-lg p-1">
<button id="reports-tab" class="px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 bg-white text-gray-900 shadow-sm">
<div class="flex items-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 712-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
报告列表
<span class="bg-blue-100 text-blue-800 text-xs font-medium px-2 py-0.5 rounded-full">8份</span>
</div>
</button>
<button id="tasks-tab" class="px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 text-gray-600 hover:text-gray-900">
<div class="flex items-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 712-2h2a2 2 0 712 2"/>
</svg>
任务列表
<span class="bg-primary-100 text-primary-800 text-xs font-medium px-2 py-0.5 rounded-full">5个</span>
</div>
</button>
</div>
</div>
<!-- 任务列表操作按钮 -->
<div id="tasks-actions" class="flex items-center gap-2 hidden">
<div class="relative">
<button id="tasks-new-task-btn" class="inline-flex items-center px-3 py-1.5 bg-primary-600 text-white text-sm font-medium rounded-lg hover:bg-primary-700 transition-colors">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
</svg>
新建任务
<svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
<div id="tasks-task-dropdown" class="absolute top-full left-0 mt-1 w-40 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 hidden">
<button class="w-full text-left px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="showSingleTaskModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
单次任务
</button>
<button class="w-full text-left px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="showScheduledTaskModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
周期任务
</button>
</div>
</div>
</div>
<!-- 今日报告操作按钮 -->
<div id="reports-actions" class="flex items-center gap-2">
<div class="relative">
<button id="reports-new-task-btn" class="inline-flex items-center px-3 py-1.5 bg-primary-600 text-white text-sm font-medium rounded-lg hover:bg-primary-700 transition-colors">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
</svg>
新建任务
<svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
<div id="reports-task-dropdown" class="absolute top-full left-0 mt-1 w-40 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 hidden">
<button class="w-full text-left px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="showSingleTaskModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
单次任务
</button>
<button class="w-full text-left px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="showScheduledTaskModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
周期任务
</button>
</div>
</div>
</div>
</div>
<!-- 任务列表内容 -->
<div id="tasks-content" class="hidden">
<!-- 任务查看器容器 -->
<div id="task-viewer-container" class="task-viewer-container task-viewer-list-mode">
<!-- 任务列表模式 -->
<div id="task-list-mode">
<!-- 任务卡片容器 -->
<div class="overflow-hidden">
<!-- 第一页主任务 -->
<div id="main-task-page-1" class="grid grid-cols-4 gap-3 transition-opacity duration-300">
<div class="task-card bg-gradient-to-r from-blue-50 to-cyan-50 rounded-lg border border-blue-200 p-3 relative" onclick="openTaskReports('task-1')">
<div class="flex items-start justify-between mb-1">
<h3 class="font-semibold text-gray-900 text-sm flex-1">客户需求分析</h3>
<div class="relative">
<button class="task-menu-btn p-1 rounded hover:bg-white/50 transition-colors" onclick="event.stopPropagation(); toggleTaskMenu('task-1')" data-task="task-1">
<svg class="w-3 h-3 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"/>
</svg>
</button>
<div id="task-menu-task-1" class="task-menu absolute right-0 top-full mt-1 w-36 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 hidden">
<button class="w-full text-left px-3 py-2 text-xs text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="executeTaskOnce('task-1')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h1m4 0h1m-6 4h1m4 0h1m6-4a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
执行一次
</button>
<button class="w-full text-left px-3 py-2 text-xs text-orange-600 hover:bg-orange-50 flex items-center gap-2" onclick="pauseTask('task-1')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 9v6m4-6v6"/>
</svg>
暂停任务
</button>
<button class="w-full text-left px-3 py-2 text-xs text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="editTask('task-1')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
</svg>
编辑任务
</button>
<button class="w-full text-left px-3 py-2 text-xs text-red-600 hover:bg-red-50 flex items-center gap-2" onclick="deleteTask('task-1')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
删除任务
</button>
</div>
</div>
</div>
<p class="text-xs text-gray-600 mb-2">关注客户反馈中的痛点和需求变化</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每日 09:00</span>
<span>明天执行</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-blue-600">
生成报告 (2) <span class="text-green-600 font-medium">+2</span>
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-green-700">运行中</span>
</div>
</div>
</div>
<div class="task-card bg-gradient-to-r from-green-50 to-emerald-50 rounded-lg border border-green-200 p-3 relative" onclick="openTaskReports('task-2')">
<div class="flex items-start justify-between mb-1">
<h3 class="font-semibold text-gray-900 text-sm flex-1">竞品动态监控</h3>
<div class="relative">
<button class="task-menu-btn p-1 rounded hover:bg-white/50 transition-colors" onclick="event.stopPropagation(); toggleTaskMenu('task-2')" data-task="task-2">
<svg class="w-3 h-3 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"/>
</svg>
</button>
<div id="task-menu-task-2" class="task-menu absolute right-0 top-full mt-1 w-36 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 hidden">
<button class="w-full text-left px-3 py-2 text-xs text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="executeTaskOnce('task-2')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h1m4 0h1m-6 4h1m4 0h1m6-4a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
执行一次
</button>
<button class="w-full text-left px-3 py-2 text-xs text-orange-600 hover:bg-orange-50 flex items-center gap-2" onclick="pauseTask('task-2')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 9v6m4-6v6"/>
</svg>
暂停任务
</button>
<button class="w-full text-left px-3 py-2 text-xs text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="editTask('task-2')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
</svg>
编辑任务
</button>
<button class="w-full text-left px-3 py-2 text-xs text-red-600 hover:bg-red-50 flex items-center gap-2" onclick="deleteTask('task-2')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
删除任务
</button>
</div>
</div>
</div>
<p class="text-xs text-gray-600 mb-2">实时监控竞争对手产品和营销动态</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每日 10:00</span>
<span>已暂停</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-green-600">
生成报告 (5)
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-gray-400 rounded-full"></div>
<span class="text-xs font-medium text-gray-700">暂停</span>
</div>
</div>
</div>
<div class="task-card bg-gradient-to-r from-purple-50 to-violet-50 rounded-lg border border-purple-200 p-3 relative" onclick="openTaskReports('task-3')">
<div class="flex items-start justify-between mb-1">
<h3 class="font-semibold text-gray-900 text-sm flex-1">行业资讯汇总</h3>
<div class="relative">
<button class="task-menu-btn p-1 rounded hover:bg-white/50 transition-colors" onclick="event.stopPropagation(); toggleTaskMenu('task-3')" data-task="task-3">
<svg class="w-3 h-3 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"/>
</svg>
</button>
<div id="task-menu-task-3" class="task-menu absolute right-0 top-full mt-1 w-36 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 hidden">
<button class="w-full text-left px-3 py-2 text-xs text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="executeTaskOnce('task-3')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h1m4 0h1m-6 4h1m4 0h1m6-4a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
执行一次
</button>
<button class="w-full text-left px-3 py-2 text-xs text-orange-600 hover:bg-orange-50 flex items-center gap-2" onclick="pauseTask('task-3')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 9v6m4-6v6"/>
</svg>
暂停任务
</button>
<button class="w-full text-left px-3 py-2 text-xs text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="editTask('task-3')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
</svg>
编辑任务
</button>
<button class="w-full text-left px-3 py-2 text-xs text-red-600 hover:bg-red-50 flex items-center gap-2" onclick="deleteTask('task-3')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
删除任务
</button>
</div>
</div>
</div>
<p class="text-xs text-gray-600 mb-2">收集和分析行业最新动态趋势</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每周一 08:00</span>
<span>下周一执行</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-purple-600">
生成报告 (3) <span class="text-blue-600 font-medium">+1</span>
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-blue-500 rounded-full animate-spin border border-blue-200 border-t-blue-500"></div>
<span class="text-xs font-medium text-blue-700">生成中</span>
</div>
</div>
</div>
<div class="task-card bg-gradient-to-r from-red-50 to-pink-50 rounded-lg border border-red-200 p-3 relative" onclick="openTaskReports('task-4')">
<div class="flex items-start justify-between mb-1">
<h3 class="font-semibold text-gray-900 text-sm flex-1">销售数据分析</h3>
<div class="relative">
<button class="task-menu-btn p-1 rounded hover:bg-white/50 transition-colors" onclick="event.stopPropagation(); toggleTaskMenu('task-4')" data-task="task-4">
<svg class="w-3 h-3 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"/>
</svg>
</button>
<div id="task-menu-task-4" class="task-menu absolute right-0 top-full mt-1 w-36 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 hidden">
<button class="w-full text-left px-3 py-2 text-xs text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="executeTaskOnce('task-4')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h1m4 0h1m-6 4h1m4 0h1m6-4a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
执行一次
</button>
<button class="w-full text-left px-3 py-2 text-xs text-orange-600 hover:bg-orange-50 flex items-center gap-2" onclick="pauseTask('task-4')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 9v6m4-6v6"/>
</svg>
暂停任务
</button>
<button class="w-full text-left px-3 py-2 text-xs text-gray-700 hover:bg-gray-50 flex items-center gap-2" onclick="editTask('task-4')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
</svg>
编辑任务
</button>
<button class="w-full text-left px-3 py-2 text-xs text-red-600 hover:bg-red-50 flex items-center gap-2" onclick="deleteTask('task-4')">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
删除任务
</button>
</div>
</div>
</div>
<p class="text-xs text-gray-600 mb-2">定期分析销售表现和转化情况</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每日 18:00</span>
<span>今日执行</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-yellow-600">
生成报告 (4)
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-red-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-red-700">异常</span>
</div>
</div>
</div>
</div>
<!-- 第二页主任务(隐藏) -->
<div id="main-task-page-2" class="grid grid-cols-4 gap-3 transition-opacity duration-300 hidden">
<div class="task-card bg-gradient-to-r from-teal-50 to-cyan-50 rounded-lg border border-teal-200 p-3 cursor-pointer" onclick="openTaskReports('task-5')">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">用户行为分析</h3>
<p class="text-xs text-gray-600 mb-2">分析用户使用习惯和偏好</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每日 18:30</span>
<span>今日执行</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-teal-600">
生成报告 (8) <span class="text-green-600 font-medium">+3</span>
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-green-700">运行中</span>
</div>
</div>
</div>
<div class="task-card bg-gradient-to-r from-indigo-50 to-purple-50 rounded-lg border border-indigo-200 p-3 cursor-pointer" onclick="openTaskReports('task-6')">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">产品功能评估</h3>
<p class="text-xs text-gray-600 mb-2">评估产品功能使用情况</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每周三 16:00</span>
<span>昨日完成</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-indigo-600">
生成报告 (12)
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-green-500 rounded-full"></div>
<span class="text-xs font-medium text-green-700">运行中</span>
</div>
</div>
</div>
<div class="task-card bg-gradient-to-r from-teal-50 to-cyan-50 rounded-lg border border-teal-200 p-3 cursor-pointer" onclick="openTaskReports('task-7')">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">市场调研汇总</h3>
<p class="text-xs text-gray-600 mb-2">汇总市场调研数据</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每月15日 14:00</span>
<span>下次: 12月15日</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-teal-600">
生成报告 (5)
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-gray-400 rounded-full"></div>
<span class="text-xs font-medium text-gray-700">暂停</span>
</div>
</div>
</div>
<div class="task-card bg-gradient-to-r from-rose-50 to-orange-50 rounded-lg border border-rose-200 p-3 cursor-pointer" onclick="openTaskReports('task-8')">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">技术趋势监控</h3>
<p class="text-xs text-gray-600 mb-2">监控技术发展趋势</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每日 20:00</span>
<span>今日执行</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-rose-600">
生成报告 (6) <span class="text-green-600 font-medium">+1</span>
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-green-700">运行中</span>
</div>
</div>
</div>
</div>
</div>
<!-- 任务列表 -->
<div id="expanded-tasks" class="mt-4 relative">
<!-- 任务卡片容器 -->
<div id="task-cards-container" class="mb-4">
<div class="grid grid-cols-4 gap-3" id="task-cards-grid">
<!-- 第1页任务 -->
<div class="task-card bg-gradient-to-r from-teal-50 to-cyan-50 rounded-lg border border-teal-200 p-3">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">用户行为分析</h3>
<p class="text-xs text-gray-600 mb-2">分析用户使用习惯和偏好</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每日 18:30</span>
<span>今日执行</span>
</div>
<div class="flex items-center justify-between mb-2">
<div class="text-xs text-teal-600">
生成报告 (8) <span class="text-green-600 font-medium">+3</span>
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-green-700">运行中</span>
</div>
</div>
<button onclick="event.stopPropagation(); openTaskReports('task-5')" class="w-full bg-teal-600 hover:bg-teal-700 text-white text-xs font-medium py-1 px-3 rounded-md transition-colors duration-200 flex items-center justify-center gap-1">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
查看报告
</button>
</div>
<div class="task-card bg-gradient-to-r from-indigo-50 to-purple-50 rounded-lg border border-indigo-200 p-3">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">产品功能评估</h3>
<p class="text-xs text-gray-600 mb-2">评估产品功能使用情况</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每周三 16:00</span>
<span>昨日完成</span>
</div>
<div class="flex items-center justify-between mb-2">
<div class="text-xs text-indigo-600">
生成报告 (12)
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-green-700">运行中</span>
</div>
</div>
<button onclick="event.stopPropagation(); openTaskReports('task-6')" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-medium py-1 px-3 rounded-md transition-colors duration-200 flex items-center justify-center gap-1">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
查看报告
</button>
</div>
<div class="task-card bg-gradient-to-r from-teal-50 to-cyan-50 rounded-lg border border-teal-200 p-3">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">市场调研汇总</h3>
<p class="text-xs text-gray-600 mb-2">汇总市场调研数据</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每月15日 14:00</span>
<span>下次: 12月15日</span>
</div>
<div class="flex items-center justify-between mb-2">
<div class="text-xs text-teal-600">
生成报告 (5)
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-gray-400 rounded-full"></div>
<span class="text-xs font-medium text-gray-700">暂停</span>
</div>
</div>
<button onclick="event.stopPropagation(); openTaskReports('task-7')" class="w-full bg-teal-600 hover:bg-teal-700 text-white text-xs font-medium py-1 px-3 rounded-md transition-colors duration-200 flex items-center justify-center gap-1">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
查看报告
</button>
</div>
<div class="task-card bg-gradient-to-r from-rose-50 to-orange-50 rounded-lg border border-rose-200 p-3">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">技术趋势监控</h3>
<p class="text-xs text-gray-600 mb-2">监控技术发展趋势</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每日 20:00</span>
<span>今日执行</span>
</div>
<div class="flex items-center justify-between mb-2">
<div class="text-xs text-rose-600">
生成报告 (6) <span class="text-green-600 font-medium">+1</span>
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-green-700">运行中</span>
</div>
</div>
<button onclick="event.stopPropagation(); openTaskReports('task-8')" class="w-full bg-rose-600 hover:bg-rose-700 text-white text-xs font-medium py-1 px-3 rounded-md transition-colors duration-200 flex items-center justify-center gap-1">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
查看报告
</button>
</div>
</div>
<!-- 第2页任务 -->
<div class="grid grid-cols-4 gap-3" id="task-page-2">
<div class="task-card bg-gradient-to-r from-amber-50 to-yellow-50 rounded-lg border border-amber-200 p-3">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">价格策略分析</h3>
<p class="text-xs text-gray-600 mb-2">分析定价策略效果</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每周一 09:00</span>
<span>今日执行</span>
</div>
<div class="flex items-center justify-between mb-2">
<div class="text-xs text-amber-600">
生成报告 (3) <span class="text-blue-600 font-medium">+1</span>
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-blue-500 rounded-full animate-spin border border-blue-200 border-t-blue-500"></div>
<span class="text-xs font-medium text-blue-700">生成中</span>
</div>
</div>
<button onclick="event.stopPropagation(); openTaskReports('task-9')" class="w-full bg-amber-600 hover:bg-amber-700 text-white text-xs font-medium py-1 px-3 rounded-md transition-colors duration-200 flex items-center justify-center gap-1">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
查看报告
</button>
</div>
<div class="task-card bg-gradient-to-r from-emerald-50 to-green-50 rounded-lg border border-emerald-200 p-3 cursor-pointer" onclick="openTaskReports('task-10')">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">客户满意度调查</h3>
<p class="text-xs text-gray-600 mb-2">客户满意度数据分析</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每季度 最后一天</span>
<span>已完成</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-emerald-600">
生成报告 (15)
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-yellow-500 rounded-full"></div>
<span class="text-xs font-medium text-yellow-700">待执行</span>
</div>
</div>
</div>
<div class="task-card bg-gradient-to-r from-violet-50 to-purple-50 rounded-lg border border-violet-200 p-3 cursor-pointer" onclick="openTaskReports('task-11')">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">供应商评估</h3>
<p class="text-xs text-gray-600 mb-2">评估供应商服务质量</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每半年 第1天</span>
<span>下次: 明年1月</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-violet-600">
生成报告 (7)
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-red-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-red-700">异常</span>
</div>
</div>
</div>
<div class="task-card bg-gradient-to-r from-sky-50 to-blue-50 rounded-lg border border-sky-200 p-3 cursor-pointer" onclick="openTaskReports('task-12')">
<h3 class="font-semibold text-gray-900 mb-1 text-sm">财务数据整理</h3>
<p class="text-xs text-gray-600 mb-2">整理财务相关数据</p>
<div class="flex items-center justify-between text-xs text-gray-500 mb-2">
<span>每月最后一天</span>
<span>月底执行</span>
</div>
<div class="flex items-center justify-between">
<div class="text-xs text-sky-600">
生成报告 (9) <span class="text-green-600 font-medium">+2</span>
</div>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-green-700">运行中</span>
</div>
</div>
</div>
</div>
<!-- 第3页任务 -->
<div class="grid grid-cols-4 gap-3" id="task-page-3">
</div>
</div>
<!-- 翻页器 -->
<div class="flex items-center justify-center gap-4 mt-6">
<button id="task-prev-btn" class="p-2 rounded-lg bg-gray-100 hover:bg-gray-200 transition-colors disabled:opacity-50 disabled:cursor-not-allowed" onclick="switchTaskPage('prev')" disabled>
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
</button>
<div class="flex items-center gap-2">
<span id="task-page-indicator" class="text-sm text-gray-600">1 / 3</span>
</div>
<button id="task-next-btn" class="p-2 rounded-lg bg-gray-100 hover:bg-gray-200 transition-colors disabled:opacity-50 disabled:cursor-not-allowed" onclick="switchTaskPage('next')">
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</button>
</div>
</div>
</div>
<!-- 任务侧边栏模式 -->
<div id="task-sidebar-mode" class="task-viewer-sidebar-mode hidden">
<div class="task-sidebar">
<div class="task-sidebar-header">
<button onclick="closeTaskSidebar()" class="flex items-center gap-2 text-sm text-gray-600 hover:text-gray-900 mb-3">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
返回任务列表
</button>
<h3 id="task-sidebar-title" class="text-lg font-semibold text-gray-900 mb-4">任务标题</h3>
</div>
<div class="task-sidebar-content">
<div id="task-sidebar-list">
<!-- 任务列表项将在这里动态生成 -->
</div>
<!-- 任务侧边栏翻页按钮 -->
<div class="mt-4 pt-3 border-t border-gray-200">
<div class="flex items-center justify-between">
<button class="flex items-center gap-1 px-2 py-1 text-xs text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded transition-colors">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
上一页
</button>
<span class="text-xs text-gray-500">1 / 2</span>
<button class="flex items-center gap-1 px-2 py-1 text-xs text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded transition-colors">
下一页
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</button>
</div>
</div>
</div>
</div>
<div class="task-content">
<div id="task-reports-content">
<!-- 任务报告内容将在这里显示 -->
</div>
</div>
</div>
</div>
</div>
<!-- 今日报告内容 -->
<div id="reports-content">
<!-- 系统处理数据展示 -->
<div class="mb-6 p-4 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg border border-blue-100">
<div class="flex items-center gap-2 mb-2">
<div class="flex items-center gap-2">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-sm font-medium text-blue-900">生成进度</span>
</div>
<div class="flex-1 bg-blue-200 rounded-full h-1.5 ml-2">
<div class="bg-blue-600 h-1.5 rounded-full transition-all duration-1000" style="width: 92%"></div>
</div>
<span class="text-xs text-blue-700 font-medium">92%</span>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mt-3">
<div class="text-center">
<div class="flex items-center justify-center gap-1 mb-1">
<svg class="w-4 h-4 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
<span class="text-sm font-semibold text-blue-900">原始数据</span>
</div>
<p class="text-lg font-bold text-blue-700">243 条</p>
<p class="text-xs text-blue-600">扫描 15 个数据源</p>
</div>
<div class="text-center">
<div class="flex items-center justify-center gap-1 mb-1">
<svg class="w-4 h-4 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
<span class="text-sm font-semibold text-indigo-900">智能提炼</span>
</div>
<p class="text-lg font-bold text-indigo-700">18 个</p>
<p class="text-xs text-indigo-600">关键信息点</p>
</div>
<div class="text-center">
<div class="flex items-center justify-center gap-1 mb-1">
<svg class="w-4 h-4 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<span class="text-sm font-semibold text-green-900">精华报告</span>
</div>
<p class="text-lg font-bold text-green-700">8 份</p>
<p class="text-xs text-green-600">已生成完成</p>
</div>
</div>
<div class="mt-3 text-center">
<p class="text-xs text-blue-700">
🤖 Agent 已帮你处理 <span class="font-semibold">2.3万字</span> 内容,去重分析后生成 <span class="font-semibold">8份精华报告</span>
</p>
</div>
</div>
<!-- 报告查看器容器 -->
<div id="report-viewer-container" class="report-viewer-container report-viewer-list-mode">
<!-- 列表模式:显示所有报告卡片 -->
<div id="report-list-mode" class="space-y-1">
<!-- 客户需求分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-3 hover:shadow-lg transition-all duration-200 hover:border-blue-300 cursor-pointer" onclick="openUnifiedReportView('report-1', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《客户需求分析 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
来自 "客户需求分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">基于客户反馈数据的深度分析识别关键需求趋势和改进机会85%客户反馈集中在产品易用性需求</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 09:00
</div>
</div>
</div>
<!-- 销售策略优化报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-green-300 cursor-pointer" onclick="openUnifiedReportView('report-2', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《销售策略优化 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
来自 "销售数据分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">销售数据分析报告提供策略优化建议和话术改进方案Q3销售转化率较Q2提升12%</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 11:30
</div>
</div>
</div>
<!-- 市场机会洞察报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-purple-300 cursor-pointer" onclick="openUnifiedReportView('report-3', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《市场机会洞察 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800">
来自 "行业资讯汇总" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">基于行业趋势分析识别市场机会和竞争优势AI驱动的解决方案需求增长67%</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 14:15
</div>
</div>
</div>
<!-- 第4个报告用户行为分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-teal-300 cursor-pointer" onclick="openUnifiedReportView('report-4', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《用户行为分析 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-teal-100 text-teal-800">
来自 "用户行为分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">深度分析用户使用习惯和偏好识别关键用户路径和转化节点用户留存率提升23%</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 16:45
</div>
</div>
</div>
<!-- 第5个报告产品功能评估报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-indigo-300 cursor-pointer" onclick="openUnifiedReportView('report-5', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《产品功能评估 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-indigo-100 text-indigo-800">
来自 "产品功能评估" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">全面评估产品功能使用情况和用户满意度核心功能使用率提升45%,用户反馈积极度显著改善</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 18:20
</div>
</div>
</div>
<!-- 第6个报告竞品分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-orange-300 cursor-pointer" onclick="openUnifiedReportView('report-6', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《竞品分析报告 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-orange-100 text-orange-800">
来自 "竞品分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">深度分析主要竞争对手的产品策略和市场表现识别差异化机会和竞争优势市场份额提升8%</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 20:10
</div>
</div>
</div>
<!-- 第7个报告技术趋势分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-cyan-300 cursor-pointer" onclick="openUnifiedReportView('report-7', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《技术趋势分析 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-cyan-100 text-cyan-800">
来自 "技术趋势分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">分析最新技术发展趋势和行业创新动态AI技术应用场景扩展67%,为产品技术路线提供决策支持</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 21:30
</div>
</div>
</div>
<!-- 第8个报告运营数据分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-pink-300 cursor-pointer" onclick="openUnifiedReportView('report-8', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《运营数据分析 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-pink-100 text-pink-800">
来自 "运营数据分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">全面分析运营关键指标和用户增长数据日活跃用户增长34%,用户参与度显著提升</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 22:15
</div>
</div>
</div>
<!-- 第9个报告财务绩效分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-emerald-300 cursor-pointer" onclick="openUnifiedReportView('report-9', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《财务绩效分析 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-emerald-100 text-emerald-800">
来自 "财务绩效分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">深度分析财务指标和成本结构收入增长28%成本控制效果显著利润率提升12%</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 23:00
</div>
</div>
</div>
<!-- 第10个报告综合决策建议报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-rose-300 cursor-pointer" onclick="openUnifiedReportView('report-10', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《综合决策建议 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-rose-100 text-rose-800">
来自 "综合决策建议" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">基于多维度数据分析的综合决策建议,涵盖产品、市场、运营等关键领域,为战略决策提供全面支持</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 23:45
</div>
</div>
</div>
</div>
<!-- 侧边栏模式:显示报告详情 -->
<div id="report-sidebar-mode" class="report-viewer-sidebar-mode hidden">
<!-- 左侧报告列表 -->
<div class="report-sidebar">
<div class="report-sidebar-header">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-900">报告列表</h3>
<button onclick="closeReportSidebar()" class="flex items-center gap-2 text-sm text-gray-600 hover:text-gray-900">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
返回今日报告
</button>
</div>
</div>
<div class="report-sidebar-content">
<div class="space-y-2">
<div class="report-list-item-compact" data-report-id="report-1" onclick="selectReportInSidebar('report-1')">
<h4 class="text-sm font-medium text-gray-900">客户需求分析报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 09:00 • 1.2MB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-2" onclick="selectReportInSidebar('report-2')">
<h4 class="text-sm font-medium text-gray-900">销售策略优化报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 11:30 • 950KB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-3" onclick="selectReportInSidebar('report-3')">
<h4 class="text-sm font-medium text-gray-900">市场机会洞察报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 14:15 • 1.1MB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-4" onclick="selectReportInSidebar('report-4')">
<h4 class="text-sm font-medium text-gray-900">用户行为分析报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 16:45 • 890KB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-5" onclick="selectReportInSidebar('report-5')">
<h4 class="text-sm font-medium text-gray-900">产品功能评估报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 18:20 • 1.3MB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-6" onclick="selectReportInSidebar('report-6')">
<h4 class="text-sm font-medium text-gray-900">竞品分析报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 20:10 • 1.0MB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-7" onclick="selectReportInSidebar('report-7')">
<h4 class="text-sm font-medium text-gray-900">技术趋势分析报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 21:30 • 1.4MB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-8" onclick="selectReportInSidebar('report-8')">
<h4 class="text-sm font-medium text-gray-900">运营数据分析报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 22:15 • 1.1MB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-9" onclick="selectReportInSidebar('report-9')">
<h4 class="text-sm font-medium text-gray-900">财务绩效分析报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 23:00 • 1.2MB</p>
</div>
<div class="report-list-item-compact" data-report-id="report-10" onclick="selectReportInSidebar('report-10')">
<h4 class="text-sm font-medium text-gray-900">综合决策建议报告</h4>
<p class="text-xs text-gray-500 mt-1">09.07 23:45 • 1.5MB</p>
</div>
</div>
<!-- 报告侧边栏翻页按钮 -->
<div class="mt-4 pt-3 border-t border-gray-200">
<div class="flex items-center justify-between">
<button class="flex items-center gap-1 px-2 py-1 text-xs text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded transition-colors">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
上一页
</button>
<span class="text-xs text-gray-500">1 / 3</span>
<button class="flex items-center gap-1 px-2 py-1 text-xs text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded transition-colors">
下一页
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</button>
</div>
</div>
</div>
</div>
<!-- 右侧报告详情 -->
<div class="report-content">
<div id="report-detail-content">
<!-- 报告详情内容将在这里动态加载 -->
</div>
</div>
</div>
</div>
<!-- 报告分页器 -->
<div class="flex items-center justify-center gap-4 mt-6">
<button id="report-prev-btn" class="p-2 rounded-lg bg-gray-100 hover:bg-gray-200 transition-colors disabled:opacity-50 disabled:cursor-not-allowed" onclick="switchReportPage('prev')" disabled>
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
</button>
<div class="flex items-center gap-2">
<span id="report-page-indicator" class="text-sm text-gray-600">1 / 2</span>
</div>
<button id="report-next-btn" class="p-2 rounded-lg bg-gray-100 hover:bg-gray-200 transition-colors disabled:opacity-50 disabled:cursor-not-allowed" onclick="switchReportPage('next')">
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</button>
</div>
</div>
</div>
<!-- 统一报告查看界面 -->
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 11:30
</div>
</div>
</div>
<!-- 市场机会洞察报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-purple-300 cursor-pointer" onclick="openUnifiedReportView('report-3', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《市场机会洞察 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800">
来自 "行业资讯汇总" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">基于行业趋势分析识别市场机会和竞争优势AI驱动的解决方案需求增长67%</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 14:20
</div>
</div>
</div>
<!-- 竞品动态监控报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-4 hover:shadow-lg transition-all duration-200 hover:border-orange-300 cursor-pointer" onclick="openUnifiedReportView('report-4', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《竞品动态监控 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-orange-100 text-orange-800">
来自 "竞品动态监控" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">竞争对手产品功能、价格策略和市场动向分析主要竞品A发布新功能模块价格策略调整</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 16:00
</div>
</div>
</div>
<!-- 用户行为分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-3 hover:shadow-lg transition-all duration-200 hover:border-indigo-300 cursor-pointer" onclick="openUnifiedReportView('report-5', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《用户行为分析 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-indigo-100 text-indigo-800">
来自 "用户行为分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">用户使用习惯、偏好分析和产品优化建议用户平均停留时间增加15%</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 712-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 18:30
</div>
</div>
</div>
<!-- 风险评估报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-3 hover:shadow-lg transition-all duration-200 hover:border-red-300 cursor-pointer" onclick="openUnifiedReportView('report-6', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《风险评估报告 - 2025.09.06》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
来自 "市场调研汇总" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">市场风险、技术风险和运营风险综合评估识别出3个高风险点和5个中等风险点</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 712-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.06 22:00
</div>
</div>
</div>
<!-- 技术分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-3 hover:shadow-lg transition-all duration-200 hover:border-cyan-300 cursor-pointer" onclick="openUnifiedReportView('report-7', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《技术分析报告 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-cyan-100 text-cyan-800">
来自 "技术趋势监控" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">技术发展趋势分析和前沿技术研究AI和云计算技术应用趋势分析</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 712-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 20:00
</div>
</div>
</div>
<!-- 财务分析报告 -->
<div class="report-card bg-white border border-gray-200 rounded-lg p-3 hover:shadow-lg transition-all duration-200 hover:border-emerald-300 cursor-pointer" onclick="openUnifiedReportView('report-8', this)">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-sm font-semibold text-gray-900">《财务分析报告 - 2025.09.07》</h3>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-emerald-100 text-emerald-800">
来自 "财务数据分析" 任务
</span>
</div>
<div class="text-xs text-gray-600">
<p class="truncate">财务数据分析和成本控制建议Q3营收增长18%,运营效率显著提升</p>
</div>
</div>
</div>
<div class="flex items-center justify-between pt-2 border-t border-gray-100">
<div class="flex items-center gap-1">
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="event.stopPropagation()" class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-600 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 712-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
</div>
<div class="flex items-center text-xs text-gray-500">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
09.07 17:45
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 统一报告查看界面 -->
<div id="unified-report-view" class="fixed top-16 left-56 right-0 bottom-0 bg-white z-40 hidden transition-all duration-500 ease-in-out">
<div class="flex h-full">
<!-- 左侧报告列表 -->
<div class="w-1/3 bg-gray-50 border-r border-gray-200 flex flex-col">
<div class="flex items-center justify-between p-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-900">所有报告</h3>
<button onclick="closeUnifiedReportView()" class="p-2 hover:bg-gray-200 rounded-lg">
<svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="flex-1 overflow-y-auto p-4">
<div class="space-y-2">
今天
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-1" onclick="selectUnifiedReport('report-1')">
<p class="font-medium text-sm">客户需求分析报告</p>
<p class="text-xs text-gray-500">今日 09:00 • 1.2MB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-2" onclick="selectUnifiedReport('report-2')">
<p class="font-medium text-sm">销售策略优化报告</p>
<p class="text-xs text-gray-500">今日 11:30 • 950KB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-3" onclick="selectUnifiedReport('report-3')">
<p class="font-medium text-sm">市场机会洞察报告</p>
<p class="text-xs text-gray-500">今日 14:20 • 1.5MB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-4" onclick="selectUnifiedReport('report-4')">
<p class="font-medium text-sm">竞品动态监控报告</p>
<p class="text-xs text-gray-500">今日 16:00 • 800KB</p>
</div>
9月8日
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-5" onclick="selectUnifiedReport('report-5')">
<p class="font-medium text-sm">用户行为分析报告</p>
<p class="text-xs text-gray-500">今日 18:30 • 1.1MB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-6" onclick="selectUnifiedReport('report-6')">
<p class="font-medium text-sm">风险评估报告</p>
<p class="text-xs text-gray-500">昨日 22:00 • 1.3MB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-7" onclick="selectUnifiedReport('report-7')">
<p class="font-medium text-sm">产品功能评估报告</p>
<p class="text-xs text-gray-500">昨日 16:00 • 850KB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-8" onclick="selectUnifiedReport('report-8')">
<p class="font-medium text-sm">市场调研汇总报告</p>
<p class="text-xs text-gray-500">本月15日 14:00 • 2.1MB</p>
</div>
9月7日
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-9" onclick="selectUnifiedReport('report-9')">
<p class="font-medium text-sm">技术趋势监控报告</p>
<p class="text-xs text-gray-500">今日 20:00 • 1.8MB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-10" onclick="selectUnifiedReport('report-10')">
<p class="font-medium text-sm">价格策略分析报告</p>
<p class="text-xs text-gray-500">今日 09:00 • 750KB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-11" onclick="selectUnifiedReport('report-11')">
<p class="font-medium text-sm">客户满意度调查报告</p>
<p class="text-xs text-gray-500">本季度 • 1.6MB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-12" onclick="selectUnifiedReport('report-12')">
<p class="font-medium text-sm">供应商评估报告</p>
<p class="text-xs text-gray-500">半年评估 • 1.4MB</p>
</div>
<div class="report-list-item bg-white border border-gray-200 rounded-lg p-3 cursor-pointer hover:shadow-sm transition-all" data-report-id="report-13" onclick="selectUnifiedReport('report-13')">
<p class="font-medium text-sm">财务数据整理报告</p>
<p class="text-xs text-gray-500">月底 • 2.3MB</p>
</div>
</div>
</div>
</div>
<!-- 右侧报告详情 -->
<div class="flex-1 flex flex-col">
<!-- 报告标题和操作栏 -->
<div class="flex items-center justify-between p-6 border-b border-gray-200">
<div>
<h2 id="unified-report-title" class="text-xl font-bold text-gray-900">报告标题</h2>
<p id="unified-report-meta" class="text-sm text-gray-500">报告信息</p>
</div>
<div class="flex items-center gap-2">
<button onclick="downloadReport()" class="inline-flex items-center px-3 py-2 bg-primary-600 text-white text-sm rounded-lg hover:bg-primary-700 transition-colors">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
<button onclick="archiveReport()" class="inline-flex items-center px-3 py-2 bg-gray-200 text-gray-700 text-sm rounded-lg hover:bg-gray-300 transition-colors">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V3"/>
</svg>
归档
</button>
<button onclick="shareReport()" class="inline-flex items-center px-3 py-2 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700 transition-colors">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z"/>
</svg>
分享
</button>
<button onclick="rerunReport()" class="inline-flex items-center px-3 py-2 bg-green-600 text-white text-sm rounded-lg hover:bg-green-700 transition-colors">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
</svg>
重新执行
</button>
</div>
</div>
<!-- 报告内容区域 -->
<div class="flex-1 overflow-y-auto p-6">
<div id="unified-report-content" class="prose prose-lg max-w-none">
<!-- 报告内容将在这里显示 -->
</div>
</div>
</div>
</div>
</div>
<!-- 报告抽屉 -->
<div id="drawer-overlay" class="drawer-overlay" onclick="closeReportDrawer()"></div>
<div id="report-drawer" class="report-drawer">
<div class="report-drawer-header">
<div class="flex items-center justify-between mb-3">
<h2 id="drawer-title" class="text-lg font-semibold text-gray-900">报告详情</h2>
<button onclick="closeReportDrawer()" class="p-2 rounded-lg hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div id="drawer-meta" class="mb-3 text-sm text-gray-600">
<!-- 报告元信息 -->
</div>
<div class="flex gap-2">
<button onclick="downloadReport()" class="flex-1 inline-flex items-center justify-center px-3 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 transition-colors">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
下载
</button>
<button onclick="archiveReport()" class="flex-1 inline-flex items-center justify-center px-3 py-2 bg-gray-600 text-white text-sm font-medium rounded-lg hover:bg-gray-700 transition-colors">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8l6 6m0 0l6-6m-6 6V4m0 0H9m3 0h3"/>
</svg>
归档
</button>
</div>
</div>
<div class="report-drawer-content">
<div id="drawer-content">
<!-- 报告内容 -->
</div>
</div>
<div class="report-drawer-footer">
<button id="prev-report-btn" onclick="navigateToPreviousReport()" class="flex-1 inline-flex items-center justify-center px-4 py-2 bg-gray-100 text-gray-700 text-sm font-medium rounded-lg hover:bg-gray-200 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
上一篇
</button>
<div class="flex items-center justify-center px-4 py-2 text-sm text-gray-500">
<span id="report-counter">1 / 1</span>
</div>
<button id="next-report-btn" onclick="navigateToNextReport()" class="flex-1 inline-flex items-center justify-center px-4 py-2 bg-gray-100 text-gray-700 text-sm font-medium rounded-lg hover:bg-gray-200 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
下一篇
<svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</button>
</div>
</div>
<script>
// 标签页切换功能
function switchTab(tabName) {
const tasksTab = document.getElementById('tasks-tab');
const reportsTab = document.getElementById('reports-tab');
const tasksContent = document.getElementById('tasks-content');
const reportsContent = document.getElementById('reports-content');
const tasksActions = document.getElementById('tasks-actions');
const reportsActions = document.getElementById('reports-actions');
if (tabName === 'tasks') {
// 激活任务列表标签
tasksTab.classList.add('bg-white', 'text-gray-900', 'shadow-sm');
tasksTab.classList.remove('text-gray-600', 'hover:text-gray-900');
reportsTab.classList.remove('bg-white', 'text-gray-900', 'shadow-sm');
reportsTab.classList.add('text-gray-600', 'hover:text-gray-900');
// 显示任务列表内容
tasksContent.classList.remove('hidden');
reportsContent.classList.add('hidden');
tasksActions.classList.remove('hidden');
reportsActions.classList.add('hidden');
} else if (tabName === 'reports') {
// 激活今日报告标签
reportsTab.classList.add('bg-white', 'text-gray-900', 'shadow-sm');
reportsTab.classList.remove('text-gray-600', 'hover:text-gray-900');
tasksTab.classList.remove('bg-white', 'text-gray-900', 'shadow-sm');
tasksTab.classList.add('text-gray-600', 'hover:text-gray-900');
// 显示今日报告内容
reportsContent.classList.remove('hidden');
tasksContent.classList.add('hidden');
reportsActions.classList.remove('hidden');
tasksActions.classList.add('hidden');
}
}
// 为按钮添加点击事件
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('tasks-tab').addEventListener('click', function() {
switchTab('tasks');
});
document.getElementById('reports-tab').addEventListener('click', function() {
switchTab('reports');
});
// 默认激活今日报告标签
switchTab('reports');
// 为所有任务卡片添加查看报告按钮
addViewReportButtonsToTaskCards();
});
// 全局函数定义 - 需要在HTML加载时就可用
function openTaskReports(taskId) {
console.log('打开任务报告:', taskId);
// 获取任务卡片元素 - 多种查找方法
let taskCard = null;
// 方法1通过查看报告按钮查找父级卡片
const viewReportButton = document.querySelector(`button[onclick*="openTaskReports('${taskId}')"]`);
if (viewReportButton) {
taskCard = viewReportButton.closest('.task-card');
}
// 方法2通过原有的onclick属性查找
if (!taskCard) {
taskCard = document.querySelector(`[onclick*="${taskId}"]`);
}
// 方法3通过任务ID查找
if (!taskCard) {
taskCard = document.querySelector(`[data-task-id="${taskId}"]`);
}
// 方法4通过任务标题查找
if (!taskCard) {
const taskTitleMap = {
'task-1': '客户需求分析',
'task-2': '竞品动态监控',
'task-3': '行业资讯汇总',
'task-4': '销售数据分析',
'task-5': '用户行为分析',
'task-6': '产品功能评估',
'task-7': '市场调研汇总',
'task-8': '技术趋势监控',
'task-9': '价格策略分析',
'task-10': '客户满意度调查',
'task-11': '供应商评估',
'task-12': '财务数据整理'
};
const expectedTitle = taskTitleMap[taskId];
if (expectedTitle) {
const titleElements = document.querySelectorAll('.task-card h3');
for (let titleEl of titleElements) {
if (titleEl.textContent.includes(expectedTitle)) {
taskCard = titleEl.closest('.task-card');
break;
}
}
}
}
if (!taskCard) {
console.error('未找到任务卡片:', taskId);
console.log('所有任务卡片:', document.querySelectorAll('.task-card'));
return;
}
// 获取任务标题 - 添加错误处理和备用方法
let titleElement = taskCard.querySelector('h3');
let taskTitle = '';
if (titleElement) {
taskTitle = titleElement.textContent;
} else {
// 备用方法从任务ID映射获取标题
const taskTitleMap = {
'task-1': '客户需求分析',
'task-2': '竞品动态监控',
'task-3': '行业资讯汇总',
'task-4': '销售数据分析',
'task-5': '用户行为分析',
'task-6': '产品功能评估',
'task-7': '市场调研汇总',
'task-8': '技术趋势监控',
'task-9': '价格策略分析',
'task-10': '客户满意度调查',
'task-11': '供应商评估',
'task-12': '财务数据整理'
};
taskTitle = taskTitleMap[taskId] || '未知任务';
console.warn('使用备用方法获取任务标题:', taskId, taskTitle);
}
if (!taskTitle) {
console.error('无法获取任务标题:', taskId);
return;
}
// 添加收缩动画类
taskCard.classList.add('task-card-shrinking');
// 延迟执行切换动画
setTimeout(() => {
// 切换到侧边栏模式
switchToTaskSidebarMode(taskId, taskTitle);
// 移除收缩动画类
taskCard.classList.remove('task-card-shrinking');
}, 300);
}
function switchToTaskSidebarMode(taskId, taskTitle) {
const taskViewerContainer = document.getElementById('task-viewer-container');
const taskListMode = document.getElementById('task-list-mode');
const taskSidebarMode = document.getElementById('task-sidebar-mode');
const taskSidebarTitle = document.getElementById('task-sidebar-title');
const taskSidebarList = document.getElementById('task-sidebar-list');
const taskReportsContent = document.getElementById('task-reports-content');
if (!taskViewerContainer || !taskListMode || !taskSidebarMode) {
console.error('未找到任务查看器元素');
return;
}
// 设置任务标题
taskSidebarTitle.textContent = taskTitle;
// 生成任务列表
generateTaskSidebarList(taskSidebarList, taskId);
// 加载任务报告
loadTaskReports(taskId, taskReportsContent);
// 切换显示模式
taskViewerContainer.classList.remove('task-viewer-list-mode');
taskViewerContainer.classList.add('task-viewer-sidebar-mode');
taskListMode.classList.add('hidden');
taskSidebarMode.classList.remove('hidden');
// 添加侧边栏项出现动画
setTimeout(() => {
const sidebarItems = taskSidebarList.querySelectorAll('.task-list-item-compact');
sidebarItems.forEach((item, index) => {
setTimeout(() => {
item.classList.add('task-sidebar-item-appearing');
}, index * 100);
});
}, 100);
}
function generateTaskSidebarList(container, currentTaskId) {
const tasks = [
{ id: 'task-1', title: '客户需求分析', status: '运行中' },
{ id: 'task-2', title: '竞品动态监控', status: '暂停' },
{ id: 'task-3', title: '行业资讯汇总', status: '生成中' },
{ id: 'task-4', title: '销售数据分析', status: '异常' },
{ id: 'task-5', title: '用户行为分析', status: '运行中' },
{ id: 'task-6', title: '产品功能评估', status: '已完成' },
{ id: 'task-7', title: '市场调研汇总', status: '运行中' },
{ id: 'task-8', title: '技术趋势监控', status: '运行中' },
{ id: 'task-9', title: '价格策略分析', status: '运行中' },
{ id: 'task-10', title: '客户满意度调查', status: '已完成' },
{ id: 'task-11', title: '供应商评估', status: '运行中' },
{ id: 'task-12', title: '财务数据整理', status: '运行中' }
];
container.innerHTML = '';
tasks.forEach(task => {
const taskItem = document.createElement('div');
taskItem.className = `task-list-item-compact ${task.id === currentTaskId ? 'active' : ''}`;
taskItem.innerHTML = `
<h4 class="font-medium text-sm mb-1">${task.title}</h4>
<p class="text-xs text-gray-500">${task.status}</p>
`;
taskItem.onclick = () => selectTaskInSidebar(task.id, task.title);
container.appendChild(taskItem);
});
}
function selectTaskInSidebar(taskId, taskTitle) {
// 更新活动状态
const taskItems = document.querySelectorAll('.task-list-item-compact');
taskItems.forEach(item => item.classList.remove('active'));
const currentItem = document.querySelector(`[onclick*="${taskId}"]`);
if (currentItem) {
currentItem.classList.add('active');
}
// 更新标题
document.getElementById('task-sidebar-title').textContent = taskTitle;
// 加载新的任务报告
const taskReportsContent = document.getElementById('task-reports-content');
loadTaskReports(taskId, taskReportsContent);
}
function loadTaskReports(taskId, container) {
// 使用统一的报告数据获取函数
const reports = getTaskReports(taskId);
container.innerHTML = '';
reports.forEach((report, index) => {
const messageItem = document.createElement('div');
messageItem.className = 'message-item';
messageItem.innerHTML = `
<div class="message-header">
<div class="message-avatar">AI</div>
<div class="message-meta">
<div class="message-title">${report.title}</div>
<div class="message-time">${report.time}</div>
</div>
</div>
<div class="message-content">${report.content}</div>
`;
// 添加点击事件
messageItem.onclick = () => {
openReportDrawer(report, taskId);
};
container.appendChild(messageItem);
});
}
function closeTaskSidebar() {
const taskViewerContainer = document.getElementById('task-viewer-container');
const taskListMode = document.getElementById('task-list-mode');
const taskSidebarMode = document.getElementById('task-sidebar-mode');
if (!taskViewerContainer || !taskListMode || !taskSidebarMode) {
console.error('未找到任务查看器元素');
return;
}
// 切换回列表模式
taskViewerContainer.classList.remove('task-viewer-sidebar-mode');
taskViewerContainer.classList.add('task-viewer-list-mode');
taskSidebarMode.classList.add('hidden');
taskListMode.classList.remove('hidden');
}
// 报告抽屉相关函数
let currentReport = null;
let currentTaskId = null;
let currentReportList = [];
let currentReportIndex = 0;
function openReportDrawer(report, taskId) {
console.log('打开报告抽屉:', report.title);
currentReport = report;
currentTaskId = taskId;
// 获取当前任务的所有报告列表
currentReportList = getTaskReports(taskId);
currentReportIndex = currentReportList.findIndex(r => r.title === report.title);
// 获取任务标题
const taskTitleMap = {
'task-1': '客户需求分析',
'task-2': '竞品动态监控',
'task-3': '行业资讯汇总',
'task-4': '销售数据分析',
'task-5': '用户行为分析',
'task-6': '产品功能评估',
'task-7': '市场调研汇总',
'task-8': '技术趋势监控',
'task-9': '价格策略分析',
'task-10': '客户满意度调查',
'task-11': '供应商评估',
'task-12': '财务数据整理'
};
const taskTitle = taskTitleMap[taskId] || '未知任务';
// 更新抽屉标题和元信息
document.getElementById('drawer-title').textContent = report.title;
document.getElementById('drawer-meta').innerHTML = `
<div class="flex items-center gap-4">
<span>📅 ${report.time}</span>
<span>👤 来自 "${taskTitle}" 任务</span>
</div>
`;
// 加载报告详情内容
loadReportDetailContent(report, taskId);
// 更新导航按钮状态
updateNavigationButtons();
// 显示抽屉
const drawer = document.getElementById('report-drawer');
const overlay = document.getElementById('drawer-overlay');
drawer.classList.add('open');
overlay.classList.add('show');
}
function closeReportDrawer() {
const drawer = document.getElementById('report-drawer');
const overlay = document.getElementById('drawer-overlay');
drawer.classList.remove('open');
overlay.classList.remove('show');
currentReport = null;
currentTaskId = null;
currentReportList = [];
currentReportIndex = 0;
}
function getTaskReports(taskId) {
// 任务报告数据
const taskReportsData = {
'task-1': [
{
title: '客户需求分析报告',
time: '2024-01-15 09:00',
content: '根据最新的客户反馈数据我们发现用户对产品响应速度的关注度提升了15%。建议优化产品加载时间,重点关注移动端用户体验。'
},
{
title: '客户满意度调研',
time: '2024-01-14 09:00',
content: '本月客户满意度调研显示整体满意度为8.2分满分10分较上月提升0.3分。主要改进点在于客服响应速度和产品质量。'
}
],
'task-2': [
{
title: '竞品动态监控报告',
time: '2024-01-15 10:00',
content: '主要竞争对手发布了新版本产品新增了AI智能推荐功能。建议我们加快相关功能的开发进度保持竞争优势。'
},
{
title: '竞品价格分析',
time: '2024-01-14 10:00',
content: '竞品价格策略分析显示同类产品平均价格下降了8%。建议重新评估我们的定价策略,考虑推出更具竞争力的套餐。'
}
],
'task-3': [
{
title: '行业资讯汇总',
time: '2024-01-15 08:00',
content: '本周行业动态显示人工智能在垂直领域的应用正在加速。建议关注AI+行业解决方案的发展趋势,提前布局相关技术。'
}
],
'task-4': [
{
title: '销售数据分析报告',
time: '2024-01-15 18:00',
content: '本月销售数据显示新客户获取成本较上月上升12%但客户生命周期价值提升了8%。建议优化获客渠道,提高转化效率。'
}
]
};
return taskReportsData[taskId] || [
{
title: '任务执行报告',
time: '2024-01-15 12:00',
content: '任务执行正常,数据收集完整,分析结果准确。建议继续按照当前策略执行。'
}
];
}
function updateNavigationButtons() {
const prevBtn = document.getElementById('prev-report-btn');
const nextBtn = document.getElementById('next-report-btn');
const counter = document.getElementById('report-counter');
// 更新按钮状态
prevBtn.disabled = currentReportIndex <= 0;
nextBtn.disabled = currentReportIndex >= currentReportList.length - 1;
// 更新计数器
counter.textContent = `${currentReportIndex + 1} / ${currentReportList.length}`;
}
function navigateToPreviousReport() {
if (currentReportIndex > 0) {
currentReportIndex--;
const report = currentReportList[currentReportIndex];
currentReport = report;
// 更新抽屉内容
updateDrawerContent(report);
updateNavigationButtons();
}
}
function navigateToNextReport() {
if (currentReportIndex < currentReportList.length - 1) {
currentReportIndex++;
const report = currentReportList[currentReportIndex];
currentReport = report;
// 更新抽屉内容
updateDrawerContent(report);
updateNavigationButtons();
}
}
function updateDrawerContent(report) {
// 更新标题和元信息
document.getElementById('drawer-title').textContent = report.title;
// 获取任务标题
const taskTitleMap = {
'task-1': '客户需求分析',
'task-2': '竞品动态监控',
'task-3': '行业资讯汇总',
'task-4': '销售数据分析',
'task-5': '用户行为分析',
'task-6': '产品功能评估',
'task-7': '市场调研汇总',
'task-8': '技术趋势监控',
'task-9': '价格策略分析',
'task-10': '客户满意度调查',
'task-11': '供应商评估',
'task-12': '财务数据整理'
};
const taskTitle = taskTitleMap[currentTaskId] || '未知任务';
document.getElementById('drawer-meta').innerHTML = `
<div class="flex items-center gap-4">
<span>📅 ${report.time}</span>
<span>👤 来自 "${taskTitle}" 任务</span>
</div>
`;
// 更新内容
loadReportDetailContent(report, currentTaskId);
}
function loadReportDetailContent(report, taskId) {
const contentContainer = document.getElementById('drawer-content');
// 获取详细的报告内容
const reportDetails = getReportDetailData(report.title, taskId);
contentContainer.innerHTML = `
<div class="space-y-6">
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
<h3 class="text-lg font-semibold text-blue-900 mb-2">执行摘要</h3>
<p class="text-blue-800">${report.content}</p>
</div>
<div>
<h3 class="text-lg font-semibold text-gray-900 mb-3">详细分析</h3>
<div class="space-y-4">
${reportDetails.details.map(detail => `
<div class="border-l-4 border-gray-300 pl-4">
<h4 class="font-medium text-gray-900 mb-1">${detail.title}</h4>
<p class="text-gray-700 text-sm">${detail.content}</p>
</div>
`).join('')}
</div>
</div>
<div class="bg-gray-50 rounded-lg p-4">
<h3 class="text-lg font-semibold text-gray-900 mb-3">关键指标</h3>
<div class="grid grid-cols-2 gap-4">
${reportDetails.metrics.map(metric => `
<div class="text-center">
<div class="text-2xl font-bold text-blue-600">${metric.value}</div>
<div class="text-sm text-gray-600">${metric.label}</div>
</div>
`).join('')}
</div>
</div>
<div>
<h3 class="text-lg font-semibold text-gray-900 mb-3">建议措施</h3>
<div class="space-y-2">
${reportDetails.recommendations.map(rec => `
<div class="flex items-start gap-2">
<div class="w-2 h-2 bg-blue-500 rounded-full mt-2 flex-shrink-0"></div>
<p class="text-gray-700 text-sm">${rec}</p>
</div>
`).join('')}
</div>
</div>
</div>
`;
}
function getReportDetailData(reportTitle, taskId) {
// 根据报告标题和任务ID返回详细数据
const detailData = {
'客户需求分析报告': {
details: [
{ title: '用户反馈分析', content: '通过分析用户反馈数据发现85%的反馈集中在产品易用性方面用户对响应速度的关注度提升了15%。' },
{ title: '满意度调研', content: '本月客户满意度调研显示整体满意度为8.2分满分10分较上月提升0.3分。' }
],
metrics: [
{ value: '85%', label: '易用性反馈' },
{ value: '8.2', label: '满意度评分' },
{ value: '+15%', label: '关注度提升' },
{ value: '+0.3', label: '满意度提升' }
],
recommendations: [
'优化产品加载时间,重点关注移动端用户体验',
'提升客服响应速度,改善服务质量',
'建立持续改进机制,定期收集用户反馈',
'加强产品质量控制,减少用户投诉'
]
},
'竞品动态监控报告': {
details: [
{ title: '竞品产品更新', content: '主要竞争对手发布了新版本产品新增了AI智能推荐功能功能更加完善。' },
{ title: '价格策略分析', content: '竞品价格策略分析显示同类产品平均价格下降了8%,市场竞争加剧。' }
],
metrics: [
{ value: '8%', label: '价格下降' },
{ value: '3', label: '主要竞品' },
{ value: 'AI', label: '新功能' },
{ value: '15%', label: '市场变化' }
],
recommendations: [
'加快AI智能推荐功能的开发进度',
'重新评估定价策略,推出更具竞争力的套餐',
'加强产品差异化,突出核心优势',
'密切关注竞品动态,及时调整策略'
]
},
'行业资讯汇总': {
details: [
{ title: '技术趋势', content: '人工智能在垂直领域的应用正在加速AI+行业解决方案成为新的增长点。' },
{ title: '市场动态', content: '行业整体呈现数字化转型趋势,企业对智能化解决方案需求增加。' }
],
metrics: [
{ value: '25%', label: 'AI应用增长' },
{ value: '60%', label: '数字化转型' },
{ value: '12', label: '新兴技术' },
{ value: '8%', label: '市场增长率' }
],
recommendations: [
'关注AI+行业解决方案的发展趋势',
'提前布局相关技术,抢占市场先机',
'加强与技术公司的合作,提升技术实力',
'制定数字化转型战略,适应市场变化'
]
},
'销售数据分析报告': {
details: [
{ title: '获客成本分析', content: '本月新客户获取成本较上月上升12%,主要原因是市场竞争加剧和广告成本上涨。' },
{ title: '客户价值分析', content: '客户生命周期价值提升了8%,说明客户粘性和满意度有所改善。' }
],
metrics: [
{ value: '+12%', label: '获客成本' },
{ value: '+8%', label: '客户价值' },
{ value: '85%', label: '转化率' },
{ value: '3.2', label: 'ROI' }
],
recommendations: [
'优化获客渠道,提高转化效率',
'加强客户关系管理,提升客户价值',
'控制营销成本提高ROI',
'建立客户推荐机制,降低获客成本'
]
}
};
return detailData[reportTitle] || {
details: [
{ title: '执行情况', content: '任务执行正常,数据收集完整,分析结果准确。' },
{ title: '结果评估', content: '各项指标表现良好,建议继续按照当前策略执行。' }
],
metrics: [
{ value: '100%', label: '完成率' },
{ value: '95%', label: '准确率' },
{ value: '8.5', label: '质量评分' },
{ value: '24h', label: '响应时间' }
],
recommendations: [
'继续按照当前策略执行',
'定期监控关键指标变化',
'及时调整执行方案',
'保持数据收集的完整性'
]
};
}
function downloadReport() {
if (!currentReport) {
console.error('没有选中的报告');
return;
}
console.log('下载报告:', currentReport.title);
// 模拟下载功能
const content = `
报告标题: ${currentReport.title}
生成时间: ${currentReport.time}
任务来源: ${currentTaskId}
执行摘要:
${currentReport.content}
详细内容请查看系统内的完整报告。
`;
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${currentReport.title}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
// 显示下载成功提示
showNotification('报告下载成功', 'success');
}
function archiveReport() {
if (!currentReport) {
console.error('没有选中的报告');
return;
}
console.log('归档报告:', currentReport.title);
// 模拟归档功能
showNotification('报告已归档', 'success');
// 关闭抽屉
closeReportDrawer();
}
// 为所有任务卡片添加查看报告按钮
function addViewReportButtonsToTaskCards() {
const taskCards = document.querySelectorAll('.task-card');
taskCards.forEach(card => {
// 检查是否已经有查看报告按钮
if (card.querySelector('.view-report-btn')) {
return;
}
// 获取任务ID
const taskId = card.getAttribute('onclick')?.match(/openTaskReports\('([^']+)'\)/)?.[1];
if (taskId) {
// 为任务卡片添加data-task-id属性方便查找
card.setAttribute('data-task-id', taskId);
// 移除原有的onclick事件和cursor-pointer类
card.removeAttribute('onclick');
card.classList.remove('cursor-pointer');
// 获取卡片的主题色
const bgClass = card.className.match(/from-(\w+)-50/)?.[1] || 'blue';
// 创建查看报告按钮
const button = document.createElement('button');
button.className = `view-report-btn w-full bg-${bgClass}-600 hover:bg-${bgClass}-700 text-white text-xs font-medium py-1 px-3 rounded-md transition-colors duration-200 flex items-center justify-center gap-1`;
button.innerHTML = `
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
查看报告
`;
button.onclick = (e) => {
e.stopPropagation();
openTaskReports(taskId);
};
// 在卡片底部添加按钮
card.appendChild(button);
// 为最后一个状态div添加mb-2类紧凑间距
const statusDiv = card.querySelector('div:last-of-type:not(.view-report-btn)');
if (statusDiv) {
statusDiv.classList.add('mb-2');
}
}
});
}
function openUnifiedReportView(reportId = 'report-1', sourceElement = null) {
const reportViewerContainer = document.getElementById('report-viewer-container');
const reportListMode = document.getElementById('report-list-mode');
const reportSidebarMode = document.getElementById('report-sidebar-mode');
if (reportViewerContainer && reportListMode && reportSidebarMode) {
// 第一阶段:所有报告卡片收缩
const allReportCards = reportListMode.querySelectorAll('.report-card');
allReportCards.forEach((card, index) => {
setTimeout(() => {
card.classList.add('report-card-shrinking');
}, index * 50);
});
// 第二阶段:切换到侧边栏模式
setTimeout(() => {
// 隐藏列表模式,显示侧边栏模式
reportListMode.classList.add('hidden');
reportSidebarMode.classList.remove('hidden');
// 切换容器模式
reportViewerContainer.classList.remove('report-viewer-list-mode');
reportViewerContainer.classList.add('report-viewer-sidebar-mode');
// 隐藏底部翻页按钮
const reportPagination = document.querySelector('#report-prev-btn')?.parentElement;
if (reportPagination) {
reportPagination.style.display = 'none';
}
// 选择报告
selectReportInSidebar(reportId);
// 侧边栏项目逐个出现
const sidebarItems = reportSidebarMode.querySelectorAll('.report-list-item-compact');
sidebarItems.forEach((item, index) => {
setTimeout(() => {
item.classList.add('sidebar-item-appearing');
}, index * 80);
});
}, 400);
// 第三阶段:清理动画类
setTimeout(() => {
allReportCards.forEach(card => {
card.classList.remove('report-card-shrinking');
});
const sidebarItems = reportSidebarMode.querySelectorAll('.report-list-item-compact');
sidebarItems.forEach(item => {
item.classList.remove('sidebar-item-appearing');
});
}, 1000);
}
}
function closeUnifiedReportView() {
const reportContainer = document.getElementById('unified-report-view');
if (reportContainer) {
// 添加关闭动画
reportContainer.style.transform = 'translateX(100%)';
reportContainer.style.opacity = '0';
setTimeout(() => {
reportContainer.classList.add('hidden');
// 重置样式
reportContainer.style.transform = '';
reportContainer.style.opacity = '';
// 清理所有动画类
const reportListItems = document.querySelectorAll('.report-list-item');
reportListItems.forEach(item => {
item.classList.remove('report-list-item-entering', 'report-list-item-morphing');
item.style.animationDelay = '';
});
// 清理报告卡片的动画类
const reportCards = document.querySelectorAll('.report-card');
reportCards.forEach(card => {
card.classList.remove('report-cards-shrinking', 'report-card-transitioning');
});
// 清理报告查看器的动画类
reportContainer.classList.remove('report-viewer-entering');
}, 300);
}
}
function selectReportInSidebar(reportId) {
// 移除所有活动状态
const allItems = document.querySelectorAll('.report-list-item-compact');
allItems.forEach(item => {
item.classList.remove('active');
});
// 激活选中的项目
const selectedItem = document.querySelector(`[data-report-id="${reportId}"]`);
if (selectedItem) {
selectedItem.classList.add('active');
}
// 加载报告详情
loadReportDetail(reportId);
}
function closeReportSidebar() {
const reportViewerContainer = document.getElementById('report-viewer-container');
const reportListMode = document.getElementById('report-list-mode');
const reportSidebarMode = document.getElementById('report-sidebar-mode');
if (reportViewerContainer && reportListMode && reportSidebarMode) {
// 切换回列表模式
reportSidebarMode.classList.add('hidden');
reportListMode.classList.remove('hidden');
// 切换容器模式
reportViewerContainer.classList.remove('report-viewer-sidebar-mode');
reportViewerContainer.classList.add('report-viewer-list-mode');
// 显示底部翻页按钮
const reportPagination = document.querySelector('#report-prev-btn')?.parentElement;
if (reportPagination) {
reportPagination.style.display = 'flex';
}
}
}
function loadReportDetail(reportId) {
const detailContent = document.getElementById('report-detail-content');
if (!detailContent) return;
// 报告详情数据
const reportDetails = {
'report-1': {
title: '客户需求分析报告',
date: '2025.09.07 09:00',
summary: '基于客户反馈数据的深度分析识别关键需求趋势和改进机会',
content: `
<div class="space-y-6">
<div>
<h2 class="text-2xl font-bold text-gray-900 mb-4">客户需求分析报告</h2>
<div class="flex items-center gap-4 text-sm text-gray-600 mb-6">
<span>📅 2025.09.07 09:00</span>
<span>📊 1.2MB</span>
<span>👤 来自 "客户需求分析" 任务</span>
</div>
</div>
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
<h3 class="text-lg font-semibold text-blue-900 mb-2">核心发现</h3>
<p class="text-blue-800">85%的客户反馈集中在产品易用性需求,其中导航优化和界面简化是最受关注的问题。</p>
</div>
<div>
<h3 class="text-lg font-semibold text-gray-900 mb-3">详细分析</h3>
<div class="space-y-4">
<div class="border-l-4 border-blue-500 pl-4">
<h4 class="font-medium text-gray-900">用户痛点识别</h4>
<p class="text-gray-600 mt-1">通过分析2,500+用户反馈,识别出三大核心痛点:操作流程复杂、功能查找困难、响应速度慢。</p>
</div>
<div class="border-l-4 border-green-500 pl-4">
<h4 class="font-medium text-gray-900">需求优先级排序</h4>
<p class="text-gray-600 mt-1">基于影响范围和实现难度,将需求分为高、中、低三个优先级,为产品迭代提供明确方向。</p>
</div>
<div class="border-l-4 border-purple-500 pl-4">
<h4 class="font-medium text-gray-900">改进建议</h4>
<p class="text-gray-600 mt-1">提出12项具体改进建议预计可提升用户满意度23%减少客户流失率15%。</p>
</div>
</div>
</div>
<div class="bg-gray-50 rounded-lg p-4">
<h3 class="text-lg font-semibold text-gray-900 mb-3">数据统计</h3>
<div class="grid grid-cols-3 gap-4">
<div class="text-center">
<div class="text-2xl font-bold text-blue-600">2,500+</div>
<div class="text-sm text-gray-600">用户反馈</div>
</div>
<div class="text-center">
<div class="text-2xl font-bold text-green-600">85%</div>
<div class="text-sm text-gray-600">易用性关注度</div>
</div>
<div class="text-center">
<div class="text-2xl font-bold text-purple-600">12</div>
<div class="text-sm text-gray-600">改进建议</div>
</div>
</div>
</div>
</div>
`
},
'report-2': {
title: '销售策略优化报告',
date: '2025.09.07 11:30',
summary: '销售数据分析报告提供策略优化建议和话术改进方案',
content: `
<div class="space-y-6">
<div>
<h2 class="text-2xl font-bold text-gray-900 mb-4">销售策略优化报告</h2>
<div class="flex items-center gap-4 text-sm text-gray-600 mb-6">
<span>📅 2025.09.07 11:30</span>
<span>📊 950KB</span>
<span>👤 来自 "销售数据分析" 任务</span>
</div>
</div>
<div class="bg-green-50 border border-green-200 rounded-lg p-4">
<h3 class="text-lg font-semibold text-green-900 mb-2">关键成果</h3>
<p class="text-green-800">Q3销售转化率较Q2提升12%客户获取成本降低18%销售周期缩短25%。</p>
</div>
<div>
<h3 class="text-lg font-semibold text-gray-900 mb-3">策略分析</h3>
<div class="space-y-4">
<div class="border-l-4 border-green-500 pl-4">
<h4 class="font-medium text-gray-900">转化率优化</h4>
<p class="text-gray-600 mt-1">通过优化销售流程和话术将潜在客户转化率从15%提升至27%。</p>
</div>
<div class="border-l-4 border-blue-500 pl-4">
<h4 class="font-medium text-gray-900">客户获取成本</h4>
<p class="text-gray-600 mt-1">通过精准定位和渠道优化,客户获取成本从$120降至$98。</p>
</div>
<div class="border-l-4 border-purple-500 pl-4">
<h4 class="font-medium text-gray-900">销售周期</h4>
<p class="text-gray-600 mt-1">平均销售周期从45天缩短至34天效率提升显著。</p>
</div>
</div>
</div>
</div>
`
}
};
const report = reportDetails[reportId] || reportDetails['report-1'];
detailContent.innerHTML = report.content;
}
function selectUnifiedReport(reportId, showAnimation = true) {
// 更新左侧列表选中状态
document.querySelectorAll('.report-list-item').forEach(item => {
item.classList.remove('border-blue-500', 'bg-blue-50');
item.classList.add('border-gray-200');
});
const selectedItem = document.querySelector(`[data-report-id="${reportId}"]`);
if (selectedItem) {
selectedItem.classList.remove('border-gray-200');
selectedItem.classList.add('border-blue-500', 'bg-blue-50');
}
// 更新右侧报告内容
updateUnifiedReportContent(reportId);
}
function updateUnifiedReportContent(reportId) {
const reportTitle = document.getElementById('unified-report-title');
const reportMeta = document.getElementById('unified-report-meta');
const reportContent = document.getElementById('unified-report-content');
const unifiedReports = {
'report-1': {
title: '客户需求分析报告',
meta: '今日 09:00 客户反馈分析任务 1.2MB',
content: `
<h2>执行摘要</h2>
<p>基于对今日收集的客户反馈数据的深度分析,我们识别出以下关键发现和建议...</p>
<h2>关键发现</h2>
<h3>1. 客户需求趋势</h3>
<ul>
<li>个性化功能需求增长35%</li>
<li>移动端体验关注度提升28%</li>
<li>集成能力要求增加42%</li>
</ul>
<h3>2. 痛点分析</h3>
<ul>
<li>产品学习成本过高68%客户反馈)</li>
<li>响应速度需要改进45%客户反馈)</li>
<li>客服支持时间不够灵活32%客户反馈)</li>
</ul>
<h2>改进建议</h2>
<h3>短期建议1-3个月</h3>
<ol>
<li>优化产品界面,降低学习成本</li>
<li>改进系统响应速度</li>
<li>扩展客服支持时间</li>
</ol>
`
},
'report-2': {
title: '销售策略优化报告',
meta: '今日 11:30 销售数据分析任务 950KB',
content: `
<h2>执行摘要</h2>
<p>通过对销售数据的深度分析,我们发现了提升销售效率的关键机会点...</p>
<h2>销售表现分析</h2>
<h3>1. 转化率分析</h3>
<ul>
<li>线上渠道转化率12.5%+2.3%</li>
<li>线下渠道转化率8.7%-1.2%</li>
<li>电话销售转化率15.2%+3.1%</li>
</ul>
`
},
'report-3': {
title: '市场机会洞察报告',
meta: '今日 14:20 行业趋势分析任务 1.5MB',
content: `
<h2>执行摘要</h2>
<p>基于行业趋势分析我们识别出中小企业AI应用市场的巨大机会...</p>
<h2>市场趋势</h2>
<h3>1. 市场规模</h3>
<ul>
<li>中小企业AI市场规模¥1,250亿+35%</li>
<li>预计3年复合增长率42%</li>
<li>我们当前市场份额2.3%</li>
</ul>
`
},
'report-4': {
title: '竞品动态监控报告',
meta: '今日 16:00 竞品监控任务 800KB',
content: `
<h2>执行摘要</h2>
<p>本周竞品动态监控显示,主要竞争对手在产品功能和定价策略方面有重要调整...</p>
<h2>竞品动态</h2>
<h3>1. 产品功能更新</h3>
<ul>
<li>OpenAI发布GPT-4 Turbo处理速度提升40%</li>
<li>百度:文心一言新增多模态能力</li>
<li>阿里云通义千问降价30%</li>
</ul>
`
},
'report-5': {
title: '用户行为分析报告',
meta: '今日 18:30 用户行为分析任务 1.1MB',
content: `
<h2>执行摘要</h2>
<p>通过分析用户行为数据,我们发现用户使用习惯正在发生显著变化...</p>
<h2>用户行为洞察</h2>
<h3>1. 使用习惯变化</h3>
<ul>
<li>移动端使用率提升至68%</li>
<li>平均会话时长增加15分钟</li>
<li>多任务并行使用增长45%</li>
</ul>
`
},
'report-6': {
title: '风险评估报告',
meta: '昨日 22:00 风险评估任务 1.3MB',
content: `
<h2>执行摘要</h2>
<p>本次风险评估覆盖市场、技术、运营三个维度,识别出需要重点关注的风险点...</p>
<h2>风险分析</h2>
<h3>1. 市场风险</h3>
<ul>
<li>竞争加剧导致利润率下降(高风险)</li>
<li>客户需求变化过快(中风险)</li>
<li>新兴技术颠覆现有模式(中风险)</li>
</ul>
`
},
'report-7': {
title: '产品功能评估报告',
meta: '昨日 16:00 产品功能评估任务 850KB',
content: `
<h2>执行摘要</h2>
<p>本周产品功能使用情况分析显示,核心功能使用率稳步提升,但部分新功能采用率较低...</p>
<h2>功能使用分析</h2>
<h3>1. 核心功能表现</h3>
<ul>
<li>数据分析功能使用率89%+5%</li>
<li>报告生成功能使用率76%+3%</li>
<li>协作功能使用率63%+8%</li>
</ul>
<h3>2. 新功能采用情况</h3>
<ul>
<li>AI助手功能32%(需要改进)</li>
<li>自动化流程45%(正常范围)</li>
<li>移动端功能58%(超预期)</li>
</ul>
<h2>改进建议</h2>
<ol>
<li>加强AI助手功能的用户引导</li>
<li>优化自动化流程的设置流程</li>
<li>继续投资移动端功能开发</li>
</ol>
`
},
'report-8': {
title: '市场调研汇总报告',
meta: '本月15日 14:00 市场调研任务 2.1MB',
content: `
<h2>执行摘要</h2>
<p>本月市场调研覆盖三个重点行业收集了500+企业的反馈数据,发现市场需求的新趋势...</p>
<h2>市场洞察</h2>
<h3>1. 行业需求分析</h3>
<ul>
<li>制造业自动化程度要求提升40%</li>
<li>零售业个性化服务需求增长60%</li>
<li>金融业:合规性要求更加严格</li>
</ul>
<h3>2. 竞争格局</h3>
<ul>
<li>新进入者增加25%</li>
<li>价格竞争加剧</li>
<li>技术差异化成为关键</li>
</ul>
`
},
'report-9': {
title: '技术趋势监控报告',
meta: '今日 20:00 技术趋势监控任务 1.8MB',
content: `
<h2>执行摘要</h2>
<p>通过监控技术发展趋势,我们识别出可能影响业务的关键技术变化...</p>
<h2>技术趋势分析</h2>
<h3>1. 新兴技术</h3>
<ul>
<li>大语言模型技术突破</li>
<li>边缘计算普及率提升</li>
<li>量子计算商用化加速</li>
</ul>
<h3>2. 技术影响评估</h3>
<ul>
<li>对现有产品架构的冲击:中等</li>
<li>客户期望变化:显著</li>
<li>竞争格局改变:可能</li>
</ul>
`
},
'report-10': {
title: '价格策略分析报告',
meta: '今日 09:00 价格策略分析任务 750KB',
content: `
<h2>执行摘要</h2>
<p>本周价格策略效果分析显示,调整后的定价策略在提升利润率的同时保持了市场竞争力...</p>
<h2>定价效果分析</h2>
<h3>1. 收入影响</h3>
<ul>
<li>总收入增长12%</li>
<li>平均单价提升8%</li>
<li>客户流失率控制在3%以内</li>
</ul>
<h3>2. 市场反应</h3>
<ul>
<li>高端客户接受度85%</li>
<li>中端客户接受度68%</li>
<li>低端客户接受度45%</li>
</ul>
`
},
'report-11': {
title: '客户满意度调查报告',
meta: '本季度 客户满意度调查任务 1.6MB',
content: `
<h2>执行摘要</h2>
<p>本季度客户满意度调查收到2000+份有效反馈,整体满意度较上季度有所提升...</p>
<h2>满意度分析</h2>
<h3>1. 整体满意度</h3>
<ul>
<li>综合满意度8.2/10+0.4</li>
<li>产品满意度8.5/10+0.3</li>
<li>服务满意度7.9/10+0.5</li>
</ul>
<h3>2. 改进领域</h3>
<ul>
<li>响应速度:需要提升</li>
<li>功能完善:持续改进</li>
<li>价格合理性:需要优化</li>
</ul>
`
},
'report-12': {
title: '供应商评估报告',
meta: '半年评估 供应商评估任务 1.4MB',
content: `
<h2>执行摘要</h2>
<p>本次供应商评估覆盖12家核心供应商从质量、交付、成本、服务四个维度进行评估...</p>
<h2>评估结果</h2>
<h3>1. 优秀供应商3家</h3>
<ul>
<li>质量稳定,交付及时</li>
<li>成本控制良好</li>
<li>服务响应快速</li>
</ul>
<h3>2. 需要改进供应商4家</h3>
<ul>
<li>交付时间不稳定</li>
<li>质量控制需要加强</li>
<li>沟通效率有待提升</li>
</ul>
`
},
'report-13': {
title: '财务数据整理报告',
meta: '月底 财务数据整理任务 2.3MB',
content: `
<h2>执行摘要</h2>
<p>本月财务数据整理完成,收入、成本、利润等关键指标均符合预期...</p>
<h2>财务概览</h2>
<h3>1. 收入分析</h3>
<ul>
<li>总收入同比增长15%</li>
<li>核心业务收入增长18%</li>
<li>新业务收入增长35%</li>
</ul>
<h3>2. 成本控制</h3>
<ul>
<li>运营成本:控制在预算内</li>
<li>研发投入:按计划执行</li>
<li>市场费用效率提升12%</li>
</ul>
`
}
};
if (unifiedReports[reportId] && reportTitle && reportMeta && reportContent) {
reportTitle.textContent = unifiedReports[reportId].title;
reportMeta.textContent = unifiedReports[reportId].meta;
reportContent.innerHTML = unifiedReports[reportId].content;
}
}
function generateTodaySummary() {
showNotification('正在生成今日总结请稍候...');
setTimeout(() => {
showNotification('今日总结已生成');
}, 2000);
}
function toggleExpandedTasks() {
const expandedTasks = document.getElementById('expanded-tasks');
const expandBtn = document.getElementById('expand-tasks');
const expandIcon = document.querySelector('#expand-tasks .expand-icon');
const expandBtnContainer = expandBtn ? expandBtn.parentElement : null;
if (expandedTasks && expandBtn && expandIcon && expandBtnContainer) {
if (expandedTasks.classList.contains('hidden')) {
// 展开任务列表
expandedTasks.classList.remove('hidden');
expandIcon.style.transform = 'rotate(180deg)';
// 隐藏中间的展开按钮
expandBtnContainer.classList.add('hidden');
// 重置到第一页
currentTaskPage = 1;
updateTaskPagination();
} else {
// 收起任务列表
expandedTasks.classList.add('hidden');
expandIcon.style.transform = 'rotate(0deg)';
// 显示中间的展开按钮
expandBtnContainer.classList.remove('hidden');
// 恢复按钮文本
expandBtn.childNodes.forEach(node => {
if (node.nodeType === Node.TEXT_NODE && node.textContent.trim()) {
node.textContent = '查看更多任务';
}
});
}
}
}
// 任务翻页相关变量和函数
let currentTaskPage = 1;
const totalTaskPages = 3;
window.switchTaskPage = function(direction) {
if (direction === 'next' && currentTaskPage < totalTaskPages) {
currentTaskPage++;
} else if (direction === 'prev' && currentTaskPage > 1) {
currentTaskPage--;
}
updateTaskPagination();
};
function updateTaskPagination() {
// 任务页面元素
const page1 = document.getElementById('task-cards-grid');
const page2 = document.getElementById('task-page-2');
const page3 = document.getElementById('task-page-3');
// 控制元素
const indicator = document.getElementById('task-page-indicator');
const prevBtn = document.getElementById('task-prev-btn');
const nextBtn = document.getElementById('task-next-btn');
// 默认显示所有页面(三行)
if (page1) page1.classList.remove('hidden');
if (page2) page2.classList.remove('hidden');
if (page3) page3.classList.remove('hidden');
// 更新按钮状态(翻页器仍然可用,但所有页面都显示)
if (prevBtn) {
prevBtn.disabled = currentTaskPage === 1;
}
if (nextBtn) {
nextBtn.disabled = currentTaskPage === totalTaskPages;
}
// 更新页面指示器
if (indicator) {
indicator.textContent = `${currentTaskPage} / ${totalTaskPages}`;
}
}
function showNotification(message) {
const notification = document.createElement('div');
notification.className = 'fixed top-4 right-4 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg z-50';
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 3000);
}
// 基础函数
function showStartPage() {
console.log('显示主页');
}
function openRecentChat(chat) {
console.log('打开聊天:', chat);
}
// 响应式侧边栏控制
document.addEventListener('DOMContentLoaded', function() {
const sidebar = document.getElementById('sidebar');
const mobileMenuToggle = document.getElementById('mobile-menu-toggle');
const sidebarToggle = document.getElementById('sidebar-toggle');
// 设置智能体菜单为激活状态
const agentMenuItem = document.querySelector('a[href="清研智参谋-新版.html"]').closest('.sidebar-item');
if (agentMenuItem) {
agentMenuItem.classList.add('active');
}
// 移动端菜单切换
if (mobileMenuToggle) {
mobileMenuToggle.addEventListener('click', function() {
sidebar.classList.toggle('show');
});
}
// 侧边栏折叠切换
if (sidebarToggle) {
sidebarToggle.addEventListener('click', function() {
sidebar.classList.toggle('sidebar-collapsed');
const mainContent = document.getElementById('main-content');
if (mainContent) {
mainContent.classList.toggle('main-content');
}
});
}
// 点击外部区域关闭移动端侧边栏
document.addEventListener('click', function(e) {
if (window.innerWidth < 1024 &&
!sidebar.contains(e.target) &&
!mobileMenuToggle.contains(e.target)) {
sidebar.classList.remove('show');
}
});
// 绑定任务列表新建任务按钮事件
const tasksNewTaskBtn = document.getElementById('tasks-new-task-btn');
const tasksTaskDropdown = document.getElementById('tasks-task-dropdown');
if (tasksNewTaskBtn) {
tasksNewTaskBtn.addEventListener('click', function(e) {
e.stopPropagation();
console.log('任务列表新建任务按钮被点击');
tasksTaskDropdown.classList.toggle('hidden');
});
}
// 绑定今日报告新建任务按钮事件
const reportsNewTaskBtn = document.getElementById('reports-new-task-btn');
const reportsTaskDropdown = document.getElementById('reports-task-dropdown');
if (reportsNewTaskBtn) {
reportsNewTaskBtn.addEventListener('click', function(e) {
e.stopPropagation();
console.log('今日报告新建任务按钮被点击');
reportsTaskDropdown.classList.toggle('hidden');
});
}
// 点击页面其他地方时关闭所有任务菜单和下拉菜单
document.addEventListener('click', function(e) {
if (!e.target.closest('.task-menu-btn') && !e.target.closest('.task-menu')) {
document.querySelectorAll('.task-menu').forEach(menu => {
menu.classList.add('hidden');
});
}
// 关闭任务下拉菜单
if (!e.target.closest('#tasks-new-task-btn') && !e.target.closest('#tasks-task-dropdown')) {
if (tasksTaskDropdown) {
tasksTaskDropdown.classList.add('hidden');
}
}
if (!e.target.closest('#reports-new-task-btn') && !e.target.closest('#reports-task-dropdown')) {
if (reportsTaskDropdown) {
reportsTaskDropdown.classList.add('hidden');
}
}
});
// 绑定上方主任务导航按钮事件
const mainPrevBtn = document.getElementById('prev-task');
const mainNextBtn = document.getElementById('next-task');
if (mainPrevBtn) {
mainPrevBtn.addEventListener('click', function() {
switchTaskPage('prev');
});
}
if (mainNextBtn) {
mainNextBtn.addEventListener('click', function() {
switchTaskPage('next');
});
}
// 初始化任务分页状态
updateTaskPagination();
});
// 显示任务模态框 - 完整版本从原文件复制
function showTaskModal(type, taskId = null) {
console.log('showTaskModal被调用类型:', type);
const isEdit = type === 'edit';
const taskName = isEdit ? getTaskName(taskId) : '';
const taskSchedule = isEdit ? getTaskSchedule(taskId) : '';
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
modal.innerHTML = `
<div class="bg-white rounded-lg w-full max-w-4xl mx-4 relative">
<!-- 模态框头部 -->
<div class="flex items-center justify-between p-6 border-b border-gray-200">
<div class="flex items-center gap-3">
<h3 class="text-lg font-semibold text-gray-900">${isEdit ? '修改周期任务' : '新建周期任务'}</h3>
</div>
<div class="flex items-center gap-4">
<button class="p-2 hover:bg-gray-100 rounded-lg" onclick="this.closest('.fixed').remove()">
<svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
</div>
<!-- 模态框内容 -->
<div class="p-6 max-h-[70vh] overflow-y-auto">
<form id="task-form">
<!-- 基本信息 -->
<div id="step1-content">
<!-- 执行时间区域 -->
<div class="mb-6 relative">
<div class="flex items-center gap-2 mb-3">
<label class="text-sm font-medium text-gray-700">执行周期</label>
<span class="text-red-500">*</span>
</div>
<div class="grid grid-cols-2 gap-3">
<div class="col-span-1 relative">
<!-- 自定义下拉框 -->
<div id="custom-dropdown" class="w-full px-3 py-2 border border-gray-300 rounded-lg bg-white cursor-pointer hover:border-primary-500 transition-colors">
<div class="flex items-center justify-between">
<span id="selected-text" class="text-sm text-gray-900">${taskSchedule === 'weekly' ? '每周' : taskSchedule === 'monthly' ? '每月' : taskSchedule === 'once' ? '每天' :''}</span>
<svg class="w-4 h-4 text-gray-400 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
</div>
<!-- 下拉选项列表 -->
<div id="dropdown-options" class="absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-50 hidden">
<div class="py-1">
<div class="dropdown-option px-3 py-2 text-sm hover:bg-gray-50 cursor-pointer" data-value="daily">
<span>每天</span>
</div>
<div class="dropdown-option px-3 py-2 text-sm hover:bg-gray-50 cursor-pointer relative" data-value="weekly">
<span>每周</span>
<!-- 每周选项侧边栏 -->
<div id="weekly-sidebar" class="absolute top-0 left-full ml-2 w-40 bg-white border border-gray-200 rounded-lg shadow-lg p-4 z-50 hidden">
<div class="mb-3">
<h4 class="text-sm font-medium text-gray-700 mb-2">选择星期</h4>
<div class="space-y-2">
<div class="weekly-day-option flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded cursor-pointer" data-day="monday">
<span class="text-sm">周一</span>
<div class="w-4 h-4 border border-gray-300 rounded flex items-center justify-center">
<svg class="w-3 h-3 text-primary-600 hidden" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
</div>
<div class="weekly-day-option flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded cursor-pointer" data-day="tuesday">
<span class="text-sm">周二</span>
<div class="w-4 h-4 border border-gray-300 rounded flex items-center justify-center">
<svg class="w-3 h-3 text-primary-600 hidden" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
</div>
<div class="weekly-day-option flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded cursor-pointer" data-day="wednesday">
<span class="text-sm">周三</span>
<div class="w-4 h-4 border border-gray-300 rounded flex items-center justify-center">
<svg class="w-3 h-3 text-primary-600 hidden" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
</div>
<div class="weekly-day-option flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded cursor-pointer" data-day="thursday">
<span class="text-sm">周四</span>
<div class="w-4 h-4 border border-gray-300 rounded flex items-center justify-center">
<svg class="w-3 h-3 text-primary-600 hidden" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
</div>
<div class="weekly-day-option flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded cursor-pointer" data-day="friday">
<span class="text-sm">周五</span>
<div class="w-4 h-4 border border-gray-300 rounded flex items-center justify-center">
<svg class="w-3 h-3 text-primary-600 hidden" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
</div>
<div class="weekly-day-option flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded cursor-pointer" data-day="saturday">
<span class="text-sm">周六</span>
<div class="w-4 h-4 border border-gray-300 rounded flex items-center justify-center">
<svg class="w-3 h-3 text-primary-600 hidden" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
</div>
<div class="weekly-day-option flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded cursor-pointer" data-day="sunday">
<span class="text-sm">周日</span>
<div class="w-4 h-4 border border-gray-300 rounded flex items-center justify-center">
<svg class="w-3 h-3 text-primary-600 hidden" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="dropdown-option px-3 py-2 text-sm hover:bg-gray-50 cursor-pointer relative" data-value="monthly">
<span>每月</span>
<!-- 每月选项侧边栏 -->
<div id="monthly-sidebar" class="absolute top-0 left-full ml-2 w-40 bg-white border border-gray-200 rounded-lg shadow-lg p-4 z-50 hidden">
<div class="mb-3">
<h4 class="text-sm font-medium text-gray-700 mb-2">选择日期</h4>
<div class="grid grid-cols-3 gap-1">
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="1">1</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="2">2</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="3">3</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="4">4</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="5">5</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="6">6</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="7">7</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="8">8</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="9">9</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="10">10</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="11">11</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="12">12</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="13">13</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="14">14</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="15">15</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="16">16</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="17">17</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="18">18</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="19">19</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="20">20</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="21">21</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="22">22</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="23">23</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="24">24</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="25">25</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="26">26</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="27">27</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="28">28</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="29">29</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="30">30</div>
<div class="monthly-day-option flex items-center justify-center py-2 px-1 hover:bg-gray-50 rounded cursor-pointer text-sm" data-day="31">31</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-span-1 relative">
<select id="time-select" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 appearance-none bg-white">
<option value="00:00">00:00</option>
<option value="00:30">00:30</option>
<option value="01:00">01:00</option>
<option value="01:30">01:30</option>
<option value="02:00">02:00</option>
<option value="02:30">02:30</option>
<option value="03:00">03:00</option>
<option value="03:30">03:30</option>
<option value="04:00">04:00</option>
<option value="04:30">04:30</option>
<option value="05:00">05:00</option>
<option value="05:30">05:30</option>
<option value="06:00">06:00</option>
<option value="06:30">06:30</option>
<option value="07:00">07:00</option>
<option value="07:30">07:30</option>
<option value="08:00">08:00</option>
<option value="08:30">08:30</option>
<option value="09:00">09:00</option>
<option value="09:30">09:30</option>
<option value="10:00" selected>10:00</option>
<option value="10:30">10:30</option>
<option value="11:00">11:00</option>
<option value="11:30">11:30</option>
<option value="12:00">12:00</option>
<option value="12:30">12:30</option>
<option value="13:00">13:00</option>
<option value="13:30">13:30</option>
<option value="14:00">14:00</option>
<option value="14:30">14:30</option>
<option value="15:00">15:00</option>
<option value="15:30">15:30</option>
<option value="16:00">16:00</option>
<option value="16:30">16:30</option>
<option value="17:00">17:00</option>
<option value="17:30">17:30</option>
<option value="18:00">18:00</option>
<option value="18:30">18:30</option>
<option value="19:00">19:00</option>
<option value="19:30">19:30</option>
<option value="20:00">20:00</option>
<option value="20:30">20:30</option>
<option value="21:00">21:00</option>
<option value="21:30">21:30</option>
<option value="22:00">22:00</option>
<option value="22:30">22:30</option>
<option value="23:00">23:00</option>
<option value="23:30">23:30</option>
</select>
<div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
</div>
</div>
</div>
<!-- 情报侧重点区域 -->
<div class="mb-6">
<label class="block text-sm font-medium text-gray-700 mb-2">需求</label>
<textarea id="task-name" rows="6" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 resize-none" required placeholder="请描述您希望关注的对象和信息侧重方向,以及您的要求,例如:
关注对象OpenAI
信息侧重点:产品发布动态和功能更新
要求:总结全面、客观、准确
">${taskName}</textarea>
</div>
</div>
<!-- 信息源配置 -->
<div id="step2-content">
<div class="flex gap-6">
<!-- 左侧:信息源分类 -->
<div class="w-1/3">
<h4 class="text-sm font-medium text-gray-700 mb-4">选择已有信息源</h4>
<div class="space-y-2" id="info-source-categories">
<!-- 信息源分类将通过JavaScript动态生成 -->
</div>
</div>
<!-- 右侧:已选信息源列表 -->
<div class="flex-1">
<h4 class="text-sm font-medium text-gray-700 mb-4">已选择的信息源</h4>
<div id="selected-sources-list" class="space-y-3">
<div class="text-center py-8 text-gray-500">请点击左侧分类添加信息源</div>
</div>
</div>
</div>
</div>
</form>
</div>
<!-- 模态框底部按钮 -->
<div class="flex items-center justify-end gap-3 p-6 border-t border-gray-200">
<button type="button" class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 transition-colors" onclick="this.closest('.fixed').remove()">
取消
</button>
<button id="save-btn" type="submit" form="task-form" class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors">
开始任务
</button>
</div>
</div>
`;
document.body.appendChild(modal);
// 全局变量
window.selectedWeekDays = new Set();
window.selectedMonthDays = new Set();
window.selectedDataSource = null;
// 自定义下拉框控制
const customDropdown = modal.querySelector('#custom-dropdown');
const dropdownOptions = modal.querySelector('#dropdown-options');
const selectedText = modal.querySelector('#selected-text');
const weeklySidebar = modal.querySelector('#weekly-sidebar');
const monthlySidebar = modal.querySelector('#monthly-sidebar');
// 设置初始值
let selectedValue = taskSchedule || 'once';
selectedText.textContent = selectedValue === 'weekly' ? '每周' : selectedValue === 'monthly' ? '每月' : selectedValue === 'once' ? '每天' : '';
// 自定义下拉框点击事件
customDropdown.addEventListener('click', function() {
dropdownOptions.classList.toggle('hidden');
});
// 下拉选项点击事件
const dropdownOptionElements = modal.querySelectorAll('.dropdown-option');
dropdownOptionElements.forEach(option => {
option.addEventListener('click', function(e) {
e.stopPropagation();
const value = this.dataset.value;
const text = this.querySelector('span').textContent;
selectedValue = value;
selectedText.textContent = text;
dropdownOptions.classList.add('hidden');
// 隐藏所有侧边栏
weeklySidebar.classList.add('hidden');
monthlySidebar.classList.add('hidden');
});
});
// 每周选项悬停事件
const weeklyOption = modal.querySelector('[data-value="weekly"]');
weeklyOption.addEventListener('mouseenter', function() {
weeklySidebar.classList.remove('hidden');
monthlySidebar.classList.add('hidden');
});
weeklyOption.addEventListener('mouseleave', function() {
setTimeout(() => {
if (!weeklySidebar.matches(':hover')) {
weeklySidebar.classList.add('hidden');
}
}, 100);
});
// 每月选项悬停事件
const monthlyOption = modal.querySelector('[data-value="monthly"]');
monthlyOption.addEventListener('mouseenter', function() {
monthlySidebar.classList.remove('hidden');
weeklySidebar.classList.add('hidden');
});
monthlyOption.addEventListener('mouseleave', function() {
setTimeout(() => {
if (!monthlySidebar.matches(':hover')) {
monthlySidebar.classList.add('hidden');
}
}, 100);
});
// 侧边栏的鼠标离开控制
weeklySidebar.addEventListener('mouseleave', function() {
this.classList.add('hidden');
});
monthlySidebar.addEventListener('mouseleave', function() {
this.classList.add('hidden');
});
// 点击模态框其他地方隐藏下拉框和侧边栏
modal.addEventListener('click', function(e) {
if (!customDropdown.contains(e.target) &&
!dropdownOptions.contains(e.target) &&
!weeklySidebar.contains(e.target) &&
!monthlySidebar.contains(e.target)) {
dropdownOptions.classList.add('hidden');
weeklySidebar.classList.add('hidden');
monthlySidebar.classList.add('hidden');
}
});
// 点击侧边栏内部时阻止事件冒泡
weeklySidebar.addEventListener('click', function(e) {
e.stopPropagation();
});
monthlySidebar.addEventListener('click', function(e) {
e.stopPropagation();
});
// 每周选项点击处理(单选)
const weeklyDayOptions = modal.querySelectorAll('.weekly-day-option');
weeklyDayOptions.forEach(option => {
option.addEventListener('click', function() {
const day = this.dataset.day;
// 自动选择"每周"选项
selectedValue = 'weekly';
selectedText.textContent = '每周';
// 清除之前的选择
weeklyDayOptions.forEach(opt => {
opt.querySelector('svg').classList.add('hidden');
});
window.selectedWeekDays.clear();
// 选择当前项
window.selectedWeekDays.add(day);
this.querySelector('svg').classList.remove('hidden');
// 隐藏下拉选项
dropdownOptions.classList.add('hidden');
});
});
// 每月选项点击处理
const monthlyDayOptions = modal.querySelectorAll('.monthly-day-option');
monthlyDayOptions.forEach(option => {
option.addEventListener('click', function() {
const day = this.dataset.day;
// 自动选择"每月"选项
selectedValue = 'monthly';
selectedText.textContent = '每月';
// 清除之前的选择
monthlyDayOptions.forEach(opt => {
opt.classList.remove('bg-primary-600', 'text-white');
});
window.selectedMonthDays.clear();
// 选择当前项
window.selectedMonthDays.add(day);
this.classList.add('bg-primary-600', 'text-white');
// 隐藏下拉选项
dropdownOptions.classList.add('hidden');
});
});
// 信息源数据和相关功能将在第二步时加载
// 这些复杂的信息源配置功能将复制自原文件
// 保存按钮处理
const saveBtn = modal.querySelector('#save-btn');
saveBtn.addEventListener('click', function(e) {
e.preventDefault();
// 验证表单
const taskName = modal.querySelector('#task-name').value.trim();
if (!taskName) {
alert('请填写情报侧重点');
return;
}
// 提交表单
submitForm();
});
// 延迟初始化信息源分类和已选列表确保DOM完全加载
setTimeout(() => {
console.log('开始初始化信息源...');
try {
renderInfoSourceCategories();
window.updateSelectedSourcesList();
console.log('信息源初始化完成');
} catch (error) {
console.error('信息源初始化失败:', error);
}
}, 200);
// 表单提交函数
window.submitForm = function() {
const taskName = modal.querySelector('#task-name').value.trim();
const schedule = selectedValue;
const time = modal.querySelector('#time-select').value;
// 获取详细的循环周期信息
let scheduleDetails = '';
if (schedule === 'once') {
scheduleDetails = `单次执行`;
} else if (schedule === 'daily') {
scheduleDetails = `每天 ${time}`;
} else if (schedule === 'weekly') {
const dayNames = {
'monday': '周一', 'tuesday': '周二', 'wednesday': '周三',
'thursday': '周四', 'friday': '周五', 'saturday': '周六', 'sunday': '周日'
};
if (window.selectedWeekDays.size > 0) {
const selectedDayNames = Array.from(window.selectedWeekDays).map(day => dayNames[day]);
scheduleDetails = `每周 ${selectedDayNames.join('')} ${time}`;
} else {
scheduleDetails = `每周 ${time}`;
}
} else if (schedule === 'monthly') {
if (window.selectedMonthDays.size > 0) {
const selectedDay = Array.from(window.selectedMonthDays)[0];
scheduleDetails = `每月${selectedDay}号 ${time}`;
} else {
scheduleDetails = `每月 ${time}`;
}
}
if (isEdit) {
updateTask(taskId, taskName, scheduleDetails);
} else {
createTask(taskName, scheduleDetails, {});
}
modal.remove();
};
// 信息源数据存储对象(从原文件复制)
const infoSources = {
wechat: [
{ name: '吃花花-微信', status: '已连接' },
{ name: '张三-企微', status: '已连接' }
],
wechatOfficial: [
{ name: '清研科技公众号', url: 'https://mp.weixin.qq.com/s/example1' },
{ name: '产品资讯号', url: 'https://mp.weixin.qq.com/s/example2' }
],
feishu: [
{ name: '清研飞书应用', appId: 'cli_123456789', appKey: 'key_abcdef123' }
],
dingtalk: [
{ name: '清研钉钉应用', appId: 'ding123456789', appSecret: 'secret_abcdef123' }
],
email: [
{ name: '工作邮箱', email: 'work@qingyan.com', authCode: 'auth_123456' },
{ name: '客服邮箱', email: 'support@qingyan.com', authCode: 'auth_789012' }
],
web: [
{ name: '公司官网', url: 'https://www.qingyan.com' },
{ name: '技术博客', url: 'https://blog.qingyan.com' }
],
cloudStorage: [
{ name: '百度网盘', appKey: 'baidu_123456', appSecret: 'secret_baidu123' }
]
};
// 信息源类型配置
const sourceTypes = [
{ key: 'wechat', name: '微信|企微', icon: 'M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z' },
{ key: 'wechatOfficial', name: '公众号', icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z' },
{ key: 'feishu', name: '飞书', icon: 'M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z' },
{ key: 'dingtalk', name: '钉钉', icon: 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z' },
{ key: 'email', name: '邮箱', icon: 'M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z' },
{ key: 'web', name: '网页', icon: 'M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9' },
{ key: 'cloudStorage', name: '百度网盘', icon: 'M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z' }
];
// 选中的信息源(全局变量,供其他函数访问)
window.selectedInfoSources = new Set();
// 选中的具体信息源子项(全局变量,供其他函数访问)
window.selectedSourceItems = new Set();
// 临时网页数据存储
window.tempWebsites = [];
// 临时公众号数据存储
window.tempOfficialAccounts = [];
// 获取信息源颜色类
function getSourceColorClass(sourceKey) {
const colorMap = {
'wechat': { bg: 'bg-green-100', text: 'text-green-600' },
'wechatOfficial': { bg: 'bg-blue-100', text: 'text-blue-600' },
'feishu': { bg: 'bg-purple-100', text: 'text-purple-600' },
'dingtalk': { bg: 'bg-indigo-100', text: 'text-indigo-600' },
'email': { bg: 'bg-yellow-100', text: 'text-yellow-600' },
'web': { bg: 'bg-orange-100', text: 'text-orange-600' },
'cloudStorage': { bg: 'bg-pink-100', text: 'text-pink-600' }
};
return colorMap[sourceKey] || { bg: 'bg-gray-100', text: 'text-gray-600' };
}
// 获取信息源详情
function getSourceDetail(source, sourceKey) {
switch (sourceKey) {
case 'wechat':
return source.status;
case 'wechatOfficial':
case 'web':
return source.url;
case 'feishu':
return `App ID: ${source.appId}`;
case 'dingtalk':
return `App ID: ${source.appId}`;
case 'email':
return source.email;
case 'cloudStorage':
return `App Key: ${source.appKey}`;
default:
return '';
}
}
// 渲染临时网页项
window.renderTempWebItem = function(source) {
const itemKey = `tempWeb-${source.name}`;
const isSelected = window.selectedSourceItems.has(itemKey);
return `
<div class="flex items-center justify-between p-2 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<div class="flex items-center gap-2 flex-1 min-w-0 cursor-pointer" onclick="toggleSourceItem('${itemKey}', this)">
<div class="w-4 h-4 border-2 border-gray-300 rounded flex items-center justify-center flex-shrink-0 ${isSelected ? 'border-primary-600 bg-primary-50' : ''}">
<svg class="w-3 h-3 text-primary-600 ${isSelected ? '' : 'hidden'}" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
<div class="w-6 h-6 bg-primary-100 rounded flex items-center justify-center flex-shrink-0">
<svg class="w-3 h-3 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9"/>
</svg>
</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium text-gray-900 truncate">${source.name}</div>
<div class="text-xs text-gray-500 truncate">${source.url}</div>
</div>
</div>
<button type="button" class="text-red-500 hover:text-red-700 ml-2 flex-shrink-0" onclick="deleteTempWebItem('${source.name}', event)">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
`;
}
// 渲染临时公众号项
window.renderTempOfficialAccountItem = function(source) {
const itemKey = `tempOfficialAccount-${source.name}`;
const isSelected = window.selectedSourceItems.has(itemKey);
return `
<div class="flex items-center justify-between p-2 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<div class="flex items-center gap-2 flex-1 min-w-0 cursor-pointer" onclick="toggleSourceItem('${itemKey}', this)">
<div class="w-4 h-4 border-2 border-gray-300 rounded flex items-center justify-center flex-shrink-0 ${isSelected ? 'border-primary-600 bg-primary-50' : ''}">
<svg class="w-3 h-3 text-primary-600 ${isSelected ? '' : 'hidden'}" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
<div class="w-6 h-6 bg-primary-100 rounded flex items-center justify-center flex-shrink-0">
<svg class="w-3 h-3 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
</svg>
</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium text-gray-900 truncate">${source.displayName}</div>
<div class="text-xs text-gray-500 truncate">${source.url}</div>
</div>
</div>
<button type="button" class="text-red-500 hover:text-red-700 ml-2 flex-shrink-0" onclick="deleteTempOfficialAccountItem('${source.name}', event)">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
`;
}
// 在模态框内重新定义 addSourceToSelected 函数
window.addSourceToSelected = function(sourceKey, sourceName) {
console.log('addSourceToSelected 被调用:', sourceKey, sourceName);
const itemKey = `${sourceKey}-${sourceName}`;
// 检查是否已经添加
if (window.selectedSourceItems.has(itemKey)) {
showNotification('该信息源已经添加', 'info');
return;
}
// 添加到已选列表
window.selectedSourceItems.add(itemKey);
window.selectedInfoSources.add(sourceKey);
// 更新已选信息源列表显示
window.updateSelectedSourcesList();
showNotification(`已添加 ${sourceName}`, 'success');
};
// 在模态框内重新定义 removeSourceFromSelected 函数
window.removeSourceFromSelected = function(itemKey) {
window.selectedSourceItems.delete(itemKey);
// 检查是否还有该类型的其他信息源
const sourceKey = itemKey.split('-')[0];
const hasOtherSources = Array.from(window.selectedSourceItems).some(key => key.startsWith(sourceKey + '-'));
if (!hasOtherSources) {
window.selectedInfoSources.delete(sourceKey);
}
// 处理临时信息源的删除
if (sourceKey === 'tempWeb') {
const sourceName = itemKey.split('-').slice(1).join('-');
if (window.tempWebsites) {
const index = window.tempWebsites.findIndex(item => item.name === sourceName);
if (index > -1) {
window.tempWebsites.splice(index, 1);
}
}
} else if (sourceKey === 'tempOfficialAccount') {
const sourceName = itemKey.split('-').slice(1).join('-');
if (window.tempOfficialAccounts) {
const index = window.tempOfficialAccounts.findIndex(item => item.name === sourceName);
if (index > -1) {
window.tempOfficialAccounts.splice(index, 1);
}
}
}
// 更新已选信息源列表显示
window.updateSelectedSourcesList();
showNotification('已移除信息源', 'info');
};
// 渲染信息源分类
function renderInfoSourceCategories() {
const categoriesContainer = modal.querySelector('#info-source-categories');
console.log('renderInfoSourceCategories 被调用, categoriesContainer:', categoriesContainer);
if (!categoriesContainer) {
console.error('找不到 #info-source-categories 元素');
return;
}
categoriesContainer.innerHTML = sourceTypes.map(type => `
<div class="info-source-category" data-source="${type.key}">
<!-- 分类标题 -->
<div class="flex items-center justify-between p-3 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors cursor-pointer" onclick="console.log('分类被点击:', '${type.key}'); toggleSourceCategory('${type.key}')">
<div class="flex items-center gap-3">
<svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${type.icon}"/>
</svg>
<span class="text-sm font-medium">${type.name}</span>
</div>
<div class="flex items-center gap-2">
<span class="text-xs text-gray-500">${(infoSources[type.key] || []).length}个</span>
<svg class="w-4 h-4 text-gray-400 transform transition-transform category-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</div>
</div>
<!-- 子节点列表(默认隐藏) -->
<div class="category-children hidden ml-4 mt-2 space-y-1" id="category-${type.key}">
${(infoSources[type.key] || []).map(source => {
const colorClass = getSourceColorClass(type.key);
return `
<div class="flex items-center justify-between p-2 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<div class="flex items-center gap-2 flex-1">
<div class="w-6 h-6 ${colorClass.bg} rounded flex items-center justify-center">
<svg class="w-3 h-3 ${colorClass.text}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${type.icon}"/>
</svg>
</div>
<div class="flex-1">
<span class="text-sm font-medium text-gray-900">${source.name}</span>
<div class="text-xs text-gray-500">${getSourceDetail(source, type.key)}</div>
</div>
</div>
<button type="button" class="w-6 h-6 bg-primary-600 hover:bg-primary-700 rounded flex items-center justify-center transition-colors" onclick="console.log('按钮被点击'); addSourceToSelected('${type.key}', '${source.name}')">
<svg class="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
</svg>
</button>
</div>
`;}).join('')}
</div>
</div>
`).join('');
}
window.updateSelectedSourcesList = function() {
const selectedListContainer = modal.querySelector('#selected-sources-list');
console.log('updateSelectedSourcesList 被调用, selectedListContainer:', selectedListContainer);
if (!selectedListContainer) {
console.error('找不到 #selected-sources-list 元素');
return;
}
let selectedSourcesHtml = '';
// 显示已选择的信息源(排除临时信息源)
const nonTempSelectedItems = Array.from(window.selectedSourceItems).filter(itemKey =>
!itemKey.startsWith('tempWeb-') && !itemKey.startsWith('tempOfficialAccount-')
);
if (nonTempSelectedItems.length > 0) {
const groupedSources = {};
// 按类型分组(排除临时信息源,它们在专门区域显示)
window.selectedSourceItems.forEach(itemKey => {
const [sourceKey, ...nameParts] = itemKey.split('-');
const sourceName = nameParts.join('-');
// 跳过临时信息源,它们在专门的临时信息源区域显示
if (sourceKey === 'tempWeb' || sourceKey === 'tempOfficialAccount') {
return;
}
if (!groupedSources[sourceKey]) {
groupedSources[sourceKey] = [];
}
groupedSources[sourceKey].push({
itemKey,
sourceName
});
});
// 生成已选信息源的HTML
Object.keys(groupedSources).forEach(sourceKey => {
let sourceType = sourceTypes.find(type => type.key === sourceKey);
let colorClass = getSourceColorClass(sourceKey);
// 处理临时信息源
if (sourceKey === 'tempWeb') {
sourceType = { key: 'tempWeb', name: '临时网页', icon: 'M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9' };
colorClass = { bg: 'bg-orange-100', text: 'text-orange-600' };
} else if (sourceKey === 'tempOfficialAccount') {
sourceType = { key: 'tempOfficialAccount', name: '临时公众号', icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z' };
colorClass = { bg: 'bg-green-100', text: 'text-green-600' };
}
if (sourceType) {
selectedSourcesHtml += `
<div class="border border-gray-200 rounded-lg p-3 mb-3">
<div class="flex items-center gap-2 mb-2">
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${sourceType.icon}"/>
</svg>
<span class="text-sm font-medium text-gray-900">${sourceType.name}</span>
</div>
<div class="space-y-1">
${groupedSources[sourceKey].map(source => {
// 获取详细信息
let detailInfo = '';
if (sourceKey === 'tempWeb' && window.tempWebsites) {
const webItem = window.tempWebsites.find(item => item.name === source.sourceName);
detailInfo = webItem ? webItem.url : '';
} else if (sourceKey === 'tempOfficialAccount' && window.tempOfficialAccounts) {
const accountItem = window.tempOfficialAccounts.find(item => item.name === source.sourceName);
detailInfo = accountItem ? accountItem.url : '';
}
return `
<div class="flex items-center justify-between p-2 bg-gray-50 rounded">
<div class="flex items-center gap-2 flex-1 min-w-0">
<div class="w-4 h-4 ${colorClass.bg} rounded flex items-center justify-center flex-shrink-0">
<svg class="w-2 h-2 ${colorClass.text}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${sourceType.icon}"/>
</svg>
</div>
<div class="min-w-0 flex-1">
<div class="text-sm text-gray-900 truncate">${source.sourceName}</div>
${detailInfo ? `<div class="text-xs text-gray-500 truncate">${detailInfo}</div>` : ''}
</div>
</div>
<button type="button" class="w-5 h-5 bg-red-500 hover:bg-red-600 rounded flex items-center justify-center transition-colors flex-shrink-0 ml-2" onclick="removeSourceFromSelected('${source.itemKey}')">
<svg class="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
`;
}).join('')}
</div>
</div>
`;
}
});
}
// 渲染临时信息源区域
let tempSourcesHtml = '';
const totalTempSources = (window.tempWebsites ? window.tempWebsites.length : 0) + (window.tempOfficialAccounts ? window.tempOfficialAccounts.length : 0);
if (totalTempSources > 0) {
tempSourcesHtml = `
<div class="border border-gray-200 rounded-lg p-4 mb-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-3">
<svg class="w-5 h-5 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9"/>
</svg>
<h5 class="font-medium text-gray-900">临时信息源</h5>
<span class="text-xs text-gray-500">${totalTempSources}个信息源</span>
</div>
<button type="button" class="text-red-500 hover:text-red-700 text-sm" onclick="deleteAllTempSources()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
</button>
</div>
<div class="space-y-2">
${window.tempWebsites ? window.tempWebsites.map(source => window.renderTempWebItem(source)).join('') : ''}
${window.tempOfficialAccounts ? window.tempOfficialAccounts.map(source => window.renderTempOfficialAccountItem(source)).join('') : ''}
</div>
</div>
`;
}
selectedListContainer.innerHTML = `
<!-- 联网搜索选项 -->
<div class="border border-gray-200 rounded-lg p-4 mb-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="w-4 h-4 border-2 border-primary-600 bg-primary-50 rounded flex items-center justify-center cursor-pointer" onclick="toggleWebSearch(this)">
<svg class="w-3 h-3 text-primary-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9"/>
</svg>
<span class="text-sm font-medium text-gray-900">联网搜索</span>
</div>
<span class="text-xs text-gray-500">实时获取最新信息</span>
</div>
</div>
<!-- 已选择的信息源 -->
${selectedSourcesHtml}
<!-- 临时信息源 -->
${tempSourcesHtml}
<!-- 添加信息源按钮 -->
<div class="mb-4 flex gap-3">
<button type="button" class="flex items-center gap-2 text-primary-600 hover:text-primary-700 text-sm font-medium" onclick="showAddWebUrlModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
</svg>
添加网页
</button>
<button type="button" class="flex items-center gap-2 text-primary-600 hover:text-primary-700 text-sm font-medium" onclick="showAddOfficialAccountModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
</svg>
添加公众号
</button>
</div>
${nonTempSelectedItems.length === 0 && totalTempSources === 0 ? '<div class="text-center py-8 text-gray-500">请点击左侧分类添加信息源</div>' : ''}
`;
}
}
// 显示单次任务模态框
function showSingleTaskModal() {
console.log('显示单次任务模态框');
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
modal.innerHTML = `
<div class="bg-white rounded-lg w-full max-w-4xl mx-4 relative">
<!-- 模态框头部 -->
<div class="flex items-center justify-between p-6 border-b border-gray-200">
<div class="flex items-center gap-3">
<h3 class="text-lg font-semibold text-gray-900">新建单次任务</h3>
</div>
<div class="flex items-center gap-4">
<button class="p-2 hover:bg-gray-100 rounded-lg" onclick="this.closest('.fixed').remove()">
<svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
</div>
<!-- 模态框内容 -->
<div class="p-6 max-h-[70vh] overflow-y-auto">
<form id="single-task-form">
<!-- 信息侧重点区域 -->
<div class="mb-6">
<label class="block text-sm font-medium text-gray-700 mb-2">需求</label>
<textarea id="single-task-name" rows="6" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 resize-none" required placeholder="请描述您希望关注的对象和信息侧重方向,以及您的要求,例如:
关注对象OpenAI
信息侧重点:产品发布动态和功能更新
要求:总结全面、客观、准确
"></textarea>
</div>
<!-- 信息源配置 -->
<div class="mb-6">
<div class="flex gap-6">
<!-- 左侧:信息源分类 -->
<div class="w-1/3">
<h4 class="text-sm font-medium text-gray-700 mb-4">选择已有信息源</h4>
<div class="space-y-2" id="single-info-source-categories">
<!-- 信息源分类将通过JavaScript动态生成 -->
</div>
</div>
<!-- 右侧:已选信息源列表 -->
<div class="flex-1">
<h4 class="text-sm font-medium text-gray-700 mb-4">已选择的信息源</h4>
<div id="single-selected-sources-list" class="space-y-3">
<div class="text-center py-8 text-gray-500">请点击左侧分类添加信息源</div>
</div>
</div>
</div>
</div>
</form>
</div>
<!-- 模态框底部按钮 -->
<div class="flex items-center justify-end gap-3 p-6 border-t border-gray-200">
<button type="button" class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 transition-colors" onclick="this.closest('.fixed').remove()">
取消
</button>
<button id="single-save-btn" type="submit" form="single-task-form" class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors">
开始任务
</button>
</div>
</div>
`;
document.body.appendChild(modal);
// 全局变量(完整复制自周期任务)
window.selectedSingleInfoSources = new Set();
window.selectedSingleSourceItems = new Set();
window.tempSingleWebsites = [];
window.tempSingleOfficialAccounts = [];
// 保存按钮处理
const saveBtn = modal.querySelector('#single-save-btn');
saveBtn.addEventListener('click', function(e) {
e.preventDefault();
// 验证表单
const taskName = modal.querySelector('#single-task-name').value.trim();
if (!taskName) {
alert('请填写信息侧重点');
return;
}
// 提交表单
submitSingleTaskForm();
});
// 延迟初始化信息源分类和已选列表确保DOM完全加载
setTimeout(() => {
console.log('开始初始化单次任务信息源...');
try {
renderSingleInfoSourceCategories();
window.updateSingleSelectedSourcesList();
} catch (error) {
console.error('初始化单次任务信息源失败:', error);
}
}, 200);
// 提交单次任务表单
function submitSingleTaskForm() {
const taskName = modal.querySelector('#single-task-name').value.trim();
const selectedSources = Array.from(window.selectedSingleInfoSources || []);
const selectedItems = Array.from(window.selectedSingleSourceItems || []);
const tempWebsites = window.tempSingleWebsites || [];
const tempOfficialAccounts = window.tempSingleOfficialAccounts || [];
if (selectedSources.length === 0 && selectedItems.length === 0 && tempWebsites.length === 0 && tempOfficialAccounts.length === 0) {
alert('请至少选择一个信息源');
return;
}
// 创建单次任务
createSingleTask(taskName, {
sources: selectedSources,
items: selectedItems,
websites: tempWebsites,
officialAccounts: tempOfficialAccounts
});
modal.remove();
}
}
// 显示周期任务模态框使用现有的showTaskModal
function showScheduledTaskModal() {
console.log('显示周期任务模态框');
showTaskModal('new');
}
// 创建单次任务
function createSingleTask(name, infoSourceInfo) {
console.log('创建单次任务:', name, infoSourceInfo);
showNotification('单次任务创建成功!');
}
// 单次任务信息源相关函数(完整复制自周期任务)
function renderSingleInfoSourceCategories() {
const categoriesContainer = document.getElementById('single-info-source-categories');
console.log('renderSingleInfoSourceCategories 被调用, categoriesContainer:', categoriesContainer);
if (!categoriesContainer) {
console.error('找不到 #single-info-source-categories 元素');
return;
}
categoriesContainer.innerHTML = singleSourceTypes.map(type => `
<div class="info-source-category" data-source="${type.key}">
<!-- 分类标题 -->
<div class="flex items-center justify-between p-3 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors cursor-pointer" onclick="console.log('分类被点击:', '${type.key}'); toggleSingleSourceCategory('${type.key}')">
<div class="flex items-center gap-3">
<svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${type.icon}"/>
</svg>
<span class="text-sm font-medium">${type.name}</span>
</div>
<div class="flex items-center gap-2">
<span class="text-xs text-gray-500">${(singleInfoSources[type.key] || []).length}个</span>
<svg class="w-4 h-4 text-gray-400 transform transition-transform category-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</div>
</div>
<!-- 子节点列表(默认隐藏) -->
<div class="category-children hidden ml-4 mt-2 space-y-1" id="single-category-${type.key}">
${(singleInfoSources[type.key] || []).map(source => {
const colorClass = getSingleSourceColorClass(type.key);
return `
<div class="flex items-center justify-between p-2 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<div class="flex items-center gap-2 flex-1">
<div class="w-6 h-6 ${colorClass.bg} rounded flex items-center justify-center">
<svg class="w-3 h-3 ${colorClass.text}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${type.icon}"/>
</svg>
</div>
<div class="flex-1">
<span class="text-sm font-medium text-gray-900">${source.name}</span>
<div class="text-xs text-gray-500">${getSingleSourceDetail(source, type.key)}</div>
</div>
</div>
<button type="button" class="w-6 h-6 bg-primary-600 hover:bg-primary-700 rounded flex items-center justify-center transition-colors" onclick="console.log('按钮被点击'); addSingleSourceToSelected('${type.key}', '${source.name}')">
<svg class="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
</svg>
</button>
</div>
`;}).join('')}
</div>
</div>
`).join('');
}
// 单次任务信息源数据存储对象(完整复制自周期任务)
const singleInfoSources = {
wechat: [
{ name: '吃花花-微信', status: '已连接' },
{ name: '张三-企微', status: '已连接' }
],
wechatOfficial: [
{ name: '清研科技公众号', url: 'https://mp.weixin.qq.com/s/example1' },
{ name: '产品资讯号', url: 'https://mp.weixin.qq.com/s/example2' }
],
feishu: [
{ name: '清研飞书应用', appId: 'cli_123456789', appKey: 'key_abcdef123' }
],
dingtalk: [
{ name: '清研钉钉应用', appId: 'ding123456789', appSecret: 'secret_abcdef123' }
],
email: [
{ name: '工作邮箱', email: 'work@qingyan.com', authCode: 'auth_123456' },
{ name: '客服邮箱', email: 'support@qingyan.com', authCode: 'auth_789012' }
],
web: [
{ name: '公司官网', url: 'https://www.qingyan.com' },
{ name: '技术博客', url: 'https://blog.qingyan.com' }
],
cloudStorage: [
{ name: '百度网盘', appKey: 'baidu_123456', appSecret: 'secret_baidu123' }
]
};
// 单次任务信息源类型配置
const singleSourceTypes = [
{ key: 'wechat', name: '微信|企微', icon: 'M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z' },
{ key: 'wechatOfficial', name: '公众号', icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z' },
{ key: 'feishu', name: '飞书', icon: 'M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z' },
{ key: 'dingtalk', name: '钉钉', icon: 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z' },
{ key: 'email', name: '邮箱', icon: 'M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z' },
{ key: 'web', name: '网页', icon: 'M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9' },
{ key: 'cloudStorage', name: '百度网盘', icon: 'M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z' }
];
// 获取单次任务信息源颜色类
function getSingleSourceColorClass(sourceKey) {
const colorMap = {
'wechat': { bg: 'bg-green-100', text: 'text-green-600' },
'wechatOfficial': { bg: 'bg-blue-100', text: 'text-blue-600' },
'feishu': { bg: 'bg-purple-100', text: 'text-purple-600' },
'dingtalk': { bg: 'bg-indigo-100', text: 'text-indigo-600' },
'email': { bg: 'bg-yellow-100', text: 'text-yellow-600' },
'web': { bg: 'bg-orange-100', text: 'text-orange-600' },
'cloudStorage': { bg: 'bg-pink-100', text: 'text-pink-600' }
};
return colorMap[sourceKey] || { bg: 'bg-gray-100', text: 'text-gray-600' };
}
// 获取单次任务信息源详情
function getSingleSourceDetail(source, sourceKey) {
switch (sourceKey) {
case 'wechat':
return source.status;
case 'wechatOfficial':
case 'web':
return source.url;
case 'feishu':
return `App ID: ${source.appId}`;
case 'dingtalk':
return `App ID: ${source.appId}`;
case 'email':
return source.email;
case 'cloudStorage':
return `App Key: ${source.appKey}`;
default:
return '';
}
}
// 单次任务信息源相关函数
window.toggleSingleSourceCategory = function(sourceKey) {
console.log('toggleSingleSourceCategory 被调用:', sourceKey);
const categoryChildren = document.querySelector(`#single-category-${sourceKey}`);
const arrow = document.querySelector(`[data-source="${sourceKey}"] .category-arrow`);
if (categoryChildren && categoryChildren.classList.contains('hidden')) {
categoryChildren.classList.remove('hidden');
if (arrow) arrow.style.transform = 'rotate(90deg)';
} else if (categoryChildren) {
categoryChildren.classList.add('hidden');
if (arrow) arrow.style.transform = 'rotate(0deg)';
}
};
window.addSingleSourceToSelected = function(sourceKey, sourceName) {
const itemKey = `${sourceKey}-${sourceName}`;
// 检查是否已经添加
if (window.selectedSingleSourceItems.has(itemKey)) {
return;
}
// 添加到已选列表
window.selectedSingleSourceItems.add(itemKey);
window.selectedSingleInfoSources.add(sourceKey);
// 更新显示
window.updateSingleSelectedSourcesList();
showNotification(`已添加 ${sourceName}`, 'success');
};
window.removeSingleSourceFromSelected = function(itemKey) {
window.selectedSingleSourceItems.delete(itemKey);
// 检查是否还有该类型的其他信息源
const sourceKey = itemKey.split('-')[0];
const hasOtherSources = Array.from(window.selectedSingleSourceItems).some(key => key.startsWith(sourceKey + '-'));
if (!hasOtherSources) {
window.selectedSingleInfoSources.delete(sourceKey);
}
// 处理临时信息源的删除
if (sourceKey === 'tempWeb') {
const sourceName = itemKey.split('-').slice(1).join('-');
if (window.tempSingleWebsites) {
const index = window.tempSingleWebsites.findIndex(item => item.name === sourceName);
if (index > -1) {
window.tempSingleWebsites.splice(index, 1);
}
}
} else if (sourceKey === 'tempOfficialAccount') {
const sourceName = itemKey.split('-').slice(1).join('-');
if (window.tempSingleOfficialAccounts) {
const index = window.tempSingleOfficialAccounts.findIndex(item => item.name === sourceName);
if (index > -1) {
window.tempSingleOfficialAccounts.splice(index, 1);
}
}
}
// 更新显示
window.updateSingleSelectedSourcesList();
showNotification('已移除信息源', 'info');
};
window.updateSingleSelectedSourcesList = function() {
const selectedListContainer = document.getElementById('single-selected-sources-list');
console.log('updateSingleSelectedSourcesList 被调用, selectedListContainer:', selectedListContainer);
if (!selectedListContainer) {
console.error('找不到 #single-selected-sources-list 元素');
return;
}
let selectedSourcesHtml = '';
// 显示已选择的信息源(排除临时信息源)
const nonTempSelectedItems = Array.from(window.selectedSingleSourceItems).filter(itemKey =>
!itemKey.startsWith('tempWeb-') && !itemKey.startsWith('tempOfficialAccount-')
);
if (nonTempSelectedItems.length > 0) {
const groupedSources = {};
// 按类型分组(排除临时信息源,它们在专门区域显示)
window.selectedSingleSourceItems.forEach(itemKey => {
const [sourceKey, ...nameParts] = itemKey.split('-');
const sourceName = nameParts.join('-');
// 跳过临时信息源,它们在专门的临时信息源区域显示
if (sourceKey === 'tempWeb' || sourceKey === 'tempOfficialAccount') {
return;
}
if (!groupedSources[sourceKey]) {
groupedSources[sourceKey] = [];
}
groupedSources[sourceKey].push({
itemKey,
sourceName
});
});
// 生成已选信息源的HTML
Object.keys(groupedSources).forEach(sourceKey => {
let sourceType = singleSourceTypes.find(type => type.key === sourceKey);
let colorClass = getSingleSourceColorClass(sourceKey);
// 处理临时信息源
if (sourceKey === 'tempWeb') {
sourceType = { key: 'tempWeb', name: '临时网页', icon: 'M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9' };
colorClass = { bg: 'bg-orange-100', text: 'text-orange-600' };
} else if (sourceKey === 'tempOfficialAccount') {
sourceType = { key: 'tempOfficialAccount', name: '临时公众号', icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z' };
colorClass = { bg: 'bg-green-100', text: 'text-green-600' };
}
if (sourceType) {
selectedSourcesHtml += `
<div class="mb-4">
<div class="flex items-center gap-2 mb-2">
<div class="w-5 h-5 ${colorClass.bg} rounded flex items-center justify-center">
<svg class="w-3 h-3 ${colorClass.text}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${sourceType.icon}"/>
</svg>
</div>
<span class="text-sm font-medium text-gray-700">${sourceType.name}</span>
<span class="text-xs text-gray-500">(${groupedSources[sourceKey].length}个)</span>
</div>
<div class="space-y-2">
${groupedSources[sourceKey].map(item => `
<div class="flex items-center justify-between p-2 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<div class="flex items-center gap-2 flex-1">
<div class="w-4 h-4 ${colorClass.bg} rounded flex items-center justify-center">
<svg class="w-2 h-2 ${colorClass.text}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${sourceType.icon}"/>
</svg>
</div>
<span class="text-sm text-gray-900">${item.sourceName}</span>
</div>
<button type="button" class="text-red-500 hover:text-red-700 transition-colors" onclick="removeSingleSourceFromSelected('${item.itemKey}')">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
`).join('')}
</div>
</div>
`;
}
});
}
// 渲染临时信息源区域
let tempSourcesHtml = '';
const totalTempSources = (window.tempSingleWebsites ? window.tempSingleWebsites.length : 0) + (window.tempSingleOfficialAccounts ? window.tempSingleOfficialAccounts.length : 0);
if (totalTempSources > 0) {
tempSourcesHtml = `
<div class="border border-gray-200 rounded-lg p-4 mb-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-3">
<svg class="w-5 h-5 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9"/>
</svg>
<h5 class="font-medium text-gray-900">临时信息源</h5>
<span class="text-xs text-gray-500">${totalTempSources}个信息源</span>
</div>
<button type="button" class="text-red-500 hover:text-red-700 text-sm" onclick="deleteAllSingleTempSources()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
</button>
</div>
<div class="space-y-2">
${window.tempSingleWebsites ? window.tempSingleWebsites.map(source => window.renderSingleTempWebItem(source)).join('') : ''}
${window.tempSingleOfficialAccounts ? window.tempSingleOfficialAccounts.map(source => window.renderSingleTempOfficialAccountItem(source)).join('') : ''}
</div>
</div>
`;
}
selectedListContainer.innerHTML = `
<!-- 联网搜索选项 -->
<div class="border border-gray-200 rounded-lg p-4 mb-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="w-4 h-4 border-2 border-primary-600 bg-primary-50 rounded flex items-center justify-center cursor-pointer" onclick="toggleSingleWebSearch(this)">
<svg class="w-3 h-3 text-primary-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9"/>
</svg>
<span class="text-sm font-medium text-gray-900">联网搜索</span>
</div>
<span class="text-xs text-gray-500">实时获取最新信息</span>
</div>
</div>
<!-- 已选择的信息源 -->
${selectedSourcesHtml}
<!-- 临时信息源 -->
${tempSourcesHtml}
<!-- 添加信息源按钮 -->
<div class="mb-4 flex gap-3">
<button type="button" class="flex items-center gap-2 text-primary-600 hover:text-primary-700 text-sm font-medium" onclick="showSingleAddWebUrlModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
</svg>
添加网页
</button>
<button type="button" class="flex items-center gap-2 text-primary-600 hover:text-primary-700 text-sm font-medium" onclick="showSingleAddOfficialAccountModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
</svg>
添加公众号
</button>
</div>
${nonTempSelectedItems.length === 0 && totalTempSources === 0 ? '<div class="text-center py-8 text-gray-500">请点击左侧分类添加信息源</div>' : ''}
`;
};
// 单次任务临时信息源相关函数(完整复制自周期任务)
window.renderSingleTempWebItem = function(source) {
const itemKey = `tempWeb-${source.name}`;
const isSelected = window.selectedSingleSourceItems.has(itemKey);
return `
<div class="flex items-center justify-between p-2 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<div class="flex items-center gap-2 flex-1 min-w-0 cursor-pointer" onclick="toggleSingleSourceItem('${itemKey}', this)">
<div class="w-4 h-4 border-2 border-gray-300 rounded flex items-center justify-center flex-shrink-0 ${isSelected ? 'border-primary-600 bg-primary-50' : ''}">
<svg class="w-3 h-3 text-primary-600 ${isSelected ? '' : 'hidden'}" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
<div class="w-6 h-6 bg-primary-100 rounded flex items-center justify-center flex-shrink-0">
<svg class="w-3 h-3 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9"/>
</svg>
</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium text-gray-900 truncate">${source.name}</div>
<div class="text-xs text-gray-500 truncate">${source.url}</div>
</div>
</div>
<button type="button" class="text-red-500 hover:text-red-700 ml-2 flex-shrink-0" onclick="deleteSingleTempWebItem('${source.name}', event)">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
`;
};
window.renderSingleTempOfficialAccountItem = function(source) {
const itemKey = `tempOfficialAccount-${source.name}`;
const isSelected = window.selectedSingleSourceItems.has(itemKey);
return `
<div class="flex items-center justify-between p-2 bg-gray-50 rounded hover:bg-gray-100 transition-colors">
<div class="flex items-center gap-2 flex-1 min-w-0 cursor-pointer" onclick="toggleSingleSourceItem('${itemKey}', this)">
<div class="w-4 h-4 border-2 border-gray-300 rounded flex items-center justify-center flex-shrink-0 ${isSelected ? 'border-primary-600 bg-primary-50' : ''}">
<svg class="w-3 h-3 text-primary-600 ${isSelected ? '' : 'hidden'}" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</div>
<div class="w-6 h-6 bg-green-100 rounded flex items-center justify-center flex-shrink-0">
<svg class="w-3 h-3 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium text-gray-900 truncate">${source.name}</div>
<div class="text-xs text-gray-500 truncate">${source.platform}</div>
</div>
</div>
<button type="button" class="text-red-500 hover:text-red-700 ml-2 flex-shrink-0" onclick="deleteSingleTempOfficialAccountItem('${source.name}', event)">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
`;
};
window.toggleSingleSourceItem = function(itemKey, element) {
const checkbox = element.querySelector('.w-4\\:h-4');
const svg = checkbox.querySelector('svg');
if (window.selectedSingleSourceItems.has(itemKey)) {
window.selectedSingleSourceItems.delete(itemKey);
svg.classList.add('hidden');
checkbox.classList.remove('border-primary-600', 'bg-primary-50');
} else {
window.selectedSingleSourceItems.add(itemKey);
svg.classList.remove('hidden');
checkbox.classList.add('border-primary-600', 'bg-primary-50');
}
window.updateSingleSelectedSourcesList();
};
window.deleteSingleTempWebItem = function(sourceName, event) {
event.stopPropagation();
if (window.tempSingleWebsites) {
const index = window.tempSingleWebsites.findIndex(item => item.name === sourceName);
if (index > -1) {
window.tempSingleWebsites.splice(index, 1);
window.selectedSingleSourceItems.delete(`tempWeb-${sourceName}`);
window.updateSingleSelectedSourcesList();
showNotification('已删除临时网页', 'info');
}
}
};
window.deleteSingleTempOfficialAccountItem = function(sourceName, event) {
event.stopPropagation();
if (window.tempSingleOfficialAccounts) {
const index = window.tempSingleOfficialAccounts.findIndex(item => item.name === sourceName);
if (index > -1) {
window.tempSingleOfficialAccounts.splice(index, 1);
window.selectedSingleSourceItems.delete(`tempOfficialAccount-${sourceName}`);
window.updateSingleSelectedSourcesList();
showNotification('已删除临时公众号', 'info');
}
}
};
window.deleteAllSingleTempSources = function() {
if (confirm('确定要删除所有临时信息源吗?')) {
window.tempSingleWebsites = [];
window.tempSingleOfficialAccounts = [];
// 删除所有临时信息源的选中状态
Array.from(window.selectedSingleSourceItems).forEach(itemKey => {
if (itemKey.startsWith('tempWeb-') || itemKey.startsWith('tempOfficialAccount-')) {
window.selectedSingleSourceItems.delete(itemKey);
}
});
window.updateSingleSelectedSourcesList();
showNotification('已删除所有临时信息源', 'info');
}
};
window.toggleSingleWebSearch = function(checkbox) {
const svg = checkbox.querySelector('svg');
if (svg.classList.contains('hidden')) {
svg.classList.remove('hidden');
checkbox.classList.add('border-primary-600', 'bg-primary-50');
} else {
svg.classList.add('hidden');
checkbox.classList.remove('border-primary-600', 'bg-primary-50');
}
};
window.showSingleAddWebUrlModal = function() {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[10001] single-add-web-modal';
modal.innerHTML = `
<div class="bg-white rounded-lg w-full max-w-md mx-4">
<div class="flex items-center justify-between p-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-900">添加网页</h3>
<button class="text-gray-400 hover:text-gray-600" onclick="closeSingleAddWebModal()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="p-4">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">网页URL</label>
<input type="url" id="single-web-url-input" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent" placeholder="https://...">
</div>
<div class="flex justify-end gap-3">
<button class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 transition-colors" onclick="closeSingleAddWebModal()">
取消
</button>
<button class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors" onclick="addSingleWebUrl()">
添加
</button>
</div>
</div>
</div>
`;
document.body.appendChild(modal);
setTimeout(() => {
const input = modal.querySelector('#single-web-url-input');
if (input) input.focus();
}, 100);
};
window.closeSingleAddWebModal = function() {
const addWebModal = document.querySelector('.single-add-web-modal');
if (addWebModal) {
addWebModal.remove();
}
};
window.addSingleWebUrl = function() {
const input = document.getElementById('single-web-url-input');
const url = input.value.trim();
if (!url) {
alert('请输入网页URL');
return;
}
if (!url.startsWith('http://') && !url.startsWith('https://')) {
alert('请输入有效的URL以http://或https://开头)');
return;
}
// 从URL中提取网站名称
let name = '';
try {
const urlObj = new URL(url);
name = urlObj.hostname.replace('www.', '');
} catch (e) {
name = url;
}
// 检查是否已存在
if (window.tempSingleWebsites.some(item => item.url === url)) {
alert('该网页已存在');
return;
}
// 添加到临时网页列表
const newWebItem = { name, url };
window.tempSingleWebsites.push(newWebItem);
// 自动选中
const itemKey = `tempWeb-${name}`;
window.selectedSingleSourceItems.add(itemKey);
// 更新显示
window.updateSingleSelectedSourcesList();
// 关闭模态框
window.closeSingleAddWebModal();
showNotification(`已添加网页: ${name}`, 'success');
};
window.showSingleAddOfficialAccountModal = function() {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[10001] single-add-official-account-modal';
modal.innerHTML = `
<div class="bg-white rounded-lg w-full max-w-md mx-4">
<div class="flex items-center justify-between p-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-900">添加公众号</h3>
<button class="text-gray-400 hover:text-gray-600" onclick="closeSingleAddOfficialAccountModal()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="p-4">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">公众号名称</label>
<input type="text" id="single-official-account-name-input" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent" placeholder="请输入公众号名称">
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">平台</label>
<select id="single-official-account-platform-input" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent">
<option value="微信">微信</option>
<option value="微博">微博</option>
<option value="抖音">抖音</option>
<option value="小红书">小红书</option>
</select>
</div>
<div class="flex justify-end gap-3">
<button class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 transition-colors" onclick="closeSingleAddOfficialAccountModal()">
取消
</button>
<button class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors" onclick="addSingleOfficialAccount()">
添加
</button>
</div>
</div>
</div>
`;
document.body.appendChild(modal);
setTimeout(() => {
const input = modal.querySelector('#single-official-account-name-input');
if (input) input.focus();
}, 100);
};
window.closeSingleAddOfficialAccountModal = function() {
const addOfficialAccountModal = document.querySelector('.single-add-official-account-modal');
if (addOfficialAccountModal) {
addOfficialAccountModal.remove();
}
};
window.addSingleOfficialAccount = function() {
const nameInput = document.getElementById('single-official-account-name-input');
const platformInput = document.getElementById('single-official-account-platform-input');
const name = nameInput.value.trim();
const platform = platformInput.value;
if (!name) {
alert('请输入公众号名称');
return;
}
// 检查是否已存在
if (window.tempSingleOfficialAccounts.some(item => item.name === name && item.platform === platform)) {
alert('该公众号已存在');
return;
}
// 添加到临时公众号列表
const newAccountItem = { name, platform };
window.tempSingleOfficialAccounts.push(newAccountItem);
// 自动选中
const itemKey = `tempOfficialAccount-${name}`;
window.selectedSingleSourceItems.add(itemKey);
// 更新显示
window.updateSingleSelectedSourcesList();
// 关闭模态框
window.closeSingleAddOfficialAccountModal();
showNotification(`已添加公众号: ${name}`, 'success');
};
// 任务菜单相关函数
function toggleTaskMenu(taskId) {
// 关闭所有其他菜单
document.querySelectorAll('.task-menu').forEach(menu => {
if (menu.id !== `task-menu-${taskId}`) {
menu.classList.add('hidden');
}
});
// 切换当前菜单
const menu = document.getElementById(`task-menu-${taskId}`);
if (menu) {
menu.classList.toggle('hidden');
}
}
// 执行一次任务
function executeTaskOnce(taskId) {
console.log(`执行一次任务: ${taskId}`);
// 隐藏菜单
const menu = document.getElementById(`task-menu-${taskId}`);
if (menu) menu.classList.add('hidden');
// 显示执行提示
showNotification(`任务 ${taskId} 已开始执行`, 'success');
}
// 暂停任务
function pauseTask(taskId) {
console.log(`暂停任务: ${taskId}`);
// 隐藏菜单
const menu = document.getElementById(`task-menu-${taskId}`);
if (menu) menu.classList.add('hidden');
// 显示暂停提示
showNotification(`任务 ${taskId} 已暂停`, 'info');
}
// 编辑任务
function editTask(taskId) {
console.log(`编辑任务: ${taskId}`);
// 隐藏菜单
const menu = document.getElementById(`task-menu-${taskId}`);
if (menu) menu.classList.add('hidden');
// 打开编辑模态框
showTaskModal('edit', taskId);
}
// 删除任务
function deleteTask(taskId) {
console.log(`删除任务: ${taskId}`);
// 隐藏菜单
const menu = document.getElementById(`task-menu-${taskId}`);
if (menu) menu.classList.add('hidden');
// 确认删除
if (confirm('确定要删除这个任务吗?此操作不可撤销。')) {
showNotification(`任务 ${taskId} 已删除`, 'info');
// 这里可以添加实际删除逻辑
}
}
// 显示通知
function showNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 z-50 px-4 py-2 rounded-lg text-white text-sm transition-all duration-300 ${
type === 'success' ? 'bg-green-600' :
type === 'error' ? 'bg-red-600' :
type === 'info' ? 'bg-blue-600' : 'bg-gray-600'
}`;
notification.textContent = message;
document.body.appendChild(notification);
// 3秒后自动移除
setTimeout(() => {
notification.remove();
}, 3000);
}
// 报告操作功能
function downloadReport() {
const reportTitle = document.getElementById('unified-report-title').textContent;
console.log(`下载报告: ${reportTitle}`);
showNotification('报告下载已开始', 'success');
}
function archiveReport() {
const reportTitle = document.getElementById('unified-report-title').textContent;
console.log(`归档报告: ${reportTitle}`);
if (confirm('确定要归档这份报告吗?归档后报告将移动到归档区域。')) {
showNotification('报告已成功归档', 'info');
}
}
function shareReport() {
const reportTitle = document.getElementById('unified-report-title').textContent;
console.log(`分享报告: ${reportTitle}`);
// 创建分享模态框
const shareModal = document.createElement('div');
shareModal.className = 'fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center';
shareModal.innerHTML = `
<div class="bg-white rounded-lg p-6 w-96 max-w-90vw">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-900">分享报告</h3>
<button onclick="this.closest('.fixed').remove()" class="text-gray-400 hover:text-gray-600">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">分享链接</label>
<div class="flex">
<input type="text" value="https://example.com/reports/share/abc123" readonly
class="flex-1 px-3 py-2 border border-gray-300 rounded-l-lg bg-gray-50 text-sm">
<button onclick="copyToClipboard(this.previousElementSibling.value)"
class="px-4 py-2 bg-primary-600 text-white rounded-r-lg hover:bg-primary-700 text-sm">
复制
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">邀请成员</label>
<input type="email" placeholder="输入邮箱地址"
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm">
</div>
<div class="flex justify-end gap-3">
<button onclick="this.closest('.fixed').remove()"
class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 text-sm">
取消
</button>
<button onclick="sendInvite(); this.closest('.fixed').remove()"
class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 text-sm">
发送邀请
</button>
</div>
</div>
</div>
`;
document.body.appendChild(shareModal);
}
function rerunReport() {
const reportTitle = document.getElementById('unified-report-title').textContent;
console.log(`重新执行报告: ${reportTitle}`);
if (confirm('确定要重新执行这份报告吗?这将使用最新的数据源重新生成报告。')) {
showNotification('报告重新执行已开始预计需要5-10分钟', 'info');
}
}
// 溯源详情展开/收起
function toggleTraceDetails() {
const details = document.getElementById('trace-details');
const button = event.target;
if (details.classList.contains('hidden')) {
details.classList.remove('hidden');
button.textContent = '收起详情';
} else {
details.classList.add('hidden');
button.textContent = '展开详情';
}
}
// 辅助功能
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
showNotification('链接已复制到剪贴板', 'success');
}).catch(() => {
showNotification('复制失败,请手动复制', 'error');
});
}
function sendInvite() {
showNotification('邀请已发送', 'success');
}
// 创建任务
function createTask(name, schedule, infoSourceInfo) {
const taskId = Date.now().toString();
showNotification('任务创建成功!');
}
// 更新任务
function updateTask(taskId, name, schedule) {
showNotification('任务修改成功!');
}
// 全局信息源功能
window.toggleSourceCategory = function(sourceKey) {
console.log('toggleSourceCategory 被调用:', sourceKey);
const categoryChildren = document.querySelector(`#category-${sourceKey}`);
const arrow = document.querySelector(`[data-source="${sourceKey}"] .category-arrow`);
if (categoryChildren && categoryChildren.classList.contains('hidden')) {
categoryChildren.classList.remove('hidden');
if (arrow) arrow.style.transform = 'rotate(90deg)';
} else if (categoryChildren) {
categoryChildren.classList.add('hidden');
if (arrow) arrow.style.transform = 'rotate(0deg)';
}
};
window.addSourceToSelected = function(sourceKey, sourceName) {
// 这个函数将在showTaskModal内部重新定义
console.log('添加信息源:', sourceKey, sourceName);
};
window.removeSourceFromSelected = function(itemKey) {
// 这个函数将在showTaskModal内部重新定义
console.log('移除信息源:', itemKey);
};
window.toggleWebSearch = function(checkbox) {
const svg = checkbox.querySelector('svg');
if (svg.classList.contains('hidden')) {
svg.classList.remove('hidden');
checkbox.classList.add('border-primary-600', 'bg-primary-50');
} else {
svg.classList.add('hidden');
checkbox.classList.remove('border-primary-600', 'bg-primary-50');
}
};
window.showAddWebUrlModal = function() {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[10001] add-web-modal';
modal.innerHTML = `
<div class="bg-white rounded-lg w-full max-w-md mx-4">
<div class="flex items-center justify-between p-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-900">添加网页</h3>
<button class="text-gray-400 hover:text-gray-600" onclick="closeAddWebModal()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="p-4">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">网页URL</label>
<input type="url" id="web-url-input" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent" placeholder="https://...">
</div>
<div class="flex justify-end gap-3">
<button class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 transition-colors" onclick="closeAddWebModal()">
取消
</button>
<button class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors" onclick="addWebUrl()">
添加
</button>
</div>
</div>
</div>
`;
document.body.appendChild(modal);
setTimeout(() => {
const input = modal.querySelector('#web-url-input');
if (input) input.focus();
}, 100);
};
window.closeAddWebModal = function() {
const addWebModal = document.querySelector('.add-web-modal');
if (addWebModal) {
addWebModal.remove();
}
};
window.showAddOfficialAccountModal = function() {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[10001] add-official-account-modal';
modal.innerHTML = `
<div class="bg-white rounded-lg w-full max-w-md mx-4">
<div class="flex items-center justify-between p-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-900">添加公众号</h3>
<button class="text-gray-400 hover:text-gray-600" onclick="closeAddOfficialAccountModal()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="p-4">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">公众号文章URL</label>
<input type="url" id="official-account-url-input" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent" placeholder="https://...">
</div>
<div class="flex justify-end gap-3">
<button class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 transition-colors" onclick="closeAddOfficialAccountModal()">
取消
</button>
<button class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors" onclick="addOfficialAccount()">
添加
</button>
</div>
</div>
</div>
`;
document.body.appendChild(modal);
setTimeout(() => {
const input = modal.querySelector('#official-account-url-input');
if (input) input.focus();
}, 100);
};
window.closeAddOfficialAccountModal = function() {
const addOfficialAccountModal = document.querySelector('.add-official-account-modal');
if (addOfficialAccountModal) {
addOfficialAccountModal.remove();
}
};
window.addWebUrl = function() {
const urlInput = document.getElementById('web-url-input');
const url = urlInput.value.trim();
if (!url) {
alert('请输入网页URL');
return;
}
if (!url.startsWith('http://') && !url.startsWith('https://')) {
alert('请输入有效的URL需要包含http://或https://');
return;
}
const urlName = `自定义网页-${Date.now()}`;
const itemKey = `tempWeb-${urlName}`;
// 检查是否已经添加过相同的URL
if (window.tempWebsites && window.tempWebsites.some(site => site.url === url)) {
alert('该网页已经添加过了');
return;
}
// 添加到临时网页存储
if (!window.tempWebsites) {
window.tempWebsites = [];
}
window.tempWebsites.push({
name: urlName,
url: url
});
// 自动添加到已选信息源列表(如果模态框已打开)
if (typeof window.selectedSourceItems !== 'undefined') {
window.selectedSourceItems.add(itemKey);
window.selectedInfoSources.add('tempWeb');
// 更新已选信息源列表显示
if (typeof window.updateSelectedSourcesList === 'function') {
window.updateSelectedSourcesList();
}
}
closeAddWebModal();
showNotification('网页添加成功');
};
window.addOfficialAccount = function() {
const urlInput = document.getElementById('official-account-url-input');
const url = urlInput.value.trim();
if (!url) {
alert('请输入公众号文章URL');
return;
}
if (!url.startsWith('http://') && !url.startsWith('https://')) {
alert('请输入有效的URL需要包含http://或https://');
return;
}
const accountName = `自定义公众号-${Date.now()}`;
const itemKey = `tempOfficialAccount-${accountName}`;
// 检查是否已经添加过相同的URL
if (window.tempOfficialAccounts && window.tempOfficialAccounts.some(account => account.url === url)) {
alert('该公众号已经添加过了');
return;
}
// 添加到临时公众号存储
if (!window.tempOfficialAccounts) {
window.tempOfficialAccounts = [];
}
window.tempOfficialAccounts.push({
name: accountName,
displayName: accountName,
url: url
});
// 自动添加到已选信息源列表(如果模态框已打开)
if (typeof window.selectedSourceItems !== 'undefined') {
window.selectedSourceItems.add(itemKey);
window.selectedInfoSources.add('tempOfficialAccount');
// 更新已选信息源列表显示
if (typeof window.updateSelectedSourcesList === 'function') {
window.updateSelectedSourcesList();
}
}
closeAddOfficialAccountModal();
showNotification('公众号添加成功');
};
// 全局函数:切换信息源子项选择状态
window.toggleSourceItem = function(itemKey, element) {
if (window.selectedSourceItems && window.selectedSourceItems.has(itemKey)) {
window.selectedSourceItems.delete(itemKey);
const checkbox = element.querySelector('.w-4.h-4');
const svg = checkbox.querySelector('svg');
checkbox.classList.remove('border-primary-600', 'bg-primary-50');
svg.classList.add('hidden');
} else if (window.selectedSourceItems) {
window.selectedSourceItems.add(itemKey);
const checkbox = element.querySelector('.w-4.h-4');
const svg = checkbox.querySelector('svg');
checkbox.classList.add('border-primary-600', 'bg-primary-50');
svg.classList.remove('hidden');
}
};
// 全局函数:删除临时网页项
window.deleteTempWebItem = function(sourceName, event) {
event.stopPropagation(); // 阻止事件冒泡
const itemKey = `tempWeb-${sourceName}`;
// 从选中的信息源子项中移除
if (window.selectedSourceItems) {
window.selectedSourceItems.delete(itemKey);
}
// 从临时网页数据中移除
window.tempWebsites = window.tempWebsites.filter(item => item.name !== sourceName);
// 重新渲染列表
window.updateSelectedSourcesList();
showNotification('网页删除成功');
};
// 全局函数:删除临时公众号项
window.deleteTempOfficialAccountItem = function(sourceName, event) {
event.stopPropagation(); // 阻止事件冒泡
const itemKey = `tempOfficialAccount-${sourceName}`;
// 从选中的信息源子项中移除
if (window.selectedSourceItems) {
window.selectedSourceItems.delete(itemKey);
}
// 从临时公众号数据中移除
window.tempOfficialAccounts = window.tempOfficialAccounts.filter(item => item.name !== sourceName);
// 重新渲染列表
window.updateSelectedSourcesList();
showNotification('公众号删除成功');
};
// 全局函数:删除所有临时信息源
window.deleteAllTempSources = function() {
// 移除所有临时信息源相关的选中项
if (window.selectedSourceItems) {
Array.from(window.selectedSourceItems).forEach(itemKey => {
if (itemKey.startsWith('tempWeb-') || itemKey.startsWith('tempOfficialAccount-')) {
window.selectedSourceItems.delete(itemKey);
}
});
}
// 清空临时数据
window.tempWebsites = [];
window.tempOfficialAccounts = [];
// 重新渲染列表
window.updateSelectedSourcesList();
showNotification('临时信息源区域已删除');
};
// 辅助函数
function getTaskName(taskId) {
return '';
}
function getTaskSchedule(taskId) {
return 'once';
}
</script>
</body>
</html>