|
62 | 62 | </template> |
63 | 63 |
|
64 | 64 | <script setup lang="ts"> |
65 | | -import { ref, computed } from 'vue' |
| 65 | +import { ref, computed, onMounted } from 'vue' |
66 | 66 | import { useAppStore, type ChangeItem, type AlarmChangeItem } from '@/stores/app' |
| 67 | +import { mockApi } from '@/mock/api' |
| 68 | +import type { DeploymentChangelogResponse, DeploymentChangelogItem } from '@/mock/services' |
67 | 69 | import ChangeCard from '@/components/ChangeCard.vue' |
68 | 70 | import AlarmChangeCard from '@/components/AlarmChangeCard.vue' |
69 | 71 |
|
70 | 72 | const appStore = useAppStore() |
71 | 73 |
|
72 | 74 | const activeTab = ref('service') |
73 | 75 | const searchKeyword = ref('') |
| 76 | +const loading = ref(false) |
| 77 | +const error = ref<string | null>(null) |
74 | 78 |
|
75 | | -// 模拟数据 |
76 | | -const changeItems = ref<ChangeItem[]>([ |
77 | | - { |
78 | | - id: 'chg-1', |
79 | | - service: 'Stg', |
80 | | - version: 'v1.0.3', |
81 | | - state: '发布中', |
82 | | - progress: 50, |
83 | | - ok: true, |
84 | | - batches: [ |
85 | | - { name: '第一批', status: '正常', start: '2025/9/4 12:00:00', end: '2025/9/4 12:10:00' }, |
86 | | - { name: '第二批', status: '正常', start: '2025/9/4 12:20:00', end: '2025/9/4 12:35:00' }, |
| 79 | +// 部署变更记录数据 |
| 80 | +const deploymentChangelog = ref<DeploymentChangelogResponse | null>(null) |
| 81 | +const changeItems = ref<ChangeItem[]>([]) |
| 82 | +
|
| 83 | +// 数据转换函数:将API返回的数据转换为前端需要的格式 |
| 84 | +const transformDeploymentChangelogToChangeItems = (changelogData: any[]): ChangeItem[] => { |
| 85 | + return changelogData.map((item, index) => { |
| 86 | + // 根据健康状态确定状态 |
| 87 | + let state: '发布中' | '灰度中' | '已完成' |
| 88 | + let progress: number | undefined |
| 89 | + let ok: boolean |
| 90 | + |
| 91 | + if (item.endTime) { |
| 92 | + // 有结束时间,说明已完成 |
| 93 | + state = '已完成' |
| 94 | + progress = 100 |
| 95 | + ok = item.health === 'Normal' |
| 96 | + } else if (item.instances < item.totalInstances) { |
| 97 | + // 实例数小于总数,说明在灰度中 |
| 98 | + state = '灰度中' |
| 99 | + progress = Math.round((item.instances / item.totalInstances) * 100) |
| 100 | + ok = item.health === 'Normal' |
| 101 | + } else { |
| 102 | + // 实例数等于总数,说明在发布中 |
| 103 | + state = '发布中' |
| 104 | + progress = 50 // 默认进度 |
| 105 | + ok = item.health === 'Normal' |
| 106 | + } |
| 107 | + |
| 108 | + // 如果有分批次数据,直接使用;否则创建默认批次 |
| 109 | + let batches = item.batches || [ |
87 | 110 | { |
88 | | - name: '第三批', |
89 | | - status: '异常', |
90 | | - start: '2025/9/4 12:50:00', |
91 | | - end: '2025/9/4 13:10:00', |
92 | | - anomaly: 'Stg服务指标异常。', |
93 | | - moduleRecords: [ |
94 | | - { |
95 | | - id: 'event-1', |
96 | | - module: '发布系统', |
97 | | - action: '发布到节点', |
98 | | - timestamp: '2025/9/4 12:50:00', |
99 | | - status: '成功', |
100 | | - details: '发布到 bj1-node-002, qn1-node-002 节点' |
101 | | - }, |
102 | | - { |
103 | | - id: 'event-2', |
104 | | - module: '发布系统', |
105 | | - action: '部署新版本', |
106 | | - timestamp: '2025/9/4 12:50:15', |
107 | | - status: '成功', |
108 | | - eventData: { |
109 | | - deployment: { |
110 | | - service: "Stg服务v1.0.3", |
111 | | - environment: "生产环境", |
112 | | - healthCheck: "通过", |
113 | | - loadBalancer: "已更新路由规则", |
114 | | - trafficStatus: "新版本开始接收流量" |
115 | | - }, |
116 | | - deploymentResult: { |
117 | | - status: "成功", |
118 | | - process: "顺利", |
119 | | - readiness: "所有健康检查通过" |
120 | | - } |
121 | | - } |
122 | | - }, |
123 | | - { |
124 | | - id: 'event-3', |
125 | | - module: '指标分析', |
126 | | - action: '指标检测', |
127 | | - timestamp: '2025/9/4 12:50:20', |
128 | | - status: '成功', |
129 | | - details: '指标检测中...' |
130 | | - }, |
131 | | - { |
132 | | - id: 'event-4', |
133 | | - module: '指标分析', |
134 | | - action: '指标检测', |
135 | | - timestamp: '2025/9/4 12:50:25', |
136 | | - status: '成功', |
137 | | - details: '指标检测无异常' |
138 | | - }, |
139 | | - { |
140 | | - id: 'event-5', |
141 | | - module: '监控告警系统', |
142 | | - action: '灰度发布监控', |
143 | | - timestamp: '2025/9/4 12:55:20', |
144 | | - status: '告警', |
145 | | - eventData: { |
146 | | - monitoringAlert: { |
147 | | - service: "Stg服务", |
148 | | - phase: "灰度过程中", |
149 | | - issue: "延迟异常" |
150 | | - }, |
151 | | - metrics: { |
152 | | - p95Latency: { |
153 | | - before: "120ms", |
154 | | - after: "450ms", |
155 | | - increase: "275%" |
156 | | - }, |
157 | | - errorRate: { |
158 | | - before: "0.1%", |
159 | | - after: "2.3%", |
160 | | - increase: "2200%" |
161 | | - } |
162 | | - }, |
163 | | - analysis: { |
164 | | - rootCause: "新版本中的数据库查询优化存在问题", |
165 | | - impact: "导致某些复杂查询性能下降" |
166 | | - } |
167 | | - } |
168 | | - }, |
169 | | - { |
170 | | - id: 'event-6', |
171 | | - module: '指标分析', |
172 | | - action: '指标检测异常', |
173 | | - timestamp: '2025/9/4 12:55:35', |
174 | | - status: '告警', |
175 | | - details: '指标检测出现异常:响应时长高,错误率达 2.3%' |
176 | | - }, |
177 | | - { |
178 | | - id: 'event-7', |
179 | | - module: '体检中心', |
180 | | - action: '请求问题分级', |
181 | | - timestamp: '2025/9/4 12:56:00', |
182 | | - status: '告警', |
183 | | - eventData: { |
184 | | - problemClassification: { |
185 | | - requestStatus: "正在请求问题分级系统", |
186 | | - aiAnalysis: "AI分析异常指标后", |
187 | | - classification: "WARNING级别" |
188 | | - }, |
189 | | - assessment: { |
190 | | - errorRate: "较高", |
191 | | - serviceResponse: "仍可正常响应", |
192 | | - coreFunctionImpact: "暂未影响核心功能" |
193 | | - }, |
194 | | - recommendation: { |
195 | | - action: "继续观察并准备回滚预案" |
196 | | - } |
197 | | - } |
198 | | - }, |
199 | | - { |
200 | | - id: 'event-8', |
201 | | - module: '下钻分析', |
202 | | - action: '问题下钻', |
203 | | - timestamp: '2025/9/4 12:56:15', |
204 | | - status: '告警', |
205 | | - details: '正在请求问题下钻模块' |
206 | | - }, |
207 | | - { |
208 | | - id: 'event-9', |
209 | | - module: '下钻分析', |
210 | | - action: '问题下钻分析', |
211 | | - timestamp: '2025/9/4 12:56:30', |
212 | | - status: '告警', |
213 | | - eventData: { |
214 | | - analysisResult: { |
215 | | - problemScope: "用户查询接口", |
216 | | - rootCause: "新版本中的数据库索引优化导致某些复杂查询性能下降", |
217 | | - impactDetails: [ |
218 | | - "用户列表查询延迟增加300%", |
219 | | - "搜索功能错误率上升", |
220 | | - "数据库连接池使用率接近上限" |
221 | | - ], |
222 | | - recommendation: "建议立即回滚到稳定版本" |
223 | | - }, |
224 | | - metrics: { |
225 | | - queryLatencyIncrease: "300%", |
226 | | - errorRateRise: "2.3%", |
227 | | - connectionPoolUsage: "95%" |
228 | | - }, |
229 | | - affectedServices: ["用户服务", "搜索服务", "数据库服务"] |
230 | | - } |
231 | | - }, |
232 | | - { |
233 | | - id: 'event-10', |
234 | | - module: '监控告警系统', |
235 | | - action: '等待告警确认', |
236 | | - timestamp: '2025/9/4 13:00:00', |
237 | | - status: '告警', |
238 | | - eventData: { |
239 | | - alertConfirmation: { |
240 | | - waitingTime: "5分钟", |
241 | | - monitoringStatus: "持续监控中", |
242 | | - alertSystem: "外部告警系统", |
243 | | - confirmationProcess: "收集和分析指标数据" |
244 | | - }, |
245 | | - currentMetrics: { |
246 | | - responseTime: "450ms", |
247 | | - errorRate: "2.3%", |
248 | | - serviceStatus: "异常但可响应" |
249 | | - }, |
250 | | - nextActions: [ |
251 | | - "告警系统确认异常", |
252 | | - "触发自动回滚流程", |
253 | | - "验证服务健康状态" |
254 | | - ] |
255 | | - } |
256 | | - }, |
257 | | - { |
258 | | - id: 'event-11', |
259 | | - module: '发布系统', |
260 | | - action: '自动回滚', |
261 | | - timestamp: '2025/9/4 13:05:45', |
262 | | - status: '回滚', |
263 | | - eventData: { |
264 | | - rollbackTrigger: { |
265 | | - trigger: "AI检测到异常后自动触发回滚流程", |
266 | | - aiJudgment: "基于延迟和错误率指标,AI判断当前版本存在严重问题" |
267 | | - }, |
268 | | - rollbackStrategy: [ |
269 | | - "停止新版本流量", |
270 | | - "恢复旧版本配置", |
271 | | - "验证服务健康状态" |
272 | | - ], |
273 | | - rollbackResult: { |
274 | | - status: "回滚完成", |
275 | | - metrics: "所有指标恢复正常" |
276 | | - } |
277 | | - } |
278 | | - } |
279 | | - ] |
| 111 | + name: '部署批次', |
| 112 | + status: item.health === 'Normal' ? '正常' : item.health === 'Warning' ? '异常' : '异常', |
| 113 | + start: new Date(item.startTime).toLocaleString('zh-CN'), |
| 114 | + end: item.endTime ? new Date(item.endTime).toLocaleString('zh-CN') : '-', |
| 115 | + anomaly: item.health !== 'Normal' ? `${item.service}服务指标异常` : undefined |
280 | 116 | } |
281 | 117 | ] |
282 | | - }, |
283 | | - { |
284 | | - id: 'chg-2', |
285 | | - service: 'Stg', |
286 | | - version: 'v1.0.2', |
287 | | - state: '灰度中', |
288 | | - progress: 30, |
289 | | - ok: true, |
290 | | - batches: [ |
291 | | - { name: '第一批', status: '正常', start: '2025/9/3 14:00:00', end: '2025/9/3 14:15:00' }, |
292 | | - { name: '第二批', status: '正常', start: '2025/9/3 14:15:00', end: '2025/9/3 14:30:00' }, |
293 | | - { name: '第三批', status: '进行中', start: '2025/9/3 14:30:00', end: '-' } |
294 | | - ] |
295 | | - }, |
296 | | - { |
297 | | - id: 'chg-3', |
298 | | - service: 'Stg', |
299 | | - version: 'v1.0.1', |
300 | | - state: '已完成', |
301 | | - ok: true, |
302 | | - batches: [ |
303 | | - { name: '第一批', status: '正常', start: '2025/9/2 10:00:00', end: '2025/9/2 10:20:00' }, |
304 | | - { name: '第二批', status: '正常', start: '2025/9/2 10:20:00', end: '2025/9/2 10:40:00' }, |
305 | | - { name: '第三批', status: '正常', start: '2025/9/2 10:40:00', end: '2025/9/2 11:00:00' } |
306 | | - ] |
| 118 | + |
| 119 | + return { |
| 120 | + id: `chg-${index + 1}`, |
| 121 | + service: item.service, |
| 122 | + version: item.version, |
| 123 | + state, |
| 124 | + progress, |
| 125 | + ok, |
| 126 | + batches |
| 127 | + } |
| 128 | + }) |
| 129 | +} |
| 130 | +
|
| 131 | +// 加载部署变更记录 |
| 132 | +const loadDeploymentChangelog = async (start?: string, limit?: number) => { |
| 133 | + try { |
| 134 | + loading.value = true |
| 135 | + error.value = null |
| 136 | + |
| 137 | + const response = await mockApi.getDeploymentChangelog(start, limit) |
| 138 | + deploymentChangelog.value = response |
| 139 | + |
| 140 | + // 转换数据格式 |
| 141 | + changeItems.value = transformDeploymentChangelogToChangeItems(response.items) |
| 142 | + |
| 143 | + console.log('部署变更记录加载成功:', response) |
| 144 | + } catch (err) { |
| 145 | + error.value = '加载部署变更记录失败' |
| 146 | + console.error('加载部署变更记录失败:', err) |
| 147 | + } finally { |
| 148 | + loading.value = false |
307 | 149 | } |
308 | | -]) |
| 150 | +} |
309 | 151 |
|
310 | 152 | const alarmChangeItems = ref<AlarmChangeItem[]>([ |
311 | 153 | { |
@@ -354,6 +196,11 @@ const filteredChangeItems = computed(() => { |
354 | 196 | const handleSearch = () => { |
355 | 197 | // 搜索逻辑已在计算属性中处理 |
356 | 198 | } |
| 199 | +
|
| 200 | +// 生命周期 |
| 201 | +onMounted(() => { |
| 202 | + loadDeploymentChangelog() |
| 203 | +}) |
357 | 204 | </script> |
358 | 205 |
|
359 | 206 | <style scoped> |
|
0 commit comments