@yuku123/z-agent-frontend-component 0.1.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.
Files changed (41) hide show
  1. package/README.md +66 -0
  2. package/dist/z-agent-frontend-component.css +1 -0
  3. package/dist/z-agent-frontend-component.es.js +9956 -0
  4. package/dist/z-agent-frontend-component.umd.js +219 -0
  5. package/package.json +77 -0
  6. package/src/api/apiRouter.js +78 -0
  7. package/src/api/index.js +23 -0
  8. package/src/api/request.js +59 -0
  9. package/src/api/routes.js +140 -0
  10. package/src/dev.jsx +80 -0
  11. package/src/index.js +86 -0
  12. package/src/pages/agent/app/index.jsx +2 -0
  13. package/src/pages/agent/editor/AgentAppEditor.jsx +456 -0
  14. package/src/pages/agent/editor/WorkflowEditor.jsx +495 -0
  15. package/src/pages/agent/editor/nodes/index.ts +225 -0
  16. package/src/pages/agent/index.jsx +1379 -0
  17. package/src/pages/agent/share.jsx +512 -0
  18. package/src/pages/ak/AkUsageDrawer.jsx +208 -0
  19. package/src/pages/ak/index.jsx +496 -0
  20. package/src/pages/llm/index.jsx +736 -0
  21. package/src/pages/llm/model/index.jsx +220 -0
  22. package/src/pages/llm/provider/index.jsx +173 -0
  23. package/src/pages/mcp/index.jsx +359 -0
  24. package/src/pages/oss/BucketList.jsx +320 -0
  25. package/src/pages/oss/ObjectBrowser.jsx +409 -0
  26. package/src/pages/product/execute.jsx +608 -0
  27. package/src/pages/product/index.jsx +628 -0
  28. package/src/pages/product/scene.jsx +746 -0
  29. package/src/pages/script/ApiBridgeEditor.jsx +255 -0
  30. package/src/pages/script/CurlImportModal.jsx +263 -0
  31. package/src/pages/script/FieldMappingEditor.jsx +131 -0
  32. package/src/pages/script/OpenApiImportModal.jsx +212 -0
  33. package/src/pages/script/index.jsx +532 -0
  34. package/src/pages/skill/index.jsx +1595 -0
  35. package/src/pages/trace/DebugPlayground.jsx +357 -0
  36. package/src/pages/trace/components/MetricsDashboard.jsx +164 -0
  37. package/src/pages/trace/components/RagFragments.jsx +134 -0
  38. package/src/pages/trace/components/Timeline.jsx +142 -0
  39. package/src/pages/trace/components/ToolCallTree.jsx +116 -0
  40. package/src/pages/trace/index.jsx +13 -0
  41. package/src/pages/usage/index.jsx +352 -0
