aegon-dangerious 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 (32) hide show
  1. package/build-report/components/AiPromptGenerateDialog.vue +349 -0
  2. package/build-report/components/CapsuleScrollbar.vue +145 -0
  3. package/build-report/components/ChapterTitleScroll.vue +292 -0
  4. package/build-report/components/PromptField.vue +314 -0
  5. package/build-report/components/RecentReportsTable.vue +408 -0
  6. package/build-report/components/ReportChapterPreview.vue +437 -0
  7. package/build-report/components/ReportChapterWorkspace.vue +923 -0
  8. package/build-report/components/ReportCollapsibleSection.vue +132 -0
  9. package/build-report/components/ReportConfigPanel.vue +609 -0
  10. package/build-report/components/ReportGenerateSettingsPanel.vue +403 -0
  11. package/build-report/components/ReportGeneratingPanel.vue +908 -0
  12. package/build-report/components/ReportHistoryList.vue +157 -0
  13. package/build-report/components/ReportHistoryPanel.vue +140 -0
  14. package/build-report/components/ReportPromptPanel.vue +445 -0
  15. package/build-report/components/ReportSectionConfirmPopover.vue +232 -0
  16. package/build-report/components/ReportSourceFileSummary.vue +544 -0
  17. package/build-report/components/ReportSourcesMoreOverlay.vue +279 -0
  18. package/build-report/components/ReportSourcesPanel.vue +1055 -0
  19. package/build-report/components/ReportTemplateDetail.vue +176 -0
  20. package/build-report/components/ReportTemplateEditorFormPanel.vue +602 -0
  21. package/build-report/components/ReportTemplatePicker.vue +802 -0
  22. package/build-report/components/ReportTemplatePromptField.vue +314 -0
  23. package/build-report/components/ReportWorkflowSidebar.vue +104 -0
  24. package/build-report/components/reportEdit.vue +334 -0
  25. package/build-report/index.vue +646 -0
  26. package/build-report/report-list.vue +407 -0
  27. package/build-report/report-template-data.ts +248 -0
  28. package/build-report/styles/report-workflow-dialog.css +33 -0
  29. package/build-report/useReportWorkflow.ts +343 -0
  30. package/build-report/utils/report-edit-route.ts +109 -0
  31. package/build-report/utils/scroll.ts +361 -0
  32. package/package.json +12 -0
