提交品牌删除更新
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>浜氶┈閫?- 鍗楁棩AI</title>
|
||||
<title>亚马逊 - 南日AI</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
.btn-home:hover { color: #fff; background: #2a2a2a; }
|
||||
|
||||
/* 椤堕儴鏍忕洰瀵艰埅锛堝鍣ㄥ寲锛屼究浜庡悗缁鍔犳爮鐩級 */
|
||||
/* 顶部栏目导航(容器化,便于后续增加栏目) */
|
||||
.nav-tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -87,7 +87,7 @@
|
||||
display: flex;
|
||||
height: calc(100vh - 56px);
|
||||
}
|
||||
/* 鏍忕洰鍐呭瀹瑰櫒锛氭瘡涓爮鐩竴涓?.tab-panel锛岄€氳繃 data-panel 涓庡鑸搴?*/
|
||||
/* 栏目内容容器:每个栏目一个 .tab-panel,通过 data-panel 与导航对应 */
|
||||
.tab-panel {
|
||||
display: none;
|
||||
flex: 1;
|
||||
@@ -338,87 +338,84 @@
|
||||
<body>
|
||||
<header class="top-bar">
|
||||
<div class="logo-area">
|
||||
<span class="app-name">鍗楁棩AI-浜氶┈閫?/span>
|
||||
<a href="/home" class="btn-home">杩斿洖棣栭〉</a>
|
||||
<span class="app-name">南日AI-亚马逊</span>
|
||||
<a href="/home" class="btn-home">返回首页</a>
|
||||
</div>
|
||||
<nav class="nav-tabs">
|
||||
<span class="nav-tab-group">
|
||||
<button type="button" class="nav-tab active" data-panel="brandCheck">鍝佺墝妫€娴?/button>
|
||||
<button type="button" class="nav-tab" onclick="window.location='/new_web_source/dedupe.html'">鎬绘暟鎹幓閲?/button>
|
||||
<button type="button" class="nav-tab" onclick="window.location='/new_web_source/convert.html'">鏍煎紡杞崲</button>
|
||||
<button type="button" class="nav-tab" onclick="window.location='/new_web_source/split.html'">琛ㄦ牸鎷嗗垎</button>
|
||||
<!-- 鍚庣画澧炲姞鏍忕洰鏃跺湪姝ゆ坊鍔狅紝渚嬪锛?button type="button" class="nav-tab" data-panel="other">鍏朵粬鏍忕洰</button> -->
|
||||
<button type="button" class="nav-tab active" data-panel="brandCheck">品牌检测</button>
|
||||
<!-- 后续增加栏目时在此添加,例如:<button type="button" class="nav-tab" data-panel="other">其他栏目</button> -->
|
||||
</span>
|
||||
<!-- 澶氱粍鏍忕洰鏃跺彲鐢ㄥ垎闅旂锛?span class="nav-tab-sep" aria-hidden="true"></span> -->
|
||||
<!-- 多组栏目时可用分隔符:<span class="nav-tab-sep" aria-hidden="true"></span> -->
|
||||
</nav>
|
||||
<div class="top-right"></div>
|
||||
</header>
|
||||
|
||||
<div class="main-content">
|
||||
<!-- 鍝佺墝妫€娴嬫爮鐩鍣紱鍚庣画澧炲姞鏍忕洰鏃跺鍒舵缁撴瀯锛屾敼 data-panel 涓?id锛屽苟鍘绘帀 .active -->
|
||||
<!-- 品牌检测栏目容器;后续增加栏目时复制此结构,改 data-panel 与 id,并去掉 .active -->
|
||||
<div class="tab-panel active" data-panel="brandCheck" id="panel-brandCheck">
|
||||
<aside class="left-panel">
|
||||
<div class="section-title">閫夋嫨鏂囦欢</div>
|
||||
<div class="section-title">选择文件</div>
|
||||
<div class="upload-zone" id="uploadZone">
|
||||
<div class="hint">閫夋嫨 .xlsx 鏂囦欢鎴栨枃浠跺す锛堝皢璇诲彇璇ユ枃浠跺す涓嬫墍鏈?xlsx锛?/div>
|
||||
<div class="hint">选择 .xlsx 文件或文件夹(将读取该文件夹下所有 xlsx)</div>
|
||||
<div class="btns">
|
||||
<button type="button" class="opt-btn" id="btnSelectFiles">閫夋嫨 Excel 鏂囦欢</button>
|
||||
<button type="button" class="opt-btn" id="btnSelectFolder">閫夋嫨鏂囦欢澶?/button>
|
||||
<button type="button" class="opt-btn" id="btnSelectFiles">选择 Excel 文件</button>
|
||||
<button type="button" class="opt-btn" id="btnSelectFolder">选择文件夹</button>
|
||||
</div>
|
||||
<div class="selected-files" id="selectedFiles"></div>
|
||||
</div>
|
||||
|
||||
<div class="section-title">杩愯鏂瑰紡</div>
|
||||
<div class="section-title">运行方式</div>
|
||||
<div class="option-group">
|
||||
<label class="radio-item">
|
||||
<input type="radio" name="runMode" value="immediate" checked>
|
||||
<div>
|
||||
<span class="label">绔嬪嵆杩愯</span>
|
||||
<div class="desc">绔嬪埢鎵ц锛屾墽琛屽畬鎴愬悗鍙笅杞界粨鏋?/div>
|
||||
<span class="label">立即运行</span>
|
||||
<div class="desc">立刻执行,执行完成后可下载结果</div>
|
||||
</div>
|
||||
</label>
|
||||
<label class="radio-item">
|
||||
<input type="radio" name="runMode" value="task">
|
||||
<div>
|
||||
<span class="label">娣诲姞浠诲姟</span>
|
||||
<div class="desc">鏁伴噺杈冨鏃跺缓璁坊鍔犱换鍔★紝鍚庡彴鎵ц锛屽彲鍦ㄥ彸渚т换鍔¢槦鍒楁煡鐪嬬姸鎬佷笌涓嬭浇缁撴灉</div>
|
||||
<span class="label">添加任务</span>
|
||||
<div class="desc">数量较多时建议添加任务,后台执行,可在右侧任务队列查看状态与下载结果</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="section-title">鍖归厤鏂瑰紡</div>
|
||||
<div class="section-title">匹配方式</div>
|
||||
<div class="option-group">
|
||||
<label class="radio-item">
|
||||
<input type="radio" name="matchStrategy" value="Terms" checked>
|
||||
<div>
|
||||
<span class="label">绮剧‘鍖归厤琛ㄨ揪寮?/span>
|
||||
<div class="desc">浣跨敤绮剧‘鍖归厤锛岄€傚悎涓ユ牸鍖归厤鍝佺墝鍚嶇О</div>
|
||||
<span class="label">精确匹配表达式</span>
|
||||
<div class="desc">使用精确匹配,适合严格匹配品牌名称</div>
|
||||
</div>
|
||||
</label>
|
||||
<label class="radio-item">
|
||||
<input type="radio" name="matchStrategy" value="Simple">
|
||||
<div>
|
||||
<span class="label">宓屽叆锛堢粨鏋滃寘鍚緭鍏ョ殑璇嶈锛?/span>
|
||||
<div class="desc">浣跨敤宓屽叆绛栫暐锛岀粨鏋滀腑鍖呭惈杈撳叆鐨勫搧鐗岃瘝璇?/div>
|
||||
<span class="label">嵌入(结果包含输入的词语)</span>
|
||||
<div class="desc">使用嵌入策略,结果中包含输入的品牌词语</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="run-row" id="runRow">
|
||||
<div style="display:flex;align-items:center;flex-wrap:wrap;gap:10px;">
|
||||
<button type="button" class="btn-run" id="btnRun">绔嬪嵆杩愯</button>
|
||||
<span class="loading-msg" id="loadingMsg" style="display:none;">鐢熸垚涓紝璇风◢鍊欌€?/span>
|
||||
<button type="button" class="btn-run" id="btnRun">立即运行</button>
|
||||
<span class="loading-msg" id="loadingMsg" style="display:none;">生成中,请稍候…</span>
|
||||
<div class="progress-wrap" id="runProgressWrap" style="display:none;">
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill" id="runProgressFill" style="width:0%;"></div></div>
|
||||
<span class="hint" style="font-size:12px;color:#888;" id="runProgressText">0 / 0</span>
|
||||
</div>
|
||||
<!-- 褰撳墠鏂囦欢琛岀骇杩涘害锛堜笉缁忔暟鎹簱涓浆锛屽彧璇诲唴瀛樻帴鍙o級 -->
|
||||
<!-- 当前文件行级进度(不经数据库中转,只读内存接口) -->
|
||||
<div class="progress-wrap" id="runLineProgressWrap" style="display:none;">
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill" id="runLineProgressFill" style="width:0%;"></div></div>
|
||||
<span class="hint" style="font-size:12px;color:#888;" id="runLineProgressText">0 / 0</span>
|
||||
</div>
|
||||
<button type="button" class="btn-cancel-run" id="btnCancelRun" style="display:none;">鍙栨秷鐢熸垚</button>
|
||||
<button type="button" class="btn-cancel-run" id="btnCancelRun" style="display:none;">取消生成</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="template-download-row" id="templateDownloadRow" role="button" tabindex="0" title="涓嬭浇鍝佺墝鏂囨。鏍煎紡妯℃澘锛堥€夋嫨淇濆瓨浣嶇疆锛?>
|
||||
<div class="template-download-row" id="templateDownloadRow" role="button" tabindex="0" title="下载品牌文档格式模板(选择保存位置)">
|
||||
<span class="template-download-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z" stroke="rgba(255,255,255,0.9)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
@@ -427,11 +424,11 @@
|
||||
</svg>
|
||||
</span>
|
||||
<span class="template-download-text">
|
||||
<span class="title">妯℃澘涓嬭浇</span>
|
||||
<span class="hint">鍝佺墝鏂囨。鏍煎紡_妯℃澘.xlsx 路 鐐瑰嚮閫夋嫨淇濆瓨浣嶇疆</span>
|
||||
<span class="title">模板下载</span>
|
||||
<span class="hint">品牌文档格式_模板.xlsx · 点击选择保存位置</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="template-download-row" id="templateDownloadRow2" role="button" tabindex="0" title="涓嬭浇妯℃澘2锛堜互鏂囦欢澶规柟寮忎笂浼狅級">
|
||||
<div class="template-download-row" id="templateDownloadRow2" role="button" tabindex="0" title="下载模板2(以文件夹方式上传)">
|
||||
<span class="template-download-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z" stroke="rgba(255,255,255,0.9)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
@@ -440,20 +437,20 @@
|
||||
</svg>
|
||||
</span>
|
||||
<span class="template-download-text">
|
||||
<span class="title">妯℃澘2涓嬭浇</span>
|
||||
<span class="hint">浠ユ枃浠跺す鏂瑰紡涓婁紶.zip 路 鐐瑰嚮涓嬭浇</span>
|
||||
<span class="title">模板2下载</span>
|
||||
<span class="hint">以文件夹方式上传.zip · 点击下载</span>
|
||||
</span>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<div class="right-panel">
|
||||
<div class="panel-header">
|
||||
<span class="panel-header-title">浠诲姟闃熷垪</span>
|
||||
<button type="button" class="btn-refresh-tasks" id="btnRefreshTasks">鍒锋柊浠诲姟鐘舵€?/button>
|
||||
<span class="panel-header-title">任务队列</span>
|
||||
<button type="button" class="btn-refresh-tasks" id="btnRefreshTasks">刷新任务状态</button>
|
||||
</div>
|
||||
<div class="task-list-wrap">
|
||||
<ul class="task-list" id="taskList"></ul>
|
||||
<div class="empty-tasks" id="emptyTasks">鏆傛棤浠诲姟</div>
|
||||
<div class="empty-tasks" id="emptyTasks">暂无任务</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -467,7 +464,7 @@
|
||||
var cachedTasks = [];
|
||||
var api = window.pywebview && window.pywebview.api;
|
||||
|
||||
// 椤堕儴鏍忕洰鍒囨崲锛氱偣鍑?nav-tab 鏃舵樉绀哄搴?data-panel 鐨?tab-panel
|
||||
// 顶部栏目切换:点击 nav-tab 时显示对应 data-panel 的 tab-panel
|
||||
document.querySelectorAll('.nav-tab').forEach(function(tab) {
|
||||
tab.addEventListener('click', function() {
|
||||
var panelId = this.getAttribute('data-panel');
|
||||
@@ -493,18 +490,18 @@
|
||||
el.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
el.innerHTML = '宸查€?<b>' + selectedPaths.length + '</b> 涓枃浠讹細<br>' +
|
||||
el.innerHTML = '已选 <b>' + selectedPaths.length + '</b> 个文件:<br>' +
|
||||
selectedPaths.slice(0, 20).map(function(p) {
|
||||
var name = p.split(/[/\\]/).pop();
|
||||
return '<span title="' + p + '">' + name + '</span>';
|
||||
}).join('') +
|
||||
(selectedPaths.length > 20 ? '<span>鈥?绛?' + selectedPaths.length + ' 涓?/span>' : '');
|
||||
(selectedPaths.length > 20 ? '<span>… 等 ' + selectedPaths.length + ' 个</span>' : '');
|
||||
}
|
||||
|
||||
document.getElementById('btnSelectFiles').onclick = async function(e) {
|
||||
e.stopPropagation();
|
||||
if (!api || !api.select_brand_xlsx_files) {
|
||||
showToast('褰撳墠鐜涓嶆敮鎸佹枃浠堕€夋嫨锛岃鍦ㄦ湰鏈哄鎴风涓墦寮€');
|
||||
showToast('当前环境不支持文件选择,请在本机客户端中打开');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -512,10 +509,10 @@
|
||||
if (paths && paths.length) {
|
||||
selectedPaths = paths;
|
||||
renderSelected();
|
||||
showToast('宸查€夋嫨 ' + paths.length + ' 涓枃浠?);
|
||||
showToast('已选择 ' + paths.length + ' 个文件');
|
||||
}
|
||||
} catch (err) {
|
||||
showToast('閫夋嫨澶辫触锛? + (err.message || err));
|
||||
showToast('选择失败:' + (err.message || err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -525,16 +522,16 @@
|
||||
try {
|
||||
var res = await api.save_template_xlsx();
|
||||
if (res && res.success) {
|
||||
showToast('妯℃澘宸蹭繚瀛樿嚦锛? + (res.path || ''));
|
||||
showToast('模板已保存至:' + (res.path || ''));
|
||||
} else {
|
||||
showToast(res && res.error ? res.error : '淇濆瓨澶辫触');
|
||||
showToast(res && res.error ? res.error : '保存失败');
|
||||
}
|
||||
} catch (err) {
|
||||
showToast('涓嬭浇澶辫触锛? + (err.message || err));
|
||||
showToast('下载失败:' + (err.message || err));
|
||||
}
|
||||
return;
|
||||
}
|
||||
window.location.href = '/static/鍝佺墝鏂囨。鏍煎紡_妯℃澘.xlsx';
|
||||
window.location.href = '/static/品牌文档格式_模板.xlsx';
|
||||
};
|
||||
document.getElementById('templateDownloadRow').onkeydown = function(e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); this.click(); }
|
||||
@@ -546,16 +543,16 @@
|
||||
try {
|
||||
var res = await api.save_template_zip();
|
||||
if (res && res.success) {
|
||||
showToast('妯℃澘宸蹭繚瀛樿嚦锛? + (res.path || ''));
|
||||
showToast('模板已保存至:' + (res.path || ''));
|
||||
} else {
|
||||
showToast(res && res.error ? res.error : '淇濆瓨澶辫触');
|
||||
showToast(res && res.error ? res.error : '保存失败');
|
||||
}
|
||||
} catch (err) {
|
||||
showToast('涓嬭浇澶辫触锛? + (err.message || err));
|
||||
showToast('下载失败:' + (err.message || err));
|
||||
}
|
||||
return;
|
||||
}
|
||||
window.location.href = '/static/妯℃澘2-浠ユ枃浠跺す鏂瑰紡涓婁紶.zip';
|
||||
window.location.href = '/static/模板2-以文件夹方式上传.zip';
|
||||
};
|
||||
document.getElementById('templateDownloadRow2').onkeydown = function(e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); this.click(); }
|
||||
@@ -564,7 +561,7 @@
|
||||
document.getElementById('btnSelectFolder').onclick =async function(e) {
|
||||
e.stopPropagation();
|
||||
if (!api || !api.select_brand_folder) {
|
||||
showToast('褰撳墠鐜涓嶆敮鎸佹枃浠跺す閫夋嫨锛岃鍦ㄦ湰鏈哄鎴风涓墦寮€');
|
||||
showToast('当前环境不支持文件夹选择,请在本机客户端中打开');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -581,14 +578,14 @@
|
||||
if (res.success && res.paths && res.paths.length) {
|
||||
selectedPaths = res.paths;
|
||||
renderSelected();
|
||||
showToast('宸查€夋嫨鏂囦欢澶瑰唴 ' + res.paths.length + ' 涓?xlsx 鏂囦欢');
|
||||
showToast('已选择文件夹内 ' + res.paths.length + ' 个 xlsx 文件');
|
||||
} else {
|
||||
showToast(res.error || '璇ユ枃浠跺す涓嬫病鏈?xlsx 鏂囦欢');
|
||||
showToast(res.error || '该文件夹下没有 xlsx 文件');
|
||||
}
|
||||
})
|
||||
.catch(function() { showToast('璇锋眰澶辫触'); });
|
||||
.catch(function() { showToast('请求失败'); });
|
||||
} catch (err) {
|
||||
showToast('閫夋嫨澶辫触锛? + (err.message || err));
|
||||
showToast('选择失败:' + (err.message || err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -628,9 +625,9 @@
|
||||
function onRunTaskFinished(status) {
|
||||
stopPollAndResetRunUI();
|
||||
loadTasks();
|
||||
if (status === 'success') showToast('鐢熸垚瀹屾垚锛屽彲涓嬭浇缁撴灉');
|
||||
else if (status === 'failed') showToast('鐢熸垚澶辫触');
|
||||
else if (status === 'cancelled') showToast('宸插彇娑?);
|
||||
if (status === 'success') showToast('生成完成,可下载结果');
|
||||
else if (status === 'failed') showToast('生成失败');
|
||||
else if (status === 'cancelled') showToast('已取消');
|
||||
}
|
||||
|
||||
function pollRunTask(taskId) {
|
||||
@@ -649,11 +646,11 @@
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(res) {
|
||||
if (res.success) onRunTaskFinished('cancelled');
|
||||
else showToast(res.error || '鍙栨秷澶辫触');
|
||||
else showToast(res.error || '取消失败');
|
||||
});
|
||||
};
|
||||
|
||||
// 閫氳繃 SSE 璁㈤槄浠诲姟瀹屾垚浜嬩欢锛屽畬鎴愬悗鐢卞悗绔富鍔ㄦ帹閫侊紝鍓嶇鏀跺埌鍚庣珛鍗抽殣钘忚繘搴︽潯鍜屽彇娑堟寜閽?
|
||||
// 通过 SSE 订阅任务完成事件,完成后由后端主动推送,前端收到后立即隐藏进度条和取消按钮
|
||||
var eventsUrl = '/api/brand/tasks/' + taskId + '/events';
|
||||
runTaskEventSource = new EventSource(eventsUrl);
|
||||
runTaskEventSource.onmessage = function(e) {
|
||||
@@ -685,18 +682,18 @@
|
||||
if (runProgressText) {
|
||||
var st = (t.status || '').toLowerCase();
|
||||
if (st === 'running') {
|
||||
runProgressText.textContent = total ? (cur + ' / ' + total) : '鐢熸垚涓€?;
|
||||
runProgressText.textContent = total ? (cur + ' / ' + total) : '生成中…';
|
||||
} else if (st === 'success') {
|
||||
runProgressText.textContent = '宸插畬鎴?;
|
||||
runProgressText.textContent = '已完成';
|
||||
} else if (st === 'failed') {
|
||||
runProgressText.textContent = '澶辫触';
|
||||
runProgressText.textContent = '失败';
|
||||
} else if (st === 'cancelled') {
|
||||
runProgressText.textContent = '宸插彇娑?;
|
||||
runProgressText.textContent = '已取消';
|
||||
} else {
|
||||
runProgressText.textContent = '鎵ц涓€?;
|
||||
runProgressText.textContent = '执行中…';
|
||||
}
|
||||
}
|
||||
// 琛岀骇杩涘害锛氫粠鍐呭瓨鎺ュ彛 /api/brand/tasks/<id>/line-progress 鎷夊彇
|
||||
// 行级进度:从内存接口 /api/brand/tasks/<id>/line-progress 拉取
|
||||
if (runLineProgressWrap && runLineProgressFill && runLineProgressText) {
|
||||
var st2 = (t.status || '').toLowerCase();
|
||||
if (st2 === 'running') {
|
||||
@@ -715,17 +712,14 @@
|
||||
var curLine = info.current_line || 0;
|
||||
runLineProgressWrap.style.display = 'block';
|
||||
runLineProgressFill.style.width = totalLines ? (100 * curLine / totalLines) + '%' : '0%';
|
||||
runLineProgressText.textContent = totalLines ? (curLine + ' / ' + totalLines) : '褰撳墠鏂囦欢澶勭悊涓€?;
|
||||
runLineProgressText.textContent = totalLines ? (curLine + ' / ' + totalLines) : '当前文件处理中…';
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error('loadTasks failed:', err);
|
||||
showToast('浠诲姟鍒楄〃鍒锋柊澶辫触');
|
||||
});
|
||||
.catch(function() {});
|
||||
} else {
|
||||
runLineProgressWrap.style.display = 'none';
|
||||
}
|
||||
}
|
||||
// 缁堟€佷篃閫氳繃杞鍏滃簳锛岀‘淇?UI 涓€瀹氳閲嶇疆锛圫SE 鍙兘鍥犵綉缁滄湭鏀跺埌锛?
|
||||
// 终态也通过轮询兜底,确保 UI 一定被重置(SSE 可能因网络未收到)
|
||||
var st = (t.status || '').toLowerCase();
|
||||
if (st === 'success' || st === 'failed' || st === 'cancelled') {
|
||||
onRunTaskFinished(st);
|
||||
@@ -738,7 +732,7 @@
|
||||
|
||||
document.getElementById('btnRun').onclick = function() {
|
||||
if (selectedPaths.length === 0) {
|
||||
showToast('璇峰厛閫夋嫨 Excel 鏂囦欢鎴栨枃浠跺す');
|
||||
showToast('请先选择 Excel 文件或文件夹');
|
||||
return;
|
||||
}
|
||||
var mode = getRunMode();
|
||||
@@ -758,17 +752,16 @@
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(res) {
|
||||
if (res.success && res.task_id) {
|
||||
loadTasks();
|
||||
loadingMsg.style.display = 'none';
|
||||
pollRunTask(res.task_id);
|
||||
} else {
|
||||
stopPollAndResetRunUI();
|
||||
showToast(res.error || '杩愯澶辫触');
|
||||
showToast(res.error || '运行失败');
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
stopPollAndResetRunUI();
|
||||
showToast('璇锋眰澶辫触鎴栬秴鏃?);
|
||||
showToast('请求失败或超时');
|
||||
});
|
||||
} else {
|
||||
fetch('/api/brand/tasks', {
|
||||
@@ -780,13 +773,13 @@
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(res) {
|
||||
if (res.success) {
|
||||
showToast('浠诲姟宸叉坊鍔狅紝璇峰湪浠诲姟闃熷垪鏌ョ湅');
|
||||
showToast('任务已添加,请在任务队列查看');
|
||||
loadTasks();
|
||||
} else {
|
||||
showToast(res.error || '娣诲姞澶辫触');
|
||||
showToast(res.error || '添加失败');
|
||||
}
|
||||
})
|
||||
.catch(function() { showToast('璇锋眰澶辫触'); });
|
||||
.catch(function() { showToast('请求失败'); });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -805,8 +798,8 @@
|
||||
cachedTasks = res.items;
|
||||
list.innerHTML = res.items.map(function(t) {
|
||||
var statusClass = (t.status || 'pending').toLowerCase();
|
||||
var statusText = { pending: '绛夊緟涓?, running: '鎵ц涓?, success: '宸插畬鎴?, failed: '澶辫触', cancelled: '宸插彇娑? }[t.status] || t.status;
|
||||
var filesDesc = (t.file_paths && t.file_paths.length) ? t.file_paths.length + ' 涓枃浠? : '';
|
||||
var statusText = { pending: '等待中', running: '执行中', success: '已完成', failed: '失败', cancelled: '已取消' }[t.status] || t.status;
|
||||
var filesDesc = (t.file_paths && t.file_paths.length) ? t.file_paths.length + ' 个文件' : '';
|
||||
var total = t.progress_total || 0;
|
||||
var cur = t.progress_current || 0;
|
||||
var pct = total ? Math.min(100, (100 * cur / total)) : 0;
|
||||
@@ -815,13 +808,13 @@
|
||||
: '';
|
||||
var hasZipUrl = t.result_paths && t.result_paths.zip_url;
|
||||
var downloadHtml = hasZipUrl
|
||||
? '<a class="download js-save-zip" href="#" data-task-id="' + t.id + '">涓嬭浇缁撴灉</a>'
|
||||
? '<a class="download js-save-zip" href="#" data-task-id="' + t.id + '">下载结果</a>'
|
||||
: '<span class="download hide"></span>';
|
||||
var cancelBtn = statusClass === 'running'
|
||||
? '<button type="button" class="btn-cancel js-cancel-task" data-task-id="' + t.id + '">鍙栨秷</button>'
|
||||
? '<button type="button" class="btn-cancel js-cancel-task" data-task-id="' + t.id + '">取消</button>'
|
||||
: '';
|
||||
var deleteBtn = '<button type="button" class="btn-delete js-delete-task" data-task-id="' + t.id + '">鍒犻櫎</button>';
|
||||
var titleDesc = (t.desc && String(t.desc).trim()) ? String(t.desc).trim() : ('浠诲姟 #' + t.id);
|
||||
var deleteBtn = '<button type="button" class="btn-delete js-delete-task" data-task-id="' + t.id + '">删除</button>';
|
||||
var titleDesc = (t.desc && String(t.desc).trim()) ? String(t.desc).trim() : ('任务 #' + t.id);
|
||||
var displayDesc = titleDesc.length > 20 ? titleDesc.substring(0, 20) + '....' : titleDesc;
|
||||
return '<li class="task-item">' +
|
||||
'<div class="left">' +
|
||||
@@ -838,18 +831,15 @@
|
||||
'</div></li>';
|
||||
}).join('');
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error('loadTasks failed:', err);
|
||||
showToast('浠诲姟鍒楄〃鍒锋柊澶辫触');
|
||||
});
|
||||
.catch(function() {});
|
||||
}
|
||||
|
||||
// 鎵嬪姩鍒锋柊浠诲姟鐘舵€佹寜閽?
|
||||
// 手动刷新任务状态按钮
|
||||
var btnRefreshTasks = document.getElementById('btnRefreshTasks');
|
||||
if (btnRefreshTasks) {
|
||||
btnRefreshTasks.onclick = function () {
|
||||
loadTasks();
|
||||
showToast('浠诲姟鐘舵€佸凡鍒锋柊');
|
||||
showToast('任务状态已刷新');
|
||||
};
|
||||
}
|
||||
|
||||
@@ -864,7 +854,7 @@
|
||||
fetch('/api/brand/tasks/' + taskId + '/cancel', { method: 'POST', credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } })
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(res) {
|
||||
if (res.success) { showToast('宸插彇娑?); loadTasks(); } else { showToast(res.error || '鍙栨秷澶辫触'); }
|
||||
if (res.success) { showToast('已取消'); loadTasks(); } else { showToast(res.error || '取消失败'); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -874,7 +864,7 @@
|
||||
fetch('/api/brand/tasks/' + taskId, { method: 'DELETE', credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } })
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(res) {
|
||||
if (res.success) { showToast('宸插垹闄?); loadTasks(); } else { showToast(res.error || '鍒犻櫎澶辫触'); }
|
||||
if (res.success) { showToast('已删除'); loadTasks(); } else { showToast(res.error || '删除失败'); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -882,7 +872,7 @@
|
||||
if (!a || !a.classList || !a.classList.contains('js-save-zip')) return;
|
||||
var task = cachedTasks.filter(function(t) { return String(t.id) === String(taskId); })[0];
|
||||
if (!task || !task.result_paths || !task.result_paths.zip_url) {
|
||||
showToast('鏃犳硶鑾峰彇涓嬭浇鍦板潃');
|
||||
showToast('无法获取下载地址');
|
||||
return;
|
||||
}
|
||||
var zipUrl = task.result_paths.zip_url;
|
||||
@@ -891,21 +881,21 @@
|
||||
a.style.pointerEvents = 'none';
|
||||
var done = function(ret) {
|
||||
if (ret && ret.success) {
|
||||
showToast('宸蹭繚瀛橈細' + (ret.path || filename));
|
||||
} else if (ret && ret.error && ret.error !== '鐢ㄦ埛鍙栨秷') {
|
||||
showToast('淇濆瓨澶辫触锛? + ret.error);
|
||||
showToast('已保存:' + (ret.path || filename));
|
||||
} else if (ret && ret.error && ret.error !== '用户取消') {
|
||||
showToast('保存失败:' + ret.error);
|
||||
}
|
||||
a.style.pointerEvents = '';
|
||||
};
|
||||
try {
|
||||
var ret = api.save_file_from_url(zipUrl, filename);
|
||||
if (ret && typeof ret.then === 'function') {
|
||||
ret.then(done).catch(function(err) { showToast('淇濆瓨澶辫触锛? + (err && err.message || err)); a.style.pointerEvents = ''; });
|
||||
ret.then(done).catch(function(err) { showToast('保存失败:' + (err && err.message || err)); a.style.pointerEvents = ''; });
|
||||
} else {
|
||||
done(ret);
|
||||
}
|
||||
} catch (err) {
|
||||
showToast('淇濆瓨澶辫触锛? + (err.message || err));
|
||||
showToast('保存失败:' + (err.message || err));
|
||||
a.style.pointerEvents = '';
|
||||
}
|
||||
} else {
|
||||
@@ -914,7 +904,7 @@
|
||||
});
|
||||
|
||||
loadTasks();
|
||||
setInterval(loadTasks, 5000);
|
||||
// setInterval(loadTasks, 10000);
|
||||
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('pywebviewready', function() {
|
||||
@@ -926,4 +916,3 @@
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user