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.
- package/package.json +12 -0
- package/src/App.vue +3 -0
- package/src/api/index.ts +19 -0
- package/src/api/modules/gen-ai/gen-entry/index.ts +30 -0
- package/src/api/modules/gen-ai/model-manager/index.ts +42 -0
- package/src/api/modules/gen-ai/model-manager/mockApi.ts +33 -0
- package/src/api/modules/index.ts +98 -0
- package/src/api/modules/user/index.ts +4 -0
- package/src/api/request.ts +102 -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 +93 -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 +142 -0
- package/src/components/GEN-AI/index1.vue +456 -0
- package/src/components/GEN-AI/index10.vue +5 -0
- package/src/components/GEN-AI/index2.vue +568 -0
- package/src/components/GEN-AI/index3.vue +623 -0
- package/src/components/GEN-AI/index4.vue +629 -0
- package/src/components/GEN-AI/index5.vue +578 -0
- package/src/components/GEN-AI/index6.vue +656 -0
- package/src/components/GEN-AI/index7.vue +717 -0
- package/src/components/GEN-AI/index8.vue +405 -0
- package/src/components/GEN-AI/index9.vue +1065 -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 +7 -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/components/el-date-picker.vue +64 -0
- package/src/directives/btnLoading.ts +427 -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 +101 -0
- package/src/main.ts +85 -0
- package/src/router/index.ts +76 -0
- package/src/router/menus.ts +28 -0
- package/src/style.css +79 -0
- package/src/styles/_variables.scss +24 -0
- package/src/styles/app-button.css +26 -0
- package/src/styles/element-overrides.css +23 -0
- package/src/styles/global.css +44 -0
- package/src/styles/index.scss +1 -0
- package/src/styles/page-card.css +21 -0
- package/src/styles/variables.css +26 -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/gen-entry/index.ts +17 -0
- package/src/types/gen-ai/model-manager/index.ts +19 -0
- package/src/utils/docxExport.ts +1610 -0
- package/src/utils/gen-ai-navigation.ts +37 -0
- package/src/utils/gen-ai-scroll.ts +455 -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/AdminCenter/index.vue +817 -0
- package/src/views/Blank.vue +68 -0
- package/src/views/Home.vue +29 -0
- package/src/views/ReportCenter/index.vue +1380 -0
- package/src/views/TemplateCenter/Knowledge.ts +83 -0
- package/src/views/TemplateCenter/data.d.ts +10 -0
- package/src/views/TemplateCenter/index.vue +1205 -0
- package/src/views/TemplateCenter/service.ts +69 -0
- package/src/views/gen-ai/components/RecentReportsTable.vue +193 -0
- package/src/views/gen-ai/gen-entry/index.vue +309 -0
- package/src/views/gen-ai/gen-entry/mockData.ts +160 -0
- package/src/views/gen-ai/management-center/index.vue +53 -0
- package/src/views/gen-ai/model-manager/ChapterTitleScroll.vue +275 -0
- package/src/views/gen-ai/model-manager/index.vue +1205 -0
- package/src/views/gen-ai/model-manager/mockData.ts +122 -0
- package/src/views/gen-ai/report-center/index.vue +158 -0
- package/src/vite-env.d.ts +38 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, reactive } from 'vue'
|
|
3
|
+
import { asBlob } from 'html-docx-js-typescript'
|
|
4
|
+
import { saveAs } from 'file-saver'
|
|
5
|
+
|
|
6
|
+
// --- 类型声明 ---
|
|
7
|
+
interface ReportConfig {
|
|
8
|
+
name: string
|
|
9
|
+
model: string
|
|
10
|
+
language: string
|
|
11
|
+
industry: string
|
|
12
|
+
year: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface SourceFile {
|
|
16
|
+
id: string
|
|
17
|
+
name: string
|
|
18
|
+
checked: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ChapterOption {
|
|
22
|
+
id: string
|
|
23
|
+
title: string
|
|
24
|
+
version: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface ReportHistory {
|
|
28
|
+
id: string
|
|
29
|
+
version: string
|
|
30
|
+
author: string
|
|
31
|
+
time: string
|
|
32
|
+
isActive?: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// --- 状态管理 ---
|
|
36
|
+
const config = reactive<ReportConfig>({
|
|
37
|
+
name: '香港房地產2024',
|
|
38
|
+
model: 'Qwen3-Max',
|
|
39
|
+
language: '中文',
|
|
40
|
+
industry: '香港房地產',
|
|
41
|
+
year: 2024
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const sharedSources = ref<SourceFile[]>([
|
|
45
|
+
{ id: 's1', name: '香港物業市場回顧及前瞻2024', checked: true },
|
|
46
|
+
{ id: 's2', name: '2024年香港住宅物業價格與租金走勢分析', checked: true },
|
|
47
|
+
{ id: 's3', name: '香港商業地產市場年度觀察報告2024', checked: true }
|
|
48
|
+
])
|
|
49
|
+
|
|
50
|
+
const personalSources = ref<SourceFile[]>([
|
|
51
|
+
{ id: 'p1', name: '香港物業市場回顧及前瞻2024', checked: true },
|
|
52
|
+
{ id: 'p2', name: '2024年香港住宅物業價格與租金走勢分析', checked: true },
|
|
53
|
+
{ id: 'p3', name: '香港商業地產市場年度觀察報告2024', checked: true }
|
|
54
|
+
])
|
|
55
|
+
|
|
56
|
+
const chapters = ref<ChapterOption[]>([
|
|
57
|
+
{ id: 'c1', title: '摘要與本年總結', version: 'V3' },
|
|
58
|
+
{ id: 'c2', title: '宏觀環境與政策背景', version: 'V3' },
|
|
59
|
+
{ id: 'c3', title: '行業運行情況與核心指標', version: 'V3' },
|
|
60
|
+
{ id: 'c4', title: '競爭格局與商業模式演變', version: 'V3' },
|
|
61
|
+
{ id: 'c5', title: '關鍵風險與監管關切', version: 'V3' },
|
|
62
|
+
{ id: 'c6', title: '附錄:數據、方法與名詞解釋', version: 'V3' }
|
|
63
|
+
])
|
|
64
|
+
|
|
65
|
+
const generateMethod = ref<'merge' | 'rewrite'>('merge')
|
|
66
|
+
|
|
67
|
+
const historyList = ref<ReportHistory[]>([
|
|
68
|
+
{ id: 'h1', version: '定稿版本', author: '陳大文', time: '15min前', isActive: true },
|
|
69
|
+
{ id: 'h2', version: 'V2', author: '陳大文', time: '15min前', isActive: false }
|
|
70
|
+
])
|
|
71
|
+
|
|
72
|
+
// --- 导出 ---
|
|
73
|
+
const isExporting = ref(false)
|
|
74
|
+
|
|
75
|
+
const exportToWord = async (containerId: string, filename: string) => {
|
|
76
|
+
const element = document.getElementById(containerId)
|
|
77
|
+
if (!element) return
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
isExporting.value = true
|
|
81
|
+
const cloneContainer = element.cloneNode(true) as HTMLElement
|
|
82
|
+
|
|
83
|
+
cloneContainer.querySelectorAll('.no-export').forEach((el) => el.remove())
|
|
84
|
+
|
|
85
|
+
cloneContainer.querySelectorAll('*').forEach((el) => {
|
|
86
|
+
const htmlEl = el as HTMLElement
|
|
87
|
+
const style = window.getComputedStyle(el)
|
|
88
|
+
htmlEl.style.color = style.color
|
|
89
|
+
htmlEl.style.fontSize = style.fontSize
|
|
90
|
+
htmlEl.style.fontFamily = style.fontFamily
|
|
91
|
+
htmlEl.style.fontWeight = style.fontWeight
|
|
92
|
+
htmlEl.style.backgroundColor = style.backgroundColor
|
|
93
|
+
htmlEl.style.textAlign = style.textAlign
|
|
94
|
+
htmlEl.style.lineHeight = style.lineHeight
|
|
95
|
+
htmlEl.style.marginBottom = style.marginBottom
|
|
96
|
+
htmlEl.style.paddingLeft = style.paddingLeft
|
|
97
|
+
htmlEl.style.borderLeft = style.borderLeft
|
|
98
|
+
if (htmlEl.tagName === 'P') {
|
|
99
|
+
htmlEl.style.marginBottom = '12pt'
|
|
100
|
+
htmlEl.style.lineHeight = '1.6'
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const contentHtml = cloneContainer.innerHTML
|
|
105
|
+
const fullHtml = `<!DOCTYPE html>
|
|
106
|
+
<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'>
|
|
107
|
+
<head>
|
|
108
|
+
<meta charset="utf-8">
|
|
109
|
+
<style>
|
|
110
|
+
@page { size: 21cm 29.7cm; margin: 2cm; }
|
|
111
|
+
body { font-family: "Microsoft YaHei", "PingFang TC", "SimSun", sans-serif; font-size: 12pt; }
|
|
112
|
+
h1 { font-size: 18pt; text-align: center; margin-bottom: 24pt; }
|
|
113
|
+
h2 { font-size: 14pt; font-weight: bold; margin-bottom: 12pt; }
|
|
114
|
+
p { margin-bottom: 12pt; line-height: 1.6; text-align: justify; }
|
|
115
|
+
</style>
|
|
116
|
+
</head>
|
|
117
|
+
<body>${contentHtml}</body>
|
|
118
|
+
</html>`
|
|
119
|
+
|
|
120
|
+
const blob = await asBlob(fullHtml, {
|
|
121
|
+
orientation: 'portrait',
|
|
122
|
+
margins: { top: 720, right: 720, bottom: 720, left: 720 },
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
saveAs(blob as Blob, `${filename}.docx`)
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Word 导出失败:', error)
|
|
128
|
+
alert('Word 导出失败,请检查浏览器控制台')
|
|
129
|
+
} finally {
|
|
130
|
+
isExporting.value = false
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// --- 业务逻辑方法 ---
|
|
135
|
+
const handleExportPDF = () => {
|
|
136
|
+
console.log('正在导出 PDF,应用 A4 打印优化布局...')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const handleExportWord = () => {
|
|
140
|
+
const filename = `${config.name}_${config.year}`.replace(/[/\\?%*:|"<>]/g, '_')
|
|
141
|
+
exportToWord('report-container', filename)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const handleGenerate = () => {
|
|
145
|
+
console.log('触发报告生成逻辑,当前模式:', generateMethod.value)
|
|
146
|
+
}
|
|
147
|
+
</script>
|
|
148
|
+
|
|
149
|
+
<template>
|
|
150
|
+
<div class="min-h-screen bg-[#f7f8fa] text-[#333] font-sans flex flex-col antialiased select-none">
|
|
151
|
+
<header class="h-14 bg-white border-b border-[#e8eaec] px-6 flex items-center justify-between shrink-0">
|
|
152
|
+
<div class="flex items-center gap-3">
|
|
153
|
+
<div class="w-7 h-5 bg-[#333] rounded-sm flex flex-col justify-between p-1">
|
|
154
|
+
<div class="h-[2px] bg-white w-full"></div>
|
|
155
|
+
<div class="h-[2px] bg-white w-2/3"></div>
|
|
156
|
+
<div class="h-[2px] bg-white w-full"></div>
|
|
157
|
+
</div>
|
|
158
|
+
<span class="font-bold text-base tracking-wide">行業分析</span>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<div class="flex items-center gap-4 text-sm text-[#666]">
|
|
162
|
+
<div class="flex items-center gap-1 cursor-pointer hover:text-primary">
|
|
163
|
+
<span class="i-unocss:translate text-lg"></span>
|
|
164
|
+
<span>繁體中文</span>
|
|
165
|
+
<span class="i-unocss:chevron-down text-xs"></span>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
</header>
|
|
169
|
+
|
|
170
|
+
<main class="flex-1 flex overflow-hidden w-full">
|
|
171
|
+
|
|
172
|
+
<aside class="w-72 bg-white border-r border-[#e8eaec] flex flex-col shrink-0 overflow-y-auto">
|
|
173
|
+
<section class="p-4 border-b border-[#e8eaec]">
|
|
174
|
+
<h3 class="font-bold text-sm mb-3 text-[#1a1a1a]">報告配置</h3>
|
|
175
|
+
<div class="space-y-2.5 text-xs">
|
|
176
|
+
<div class="flex items-center justify-between">
|
|
177
|
+
<span class="text-[#86909c]">名稱:{{ config.name }}</span>
|
|
178
|
+
<span class="i-unocss:edit text-[#999] cursor-pointer hover:text-primary"></span>
|
|
179
|
+
</div>
|
|
180
|
+
<div class="flex items-center justify-between">
|
|
181
|
+
<span class="text-[#86909c]">模型:{{ config.model }}</span>
|
|
182
|
+
<span class="i-unocss:edit text-[#999] cursor-pointer hover:text-primary"></span>
|
|
183
|
+
</div>
|
|
184
|
+
<div class="text-[#86909c]">語言:{{ config.language }}</div>
|
|
185
|
+
<div class="text-[#86909c]">行業:{{ config.industry }}</div>
|
|
186
|
+
<div class="text-[#86909c]">年份:{{ config.year }}</div>
|
|
187
|
+
</div>
|
|
188
|
+
</section>
|
|
189
|
+
|
|
190
|
+
<section class="p-4 flex-1 space-y-4">
|
|
191
|
+
<div class="flex items-center justify-between">
|
|
192
|
+
<h3 class="font-bold text-sm text-[#1a1a1a]">信息源</h3>
|
|
193
|
+
</div>
|
|
194
|
+
|
|
195
|
+
<div class="border border-dashed border-[#e8eaec] rounded-md p-4 flex flex-col items-center justify-center gap-2 cursor-pointer bg-[#fafafa] hover:bg-gray-50 transition-colors">
|
|
196
|
+
<span class="i-unocss:plus text-lg text-[#999]"></span>
|
|
197
|
+
<span class="text-xs text-[#86909c]">添加信息源</span>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<div class="flex items-center gap-2 text-xs bg-[#f4f5f7] p-2 rounded text-[#4e5969] cursor-pointer">
|
|
201
|
+
<input type="checkbox" id="web-search" checked class="accent-primary" />
|
|
202
|
+
<label for="web-search" class="cursor-pointer flex items-center gap-1">
|
|
203
|
+
<span class="i-unocss:globe"></span> 在網絡中搜索信息源
|
|
204
|
+
</label>
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<div class="space-y-2">
|
|
208
|
+
<div class="text-xs font-bold text-[#4e5969] flex items-center justify-between">
|
|
209
|
+
<span>共享文檔集</span>
|
|
210
|
+
<span class="text-[#999] font-normal scale-90">全選</span>
|
|
211
|
+
</div>
|
|
212
|
+
<div class="space-y-1.5">
|
|
213
|
+
<div v-for="file in sharedSources" :key="file.id" class="flex items-start gap-2 text-xs text-[#1d2129]">
|
|
214
|
+
<input type="checkbox" v-model="file.checked" class="mt-0.5 accent-primary" />
|
|
215
|
+
<span class="truncate pr-2" :title="file.name">📄 {{ file.name }}</span>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<div class="space-y-2">
|
|
221
|
+
<div class="text-xs font-bold text-[#4e5969] flex items-center justify-between">
|
|
222
|
+
<span>個人文檔集</span>
|
|
223
|
+
<span class="text-[#999] font-normal scale-90">全選</span>
|
|
224
|
+
</div>
|
|
225
|
+
<div class="space-y-1.5">
|
|
226
|
+
<div v-for="file in personalSources" :key="file.id" class="flex items-start gap-2 text-xs text-[#1d2129]">
|
|
227
|
+
<input type="checkbox" v-model="file.checked" class="mt-0.5 accent-primary" />
|
|
228
|
+
<span class="truncate pr-2" :title="file.name">📄 {{ file.name }}</span>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
</section>
|
|
233
|
+
</aside>
|
|
234
|
+
|
|
235
|
+
<section class="flex-1 bg-[#f0f2f5] p-6 flex flex-col overflow-y-auto items-center">
|
|
236
|
+
<div class="w-[842px] flex justify-between items-center mb-4 shrink-0">
|
|
237
|
+
<button class="px-4 py-1.5 bg-white border border-[#e8eaec] rounded text-xs font-medium text-[#4e5969] hover:bg-gray-50 transition-colors">
|
|
238
|
+
返回章節編輯
|
|
239
|
+
</button>
|
|
240
|
+
<div class="flex gap-2">
|
|
241
|
+
<button @click="handleExportPDF" class="px-4 py-1.5 bg-white border border-[#ea3447] text-[#ea3447] rounded text-xs font-medium hover:bg-[#fff5f6] transition-colors">
|
|
242
|
+
匯出為PDF
|
|
243
|
+
</button>
|
|
244
|
+
<button
|
|
245
|
+
@click="handleExportWord"
|
|
246
|
+
:disabled="isExporting"
|
|
247
|
+
class="px-4 py-1.5 bg-white border border-[#ea3447] text-[#ea3447] rounded text-xs font-medium hover:bg-[#fff5f6] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
|
248
|
+
>
|
|
249
|
+
{{ isExporting ? '匯出中...' : '匯出為Word' }}
|
|
250
|
+
</button>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<article id="report-container" class="w-[842px] min-h-[1191px] bg-white shadow-md p-16 relative box-border mx-auto mb-12">
|
|
255
|
+
<div class="no-export absolute top-8 right-12 flex items-center gap-1 cursor-pointer group">
|
|
256
|
+
<span class="i-unocss:edit text-sm text-[#999] group-hover:text-primary"></span>
|
|
257
|
+
</div>
|
|
258
|
+
<h1 class="text-xl font-bold text-center text-[#1a1a1a] mb-12 tracking-wide">
|
|
259
|
+
報告標題:行業風險年報 | 房地產 | 2024
|
|
260
|
+
</h1>
|
|
261
|
+
|
|
262
|
+
<div class="relative group">
|
|
263
|
+
<div class="no-export absolute -left-2 top-0.5 opacity-0 group-hover:opacity-100 transition-opacity flex items-center gap-1 cursor-pointer">
|
|
264
|
+
<span class="i-unocss:edit text-sm text-[#999] hover:text-primary"></span>
|
|
265
|
+
</div>
|
|
266
|
+
<h2 class="text-base font-bold text-[#1a1a1a] mb-4 border-l-4 border-primary pl-2.5">
|
|
267
|
+
正文:
|
|
268
|
+
</h2>
|
|
269
|
+
</div>
|
|
270
|
+
|
|
271
|
+
<div class="text-xs leading-6 text-[#2d3748] text-justify space-y-4 font-normal">
|
|
272
|
+
<p>
|
|
273
|
+
2024年香港房地產市場整體呈現「價跌量穩、租金偏強、商業不振」的分化局面,全年各類物業價格普遍下跌,但成交及租賃需求在政策放寬和人口流入支持下較前兩年有所改善。住宅方面,撤銷所有樓市「辣招」、放寬按揭成數及利率見頂後回落,帶動一手主導的成交回升,但無礙樓價全年再跌約中個位百分比,反映經濟及供應壓力仍然主導價格走勢。<span class="inline-flex items-center justify-center w-3.5 h-3.5 bg-[#e2e8f0] text-[#4a5568] rounded-full text-[10px] scale-90 mx-0.5">1</span>
|
|
274
|
+
</p>
|
|
275
|
+
<p class="font-semibold text-[#1a1a1a]">在住宅市場,本年特點包括:</p>
|
|
276
|
+
<p>
|
|
277
|
+
一、銷售量回升、價格續調:2024年在全面撤辣及按揭寬鬆後,全年住宅買賣宗數按年錄得逾兩成增長,但全年樓價仍錄得約6%至7%的跌幅,延續過去兩年的調整趨勢。<span class="inline-flex items-center justify-center w-3.5 h-3.5 bg-[#e2e8f0] text-[#4a5568] rounded-full text-[10px] scale-90 mx-0.5">2</span>
|
|
278
|
+
</p>
|
|
279
|
+
<p>
|
|
280
|
+
二、供應量顯著增加:私樓落成量約2.4萬個單位,較2023年大幅增加約七成,主要為中小方型單位,為後市價格帶來持續壓力。
|
|
281
|
+
</p>
|
|
282
|
+
<p>
|
|
283
|
+
三、租金走勢優於樓價:在人口及人才計劃帶動下,住宅租金全年錄得中低個位升幅,租金指數跑贏歷史高位約數個百分點,令小型單位的平均回報率升至近年十多年高位水平。<span class="inline-flex items-center justify-center w-3.5 h-3.5 bg-[#e2e8f0] text-[#4a5568] rounded-full text-[10px] scale-90 mx-0.5">3</span>
|
|
284
|
+
</p>
|
|
285
|
+
<p>
|
|
286
|
+
在非住宅方面,2024年為商鋪及鋪位市場的「谷底年」,寫字樓空置率創逾十年新高,商業成交金額及宗數均跌至有紀錄以來低位,而工廈則相對對抗跌但成交同樣收縮。一方面,整體寫字樓空置率升至接近17%,中環空置率突破14%,租金全年續跌,業主需提供更具吸引力條款以鎖定租戶;另一方面,整體商用物業買賣宗數僅約三千多宗,為1996年有紀錄以來最低水平,反映投資情緒謹慎、資金傾向觀望。宏觀層面上,外圍經濟不確定、地緣政治風險及本地結構性供應增加,令2024年香港資產價格整體承受壓,但利率回落預期、人口淨流入及政府發展北部都會區、降低強拍門檻等政策,為中長期物業需求及重建活動提供一定支撐。
|
|
287
|
+
</p>
|
|
288
|
+
</div>
|
|
289
|
+
</article>
|
|
290
|
+
</section>
|
|
291
|
+
|
|
292
|
+
<aside class="w-80 bg-white border-l border-[#e8eaec] flex flex-col shrink-0 overflow-y-auto">
|
|
293
|
+
<section class="p-4 border-b border-[#e8eaec]">
|
|
294
|
+
<div class="flex items-center justify-between mb-3">
|
|
295
|
+
<h3 class="font-bold text-sm text-[#1a1a1a]">選擇章節及版本</h3>
|
|
296
|
+
<div class="flex items-center gap-1 text-xs text-[#ea3447] font-medium cursor-pointer">
|
|
297
|
+
<span class="i-unocss:check-circle"></span> 全選章節
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
|
|
301
|
+
<div class="space-y-2.5">
|
|
302
|
+
<div v-for="item in chapters" :key="item.id" class="flex items-center justify-between text-xs py-0.5">
|
|
303
|
+
<div class="flex items-center gap-2 max-w-[70%]">
|
|
304
|
+
<input type="checkbox" checked class="accent-primary" />
|
|
305
|
+
<span class="truncate text-[#2d3139]">{{ item.title }}</span>
|
|
306
|
+
</div>
|
|
307
|
+
<div class="flex items-center gap-1 border border-[#e8eaec] px-1.5 py-0.5 rounded bg-white cursor-pointer hover:border-gray-400">
|
|
308
|
+
<span class="scale-90 text-[#4e5969]">{{ item.version }}</span>
|
|
309
|
+
<span class="i-unocss:chevron-down text-[10px] text-[#999]"></span>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
</div>
|
|
313
|
+
</section>
|
|
314
|
+
|
|
315
|
+
<section class="p-4 border-b border-[#e8eaec] space-y-3">
|
|
316
|
+
<h3 class="font-bold text-sm text-[#1a1a1a]">生成報告方式</h3>
|
|
317
|
+
<div class="space-y-2 text-xs">
|
|
318
|
+
<label class="flex items-center gap-2 cursor-pointer">
|
|
319
|
+
<input type="radio" value="merge" v-model="generateMethod" class="accent-primary" />
|
|
320
|
+
<span class="text-[#2d3139]">拼裝並潤色</span>
|
|
321
|
+
</label>
|
|
322
|
+
<label class="flex items-center gap-2 cursor-pointer">
|
|
323
|
+
<input type="radio" value="rewrite" v-model="generateMethod" class="accent-primary" />
|
|
324
|
+
<span class="text-[#2d3139]">重寫整篇報告</span>
|
|
325
|
+
</label>
|
|
326
|
+
</div>
|
|
327
|
+
<button @click="handleGenerate" class="w-full py-2 bg-[#ea3447] text-white rounded text-xs font-semibold hover:bg-[#d62f3f] transition-colors mt-2 shadow-sm">
|
|
328
|
+
生成報告
|
|
329
|
+
</button>
|
|
330
|
+
</section>
|
|
331
|
+
|
|
332
|
+
<section class="p-4 flex-1">
|
|
333
|
+
<h3 class="font-bold text-sm text-[#1a1a1a] mb-3">報告歷史</h3>
|
|
334
|
+
<div class="space-y-2">
|
|
335
|
+
<div
|
|
336
|
+
v-for="history in historyList"
|
|
337
|
+
:key="history.id"
|
|
338
|
+
:class="[
|
|
339
|
+
'p-3 rounded-md border text-xs relative group cursor-pointer transition-all',
|
|
340
|
+
history.isActive ? 'bg-[#fff5f6] border-[#fcd4d7]' : 'bg-[#fafafa] border-[#e8eaec] hover:bg-gray-50'
|
|
341
|
+
]"
|
|
342
|
+
>
|
|
343
|
+
<div class="absolute left-0 top-0 bottom-0 w-1 bg-[#ea3447] rounded-l-md" v-if="history.isActive"></div>
|
|
344
|
+
<div class="flex justify-between items-center mb-1">
|
|
345
|
+
<span :class="['font-semibold', history.isActive ? 'text-[#ea3447]' : 'text-[#2d3139]']">
|
|
346
|
+
{{ history.version }}
|
|
347
|
+
</span>
|
|
348
|
+
<span class="i-unocss:more-horizontal text-[#999] opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer"></span>
|
|
349
|
+
</div>
|
|
350
|
+
<div class="text-[#86909c] scale-95 origin-left flex items-center gap-2">
|
|
351
|
+
<span>{{ history.author }}</span>
|
|
352
|
+
<span>{{ history.time }}</span>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
</div>
|
|
356
|
+
</section>
|
|
357
|
+
</aside>
|
|
358
|
+
|
|
359
|
+
</main>
|
|
360
|
+
</div>
|
|
361
|
+
</template>
|
|
362
|
+
|
|
363
|
+
<style>
|
|
364
|
+
/* 统一定制的主题主色调 */
|
|
365
|
+
:root {
|
|
366
|
+
--color-primary: #ea3447;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/* 全局滚动条样式锁死:完美适配 12px 黄金厚度规格 */
|
|
370
|
+
html *::-webkit-scrollbar,
|
|
371
|
+
body *::-webkit-scrollbar,
|
|
372
|
+
div::-webkit-scrollbar {
|
|
373
|
+
width: 12px !important;
|
|
374
|
+
height: 12px !important;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
html *::-webkit-scrollbar-track,
|
|
378
|
+
body *::-webkit-scrollbar-track,
|
|
379
|
+
div::-webkit-scrollbar-track {
|
|
380
|
+
background: #f4f5f7 !important;
|
|
381
|
+
border-radius: 6px !important;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
html *::-webkit-scrollbar-thumb,
|
|
385
|
+
body *::-webkit-scrollbar-thumb,
|
|
386
|
+
div::-webkit-scrollbar-thumb {
|
|
387
|
+
background: #cbd5e1 !important;
|
|
388
|
+
border-radius: 6px !important;
|
|
389
|
+
border: 3px solid #f4f5f7 !important;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
html *::-webkit-scrollbar-thumb:hover,
|
|
393
|
+
body *::-webkit-scrollbar-thumb:hover,
|
|
394
|
+
div::-webkit-scrollbar-thumb:hover {
|
|
395
|
+
background: #94a3b8 !important;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* 兼容 Firefox 降级处理 */
|
|
399
|
+
@supports (scrollbar-width: thin) {
|
|
400
|
+
* {
|
|
401
|
+
scrollbar-width: thin;
|
|
402
|
+
scrollbar-color: #cbd5e1 #f4f5f7;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
</style>
|