aegon-lv97 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.
- package/gen-ai/build-report/chartStreamRefs.ts +227 -0
- package/gen-ai/build-report/coherence-check/index.vue +559 -0
- package/gen-ai/build-report/components/ReportChapterWorkspace.vue +4571 -0
- package/gen-ai/build-report/components/ReportConfigPanel.vue +727 -0
- package/gen-ai/build-report/components/ReportGenerateSettingsPanel.vue +2361 -0
- package/gen-ai/build-report/components/ReportGeneratingPanel.vue +1765 -0
- package/gen-ai/build-report/components/ReportPromptPanel.vue +625 -0
- package/gen-ai/build-report/components/ReportSourceFileSummary.vue +665 -0
- package/gen-ai/build-report/components/ReportSourcesPanel.vue +1327 -0
- package/gen-ai/build-report/components/ReportTemplateDetail.vue +191 -0
- package/gen-ai/build-report/components/ReportTemplateEditorFormPanel.vue +667 -0
- package/gen-ai/build-report/components/ReportTemplatePicker.vue +302 -0
- package/gen-ai/build-report/components/ReportWorkflowSidebar.vue +148 -0
- package/gen-ai/build-report/components/paramsSetting.vue +886 -0
- package/gen-ai/build-report/components/reportEdit.vue +2283 -0
- package/gen-ai/build-report/index.vue +856 -0
- package/gen-ai/build-report/report-domain.ts +1133 -0
- package/gen-ai/build-report/report-template-data.ts +295 -0
- package/gen-ai/build-report/useReportWorkflow.ts +1386 -0
- package/gen-ai/common/assets/NotoSans-SC.woff2 +0 -0
- package/gen-ai/common/assets/NotoSans-TC.woff2 +0 -0
- package/gen-ai/common/assets/NotoSans.woff2 +0 -0
- package/gen-ai/common/assets/fonts.css +278 -0
- package/gen-ai/common/assets/pagination.css +163 -0
- package/gen-ai/common/directives/btnLoading.ts +455 -0
- package/gen-ai/common/directives/debounce.ts +98 -0
- package/gen-ai/common/directives/index.ts +30 -0
- package/gen-ai/common/en.md +417 -0
- package/gen-ai/common/index.ts +36 -0
- package/gen-ai/common/types/component-expose.ts +9 -0
- package/gen-ai/common/utils/api-res-status.ts +7 -0
- package/gen-ai/common/utils/navigation.ts +59 -0
- package/gen-ai/common/utils/remote-request.ts +45 -0
- package/gen-ai/common/utils/scroll.ts +577 -0
- package/gen-ai/components/AIExport/docx-export.ts +950 -0
- package/gen-ai/components/AIExport/docxExport.ts +2566 -0
- package/gen-ai/components/AIExport/index.ts +52 -0
- package/gen-ai/components/AIExport/parseMarkdownHtml.ts +653 -0
- package/gen-ai/components/CapsuleScrollbar.vue +149 -0
- package/gen-ai/components/ChapterTitleScroll.vue +468 -0
- package/gen-ai/components/EntryHeroNavCards.vue +379 -0
- package/gen-ai/components/GenAiPagination.vue +52 -0
- package/gen-ai/components/ModelCard.vue +1114 -0
- package/gen-ai/components/Preview/FilePreviewPage.vue +949 -0
- package/gen-ai/components/Preview/PreviewCapsuleScroll.vue +205 -0
- package/gen-ai/components/Preview/PreviewOutlineTree.vue +148 -0
- package/gen-ai/components/Preview/index.ts +11 -0
- package/gen-ai/components/Preview/preview.ts +724 -0
- package/gen-ai/components/PromptField.vue +505 -0
- package/gen-ai/components/RecentReportsTable.vue +974 -0
- package/gen-ai/components/ReportCollapsibleSection.vue +172 -0
- package/gen-ai/components/ReportHistoryList.vue +637 -0
- package/gen-ai/components/ReportSectionConfirmPopover.vue +251 -0
- package/gen-ai/components/editor/ChapterTiptapEditor.vue +3718 -0
- package/gen-ai/components/editor/StructureBlockView.vue +441 -0
- package/gen-ai/components/editor/TiptapToolbar.vue +1036 -0
- package/gen-ai/components/editor/TypewriterDocEditor.vue +422 -0
- package/gen-ai/components/editor/_StructureOrgNode.vue +326 -0
- package/gen-ai/components/editor/index.ts +28 -0
- package/gen-ai/components/editor/parseMarkdownHtml.ts +754 -0
- package/gen-ai/components/editor/reviewCitationTip.ts +163 -0
- package/gen-ai/gen-entry/api/index.ts +32 -0
- package/gen-ai/gen-entry/index.vue +287 -0
- package/gen-ai/gen-entry/types/index.ts +4 -0
- package/gen-ai/i.mark +2 -0
- package/gen-ai/management-center/index.vue +1815 -0
- package/gen-ai/management-center/mockData.ts +248 -0
- package/gen-ai/management-center/types/index.ts +37 -0
- package/gen-ai/model-manager/TemplateEditorFormPanel.vue +661 -0
- package/gen-ai/model-manager/api/index.ts +32 -0
- package/gen-ai/model-manager/api/mockApi.ts +33 -0
- package/gen-ai/model-manager/index.vue +1583 -0
- package/gen-ai/model-manager/mockData.ts +177 -0
- package/gen-ai/model-manager/template-detail-shared.ts +154 -0
- package/gen-ai/model-manager/template-editor.vue +345 -0
- package/gen-ai/model-manager/types/index.ts +40 -0
- package/gen-ai/model-manager/utils.ts +25 -0
- package/package.json +12 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* //0918 tip / REF 兼容层(归类)
|
|
3
|
+
*
|
|
4
|
+
* 旧底(开发前,不可破坏):
|
|
5
|
+
* [^n] / [+n] / HTML title / Element Plus tip
|
|
6
|
+
* → span.report-tiptap-citation → 鼠标移入打开 report-chapter-review-popover
|
|
7
|
+
*
|
|
8
|
+
* 新叠(0918):
|
|
9
|
+
* chartAsStream REF / [ref:uuid] → 同一 citation DOM(data-chunk-id 等)
|
|
10
|
+
* + 14px / >18 行灰胶囊 / 文件名新 tab 预览(UI 在 ChapterTiptapEditor)
|
|
11
|
+
*
|
|
12
|
+
* 兼容约定:
|
|
13
|
+
* - 库未命中 [ref:uuid] → 删除占位(不显示原文 / 不造死圆点);REF 入库后重解析再出 tip
|
|
14
|
+
* - [+n] 无 tip 也可开 popup(只显示序号)
|
|
15
|
+
* - 禁止另起 tip DOM
|
|
16
|
+
*/
|
|
17
|
+
//0918
|
|
18
|
+
import {
|
|
19
|
+
getChartStreamRef,
|
|
20
|
+
listChartStreamRefs,
|
|
21
|
+
type ChartStreamRefItem,
|
|
22
|
+
} from '../../build-report/chartStreamRefs'
|
|
23
|
+
|
|
24
|
+
export const REF_MARKER_RE =
|
|
25
|
+
/\[ref:\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\s*\]/gi
|
|
26
|
+
|
|
27
|
+
/** //0918-1:正文残留的任意 [ref:…](含空格/非 UUID)一律清空,打字机不显示 */
|
|
28
|
+
export const REF_ANY_MARKER_RE = /\[ref:[^\]]*\]/gi
|
|
29
|
+
//0918-1
|
|
30
|
+
|
|
31
|
+
export type CitationTipExtra = {
|
|
32
|
+
sourceName?: string
|
|
33
|
+
filePath?: string
|
|
34
|
+
filePreviewUrl?: string
|
|
35
|
+
chunkId?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type ResolvedRefCitation = {
|
|
39
|
+
id: string
|
|
40
|
+
tip: string
|
|
41
|
+
extra: CitationTipExtra
|
|
42
|
+
ref: ChartStreamRefItem
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** [ref:{chunkId}] → 在 SSERefList 中按 chunkId 匹配;未命中过滤 */
|
|
46
|
+
export function resolveRefMarker(chunkId: string): ResolvedRefCitation | null {
|
|
47
|
+
const id = String(chunkId ?? '').trim().toLowerCase()
|
|
48
|
+
const pool = listChartStreamRefs()
|
|
49
|
+
console.log('[REF tip] 匹配 SSERefList', {
|
|
50
|
+
chunkId: id,
|
|
51
|
+
SSERefListLen: pool.length,
|
|
52
|
+
chunkIds: pool.map((r) => r.chunkId),
|
|
53
|
+
})
|
|
54
|
+
if (!id) return null
|
|
55
|
+
const ref = getChartStreamRef(id)
|
|
56
|
+
if (!ref) {
|
|
57
|
+
console.log('[REF tip] 未命中 → 过滤', { chunkId: id })
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
console.log('[REF tip] 命中', {
|
|
61
|
+
chunkId: ref.chunkId,
|
|
62
|
+
index: ref.index,
|
|
63
|
+
sourceName: ref.sourceName,
|
|
64
|
+
})
|
|
65
|
+
return {
|
|
66
|
+
id: String(ref.index),
|
|
67
|
+
tip: ref.sourceText || '',
|
|
68
|
+
extra: {
|
|
69
|
+
sourceName: ref.sourceName || undefined,
|
|
70
|
+
filePath: ref.filePath || undefined,
|
|
71
|
+
filePreviewUrl: ref.filePreviewUrl || undefined,
|
|
72
|
+
chunkId: ref.chunkId,
|
|
73
|
+
},
|
|
74
|
+
ref,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type CitationDatasetFields = {
|
|
79
|
+
citationId: number
|
|
80
|
+
tip: string
|
|
81
|
+
href: string
|
|
82
|
+
linkLabel: string
|
|
83
|
+
sourceName: string
|
|
84
|
+
filePath: string
|
|
85
|
+
filePreviewUrl: string
|
|
86
|
+
chunkId: string
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** 从 citation DOM 读字段;缺省时用 chartStreamRefs 回填(不覆盖已有 tip) */
|
|
90
|
+
export function readCitationDataset(el: HTMLElement): CitationDatasetFields {
|
|
91
|
+
let tip = String(el.dataset.tip || el.getAttribute('title') || '').trim()
|
|
92
|
+
const href = String(el.dataset.href || '').trim()
|
|
93
|
+
const linkLabel = String(el.dataset.linkLabel || '').trim()
|
|
94
|
+
let sourceName = String(el.dataset.sourceName || '').trim()
|
|
95
|
+
let filePath = String(el.dataset.filePath || '').trim()
|
|
96
|
+
let filePreviewUrl = String(el.dataset.filePreviewUrl || '').trim()
|
|
97
|
+
const chunkId = String(el.dataset.chunkId || '').trim()
|
|
98
|
+
const citationId = Number(el.dataset.citation)
|
|
99
|
+
|
|
100
|
+
if (chunkId) {
|
|
101
|
+
const ref = getChartStreamRef(chunkId)
|
|
102
|
+
if (ref) {
|
|
103
|
+
if (!tip && ref.sourceText) tip = String(ref.sourceText).trim()
|
|
104
|
+
if (!sourceName && ref.sourceName) sourceName = ref.sourceName
|
|
105
|
+
if (!filePath && ref.filePath) filePath = ref.filePath
|
|
106
|
+
if (!filePreviewUrl && ref.filePreviewUrl) filePreviewUrl = ref.filePreviewUrl
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
citationId,
|
|
112
|
+
tip,
|
|
113
|
+
href,
|
|
114
|
+
linkLabel,
|
|
115
|
+
sourceName,
|
|
116
|
+
filePath,
|
|
117
|
+
filePreviewUrl,
|
|
118
|
+
chunkId,
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function resolveCitationTipText(fields: CitationDatasetFields): string {
|
|
123
|
+
const fromDom = String(fields.tip || '').trim()
|
|
124
|
+
if (fromDom) return fromDom
|
|
125
|
+
if (!fields.chunkId) return ''
|
|
126
|
+
const ref = getChartStreamRef(fields.chunkId)
|
|
127
|
+
return String(ref?.sourceText || '').trim()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 可否打开 tip popup
|
|
132
|
+
* - 旧:有 tip / href / sourceName / filePath
|
|
133
|
+
* - 旧 [+n]:仅有合法序号也可开(正文可空)
|
|
134
|
+
* - 新:chunkId 且库中已有 REF
|
|
135
|
+
*/
|
|
136
|
+
export function canOpenCitationTip(fields: CitationDatasetFields): boolean {
|
|
137
|
+
if (fields.tip || fields.href || fields.sourceName || fields.filePath || fields.filePreviewUrl) {
|
|
138
|
+
return true
|
|
139
|
+
}
|
|
140
|
+
// [+n] / 仅序号圆点:开发前也可点出 popup(哪怕尚无批注文案)
|
|
141
|
+
if (Number.isFinite(fields.citationId) && fields.citationId > 0) return true
|
|
142
|
+
if (!fields.chunkId) return false
|
|
143
|
+
const ref = getChartStreamRef(fields.chunkId)
|
|
144
|
+
return !!(ref && (ref.sourceText || ref.sourceName || ref.filePath || ref.filePreviewUrl))
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function citationIndexFromRefOrDom(
|
|
148
|
+
fields: CitationDatasetFields,
|
|
149
|
+
fallbackId: number
|
|
150
|
+
): number {
|
|
151
|
+
// 优先 REF.index(popup 序号);再用 DOM data-citation;禁止落到 0 当「有序号」
|
|
152
|
+
if (fields.chunkId) {
|
|
153
|
+
const ref = getChartStreamRef(fields.chunkId)
|
|
154
|
+
const idx = Number(ref?.index)
|
|
155
|
+
if (Number.isFinite(idx) && idx > 0) return Math.floor(idx)
|
|
156
|
+
}
|
|
157
|
+
if (Number.isFinite(fields.citationId) && fields.citationId > 0) {
|
|
158
|
+
return Math.floor(fields.citationId)
|
|
159
|
+
}
|
|
160
|
+
if (Number.isFinite(fallbackId) && fallbackId > 0) return Math.floor(fallbackId)
|
|
161
|
+
return 0
|
|
162
|
+
}
|
|
163
|
+
//0918
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { genAiReportDataParams } from '../types'
|
|
2
|
+
import { RECENT_REPORTS, type RecentReport } from '../../components/RecentReportsTable.vue'
|
|
3
|
+
import { postGenAiRequest } from '../../common/utils/remote-request'
|
|
4
|
+
|
|
5
|
+
function isRecentReportList(data: unknown) {
|
|
6
|
+
return Array.isArray(data) && data.length > 0 && typeof data[0]?.id === 'string'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function fallbackRecentReports() {
|
|
10
|
+
return [...RECENT_REPORTS]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const genEntryApi = {
|
|
14
|
+
/** gen-entry: report list;網絡失敗或超時時回退 mock,不阻塞頁面 */
|
|
15
|
+
async fetchGenAiReportListData(data: genAiReportDataParams) {
|
|
16
|
+
try {
|
|
17
|
+
const response = await postGenAiRequest('/reportLatest', data)
|
|
18
|
+
if (isRecentReportList(response)) {
|
|
19
|
+
return response as RecentReport[]
|
|
20
|
+
}
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('獲取 fetchGenAiReportListData 失敗', error)
|
|
23
|
+
}
|
|
24
|
+
return fallbackRecentReports()
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
async fetchtest(data: unknown) {
|
|
28
|
+
return postGenAiRequest('/hello', data)
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default genEntryApi
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="industry-page">
|
|
3
|
+
<main ref="pageBodyRef" class="industry-page__body">
|
|
4
|
+
<section class="industry-hero">
|
|
5
|
+
<h2 class="industry-hero__title">AI產業分析報告</h2>
|
|
6
|
+
<p class="industry-hero__desc">
|
|
7
|
+
基於你選擇的模型、行業與年份,並結合上傳或雲端引用的資料,自動生成結構化的風控分析報告。
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<div class="industry-hero__actions">
|
|
11
|
+
<EntryHeroNavCards @select="handleHeroAction" />
|
|
12
|
+
</div>
|
|
13
|
+
</section>
|
|
14
|
+
|
|
15
|
+
<section class="industry-reports">
|
|
16
|
+
<h3 class="industry-reports__title">
|
|
17
|
+
<el-icon class="industry-reports__title-icon">
|
|
18
|
+
<Document />
|
|
19
|
+
</el-icon>
|
|
20
|
+
最近的報告
|
|
21
|
+
</h3>
|
|
22
|
+
<RecentReportsTable ref="tableRef" :reports="displayedReports" @open="openReport" />
|
|
23
|
+
<a
|
|
24
|
+
v-if="showMoreLink"
|
|
25
|
+
href="#"
|
|
26
|
+
class="industry-reports__more"
|
|
27
|
+
@click.prevent="handleMoreReports"
|
|
28
|
+
>
|
|
29
|
+
更多報告 >>
|
|
30
|
+
</a>
|
|
31
|
+
</section>
|
|
32
|
+
</main>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang="ts">
|
|
37
|
+
import '../common/assets/fonts.css'
|
|
38
|
+
import { Document } from '@element-plus/icons-vue'
|
|
39
|
+
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
40
|
+
import { useRouter } from 'vue-router'
|
|
41
|
+
import {
|
|
42
|
+
bindViewportBodyHeight,
|
|
43
|
+
lockDocumentScroll,
|
|
44
|
+
RECENT_REPORTS,
|
|
45
|
+
navigateToReportCenter,
|
|
46
|
+
openManagementCenter,
|
|
47
|
+
openModelManager,
|
|
48
|
+
openReportCenter,
|
|
49
|
+
openReportCreate,
|
|
50
|
+
RecentReportsTable,
|
|
51
|
+
type RecentReport,
|
|
52
|
+
type RecentReportsTableExpose,
|
|
53
|
+
} from '../common'
|
|
54
|
+
import EntryHeroNavCards, { type EntryHeroNavId } from '../components/EntryHeroNavCards.vue'
|
|
55
|
+
import genEntryApi from './api'
|
|
56
|
+
|
|
57
|
+
const DEFAULT_VISIBLE_ROWS = 10
|
|
58
|
+
|
|
59
|
+
const router = useRouter()
|
|
60
|
+
const recentReports = ref([...RECENT_REPORTS])
|
|
61
|
+
|
|
62
|
+
function isRecentReportList(data: unknown) {
|
|
63
|
+
return Array.isArray(data) && data.length > 0 && typeof data[0]?.id === 'string'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function loadRecentReports() {
|
|
67
|
+
const data = await genEntryApi.fetchGenAiReportListData({})
|
|
68
|
+
if (isRecentReportList(data)) {
|
|
69
|
+
recentReports.value = data as RecentReport[]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const pageBodyRef = ref(null as HTMLElement | null)
|
|
74
|
+
const tableRef = ref<RecentReportsTableExpose | null>(null)
|
|
75
|
+
|
|
76
|
+
const displayedReports = computed(() => recentReports.value.slice(0, DEFAULT_VISIBLE_ROWS))
|
|
77
|
+
|
|
78
|
+
const showMoreLink = computed(() => recentReports.value.length > DEFAULT_VISIBLE_ROWS)
|
|
79
|
+
|
|
80
|
+
let cleanupBodyHeight: (() => void) | undefined
|
|
81
|
+
let cleanupLock: (() => void) | undefined
|
|
82
|
+
let resizeObserver: ResizeObserver | undefined
|
|
83
|
+
let measureRafId = 0
|
|
84
|
+
|
|
85
|
+
async function relayoutTable() {
|
|
86
|
+
await nextTick()
|
|
87
|
+
await new Promise((resolve) => {
|
|
88
|
+
cancelAnimationFrame(measureRafId)
|
|
89
|
+
measureRafId = requestAnimationFrame(() => {
|
|
90
|
+
measureRafId = requestAnimationFrame(() => resolve(undefined))
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
tableRef.value?.doLayout()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function scheduleRelayoutTable() {
|
|
97
|
+
cancelAnimationFrame(measureRafId)
|
|
98
|
+
measureRafId = requestAnimationFrame(() => {
|
|
99
|
+
void relayoutTable()
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function handleMoreReports() {
|
|
104
|
+
navigateToReportCenter(router)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
onMounted(() => {
|
|
108
|
+
void loadRecentReports()
|
|
109
|
+
if (pageBodyRef.value) {
|
|
110
|
+
cleanupBodyHeight = bindViewportBodyHeight(pageBodyRef.value)
|
|
111
|
+
resizeObserver = new ResizeObserver(() => scheduleRelayoutTable())
|
|
112
|
+
resizeObserver.observe(pageBodyRef.value)
|
|
113
|
+
}
|
|
114
|
+
cleanupLock = lockDocumentScroll()
|
|
115
|
+
window.addEventListener('resize', scheduleRelayoutTable)
|
|
116
|
+
scheduleRelayoutTable()
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
onUnmounted(() => {
|
|
120
|
+
cancelAnimationFrame(measureRafId)
|
|
121
|
+
resizeObserver?.disconnect()
|
|
122
|
+
window.removeEventListener('resize', scheduleRelayoutTable)
|
|
123
|
+
cleanupBodyHeight?.()
|
|
124
|
+
cleanupLock?.()
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
watch(displayedReports, () => {
|
|
128
|
+
scheduleRelayoutTable()
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
function handleHeroAction(id: EntryHeroNavId) {
|
|
132
|
+
if (id === 'new-report') {
|
|
133
|
+
openReportCreate(router)
|
|
134
|
+
}
|
|
135
|
+
if (id === 'report-sim') {
|
|
136
|
+
openReportCenter(router)
|
|
137
|
+
}
|
|
138
|
+
if (id === 'template-sim') {
|
|
139
|
+
openModelManager(router)
|
|
140
|
+
}
|
|
141
|
+
if (id === 'admin-sim') {
|
|
142
|
+
openManagementCenter(router)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function openReport(report: RecentReport) {
|
|
147
|
+
openModelManager(router, { id: report.id })
|
|
148
|
+
}
|
|
149
|
+
</script>
|
|
150
|
+
|
|
151
|
+
<style scoped>
|
|
152
|
+
.industry-page {
|
|
153
|
+
--gen-ai-design-w: 1920;
|
|
154
|
+
--gen-ai-fs-xs: clamp(11px, calc(12 * 100vw / 1920), 12px);
|
|
155
|
+
--gen-ai-fs-sm: clamp(12px, calc(13 * 100vw / 1920), 13px);
|
|
156
|
+
--gen-ai-fs-base: clamp(13px, calc(14 * 100vw / 1920), 14px);
|
|
157
|
+
--gen-ai-fs-md: clamp(14px, calc(16 * 100vw / 1920), 16px);
|
|
158
|
+
--gen-ai-fs-lg: clamp(16px, calc(18 * 100vw / 1920), 18px);
|
|
159
|
+
--gen-ai-fs-hero: clamp(26px, calc(32 * 100vw / 1920), 32px);
|
|
160
|
+
--gen-ai-lh-tight: 1.4;
|
|
161
|
+
--gen-ai-lh-normal: 1.6;
|
|
162
|
+
--gen-ai-lh-relaxed: 1.7;
|
|
163
|
+
--gen-ai-fw-semibold: 600;
|
|
164
|
+
--gen-ai-fw-bold: 700;
|
|
165
|
+
font-family: var(--gen-ai-font-family, 'Noto Sans', 'Noto Sans TC', sans-serif);
|
|
166
|
+
font-size: var(--gen-ai-fs-base);
|
|
167
|
+
line-height: var(--gen-ai-lh-normal);
|
|
168
|
+
color: #2d3139;
|
|
169
|
+
font-synthesis: none;
|
|
170
|
+
text-rendering: optimizeLegibility;
|
|
171
|
+
-webkit-font-smoothing: antialiased;
|
|
172
|
+
-moz-osx-font-smoothing: grayscale;
|
|
173
|
+
display: flex;
|
|
174
|
+
flex-direction: column;
|
|
175
|
+
height: 100vh;
|
|
176
|
+
overflow: hidden;
|
|
177
|
+
background: #fff;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.industry-page :deep(.el-table),
|
|
181
|
+
.industry-page :deep(.el-input),
|
|
182
|
+
.industry-page :deep(.el-select),
|
|
183
|
+
.industry-page :deep(.el-pagination) {
|
|
184
|
+
font-size: inherit;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.industry-page :deep(.el-button) {
|
|
188
|
+
font-size: 18px;
|
|
189
|
+
font-family: var(--gen-ai-font-family, 'Noto Sans', 'Noto Sans TC', sans-serif);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.industry-page__body {
|
|
193
|
+
flex: 1;
|
|
194
|
+
min-height: 0;
|
|
195
|
+
overflow: hidden;
|
|
196
|
+
display: flex;
|
|
197
|
+
flex-direction: column;
|
|
198
|
+
width: 100%;
|
|
199
|
+
padding: 48px 24px 40px;
|
|
200
|
+
box-sizing: border-box;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.industry-hero {
|
|
204
|
+
flex-shrink: 0;
|
|
205
|
+
text-align: center;
|
|
206
|
+
margin-bottom: 48px;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.industry-hero__title {
|
|
210
|
+
margin: 0 0 20px;
|
|
211
|
+
font-size: var(--gen-ai-fs-hero);
|
|
212
|
+
font-weight: var(--gen-ai-fw-bold);
|
|
213
|
+
color: #1a1a1a;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.industry-hero__desc {
|
|
217
|
+
margin: 0 0 8px;
|
|
218
|
+
font-size: 16px;
|
|
219
|
+
font-weight: 600;
|
|
220
|
+
line-height: var(--gen-ai-lh-relaxed);
|
|
221
|
+
color: #666;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.industry-hero__actions {
|
|
225
|
+
display: flex;
|
|
226
|
+
flex-wrap: wrap;
|
|
227
|
+
align-items: center;
|
|
228
|
+
justify-content: center;
|
|
229
|
+
gap: 16px;
|
|
230
|
+
margin-top: 28px;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.industry-reports {
|
|
234
|
+
width: 80%;
|
|
235
|
+
max-width: 80%;
|
|
236
|
+
margin: 0 auto;
|
|
237
|
+
padding: 0;
|
|
238
|
+
box-sizing: border-box;
|
|
239
|
+
flex: 1 1 auto;
|
|
240
|
+
min-height: 0;
|
|
241
|
+
display: flex;
|
|
242
|
+
flex-direction: column;
|
|
243
|
+
overflow: hidden;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.industry-reports :deep(.recent-reports-table) {
|
|
247
|
+
flex: 0 1 auto;
|
|
248
|
+
min-height: 0;
|
|
249
|
+
width: 100%;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.industry-reports__title {
|
|
253
|
+
display: inline-flex;
|
|
254
|
+
align-items: center;
|
|
255
|
+
gap: 8px;
|
|
256
|
+
margin: 0 0 16px;
|
|
257
|
+
padding: 0;
|
|
258
|
+
font-size: 18px;
|
|
259
|
+
font-weight: var(--gen-ai-fw-semibold);
|
|
260
|
+
color: #1a1a1a;
|
|
261
|
+
text-align: left;
|
|
262
|
+
width: 100%;
|
|
263
|
+
flex-shrink: 0;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.industry-reports__title-icon {
|
|
267
|
+
font-size: var(--gen-ai-fs-lg);
|
|
268
|
+
color: #606266;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.industry-reports__more {
|
|
272
|
+
display: inline-block;
|
|
273
|
+
margin: 12px 0 0;
|
|
274
|
+
padding: 0;
|
|
275
|
+
font-size: var(--gen-ai-fs-base);
|
|
276
|
+
color: #409eff;
|
|
277
|
+
text-decoration: none;
|
|
278
|
+
cursor: pointer;
|
|
279
|
+
text-align: left;
|
|
280
|
+
flex-shrink: 0;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.industry-reports__more:hover {
|
|
284
|
+
color: #66b1ff;
|
|
285
|
+
text-decoration: none;
|
|
286
|
+
}
|
|
287
|
+
</style>
|
package/gen-ai/i.mark
ADDED