Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 18 additions & 69 deletions client/src/mock/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1707,44 +1707,21 @@ export const mockAlertRuleChangelog: AlertRuleChangelogResponse = {
// 使用 localStorage 实现前端数据持久化

/**
* 保存数据到 localStorage
* 保存数据到 localStorage(已禁用)
*/
const saveDataToStorage = () => {
try {
localStorage.setItem('mockServiceActiveVersions', JSON.stringify(mockServiceActiveVersions))
localStorage.setItem('mockAvailableVersions', JSON.stringify(mockAvailableVersions))
console.log('数据已保存到 localStorage')
} catch (error) {
console.error('保存数据到 localStorage 失败:', error)
}
// 不再保存到 localStorage,所有数据从API获取
}

/**
* 从 localStorage 加载数据
* 从 localStorage 加载数据(已禁用)
*/
const loadDataFromStorage = () => {
try {
const activeVersionsData = localStorage.getItem('mockServiceActiveVersions')
const availableVersionsData = localStorage.getItem('mockAvailableVersions')

if (activeVersionsData) {
const parsedData = JSON.parse(activeVersionsData)
Object.assign(mockServiceActiveVersions, parsedData)
console.log('已从 localStorage 加载活跃版本数据')
}

if (availableVersionsData) {
const parsedData = JSON.parse(availableVersionsData)
Object.assign(mockAvailableVersions, parsedData)
console.log('已从 localStorage 加载可发布版本数据')
}
} catch (error) {
console.error('从 localStorage 加载数据失败:', error)
}
// 不再从 localStorage 加载,所有数据从API获取
}
Comment on lines 1712 to 1721
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

这个PR移除了 localStorage 的使用,非常好。但目前只是将相关函数 (saveDataToStorage, loadDataFromStorage, saveServiceAlertStatus, loadServiceAlertStatus 等) 的函数体清空,而函数本身和对它们的调用仍然保留在代码中。

为了使代码更整洁、更易于维护,建议将这些已无实际作用的函数以及所有对它们的调用完全移除。例如,saveDataToStorage 函数的调用在 removeVersionFromAvailableaddVersionToAvailable 等函数中仍然存在。

如果未来可能需要恢复这些功能,通过 Git 历史记录来找回会是更好的选择。


// 页面加载时自动从 localStorage 恢复数据
loadDataFromStorage()
// 页面加载时不再从 localStorage 恢复数据(已禁用)
// loadDataFromStorage()

// ==================== 服务告警状态管理 ====================
// 管理服务节点的告警状态,用于改变拓扑图中节点的颜色
Expand All @@ -1760,31 +1737,17 @@ export type ServiceAlertStatus = 'normal' | 'pending' | 'processing'
export const serviceAlertStatusMap: Record<string, ServiceAlertStatus> = {}

/**
* 保存服务告警状态到 localStorage
* 保存服务告警状态(已禁用localStorage)
*/
const saveServiceAlertStatus = () => {
try {
localStorage.setItem('serviceAlertStatusMap', JSON.stringify(serviceAlertStatusMap))
console.log('服务告警状态已保存到 localStorage')
} catch (error) {
console.error('保存服务告警状态失败:', error)
}
// 不再保存到 localStorage,只在内存中维护
}

/**
* 从 localStorage 加载服务告警状态
* 从 localStorage 加载服务告警状态(已禁用)
*/
const loadServiceAlertStatus = () => {
try {
const data = localStorage.getItem('serviceAlertStatusMap')
if (data) {
const parsedData = JSON.parse(data)
Object.assign(serviceAlertStatusMap, parsedData)
console.log('已从 localStorage 加载服务告警状态')
}
} catch (error) {
console.error('从 localStorage 加载服务告警状态失败:', error)
}
// 不再从 localStorage 加载,改为从API获取
}

/**
Expand Down Expand Up @@ -1834,8 +1797,8 @@ export const clearServiceAlertStatus = (serviceName: string) => {
console.log(`已清除服务 ${serviceName} 的告警状态`)
}

// 页面加载时自动从 localStorage 恢复服务告警状态
loadServiceAlertStatus()
// 页面加载时不再从 localStorage 恢复服务告警状态(已禁用)
// loadServiceAlertStatus()

// ==================== 服务版本告警状态管理 ====================
// 让首页服务详情中的各版本颜色与告警状态同步
Expand Down Expand Up @@ -1917,31 +1880,17 @@ export type DeploymentStatus = 'idle' | 'deploying'
export const serviceDeploymentStatusMap: Record<string, DeploymentStatus> = {}

/**
* 保存服务发布状态到 localStorage
* 保存服务发布状态(已禁用localStorage)
*/
const saveServiceDeploymentStatus = () => {
try {
localStorage.setItem('serviceDeploymentStatusMap', JSON.stringify(serviceDeploymentStatusMap))
console.log('服务发布状态已保存到 localStorage')
} catch (error) {
console.error('保存服务发布状态失败:', error)
}
// 不再保存到 localStorage,只在内存中维护
}

/**
* 从 localStorage 加载服务发布状态
* 从 localStorage 加载服务发布状态(已禁用)
*/
const loadServiceDeploymentStatus = () => {
try {
const data = localStorage.getItem('serviceDeploymentStatusMap')
if (data) {
const parsedData = JSON.parse(data)
Object.assign(serviceDeploymentStatusMap, parsedData)
console.log('已从 localStorage 加载服务发布状态')
}
} catch (error) {
console.error('从 localStorage 加载服务发布状态失败:', error)
}
// 不再从 localStorage 加载,改为从API获取
}

/**
Expand Down Expand Up @@ -1973,8 +1922,8 @@ export const clearServiceDeploymentStatus = (serviceName: string) => {
console.log(`已清除服务 ${serviceName} 的发布状态`)
}

// 页面加载时自动从 localStorage 恢复服务发布状态
loadServiceDeploymentStatus()
// 页面加载时不再从 localStorage 恢复服务发布状态(已禁用)
// loadServiceDeploymentStatus()

// ==================== 数据操作函数 ====================
// 这些函数模拟后端操作数据的过程,用于支持前端的发布和回滚功能
Expand Down
58 changes: 0 additions & 58 deletions client/src/views/AlertsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ import {
} from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { apiService } from '@/api'
import { updateServiceAlertStatus, updateServiceVersionAlertStatus } from '@/mock/services'
import type { AlertsResponse, AlertIssue, AlertDetail } from '@/mock/services'
import { marked } from 'marked'

Expand Down Expand Up @@ -397,8 +396,6 @@ const loadAlerts = async () => {

alerts.value = merged.slice(0, 10)
allAlerts.value = merged
// 同步拓扑服务状态
syncServiceAlertStatuses(allAlerts.value)
console.log('告警数据加载成功: All', { total: merged.length })
} else {
const state = filterState.value === 'open' ? 'Open' : 'Closed'
Expand All @@ -415,8 +412,6 @@ const loadAlerts = async () => {
const mergedAll = [...openResp.data.items, ...closedResp.data.items]
.sort((a: any, b: any) => new Date(b.alertSince).getTime() - new Date(a.alertSince).getTime())
allAlerts.value = mergedAll
// 同步拓扑服务状态
syncServiceAlertStatuses(allAlerts.value)
console.log('告警数据加载成功:', { filter: state, count: alerts.value.length, total: mergedAll.length })
}
} catch (err) {
Expand All @@ -428,59 +423,6 @@ const loadAlerts = async () => {
}
}

// 将告警状态同步到首页拓扑的服务节点颜色
const syncServiceAlertStatuses = (issues: AlertIssue[]) => {
// 优先级:Pending > InProcessing > Restored > AutoRestored
const priority: Record<string, number> = {
Pending: 4,
InProcessing: 3,
Restored: 2,
AutoRestored: 1
}

// 可能需要从其他标签映射到首页的服务名
const prophetToServiceMap: Record<string, string> = {
s3apiv2: 's3'
}

const latestStateByService = new Map<string, { state: AlertIssue['alertState']; ts: number; prio: number }>()

for (const issue of issues) {
// 解析服务名:优先 labels.service,其次 prophet_service 的映射
const serviceLabel = issue.labels.find(l => l.key === 'service')?.value
const prophetService = issue.labels.find(l => l.key === 'prophet_service')?.value
const mapped = prophetService ? prophetToServiceMap[prophetService] : undefined
const serviceName = serviceLabel || mapped
if (!serviceName) continue

const ts = new Date(issue.alertSince).getTime()
const prio = priority[issue.alertState] || 0
const existing = latestStateByService.get(serviceName)
if (!existing || prio > existing.prio || (prio === existing.prio && ts > existing.ts)) {
latestStateByService.set(serviceName, { state: issue.alertState, ts, prio })
}

// 同步版本状态(如果存在 service_version 标签)
// 版本标签检测:兼容多种后端命名
const versionLabel =
issue.labels.find(l => l.key === 'service_version')?.value ||
issue.labels.find(l => l.key === 'version')?.value ||
issue.labels.find(l => l.key === 'serviceVersion')?.value ||
issue.labels.find(l => l.key === 'svc_version')?.value ||
issue.labels.find(l => l.key === 'deploy_version')?.value ||
issue.labels.find(l => l.key === 'deployVersion')?.value ||
issue.labels.find(l => l.key.toLowerCase().includes('version'))?.value
if (versionLabel) {
updateServiceVersionAlertStatus(serviceName, versionLabel, issue.alertState)
}
}

// 写入共享状态映射(持久化到 localStorage)
latestStateByService.forEach((val, service) => {
updateServiceAlertStatus(service, val.state)
})
}

// 生命周期
onMounted(() => {
loadAlerts()
Expand Down
53 changes: 50 additions & 3 deletions client/src/views/HomeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -643,18 +643,65 @@ const generateVersionsFromDeployState = (service: any) => {
}
}

// 解析告警列表,提取服务告警状态
const parseAlertsToServiceStatus = (alertsData: any) => {
// 优先级:Pending > InProcessing > Restored > AutoRestored
const priority: Record<string, number> = {
Pending: 4,
InProcessing: 3,
Restored: 2,
AutoRestored: 1
}

// 服务名映射
const prophetToServiceMap: Record<string, string> = {
s3apiv2: 's3'
}

const latestStateByService = new Map<string, { state: string; ts: number; prio: number }>()

for (const issue of alertsData) {
// 解析服务名:优先 labels.service,其次 prophet_service 的映射
const serviceLabel = issue.labels.find((l: any) => l.key === 'service')?.value
const prophetService = issue.labels.find((l: any) => l.key === 'prophet_service')?.value
const mapped = prophetService ? prophetToServiceMap[prophetService] : undefined
const serviceName = serviceLabel || mapped
if (!serviceName) continue

const ts = new Date(issue.alertSince).getTime()
const prio = priority[issue.alertState] || 0
const existing = latestStateByService.get(serviceName)
if (!existing || prio > existing.prio || (prio === existing.prio && ts > existing.ts)) {
latestStateByService.set(serviceName, { state: issue.alertState, ts, prio })
}
}

// 更新到全局状态映射
latestStateByService.forEach((val, service) => {
updateServiceAlertStatus(service, val.state)
})
}
Comment on lines +647 to +683
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

新添加的 parseAlertsToServiceStatus 函数存在两个问题:

  1. 类型不明确: 参数 alertsData 和循环变量 l 使用了 any 类型,这降低了代码的类型安全性和可读性。
  2. 缺少关键逻辑: 该函数遗漏了同步服务版本告警状态的逻辑。这部分逻辑在被替换的 syncServiceAlertStatuses 函数中是存在的,对于在UI上正确显示各版本的状态颜色至关重要,遗漏它可能导致显示错误。

建议进行如下修改,同时解决这两个问题。请注意,你需要在文件顶部导入 AlertIssue, AlertLabelupdateServiceVersionAlertStatus 类型和函数。

const parseAlertsToServiceStatus = (alertsData: AlertIssue[]) => {
  // 优先级:Pending > InProcessing > Restored > AutoRestored
  const priority: Record<string, number> = {
    Pending: 4,
    InProcessing: 3,
    Restored: 2,
    AutoRestored: 1
  }

  // 服务名映射
  const prophetToServiceMap: Record<string, string> = {
    s3apiv2: 's3'
  }

  const latestStateByService = new Map<string, { state: string; ts: number; prio: number }>()

  for (const issue of alertsData) {
    // 解析服务名:优先 labels.service,其次 prophet_service 的映射
    const serviceLabel = issue.labels.find((l: AlertLabel) => l.key === 'service')?.value
    const prophetService = issue.labels.find((l: AlertLabel) => l.key === 'prophet_service')?.value
    const mapped = prophetService ? prophetToServiceMap[prophetService] : undefined
    const serviceName = serviceLabel || mapped
    if (!serviceName) continue

    const ts = new Date(issue.alertSince).getTime()
    const prio = priority[issue.alertState] || 0
    const existing = latestStateByService.get(serviceName)
    if (!existing || prio > existing.prio || (prio === existing.prio && ts > existing.ts)) {
      latestStateByService.set(serviceName, { state: issue.alertState, ts, prio })
    }

    // 同步版本状态(如果存在 service_version 标签)
    // 版本标签检测:兼容多种后端命名
    const versionLabel =
      issue.labels.find((l: AlertLabel) => l.key === 'service_version')?.value ||
      issue.labels.find((l: AlertLabel) => l.key === 'version')?.value ||
      issue.labels.find((l: AlertLabel) => l.key === 'serviceVersion')?.value ||
      issue.labels.find((l: AlertLabel) => l.key === 'svc_version')?.value ||
      issue.labels.find((l: AlertLabel) => l.key === 'deploy_version')?.value ||
      issue.labels.find((l: AlertLabel) => l.key === 'deployVersion')?.value ||
      issue.labels.find((l: AlertLabel) => l.key.toLowerCase().includes('version'))?.value
    if (versionLabel) {
      updateServiceVersionAlertStatus(serviceName, versionLabel, issue.alertState)
    }
  }

  // 更新到全局状态映射
  latestStateByService.forEach((val, service) => {
    updateServiceAlertStatus(service, val.state)
  })
}


// API调用函数
const loadServicesData = async () => {
loading.value = true
error.value = null

try {
// 加载服务数据 - 调用真实后端API
const response = await apiService.getServices()
const servicesResponse = response.data
// 并行加载服务数据和告警数据
const [servicesRes, openAlertsRes, closedAlertsRes] = await Promise.all([
apiService.getServices(),
apiService.getAlerts(undefined, 100, 'Open'),
apiService.getAlerts(undefined, 100, 'Closed')
])

const servicesResponse = servicesRes.data
servicesData.value = servicesResponse

// 解析告警状态并更新到内存
const allAlerts = [...openAlertsRes.data.items, ...closedAlertsRes.data.items]
parseAlertsToServiceStatus(allAlerts)

// 转换数据
try {
const { nodes: transformedNodes, edges: transformedEdges } = transformServiceData(servicesResponse)
Expand Down