优化: 大文件拆分+代码分割+按需加载+console清理+any类型替换

- Money.tsx (2260行→54行): 拆分为 money/ 子目录4个组件, React.lazy二级分割
- AIAssistant.tsx (2038行→63行): 拆分为 ai-assistant/ 子目录6个组件, React.lazy二级分割
- xlsx改为动态导入, OvertimeTab从345KB降至12.7KB
- api-services.ts: 请求参数 any→Record<string,unknown>
- 移除前端3处console.log残留
- 后端console替换为pino logger
- 前后端未使用import/变量清理
- Zod schema验证: termination/platform/special-status/work-process
- 新增 leave.routes.ts, acceptance-test.routes.ts
- UI组件: PageGuide, QueryError, Stepper
This commit is contained in:
freedakgmail
2026-08-04 07:53:37 +08:00
parent 1da385cd5d
commit 2968484d2d
109 changed files with 8950 additions and 5926 deletions
+9 -7
View File
@@ -7,6 +7,8 @@
* 功能:存储、验证、过期清理、失败次数限制
*/
import logger from './logger'
interface CodeEntry {
code: string
expiresAt: number
@@ -28,11 +30,11 @@ async function getRedis() {
try {
const { createClient } = await import('redis')
redisClient = createClient({ url: REDIS_URL })
redisClient.on('error', (err: any) => console.error('[Redis] error:', err))
redisClient.on('error', (err: any) => logger.error({ err }, 'Redis error'))
await redisClient.connect()
console.log('[Redis] 验证码存储已连接')
logger.info('Redis 验证码存储已连接')
} catch (err) {
console.warn('[Redis] 连接失败,降级为内存存储:', err)
logger.warn({ err }, 'Redis 连接失败,降级为内存存储')
return null
}
}
@@ -59,7 +61,7 @@ export async function setCode(key: string, code: string, ttlMs: number = 5 * 60
await redis.set(`${KEY_PREFIX}${key}`, JSON.stringify(entry), { PX: ttlMs })
return
} catch (err) {
console.warn('[Redis] set 失败,降级内存:', err)
logger.warn({ err }, 'Redis set 失败,降级内存')
}
}
memoryStore.set(key, entry)
@@ -81,7 +83,7 @@ export async function getCode(key: string): Promise<CodeEntry | null> {
}
return entry
} catch (err) {
console.warn('[Redis] get 失败,降级内存:', err)
logger.warn({ err }, 'Redis get 失败,降级内存')
}
}
@@ -108,7 +110,7 @@ export async function updateCode(key: string, updates: Partial<CodeEntry>): Prom
}
return
} catch (err) {
console.warn('[Redis] update 失败,降级内存:', err)
logger.warn({ err }, 'Redis update 失败,降级内存')
}
}
@@ -128,7 +130,7 @@ export async function deleteCode(key: string): Promise<void> {
await redis.del(`${KEY_PREFIX}${key}`)
return
} catch (err) {
console.warn('[Redis] del 失败,降级内存:', err)
logger.warn({ err }, 'Redis del 失败,降级内存')
}
}
memoryStore.delete(key)
+4 -2
View File
@@ -1,3 +1,5 @@
import logger from './logger'
const required = ['JWT_SECRET', 'JWT_REFRESH_SECRET', 'ENCRYPTION_KEY']
const defaults: Record<string, string> = {
JWT_SECRET: 'dev-secret',
@@ -13,10 +15,10 @@ export function validateEnv(): void {
}
}
if (missing.length > 0 && process.env.NODE_ENV === 'production') {
console.error(`[FATAL] 以下环境变量未设置或使用了默认值,生产环境禁止启动: ${missing.join(', ')}`)
logger.fatal({ missing }, '以下环境变量未设置或使用了默认值,生产环境禁止启动')
process.exit(1)
}
if (missing.length > 0) {
console.warn(`[WARN] 以下环境变量使用了默认值,仅限开发环境: ${missing.join(', ')}`)
logger.warn({ missing }, '以下环境变量使用了默认值,仅限开发环境')
}
}
+23
View File
@@ -0,0 +1,23 @@
import pino from 'pino'
const isDev = process.env.NODE_ENV !== 'production'
const logger = pino({
level: process.env.LOG_LEVEL || (isDev ? 'debug' : 'info'),
transport: isDev
? {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'HH:MM:ss',
ignore: 'pid,hostname',
},
}
: undefined,
redact: {
paths: ['req.headers.authorization', 'req.headers.cookie', '*.password', '*.passwordHash', '*.token', '*.refreshToken'],
censor: '[REDACTED]',
},
})
export default logger
+8
View File
@@ -0,0 +1,8 @@
/**
* 统一分页参数解析,全局限制 pageSize ≤ 200,防止过量数据查询
*/
export function parsePagination(query: Record<string, any>): { page: number; pageSize: number } {
const page = Math.max(1, parseInt(query.page as string) || 1)
const pageSize = Math.min(Math.max(1, parseInt(query.pageSize as string) || 20), 200)
return { page, pageSize }
}