aegon-lv82 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/package.json +12 -0
- package/src/App.vue +44 -0
- package/src/api/index.ts +19 -0
- package/src/api/modules/build-report/reportEditor.ts +526 -0
- package/src/api/modules/build-report/reportPermission.ts +64 -0
- package/src/api/modules/index.ts +69 -0
- package/src/api/modules/industry/green_mortgage.ts +42 -0
- package/src/api/modules/user/index.ts +4 -0
- package/src/api/request.ts +124 -0
- package/src/assets/sample-access-icon.png +0 -0
- package/src/assets/sample-pie-chart.png +0 -0
- package/src/assets/vue.svg +1 -0
- package/src/components/CapsuleScrollbar.vue +7 -0
- package/src/components/Export/ExcelExport.vue +592 -0
- package/src/components/Export/ExcelExport2.vue +494 -0
- package/src/components/Export/ExcelExport3.vue +342 -0
- package/src/components/Export/ExcelExport4.vue +665 -0
- package/src/components/Export/excelExport.js +547 -0
- package/src/components/Export/excelExport.ts +551 -0
- package/src/components/GEN-AI/index.vue +140 -0
- package/src/components/GEN-AI/index1.vue +422 -0
- package/src/components/GEN-AI/index10.vue +5 -0
- package/src/components/GEN-AI/index2.vue +548 -0
- package/src/components/GEN-AI/index3.vue +605 -0
- package/src/components/GEN-AI/index4.vue +609 -0
- package/src/components/GEN-AI/index5.vue +558 -0
- package/src/components/GEN-AI/index6.vue +634 -0
- package/src/components/GEN-AI/index7.vue +688 -0
- package/src/components/GEN-AI/index8.vue +458 -0
- package/src/components/GEN-AI/index9.vue +1217 -0
- package/src/components/GEN-AI/types.ts +12 -0
- package/src/components/GEN-AI/utils.ts +42 -0
- package/src/components/HelloWorld.vue +41 -0
- package/src/components/PageCard.vue +124 -0
- package/src/components/PageHeader.vue +32 -0
- package/src/components/backup/index5 copy.vue +556 -0
- package/src/components/backup/index5.vue +620 -0
- package/src/components/backup/index9 copy.vue +1029 -0
- package/src/components/backup/index9-pro.vue +1065 -0
- package/src/components/backup/index9.vue +1057 -0
- package/src/directives/btnLoading.ts +455 -0
- package/src/directives/debounce copy.ts +670 -0
- package/src/directives/debounce.ts +98 -0
- package/src/directives/index.ts +25 -0
- package/src/layouts/MainLayout.vue +129 -0
- package/src/main.ts +76 -0
- package/src/router/index.ts +142 -0
- package/src/router/menus.ts +28 -0
- package/src/store/modules/gen-ai/index.ts +1 -0
- package/src/store/modules/gen-ai/reportBuild.ts +37 -0
- package/src/style.css +79 -0
- package/src/styles/report-config-popover.css +39 -0
- package/src/styles/report-icon-btn.css +19 -0
- package/src/test/mock.ts +101 -0
- package/src/test/test1.vue +402 -0
- package/src/test/test2.vue +1689 -0
- package/src/types/gen-ai/build-report/reportEditor.ts +684 -0
- package/src/utils/function.ts +46 -0
- package/src/utils/gen-ai-navigation.ts +1 -0
- package/src/utils/gen-ai-scroll.ts +1 -0
- package/src/utils/openDataLoaderWordExport.ts +33 -0
- package/src/utils/pageScrollbar.ts +115 -0
- package/src/utils/randomTranscode.ts +87 -0
- package/src/utils/reportPdfExport.ts +44 -0
- package/src/views/Blank.vue +68 -0
- package/src/views/Home.vue +29 -0
- package/src/views/TemplateCenter/Knowledge.ts +83 -0
- package/src/views/TemplateCenter/data.d.ts +10 -0
- package/src/views/TemplateCenter/index.vue +1128 -0
- package/src/views/TemplateCenter/service.ts +69 -0
- package/src/views/gen-ai/build-report/chartStreamRefs.ts +174 -0
- package/src/views/gen-ai/build-report/coherence-check/index.vue +559 -0
- package/src/views/gen-ai/build-report/components/ReportChapterWorkspace.vue +4258 -0
- package/src/views/gen-ai/build-report/components/ReportConfigPanel.vue +727 -0
- package/src/views/gen-ai/build-report/components/ReportGenerateSettingsPanel.vue +2361 -0
- package/src/views/gen-ai/build-report/components/ReportGeneratingPanel.vue +1765 -0
- package/src/views/gen-ai/build-report/components/ReportPromptPanel.vue +614 -0
- package/src/views/gen-ai/build-report/components/ReportSourceFileSummary.vue +656 -0
- package/src/views/gen-ai/build-report/components/ReportSourcesPanel.vue +1327 -0
- package/src/views/gen-ai/build-report/components/ReportTemplateDetail.vue +191 -0
- package/src/views/gen-ai/build-report/components/ReportTemplateEditorFormPanel.vue +667 -0
- package/src/views/gen-ai/build-report/components/ReportTemplatePicker.vue +302 -0
- package/src/views/gen-ai/build-report/components/ReportWorkflowSidebar.vue +148 -0
- package/src/views/gen-ai/build-report/components/paramsSetting.vue +886 -0
- package/src/views/gen-ai/build-report/components/reportEdit.vue +2283 -0
- package/src/views/gen-ai/build-report/index.vue +856 -0
- package/src/views/gen-ai/build-report/report-domain.ts +1133 -0
- package/src/views/gen-ai/build-report/report-template-data.ts +295 -0
- package/src/views/gen-ai/build-report/useReportWorkflow.ts +1408 -0
- package/src/views/gen-ai/common/assets/NotoSans-SC.woff2 +0 -0
- package/src/views/gen-ai/common/assets/NotoSans-TC.woff2 +0 -0
- package/src/views/gen-ai/common/assets/NotoSans.woff2 +0 -0
- package/src/views/gen-ai/common/assets/fonts.css +278 -0
- package/src/views/gen-ai/common/assets/pagination.css +163 -0
- package/src/views/gen-ai/common/directives/btnLoading.ts +455 -0
- package/src/views/gen-ai/common/directives/debounce.ts +98 -0
- package/src/views/gen-ai/common/directives/index.ts +30 -0
- package/src/views/gen-ai/common/en.md +417 -0
- package/src/views/gen-ai/common/index.ts +36 -0
- package/src/views/gen-ai/common/types/component-expose.ts +9 -0
- package/src/views/gen-ai/common/utils/api-res-status.ts +7 -0
- package/src/views/gen-ai/common/utils/navigation.ts +59 -0
- package/src/views/gen-ai/common/utils/remote-request.ts +45 -0
- package/src/views/gen-ai/common/utils/scroll.ts +577 -0
- package/src/views/gen-ai/components/AIExport/docx-export.ts +950 -0
- package/src/views/gen-ai/components/AIExport/docxExport.ts +2566 -0
- package/src/views/gen-ai/components/AIExport/index.ts +52 -0
- package/src/views/gen-ai/components/AIExport/parseMarkdownHtml.ts +649 -0
- package/src/views/gen-ai/components/CapsuleScrollbar.vue +149 -0
- package/src/views/gen-ai/components/ChapterTitleScroll.vue +468 -0
- package/src/views/gen-ai/components/EntryHeroNavCards.vue +379 -0
- package/src/views/gen-ai/components/GenAiPagination.vue +52 -0
- package/src/views/gen-ai/components/ModelCard.vue +1114 -0
- package/src/views/gen-ai/components/Preview/FilePreviewPage.vue +947 -0
- package/src/views/gen-ai/components/Preview/PreviewCapsuleScroll.vue +205 -0
- package/src/views/gen-ai/components/Preview/PreviewOutlineTree.vue +148 -0
- package/src/views/gen-ai/components/Preview/index.ts +11 -0
- package/src/views/gen-ai/components/Preview/preview.ts +722 -0
- package/src/views/gen-ai/components/PromptField.vue +505 -0
- package/src/views/gen-ai/components/RecentReportsTable.vue +974 -0
- package/src/views/gen-ai/components/ReportCollapsibleSection.vue +172 -0
- package/src/views/gen-ai/components/ReportHistoryList.vue +637 -0
- package/src/views/gen-ai/components/ReportSectionConfirmPopover.vue +251 -0
- package/src/views/gen-ai/components/editor/ChapterTiptapEditor.vue +3139 -0
- package/src/views/gen-ai/components/editor/StructureBlockView.vue +441 -0
- package/src/views/gen-ai/components/editor/TiptapToolbar.vue +1036 -0
- package/src/views/gen-ai/components/editor/TypewriterDocEditor.vue +398 -0
- package/src/views/gen-ai/components/editor/_StructureOrgNode.vue +326 -0
- package/src/views/gen-ai/components/editor/index.ts +12 -0
- package/src/views/gen-ai/components/editor/parseMarkdownHtml.ts +667 -0
- package/src/views/gen-ai/gen-entry/api/index.ts +32 -0
- package/src/views/gen-ai/gen-entry/index.vue +287 -0
- package/src/views/gen-ai/gen-entry/types/index.ts +4 -0
- package/src/views/gen-ai/i.mark +2 -0
- package/src/views/gen-ai/management-center/index.vue +1815 -0
- package/src/views/gen-ai/management-center/mockData.ts +248 -0
- package/src/views/gen-ai/management-center/types/index.ts +37 -0
- package/src/views/gen-ai/model-manager/TemplateEditorFormPanel.vue +661 -0
- package/src/views/gen-ai/model-manager/api/index.ts +32 -0
- package/src/views/gen-ai/model-manager/api/mockApi.ts +33 -0
- package/src/views/gen-ai/model-manager/index.vue +1583 -0
- package/src/views/gen-ai/model-manager/mockData.ts +177 -0
- package/src/views/gen-ai/model-manager/template-detail-shared.ts +154 -0
- package/src/views/gen-ai/model-manager/template-editor.vue +345 -0
- package/src/views/gen-ai/model-manager/types/index.ts +40 -0
- package/src/views/gen-ai/model-manager/utils.ts +25 -0
- package/src/views/greenMortgage.vue +1834 -0
- package/src/vite-env.d.ts +46 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Directive, DirectiveBinding } from 'vue'
|
|
2
|
+
|
|
3
|
+
const DEBOUNCE_KEY = Symbol('vDebounce')
|
|
4
|
+
|
|
5
|
+
/** 默认防重间隔 2s;v-debounce:800 自定义毫秒 */
|
|
6
|
+
const DEFAULT_WAIT_MS = 2000
|
|
7
|
+
const DEFAULT_EVENT = 'click'
|
|
8
|
+
|
|
9
|
+
export type DebounceHandler = (event: Event) => unknown
|
|
10
|
+
export type DebounceBindingValue = DebounceHandler | undefined
|
|
11
|
+
export type DebounceDirective = Directive<HTMLElement, DebounceBindingValue>
|
|
12
|
+
export type DebounceDirectiveBinding = DirectiveBinding<DebounceBindingValue>
|
|
13
|
+
|
|
14
|
+
interface DebounceBindingMeta {
|
|
15
|
+
listener: (event: Event) => void
|
|
16
|
+
event: string
|
|
17
|
+
binding: DebounceDirectiveBinding
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function resolveButtonHost(el: HTMLElement): HTMLElement {
|
|
21
|
+
if (el.tagName === 'BUTTON') return el
|
|
22
|
+
const nested = el.querySelector<HTMLElement>('button.el-button')
|
|
23
|
+
return nested ?? el
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function resolveWait(arg?: string): number {
|
|
27
|
+
if (arg && /^\d+$/.test(arg)) return Number(arg)
|
|
28
|
+
return DEFAULT_WAIT_MS
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolveEvent(arg?: string): string {
|
|
32
|
+
if (arg && !/^\d+$/.test(arg)) return arg
|
|
33
|
+
return DEFAULT_EVENT
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* v-debounce — 纯点击防重,与 loading 解耦
|
|
38
|
+
* - v-debounce @click="fn" 默认 2s
|
|
39
|
+
* - v-debounce:800 @click="fn" 自定义间隔
|
|
40
|
+
* - v-debounce:800="fn" 绑定 handler(拦截原生 @click)
|
|
41
|
+
*/
|
|
42
|
+
export const vDebounce: DebounceDirective = {
|
|
43
|
+
mounted(el: HTMLElement, binding: DebounceDirectiveBinding) {
|
|
44
|
+
const host = resolveButtonHost(el)
|
|
45
|
+
let locked = false
|
|
46
|
+
|
|
47
|
+
const listener = (e: Event) => {
|
|
48
|
+
const meta = (host as HTMLElement & { [DEBOUNCE_KEY]?: DebounceBindingMeta })[DEBOUNCE_KEY]
|
|
49
|
+
const currentBinding = meta?.binding ?? binding
|
|
50
|
+
const wait = resolveWait(currentBinding.arg)
|
|
51
|
+
const handler =
|
|
52
|
+
typeof currentBinding.value === 'function' ? currentBinding.value : undefined
|
|
53
|
+
|
|
54
|
+
if (locked) {
|
|
55
|
+
e.preventDefault()
|
|
56
|
+
e.stopImmediatePropagation()
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
locked = true
|
|
61
|
+
|
|
62
|
+
if (handler) {
|
|
63
|
+
e.preventDefault()
|
|
64
|
+
e.stopImmediatePropagation()
|
|
65
|
+
Promise.resolve(handler(e)).finally(() => {
|
|
66
|
+
window.setTimeout(() => {
|
|
67
|
+
locked = false
|
|
68
|
+
}, wait)
|
|
69
|
+
})
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
window.setTimeout(() => {
|
|
74
|
+
locked = false
|
|
75
|
+
}, wait)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const event = resolveEvent(binding.arg)
|
|
79
|
+
host.addEventListener(event, listener, true)
|
|
80
|
+
;(host as HTMLElement & { [DEBOUNCE_KEY]?: DebounceBindingMeta })[DEBOUNCE_KEY] = {
|
|
81
|
+
listener,
|
|
82
|
+
event,
|
|
83
|
+
binding,
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
updated(el: HTMLElement, binding: DebounceDirectiveBinding) {
|
|
87
|
+
const host = resolveButtonHost(el)
|
|
88
|
+
const meta = (host as HTMLElement & { [DEBOUNCE_KEY]?: DebounceBindingMeta })[DEBOUNCE_KEY]
|
|
89
|
+
if (meta) meta.binding = binding
|
|
90
|
+
},
|
|
91
|
+
unmounted(el: HTMLElement) {
|
|
92
|
+
const host = resolveButtonHost(el)
|
|
93
|
+
const meta = (host as HTMLElement & { [DEBOUNCE_KEY]?: DebounceBindingMeta })[DEBOUNCE_KEY]
|
|
94
|
+
if (!meta) return
|
|
95
|
+
host.removeEventListener(meta.event, meta.listener, true)
|
|
96
|
+
delete (host as HTMLElement & { [DEBOUNCE_KEY]?: DebounceBindingMeta })[DEBOUNCE_KEY]
|
|
97
|
+
},
|
|
98
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { App, Directive } from 'vue'
|
|
2
|
+
import { closeBtnLoading, vBtnLoading } from './btnLoading'
|
|
3
|
+
import { vDebounce } from './debounce'
|
|
4
|
+
|
|
5
|
+
/** 全局自定义指令清单(新增指令在此单独追加一项) */
|
|
6
|
+
const directiveRegistry: ReadonlyArray<{
|
|
7
|
+
name: string
|
|
8
|
+
directive: Directive
|
|
9
|
+
}> = [
|
|
10
|
+
{ name: 'debounce', directive: vDebounce as Directive },
|
|
11
|
+
{ name: 'btnLoading', directive: vBtnLoading },
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
export function registerDirectives(app: App) {
|
|
15
|
+
directiveRegistry.forEach(({ name, directive }) => {
|
|
16
|
+
app.directive(name, directive)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
app.config.globalProperties.closeBtnLoading = closeBtnLoading
|
|
20
|
+
;(globalThis as typeof globalThis & { closeBtnLoading: typeof closeBtnLoading }).closeBtnLoading =
|
|
21
|
+
closeBtnLoading
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { vDebounce, type DebounceBindingValue, type DebounceDirective, type DebounceHandler } from './debounce'
|
|
25
|
+
export { vBtnLoading, closeBtnLoading, hasActiveBtnLoading } from './btnLoading'
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-container class="main-layout">
|
|
3
|
+
<el-aside width="220px" class="main-layout__aside">
|
|
4
|
+
<div class="main-layout__logo">GenAI Demo</div>
|
|
5
|
+
<el-menu
|
|
6
|
+
:default-active="activeMenu"
|
|
7
|
+
router
|
|
8
|
+
class="main-layout__menu"
|
|
9
|
+
>
|
|
10
|
+
<el-menu-item index="/">
|
|
11
|
+
<span>HOME</span>
|
|
12
|
+
</el-menu-item>
|
|
13
|
+
<el-menu-item index="/blank">
|
|
14
|
+
<span>SMART</span>
|
|
15
|
+
</el-menu-item>
|
|
16
|
+
<el-menu-item index="/report-center">
|
|
17
|
+
<span>ReportCenter</span>
|
|
18
|
+
</el-menu-item>
|
|
19
|
+
<el-menu-item index="new-tab:template-center" @click.stop.prevent="openTemplateCenterPage">
|
|
20
|
+
<span>TemplateCenter</span>
|
|
21
|
+
</el-menu-item>
|
|
22
|
+
<el-menu-item index="/admin-center">
|
|
23
|
+
<span>AdminCenter</span>
|
|
24
|
+
</el-menu-item>
|
|
25
|
+
<el-sub-menu index="gen-ai">
|
|
26
|
+
<template #title>
|
|
27
|
+
<span>GEN-TYPER</span>
|
|
28
|
+
</template>
|
|
29
|
+
<el-menu-item
|
|
30
|
+
v-for="item in genAiAppMenus"
|
|
31
|
+
:key="item.path"
|
|
32
|
+
:index="item.path"
|
|
33
|
+
>
|
|
34
|
+
{{ item.title }}
|
|
35
|
+
</el-menu-item>
|
|
36
|
+
<el-menu-item
|
|
37
|
+
v-for="item in genAiMenus"
|
|
38
|
+
:key="item.path"
|
|
39
|
+
:index="item.path"
|
|
40
|
+
>
|
|
41
|
+
{{ item.title }}
|
|
42
|
+
</el-menu-item>
|
|
43
|
+
</el-sub-menu>
|
|
44
|
+
</el-menu>
|
|
45
|
+
</el-aside>
|
|
46
|
+
<el-main class="main-layout__main layout">
|
|
47
|
+
<PageCard>
|
|
48
|
+
<router-view />
|
|
49
|
+
</PageCard>
|
|
50
|
+
</el-main>
|
|
51
|
+
</el-container>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script setup lang="ts">
|
|
55
|
+
import { computed } from 'vue'
|
|
56
|
+
import { useRoute, useRouter } from 'vue-router'
|
|
57
|
+
import PageCard from '../components/PageCard.vue'
|
|
58
|
+
import { genAiAppMenus, genAiMenus } from '../router/menus'
|
|
59
|
+
import { openTemplateCenter } from '@/views/gen-ai/common/utils/navigation'
|
|
60
|
+
|
|
61
|
+
const route = useRoute()
|
|
62
|
+
const router = useRouter()
|
|
63
|
+
|
|
64
|
+
const activeMenu = computed(() => route.path)
|
|
65
|
+
|
|
66
|
+
function openTemplateCenterPage() {
|
|
67
|
+
openTemplateCenter(router)
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<style scoped>
|
|
72
|
+
.main-layout {
|
|
73
|
+
--page-bg: #f3f4f6;
|
|
74
|
+
--page-outer-spacing: 20px;
|
|
75
|
+
--page-card-border: #e8eaec;
|
|
76
|
+
height: 100vh;
|
|
77
|
+
min-height: 100vh;
|
|
78
|
+
background: var(--page-bg);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.main-layout__aside {
|
|
82
|
+
background: #fff;
|
|
83
|
+
border-right: 1px solid var(--page-card-border);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.main-layout__logo {
|
|
87
|
+
height: 56px;
|
|
88
|
+
line-height: 56px;
|
|
89
|
+
padding: 0 20px;
|
|
90
|
+
font-size: 16px;
|
|
91
|
+
font-weight: 600;
|
|
92
|
+
color: #2d3139;
|
|
93
|
+
border-bottom: 1px solid var(--page-card-border);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.main-layout__menu {
|
|
97
|
+
border-right: none;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.main-layout__main.layout {
|
|
101
|
+
flex: 1;
|
|
102
|
+
min-height: 0;
|
|
103
|
+
display: flex;
|
|
104
|
+
flex-direction: column;
|
|
105
|
+
padding: var(--page-outer-spacing);
|
|
106
|
+
box-sizing: border-box;
|
|
107
|
+
height: 100%;
|
|
108
|
+
overflow-x: hidden;
|
|
109
|
+
overflow-y: auto;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* 報告編輯頁:禁最外層滾動,高度交給內欄 el-scrollbar */
|
|
113
|
+
.main-layout__main:has(:deep(.report-edit-page)) {
|
|
114
|
+
overflow: hidden;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* prompt 三欄:貼齊可見視窗(頂欄 62px) */
|
|
118
|
+
.main-layout__main:has(:deep(.report-edit-page.is-prompt)) {
|
|
119
|
+
padding: 0;
|
|
120
|
+
max-height: calc(100dvh - 62px);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Green Mortgage:灰底 + 外邊距;白色 iOS card 由 el-card__body 承載 */
|
|
124
|
+
.main-layout__main.layout:has(:deep(.green-mortgage-page)) {
|
|
125
|
+
padding: 24px 20px 20px;
|
|
126
|
+
background: #f2f2f7;
|
|
127
|
+
box-sizing: border-box;
|
|
128
|
+
}
|
|
129
|
+
</style>
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { registerDirectives } from '@/directives'
|
|
2
|
+
import { registerGenAiDirectives } from '@/views/gen-ai/common/directives'
|
|
3
|
+
import CapsuleScrollbar from '@/views/gen-ai/components/CapsuleScrollbar.vue'
|
|
4
|
+
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
|
5
|
+
import ElementPlus from 'element-plus'
|
|
6
|
+
import 'element-plus/dist/index.css'
|
|
7
|
+
import zhTw from 'element-plus/es/locale/lang/zh-tw'
|
|
8
|
+
import { createPinia } from 'pinia'
|
|
9
|
+
import { createApp, type App as VueApp } from 'vue'
|
|
10
|
+
import App from './App.vue'
|
|
11
|
+
import router from './router'
|
|
12
|
+
|
|
13
|
+
let app: VueApp | null = null
|
|
14
|
+
|
|
15
|
+
function registerElementPlusIcons(instance: VueApp) {
|
|
16
|
+
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
17
|
+
instance.component(key, component)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function mountApp() {
|
|
22
|
+
if (app) return
|
|
23
|
+
app = createApp(App)
|
|
24
|
+
registerElementPlusIcons(app)
|
|
25
|
+
registerDirectives(app)
|
|
26
|
+
registerGenAiDirectives(app)
|
|
27
|
+
app.component('CapsuleScrollbar', CapsuleScrollbar)
|
|
28
|
+
app.use(createPinia())
|
|
29
|
+
app.use(ElementPlus, { locale: zhTw })
|
|
30
|
+
app.use(router)
|
|
31
|
+
app.mount('#app')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function unmountApp() {
|
|
35
|
+
app?.unmount()
|
|
36
|
+
app = null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function shouldRemountOnUpdate(payload: { updates?: Array<{ type?: string }> }) {
|
|
40
|
+
return (
|
|
41
|
+
payload.updates?.some((update) => update.type === 'js-update' || update.type === 'vue') ?? false
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
mountApp()
|
|
46
|
+
|
|
47
|
+
if (import.meta.hot) {
|
|
48
|
+
import.meta.hot.accept(['./App.vue'], () => {
|
|
49
|
+
unmountApp()
|
|
50
|
+
mountApp()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
import.meta.hot.accept(
|
|
54
|
+
['./components/GEN-AI/index9.vue', './components/GEN-AI/index10.vue', './views/gen-ai/components/AIExport/docxExport.ts'],
|
|
55
|
+
() => {
|
|
56
|
+
unmountApp()
|
|
57
|
+
mountApp()
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
import.meta.hot.on('vite:beforeUpdate', (payload) => {
|
|
62
|
+
if (shouldRemountOnUpdate(payload)) {
|
|
63
|
+
unmountApp()
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
import.meta.hot.on('vite:afterUpdate', (payload) => {
|
|
68
|
+
if (shouldRemountOnUpdate(payload) && !app) {
|
|
69
|
+
mountApp()
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
import.meta.hot.dispose(() => {
|
|
74
|
+
unmountApp()
|
|
75
|
+
})
|
|
76
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// router/index.ts
|
|
2
|
+
import type { Component } from 'vue'
|
|
3
|
+
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
|
|
4
|
+
import MainLayout from '../layouts/MainLayout.vue'
|
|
5
|
+
import { genAiMenus } from './menus'
|
|
6
|
+
|
|
7
|
+
const genAiModules = import.meta.glob('../components/GEN-AI/index*.vue')
|
|
8
|
+
|
|
9
|
+
const genAiRoutes: RouteRecordRaw[] = genAiMenus.flatMap((item) => {
|
|
10
|
+
const modulePath = `../components/GEN-AI/${item.file}.vue`
|
|
11
|
+
const componentLoader = genAiModules[modulePath]
|
|
12
|
+
if (!componentLoader) {
|
|
13
|
+
console.warn(`GEN-AI component not found: ${modulePath}`)
|
|
14
|
+
return []
|
|
15
|
+
}
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
path: item.path.replace(/^\//, ''),
|
|
19
|
+
name: `GenAI-${item.file}`,
|
|
20
|
+
component: componentLoader as () => Promise<Component>,
|
|
21
|
+
meta: { title: item.title, group: 'GEN-TYPER' },
|
|
22
|
+
},
|
|
23
|
+
]
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const routes: RouteRecordRaw[] = [
|
|
27
|
+
{
|
|
28
|
+
path: '/gen-ai/gen-entry',
|
|
29
|
+
name: 'gen-entry',
|
|
30
|
+
component: () => import('../views/gen-ai/gen-entry/index.vue'),
|
|
31
|
+
meta: { title: '行業分析', standalone: true },
|
|
32
|
+
},
|
|
33
|
+
{ path: '/gen-entry', redirect: '/gen-ai/gen-entry' },
|
|
34
|
+
{
|
|
35
|
+
path: '/gen-ai/model-manager',
|
|
36
|
+
name: 'model-manager',
|
|
37
|
+
component: () => import('../views/gen-ai/model-manager/index.vue'),
|
|
38
|
+
meta: { title: '模板中心', standalone: true },
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
path: '/gen-ai/model-manager/template-editor',
|
|
42
|
+
name: 'model-manager-template-editor',
|
|
43
|
+
component: () => import('../views/gen-ai/model-manager/template-editor.vue'),
|
|
44
|
+
meta: { title: '報告模板編輯', standalone: true },
|
|
45
|
+
},
|
|
46
|
+
{ path: '/model-manager', redirect: '/gen-ai/model-manager' },
|
|
47
|
+
{
|
|
48
|
+
path: '/gen-ai/management-center',
|
|
49
|
+
name: 'management-center',
|
|
50
|
+
component: () => import('../views/gen-ai/management-center/index.vue'),
|
|
51
|
+
meta: { title: '管理中心', standalone: true },
|
|
52
|
+
},
|
|
53
|
+
{ path: '/management-center', redirect: '/gen-ai/management-center' },
|
|
54
|
+
{
|
|
55
|
+
path: '/gen-ai/build-report',
|
|
56
|
+
name: 'build-report',
|
|
57
|
+
component: () => import('../views/gen-ai/build-report/index.vue'),
|
|
58
|
+
meta: { title: '新建報告', standalone: true },
|
|
59
|
+
},
|
|
60
|
+
// report-list.vue 已刪除:原「報告中心」列表改走 gen-entry
|
|
61
|
+
{
|
|
62
|
+
path: '/gen-ai/build-report/list',
|
|
63
|
+
redirect: '/gen-ai/gen-entry',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
path: '/gen-ai/build-report/coherence-check',
|
|
67
|
+
name: 'report-coherence-check',
|
|
68
|
+
component: () => import('../views/gen-ai/build-report/coherence-check/index.vue'),
|
|
69
|
+
meta: { title: '報告連貫性檢查', standalone: true },
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
path: '/gen-ai/file-preview',
|
|
73
|
+
name: 'gen-ai-file-preview',
|
|
74
|
+
component: () => import('../views/gen-ai/components/Preview/FilePreviewPage.vue'),
|
|
75
|
+
meta: { title: '檔案預覽', standalone: true },
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
path: '/gen-ai/build-report/model',
|
|
79
|
+
name: 'report-model',
|
|
80
|
+
redirect: (to) => ({
|
|
81
|
+
path: '/gen-ai/build-report',
|
|
82
|
+
query: { pageName: 'reportEdit', step: 'select', ...to.query },
|
|
83
|
+
}),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
path: '/gen-ai/build-report/generating',
|
|
87
|
+
name: 'report-generating',
|
|
88
|
+
redirect: (to) => ({
|
|
89
|
+
path: '/gen-ai/build-report',
|
|
90
|
+
query: { pageName: 'reportEdit', step: 'generating', ...to.query },
|
|
91
|
+
}),
|
|
92
|
+
},
|
|
93
|
+
{ path: '/gen-ai/report-center', redirect: '/gen-ai/gen-entry' },
|
|
94
|
+
{ path: '/gen-ai/report-center/create', redirect: '/gen-ai/build-report' },
|
|
95
|
+
{ path: '/gen-ai/report-center/model', redirect: { name: 'report-model' } },
|
|
96
|
+
{ path: '/gen-ai/report-center/generating', redirect: { name: 'report-generating' } },
|
|
97
|
+
{
|
|
98
|
+
path: '/template-center',
|
|
99
|
+
name: 'TemplateCenter',
|
|
100
|
+
component: () => import('../test/test2.vue'),
|
|
101
|
+
meta: { title: '模板中心', standalone: true },
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
path: '/',
|
|
105
|
+
component: MainLayout,
|
|
106
|
+
children: [
|
|
107
|
+
{
|
|
108
|
+
path: '',
|
|
109
|
+
name: 'Home',
|
|
110
|
+
component: () => import('../views/Home.vue'),
|
|
111
|
+
meta: { title: 'HOME' },
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
path: 'blank',
|
|
115
|
+
name: 'Blank',
|
|
116
|
+
component: () => import('../views/Blank.vue'),
|
|
117
|
+
meta: { title: 'SMART' },
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
path: 'green-mortgage',
|
|
121
|
+
name: 'GreenMortgage',
|
|
122
|
+
component: () => import('../views/greenMortgage.vue'),
|
|
123
|
+
meta: { title: 'Green Mortgage' },
|
|
124
|
+
},
|
|
125
|
+
{ path: 'report-center', redirect: '/gen-ai/gen-entry' },
|
|
126
|
+
{
|
|
127
|
+
path: 'admin-center',
|
|
128
|
+
name: 'AdminCenter',
|
|
129
|
+
component: () => import('../views/gen-ai/build-report/components/paramsSetting.vue'),
|
|
130
|
+
meta: { title: '管理後台' },
|
|
131
|
+
},
|
|
132
|
+
...genAiRoutes,
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
const router = createRouter({
|
|
138
|
+
history: createWebHistory(import.meta.env.BASE_URL),
|
|
139
|
+
routes,
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
export default router
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface GenAiMenuItem {
|
|
2
|
+
title: string
|
|
3
|
+
path: string
|
|
4
|
+
file: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/** GEN-AI 業務頁面(獨立全屏) */
|
|
8
|
+
export const genAiAppMenus: GenAiMenuItem[] = [
|
|
9
|
+
{ title: '行業分析', path: '/gen-ai/gen-entry', file: 'gen-entry' },
|
|
10
|
+
{ title: '報告中心', path: '/gen-ai/gen-entry', file: 'build-report' },
|
|
11
|
+
{ title: '模板中心', path: '/gen-ai/model-manager', file: 'model-manager' },
|
|
12
|
+
{ title: '管理中心', path: '/gen-ai/management-center', file: 'management-center' },
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
/** GEN-AI 目录下全部 index 页面(二级菜单) */
|
|
16
|
+
export const genAiMenus: GenAiMenuItem[] = [
|
|
17
|
+
{ title: 'index', path: '/gen-ai/index', file: 'index' },
|
|
18
|
+
{ title: 'index1', path: '/gen-ai/index1', file: 'index1' },
|
|
19
|
+
{ title: 'index2', path: '/gen-ai/index2', file: 'index2' },
|
|
20
|
+
{ title: 'index3', path: '/gen-ai/index3', file: 'index3' },
|
|
21
|
+
{ title: 'index4', path: '/gen-ai/index4', file: 'index4' },
|
|
22
|
+
{ title: 'index5', path: '/gen-ai/index5', file: 'index5' },
|
|
23
|
+
{ title: 'index6', path: '/gen-ai/index6', file: 'index6' },
|
|
24
|
+
{ title: 'index7', path: '/gen-ai/index7', file: 'index7' },
|
|
25
|
+
{ title: 'index8', path: '/gen-ai/index8', file: 'index8' },
|
|
26
|
+
{ title: 'index9', path: '/gen-ai/index9', file: 'index9' },
|
|
27
|
+
{ title: 'index10', path: '/gen-ai/index10', file: 'index10' },
|
|
28
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useGenAiBuildReportStore } from './reportBuild'
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 報告構建流程共享狀態
|
|
6
|
+
* instanceId:進入報告編輯 / 設置頁後由業務寫入
|
|
7
|
+
*/
|
|
8
|
+
export const useGenAiBuildReportStore = defineStore('genAiBuildReport', () => {
|
|
9
|
+
const instanceId = ref<string | null>(null)
|
|
10
|
+
|
|
11
|
+
function setInstanceId(id: string | null) {
|
|
12
|
+
instanceId.value = id == null || id === '' ? null : String(id).trim()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function clearInstanceId() {
|
|
16
|
+
instanceId.value = null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** 與遷移頁 init 對齊:從本地恢復 instanceId(無則保持現值) */
|
|
20
|
+
async function initFromStorage() {
|
|
21
|
+
try {
|
|
22
|
+
const raw = sessionStorage.getItem('genAiBuildReport.instanceId')
|
|
23
|
+
if (raw != null && String(raw).trim()) {
|
|
24
|
+
setInstanceId(String(raw).trim())
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
/* ignore */
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
instanceId,
|
|
33
|
+
setInstanceId,
|
|
34
|
+
clearInstanceId,
|
|
35
|
+
initFromStorage,
|
|
36
|
+
}
|
|
37
|
+
})
|
package/src/style.css
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
color: rgba(255, 255, 255, 0.87);
|
|
8
|
+
background-color: #242424;
|
|
9
|
+
|
|
10
|
+
font-synthesis: none;
|
|
11
|
+
text-rendering: optimizeLegibility;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
a {
|
|
17
|
+
font-weight: 500;
|
|
18
|
+
color: #646cff;
|
|
19
|
+
text-decoration: inherit;
|
|
20
|
+
}
|
|
21
|
+
a:hover {
|
|
22
|
+
color: #535bf2;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
body {
|
|
26
|
+
margin: 0;
|
|
27
|
+
display: flex;
|
|
28
|
+
place-items: center;
|
|
29
|
+
min-width: 320px;
|
|
30
|
+
min-height: 100vh;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h1 {
|
|
34
|
+
font-size: 3.2em;
|
|
35
|
+
line-height: 1.1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
button {
|
|
39
|
+
border-radius: 8px;
|
|
40
|
+
border: 1px solid transparent;
|
|
41
|
+
padding: 0.6em 1.2em;
|
|
42
|
+
font-size: 1em;
|
|
43
|
+
font-weight: 500;
|
|
44
|
+
font-family: inherit;
|
|
45
|
+
background-color: #1a1a1a;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
transition: border-color 0.25s;
|
|
48
|
+
}
|
|
49
|
+
button:hover {
|
|
50
|
+
border-color: #646cff;
|
|
51
|
+
}
|
|
52
|
+
button:focus,
|
|
53
|
+
button:focus-visible {
|
|
54
|
+
outline: 4px auto -webkit-focus-ring-color;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.card {
|
|
58
|
+
padding: 2em;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#app {
|
|
62
|
+
max-width: 1280px;
|
|
63
|
+
margin: 0 auto;
|
|
64
|
+
padding: 2rem;
|
|
65
|
+
text-align: center;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@media (prefers-color-scheme: light) {
|
|
69
|
+
:root {
|
|
70
|
+
color: #213547;
|
|
71
|
+
background-color: #ffffff;
|
|
72
|
+
}
|
|
73
|
+
a:hover {
|
|
74
|
+
color: #747bff;
|
|
75
|
+
}
|
|
76
|
+
button {
|
|
77
|
+
background-color: #f9f9f9;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.report-config-popover.el-popover.el-popper {
|
|
2
|
+
max-width: 100%;
|
|
3
|
+
padding: 12px;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.report-config-popover.el-popper[data-popper-placement^='bottom'] .el-popper__arrow {
|
|
9
|
+
left: var(--report-config-arrow-left) !important;
|
|
10
|
+
right: auto !important;
|
|
11
|
+
top: -6px !important;
|
|
12
|
+
transform: translateX(-50%) !important;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.report-config-popover.el-popper[data-popper-placement^='bottom'] .el-popper__arrow::before {
|
|
16
|
+
bottom: -1px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* 仅透明度渐变,关闭时不产生向上位移浮影 */
|
|
20
|
+
.report-config-popover-fade-enter-active,
|
|
21
|
+
.report-config-popover-fade-leave-active {
|
|
22
|
+
transition: opacity 0.12s ease;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.report-config-popover-fade-enter-from,
|
|
26
|
+
.report-config-popover-fade-leave-to {
|
|
27
|
+
opacity: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* 收起区块时原地关闭,无过渡浮影 */
|
|
31
|
+
.report-config-popover-instant-enter-active,
|
|
32
|
+
.report-config-popover-instant-leave-active {
|
|
33
|
+
transition: none !important;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.report-config-popover-instant-enter-from,
|
|
37
|
+
.report-config-popover-instant-leave-to {
|
|
38
|
+
opacity: 0;
|
|
39
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.report-icon-btn {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
width: 24px;
|
|
6
|
+
height: 24px;
|
|
7
|
+
padding: 0;
|
|
8
|
+
border: 0;
|
|
9
|
+
background: none;
|
|
10
|
+
color: #4e5969;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
border-radius: 4px;
|
|
13
|
+
vertical-align: middle;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.report-icon-btn:hover {
|
|
17
|
+
color: #c53355;
|
|
18
|
+
background: #fff5f6;
|
|
19
|
+
}
|