Commit bb703b73 authored by Yaowentong's avatar Yaowentong

修复

parent 56367639
from flask import jsonify,Blueprint,render_template from datetime import datetime
from flask import jsonify, Blueprint, render_template, request
import requests
from aidso_geo.config.base_config import init_redis from aidso_geo.config.base_config import init_redis
dashboard_app = Blueprint("dashboard", __name__) dashboard_app = Blueprint("dashboard", __name__)
redis_client = init_redis() redis_client = init_redis()
@dashboard_app.route("/api/queue/status", methods=["GET"]) @dashboard_app.route("/api/queue/status", methods=["GET"])
def queue_status(): def queue_status():
data = {} data = {}
...@@ -29,3 +33,56 @@ def queue_status(): ...@@ -29,3 +33,56 @@ def queue_status():
@dashboard_app.route("/queue/monitor", methods=["GET"]) @dashboard_app.route("/queue/monitor", methods=["GET"])
def queue_monitor_page(): def queue_monitor_page():
return render_template("queue_monitor.html") return render_template("queue_monitor.html")
@dashboard_app.route("/api/queue/platformStats", methods=["GET"])
def get_req_trend():
begin = request.args.get("begin", "").strip()
end = request.args.get("end", "").strip()
if not begin or not end:
return jsonify({
"code": 400,
"msg": "begin and end are required",
"data": []
}), 400
try:
params = {
"begin": normalize_date_to_datetime(begin, "00:00:00"),
"end": normalize_date_to_datetime(end, "23:59:59"),
}
begin_time = datetime.strptime(params["begin"], "%Y-%m-%d %H:%M:%S")
end_time = datetime.strptime(params["end"], "%Y-%m-%d %H:%M:%S")
if begin_time > end_time:
return jsonify({
"code": 400,
"msg": "begin must be earlier than end",
"data": []
}), 400
except ValueError:
return jsonify({
"code": 400,
"msg": "begin and end must be YYYY-MM-DD",
"data": []
}), 400
url = "https://openapi.aidso.com/openapi/ywt/platformStats"
try:
response = requests.get(url, params=params, timeout=300)
response.raise_for_status()
return jsonify(response.json())
except (requests.RequestException, ValueError) as e:
return jsonify({
"code": 500,
"msg": f"platformStats request failed: {e}",
"data": []
}), 500
def normalize_date_to_datetime(value, default_time):
date_value = value.replace("T", " ").strip()[:10]
datetime.strptime(date_value, "%Y-%m-%d")
return f"{date_value} {default_time}"
...@@ -2,237 +2,57 @@ ...@@ -2,237 +2,57 @@
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Geo 队列监控面板</title> <title>GEO 队列监控面板</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<style> <link rel="stylesheet" href="{{ url_for('static', filename='dashboard/queue_monitor.css') }}">
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 24px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
background: #f3f5f9;
color: #1f2937;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.title {
font-size: 26px;
font-weight: 700;
}
.desc {
margin-top: 6px;
font-size: 14px;
color: #6b7280;
}
.right {
display: flex;
align-items: center;
gap: 12px;
}
.last-time {
font-size: 13px;
color: #6b7280;
}
.btn {
border: none;
border-radius: 8px;
background: #2563eb;
color: #fff;
padding: 9px 16px;
cursor: pointer;
font-size: 14px;
}
.btn:hover {
background: #1d4ed8;
}
.summary {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.card {
background: #fff;
border-radius: 14px;
padding: 18px;
box-shadow: 0 6px 18px rgba(15, 23, 42, 0.06);
}
.card-name {
color: #6b7280;
font-size: 14px;
margin-bottom: 10px;
}
.card-value {
font-size: 30px;
font-weight: 700;
}
.table-wrap {
background: #fff;
border-radius: 14px;
overflow: hidden;
box-shadow: 0 6px 18px rgba(15, 23, 42, 0.06);
}
table {
width: 100%;
border-collapse: collapse;
}
thead {
background: #f9fafb;
}
th, td {
padding: 14px 16px;
border-bottom: 1px solid #edf0f5;
text-align: left;
font-size: 14px;
}
th {
font-weight: 600;
color: #374151;
}
.platform {
font-weight: 700;
}
.num {
font-weight: 700;
}
.num-ok {
color: #16a34a;
}
.num-warn {
color: #f59e0b;
}
.num-danger {
color: #dc2626;
}
.status {
display: inline-block;
padding: 4px 10px;
border-radius: 999px;
font-size: 12px;
font-weight: 600;
}
.status-ok {
background: #dcfce7;
color: #166534;
}
.status-warn {
background: #fef3c7;
color: #92400e;
}
.status-danger {
background: #fee2e2;
color: #991b1b;
}
.error {
display: none;
margin-top: 16px;
padding: 12px 14px;
border-radius: 8px;
background: #fee2e2;
color: #991b1b;
font-size: 14px;
}
@media (max-width: 900px) {
.summary {
grid-template-columns: repeat(2, 1fr);
}
.header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
}
@media (max-width: 600px) {
body {
padding: 14px;
}
.summary {
grid-template-columns: 1fr;
}
th, td {
padding: 10px;
font-size: 13px;
}
}
</style>
</head> </head>
<body> <body>
<div class="layout">
<div class="header"> <aside class="sidebar">
<button class="nav-btn active" id="queueNavBtn" onclick="showPanel('queue')">积压查看</button>
<button class="nav-btn" id="trendNavBtn" onclick="showPanel('trend')">历史任务趋势</button>
</aside>
<main class="main">
<div class="header">
<div> <div>
<div class="title">Geo 队列监控面板</div> <div class="title" id="pageTitle">GEO 队列监控面板</div>
<div class="desc">查看各平台 stream_batch / batch 队列积压情况</div> <div class="desc" id="pageDesc">查看各平台 stream_batch / batch 队列积压情况</div>
</div> </div>
<div class="right"> <div class="right">
<span class="last-time" id="lastTime">未刷新</span> <span class="last-time" id="lastTime">未刷新</span>
<button class="btn" onclick="loadQueueStatus()">刷新</button> <button class="btn" onclick="refreshCurrentPanel()">刷新</button>
</div>
</div> </div>
</div>
<div class="summary"> <section class="panel active" id="queuePanel">
<div class="summary">
<div class="card"> <div class="card">
<div class="card-name">总积压</div> <div class="card-name">总积压</div>
<div class="card-value" id="totalCount">0</div> <div class="card-value" id="totalCount">0</div>
</div> </div>
<div class="card"> <div class="card">
<div class="card-name">stream_batch 总数</div> <div class="card-name">stream_batch 总数</div>
<div class="card-value" id="streamBatchCount">0</div> <div class="card-value" id="streamBatchCount">0</div>
</div> </div>
<div class="card"> <div class="card">
<div class="card-name">batch 总数</div> <div class="card-name">batch 总数</div>
<div class="card-value" id="batchCount">0</div> <div class="card-value" id="batchCount">0</div>
</div> </div>
<div class="card"> <div class="card">
<div class="card-name">提交队列</div> <div class="card-name">提交队列</div>
<div class="card-value" id="commitCount">0</div> <div class="card-value" id="commitCount">0</div>
</div> </div>
</div> </div>
<div class="table-wrap"> <div class="section-head">
<div class="section-title">队列积压详情</div>
<div class="section-note">Redis 队列长度</div>
</div>
<div class="table-wrap">
<table> <table>
<thead> <thead>
<tr> <tr>
...@@ -245,121 +65,45 @@ ...@@ -245,121 +65,45 @@
</thead> </thead>
<tbody id="queueTableBody"></tbody> <tbody id="queueTableBody"></tbody>
</table> </table>
</div> </div>
</section>
<div class="error" id="errorBox"></div>
<script>
const API_URL = "/api/queue/status";
const platforms = [
"BDAI", "DB", "DOUBA", "DP", "DPA", "DYAI",
"KIMI", "TXYB", "TXYBA", "TYQW", "TYQWA", "WXYY"
];
function getNumClass(num) {
if (num === 0) {
return "num-ok";
}
if (num < 500) {
return "num-warn";
}
return "num-danger";
}
function getStatus(total) {
if (total === 0) {
return {
text: "正常",
className: "status status-ok"
};
}
if (total < 500) {
return {
text: "轻微积压",
className: "status status-warn"
};
}
return {
text: "严重积压",
className: "status status-danger"
};
}
function renderData(data) {
const tbody = document.getElementById("queueTableBody");
let totalCount = 0;
let streamBatchCount = 0;
let batchCount = 0;
tbody.innerHTML = "";
platforms.forEach(platform => {
const streamKey = `${platform}:geo:stream_batch:list`;
const batchKey = `${platform}:geo:batch:list`;
const streamValue = Number(data[streamKey] || 0);
const batchValue = Number(data[batchKey] || 0);
const platformTotal = streamValue + batchValue;
streamBatchCount += streamValue;
batchCount += batchValue;
totalCount += platformTotal;
const status = getStatus(platformTotal);
const tr = document.createElement("tr");
tr.innerHTML = `
<td class="platform">${platform}</td>
<td class="num ${getNumClass(streamValue)}">${streamValue}</td>
<td class="num ${getNumClass(batchValue)}">${batchValue}</td>
<td class="num ${getNumClass(platformTotal)}">${platformTotal}</td>
<td><span class="${status.className}">${status.text}</span></td>
`;
tbody.appendChild(tr);
});
const commitCount = Number(data["geo:task_commit:list"] || 0);
document.getElementById("totalCount").innerText = totalCount;
document.getElementById("streamBatchCount").innerText = streamBatchCount;
document.getElementById("batchCount").innerText = batchCount;
document.getElementById("commitCount").innerText = commitCount;
document.getElementById("lastTime").innerText = "最后刷新:" + new Date().toLocaleString();
}
async function loadQueueStatus() {
const errorBox = document.getElementById("errorBox");
try {
errorBox.style.display = "none";
errorBox.innerText = "";
const res = await fetch(API_URL, {
method: "GET",
cache: "no-store"
});
if (!res.ok) {
throw new Error("接口请求失败,状态码:" + res.status);
}
const data = await res.json();
renderData(data);
} catch (e) {
errorBox.style.display = "block";
errorBox.innerText = "加载失败:" + e.message;
}
}
loadQueueStatus(); <section class="panel" id="trendPanel">
<div class="section-head">
<div class="section-title">历史任务趋势</div>
<div class="section-note" id="statsNote">等待加载</div>
</div>
<div class="trend-panel">
<div class="filter-row">
<div class="quick-range">
<button class="quick-btn active" id="range3Btn" onclick="setQuickRange(3)">近3天</button>
<button class="quick-btn" id="range7Btn" onclick="setQuickRange(7)">近7天</button>
<button class="quick-btn" id="range30Btn" onclick="setQuickRange(30)">近30天</button>
</div>
<div class="field">
<label for="beginTime">开始时间</label>
<input id="beginTime" type="date">
</div>
<div class="field">
<label for="endTime">结束时间</label>
<input id="endTime" type="date">
</div>
</div>
<div class="trend-chart" id="platformTrendChart"></div>
<div class="trend-summary" id="trendSummary"></div>
<div class="trend-loading-mask" id="trendLoadingMask">
<div class="loading-box">
<span class="loading-spinner"></span>
<span>加载中</span>
</div>
</div>
</div>
</section>
setInterval(loadQueueStatus, 30000); <div class="error" id="errorBox"></div>
</script> </main>
</div>
<script src="{{ url_for('static', filename='dashboard/queue_monitor.js') }}" defer></script>
</body> </body>
</html> </html>
...@@ -1625,14 +1625,14 @@ def platform_process(data): ...@@ -1625,14 +1625,14 @@ def platform_process(data):
response_content = None response_content = None
# #——————————————################### #——————————————###################
# has_original = check_file_in_tos(original_path) # has_original = check_file_in_tos(original_path)
# has_context = check_file_in_tos(context_path) # has_context = check_file_in_tos(context_path)
# # 重新跑逻辑 当俩个都有走下面 # # 重新跑逻辑 当俩个都有走下面
# if has_original and has_context: # if has_original and has_context:
# process_func = PLATFORM_PROCESS_MAP.get(platform) # process_func = PLATFORM_PROCESS_MAP.get(platform)
# if process_func: # if process_func:
# _, _, _, _, response_content, _ = process_func(original_path) # _, _, _, _, response_content, _ = process_func(data)
# # 2. 只有 context:直接读 context # # 2. 只有 context:直接读 context
# elif has_context: # elif has_context:
# response_content = tos_utils.get_string_from_tos(context_path) # response_content = tos_utils.get_string_from_tos(context_path)
...@@ -1641,16 +1641,18 @@ def platform_process(data): ...@@ -1641,16 +1641,18 @@ def platform_process(data):
# elif has_original: # elif has_original:
# process_func = PLATFORM_PROCESS_MAP.get(platform) # process_func = PLATFORM_PROCESS_MAP.get(platform)
# if process_func: # if process_func:
# _, _, _, _, response_content, _ = process_func(original_path) # _, _, _, _, response_content, _ = process_func(data)
# #——————————————################### #——————————————###################
#-------------
if check_file_in_tos(context_path): if check_file_in_tos(context_path):
response_content = tos_utils.get_string_from_tos(context_path) response_content = tos_utils.get_string_from_tos(context_path)
else: else:
process_func = PLATFORM_PROCESS_MAP.get(platform) process_func = PLATFORM_PROCESS_MAP.get(platform)
if process_func: if process_func:
_, _, _, _, response_content, _ = process_func(data) _, _, _, _, response_content, _ = process_func(data)
#-------------
if response_content: if response_content:
result_v2(response_content, data) result_v2(response_content, data)
else: else:
......
...@@ -262,10 +262,7 @@ if __name__ == '__main__': ...@@ -262,10 +262,7 @@ if __name__ == '__main__':
i['keywords'] = json.loads(i.get('keywords')) i['keywords'] = json.loads(i.get('keywords'))
if i.get('productWordsMap'): if i.get('productWordsMap'):
i['productWordsMap'] = json.loads(i.get('productWordsMap')) i['productWordsMap'] = json.loads(i.get('productWordsMap'))
type_t = i.get('type')
# type_t = 'batch'
# return task_send_queue(i,type_t)
return qianwen_android_process_original_data(i) return qianwen_android_process_original_data(i)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment