@aidget-community/gold-price 0.0.0-stage → 0.1.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/agents.md +25 -0
- package/assets/screenshot.png +0 -0
- package/config.json +11 -0
- package/index.html +177 -0
- package/package.json +23 -4
- package/style.css +176 -0
- package/README.md +0 -3
package/agents.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 黄金价格卡片
|
|
2
|
+
|
|
3
|
+
## 用途
|
|
4
|
+
|
|
5
|
+
展示上海黄金交易所黄金 9999(AU99.99)的最新价、日内涨跌幅和日内走势。数据来自东方财富公开行情接口,不代表交易所官方直连。
|
|
6
|
+
|
|
7
|
+
## 区域与布局
|
|
8
|
+
|
|
9
|
+
- `quote`:品类标签、涨跌幅和大号最新价。涨跌幅按昨收计算,上涨显示正号,下跌显示负号;文字始终保持白色。
|
|
10
|
+
- `chart`:原生 SVG 日内面积图。金色折线表示收盘价走势,金色虚线表示昨收,右下圆点表示最新位置。
|
|
11
|
+
- 窗口固定为 180×180,外边距约 12px;内容卡片使用深海军蓝背景和金色强调色。窗口位置与尺寸归用户控制,内容更新不得移动窗口。
|
|
12
|
+
|
|
13
|
+
## 数据与刷新
|
|
14
|
+
|
|
15
|
+
- 数据源:`https://push2.eastmoney.com/api/qt/stock/trends2/get`,`secid=118.AU9999`。
|
|
16
|
+
- `data.preClose` 为昨收,`data.trends` 每行逗号分隔字段中的第三项为收盘价;最后价格与昨收计算涨跌幅,价格精度使用 `data.decimal`。
|
|
17
|
+
- 页面加载后立即获取一次行情,之后每 5 分钟使用单一定时器刷新,禁止重叠请求。
|
|
18
|
+
- 请求或字段校验失败时,价格和涨跌幅显示 `--`,涨跌幅位置显示“行情加载失败”,清空图表并等待下一周期重试;不得缓存旧行情、伪造数据或切换备用源。
|
|
19
|
+
- 首次渲染或错误状态完成后调用 `window.aidget.ready()`。
|
|
20
|
+
|
|
21
|
+
## 权限与资源
|
|
22
|
+
|
|
23
|
+
- 仅启用 `script` 权限,网络白名单仅允许 `https://push2.eastmoney.com`。
|
|
24
|
+
- 不启用 `storage` 或 `location`。
|
|
25
|
+
- 不加载远程脚本、字体、图片或第三方图表库;视觉资源全部由本地 HTML、CSS 和 SVG 生成。
|
|
Binary file
|
package/config.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "gold-price",
|
|
3
|
+
"title": "黄金价格",
|
|
4
|
+
"logo": null,
|
|
5
|
+
"screenshots": ["assets/screenshot.png"],
|
|
6
|
+
"platforms": ["macos", "windows", "linux"],
|
|
7
|
+
"size": { "width": 180, "height": 180 },
|
|
8
|
+
"dragMode": "all",
|
|
9
|
+
"permissions": ["script"],
|
|
10
|
+
"network": ["https://push2.eastmoney.com"]
|
|
11
|
+
}
|
package/index.html
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<meta name="aidget-surface" content="none" />
|
|
7
|
+
<title>黄金价格</title>
|
|
8
|
+
<link rel="stylesheet" href="style.css" />
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<main class="gold-card" aria-label="黄金价格 AU99.99">
|
|
12
|
+
<h1 class="gold-title">黄金价格</h1>
|
|
13
|
+
|
|
14
|
+
<section class="gold-quote" data-aidget-region="quote" aria-live="polite" aria-busy="true">
|
|
15
|
+
<div class="quote-meta">
|
|
16
|
+
<span class="symbol-pill">AU99.99</span>
|
|
17
|
+
<span id="change" class="change">--</span>
|
|
18
|
+
</div>
|
|
19
|
+
<div id="price" class="price">--</div>
|
|
20
|
+
</section>
|
|
21
|
+
|
|
22
|
+
<div id="chart" class="chart" data-aidget-region="chart" aria-hidden="true">
|
|
23
|
+
<svg
|
|
24
|
+
class="chart-svg"
|
|
25
|
+
viewBox="0 0 128 42"
|
|
26
|
+
preserveAspectRatio="none"
|
|
27
|
+
role="img"
|
|
28
|
+
aria-label="AU99.99 日内走势"
|
|
29
|
+
>
|
|
30
|
+
<defs>
|
|
31
|
+
<linearGradient id="chart-fill" x1="0" y1="0" x2="0" y2="1">
|
|
32
|
+
<stop offset="0%" stop-color="#d8a52f" stop-opacity="0.88"></stop>
|
|
33
|
+
<stop offset="100%" stop-color="#8d6e27" stop-opacity="0.76"></stop>
|
|
34
|
+
</linearGradient>
|
|
35
|
+
</defs>
|
|
36
|
+
<line id="baseline" class="baseline" x1="0" y1="24" x2="128" y2="24"></line>
|
|
37
|
+
<path id="area" class="area" d=""></path>
|
|
38
|
+
<path id="line" class="line" d=""></path>
|
|
39
|
+
<circle id="dot" class="dot" cx="0" cy="0" r="1.8" hidden></circle>
|
|
40
|
+
</svg>
|
|
41
|
+
</div>
|
|
42
|
+
</main>
|
|
43
|
+
|
|
44
|
+
<script>
|
|
45
|
+
const API_URL = new URL('https://push2.eastmoney.com/api/qt/stock/trends2/get');
|
|
46
|
+
API_URL.search = new URLSearchParams({
|
|
47
|
+
secid: '118.AU9999',
|
|
48
|
+
fields1: 'f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13',
|
|
49
|
+
fields2: 'f51,f52,f53,f54,f55,f56,f57,f58',
|
|
50
|
+
ndays: '1',
|
|
51
|
+
iscr: '0',
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const REFRESH_MS = 5 * 60 * 1000;
|
|
55
|
+
const quote = document.querySelector('.gold-quote');
|
|
56
|
+
const price = document.querySelector('#price');
|
|
57
|
+
const change = document.querySelector('#change');
|
|
58
|
+
const baseline = document.querySelector('#baseline');
|
|
59
|
+
const area = document.querySelector('#area');
|
|
60
|
+
const line = document.querySelector('#line');
|
|
61
|
+
const dot = document.querySelector('#dot');
|
|
62
|
+
const chart = document.querySelector('#chart');
|
|
63
|
+
|
|
64
|
+
let refreshTimer = 0;
|
|
65
|
+
let loading = false;
|
|
66
|
+
let initialized = false;
|
|
67
|
+
|
|
68
|
+
function drawChart(closes, previousClose, percentage) {
|
|
69
|
+
const width = 128;
|
|
70
|
+
const height = 42;
|
|
71
|
+
const inset = 3;
|
|
72
|
+
const values = [...closes, previousClose];
|
|
73
|
+
const min = Math.min(...values);
|
|
74
|
+
const max = Math.max(...values);
|
|
75
|
+
const range = max - min || 1;
|
|
76
|
+
const x = (index) => (index / (closes.length - 1)) * width;
|
|
77
|
+
const y = (value) => inset + ((max - value) / range) * (height - inset * 2);
|
|
78
|
+
const points = closes.map(
|
|
79
|
+
(value, index) => `${x(index).toFixed(2)},${y(value).toFixed(2)}`,
|
|
80
|
+
);
|
|
81
|
+
const previousY = y(previousClose).toFixed(2);
|
|
82
|
+
const last = points[points.length - 1].split(',');
|
|
83
|
+
|
|
84
|
+
baseline.setAttribute('y1', previousY);
|
|
85
|
+
baseline.setAttribute('y2', previousY);
|
|
86
|
+
area.setAttribute('d', `M0,${height} L${points.join(' L')} L${width},${height} Z`);
|
|
87
|
+
line.setAttribute('d', `M${points.join(' L')}`);
|
|
88
|
+
dot.setAttribute('cx', last[0]);
|
|
89
|
+
dot.setAttribute('cy', last[1]);
|
|
90
|
+
dot.removeAttribute('hidden');
|
|
91
|
+
chart.setAttribute(
|
|
92
|
+
'aria-label',
|
|
93
|
+
`AU99.99 日内走势,涨跌幅 ${percentage > 0 ? '+' : ''}${percentage.toFixed(2)}%`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function clearChart() {
|
|
98
|
+
baseline.removeAttribute('y1');
|
|
99
|
+
baseline.removeAttribute('y2');
|
|
100
|
+
area.setAttribute('d', '');
|
|
101
|
+
line.setAttribute('d', '');
|
|
102
|
+
dot.setAttribute('hidden', '');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function renderQuote(data) {
|
|
106
|
+
const rows = data?.trends;
|
|
107
|
+
const previousClose = Number(data?.preClose);
|
|
108
|
+
const decimals = Number.isInteger(data?.decimal) ? data.decimal : 2;
|
|
109
|
+
|
|
110
|
+
if (!Array.isArray(rows) || rows.length === 0) {
|
|
111
|
+
throw new Error('行情缺少日内数据');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const closes = rows
|
|
115
|
+
.map((row) => Number(String(row).split(',')[2]))
|
|
116
|
+
.filter((value) => Number.isFinite(value) && value > 0);
|
|
117
|
+
const latest = closes[closes.length - 1];
|
|
118
|
+
|
|
119
|
+
if (
|
|
120
|
+
closes.length < 2 ||
|
|
121
|
+
!Number.isFinite(previousClose) ||
|
|
122
|
+
previousClose <= 0 ||
|
|
123
|
+
!Number.isFinite(latest)
|
|
124
|
+
) {
|
|
125
|
+
throw new Error('行情字段不完整');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let percentage = ((latest - previousClose) / previousClose) * 100;
|
|
129
|
+
if (Math.abs(percentage) < 0.005) percentage = 0;
|
|
130
|
+
|
|
131
|
+
price.textContent = new Intl.NumberFormat('zh-CN', {
|
|
132
|
+
useGrouping: false,
|
|
133
|
+
minimumFractionDigits: decimals,
|
|
134
|
+
maximumFractionDigits: decimals,
|
|
135
|
+
}).format(latest);
|
|
136
|
+
change.textContent = `${percentage > 0 ? '+' : ''}${percentage.toFixed(2)}%`;
|
|
137
|
+
quote.dataset.direction = percentage > 0 ? 'up' : percentage < 0 ? 'down' : 'flat';
|
|
138
|
+
quote.setAttribute('aria-busy', 'false');
|
|
139
|
+
drawChart(closes, previousClose, percentage);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function renderError() {
|
|
143
|
+
price.textContent = '--';
|
|
144
|
+
change.textContent = '行情加载失败';
|
|
145
|
+
quote.dataset.direction = 'error';
|
|
146
|
+
quote.setAttribute('aria-busy', 'false');
|
|
147
|
+
clearChart();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function refresh() {
|
|
151
|
+
if (loading) return;
|
|
152
|
+
loading = true;
|
|
153
|
+
window.clearTimeout(refreshTimer);
|
|
154
|
+
quote.setAttribute('aria-busy', 'true');
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const payload = await window.aidget.fetch(API_URL.toString());
|
|
158
|
+
if (payload.rc !== 0 || !payload.data) {
|
|
159
|
+
throw new Error('行情返回为空');
|
|
160
|
+
}
|
|
161
|
+
renderQuote(payload.data);
|
|
162
|
+
} catch {
|
|
163
|
+
renderError();
|
|
164
|
+
} finally {
|
|
165
|
+
loading = false;
|
|
166
|
+
if (!initialized) {
|
|
167
|
+
initialized = true;
|
|
168
|
+
window.aidget.ready();
|
|
169
|
+
}
|
|
170
|
+
refreshTimer = window.setTimeout(refresh, REFRESH_MS);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
refresh();
|
|
175
|
+
</script>
|
|
176
|
+
</body>
|
|
177
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aidget-community/gold-price",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AU99.99 黄金实时价格、涨跌幅与日内走势卡片。",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "micooz",
|
|
8
|
+
"url": "https://github.com/micooz"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/aidget-ai/widgets.git",
|
|
13
|
+
"directory": "packages/gold-price"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"config.json",
|
|
17
|
+
"index.html",
|
|
18
|
+
"style.css",
|
|
19
|
+
"agents.md",
|
|
20
|
+
"assets"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/style.css
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: dark;
|
|
3
|
+
--card: #001529;
|
|
4
|
+
--gold: #d8a52f;
|
|
5
|
+
--gold-deep: #4a391d;
|
|
6
|
+
--text: #f7f8fa;
|
|
7
|
+
--muted: #9ca4ad;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
* {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
html,
|
|
15
|
+
body {
|
|
16
|
+
width: 100%;
|
|
17
|
+
height: 100%;
|
|
18
|
+
margin: 0;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
background: transparent;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
body {
|
|
24
|
+
padding: 12px;
|
|
25
|
+
font-family:
|
|
26
|
+
'Avenir Next', 'SF Pro Display', 'PingFang SC', 'Hiragino Sans GB', 'Segoe UI Variable',
|
|
27
|
+
'Microsoft YaHei UI', 'Noto Sans CJK SC', sans-serif;
|
|
28
|
+
-webkit-font-smoothing: antialiased;
|
|
29
|
+
text-rendering: geometricPrecision;
|
|
30
|
+
user-select: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.gold-card {
|
|
34
|
+
position: relative;
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
width: 100%;
|
|
38
|
+
height: 100%;
|
|
39
|
+
padding: 12px 14px 7px;
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
border: 1px solid rgba(70, 91, 111, 0.42);
|
|
42
|
+
border-radius: 27px;
|
|
43
|
+
background:
|
|
44
|
+
radial-gradient(circle at 90% 8%, rgba(20, 51, 74, 0.34), transparent 38%),
|
|
45
|
+
linear-gradient(155deg, #031c33 0%, var(--card) 58%, #00182b 100%);
|
|
46
|
+
box-shadow:
|
|
47
|
+
inset 0 1px 0 rgba(171, 197, 218, 0.08),
|
|
48
|
+
0 12px 24px rgba(0, 0, 0, 0.24);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.gold-title {
|
|
52
|
+
flex: 0 0 auto;
|
|
53
|
+
margin: 0;
|
|
54
|
+
color: var(--text);
|
|
55
|
+
font-size: 19px;
|
|
56
|
+
font-weight: 760;
|
|
57
|
+
letter-spacing: 0.015em;
|
|
58
|
+
line-height: 1.05;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.gold-quote {
|
|
62
|
+
display: flex;
|
|
63
|
+
flex: 0 0 auto;
|
|
64
|
+
flex-direction: column;
|
|
65
|
+
margin-top: 9px;
|
|
66
|
+
min-height: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.quote-meta {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: space-between;
|
|
73
|
+
min-height: 18px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.symbol-pill {
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
height: 18px;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
min-width: 59px;
|
|
82
|
+
padding: 0 6px;
|
|
83
|
+
border-radius: 5px;
|
|
84
|
+
background: var(--gold-deep);
|
|
85
|
+
color: var(--gold);
|
|
86
|
+
font-family: 'SF Mono', 'SFMono-Regular', Menlo, Consolas, 'Avenir Next', monospace;
|
|
87
|
+
font-size: 10px;
|
|
88
|
+
font-weight: 760;
|
|
89
|
+
letter-spacing: 0.01em;
|
|
90
|
+
line-height: 1;
|
|
91
|
+
white-space: nowrap;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.change {
|
|
95
|
+
color: var(--text);
|
|
96
|
+
font-family: 'Avenir Next', 'SF Pro Display', 'PingFang SC', 'Segoe UI Variable', sans-serif;
|
|
97
|
+
font-size: 13px;
|
|
98
|
+
font-variant-numeric: tabular-nums;
|
|
99
|
+
font-weight: 720;
|
|
100
|
+
letter-spacing: -0.01em;
|
|
101
|
+
line-height: 1;
|
|
102
|
+
white-space: nowrap;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.gold-quote[data-direction='error'] .change {
|
|
106
|
+
max-width: 82px;
|
|
107
|
+
overflow: hidden;
|
|
108
|
+
color: var(--muted);
|
|
109
|
+
font-size: 10px;
|
|
110
|
+
font-weight: 650;
|
|
111
|
+
text-overflow: ellipsis;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.price {
|
|
115
|
+
height: 45px;
|
|
116
|
+
margin-top: 2px;
|
|
117
|
+
overflow: hidden;
|
|
118
|
+
color: var(--text);
|
|
119
|
+
font-family:
|
|
120
|
+
'DIN Alternate', 'Avenir Next', 'SF Pro Display', 'PingFang SC', 'Segoe UI Variable', sans-serif;
|
|
121
|
+
font-size: 40px;
|
|
122
|
+
font-variant-numeric: tabular-nums;
|
|
123
|
+
font-weight: 650;
|
|
124
|
+
letter-spacing: -0.035em;
|
|
125
|
+
line-height: 45px;
|
|
126
|
+
white-space: nowrap;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.gold-quote[data-direction='error'] .price {
|
|
130
|
+
color: var(--muted);
|
|
131
|
+
font-size: 28px;
|
|
132
|
+
letter-spacing: 0.02em;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.chart {
|
|
136
|
+
display: flex;
|
|
137
|
+
flex: 1 1 auto;
|
|
138
|
+
align-items: flex-end;
|
|
139
|
+
min-height: 0;
|
|
140
|
+
margin-top: -2px;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.chart-svg {
|
|
144
|
+
display: block;
|
|
145
|
+
width: 100%;
|
|
146
|
+
height: 42px;
|
|
147
|
+
overflow: visible;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.baseline {
|
|
151
|
+
stroke: rgba(216, 165, 47, 0.65);
|
|
152
|
+
stroke-width: 1;
|
|
153
|
+
stroke-dasharray: 2 3;
|
|
154
|
+
vector-effect: non-scaling-stroke;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.area {
|
|
158
|
+
fill: url('#chart-fill');
|
|
159
|
+
stroke: none;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.line {
|
|
163
|
+
fill: none;
|
|
164
|
+
stroke: var(--gold);
|
|
165
|
+
stroke-linecap: round;
|
|
166
|
+
stroke-linejoin: round;
|
|
167
|
+
stroke-width: 1.25;
|
|
168
|
+
vector-effect: non-scaling-stroke;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.dot {
|
|
172
|
+
fill: var(--gold);
|
|
173
|
+
stroke: #001529;
|
|
174
|
+
stroke-width: 0.8;
|
|
175
|
+
vector-effect: non-scaling-stroke;
|
|
176
|
+
}
|
package/README.md
DELETED