@@ -0,0 +1,403 @@
1
+ <template>
2
+ <aside class="chatbot-report-panel chatbot-report-panel--settings">
3
+ <div class="chatbot-report-panel__body">
4
+ <ReportCollapsibleSection v-model:open="settingsOpen" title="生成報告設置">
5
+ <div class="chatbot-report-settings__content">
6
+ <div class="chatbot-report-chapter-select">
7
+ <div class="chatbot-report-chapter-header">
8
+ <span class="chatbot-report-chapter-header__title">選擇章節及版本</span>
9
+ <div class="chatbot-report-chapter-header__all" @click="toggleAllChapters">
10
+ <CheckMark :checked="allChaptersSelected" />
11
+ <span>全部章節</span>
12
+ </div>
13
+ </div>
14
+ <div class="chatbot-report-chapter-list">
15
+ <div
16
+ v-for="preset in orderedPresets"
17
+ :key="preset.key"
18
+ class="chatbot-report-chapter-row"
19
+ :class="{
20
+ 'is-dragging': dragChapterKey === preset.key,
21
+ 'is-drag-over': dragOverChapterKey === preset.key,
22
+ }"
23
+ draggable="true"
24
+ @dragstart="onChapterDragStart($event, preset.key)"
25
+ @dragend="handleChapterDragEnd"
26
+ @dragover.prevent="dragOverChapterKey = preset.key"
27
+ @drop="handleChapterDrop(preset.key)"
28
+ >
29
+ <CheckMark
30
+ :checked="!!selectedChapters[preset.key]"
31
+ @click.stop="toggleChapter(preset.key)"
32
+ @mousedown.stop
33
+ @dragstart.prevent
34
+ />
35
+ <span class="chatbot-report-chapter-row__label">{{ preset.label }}</span>
36
+ <select
37
+ class="chatbot-report-chapter-row__version"
38
+ :value="chapterVersions[preset.key]"
39
+ @change="chapterVersions[preset.key] = ($event.target as HTMLSelectElement).value"
40
+ @click.stop
41
+ @mousedown.stop
42
+ >
43
+ <option v-for="version in CHAPTER_VERSIONS" :key="version" :value="version">{{ version }}</option>
44
+ </select>
45
+ </div>
46
+ </div>
47
+ </div>
48
+
49
+ <div class="chatbot-report-section-title chatbot-report-section-title--settings">生成報告方式</div>
50
+ <el-radio-group v-model="reportMode" class="chatbot-report-radio-group">
51
+ <el-radio value="polish">拼裝並潤色</el-radio>
52
+ <el-radio value="rewrite">重寫整篇報告</el-radio>
53
+ </el-radio-group>
54
+
55
+ <el-button class="chatbot-report-generate-btn" :disabled="!hasSelectedChapters" @click="handleGenerate">
56
+ 生成報告
57
+ </el-button>
58
+ </div>
59
+ </ReportCollapsibleSection>
60
+ </div>
61
+ </aside>
62
+ </template>
63
+
64
+ <script setup lang="ts">
65
+ import { ElButton, ElRadio, ElRadioGroup } from 'element-plus'
66
+ import { computed, defineComponent, h, ref, watch } from 'vue'
67
+ import ReportCollapsibleSection from './ReportCollapsibleSection.vue'
68
+ import { useReportWorkflow } from '../useReportWorkflow'
69
+
70
+ const CHAPTER_VERSIONS = ['V1', 'V2', 'V3']
71
+
72
+ interface ChapterPreset {
73
+ key: string
74
+ label: string
75
+ }
76
+
77
+ const emit = defineEmits<{
78
+ generate: []
79
+ }>()
80
+
81
+ const CheckMark = defineComponent({
82
+ name: 'CheckMark',
83
+ inheritAttrs: false,
84
+ props: {
85
+ checked: { type: Boolean, required: true },
86
+ },
87
+ emits: ['click'],
88
+ setup(props, { emit: emitClick, attrs }) {
89
+ return () =>
90
+ h('span', {
91
+ ...attrs,
92
+ class: ['chatbot-report-check', props.checked && 'is-checked', attrs.class],
93
+ onClick: (event: MouseEvent) => emitClick('click', event),
94
+ })
95
+ },
96
+ })
97
+
98
+ const settingsOpen = ref(true)
99
+ const { selectedTemplate } = useReportWorkflow()
100
+
101
+ const chapterPresets = ref<ChapterPreset[]>([])
102
+ const selectedChapters = ref<Record<string, boolean>>({})
103
+ const chapterVersions = ref<Record<string, string>>({})
104
+ const chapterOrder = ref<string[]>([])
105
+ const reportMode = ref('polish')
106
+ const dragChapterKey = ref<string | null>(null)
107
+ const dragOverChapterKey = ref<string | null>(null)
108
+
109
+ const orderedPresets = computed(() =>
110
+ chapterOrder.value
111
+ .map((key) => chapterPresets.value.find((preset) => preset.key === key))
112
+ .filter((preset): preset is ChapterPreset => !!preset),
113
+ )
114
+
115
+ const allChaptersSelected = computed(
116
+ () => chapterPresets.value.length > 0 && chapterPresets.value.every((preset) => selectedChapters.value[preset.key]),
117
+ )
118
+
119
+ const hasSelectedChapters = computed(() =>
120
+ orderedPresets.value.some((preset) => selectedChapters.value[preset.key]),
121
+ )
122
+
123
+ function buildChapterPresets(chapters: string[]) {
124
+ return chapters.map((title, index) => ({
125
+ key: `chapter-${index}`,
126
+ label: title.trim(),
127
+ }))
128
+ }
129
+
130
+ function resetChapterState(chapters: string[]) {
131
+ const presets = buildChapterPresets(chapters)
132
+ chapterPresets.value = presets
133
+ chapterOrder.value = presets.map((preset) => preset.key)
134
+ selectedChapters.value = Object.fromEntries(presets.map((preset) => [preset.key, true]))
135
+ chapterVersions.value = Object.fromEntries(presets.map((preset) => [preset.key, 'V3']))
136
+ }
137
+
138
+ watch(
139
+ () => selectedTemplate.value?.chapters,
140
+ (chapters) => {
141
+ resetChapterState(chapters?.length ? chapters : ['摘要與本年總結'])
142
+ },
143
+ { immediate: true, deep: true },
144
+ )
145
+
146
+ function toggleChapter(key: string) {
147
+ selectedChapters.value[key] = !selectedChapters.value[key]
148
+ }
149
+
150
+ function toggleAllChapters() {
151
+ const next = !allChaptersSelected.value
152
+ chapterPresets.value.forEach((preset) => {
153
+ selectedChapters.value[preset.key] = next
154
+ })
155
+ }
156
+
157
+ function onChapterDragStart(event: DragEvent, key: string) {
158
+ if ((event.target as HTMLElement).closest('.chatbot-report-check, .chatbot-report-chapter-row__version')) {
159
+ event.preventDefault()
160
+ return
161
+ }
162
+ dragChapterKey.value = key
163
+ dragOverChapterKey.value = key
164
+ }
165
+
166
+ function handleChapterDragEnd() {
167
+ dragChapterKey.value = null
168
+ dragOverChapterKey.value = null
169
+ }
170
+
171
+ function handleChapterDrop(targetKey: string) {
172
+ const draggingKey = dragChapterKey.value
173
+ if (draggingKey && draggingKey !== targetKey) {
174
+ const newOrder = [...chapterOrder.value]
175
+ const fromIdx = newOrder.indexOf(draggingKey)
176
+ const toIdx = newOrder.indexOf(targetKey)
177
+ if (fromIdx !== -1 && toIdx !== -1) {
178
+ newOrder.splice(fromIdx, 1)
179
+ newOrder.splice(toIdx, 0, draggingKey)
180
+ chapterOrder.value = newOrder
181
+ }
182
+ }
183
+ handleChapterDragEnd()
184
+ }
185
+
186
+ function handleGenerate() {
187
+ if (!hasSelectedChapters.value) return
188
+ emit('generate')
189
+ }
190
+ </script>
191
+
192
+ <style scoped>
193
+ .chatbot-report-panel {
194
+ --report-border: #ebeef5;
195
+ --report-card-bg: #f5f5f5;
196
+ display: flex;
197
+ flex-direction: column;
198
+ min-width: 0;
199
+ min-height: 0;
200
+ box-sizing: border-box;
201
+ }
202
+
203
+ .chatbot-report-panel--settings .chatbot-report-panel__body {
204
+ padding: 0;
205
+ border: 1px solid var(--report-border);
206
+ border-radius: 8px;
207
+ background: #fff;
208
+ box-sizing: border-box;
209
+ overflow: hidden;
210
+ }
211
+
212
+ .chatbot-report-panel__body > :deep(.report-collapsible-section) {
213
+ border: none;
214
+ border-radius: 0;
215
+ padding: 14px 16px;
216
+ }
217
+
218
+ .chatbot-report-panel__body > :deep(.report-collapsible-section__toggle) {
219
+ border-bottom: none;
220
+ padding-bottom: 14px;
221
+ }
222
+
223
+ .chatbot-report-panel__body > :deep(.report-collapsible-section.is-collapsed .report-collapsible-section__toggle) {
224
+ padding-bottom: 0;
225
+ }
226
+
227
+ .chatbot-report-settings__content {
228
+ display: flex;
229
+ flex-direction: column;
230
+ min-width: 0;
231
+ }
232
+
233
+ .chatbot-report-chapter-select {
234
+ --chapter-check-size: 20px;
235
+ --chapter-version-width: 52px;
236
+ }
237
+
238
+ .chatbot-report-chapter-header {
239
+ display: flex;
240
+ align-items: center;
241
+ justify-content: space-between;
242
+ gap: 12px;
243
+ margin-bottom: 4px;
244
+ }
245
+
246
+ .chatbot-report-chapter-header__title {
247
+ font-size: 13px;
248
+ font-weight: 600;
249
+ color: #1a1a1a;
250
+ }
251
+
252
+ .chatbot-report-chapter-header__all {
253
+ display: flex;
254
+ align-items: center;
255
+ gap: 6px;
256
+ font-size: 12px;
257
+ color: #555;
258
+ cursor: pointer;
259
+ white-space: nowrap;
260
+ flex-shrink: 0;
261
+ }
262
+
263
+ .chatbot-report-chapter-list {
264
+ display: flex;
265
+ flex-direction: column;
266
+ }
267
+
268
+ .chatbot-report-chapter-row {
269
+ display: grid;
270
+ grid-template-columns: var(--chapter-check-size) minmax(0, 1fr) var(--chapter-version-width);
271
+ column-gap: 8px;
272
+ align-items: center;
273
+ padding: 7px 4px;
274
+ margin: 0 -4px;
275
+ font-size: 13px;
276
+ color: #333;
277
+ border-radius: 6px;
278
+ cursor: grab;
279
+ user-select: none;
280
+ transition: background 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
281
+ }
282
+
283
+ .chatbot-report-chapter-row:hover {
284
+ background: var(--report-card-bg);
285
+ }
286
+
287
+ .chatbot-report-chapter-row.is-dragging {
288
+ opacity: 0.5;
289
+ cursor: grabbing;
290
+ background: #fff;
291
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
292
+ }
293
+
294
+ .chatbot-report-chapter-row.is-drag-over {
295
+ background: #fdf0f2;
296
+ box-shadow: inset 0 0 0 1px rgba(197, 51, 85, 0.35);
297
+ }
298
+
299
+ .chatbot-report-chapter-row__label {
300
+ min-width: 0;
301
+ overflow: hidden;
302
+ text-overflow: ellipsis;
303
+ white-space: nowrap;
304
+ line-height: 1.45;
305
+ }
306
+
307
+ .chatbot-report-chapter-row__version {
308
+ width: var(--chapter-version-width);
309
+ height: 26px;
310
+ padding: 0 18px 0 8px;
311
+ border: 1px solid #e5e5e5;
312
+ border-radius: 4px;
313
+ font-size: 12px;
314
+ appearance: none;
315
+ cursor: pointer;
316
+ justify-self: end;
317
+ box-sizing: border-box;
318
+ }
319
+
320
+ .chatbot-report-check {
321
+ flex-shrink: 0;
322
+ box-sizing: border-box;
323
+ width: 20px;
324
+ height: 20px;
325
+ border-radius: 50%;
326
+ border: 2px solid #ccc;
327
+ position: relative;
328
+ cursor: pointer;
329
+ background: #fff;
330
+ }
331
+
332
+ .chatbot-report-check.is-checked {
333
+ border-color: #c53355;
334
+ background-color: #c53355;
335
+ }
336
+
337
+ .chatbot-report-check.is-checked::after {
338
+ content: '';
339
+ position: absolute;
340
+ left: 4px;
341
+ top: 1px;
342
+ width: 5px;
343
+ height: 9px;
344
+ border: solid #fff;
345
+ border-width: 0 2px 2px 0;
346
+ transform: rotate(45deg);
347
+ }
348
+
349
+ .chatbot-report-section-title--settings {
350
+ margin: 20px 0 12px;
351
+ font-size: 13px;
352
+ font-weight: 600;
353
+ color: #1a1a1a;
354
+ }
355
+
356
+ .chatbot-report-radio-group {
357
+ display: flex;
358
+ flex-direction: column;
359
+ align-items: flex-start;
360
+ gap: 12px;
361
+ margin: 0 0 20px;
362
+ }
363
+
364
+ .chatbot-report-radio-group :deep(.el-radio) {
365
+ margin-right: 0;
366
+ height: auto;
367
+ }
368
+
369
+ .chatbot-report-radio-group :deep(.el-radio__label) {
370
+ font-size: 13px;
371
+ color: #333;
372
+ padding-left: 8px;
373
+ }
374
+
375
+ .chatbot-report-radio-group :deep(.el-radio__inner) {
376
+ width: 16px;
377
+ height: 16px;
378
+ border: 1px solid #d9d9d9;
379
+ }
380
+
381
+ .chatbot-report-radio-group :deep(.el-radio__input.is-checked .el-radio__inner) {
382
+ border-color: #c53355;
383
+ background: #c53355;
384
+ }
385
+
386
+ .chatbot-report-generate-btn.el-button {
387
+ display: flex;
388
+ width: 100%;
389
+ height: 40px;
390
+ border: 1px solid #c53355;
391
+ color: #c53355;
392
+ background: #fff;
393
+ border-radius: 20px;
394
+ font-size: 14px;
395
+ font-weight: 500;
396
+ }
397
+
398
+ .chatbot-report-generate-btn.el-button:hover:not(.is-disabled) {
399
+ background: #fdf0f2;
400
+ color: #c53355;
401
+ border-color: #c53355;
402
+ }
403
+ </style>