mirror of
https://github.com/woodchen-ink/random-api-go.git
synced 2025-07-19 14:22:00 +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:
|
services:
|
||||||
random-api:
|
random-api-go:
|
||||||
|
container_name: random-api-go
|
||||||
image: woodchen/random-api-go:latest
|
image: woodchen/random-api-go:latest
|
||||||
ports:
|
ports:
|
||||||
- "5003:5003"
|
- "5003:5003"
|
||||||
volumes:
|
volumes:
|
||||||
- ./public:/root/public
|
- ./public:/root/public
|
||||||
- ./logs:/var/log/random-api
|
- ./logs:/var/log/random-api
|
||||||
|
- ./data:/root/data
|
||||||
environment:
|
environment:
|
||||||
- TZ=Asia/Shanghai
|
- TZ=Asia/Shanghai
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
16
main.go
16
main.go
@ -180,11 +180,11 @@ func getCSVContent(path string) (*URLSelector, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fullPath := filepath.Join("public", path)
|
fullPath := filepath.Join("public", path)
|
||||||
log.Printf("Attempting to read file: %s", fullPath)
|
log.Printf("尝试读取文件: %s", fullPath)
|
||||||
|
|
||||||
fileContent, err := os.ReadFile(fullPath)
|
fileContent, err := os.ReadFile(fullPath)
|
||||||
if err != nil {
|
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")
|
lines := strings.Split(string(fileContent), "\n")
|
||||||
@ -225,8 +225,8 @@ func handleAPIRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
if time.Since(lastFetchTime) > cacheDuration {
|
if time.Since(lastFetchTime) > cacheDuration {
|
||||||
if err := loadCSVPaths(); err != nil {
|
if err := loadCSVPaths(); err != nil {
|
||||||
http.Error(w, "Failed to load CSV paths", http.StatusInternalServerError)
|
http.Error(w, "无法加载 CSV 路径", http.StatusInternalServerError)
|
||||||
log.Printf("Error loading CSV paths: %v", err)
|
log.Printf("加载 CSV 路径时出错: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,13 +253,13 @@ func handleAPIRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
selector, err := getCSVContent(csvPath)
|
selector, err := getCSVContent(csvPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to fetch CSV content", http.StatusInternalServerError)
|
http.Error(w, "无法获取 CSV 内容", http.StatusInternalServerError)
|
||||||
log.Printf("Error fetching CSV content: %v", err)
|
log.Printf("获取 CSV 内容时出错: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(selector.URLs) == 0 {
|
if len(selector.URLs) == 0 {
|
||||||
http.Error(w, "No content available", http.StatusNotFound)
|
http.Error(w, "无可用内容", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ func handleAPIRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
statsManager.IncrementCalls(endpoint)
|
statsManager.IncrementCalls(endpoint)
|
||||||
|
|
||||||
duration := time.Since(start)
|
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)
|
r.Method, r.URL.Path, realIP, sourceDomain, duration, randomURL)
|
||||||
|
|
||||||
http.Redirect(w, r, randomURL, http.StatusFound)
|
http.Redirect(w, r, randomURL, http.StatusFound)
|
||||||
|
@ -54,6 +54,32 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
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>
|
</style>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/13.0.2/markdown-it.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/13.0.2/markdown-it.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
@ -72,6 +98,81 @@
|
|||||||
html: true
|
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 文件内容
|
// 异步加载 index.md 文件内容
|
||||||
fetch('./index.md')
|
fetch('./index.md')
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
# Random-Api 随机文件API
|
# Random-Api 随机文件API
|
||||||
|
|
||||||
|
## 接口统计
|
||||||
|
<div id="stats-summary"></div>
|
||||||
|
|
||||||
|
## 详细统计
|
||||||
|
<div id="stats-detail"></div>
|
||||||
|
|
||||||
## 图片接口
|
## 图片接口
|
||||||
|
|
||||||
| 种类 | 请求地址 |
|
| 种类 | 请求地址 |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user