```
chore(config): 更新.gitignore文件以忽略数据库相关文件 添加了data/目录、SQLite数据库文件及相关临时文件到.gitignore中, 避免敏感数据和临时文件被提交到版本控制系统。 ```
This commit is contained in:
@@ -534,6 +534,13 @@
|
||||
<div style="font-size:13px;color:#888;" id="taskSummary"></div>
|
||||
</div>
|
||||
|
||||
<div class="toolbar" style="margin-bottom: 14px;">
|
||||
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;width:100%;">
|
||||
<input type="text" id="taskFilterCity" placeholder="搜索城市" oninput="onTaskFilterChange()" style="max-width:220px;">
|
||||
<input type="text" id="taskFilterPlate" placeholder="搜索板块" oninput="onTaskFilterChange()" style="max-width:220px;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -542,17 +549,18 @@
|
||||
<th>提示词</th>
|
||||
<th>模型</th>
|
||||
<th>状态</th>
|
||||
<th>浏览器</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tasksTbody">
|
||||
<tr>
|
||||
<td colspan="7" class="empty-state">加载中...</td>
|
||||
<td colspan="6" class="empty-state">加载中...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="tasksPagination" style="text-align:center;margin-top:16px;"></div>
|
||||
|
||||
<div id="batchRunStatus" class="status-box status-info" style="display:none;"></div>
|
||||
</div>
|
||||
|
||||
@@ -582,13 +590,6 @@
|
||||
<label>服务地址 (baseUrl)</label>
|
||||
<input type="text" id="cfgBaseUrl" placeholder="http://192.168.3.65:18625">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>useBrowser</label>
|
||||
<select id="cfgUseBrowser">
|
||||
<option value="false">false</option>
|
||||
<option value="true">true</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
@@ -698,11 +699,6 @@
|
||||
<input type="checkbox" id="taskEnabled" checked> 启用
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="checkbox" id="taskUseBrowser"> 打开浏览器
|
||||
</label>
|
||||
</div>
|
||||
<div style="display:flex;gap:10px;justify-content:flex-end;">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeTaskModal()">取消</button>
|
||||
<button type="submit" class="btn btn-primary">保存</button>
|
||||
@@ -713,6 +709,8 @@
|
||||
|
||||
<script>
|
||||
let tasksList = [];
|
||||
let currentTasksPage = 1;
|
||||
const tasksPageSize = 10;
|
||||
let currentResultsPage = 1;
|
||||
|
||||
// ===== Tab 切换 =====
|
||||
@@ -733,30 +731,58 @@
|
||||
const res = await fetch('/api/tasks');
|
||||
const json = await res.json();
|
||||
tasksList = json.data || [];
|
||||
currentTasksPage = 1;
|
||||
renderTasks();
|
||||
} catch (e) {
|
||||
console.error('加载任务失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function getFilteredTasks() {
|
||||
const cityKeyword = document.getElementById('taskFilterCity').value.trim().toLowerCase();
|
||||
const plateKeyword = document.getElementById('taskFilterPlate').value.trim().toLowerCase();
|
||||
|
||||
return tasksList.filter(t => {
|
||||
const city = (t.city || '').toLowerCase();
|
||||
const plate = (t.plateName || '').toLowerCase();
|
||||
const matchCity = !cityKeyword || city.includes(cityKeyword);
|
||||
const matchPlate = !plateKeyword || plate.includes(plateKeyword);
|
||||
return matchCity && matchPlate;
|
||||
});
|
||||
}
|
||||
|
||||
function onTaskFilterChange() {
|
||||
currentTasksPage = 1;
|
||||
renderTasks();
|
||||
}
|
||||
|
||||
function renderTasks() {
|
||||
const tbody = document.getElementById('tasksTbody');
|
||||
const enabled = tasksList.filter(t => t.enabled).length;
|
||||
document.getElementById('taskSummary').textContent = `共 ${tasksList.length} 个任务,${enabled} 个启用`;
|
||||
const filtered = getFilteredTasks();
|
||||
const totalPages = Math.max(1, Math.ceil(filtered.length / tasksPageSize));
|
||||
if (currentTasksPage > totalPages) currentTasksPage = totalPages;
|
||||
|
||||
if (tasksList.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="7" class="empty-state">暂无任务,点击「新增任务」添加</td></tr>';
|
||||
const startIdx = (currentTasksPage - 1) * tasksPageSize;
|
||||
const pageData = filtered.slice(startIdx, startIdx + tasksPageSize);
|
||||
|
||||
document.getElementById('taskSummary').textContent =
|
||||
`共 ${tasksList.length} 个任务,${enabled} 个启用,筛选后 ${filtered.length} 个`;
|
||||
|
||||
if (filtered.length === 0) {
|
||||
const hasKeyword = document.getElementById('taskFilterCity').value.trim() || document.getElementById('taskFilterPlate').value.trim();
|
||||
tbody.innerHTML = `<tr><td colspan="6" class="empty-state">${hasKeyword ? '没有匹配的任务' : '暂无任务,点击「新增任务」添加'}</td></tr>`;
|
||||
document.getElementById('tasksPagination').innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = tasksList.map(t => `
|
||||
tbody.innerHTML = pageData.map(t => `
|
||||
<tr>
|
||||
<td><strong>${t.city || '-'}</strong></td>
|
||||
<td>${t.plateName || '-'}</td>
|
||||
<td class="prompt-cell" title="${(t.prompt || '').replace(/"/g, '"')}">${t.prompt || '-'}</td>
|
||||
<td><code style="font-family:'Fira Code','Cascadia Code',monospace;font-size:12px;">${t.mode || 'qwen3.5-plus'}</code></td>
|
||||
<td><span class="tag ${t.enabled ? 'tag-on' : 'tag-off'}">${t.enabled ? '启用' : '禁用'}</span></td>
|
||||
<td><span class="tag ${t.useBrowser === true ? 'tag-on' : (t.useBrowser === false ? 'tag-off' : '')}">${t.useBrowser === true ? '打开' : (t.useBrowser === false ? '关闭' : '继承全局')}</span></td>
|
||||
<td>
|
||||
<button class="btn btn-primary btn-sm" onclick="openTaskModal('${t.id}')">编辑</button>
|
||||
<button class="btn btn-success btn-sm" onclick="runSingleTask('${t.id}', this)">运行</button>
|
||||
@@ -765,11 +791,59 @@
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
|
||||
renderTasksPagination(filtered.length, totalPages);
|
||||
}
|
||||
|
||||
function renderTasksPagination(totalFiltered, totalPages) {
|
||||
const paginationDiv = document.getElementById('tasksPagination');
|
||||
|
||||
if (totalPages <= 1) {
|
||||
paginationDiv.innerHTML = totalFiltered > 0
|
||||
? `<span style="font-size:13px;color:#888;">共 ${totalFiltered} 条</span>`
|
||||
: '';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '';
|
||||
html += `<button class="btn btn-secondary btn-sm" onclick="goTasksPage(${currentTasksPage - 1})" ${currentTasksPage <= 1 ? 'disabled' : ''}>上一页</button>`;
|
||||
|
||||
const maxVisiblePages = 7;
|
||||
let startPage = Math.max(1, currentTasksPage - Math.floor(maxVisiblePages / 2));
|
||||
let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);
|
||||
if (endPage - startPage < maxVisiblePages - 1) {
|
||||
startPage = Math.max(1, endPage - maxVisiblePages + 1);
|
||||
}
|
||||
|
||||
if (startPage > 1) {
|
||||
html += `<button class="btn btn-sm btn-secondary" onclick="goTasksPage(1)" style="margin:0 2px;">1</button>`;
|
||||
if (startPage > 2) html += `<span style="color:#888;font-size:13px;margin:0 4px;">...</span>`;
|
||||
}
|
||||
|
||||
for (let i = startPage; i <= endPage; i++) {
|
||||
html += `<button class="btn btn-sm ${i === currentTasksPage ? 'btn-primary' : 'btn-secondary'}" onclick="goTasksPage(${i})" style="margin:0 2px;">${i}</button>`;
|
||||
}
|
||||
|
||||
if (endPage < totalPages) {
|
||||
if (endPage < totalPages - 1) html += `<span style="color:#888;font-size:13px;margin:0 4px;">...</span>`;
|
||||
html += `<button class="btn btn-sm btn-secondary" onclick="goTasksPage(${totalPages})" style="margin:0 2px;">${totalPages}</button>`;
|
||||
}
|
||||
|
||||
html += `<button class="btn btn-secondary btn-sm" onclick="goTasksPage(${currentTasksPage + 1})" ${currentTasksPage >= totalPages ? 'disabled' : ''}>下一页</button>`;
|
||||
html += `<span style="font-size:13px;color:#888;margin-left:8px;">第 ${currentTasksPage}/${totalPages} 页,共 ${totalFiltered} 条</span>`;
|
||||
|
||||
paginationDiv.innerHTML = html;
|
||||
}
|
||||
|
||||
function goTasksPage(page) {
|
||||
const totalPages = Math.max(1, Math.ceil(getFilteredTasks().length / tasksPageSize));
|
||||
if (page < 1 || page > totalPages) return;
|
||||
currentTasksPage = page;
|
||||
renderTasks();
|
||||
}
|
||||
|
||||
function openTaskModal(id) {
|
||||
const item = id ? tasksList.find(t => t.id === id) : null;
|
||||
const globalUseBrowser = document.getElementById('cfgUseBrowser').value === 'true';
|
||||
document.getElementById('taskModalTitle').textContent = item ? '编辑任务' : '新增任务';
|
||||
document.getElementById('taskEditId').value = item ? item.id : '';
|
||||
document.getElementById('taskCity').value = item ? item.city : '';
|
||||
@@ -785,9 +859,6 @@
|
||||
}
|
||||
modeSelect.value = modeValue;
|
||||
document.getElementById('taskEnabled').checked = item ? item.enabled : true;
|
||||
document.getElementById('taskUseBrowser').checked = item
|
||||
? (typeof item.useBrowser === 'boolean' ? item.useBrowser : globalUseBrowser)
|
||||
: globalUseBrowser;
|
||||
document.getElementById('taskModal').classList.add('show');
|
||||
}
|
||||
|
||||
@@ -804,7 +875,6 @@
|
||||
prompt: document.getElementById('taskPrompt').value.trim(),
|
||||
mode: document.getElementById('taskMode').value.trim() || 'qwen3.5-plus',
|
||||
enabled: document.getElementById('taskEnabled').checked,
|
||||
useBrowser: document.getElementById('taskUseBrowser').checked,
|
||||
};
|
||||
try {
|
||||
const url = id ? `/api/tasks/${id}` : '/api/tasks';
|
||||
@@ -1067,7 +1137,6 @@
|
||||
|
||||
// Agent
|
||||
document.getElementById('cfgBaseUrl').value = cfg.agent?.baseUrl || '';
|
||||
document.getElementById('cfgUseBrowser').value = String(cfg.agent?.useBrowser ?? false);
|
||||
document.getElementById('cfgPollInterval').value = cfg.agent?.pollInterval || 3000;
|
||||
document.getElementById('cfgTimeout').value = cfg.agent?.timeout || 300000;
|
||||
|
||||
@@ -1098,19 +1167,12 @@
|
||||
|
||||
async function saveSettings() {
|
||||
try {
|
||||
// 先获取当前完整配置(保留 tasks)
|
||||
const curRes = await fetch('/api/config');
|
||||
const curJson = await curRes.json();
|
||||
const curCfg = curJson.data || {};
|
||||
|
||||
const cfg = {
|
||||
agent: {
|
||||
baseUrl: document.getElementById('cfgBaseUrl').value.trim(),
|
||||
useBrowser: document.getElementById('cfgUseBrowser').value === 'true',
|
||||
pollInterval: parseInt(document.getElementById('cfgPollInterval').value) || 3000,
|
||||
timeout: parseInt(document.getElementById('cfgTimeout').value) || 300000,
|
||||
},
|
||||
tasks: curCfg.tasks || [],
|
||||
scheduler: {
|
||||
enabled: document.getElementById('cfgSchedulerEnabled').value === 'true',
|
||||
cronTime: document.getElementById('cfgCronTime').value.trim() || '0 9 * * *',
|
||||
@@ -1159,4 +1221,4 @@
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user