lfqian commited on
Commit
dda1ac1
·
1 Parent(s): 860b026

Fix MiniEchart: move to standalone Vue component for proper template compilation

Browse files
src/components/MiniEchart.vue ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <template>
2
+ <div ref="chartContainer" class="echart-mini"></div>
3
+ </template>
4
+
5
+ <script>
6
+ import * as echarts from 'echarts/core'
7
+ import { LineChart } from 'echarts/charts'
8
+ import { GridComponent, TooltipComponent } from 'echarts/components'
9
+ import { CanvasRenderer } from 'echarts/renderers'
10
+ import { nextTick } from 'vue'
11
+
12
+ echarts.use([LineChart, GridComponent, TooltipComponent, CanvasRenderer])
13
+
14
+ export default {
15
+ name: 'MiniEchart',
16
+ props: {
17
+ data: { type: Array, default: () => [] },
18
+ color: { type: String, default: '#22c55e' }
19
+ },
20
+ data() {
21
+ return {
22
+ chart: null,
23
+ resizeObserver: null
24
+ }
25
+ },
26
+ mounted() {
27
+ console.log('[MiniEchart] Mounted with data:', this.data?.length || 0, 'items')
28
+ nextTick(() => this.initChart())
29
+ },
30
+ beforeUnmount() {
31
+ if (this.resizeObserver) {
32
+ this.resizeObserver.disconnect()
33
+ this.resizeObserver = null
34
+ }
35
+ if (this.chart) {
36
+ this.chart.dispose()
37
+ this.chart = null
38
+ }
39
+ },
40
+ watch: {
41
+ data(newVal) {
42
+ if (this.chart && Array.isArray(newVal)) {
43
+ this.updateChart(newVal)
44
+ }
45
+ }
46
+ },
47
+ methods: {
48
+ initChart() {
49
+ const el = this.$refs.chartContainer
50
+ console.log('[MiniEchart] initChart - el:', el)
51
+
52
+ if (!el) {
53
+ console.log('[MiniEchart] No element found')
54
+ return
55
+ }
56
+
57
+ const { clientWidth: w, clientHeight: h } = el
58
+ console.log('[MiniEchart] Element size:', w, 'x', h)
59
+
60
+ if (!w || !h) {
61
+ console.log('[MiniEchart] Size is 0, will retry on next tick')
62
+ setTimeout(() => this.initChart(), 100)
63
+ return
64
+ }
65
+
66
+ console.log('[MiniEchart] Initializing ECharts...')
67
+ this.chart = echarts.init(el, null, { renderer: 'canvas' })
68
+ console.log('[MiniEchart] Chart initialized, rendering data:', this.data?.length || 0)
69
+
70
+ this.renderChart(this.data)
71
+
72
+ // Listen for container resize
73
+ this.resizeObserver = new ResizeObserver(() => {
74
+ if (this.chart) {
75
+ this.chart.resize()
76
+ }
77
+ })
78
+ this.resizeObserver.observe(el)
79
+ },
80
+ renderChart(arr) {
81
+ if (!this.chart) return
82
+
83
+ const d = Array.isArray(arr) ? arr : []
84
+ console.log('[MiniEchart] Rendering chart with', d.length, 'data points')
85
+
86
+ this.chart.setOption({
87
+ animation: true,
88
+ grid: { left: 0, right: 0, top: 0, bottom: 0 },
89
+ xAxis: {
90
+ type: 'category',
91
+ show: false,
92
+ boundaryGap: false,
93
+ data: d.map((_, i) => i)
94
+ },
95
+ yAxis: {
96
+ type: 'value',
97
+ show: false,
98
+ scale: true
99
+ },
100
+ tooltip: { show: false },
101
+ color: [this.color || '#22c55e'],
102
+ series: [{
103
+ type: 'line',
104
+ data: d,
105
+ showSymbol: false,
106
+ smooth: 0.35,
107
+ lineStyle: { width: 2 },
108
+ areaStyle: { opacity: 0.15 }
109
+ }]
110
+ })
111
+ },
112
+ updateChart(newData) {
113
+ if (!this.chart) return
114
+
115
+ const d = Array.isArray(newData) ? newData : []
116
+ this.chart.setOption({
117
+ xAxis: { data: d.map((_, i) => i) },
118
+ series: [{ data: d }]
119
+ })
120
+ }
121
+ }
122
+ }
123
+ </script>
124
+
125
+ <style scoped>
126
+ .echart-mini {
127
+ width: 100%;
128
+ height: 100%;
129
+ }
130
+ </style>
131
+
src/views/RequestView.vue CHANGED
@@ -158,96 +158,7 @@ import { getAllDecisions } from '../lib/dataCache'
158
  import { readAllRawDecisions } from '../lib/idb'
159
  import { filterRowsToNyseTradingDays } from '../lib/marketCalendar'
160
  import { computeBuyHoldEquity } from '../lib/perf'
