feat: 添加多项功能和修复

功能新增:
- OSS 存储使用情况显示(文件页面)
- OSS 当日流量统计(阿里云云监控API)
- 分享页面路由修复(/s/xxx 格式支持)

Bug修复:
- 修复分享页面资源路径(相对路径改绝对路径)
- 修复分享码获取逻辑(支持路径格式)
- 修复OSS配额undefined显示问题
- 修复登录流程OSS配置检查
- 修复文件数为null时的显示问题

依赖更新:
- 添加 @alicloud/cms20190101 云监控SDK
- 添加 @alicloud/openapi-client

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-22 21:04:22 +08:00
parent a86903fcdc
commit b135987fe8
3410 changed files with 494007 additions and 11 deletions

View File

@@ -6111,3 +6111,107 @@ app.listen(PORT, '0.0.0.0', () => {
console.log(`外网访问地址: http://0.0.0.0:${PORT}`);
console.log(`========================================\n`);
});
// ===== OSS 流量统计 API =====
const Cms20190101 = require('@alicloud/cms20190101');
const OpenApi = require('@alicloud/openapi-client');
// 获取 OSS 当日流量统计(仅管理员或用户自己)
app.get('/api/oss/traffic', authMiddleware, async (req, res) => {
try {
// 获取统一 OSS 配置
const ossConfig = SettingsDB.getUnifiedOssConfig();
if (!ossConfig) {
return res.status(400).json({
success: false,
message: 'OSS 未配置'
});
}
// 只支持阿里云
if (ossConfig.provider !== 'aliyun') {
return res.status(400).json({
success: false,
message: '流量统计仅支持阿里云 OSS'
});
}
// 创建云监控客户端
const config = new OpenApi.Config({
accessKeyId: ossConfig.access_key_id,
accessKeySecret: ossConfig.access_key_secret,
});
config.endpoint = 'metrics.cn-hangzhou.aliyuncs.com';
const client = new Cms20190101.default(config);
// 获取今天的时间范围
const now = new Date();
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const startTime = startOfDay.toISOString();
const endTime = now.toISOString();
// 查询外网流出流量(下载)
const downloadReq = new Cms20190101.DescribeMetricLastRequest({
namespace: 'acs_oss_dashboard',
metricName: 'InternetSend',
dimensions: JSON.stringify([{ BucketName: ossConfig.bucket }]),
startTime: startTime,
endTime: endTime,
period: '86400', // 按天汇总
});
// 查询外网流入流量(上传)
const uploadReq = new Cms20190101.DescribeMetricLastRequest({
namespace: 'acs_oss_dashboard',
metricName: 'InternetRecv',
dimensions: JSON.stringify([{ BucketName: ossConfig.bucket }]),
startTime: startTime,
endTime: endTime,
period: '86400',
});
const [downloadRes, uploadRes] = await Promise.all([
client.describeMetricLast(downloadReq),
client.describeMetricLast(uploadReq)
]);
// 解析结果
let downloadTraffic = 0;
let uploadTraffic = 0;
if (downloadRes.body?.datapoints) {
const datapoints = JSON.parse(downloadRes.body.datapoints);
if (datapoints.length > 0) {
downloadTraffic = datapoints.reduce((sum, dp) => sum + (dp.Value || dp.value || 0), 0);
}
}
if (uploadRes.body?.datapoints) {
const datapoints = JSON.parse(uploadRes.body.datapoints);
if (datapoints.length > 0) {
uploadTraffic = datapoints.reduce((sum, dp) => sum + (dp.Value || dp.value || 0), 0);
}
}
res.json({
success: true,
traffic: {
download: downloadTraffic,
downloadFormatted: formatFileSize(downloadTraffic),
upload: uploadTraffic,
uploadFormatted: formatFileSize(uploadTraffic),
total: downloadTraffic + uploadTraffic,
totalFormatted: formatFileSize(downloadTraffic + uploadTraffic),
date: startOfDay.toISOString().split('T')[0]
}
});
} catch (error) {
console.error('[OSS流量统计] 查询失败:', error);
res.status(500).json({
success: false,
message: '查询流量失败: ' + (error.message || '未知错误')
});
}
});