koishi-plugin-monetary-bourse 2.0.0-Alpha.9 → 2.0.1

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.
@@ -0,0 +1,379 @@
1
+ <html>
2
+ <head>
3
+ <style>
4
+ :root {
5
+ --bg-color: #0c0f15;
6
+ --card-bg: #151921;
7
+ --item-bg: #1e232e;
8
+ --text-primary: #e1e3e6;
9
+ --text-secondary: #8b919e;
10
+ --border-color: #232730;
11
+ --accent-color: #6366f1;
12
+ --accent-gradient: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
13
+
14
+ /* 盈亏颜色 - 适配深色底 */
15
+ --profit-up: #f87171;
16
+ --profit-down: #4ade80;
17
+ --profit-up-bg: rgba(248, 113, 113, 0.15);
18
+ --profit-down-bg: rgba(74, 222, 128, 0.15);
19
+ }
20
+
21
+ body {
22
+ margin: 0;
23
+ padding: 24px;
24
+ font-family: 'Roboto Mono', 'Trebuchet MS', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
25
+ background-color: var(--bg-color);
26
+ width: 480px;
27
+ box-sizing: border-box;
28
+ color: var(--text-primary);
29
+ }
30
+
31
+ .card {
32
+ background-color: var(--card-bg);
33
+ padding: 32px;
34
+ border-radius: 24px;
35
+ box-shadow: 0 24px 48px rgba(0,0,0,0.5), inset 0 1px 1px rgba(255,255,255,0.05);
36
+ border: 1px solid var(--border-color);
37
+ }
38
+
39
+ /* Header */
40
+ .header {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: 16px;
44
+ margin-bottom: 32px;
45
+ padding-bottom: 20px;
46
+ border-bottom: 1px solid var(--border-color);
47
+ }
48
+ .avatar {
49
+ width: 56px;
50
+ height: 56px;
51
+ background: var(--accent-gradient);
52
+ border-radius: 16px;
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: center;
56
+ color: white;
57
+ font-size: 24px;
58
+ font-weight: 700;
59
+ box-shadow: 0 8px 16px rgba(99, 102, 241, 0.3);
60
+ }
61
+ .user-info { flex: 1; }
62
+ .username {
63
+ font-size: 20px;
64
+ font-weight: 700;
65
+ color: var(--text-primary);
66
+ margin-bottom: 4px;
67
+ }
68
+ .account-label {
69
+ font-size: 13px;
70
+ color: var(--text-secondary);
71
+ font-weight: 500;
72
+ display: flex;
73
+ align-items: center;
74
+ gap: 6px;
75
+ }
76
+ .account-label::before {
77
+ content: '';
78
+ display: block;
79
+ width: 6px;
80
+ height: 6px;
81
+ background-color: #22c55e;
82
+ border-radius: 50%;
83
+ box-shadow: 0 0 8px #22c55e;
84
+ }
85
+
86
+ /* Sections */
87
+ .section { margin-bottom: 28px; }
88
+ .section:last-child { margin-bottom: 0; }
89
+
90
+ .section-title {
91
+ font-size: 12px;
92
+ font-weight: 600;
93
+ color: var(--text-secondary);
94
+ margin-bottom: 16px;
95
+ text-transform: uppercase;
96
+ letter-spacing: 1px;
97
+ display: flex;
98
+ align-items: center;
99
+ gap: 8px;
100
+ }
101
+ .section-title::after {
102
+ content: '';
103
+ flex: 1;
104
+ height: 1px;
105
+ background: var(--border-color);
106
+ opacity: 0.5;
107
+ }
108
+
109
+ /* Stock Card */
110
+ .stock-card {
111
+ background-color: var(--item-bg);
112
+ border-radius: 16px;
113
+ overflow: hidden;
114
+ border: 1px solid var(--border-color);
115
+ }
116
+ .stock-header {
117
+ display: flex;
118
+ justify-content: space-between;
119
+ align-items: center;
120
+ padding: 20px 24px;
121
+ background: rgba(255,255,255,0.02);
122
+ border-bottom: 1px solid var(--border-color);
123
+ }
124
+ .stock-name {
125
+ font-size: 18px;
126
+ font-weight: 700;
127
+ color: var(--text-primary);
128
+ display: flex;
129
+ align-items: center;
130
+ gap: 8px;
131
+ letter-spacing: -0.2px;
132
+ }
133
+ .stock-amount {
134
+ font-size: 13px;
135
+ font-weight: 600;
136
+ background: rgba(255,255,255,0.1);
137
+ color: var(--text-primary);
138
+ padding: 4px 10px;
139
+ border-radius: 6px;
140
+ font-family: 'Roboto Mono', 'Trebuchet MS', monospace;
141
+ }
142
+
143
+ .stock-body { padding: 24px; }
144
+
145
+ .stat-grid {
146
+ display: grid;
147
+ grid-template-columns: 1fr 1fr;
148
+ gap: 20px;
149
+ }
150
+ .stat-item { display: flex; flex-direction: column; gap: 4px; }
151
+ .stat-label { font-size: 12px; color: var(--text-secondary); }
152
+ .stat-value {
153
+ font-size: 18px;
154
+ font-weight: 600;
155
+ color: var(--text-primary);
156
+ font-family: 'Roboto Mono', 'Trebuchet MS', monospace;
157
+ letter-spacing: -0.3px;
158
+ }
159
+ .stat-value.highlight { color: var(--accent-color); }
160
+
161
+ /* Profit Section */
162
+ .profit-section {
163
+ display: flex;
164
+ justify-content: space-between;
165
+ align-items: center;
166
+ padding: 16px 24px;
167
+ border-top: 1px solid var(--border-color);
168
+ }
169
+ .profit-label { font-size: 13px; font-weight: 600; color: var(--text-secondary); }
170
+ .profit-value { font-size: 18px; font-weight: 700; font-family: 'Roboto Mono', monospace; }
171
+ .profit-percent { font-size: 13px; font-weight: 600; margin-left: 8px; opacity: 0.9; }
172
+ .profit-hint { font-size: 12px; font-weight: 400; display: block; margin-top: 4px; opacity: 0.7; }
173
+
174
+ /* Empty State */
175
+ .empty-state {
176
+ background: var(--item-bg);
177
+ border-radius: 16px;
178
+ padding: 40px 20px;
179
+ text-align: center;
180
+ border: 1px dashed var(--border-color);
181
+ }
182
+ .empty-icon { font-size: 32px; margin-bottom: 12px; opacity: 0.5; }
183
+ .empty-text { font-size: 14px; color: var(--text-secondary); }
184
+
185
+ /* Pending Items */
186
+ .pending-list { display: flex; flex-direction: column; gap: 12px; }
187
+ .pending-item {
188
+ display: flex;
189
+ justify-content: space-between;
190
+ align-items: center;
191
+ background: var(--item-bg);
192
+ border-radius: 12px;
193
+ padding: 16px;
194
+ border: 1px solid var(--border-color);
195
+ position: relative;
196
+ overflow: hidden;
197
+ }
198
+ .pending-item::before {
199
+ content: '';
200
+ position: absolute;
201
+ left: 0; top: 0; bottom: 0;
202
+ width: 4px;
203
+ }
204
+ .pending-item.buy::before { background-color: var(--profit-up); }
205
+ .pending-item.sell::before { background-color: var(--profit-down); }
206
+
207
+ .pending-left { display: flex; align-items: center; gap: 12px; }
208
+ .pending-type {
209
+ font-size: 11px;
210
+ font-weight: 700;
211
+ padding: 2px 6px;
212
+ border-radius: 4px;
213
+ text-transform: uppercase;
214
+ }
215
+ .pending-type.buy { background: var(--profit-up-bg); color: var(--profit-up); }
216
+ .pending-type.sell { background: var(--profit-down-bg); color: var(--profit-down); }
217
+
218
+ .pending-amount { font-size: 14px; font-weight: 600; color: var(--text-primary); }
219
+
220
+ .pending-center { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; margin-left: auto; margin-right: 16px; }
221
+ .pending-price { font-size: 12px; color: var(--text-secondary); }
222
+ .pending-cost { font-size: 11px; color: var(--text-secondary); opacity: 0.7; }
223
+
224
+ .pending-right { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #eab308; font-weight: 600; }
225
+
226
+ /* Footer */
227
+ .footer {
228
+ margin-top: 32px;
229
+ padding-top: 16px;
230
+ border-top: 1px solid var(--border-color);
231
+ text-align: center;
232
+ font-size: 11px;
233
+ color: var(--text-secondary);
234
+ opacity: 0.6;
235
+ }
236
+ </style>
237
+ </head>
238
+ <body>
239
+ <div class="card">
240
+ <div class="header">
241
+ <div class="avatar" id="avatar"></div>
242
+ <div class="user-info">
243
+ <div class="username" id="username"></div>
244
+ <div class="account-label">股票账户</div>
245
+ </div>
246
+ </div>
247
+ <div id="holding-container"></div>
248
+ <div id="pending-container"></div>
249
+ <div class="footer" id="footer"></div>
250
+ </div>
251
+
252
+ <script type="application/json" id="data-source">
253
+ {{DATA}}
254
+ </script>
255
+ <script>
256
+ // 从 JSON 标签中读取数据
257
+ const DATA = JSON.parse(document.getElementById('data-source').textContent);
258
+
259
+ // 统一字体:数字和金额统一使用与其他页面一致的等宽字体
260
+ const monoTargets = document.querySelectorAll('.stat-value, .profit-value, .pending-amount, .pending-price, .pending-cost, .pending-type, .stock-amount')
261
+ monoTargets.forEach(el => {
262
+ el.style.fontFamily = "'Roboto Mono','Trebuchet MS','Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif"
263
+ el.style.letterSpacing = '-0.2px'
264
+ })
265
+
266
+ // 渲染用户信息
267
+ document.getElementById('avatar').textContent = DATA.username.charAt(0).toUpperCase();
268
+ document.getElementById('username').textContent = DATA.username;
269
+ document.getElementById('footer').textContent = `数据更新于 ${DATA.updateTime}`;
270
+
271
+ // 渲染持仓信息
272
+ const holdingContainer = document.getElementById('holding-container');
273
+ if (DATA.holding) {
274
+ const h = DATA.holding;
275
+ const hasCostData = h.totalCost !== null;
276
+ const isProfit = hasCostData ? h.profit >= 0 : true;
277
+
278
+ // 适配深色模式的颜色
279
+ const profitColor = isProfit ? '#f87171' : '#4ade80';
280
+ const profitSign = isProfit ? '+' : '';
281
+ const profitBgColor = isProfit ? 'rgba(248, 113, 113, 0.1)' : 'rgba(74, 222, 128, 0.1)';
282
+
283
+ const profitSection = hasCostData ? `
284
+ <div class="profit-section" style="background: ${profitBgColor}">
285
+ <div class="profit-label">盈亏</div>
286
+ <div class="profit-value" style="color: ${profitColor}">
287
+ ${profitSign}${h.profit.toFixed(2)} ${DATA.currency}
288
+ <span class="profit-percent">(${profitSign}${h.profitPercent.toFixed(2)}%)</span>
289
+ </div>
290
+ </div>
291
+ ` : `
292
+ <div class="profit-section no-data" style="background: rgba(255, 255, 255, 0.03)">
293
+ <div class="profit-label">盈亏</div>
294
+ <div class="profit-value" style="color: #8b919e">
295
+ 暂无成本记录
296
+ <span class="profit-hint">(新交易后将自动记录)</span>
297
+ </div>
298
+ </div>
299
+ `;
300
+
301
+ holdingContainer.innerHTML = `
302
+ <div class="section">
303
+ <div class="section-title">持仓详情 Holding</div>
304
+ <div class="stock-card">
305
+ <div class="stock-header">
306
+ <div class="stock-name">
307
+ <span>⚡</span>
308
+ ${h.stockName}
309
+ </div>
310
+ <div class="stock-amount">${h.amount} 股</div>
311
+ </div>
312
+ <div class="stock-body">
313
+ <div class="stat-grid">
314
+ <div class="stat-item">
315
+ <div class="stat-label">现价 Current</div>
316
+ <div class="stat-value">${h.currentPrice.toFixed(2)}</div>
317
+ </div>
318
+ <div class="stat-item">
319
+ <div class="stat-label">成本价 Cost</div>
320
+ <div class="stat-value">${hasCostData ? h.avgCost.toFixed(2) : '--'}</div>
321
+ </div>
322
+ <div class="stat-item">
323
+ <div class="stat-label">持仓成本 Total Cost</div>
324
+ <div class="stat-value">${hasCostData ? h.totalCost.toFixed(2) : '--'}</div>
325
+ </div>
326
+ <div class="stat-item">
327
+ <div class="stat-label">市值 Market Value</div>
328
+ <div class="stat-value highlight">${h.marketValue.toFixed(2)}</div>
329
+ </div>
330
+ </div>
331
+ </div>
332
+ ${profitSection}
333
+ </div>
334
+ </div>
335
+ `;
336
+ } else {
337
+ holdingContainer.innerHTML = `
338
+ <div class="section">
339
+ <div class="section-title">持仓详情 Holding</div>
340
+ <div class="empty-state">
341
+ <div class="empty-icon">📭</div>
342
+ <div class="empty-text">暂无持仓</div>
343
+ </div>
344
+ </div>
345
+ `;
346
+ }
347
+
348
+ // 渲染待处理交易
349
+ const pendingContainer = document.getElementById('pending-container');
350
+ if (DATA.pending && DATA.pending.length > 0) {
351
+ const pendingItems = DATA.pending.map(p => `
352
+ <div class="pending-item ${p.typeClass}">
353
+ <div class="pending-left">
354
+ <span class="pending-type ${p.typeClass}">${p.type}</span>
355
+ <span class="pending-amount">${p.amount} 股</span>
356
+ </div>
357
+ <div class="pending-center">
358
+ <span class="pending-price">@ ${p.price.toFixed(2)}</span>
359
+ <span class="pending-cost">总 ${p.cost.toFixed(2)}</span>
360
+ </div>
361
+ <div class="pending-right">
362
+ <span>⏱</span>
363
+ <span>${p.timeLeft}</span>
364
+ </div>
365
+ </div>
366
+ `).join('');
367
+
368
+ pendingContainer.innerHTML = `
369
+ <div class="section">
370
+ <div class="section-title">进行中的交易 Pending</div>
371
+ <div class="pending-list">
372
+ ${pendingItems}
373
+ </div>
374
+ </div>
375
+ `;
376
+ }
377
+ </script>
378
+ </body>
379
+ </html>
@@ -23,7 +23,7 @@
23
23
  body {
24
24
  padding: 32px;
25
25
  /* 字体栈优化:优先使用现代系统字体 */
26
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif;
26
+ font-family: 'Roboto Mono', 'Trebuchet MS', 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif;
27
27
  background-color: var(--bg-color);
28
28
 
29
29
  /* 强制 4:3 比例 (1024x768) */
@@ -105,7 +105,7 @@
105
105
  }
106
106
 
107
107
  .current-price {
108
- font-family: 'Trebuchet MS', monospace;
108
+ font-family: 'Roboto Mono', 'Trebuchet MS', monospace;
109
109
  font-size: 64px;
110
110
  font-weight: normal;
111
111
  color: var(--main-color);