mirror of
https://github.com/woodchen-ink/random-api-go.git
synced 2025-07-18 05:42:01 +08:00
feat: update random-api-go service and UI with stats display
This commit is contained in:
parent
fe18d6c828
commit
ff2163b207
@ -1,11 +1,13 @@
|
||||
services:
|
||||
random-api:
|
||||
random-api-go:
|
||||
container_name: random-api-go
|
||||
image: woodchen/random-api-go:latest
|
||||
ports:
|
||||
- "5003:5003"
|
||||
volumes:
|
||||
- ./public:/root/public
|
||||
- ./logs:/var/log/random-api
|
||||
- ./data:/root/data
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
restart: unless-stopped
|
16
main.go
16
main.go
@ -180,11 +180,11 @@ func getCSVContent(path string) (*URLSelector, error) {
|
||||
}
|
||||
|
||||
fullPath := filepath.Join("public", path)
|
||||
log.Printf("Attempting to read file: %s", fullPath)
|
||||
log.Printf("尝试读取文件: %s", fullPath)
|
||||
|
||||
fileContent, err := os.ReadFile(fullPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading CSV content: %w", err)
|
||||
return nil, fmt.Errorf("读取 CSV 内容时出错: %w", err)
|
||||
}
|
||||
|
||||
lines := strings.Split(string(fileContent), "\n")
|
||||
@ -225,8 +225,8 @@ func handleAPIRequest(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if time.Since(lastFetchTime) > cacheDuration {
|
||||
if err := loadCSVPaths(); err != nil {
|
||||
http.Error(w, "Failed to load CSV paths", http.StatusInternalServerError)
|
||||
log.Printf("Error loading CSV paths: %v", err)
|
||||
http.Error(w, "无法加载 CSV 路径", http.StatusInternalServerError)
|
||||
log.Printf("加载 CSV 路径时出错: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -253,13 +253,13 @@ func handleAPIRequest(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
selector, err := getCSVContent(csvPath)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to fetch CSV content", http.StatusInternalServerError)
|
||||
log.Printf("Error fetching CSV content: %v", err)
|
||||
http.Error(w, "无法获取 CSV 内容", http.StatusInternalServerError)
|
||||
log.Printf("获取 CSV 内容时出错: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(selector.URLs) == 0 {
|
||||
http.Error(w, "No content available", http.StatusNotFound)
|
||||
http.Error(w, "无可用内容", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
@ -270,7 +270,7 @@ func handleAPIRequest(w http.ResponseWriter, r *http.Request) {
|
||||
statsManager.IncrementCalls(endpoint)
|
||||
|
||||
duration := time.Since(start)
|
||||
log.Printf("Request: %s %s from %s - Source: %s - Duration: %v - Redirecting to: %s",
|
||||
log.Printf("请求:%s %s,来自 %s -来源:%s -持续时间:%v -重定向至:%s",
|
||||
r.Method, r.URL.Path, realIP, sourceDomain, duration, randomURL)
|
||||
|
||||
http.Redirect(w, r, randomURL, http.StatusFound)
|
||||
|
@ -54,6 +54,32 @@
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.stats-summary {
|
||||
background-color: #f5f5f5;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
/* 两列布局 */
|
||||
gap: 10px;
|
||||
/* 项目之间的间距 */
|
||||
}
|
||||
|
||||
.stats-item {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
/* 确保在小屏幕上切换为单列 */
|
||||
@media (max-width: 600px) {
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/13.0.2/markdown-it.min.js"></script>
|
||||
</head>
|
||||
@ -72,6 +98,81 @@
|
||||
html: true
|
||||
});
|
||||
|
||||
// 加载统计数据
|
||||
async function loadStats() {
|
||||
try {
|
||||
const response = await fetch('/stats');
|
||||
const stats = await response.json();
|
||||
updateStats(stats);
|
||||
} catch (error) {
|
||||
console.error('Error loading stats:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理统计数据
|
||||
function updateStats(stats) {
|
||||
const startDate = new Date('2024-10-26');
|
||||
const today = new Date();
|
||||
const daysSinceStart = Math.ceil((today - startDate) / (1000 * 60 * 60 * 24));
|
||||
|
||||
let totalCalls = 0;
|
||||
let todayCalls = 0;
|
||||
|
||||
Object.values(stats).forEach(stat => {
|
||||
totalCalls += stat.total_calls;
|
||||
todayCalls += stat.today_calls;
|
||||
});
|
||||
|
||||
const avgCallsPerDay = Math.round(totalCalls / daysSinceStart);
|
||||
|
||||
// 更新总体统计
|
||||
const summaryHtml = `
|
||||
<div class="stats-summary">
|
||||
<p>📊 <strong>接口调用统计</strong></p>
|
||||
<div class="stats-grid">
|
||||
<div class="stats-item">今日总调用:${todayCalls} 次</div>
|
||||
<div class="stats-item">平均每天调用:${avgCallsPerDay} 次</div>
|
||||
<div class="stats-item">总调用次数:${totalCalls} 次</div>
|
||||
<div class="stats-item">统计开始日期:2024-10-26</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 更新详细统计
|
||||
let detailHtml = `
|
||||
<div class="prose">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>接口</th>
|
||||
<th>今日调用</th>
|
||||
<th>总调用</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
`;
|
||||
|
||||
Object.entries(stats).forEach(([endpoint, stat]) => {
|
||||
detailHtml += `
|
||||
<tr>
|
||||
<td>${endpoint}</td>
|
||||
<td>${stat.today_calls}</td>
|
||||
<td>${stat.total_calls}</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
|
||||
detailHtml += `
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 插入统计数据
|
||||
document.getElementById('stats-summary').innerHTML = summaryHtml;
|
||||
document.getElementById('stats-detail').innerHTML = detailHtml;
|
||||
}
|
||||
|
||||
// 异步加载 index.md 文件内容
|
||||
fetch('./index.md')
|
||||
.then(response => response.text())
|
||||
@ -83,4 +184,4 @@
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
@ -1,5 +1,11 @@
|
||||
# Random-Api 随机文件API
|
||||
|
||||
## 接口统计
|
||||
<div id="stats-summary"></div>
|
||||
|
||||
## 详细统计
|
||||
<div id="stats-detail"></div>
|
||||
|
||||
## 图片接口
|
||||
|
||||
| 种类 | 请求地址 |
|
||||
|
Loading…
x
Reference in New Issue
Block a user