添加新需求
This commit is contained in:
@@ -107,6 +107,7 @@
|
||||
'skip-price-asin': 'panel-skip-price-asin',
|
||||
'query-asin': 'panel-query-asin',
|
||||
'product-categories': 'panel-product-categories',
|
||||
'image-video-tasks': 'panel-image-video-tasks',
|
||||
'history': 'panel-history',
|
||||
'version': 'panel-version',
|
||||
'digital-human-version': 'panel-digital-human-version'
|
||||
@@ -121,6 +122,7 @@
|
||||
else if (tabName === 'skip-price-asin') loadSkipPriceAsin(1);
|
||||
else if (tabName === 'query-asin') loadQueryAsin(1);
|
||||
else if (tabName === 'product-categories') loadProductCategories();
|
||||
else if (tabName === 'image-video-tasks') loadImageVideoTasks(1);
|
||||
else if (tabName === 'history') loadHistory(1);
|
||||
else if (tabName === 'version') loadSoftwareVersions();
|
||||
else if (tabName === 'digital-human-version') loadDigitalHumanVersions();
|
||||
@@ -616,6 +618,133 @@
|
||||
};
|
||||
|
||||
// ========== 生成记录 ==========
|
||||
var imageVideoTaskPage = 1, imageVideoTaskPageSize = 20;
|
||||
function buildImageVideoTaskQuery(page) {
|
||||
var params = new URLSearchParams();
|
||||
params.set('page', String(page || 1));
|
||||
params.set('page_size', String(imageVideoTaskPageSize));
|
||||
var values = {
|
||||
user_id: document.getElementById('imageVideoFilterUserId').value,
|
||||
username: document.getElementById('imageVideoFilterUsername').value.trim(),
|
||||
status: document.getElementById('imageVideoFilterStatus').value,
|
||||
coze_execute_id: document.getElementById('imageVideoFilterExecuteId').value.trim(),
|
||||
submitted_from: document.getElementById('imageVideoFilterFrom').value,
|
||||
submitted_to: document.getElementById('imageVideoFilterTo').value
|
||||
};
|
||||
Object.keys(values).forEach(function (key) { if (values[key]) params.set(key, values[key]); });
|
||||
return params.toString();
|
||||
}
|
||||
function renderImageVideoStatus(value) {
|
||||
var status = String(value || '-').toUpperCase();
|
||||
return '<span class="image-video-status ' + escapeHtml(status) + '">' + escapeHtml(status) + '</span>';
|
||||
}
|
||||
function safeAdminUrl(value) {
|
||||
var url = String(value || '').trim();
|
||||
return /^https?:\/\//i.test(url) ? url : '';
|
||||
}
|
||||
function loadImageVideoTasks(page) {
|
||||
imageVideoTaskPage = page || 1;
|
||||
var tbody = document.getElementById('imageVideoTaskListBody');
|
||||
tbody.innerHTML = '<tr><td colspan="10" class="empty-tip">加载中...</td></tr>';
|
||||
fetch('/api/admin/image-video-tasks?' + buildImageVideoTaskQuery(imageVideoTaskPage))
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (res) {
|
||||
if (!res.success) {
|
||||
tbody.innerHTML = '<tr><td colspan="10" class="empty-tip">加载失败:' + escapeHtml(res.error || '') + '</td></tr>';
|
||||
return;
|
||||
}
|
||||
var items = res.items || [];
|
||||
document.getElementById('imageVideoTaskTotal').textContent = '共 ' + (res.total || 0) + ' 条';
|
||||
if (!items.length) {
|
||||
tbody.innerHTML = '<tr><td colspan="10" class="empty-tip">暂无视频任务</td></tr>';
|
||||
} else {
|
||||
tbody.innerHTML = items.map(function (item) {
|
||||
var videoUrl = safeAdminUrl(item.video_url);
|
||||
var videoLink = videoUrl ? '<a href="' + escapeHtml(videoUrl) + '" target="_blank" rel="noreferrer">查看视频</a>' : '-';
|
||||
return '<tr>' +
|
||||
'<td>' + escapeHtml(item.task_id) + '</td>' +
|
||||
'<td>' + escapeHtml(item.username || '-') + '<div style="color:#888;font-size:12px;">ID ' + escapeHtml(item.user_id) + '</div></td>' +
|
||||
'<td>' + escapeHtml(item.mode || '-') + '</td>' +
|
||||
'<td>' + renderImageVideoStatus(item.status) + '</td>' +
|
||||
'<td>' + escapeHtml(item.coze_status || '-') + '</td>' +
|
||||
'<td title="' + escapeHtml(item.coze_execute_id || '') + '">' + escapeHtml(item.coze_execute_id || '-').slice(0, 18) + '</td>' +
|
||||
'<td>' + videoLink + '</td>' +
|
||||
'<td>' + escapeHtml(item.archive_status || '-') + '</td>' +
|
||||
'<td>' + escapeHtml(item.submitted_at || '-') + '</td>' +
|
||||
'<td><button class="btn btn-sm" data-image-video-detail="' + escapeHtml(item.task_id) + '">详情</button></td>' +
|
||||
'</tr>';
|
||||
}).join('');
|
||||
}
|
||||
renderPagination('imageVideoTaskPagination', res.total, res.page, res.page_size, loadImageVideoTasks);
|
||||
})
|
||||
.catch(function () {
|
||||
tbody.innerHTML = '<tr><td colspan="10" class="empty-tip">请求失败</td></tr>';
|
||||
});
|
||||
}
|
||||
function formatImageVideoJson(value) {
|
||||
try { return JSON.stringify(value == null ? {} : value, null, 2); }
|
||||
catch (error) { return String(value || ''); }
|
||||
}
|
||||
function renderImageVideoTaskDetail(item) {
|
||||
var videos = item.videos || [];
|
||||
var videoHtml = videos.length ? videos.map(function (video, index) {
|
||||
var displayUrl = safeAdminUrl(video.display_url);
|
||||
var sourceUrl = safeAdminUrl(video.source_url);
|
||||
var archivedUrl = safeAdminUrl(video.archived_url);
|
||||
return '<div class="image-video-video-item">' +
|
||||
'<strong>视频 ' + (index + 1) + '</strong>' +
|
||||
(displayUrl ? '<video src="' + escapeHtml(displayUrl) + '" controls playsinline preload="metadata"></video>' : '<p class="empty-tip">无可用视频地址</p>') +
|
||||
'<div style="margin-top:8px;display:flex;gap:10px;flex-wrap:wrap;">' +
|
||||
(archivedUrl ? '<a href="' + escapeHtml(archivedUrl) + '" target="_blank" rel="noreferrer">OSS 视频</a>' : '') +
|
||||
(sourceUrl ? '<a href="' + escapeHtml(sourceUrl) + '" target="_blank" rel="noreferrer">Coze 原始视频</a>' : '') +
|
||||
'</div><div style="font-size:12px;color:#777;margin-top:6px;">归档:' + escapeHtml(video.archive_status || '-') +
|
||||
(video.archive_error ? ' · ' + escapeHtml(video.archive_error) : '') + '</div></div>';
|
||||
}).join('') : '<p class="empty-tip">当前没有解析到视频地址</p>';
|
||||
var debugUrl = safeAdminUrl(item.debug_url);
|
||||
return '<div class="image-video-detail-meta">' +
|
||||
'<div><span>任务 ID</span>' + escapeHtml(item.task_id) + '</div>' +
|
||||
'<div><span>用户</span>' + escapeHtml(item.username || '-') + '(' + escapeHtml(item.user_id) + ')</div>' +
|
||||
'<div><span>任务模式</span>' + escapeHtml(item.mode || '-') + '</div>' +
|
||||
'<div><span>状态</span>' + escapeHtml(item.status || '-') + ' / ' + escapeHtml(item.coze_status || '-') + '</div>' +
|
||||
'<div><span>Coze 执行 ID</span>' + escapeHtml(item.coze_execute_id || '-') + '</div>' +
|
||||
'<div><span>提交时间</span>' + escapeHtml(item.submitted_at || '-') + '</div>' +
|
||||
'<div><span>完成时间</span>' + escapeHtml(item.completed_at || '-') + '</div>' +
|
||||
'<div><span>归档状态</span>' + escapeHtml(item.archive_status || '-') + '</div>' +
|
||||
'</div>' +
|
||||
(debugUrl ? '<p><strong>调试链接:</strong><a href="' + escapeHtml(debugUrl) + '" target="_blank" rel="noreferrer">' + escapeHtml(debugUrl) + '</a></p>' : '') +
|
||||
(item.error_message ? '<p class="msg err">任务错误:' + escapeHtml(item.error_message) + '</p>' : '') +
|
||||
(item.archive_error ? '<p class="msg err">归档错误:' + escapeHtml(item.archive_error) + '</p>' : '') +
|
||||
'<div class="image-video-video-grid">' + videoHtml + '</div>' +
|
||||
'<details class="image-video-json"><summary>请求参数(密钥已脱敏)</summary><pre>' + escapeHtml(formatImageVideoJson(item.request)) + '</pre></details>' +
|
||||
'<details class="image-video-json"><summary>Coze 首次提交响应</summary><pre>' + escapeHtml(formatImageVideoJson(item.submit_response)) + '</pre></details>' +
|
||||
'<details class="image-video-json"><summary>Coze 最终响应</summary><pre>' + escapeHtml(formatImageVideoJson(item.result)) + '</pre></details>';
|
||||
}
|
||||
function openImageVideoTaskDetail(taskId) {
|
||||
var content = document.getElementById('imageVideoTaskDetailContent');
|
||||
content.innerHTML = '<p class="empty-tip">加载中...</p>';
|
||||
document.getElementById('imageVideoTaskDetailModal').classList.add('show');
|
||||
fetch('/api/admin/image-video-tasks/' + encodeURIComponent(taskId))
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (res) {
|
||||
content.innerHTML = res.success ? renderImageVideoTaskDetail(res.item || {}) : '<p class="msg err">' + escapeHtml(res.error || '加载失败') + '</p>';
|
||||
})
|
||||
.catch(function () { content.innerHTML = '<p class="msg err">请求失败</p>'; });
|
||||
}
|
||||
document.getElementById('btnFilterImageVideoTasks').onclick = function () { loadImageVideoTasks(1); };
|
||||
document.getElementById('btnResetImageVideoTasks').onclick = function () {
|
||||
['imageVideoFilterUserId', 'imageVideoFilterUsername', 'imageVideoFilterStatus', 'imageVideoFilterExecuteId', 'imageVideoFilterFrom', 'imageVideoFilterTo']
|
||||
.forEach(function (id) { document.getElementById(id).value = ''; });
|
||||
loadImageVideoTasks(1);
|
||||
};
|
||||
document.getElementById('imageVideoTaskListBody').onclick = function (event) {
|
||||
var button = event.target.closest('[data-image-video-detail]');
|
||||
if (button) openImageVideoTaskDetail(button.dataset.imageVideoDetail);
|
||||
};
|
||||
document.getElementById('btnCloseImageVideoTaskDetail').onclick = function () {
|
||||
document.getElementById('imageVideoTaskDetailModal').classList.remove('show');
|
||||
document.getElementById('imageVideoTaskDetailContent').innerHTML = '';
|
||||
};
|
||||
|
||||
var historyPage = 1, historyPageSize = 15;
|
||||
function toSqlDatetime(val) {
|
||||
if (!val) return '';
|
||||
|
||||
Reference in New Issue
Block a user