aegon-gen 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/package.json +12 -0
  2. package/src/App.vue +3 -0
  3. package/src/api/index.ts +19 -0
  4. package/src/api/modules/gen-ai/gen-entry/index.ts +30 -0
  5. package/src/api/modules/gen-ai/model-manager/index.ts +42 -0
  6. package/src/api/modules/gen-ai/model-manager/mockApi.ts +33 -0
  7. package/src/api/modules/index.ts +98 -0
  8. package/src/api/modules/user/index.ts +4 -0
  9. package/src/api/request.ts +102 -0
  10. package/src/assets/sample-access-icon.png +0 -0
  11. package/src/assets/sample-pie-chart.png +0 -0
  12. package/src/assets/vue.svg +1 -0
  13. package/src/components/CapsuleScrollbar.vue +93 -0
  14. package/src/components/Export/ExcelExport.vue +592 -0
  15. package/src/components/Export/ExcelExport2.vue +494 -0
  16. package/src/components/Export/ExcelExport3.vue +342 -0
  17. package/src/components/Export/ExcelExport4.vue +665 -0
  18. package/src/components/Export/excelExport.js +547 -0
  19. package/src/components/Export/excelExport.ts +551 -0
  20. package/src/components/GEN-AI/index.vue +142 -0
  21. package/src/components/GEN-AI/index1.vue +456 -0
  22. package/src/components/GEN-AI/index10.vue +5 -0
  23. package/src/components/GEN-AI/index2.vue +568 -0
  24. package/src/components/GEN-AI/index3.vue +623 -0
  25. package/src/components/GEN-AI/index4.vue +629 -0
  26. package/src/components/GEN-AI/index5.vue +578 -0
  27. package/src/components/GEN-AI/index6.vue +656 -0
  28. package/src/components/GEN-AI/index7.vue +717 -0
  29. package/src/components/GEN-AI/index8.vue +405 -0
  30. package/src/components/GEN-AI/index9.vue +1065 -0
  31. package/src/components/GEN-AI/types.ts +12 -0
  32. package/src/components/GEN-AI/utils.ts +42 -0
  33. package/src/components/HelloWorld.vue +41 -0
  34. package/src/components/PageCard.vue +7 -0
  35. package/src/components/PageHeader.vue +32 -0
  36. package/src/components/backup/index5 copy.vue +556 -0
  37. package/src/components/backup/index5.vue +620 -0
  38. package/src/components/backup/index9 copy.vue +1029 -0
  39. package/src/components/backup/index9-pro.vue +1065 -0
  40. package/src/components/backup/index9.vue +1057 -0
  41. package/src/components/el-date-picker.vue +64 -0
  42. package/src/directives/btnLoading.ts +427 -0
  43. package/src/directives/debounce copy.ts +670 -0
  44. package/src/directives/debounce.ts +98 -0
  45. package/src/directives/index.ts +25 -0
  46. package/src/layouts/MainLayout.vue +101 -0
  47. package/src/main.ts +85 -0
  48. package/src/router/index.ts +76 -0
  49. package/src/router/menus.ts +28 -0
  50. package/src/style.css +79 -0
  51. package/src/styles/_variables.scss +24 -0
  52. package/src/styles/app-button.css +26 -0
  53. package/src/styles/element-overrides.css +23 -0
  54. package/src/styles/global.css +44 -0
  55. package/src/styles/index.scss +1 -0
  56. package/src/styles/page-card.css +21 -0
  57. package/src/styles/variables.css +26 -0
  58. package/src/test/mock.ts +101 -0
  59. package/src/test/test1.vue +402 -0
  60. package/src/test/test2.vue +1689 -0
  61. package/src/types/gen-ai/gen-entry/index.ts +17 -0
  62. package/src/types/gen-ai/model-manager/index.ts +19 -0
  63. package/src/utils/docxExport.ts +1610 -0
  64. package/src/utils/gen-ai-navigation.ts +37 -0
  65. package/src/utils/gen-ai-scroll.ts +455 -0
  66. package/src/utils/openDataLoaderWordExport.ts +33 -0
  67. package/src/utils/pageScrollbar.ts +115 -0
  68. package/src/utils/randomTranscode.ts +87 -0
  69. package/src/utils/reportPdfExport.ts +44 -0
  70. package/src/views/AdminCenter/index.vue +817 -0
  71. package/src/views/Blank.vue +68 -0
  72. package/src/views/Home.vue +29 -0
  73. package/src/views/ReportCenter/index.vue +1380 -0
  74. package/src/views/TemplateCenter/Knowledge.ts +83 -0
  75. package/src/views/TemplateCenter/data.d.ts +10 -0
  76. package/src/views/TemplateCenter/index.vue +1205 -0
  77. package/src/views/TemplateCenter/service.ts +69 -0
  78. package/src/views/gen-ai/components/RecentReportsTable.vue +193 -0
  79. package/src/views/gen-ai/gen-entry/index.vue +309 -0
  80. package/src/views/gen-ai/gen-entry/mockData.ts +160 -0
  81. package/src/views/gen-ai/management-center/index.vue +53 -0
  82. package/src/views/gen-ai/model-manager/ChapterTitleScroll.vue +275 -0
  83. package/src/views/gen-ai/model-manager/index.vue +1205 -0
  84. package/src/views/gen-ai/model-manager/mockData.ts +122 -0
  85. package/src/views/gen-ai/report-center/index.vue +158 -0
  86. package/src/vite-env.d.ts +38 -0