@@ -0,0 +1,208 @@
1
+ import {useEffect, useState} from 'react'
2
+ import {Card, Col, Divider, Drawer, Empty, Row, Space, Spin, Statistic, Table, Tabs, Tag, Typography} from 'antd'
3
+ import {
4
+ ApiOutlined,
5
+ BarChartOutlined,
6
+ ClockCircleOutlined,
7
+ CopyOutlined,
8
+ DollarOutlined,
9
+ ThunderboltOutlined
10
+ } from '@ant-design/icons'
11
+ import ReactECharts from 'echarts-for-react'
12
+ import request from '../../api'
13
+
14
+ const {Text} = Typography
15
+
16
+ const formatTokens = (n) => {
17
+ if (!n) return '0'
18
+ if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M'
19
+ if (n >= 1000) return (n / 1000).toFixed(1) + 'K'
20
+ return Number(n).toLocaleString()
21
+ }
22
+
23
+ const formatCost = (v) => {
24
+ if (!v) return '0.0000'
25
+ return Number(v).toFixed(4)
26
+ }
27
+
28
+ const AkUsageDrawer = ({open, ak, onClose}) => {
29
+ const [overview, setOverview] = useState(null)
30
+ const [trend, setTrend] = useState([])
31
+ const [records, setRecords] = useState([])
32
+ const [loading, setLoading] = useState(false)
33
+
34
+ useEffect(() => {
35
+ if (!open || !ak) return
36
+ fetchAll()
37
+ }, [open, ak])
38
+
39
+ const fetchAll = async () => {
40
+ setLoading(true)
41
+ try {
42
+ // 并行加载 3 个接口
43
+ const [ov, tr, rec] = await Promise.allSettled([
44
+ request('/llm-gateway/usage/overview', {method: 'GET', params: {accessKey: ak.accessKey}}),
45
+ request('/llm-gateway/usage/trend', {method: 'GET', params: {accessKey: ak.accessKey, days: 7}}),
46
+ request('/llm-gateway/usage/records', {
47
+ method: 'GET',
48
+ params: {accessKey: ak.accessKey, page: 1, size: 20}
49
+ }),
50
+ ])
51
+ setOverview(ov.status === 'fulfilled' ? (ov.value?.data || ov.value || null) : null)
52
+ setTrend(tr.status === 'fulfilled' ? (Array.isArray(tr.value) ? tr.value : (tr.value?.data || [])) : [])
53
+ const recVal = rec.status === 'fulfilled' ? rec.value : null
54
+ setRecords(recVal ? (Array.isArray(recVal) ? recVal : (recVal.records || recVal.data || [])) : [])
55
+ } catch (e) {
56
+ // 单个接口失败不影响其他
57
+ } finally {
58
+ setLoading(false)
59
+ }
60
+ }
61
+
62
+ const handleCopy = (text, label) => {
63
+ navigator.clipboard.writeText(text)
64
+ // eslint-disable-next-line no-undef
65
+ message.success(`${label} 已复制`)
66
+ }
67
+
68
+ const trendOption = {
69
+ tooltip: {trigger: 'axis'},
70
+ legend: {data: ['Token消耗', '调用次数']},
71
+ grid: {top: 40, right: 40, bottom: 30, left: 50},
72
+ xAxis: {
73
+ type: 'category',
74
+ data: trend.map(t => t.date || t.statDate || ''),
75
+ },
76
+ yAxis: [
77
+ {type: 'value', name: 'Tokens', position: 'left'},
78
+ {type: 'value', name: '调用次数', position: 'right'},
79
+ ],
80
+ series: [
81
+ {name: 'Token消耗', type: 'bar', data: trend.map(t => t.dailyTokens || t.totalTokens || 0)},
82
+ {name: '调用次数', type: 'line', yAxisIndex: 1, data: trend.map(t => t.dailyCalls || t.totalCalls || 0)},
83
+ ],
84
+ }
85
+
86
+ const recordColumns = [
87
+ {title: '时间', dataIndex: 'gmtCreate', width: 160},
88
+ {title: '应用', dataIndex: 'appCode', render: v => v ? <Tag color="blue">{v}</Tag> : '-'},
89
+ {title: '用户', dataIndex: 'userName', render: v => v || '-'},
90
+ {title: '供应商', dataIndex: 'providerCode', render: v => v ? <Tag color="purple">{v}</Tag> : '-'},
91
+ {title: '模型', dataIndex: 'modelCode', render: v => v ? <Tag>{v}</Tag> : '-'},
92
+ {title: '输入Token', dataIndex: 'inputTokens', render: v => v?.toLocaleString() || '-'},
93
+ {title: '输出Token', dataIndex: 'outputTokens', render: v => v?.toLocaleString() || '-'},
94
+ {
95
+ title: '状态', dataIndex: 'status',
96
+ render: v => <Tag color={v === 'SUCCESS' ? 'green' : 'red'}>{v || '-'}</Tag>,
97
+ },
98
+ {title: '费用', dataIndex: 'totalCost', render: v => <Text style={{color: '#faad14'}}>¥{v || '0.0000'}</Text>},
99
+ ]
100
+
101
+ return (
102
+ <Drawer
103
+ title={
104
+ <Space>
105
+ <span>用量详情 ·</span>
106
+ <Text strong>{ak?.akName}</Text>
107
+ {ak?.accessKey && (
108
+ <Space size={4}>
109
+ <code style={{
110
+ fontSize: 12,
111
+ color: '#595959',
112
+ background: '#f5f5f5',
113
+ padding: '2px 6px',
114
+ borderRadius: 4
115
+ }}>
116
+ {ak.accessKey}
117
+ </code>
118
+ <CopyOutlined
119
+ style={{cursor: 'pointer', color: '#1677ff'}}
120
+ onClick={() => handleCopy(ak.accessKey, 'AccessKey')}
121
+ />
122
+ </Space>
123
+ )}
124
+ </Space>
125
+ }
126
+ open={open}
127
+ onClose={onClose}
128
+ width={820}
129
+ destroyOnClose
130
+ >
131
+ <Spin spinning={loading}>
132
+ {/* 4 列统计 */}
133
+ <Row gutter={12} style={{marginBottom: 16}}>
134
+ <Col span={6}>
135
+ <Card size="small" style={{background: '#f5f5f5'}} bodyStyle={{padding: '10px 14px'}}>
136
+ <Statistic
137
+ title="累计 Token"
138
+ value={overview?.totalTokens || 0}
139
+ prefix={<ThunderboltOutlined style={{color: '#667eea'}}/>}
140
+ formatter={v => Number(v).toLocaleString()}
141
+ valueStyle={{fontSize: 18}}
142
+ />
143
+ </Card>
144
+ </Col>
145
+ <Col span={6}>
146
+ <Card size="small" style={{background: '#f5f5f5'}} bodyStyle={{padding: '10px 14px'}}>
147
+ <Statistic
148
+ title="累计费用"
149
+ value={formatCost(overview?.totalCost)}
150
+ prefix={<DollarOutlined style={{color: '#faad14'}}/>}
151
+ valueStyle={{fontSize: 18}}
152
+ />
153
+ </Card>
154
+ </Col>
155
+ <Col span={6}>
156
+ <Card size="small" style={{background: '#f5f5f5'}} bodyStyle={{padding: '10px 14px'}}>
157
+ <Statistic
158
+ title="今日 Token"
159
+ value={overview?.todayTokens || 0}
160
+ prefix={<ClockCircleOutlined style={{color: '#52c41a'}}/>}
161
+ formatter={v => Number(v).toLocaleString()}
162
+ valueStyle={{fontSize: 18}}
163
+ />
164
+ </Card>
165
+ </Col>
166
+ <Col span={6}>
167
+ <Card size="small" style={{background: '#f5f5f5'}} bodyStyle={{padding: '10px 14px'}}>
168
+ <Statistic
169
+ title="今日费用"
170
+ value={formatCost(overview?.todayCost)}
171
+ prefix={<DollarOutlined style={{color: '#faad14'}}/>}
172
+ valueStyle={{fontSize: 18}}
173
+ />
174
+ </Card>
175
+ </Col>
176
+ </Row>
177
+
178
+ <Divider style={{margin: '12px 0'}}/>
179
+
180
+ {/* Tab 切换 */}
181
+ <Tabs defaultActiveKey="trend" size="small">
182
+ <Tabs.TabPane tab="用量趋势" key="trend" icon={<BarChartOutlined/>}>
183
+ <Card size="small" bodyStyle={{padding: 12}}>
184
+ {trend.length > 0 ? (
185
+ <ReactECharts option={trendOption} style={{height: 300}}/>
186
+ ) : (
187
+ <Empty description="该 AK 暂无用量数据" style={{padding: '40px 0'}}/>
188
+ )}
189
+ </Card>
190
+ </Tabs.TabPane>
191
+
192
+ <Tabs.TabPane tab="调用明细" key="records" icon={<ApiOutlined/>}>
193
+ <Table
194
+ columns={recordColumns}
195
+ dataSource={records}
196
+ rowKey="id"
197
+ size="small"
198
+ pagination={{pageSize: 20, showSizeChanger: false}}
199
+ locale={{emptyText: <Empty description="暂无调用记录"/>}}
200
+ />
201
+ </Tabs.TabPane>
202
+ </Tabs>
203
+ </Spin>
204
+ </Drawer>
205
+ )
206
+ }
207
+
208
+ export default AkUsageDrawer