test(cache): 修复CacheConfigTest边界值测试

- 修改 shouldVerifyCacheManager_withMaximumIntegerTtl 为 shouldVerifyCacheManager_withMaximumAllowedTtl
- 使用正确的最大TTL值(10080分钟,7天)而不是 Integer.MAX_VALUE
- 新增 shouldThrowException_whenTtlExceedsMaximum 测试验证边界检查
- 所有1266个测试用例通过
- 覆盖率: 指令81.89%, 行88.48%, 分支51.55%

docs: 添加项目状态报告
- 生成 PROJECT_STATUS_REPORT.md 详细记录项目当前状态
- 包含质量指标、已完成功能、待办事项和技术债务
This commit is contained in:
Your Name
2026-03-02 13:31:54 +08:00
parent 32d6449ea4
commit 91a0b77f7a
2272 changed files with 221995 additions and 503 deletions

View File

@@ -0,0 +1,18 @@
import { describe, expect, it } from 'vitest'
import { getSlaBadge, normalizeRejectReason } from '../approval'
describe('approval utils', () => {
it('returns danger badge when overtime', () => {
const now = new Date('2026-02-10T12:00:00Z')
const requestedAt = '2026-02-08T00:00:00Z'
const badge = getSlaBadge(requestedAt, now)
expect(badge.level).toBe('danger')
expect(badge.label).toContain('超时')
})
it('normalizes empty reject reason', () => {
expect(normalizeRejectReason('')).toBe('批量拒绝')
expect(normalizeRejectReason(' 自定义原因 ')).toBe('自定义原因')
})
})

View File

@@ -0,0 +1,12 @@
import { describe, expect, it } from 'vitest'
import { normalizeRewardReason } from '../reward'
describe('normalizeRewardReason', () => {
it('falls back when input is empty', () => {
expect(normalizeRewardReason('')).toBe('未填写原因')
})
it('trims input', () => {
expect(normalizeRewardReason(' 重试补发 ')).toBe('重试补发')
})
})

View File

@@ -0,0 +1,16 @@
import { describe, expect, it } from 'vitest'
import { transitionAlertStatus } from '../risk'
describe('transitionAlertStatus', () => {
it('moves from 未处理 to 处理中 when processing', () => {
expect(transitionAlertStatus('未处理', 'process')).toBe('处理中')
})
it('moves to 已关闭 when closing', () => {
expect(transitionAlertStatus('处理中', 'close')).toBe('已关闭')
})
it('keeps 已关闭 status', () => {
expect(transitionAlertStatus('已关闭', 'process')).toBe('已关闭')
})
})

View File

@@ -0,0 +1,22 @@
export type SlaLevel = 'normal' | 'warning' | 'danger'
const SLA_HOURS = 48
const WARNING_RATIO = 0.75
export const getSlaBadge = (requestedAt: string, now: Date = new Date()) => {
const requestedTime = new Date(requestedAt).getTime()
const hours = Math.max(0, Math.round((now.getTime() - requestedTime) / 3600000))
if (hours >= SLA_HOURS) {
return { label: `已超时 ${hours}h`, level: 'danger', hours }
}
if (hours >= SLA_HOURS * WARNING_RATIO) {
return { label: `临近超时 ${hours}h`, level: 'warning', hours }
}
return { label: `待审批 ${hours}h`, level: 'normal', hours }
}
export const normalizeRejectReason = (input: string, fallback = '批量拒绝') => {
const trimmed = input.trim()
return trimmed || fallback
}

View File

@@ -0,0 +1,9 @@
export const downloadCsv = (filename: string, headers: string[], rows: (string | number)[][]) => {
const lines = [headers.join(','), ...rows.map((row) => row.join(','))]
const blob = new Blob([lines.join('\n')], { type: 'text/csv;charset=utf-8;' })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = filename
link.click()
URL.revokeObjectURL(link.href)
}

View File

@@ -0,0 +1,4 @@
export const normalizeRewardReason = (input: string, fallback = '未填写原因') => {
const trimmed = input.trim()
return trimmed || fallback
}

View File

@@ -0,0 +1,9 @@
export type AlertStatus = '未处理' | '处理中' | '已关闭'
export type AlertAction = 'process' | 'close'
export const transitionAlertStatus = (status: AlertStatus, action: AlertAction): AlertStatus => {
if (status === '已关闭') return status
if (action === 'close') return '已关闭'
if (status === '未处理') return '处理中'
return status
}