161
-
162
- /* ---- ECharts (LineChart) ---- */
163
- import * as echarts from 'echarts/core'
164
- import { LineChart } from 'echarts/charts'
165
- import { GridComponent, TooltipComponent } from 'echarts/components'
166
- import { CanvasRenderer } from 'echarts/renderers'
167
- import { nextTick } from 'vue'
168
- echarts.use([LineChart, GridComponent, TooltipComponent, CanvasRenderer])
169
-
170
- /**
171
- * Robust ECharts mini line spark that waits for layout
172
- */
173
- const MiniEchart = {
174
- name: 'MiniEchart',
175
- props: {
176
- data: { type: Array, default: () => [] },
177
- color: { type: String, default: '#22c55e' }
178
- },
179
- data() {
180
- return { _chart: null, _ro: null, _raf: 0 }
181
- },
182
- mounted() {
183
- console.log('[MiniEchart] Mounted with data:', this.data?.length || 0, 'items')
184
- nextTick(() => this.initChartSafely())
185
- },
186
- beforeUnmount() {
187
- if (this._ro) { this._ro.disconnect(); this._ro = null }
188
- if (this._raf) { cancelAnimationFrame(this._raf); this._raf = 0 }
189
- if (this._chart) { this._chart.dispose(); this._chart = null }
190
- },
191
- methods: {
192
- initChartSafely() {
193
- const el = this.$refs.c || this.$el
194
- console.log('[MiniEchart] initChartSafely - el:', el)
195
- if (!el) {
196
- console.log('[MiniEchart] No element, retrying...')
197
- this._raf = requestAnimationFrame(() => this.initChartSafely())
198
- return
199
- }
200
- const { clientWidth: w, clientHeight: h } = el
201
- console.log('[MiniEchart] Element size:', w, 'x', h)
202
- if (!w || !h) {
203
- console.log('[MiniEchart] Size is 0, retrying...')
204
- this._raf = requestAnimationFrame(() => this.initChartSafely())
205
- return
206
- }
207
- console.log('[MiniEchart] Initializing ECharts...')
208
- this._chart = echarts.init(el, null, { renderer: 'canvas' })
209
- console.log('[MiniEchart] Chart initialized, rendering data:', this.data?.length || 0)
210
- this.render(this.data)
211
-
212
- // Listen for container resize
213
- this._ro = new ResizeObserver(() => {
214
- if (this._chart) this._chart.resize()
215
- })
216
- this._ro.observe(el)
217
- },
218
- render(arr) {
219
- if (!this._chart) return
220
- const d = Array.isArray(arr) ? arr : []
221
- this._chart.setOption({
222
- animation: true,
223
- grid: { left: 0, right: 0, top: 0, bottom: 0 },
224
- xAxis: { type: 'category', show: false, boundaryGap: false, data: d.map((_, i) => i) },
225
- yAxis: { type: 'value', show: false, scale: true },
226
- tooltip: { show: false },
227
- color: [this.color || '#22c55e'],
228
- series: [{
229
- type: 'line',
230
- data: d,
231
- showSymbol: false,
232
- smooth: 0.35,
233
- lineStyle: { width: 2 },
234
- areaStyle: { opacity: 0.15 }
235
- }]
236
- })
237
- }
238
- },
239
- watch: {
240
- data(newVal) {
241
- if (!this._chart) return
242
- const d = Array.isArray(newVal) ? newVal : []
243
- this._chart.setOption({
244
- xAxis: { data: d.map((_, i) => i) },
245
- series: [{ data: d }]
246
- })
247
- }
248
- },
249
- template: `<div ref="c" class="echart-mini"></div>`
250
- }
251
 
252
  export default {
253
  name: 'RequestView',
@@ -264,7 +175,7 @@ export default {
264
  agents: [
265
  {
266
  name: 'InvestorAgent',
267
- github: '#',
268
  arxiv: 'https://arxiv.org/abs/2412.18174',
269
  strategy: 'Aggressive Long Only',
270
  focus: 'BTC, MSFT',
@@ -447,7 +358,6 @@ export default {
447
  .truncate{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
448
  .clamp-2{ display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
449
  .w-full{ width:100%; }
450
- .echart-mini{ width:100%; height:100%; }
451
 
452
  /* ===== Sections ===== */
453
  .section{ margin-top:18px; }
 
158
  import { readAllRawDecisions } from '../lib/idb'
159
  import { filterRowsToNyseTradingDays } from '../lib/marketCalendar'
160
  import { computeBuyHoldEquity } from '../lib/perf'
161
+ import MiniEchart from '../components/MiniEchart.vue'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
  export default {
164
  name: 'RequestView',
 
175
  agents: [
176
  {
177
  name: 'InvestorAgent',
178
+ github: 'https://github.com/felis33/INVESTOR-BENCH',
179
  arxiv: 'https://arxiv.org/abs/2412.18174',
180
  strategy: 'Aggressive Long Only',
181
  focus: 'BTC, MSFT',
 
358
  .truncate{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
359
  .clamp-2{ display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
360
  .w-full{ width:100%; }
 
361
 
362
  /* ===== Sections ===== */
363
  .section{ margin-top:18px; }