@@ -0,0 +1,1205 @@
1
+ <template>
2
+ <div class="template-center-page">
3
+ <PageHeader title="IR-DEMO" />
4
+
5
+ <div class="chatbot-report-shell">
6
+ <!-- 左侧:报告配置 -->
7
+ <aside class="chatbot-report-panel chatbot-report-panel--config left">
8
+ <div class="chatbot-report-panel__body">
9
+ <h3 class="chatbot-report-config-title">報告配置</h3>
10
+ <div class="chatbot-report-field">
11
+ <span class="chatbot-report-field__label">名稱</span>
12
+ <span class="chatbot-report-field__value">
13
+ {{ activeConversation?.label || 'Hedera 鏈上運營 2026' }}
14
+ </span>
15
+ <EditPen class="chatbot-report-field__edit" @click="newChat" />
16
+ </div>
17
+ <div class="chatbot-report-field">
18
+ <span class="chatbot-report-field__label">模型</span>
19
+ <span class="chatbot-report-field__value">
20
+ {{ useLocalFallback ? '本地知識庫' : displayModel }}
21
+ </span>
22
+ <EditPen class="chatbot-report-field__edit" @click="useLocalFallback = !useLocalFallback" />
23
+ </div>
24
+ <div class="chatbot-report-field chatbot-report-field--readonly">
25
+ <span class="chatbot-report-field__label">語言</span>
26
+ <span class="chatbot-report-field__value">中文</span>
27
+ </div>
28
+ <div class="chatbot-report-field chatbot-report-field--readonly">
29
+ <span class="chatbot-report-field__label">行業</span>
30
+ <span class="chatbot-report-field__value">Hedera 鏈上運營</span>
31
+ </div>
32
+ <div class="chatbot-report-field chatbot-report-field--readonly">
33
+ <span class="chatbot-report-field__label">年份</span>
34
+ <span class="chatbot-report-field__value">2026</span>
35
+ </div>
36
+
37
+ <div class="chatbot-report-section-title">信息源</div>
38
+ <div class="chatbot-report-add-source" role="presentation">
39
+ <div style="display: flex; align-items: center;justify-content: center;">
40
+ <span class="chatbot-report-add-source__icon"><Plus /></span>
41
+ </div>
42
+ <div>
43
+ 添加信息源
44
+ </div>
45
+ </div>
46
+ <button type="button" class="chatbot-report-web-search" @click="webSearch = !webSearch">
47
+ <CheckMark :checked="webSearch" />
48
+ 在網絡中搜索信息源
49
+ </button>
50
+
51
+ <div class="chatbot-report-source-select">
52
+ <div class="chatbot-report-select-all" @click="toggleAllDocs">
53
+ <span>選擇所有信息源</span>
54
+ <CheckMark :checked="allDocsSelected" />
55
+ </div>
56
+
57
+ <div class="chatbot-report-doc-group">
58
+ <div
59
+ class="chatbot-report-doc-group__header chatbot-report-source-row"
60
+ @click="toggleDocGroup(SHARED_DOCS.map(d => d.id))"
61
+ >
62
+ <span class="chatbot-report-source-row__label">共享文檔集</span>
63
+ <CheckMark :checked="SHARED_DOCS.every(d => selectedDocs[d.id])" />
64
+ </div>
65
+ <div
66
+ v-for="doc in SHARED_DOCS"
67
+ :key="doc.id"
68
+ class="chatbot-report-source-row chatbot-report-source-row--doc"
69
+ @click="toggleDoc(doc.id)"
70
+ >
71
+ <PdfIcon />
72
+ <span class="chatbot-report-source-row__label">{{ doc.title }}</span>
73
+ <CheckMark :checked="!!selectedDocs[doc.id]" />
74
+ </div>
75
+ </div>
76
+
77
+ <div class="chatbot-report-doc-group">
78
+ <div
79
+ class="chatbot-report-doc-group__header chatbot-report-source-row"
80
+ @click="toggleDocGroup(PERSONAL_DOCS.map(d => d.id))"
81
+ >
82
+ <span class="chatbot-report-source-row__label">個人文檔集</span>
83
+ <CheckMark :checked="PERSONAL_DOCS.every(d => selectedDocs[d.id])" />
84
+ </div>
85
+ <div
86
+ v-for="doc in PERSONAL_DOCS"
87
+ :key="doc.id"
88
+ class="chatbot-report-source-row chatbot-report-source-row--doc"
89
+ @click="toggleDoc(doc.id)"
90
+ >
91
+ <PdfIcon />
92
+ <span class="chatbot-report-source-row__label">{{ doc.title }}</span>
93
+ <CheckMark :checked="!!selectedDocs[doc.id]" />
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </aside>
99
+
100
+ <!-- 中间:对话预览(当前注释,保留占位) -->
101
+ <main class="chatbot-report-center center">
102
+ <div class="chatbot-report-toolbar">
103
+ <el-button class="chatbot-report-btn-outline" @click="backToChapterEdit">返回章节编辑</el-button>
104
+ <div>
105
+ <el-button
106
+ class="chatbot-report-btn-outline"
107
+ :icon="Download"
108
+ :disabled="!reportPreviewVisible"
109
+ @click="exportReportPdf"
110
+ >
111
+ 匯出為 PDF
112
+ </el-button>
113
+ <el-button
114
+ class="chatbot-report-btn-outline"
115
+ :icon="Download"
116
+ :disabled="!reportPreviewVisible"
117
+ @click="exportReportWord"
118
+ >
119
+ 匯出為 Word
120
+ </el-button>
121
+ </div>
122
+ </div>
123
+
124
+ <div v-if="!reportPreviewVisible" class="chatbot-report-center__empty">
125
+ <p>選擇章節後點擊「生成報告」預覽內容</p>
126
+ </div>
127
+ <div v-else class="chatbot-report-center__preview">
128
+ <!-- 暂时:SSE 流式调试面板(postRequest + Token) -->
129
+ <div class="chatbot-report-stream-debug">
130
+ <div v-if="isRequesting" class="chatbot-report-stream-debug__status">输出中...</div>
131
+ <div class="chatbot-report-stream-debug__body">{{ reportStreamText || '等待 SSE 数据...' }}</div>
132
+ </div>
133
+ <!-- index9 预览(调试完成后可改回 v-if="!reportSseDebug") -->
134
+ <GenAiIndex9
135
+ v-if="false"
136
+ ref="reportPreviewRef"
137
+ embedded
138
+ :key="reportPreviewKey"
139
+ />
140
+ </div>
141
+ </main>
142
+
143
+ <!-- 右侧:生成報告設置 -->
144
+ <aside class="chatbot-report-panel chatbot-report-panel--settings right">
145
+ <div class="chatbot-report-panel__body">
146
+ <h3 class="chatbot-report-config-title">生成報告設置</h3>
147
+
148
+ <div class="chatbot-report-chapter-select">
149
+ <div class="chatbot-report-chapter-header">
150
+ <span class="chatbot-report-chapter-header__title">選擇章節及版本</span>
151
+ <div class="chatbot-report-chapter-header__all" @click="toggleAllChapters">
152
+ <CheckMark :checked="allChaptersSelected" />
153
+ <span>全部章節</span>
154
+ </div>
155
+ </div>
156
+ <div class="chatbot-report-chapter-list">
157
+ <div
158
+ v-for="preset in orderedPresets"
159
+ :key="preset.key"
160
+ class="chatbot-report-chapter-row"
161
+ :class="{
162
+ 'is-dragging': dragChapterKey === preset.key,
163
+ 'is-drag-over': dragOverChapterKey === preset.key,
164
+ }"
165
+ draggable="true"
166
+ @dragstart="onChapterDragStart($event, preset.key)"
167
+ @dragend="handleChapterDragEnd"
168
+ @dragover.prevent="setDragOverChapterKey(preset.key)"
169
+ @drop="handleChapterDrop(preset.key)"
170
+ >
171
+ <CheckMark
172
+ :checked="!!selectedChapters[preset.key]"
173
+ @click.stop="toggleChapter(preset.key)"
174
+ @mousedown.stop
175
+ @dragstart.prevent
176
+ />
177
+ <span
178
+ class="chatbot-report-chapter-row__label"
179
+ @click="setActiveKey(preset.key); sendMessage(preset.label)"
180
+ >
181
+ {{ preset.label }}
182
+ </span>
183
+ <select
184
+ class="chatbot-report-chapter-row__version"
185
+ :value="chapterVersions[preset.key]"
186
+ @change="chapterVersions[preset.key] = ($event.target as HTMLSelectElement).value"
187
+ @click.stop
188
+ @mousedown.stop
189
+ >
190
+ <option v-for="v in CHAPTER_VERSIONS" :key="v" :value="v">{{ v }}</option>
191
+ </select>
192
+ </div>
193
+ </div>
194
+ </div>
195
+
196
+ <div class="chatbot-report-section-title chatbot-report-section-title--settings">生成報告方式</div>
197
+ <el-radio-group v-model="reportMode" class="chatbot-report-radio-group">
198
+ <el-radio value="polish">拼裝並潤色</el-radio>
199
+ <el-radio value="rewrite">重寫整篇報告</el-radio>
200
+ </el-radio-group>
201
+
202
+ <button
203
+ type="button"
204
+ class="chatbot-report-generate-btn"
205
+ :disabled="isRequesting"
206
+ @click="generateFromChapters"
207
+ >
208
+ 生成報告
209
+ </button>
210
+
211
+ <div class="chatbot-report-history">
212
+ <div class="chatbot-report-history__title">報告歷史</div>
213
+ <div class="chatbot-report-history-list">
214
+ <div
215
+ v-for="item in reportHistory"
216
+ :key="item.key"
217
+ class="chatbot-report-history-row"
218
+ :class="{ 'is-active': item.key === activeHistoryKey }"
219
+ @click="activeHistoryKey = item.key"
220
+ >
221
+ <span class="chatbot-report-history-item__indicator" aria-hidden="true" />
222
+ <div class="chatbot-report-history-item">
223
+ <div class="chatbot-report-history-item__body">
224
+ <div class="chatbot-report-history-item__title">{{ item.title }}</div>
225
+ <div class="chatbot-report-history-item__meta">
226
+ {{ item.author }} {{ item.time }}
227
+ </div>
228
+ </div>
229
+ <MoreFilled class="chatbot-report-history-item__menu" @click.stop />
230
+ </div>
231
+ </div>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ </aside>
236
+ </div>
237
+ </div>
238
+ </template>
239
+
240
+ <script setup lang="ts">
241
+ import { ref, computed, nextTick, h, defineComponent, onUnmounted } from 'vue'
242
+ import { ElButton, ElRadioGroup, ElRadio } from 'element-plus'
243
+ import {
244
+ EditPen,
245
+ Plus,
246
+ Download,
247
+ MoreFilled,
248
+ } from '@element-plus/icons-vue'
249
+ import GenAiIndex9 from '../../components/GEN-AI/index9.vue'
250
+ import {
251
+ MOCK_REPORT_STREAM_TEXT,
252
+ reportApi,
253
+ streamGenerateReport,
254
+ } from '../../api'
255
+ import {
256
+ CHAT_MODEL,
257
+ streamChatCompletion,
258
+ } from './service'
259
+ import {
260
+ HEDERA_SYSTEM_PROMPT,
261
+ matchLocalKnowledge,
262
+ } from './Knowledge'
263
+
264
+ const displayModel = CHAT_MODEL.split('/').pop()?.replace(/:.*$/, '') ?? 'Qwen3-Max'
265
+
266
+ const SHARED_DOCS = [
267
+ { id: 'hts', title: 'Hedera HTS 代币创建与 KYC 操作指南' },
268
+ { id: 'hscs', title: 'HSCS 智能合约部署与调试手册' },
269
+ { id: 'rwa', title: 'RWA 上链 metadata 与 HCS 存证说明' },
270
+ ]
271
+ const PERSONAL_DOCS = [
272
+ { id: 'env', title: 'Operator .env 配置与 Mirror Node 说明' },
273
+ { id: 'gov', title: 'Governance 密钥矩阵与 KYC 准入流程' },
274
+ { id: 'audit', title: 'AI 审计与链上风险事件采样' },
275
+ ]
276
+ const ALL_DOC_IDS = [...SHARED_DOCS, ...PERSONAL_DOCS].map(d => d.id)
277
+ const HEDERA_PRESETS = [
278
+ { key: 'preset-summary', label: '摘要與本年總結', group: 'Hedera' },
279
+ { key: 'preset-macro', label: '宏觀環境與政策背景', group: 'Hedera' },
280
+ { key: 'preset-industry', label: '行業運行情況與核心指標', group: 'Hedera' },
281
+ { key: 'preset-competition', label: '競爭格局與商業模式演變', group: 'Hedera' },
282
+ { key: 'preset-risk', label: '關鍵風險與監管關切', group: 'Hedera' },
283
+ { key: 'preset-appendix', label: '附錄:數據、方法與名詞解釋', group: 'Hedera' },
284
+ ]
285
+ const CHAPTER_VERSIONS = ['V1', 'V2', 'V3']
286
+
287
+ type ParsedMessage = { role: 'user'; content: string } | { role: 'assistant'; content: string; thinkContent?: string }
288
+ type ConversationItem = { key: string; label: string; group?: string; isDraft?: boolean }
289
+ type ReportHistoryItem = { key: string; title: string; author: string; time: string }
290
+
291
+ const CheckMark = defineComponent({
292
+ name: 'CheckMark',
293
+ inheritAttrs: false,
294
+ props: {
295
+ checked: { type: Boolean, required: true },
296
+ },
297
+ emits: ['click'],
298
+ setup(props, { emit, attrs }) {
299
+ return () =>
300
+ h('span', {
301
+ ...attrs,
302
+ class: ['chatbot-report-check', props.checked && 'is-checked', attrs.class],
303
+ onClick: (e: MouseEvent) => emit('click', e),
304
+ })
305
+ },
306
+ })
307
+
308
+ const PdfIcon = defineComponent({
309
+ name: 'PdfIcon',
310
+ setup() {
311
+ return () =>
312
+ h(
313
+ 'svg',
314
+ {
315
+ xmlns: 'http://www.w3.org/2000/svg',
316
+ viewBox: '0 0 1024 1024',
317
+ class: 'chatbot-report-doc-card__pdf',
318
+ },
319
+ [
320
+ h('path', {
321
+ fill: 'currentColor',
322
+ d: 'M832 384H576V128H192v768h640zm-26.496-64L640 154.496V320zM160 64h480l256 256v608a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V96a32 32 0 0 1 32-32m160 448h384v64H320zm0-192h160v64H320zm0 384h384v64H320z',
323
+ }),
324
+ ],
325
+ )
326
+ },
327
+ })
328
+
329
+ const useLocalFallback = ref(false)
330
+ const webSearch = ref(true)
331
+ const conversations = ref<ConversationItem[]>([
332
+ { key: 'default', label: 'Hedera 运营问答', group: '今天', isDraft: true },
333
+ ...HEDERA_PRESETS,
334
+ ])
335
+ const activeKey = ref('default')
336
+ const activeHistoryKey = ref('history-final')
337
+ const reportHistory = ref<ReportHistoryItem[]>([
338
+ { key: 'history-final', title: '定稿版本', author: '陳大文', time: '15min前' },
339
+ { key: 'history-v2', title: 'V2', author: '陳大文', time: '15min前' },
340
+ ])
341
+ const inputValue = ref('')
342
+ const selectedDocs = ref<Record<string, boolean>>(Object.fromEntries(ALL_DOC_IDS.map(id => [id, true])))
343
+ const selectedChapters = ref<Record<string, boolean>>(Object.fromEntries(HEDERA_PRESETS.map(p => [p.key, true])))
344
+ const chapterVersions = ref<Record<string, string>>(Object.fromEntries(HEDERA_PRESETS.map(p => [p.key, 'V3'])))
345
+ const chapterOrder = ref<string[]>(HEDERA_PRESETS.map(p => p.key))
346
+ const reportMode = ref('polish')
347
+ const isRequesting = ref(false)
348
+ const reportPreviewVisible = ref(false)
349
+ const reportPreviewKey = ref(0)
350
+ const reportPreviewRef = ref<InstanceType<typeof GenAiIndex9> | null>(null)
351
+ /** 报告 SSE 流文本:Mock 或真实接口返回,后续可替换 index9 内容源 */
352
+ const reportStreamText = ref('')
353
+ let reportStreamAbort: AbortController | null = null
354
+ const messages = ref<ParsedMessage[]>([])
355
+ const dragChapterKey = ref<string | null>(null)
356
+ const dragOverChapterKey = ref<string | null>(null)
357
+
358
+ const setDragOverChapterKey = (key: string) => {
359
+ dragOverChapterKey.value = key
360
+ }
361
+
362
+ const activeConversation = computed(() => conversations.value.find(c => c.key === activeKey.value))
363
+ const orderedPresets = computed(() => chapterOrder.value.map(key => HEDERA_PRESETS.find(p => p.key === key)!).filter(Boolean))
364
+ const allDocsSelected = computed(() => ALL_DOC_IDS.every(id => selectedDocs.value[id]))
365
+ const allChaptersSelected = computed(() => HEDERA_PRESETS.every(p => selectedChapters.value[p.key]))
366
+
367
+ const toggleDoc = (id: string) => {
368
+ selectedDocs.value[id] = !selectedDocs.value[id]
369
+ }
370
+ const toggleAllDocs = () => {
371
+ const next = !allDocsSelected.value
372
+ selectedDocs.value = Object.fromEntries(ALL_DOC_IDS.map(id => [id, next]))
373
+ }
374
+ const toggleDocGroup = (ids: string[]) => {
375
+ const allOn = ids.every(id => selectedDocs.value[id])
376
+ ids.forEach(id => {
377
+ selectedDocs.value[id] = !allOn
378
+ })
379
+ }
380
+ const toggleChapter = (key: string) => {
381
+ selectedChapters.value[key] = !selectedChapters.value[key]
382
+ }
383
+ const toggleAllChapters = () => {
384
+ const next = !allChaptersSelected.value
385
+ HEDERA_PRESETS.forEach(p => {
386
+ selectedChapters.value[p.key] = next
387
+ })
388
+ }
389
+ const setActiveKey = (key: string) => {
390
+ activeKey.value = key
391
+ }
392
+ const newChat = () => {
393
+ const key = crypto.randomUUID()
394
+ conversations.value = [{ key, label: '新对话', group: '今天', isDraft: true }, ...conversations.value.filter(c => c.key !== key)]
395
+ activeKey.value = key
396
+ messages.value = []
397
+ }
398
+ const backToChapterEdit = () => {
399
+ reportPreviewVisible.value = false
400
+ }
401
+ const generateFromChapters = async () => {
402
+ const selected = orderedPresets.value.filter(p => selectedChapters.value[p.key])
403
+ if (!selected.length) return
404
+
405
+ const token = reportApi.getToken()
406
+ if (!token) {
407
+ alert('请先登录')
408
+ return
409
+ }
410
+
411
+ if (reportStreamAbort) reportStreamAbort.abort()
412
+ reportStreamAbort = new AbortController()
413
+
414
+ isRequesting.value = true
415
+ reportStreamText.value = ''
416
+ reportPreviewKey.value += 1
417
+ reportPreviewVisible.value = true
418
+
419
+ const question = selected.map(p => p.label).join('、')
420
+
421
+ try {
422
+ for await (const chunk of streamGenerateReport(
423
+ {
424
+ userId: 'user001',
425
+ question,
426
+ chapters: selected.map(p => p.label),
427
+ chapterVersions: Object.fromEntries(
428
+ selected.map((p) => [p.key, chapterVersions.value[p.key] ?? 'V3']),
429
+ ),
430
+ reportMode: reportMode.value,
431
+ },
432
+ reportStreamAbort.signal,
433
+ )) {
434
+ reportStreamText.value += chunk
435
+ }
436
+ } catch (err) {
437
+ if ((err as Error).name !== 'AbortError') {
438
+ console.error('流异常', err)
439
+ reportStreamText.value = `[SSE 请求失败] ${(err as Error).message}\n\n${MOCK_REPORT_STREAM_TEXT}`
440
+ }
441
+ } finally {
442
+ isRequesting.value = false
443
+ reportStreamAbort = null
444
+ }
445
+ }
446
+
447
+ onUnmounted(() => {
448
+ reportStreamAbort?.abort()
449
+ })
450
+ const exportReportPdf = () => {
451
+ reportPreviewRef.value?.handleExportPDF()
452
+ }
453
+ const exportReportWord = () => {
454
+ reportPreviewRef.value?.handleExportWord()
455
+ }
456
+
457
+ const handleChapterDragStart = (key: string) => {
458
+ dragChapterKey.value = key
459
+ dragOverChapterKey.value = key
460
+ }
461
+ const onChapterDragStart = (event: DragEvent, key: string) => {
462
+ if ((event.target as HTMLElement).closest('.chatbot-report-check, .chatbot-report-chapter-row__version')) {
463
+ event.preventDefault()
464
+ return
465
+ }
466
+ handleChapterDragStart(key)
467
+ }
468
+ const handleChapterDragEnd = () => {
469
+ dragChapterKey.value = null
470
+ dragOverChapterKey.value = null
471
+ }
472
+ const handleChapterDrop = (targetKey: string) => {
473
+ const draggingKey = dragChapterKey.value
474
+ if (draggingKey && draggingKey !== targetKey) {
475
+ const newOrder = [...chapterOrder.value]
476
+ const fromIdx = newOrder.indexOf(draggingKey)
477
+ const toIdx = newOrder.indexOf(targetKey)
478
+ if (fromIdx !== -1 && toIdx !== -1) {
479
+ newOrder.splice(fromIdx, 1)
480
+ newOrder.splice(toIdx, 0, draggingKey)
481
+ chapterOrder.value = newOrder
482
+ }
483
+ }
484
+ handleChapterDragEnd()
485
+ }
486
+
487
+ const sendMessage = async (text: string) => {
488
+ if (!text.trim()) return
489
+ inputValue.value = ''
490
+ messages.value.push({ role: 'user', content: text })
491
+ if (useLocalFallback.value) {
492
+ const answer = matchLocalKnowledge(text) ?? '本地知识库暂未收录该问题。请切换「云端模型」或尝试:创建代币、KYC、RWA、HSCS、暂停代币、Mirror Node 等关键词。'
493
+ messages.value.push({ role: 'assistant', content: answer })
494
+ return
495
+ }
496
+ isRequesting.value = true
497
+ const apiMessages = [
498
+ { role: 'system', content: HEDERA_SYSTEM_PROMPT },
499
+ { role: 'user', content: text },
500
+ ]
501
+ try {
502
+ let fullContent = ''
503
+ messages.value.push({ role: 'assistant', content: '' })
504
+ const lastIndex = messages.value.length - 1
505
+ for await (const chunk of streamChatCompletion(apiMessages)) {
506
+ fullContent += chunk
507
+ messages.value[lastIndex] = { role: 'assistant', content: fullContent }
508
+ await nextTick()
509
+ }
510
+ } catch (err) {
511
+ console.error(err)
512
+ messages.value.push({ role: 'assistant', content: '请求失败,请检查网络或 API 配置。' })
513
+ } finally {
514
+ isRequesting.value = false
515
+ }
516
+ }
517
+ </script>
518
+
519
+ <style lang="scss" scoped>
520
+ .template-center-page {
521
+ display: flex;
522
+ flex-direction: column;
523
+ height: 100vh;
524
+ overflow: hidden;
525
+ background: var(--report-bg, #f3f3f3);
526
+ }
527
+
528
+ .chatbot-report-shell {
529
+ --report-accent: #c53355;
530
+ --report-accent-soft: #fdf0f2;
531
+ --report-border: #ebebeb;
532
+ --report-bg: #f3f3f3;
533
+ --report-text: #1a1a1a;
534
+ --report-muted: #999;
535
+ --report-card-bg: #f5f5f5;
536
+ --report-add-blue: #4a90d9;
537
+
538
+ flex: 1;
539
+ display: flex;
540
+ gap: 0px;
541
+ min-height: 0;
542
+ min-width: 0;
543
+ overflow: hidden;
544
+ background: var(--report-bg);
545
+ padding: 20px;
546
+ }
547
+
548
+ .chatbot-report-shell .left,
549
+ .chatbot-report-shell .right {
550
+ width: 20%;
551
+ min-width: 280px;
552
+ flex-shrink: 0;
553
+ }
554
+
555
+ .chatbot-report-shell .center {
556
+ flex: 1;
557
+ min-width: 520px;
558
+ min-height: 0;
559
+ display: flex;
560
+ flex-direction: column;
561
+ }
562
+
563
+ .chatbot-report-panel {
564
+ background: #fff;
565
+ border: 0px solid var(--report-border);
566
+ border-radius: 2px;
567
+ display: flex;
568
+ flex-direction: column;
569
+ min-height: 0;
570
+ overflow: hidden;
571
+ }
572
+
573
+ .chatbot-report-panel--config .chatbot-report-panel__body,
574
+ .chatbot-report-panel--settings .chatbot-report-panel__body {
575
+ padding: 16px 18px 20px;
576
+ }
577
+
578
+ .chatbot-report-panel__head {
579
+ padding: 14px 16px 10px;
580
+ font-size: 15px;
581
+ font-weight: 600;
582
+ color: var(--report-text);
583
+ border-bottom: 1px solid #f0f0f0;
584
+ flex-shrink: 0;
585
+ }
586
+
587
+ .chatbot-report-panel__body {
588
+ flex: 1;
589
+ overflow-y: auto;
590
+ }
591
+
592
+ .chatbot-report-config-title {
593
+ font-size: 15px;
594
+ font-weight: 600;
595
+ color: var(--report-text);
596
+ margin: 0 0 4px;
597
+ }
598
+
599
+ .chatbot-report-field {
600
+ display: grid;
601
+ grid-template-columns: 72px 1fr auto;
602
+ align-items: center;
603
+ gap: 8px;
604
+ padding: 11px 0;
605
+ border-bottom: 1px solid #f0f0f0;
606
+ font-size: 13px;
607
+ }
608
+
609
+ .chatbot-report-field--readonly {
610
+ grid-template-columns: 72px 1fr;
611
+ }
612
+
613
+ .chatbot-report-field__label {
614
+ color: var(--report-muted);
615
+ }
616
+
617
+ .chatbot-report-field__value {
618
+ text-align: right;
619
+ color: #555;
620
+ overflow: hidden;
621
+ text-overflow: ellipsis;
622
+ white-space: nowrap;
623
+ }
624
+
625
+ .chatbot-report-field__edit {
626
+ color: var(--report-accent);
627
+ cursor: pointer;
628
+ font-size: 13px;
629
+ }
630
+
631
+ .chatbot-report-section-title {
632
+ margin: 18px 0 12px;
633
+ font-size: 14px;
634
+ font-weight: 600;
635
+ color: var(--report-text);
636
+ }
637
+
638
+ .chatbot-report-add-source {
639
+ border: 1px dashed #d9d9d9;
640
+ border-radius: 20px;
641
+ padding: 20px;
642
+ text-align: center;
643
+ color: var(--report-muted);
644
+ cursor: pointer;
645
+ font-size: 13px;
646
+ background: #fff;
647
+ transition: border-color 0.2s;
648
+ }
649
+
650
+ .chatbot-report-add-source:hover {
651
+ border-color: var(--report-add-blue);
652
+ }
653
+
654
+ .chatbot-report-add-source__icon {
655
+ display: block;
656
+ font-size: 24px;
657
+ line-height: 1;
658
+ margin-bottom: 8px;
659
+ color: var(--report-add-blue);
660
+ width: 20px;
661
+ }
662
+
663
+ .chatbot-report-doc-card__pdf {
664
+ width: 14px;
665
+ height: 14px;
666
+ color: #c53355;
667
+ flex-shrink: 0;
668
+ }
669
+
670
+ .chatbot-report-web-search {
671
+ display: flex;
672
+ align-items: center;
673
+ gap: 10px;
674
+ width: 100%;
675
+ padding: 10px 14px;
676
+ border: none;
677
+ border-radius: 6px;
678
+ background: var(--report-card-bg);
679
+ font-size: 13px;
680
+ color: #555;
681
+ cursor: pointer;
682
+ text-align: left;
683
+ transition: background 0.15s;
684
+ box-sizing: border-box;
685
+ }
686
+
687
+ .chatbot-report-source-select .chatbot-report-source-row {
688
+ display: grid;
689
+ grid-template-columns: minmax(0, 1fr) var(--source-check-size);
690
+ column-gap: var(--source-check-gap);
691
+ align-items: center;
692
+ width: 100%;
693
+ padding: 10px var(--source-row-padding-x);
694
+ border: none;
695
+ border-radius: 6px;
696
+ background: var(--report-card-bg);
697
+ font-size: 13px;
698
+ color: #555;
699
+ cursor: pointer;
700
+ text-align: left;
701
+ transition: background 0.15s;
702
+ box-sizing: border-box;
703
+ }
704
+
705
+ .chatbot-report-source-select .chatbot-report-source-row--doc {
706
+ grid-template-columns: 14px minmax(0, 1fr) var(--source-check-size);
707
+ }
708
+
709
+ .chatbot-report-web-search:hover,
710
+ .chatbot-report-source-row:hover {
711
+ background: #efefef;
712
+ }
713
+
714
+ .chatbot-report-web-search {
715
+ margin-top: 12px;
716
+ }
717
+
718
+ .chatbot-report-source-row__label {
719
+ min-width: 0;
720
+ overflow: hidden;
721
+ text-overflow: ellipsis;
722
+ white-space: nowrap;
723
+ }
724
+
725
+ .chatbot-report-source-select {
726
+ --source-check-size: 20px;
727
+ --source-check-gap: 10px;
728
+ --source-row-padding-x: 12px;
729
+ }
730
+
731
+ .chatbot-report-select-all {
732
+ display: grid;
733
+ grid-template-columns: minmax(0, 1fr) var(--source-check-size);
734
+ column-gap: var(--source-check-gap);
735
+ align-items: center;
736
+ padding: 0 var(--source-row-padding-x);
737
+ margin: 16px 0 10px;
738
+ font-size: 13px;
739
+ color: #555;
740
+ cursor: pointer;
741
+ }
742
+
743
+ .chatbot-report-source-select .chatbot-report-check {
744
+ justify-self: end;
745
+ }
746
+
747
+ .chatbot-report-check {
748
+ flex-shrink: 0;
749
+ box-sizing: border-box;
750
+ width: 20px;
751
+ height: 20px;
752
+ border-radius: 50%;
753
+ border: 2px solid #ccc;
754
+ position: relative;
755
+ transition: all 0.2s;
756
+ cursor: pointer;
757
+ background: #fff;
758
+ }
759
+
760
+ .chatbot-report-check.is-checked {
761
+ border-color: #c53355;
762
+ background-color: #c53355;
763
+ }
764
+
765
+ .chatbot-report-check.is-checked::after {
766
+ content: '';
767
+ position: absolute;
768
+ left: 4px;
769
+ top: 1px;
770
+ width: 5px;
771
+ height: 9px;
772
+ border: solid #fff;
773
+ border-width: 0 2px 2px 0;
774
+ transform: rotate(45deg);
775
+ }
776
+
777
+ .chatbot-report-doc-group {
778
+ margin-top: 14px;
779
+ }
780
+
781
+ .chatbot-report-doc-group .chatbot-report-source-row {
782
+ margin-bottom: 8px;
783
+ }
784
+
785
+ .chatbot-report-doc-group .chatbot-report-source-row:last-child {
786
+ margin-bottom: 0;
787
+ }
788
+
789
+ .chatbot-report-doc-group__header.chatbot-report-source-row {
790
+ font-weight: 600;
791
+ color: var(--report-text);
792
+ }
793
+
794
+ .chatbot-report-center {
795
+ flex: 1;
796
+ height: 100%;
797
+ display: flex;
798
+ flex-direction: column;
799
+ min-height: 0;
800
+ background: #fff;
801
+ border-left: 1px solid var(--report-border);
802
+ border-right: 1px solid var(--report-border);
803
+ border-radius: 2px;
804
+ overflow: hidden;
805
+ }
806
+
807
+ .chatbot-report-center__empty {
808
+ flex: 1;
809
+ display: flex;
810
+ align-items: center;
811
+ justify-content: center;
812
+ min-height: 0;
813
+ padding: 24px;
814
+ color: #999;
815
+ font-size: 14px;
816
+ background: #fff;
817
+ }
818
+
819
+ .chatbot-report-center__preview {
820
+ flex: 1;
821
+ min-height: 0;
822
+ display: flex;
823
+ flex-direction: column;
824
+ overflow: hidden;
825
+ background: #fff;
826
+ }
827
+
828
+ .chatbot-report-stream-debug {
829
+ flex: 1;
830
+ min-height: 0;
831
+ display: flex;
832
+ flex-direction: column;
833
+ overflow: hidden;
834
+ background: #fff;
835
+ }
836
+
837
+ .chatbot-report-stream-debug__status {
838
+ flex-shrink: 0;
839
+ padding: 8px 16px;
840
+ font-size: 12px;
841
+ color: var(--report-accent);
842
+ border-bottom: 1px solid var(--report-border);
843
+ }
844
+
845
+ .chatbot-report-stream-debug__body {
846
+ flex: 1;
847
+ min-height: 0;
848
+ overflow-y: auto;
849
+ padding: 20px 28px;
850
+ font-size: 14px;
851
+ line-height: 1.6;
852
+ color: #333;
853
+ white-space: pre-wrap;
854
+ word-break: break-word;
855
+ }
856
+
857
+ .chatbot-report-toolbar {
858
+ display: flex;
859
+ align-items: center;
860
+ justify-content: space-between;
861
+ padding: 10px 16px;
862
+ flex-shrink: 0;
863
+ gap: 8px;
864
+ flex-wrap: wrap;
865
+ }
866
+
867
+ .chatbot-report-btn-outline {
868
+ border: 1px solid var(--report-accent) !important;
869
+ color: var(--report-accent) !important;
870
+ background: #fff !important;
871
+ border-radius: 4px !important;
872
+ font-size: 13px !important;
873
+ height: 32px !important;
874
+ padding-inline: 14px !important;
875
+ }
876
+
877
+ .chatbot-report-btn-outline:hover {
878
+ background: var(--report-accent-soft) !important;
879
+ }
880
+
881
+ .chatbot-report-document {
882
+ flex: 1;
883
+ overflow-y: auto;
884
+ padding: 20px 28px 24px;
885
+ background: #fafafa;
886
+ min-height: 0;
887
+ }
888
+
889
+ .chatbot-report-document__paper {
890
+ max-width: 720px;
891
+ margin: 0 auto;
892
+ background: #fff;
893
+ border: 1px solid #eee;
894
+ padding: 32px 36px 40px;
895
+ min-height: 100%;
896
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
897
+ }
898
+
899
+ .chatbot-report-document__title-row {
900
+ display: flex;
901
+ align-items: flex-start;
902
+ gap: 8px;
903
+ margin-bottom: 20px;
904
+ font-size: 15px;
905
+ font-weight: 600;
906
+ line-height: 1.5;
907
+ }
908
+
909
+ .chatbot-report-document__welcome {
910
+ text-align: center;
911
+ padding: 48px 16px 32px;
912
+ color: var(--report-muted);
913
+ }
914
+
915
+ .chatbot-report-document__welcome h2 {
916
+ font-size: 22px;
917
+ font-weight: 600;
918
+ color: var(--report-text);
919
+ margin: 0 0 12px;
920
+ }
921
+
922
+ .chatbot-report-messages {
923
+ display: flex;
924
+ flex-direction: column;
925
+ gap: 16px;
926
+ }
927
+
928
+ .chatbot-report-sender {
929
+ flex-shrink: 0;
930
+ padding: 12px 16px 14px;
931
+ border-top: 1px solid #f0f0f0;
932
+ background: #fff;
933
+ }
934
+
935
+ .chatbot-report-chapter-select {
936
+ --chapter-check-size: 20px;
937
+ --chapter-version-width: 52px;
938
+ margin-top: 8px;
939
+ }
940
+
941
+ .chatbot-report-chapter-header {
942
+ display: flex;
943
+ align-items: center;
944
+ justify-content: space-between;
945
+ gap: 12px;
946
+ margin-bottom: 4px;
947
+ }
948
+
949
+ .chatbot-report-chapter-header__title {
950
+ font-size: 13px;
951
+ font-weight: 600;
952
+ color: #1a1a1a;
953
+ }
954
+
955
+ .chatbot-report-chapter-header__all {
956
+ display: flex;
957
+ align-items: center;
958
+ gap: 6px;
959
+ font-size: 12px;
960
+ color: #555;
961
+ cursor: pointer;
962
+ white-space: nowrap;
963
+ flex-shrink: 0;
964
+ }
965
+
966
+ .chatbot-report-chapter-list {
967
+ display: flex;
968
+ flex-direction: column;
969
+ }
970
+
971
+ .chatbot-report-chapter-row {
972
+ display: grid;
973
+ grid-template-columns: var(--chapter-check-size) minmax(0, 1fr) var(--chapter-version-width);
974
+ column-gap: 8px;
975
+ align-items: center;
976
+ padding: 7px 4px;
977
+ margin: 0 -4px;
978
+ font-size: 13px;
979
+ color: #333;
980
+ border-radius: 6px;
981
+ cursor: grab;
982
+ user-select: none;
983
+ transition: background 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
984
+ }
985
+
986
+ .chatbot-report-chapter-row:hover {
987
+ background: var(--report-card-bg);
988
+ }
989
+
990
+ .chatbot-report-chapter-row.is-dragging {
991
+ opacity: 0.5;
992
+ cursor: grabbing;
993
+ background: #fff;
994
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
995
+ }
996
+
997
+ .chatbot-report-chapter-row.is-drag-over {
998
+ background: #fdf0f2;
999
+ box-shadow: inset 0 0 0 1px rgba(197, 51, 85, 0.35);
1000
+ }
1001
+
1002
+ .chatbot-report-chapter-row .chatbot-report-check {
1003
+ cursor: pointer;
1004
+ }
1005
+
1006
+ .chatbot-report-chapter-row__label {
1007
+ min-width: 0;
1008
+ overflow: hidden;
1009
+ text-overflow: ellipsis;
1010
+ white-space: nowrap;
1011
+ cursor: pointer;
1012
+ line-height: 1.45;
1013
+ color: #333;
1014
+ }
1015
+
1016
+ .chatbot-report-chapter-row__version {
1017
+ width: var(--chapter-version-width);
1018
+ height: 26px;
1019
+ padding: 0 18px 0 8px;
1020
+ border: 1px solid #e5e5e5;
1021
+ border-radius: 4px;
1022
+ font-size: 12px;
1023
+ color: #333;
1024
+ background-color: #fff;
1025
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath fill='%23999' d='M831.872 340.864 512 652.672 192.128 340.864a30.592 30.592 0 0 0-42.752 0 29.12 29.12 0 0 0 0 41.6L489.664 714.24a32 32 0 0 0 44.672 0l340.288-331.712a29.12 29.12 0 0 0 0-41.728 30.592 30.592 0 0 0-42.752 0z'/%3E%3C/svg%3E");
1026
+ background-repeat: no-repeat;
1027
+ background-position: right 4px center;
1028
+ background-size: 12px;
1029
+ appearance: none;
1030
+ cursor: pointer;
1031
+ justify-self: end;
1032
+ box-sizing: border-box;
1033
+ }
1034
+
1035
+ .chatbot-report-section-title--settings {
1036
+ margin: 20px 0 12px;
1037
+ font-size: 13px;
1038
+ font-weight: 600;
1039
+ color: #1a1a1a;
1040
+ }
1041
+
1042
+ .chatbot-report-radio-group {
1043
+ display: flex;
1044
+ flex-direction: column;
1045
+ align-items: flex-start;
1046
+ gap: 12px;
1047
+ margin: 0 0 20px;
1048
+ }
1049
+
1050
+ .chatbot-report-radio-group :deep(.el-radio) {
1051
+ margin-right: 0;
1052
+ height: auto;
1053
+ }
1054
+
1055
+ .chatbot-report-radio-group :deep(.el-radio__label) {
1056
+ font-size: 13px;
1057
+ color: #333;
1058
+ padding-left: 8px;
1059
+ }
1060
+
1061
+ .chatbot-report-radio-group :deep(.el-radio__inner) {
1062
+ width: 16px;
1063
+ height: 16px;
1064
+ border: 1px solid #d9d9d9;
1065
+ }
1066
+
1067
+ .chatbot-report-radio-group :deep(.el-radio__input.is-checked .el-radio__inner) {
1068
+ border-color: #c53355;
1069
+ background: #c53355;
1070
+ }
1071
+
1072
+ .chatbot-report-radio-group :deep(.el-radio__inner::after) {
1073
+ width: 6px;
1074
+ height: 6px;
1075
+ background-color: #fff;
1076
+ }
1077
+
1078
+ .chatbot-report-generate-btn {
1079
+ display: block;
1080
+ width: 100%;
1081
+ height: 40px;
1082
+ border: 1px solid #c53355;
1083
+ color: #c53355;
1084
+ background: #fff;
1085
+ border-radius: 20px;
1086
+ font-size: 14px;
1087
+ font-weight: 500;
1088
+ margin: 0 auto 24px;
1089
+ cursor: pointer;
1090
+ transition: background 0.2s, color 0.2s;
1091
+ }
1092
+
1093
+ .chatbot-report-generate-btn:hover:not(:disabled) {
1094
+ background: #fdf0f2;
1095
+ }
1096
+
1097
+ .chatbot-report-generate-btn:disabled {
1098
+ opacity: 0.6;
1099
+ cursor: not-allowed;
1100
+ }
1101
+
1102
+ .chatbot-report-history {
1103
+ border-top: 1px solid #f0f0f0;
1104
+ padding-top: 20px;
1105
+ }
1106
+
1107
+ .chatbot-report-history__title {
1108
+ font-size: 13px;
1109
+ font-weight: 600;
1110
+ color: #1a1a1a;
1111
+ margin-bottom: 12px;
1112
+ }
1113
+
1114
+ .chatbot-report-history-list {
1115
+ display: flex;
1116
+ flex-direction: column;
1117
+ gap: 6px;
1118
+ }
1119
+
1120
+ .chatbot-report-history-row {
1121
+ display: grid;
1122
+ grid-template-columns: 4px minmax(0, 1fr);
1123
+ column-gap: 10px;
1124
+ align-items: stretch;
1125
+ cursor: pointer;
1126
+ }
1127
+
1128
+ .chatbot-report-history-item__indicator {
1129
+ width: 4px;
1130
+ border-radius: 2px;
1131
+ background: transparent;
1132
+ align-self: center;
1133
+ min-height: 36px;
1134
+ transition: background 0.15s;
1135
+ }
1136
+
1137
+ .chatbot-report-history-row.is-active .chatbot-report-history-item__indicator {
1138
+ background: #c53355;
1139
+ }
1140
+
1141
+ .chatbot-report-history-item {
1142
+ display: flex;
1143
+ align-items: center;
1144
+ justify-content: space-between;
1145
+ gap: 10px;
1146
+ padding: 12px 14px;
1147
+ border-radius: 12px;
1148
+ transition: background 0.15s;
1149
+ }
1150
+
1151
+ .chatbot-report-history-row.is-active .chatbot-report-history-item {
1152
+ background: #fdf0f3;
1153
+ }
1154
+
1155
+ .chatbot-report-history-row:not(.is-active):hover .chatbot-report-history-item {
1156
+ background: #fafafa;
1157
+ }
1158
+
1159
+ .chatbot-report-history-item__body {
1160
+ flex: 1;
1161
+ min-width: 0;
1162
+ }
1163
+
1164
+ .chatbot-report-history-item__title {
1165
+ font-size: 13px;
1166
+ font-weight: 600;
1167
+ color: #1a1a1a;
1168
+ line-height: 1.4;
1169
+ }
1170
+
1171
+ .chatbot-report-history-item__meta {
1172
+ margin-top: 2px;
1173
+ color: #999;
1174
+ font-size: 12px;
1175
+ line-height: 1.4;
1176
+ }
1177
+
1178
+ .chatbot-report-history-item__menu {
1179
+ flex-shrink: 0;
1180
+ width: 16px;
1181
+ height: 16px;
1182
+ font-size: 16px;
1183
+ color: #c53355;
1184
+ transform: rotate(90deg);
1185
+ cursor: pointer;
1186
+ }
1187
+
1188
+ @media (max-width: 1200px) {
1189
+ .chatbot-report-shell {
1190
+ flex-direction: column;
1191
+ overflow-y: auto;
1192
+ }
1193
+
1194
+ .chatbot-report-shell .left,
1195
+ .chatbot-report-shell .right {
1196
+ width: 100%;
1197
+ min-width: 0;
1198
+ }
1199
+
1200
+ .chatbot-report-shell .center {
1201
+ min-width: 0;
1202
+ min-height: 420px;
1203
+ }
1204
+ }
1205
+ </style>