style(history): 调整历史列表与操作区样式
This commit is contained in:
parent
8d5af9799c
commit
f0fb54e41f
|
|
@ -71,10 +71,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
const timeStr = `${timeObj.getMonth() + 1}/${timeObj.getDate()} ${String(timeObj.getHours()).padStart(2, '0')}:${String(timeObj.getMinutes()).padStart(2, '0')}`;
|
const timeStr = `${timeObj.getMonth() + 1}/${timeObj.getDate()} ${String(timeObj.getHours()).padStart(2, '0')}:${String(timeObj.getMinutes()).padStart(2, '0')}`;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="group flex items-center gap-2 px-2 py-1.5 text-[13px] text-[#000f33] hover:bg-[#000f33] hover:text-[#ffffff] transition-colors cursor-pointer rounded-md mx-2 mb-0.5" onclick="showHistoryDetail('${safeId}')" title="${name}\n${timeObj.toLocaleString()}">
|
<div class="group h-[58px] flex flex-col px-[15px] py-[10px] text-[13px] text-[#666666] hover:bg-[#E6E7EB] transition-colors cursor-pointer rounded-md mb-0.5" onclick="showHistoryDetail('${safeId}')" title="${name}\n${timeObj.toLocaleString()}">
|
||||||
|
|
||||||
<span class="truncate flex-1">${name}</span>
|
<span class="truncate flex-1">${name}</span>
|
||||||
<span class="text-[10px] text-slate-400 flex-shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">${timeStr}</span>
|
<span class="text-[12px] text-[#999999] flex-shrink-0 ">${timeStr}</span>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
@ -854,18 +854,18 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
function renderFolderListItem({ id, name, count, system }) {
|
function renderFolderListItem({ id, name, count, system }) {
|
||||||
const isActive = historyUIState.activeFolder === id;
|
const isActive = historyUIState.activeFolder === id;
|
||||||
const baseClasses = 'group flex items-center justify-between px-2 py-1.5 rounded-lg border transition-colors';
|
const baseClasses = 'group flex items-center justify-between px-2 py-1.5 rounded-[5px] border transition-colors';
|
||||||
const activeClasses = isActive ? 'border-blue-200 bg-blue-50 text-blue-600' : 'border-transparent hover:bg-gray-100 text-gray-700';
|
const activeClasses = isActive ? ' bg-[#E4E6EA] text-[#000F33]' : 'border-transparent hover:bg-gray-100 text-[#666666]';
|
||||||
const title = escapeAttr(name || '未命名');
|
const title = escapeAttr(name || '未命名');
|
||||||
const countBadge = `<span class="ml-2 inline-flex min-w-[1.5rem] justify-center rounded-full bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium text-gray-500">${typeof count === 'number' ? count : 0}</span>`;
|
const countBadge = `<span class="ml-2 inline-flex min-w-[1.5rem] justify-center rounded-full bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium text-gray-500">${typeof count === 'number' ? count : 0}</span>`;
|
||||||
const selectButton = `
|
const selectButton = `
|
||||||
<button type="button" class="flex-1 text-left text-sm font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-300 focus-visible:ring-offset-1" data-folder-action="select" data-folder-id="${escapeAttr(id)}" title="查看${title}">
|
<button type="button" class="flex items-center justify-between flex-1 text-left text-sm font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-300 focus-visible:ring-offset-1" data-folder-action="select" data-folder-id="${escapeAttr(id)}" title="查看${title}">
|
||||||
<span>${escapeHtml(name || '未命名')}</span>
|
<span>${escapeHtml(name || '未命名')}</span>
|
||||||
${countBadge}
|
${countBadge}
|
||||||
</button>`;
|
</button>`;
|
||||||
const actionButtons = system ? '' : `
|
const actionButtons = system ? '' : `
|
||||||
<div class="ml-2 flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100">
|
<div class="ml-2 flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100">
|
||||||
<button type="button" class="rounded p-1 text-gray-400 hover:text-blue-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-300" data-folder-action="rename" data-folder-id="${escapeAttr(id)}" title="重命名">
|
<button type="button" class="rounded p-1 text-gray-400 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-300" data-folder-action="rename" data-folder-id="${escapeAttr(id)}" title="重命名">
|
||||||
<iconify-icon icon="carbon:edit" width="14"></iconify-icon>
|
<iconify-icon icon="carbon:edit" width="14"></iconify-icon>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="rounded p-1 text-gray-400 hover:text-red-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-red-300" data-folder-action="delete" data-folder-id="${escapeAttr(id)}" title="删除">
|
<button type="button" class="rounded p-1 text-gray-400 hover:text-red-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-red-300" data-folder-action="delete" data-folder-id="${escapeAttr(id)}" title="删除">
|
||||||
|
|
@ -1059,10 +1059,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
preserve: 'preserve',
|
preserve: 'preserve',
|
||||||
flat: 'flat'
|
flat: 'flat'
|
||||||
};
|
};
|
||||||
const ICON_BUTTON_CLASS = 'inline-flex items-center justify-center w-9 h-9 rounded-full border border-slate-200 bg-white text-gray-500 hover:text-blue-600 hover:border-blue-200 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-300 focus:ring-offset-1';
|
const ICON_BUTTON_CLASS = 'inline-flex items-center justify-center w-9 h-9 text-gray-500 hover:text-[#000F33] hover:border-[#E4E6EA]transition-colors focus:outline-none focus:ring-2 focus:ring-blue-300 focus:ring-offset-1';
|
||||||
const ICON_BUTTON_DANGER_EXTRA = 'hover:text-red-500 hover:border-red-200 focus:ring-red-300';
|
const ICON_BUTTON_DANGER_EXTRA = 'hover:text-red-500 hover:border-red-200 focus:ring-red-300';
|
||||||
const ICON_BUTTON_SUCCESS_EXTRA = 'hover:text-emerald-500 hover:border-emerald-200 focus:ring-emerald-300';
|
const ICON_BUTTON_SUCCESS_EXTRA = '';
|
||||||
|
// hover:text-emerald-500 hover:border-emerald-200 focus:ring-emerald-300
|
||||||
const historyListElement = document.getElementById('historyList');
|
const historyListElement = document.getElementById('historyList');
|
||||||
if (historyListElement) {
|
if (historyListElement) {
|
||||||
historyListElement.addEventListener('click', handleHistoryListAction);
|
historyListElement.addEventListener('click', handleHistoryListAction);
|
||||||
|
|
@ -1222,39 +1222,36 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
const escapedRecordId = escapeAttr(record.id || '');
|
const escapedRecordId = escapeAttr(record.id || '');
|
||||||
const exportBtnHtml = `
|
const exportBtnHtml = `
|
||||||
<button type="button" class="${ICON_BUTTON_CLASS}" data-history-action="open-record-export" data-record-id="${escapeAttr(record.id)}" data-target="${configId}" aria-label="配置导出" title="配置导出">
|
<button type="button" class="${ICON_BUTTON_CLASS}" data-history-action="open-record-export" data-record-id="${escapeAttr(record.id)}" data-target="${configId}" aria-label="配置导出" title="配置导出">
|
||||||
<iconify-icon icon="carbon:share" width="18"></iconify-icon>
|
导出
|
||||||
</button>`;
|
</button>`;
|
||||||
const downloadBtnHtml = `
|
const downloadBtnHtml = `
|
||||||
<button type="button" class="${ICON_BUTTON_CLASS} ${ICON_BUTTON_SUCCESS_EXTRA}" onclick="downloadHistoryRecord('${escapedRecordId}')" aria-label="下载记录" title="下载记录">
|
<button type="button" class="${ICON_BUTTON_CLASS} ${ICON_BUTTON_SUCCESS_EXTRA}" onclick="downloadHistoryRecord('${escapedRecordId}')" aria-label="下载记录" title="下载记录">
|
||||||
<iconify-icon icon="carbon:download" width="18"></iconify-icon>
|
下载
|
||||||
</button>`;
|
</button>`;
|
||||||
const recordDisplayName = record.name || relativePathLabel || record.id || '历史记录';
|
const recordDisplayName = record.name || relativePathLabel || record.id || '历史记录';
|
||||||
const escapedRecordNameAttr = escapeAttr(recordDisplayName);
|
const escapedRecordNameAttr = escapeAttr(recordDisplayName);
|
||||||
const deleteBtnHtml = withinBatch ? '' : `
|
const deleteBtnHtml = withinBatch ? '' : `
|
||||||
<button type="button" class="${ICON_BUTTON_CLASS} ${ICON_BUTTON_DANGER_EXTRA}" data-history-action="delete-record" data-record-id="${escapedRecordId}" data-record-name="${escapedRecordNameAttr}" aria-label="删除记录" title="删除记录">
|
<button type="button" class="${ICON_BUTTON_CLASS} ${ICON_BUTTON_DANGER_EXTRA}" data-history-action="delete-record" data-record-id="${escapedRecordId}" data-record-name="${escapedRecordNameAttr}" aria-label="删除记录" title="删除记录">
|
||||||
<iconify-icon icon="carbon:trash-can" width="18"></iconify-icon>
|
删除
|
||||||
</button>`;
|
</button>`;
|
||||||
const startReadingBtnHtml = `
|
const startReadingBtnHtml = `
|
||||||
<button type="button" class="inline-flex items-center gap-2 px-3 py-1.5 bg-blue-600 text-white rounded-md shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1" onclick="showHistoryDetail('${escapedRecordId}')">
|
<button type="button" class="inline-flex items-center gap-2 px-5 py-2 bg-[#000F33] text-white rounded-md " onclick="showHistoryDetail('${escapedRecordId}')">
|
||||||
<iconify-icon icon="carbon:document-view" width="18"></iconify-icon>
|
|
||||||
<span>开始阅读</span>
|
<span>开始阅读</span>
|
||||||
</button>`;
|
</button>`;
|
||||||
|
|
||||||
const containerClasses = withinBatch
|
const containerClasses = withinBatch
|
||||||
? 'border border-slate-200 rounded-xl p-3 bg-white shadow-sm hover:border-blue-200 transition'
|
? 'rounded-[20px] p-3 bg-[#F8F9FA] hover:border-blue-200 transition'
|
||||||
: 'border border-slate-200 rounded-xl p-4 bg-white shadow-sm hover:border-blue-200 hover:shadow-md transition';
|
: 'rounded-[20px] p-4 bg-[#F8F9FA] hover:border-blue-200 transition';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="${containerClasses}" id="history-item-${safeId}" data-record-id="${escapeAttr(record.id)}">
|
<div class="${containerClasses}" id="history-item-${safeId}" data-record-id="${escapeAttr(record.id)}">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between md:gap-4">
|
<div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between md:gap-4">
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
<div class="text-sm font-semibold text-gray-800 flex flex-wrap items-center gap-2 break-all">
|
<div class="text-sm text-[#333333] flex flex-wrap items-center gap-2 break-all">
|
||||||
<span>${escapeHtml(record.name || '未命名')}</span> ${statusBadge}
|
<span>${escapeHtml(record.name || '未命名')}</span> ${statusBadge}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs text-gray-500 mt-1">
|
|
||||||
${timeLabel}${targetLang ? ` · 语言:${escapeHtml(targetLang)}` : ''}
|
|
||||||
</div>
|
|
||||||
${(ocrLabel || (transLabel && transLabel !== '未翻译')) ? `
|
${(ocrLabel || (transLabel && transLabel !== '未翻译')) ? `
|
||||||
<div class="text-xs text-gray-500">
|
<div class="text-xs text-gray-500">
|
||||||
${ocrLabel ? `OCR:${ocrLabel}` : ''}
|
${ocrLabel ? `OCR:${ocrLabel}` : ''}
|
||||||
|
|
@ -1269,7 +1266,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden md:flex flex-wrap gap-2 text-xs text-gray-600 justify-end md:text-sm items-center">
|
<div class="hidden md:flex flex-wrap gap-2 text-xs text-gray-600 justify-end md:text-sm items-center">
|
||||||
${exportBtnHtml}
|
${exportBtnHtml}
|
||||||
${startReadingBtnHtml}
|
|
||||||
${downloadBtnHtml}
|
${downloadBtnHtml}
|
||||||
${deleteBtnHtml}
|
${deleteBtnHtml}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1282,7 +1278,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
</summary>
|
</summary>
|
||||||
<div class="mt-2 flex flex-wrap gap-2 text-xs text-gray-600">
|
<div class="mt-2 flex flex-wrap gap-2 text-xs text-gray-600">
|
||||||
${exportBtnHtml}
|
${exportBtnHtml}
|
||||||
${startReadingBtnHtml}
|
|
||||||
${downloadBtnHtml}
|
${downloadBtnHtml}
|
||||||
${deleteBtnHtml}
|
${deleteBtnHtml}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1290,10 +1285,16 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs text-gray-600 break-words">OCR:${ocrSnippet}</div>
|
<div class="text-xs text-gray-600 break-words">OCR:${ocrSnippet}</div>
|
||||||
<div class="text-xs text-gray-600 break-words">翻译:${translationSnippet}</div>
|
<div class="text-xs text-gray-600 break-words">翻译:${translationSnippet}</div>
|
||||||
<div class="flex flex-wrap items-center gap-2 text-xs text-gray-600 mt-2">
|
<div class="flex flex-wrap justify-between items-center text-xs text-gray-600">
|
||||||
|
<div class="text-xs text-gray-500 mt-1">
|
||||||
|
${timeLabel}${targetLang ? ` · 语言:${escapeHtml(targetLang)}` : ''}
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap justify-between items-center gap-3">
|
||||||
<button id="retry-failed-btn-${safeId}" onclick="retryTranslateRecord('${record.id}','failed')" class="px-2 py-1 border border-gray-200 rounded hover:bg-gray-100 ${retryDisabled}">重试失败段</button>
|
<button id="retry-failed-btn-${safeId}" onclick="retryTranslateRecord('${record.id}','failed')" class="px-2 py-1 border border-gray-200 rounded hover:bg-gray-100 ${retryDisabled}">重试失败段</button>
|
||||||
<button id="retry-all-btn-${safeId}" onclick="retryTranslateRecord('${record.id}','all')" class="px-2 py-1 border border-gray-200 rounded hover:bg-gray-100">重新翻译全部</button>
|
<button id="retry-all-btn-${safeId}" onclick="retryTranslateRecord('${record.id}','all')" class="px-2 py-1 border border-gray-200 rounded hover:bg-gray-100">重新翻译全部</button>
|
||||||
|
${startReadingBtnHtml}
|
||||||
<span id="retry-status-${safeId}" class="text-xs text-gray-500"></span>
|
<span id="retry-status-${safeId}" class="text-xs text-gray-500"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
${renderExportConfigPanel({
|
${renderExportConfigPanel({
|
||||||
id: configId,
|
id: configId,
|
||||||
|
|
@ -1501,22 +1502,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
function buildStatusBadge(status) {
|
function buildStatusBadge(status) {
|
||||||
if (!status || status.total === 0) {
|
if (!status || status.total === 0) {
|
||||||
return '<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-gray-100 text-gray-500">未分块</span>';
|
return '<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-[#ffffff] text-gray-500">未分块</span>';
|
||||||
}
|
}
|
||||||
// 若没有任何成功块(0/total),改为“预览中,无翻译块”
|
// 若没有任何成功块(0/total),改为“预览中,无翻译块”
|
||||||
if (status.success === 0) {
|
if (status.success === 0) {
|
||||||
// 结构化翻译下,将提示文案替换为“PDF对照”
|
// 结构化翻译下,将提示文案替换为“PDF对照”
|
||||||
if (status.isStructured) {
|
if (status.isStructured) {
|
||||||
return '<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-blue-100 text-blue-700">PDF对照</span>';
|
return '<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-[#ffffff] text-blue-700">PDF对照</span>';
|
||||||
}
|
}
|
||||||
return '<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-gray-100 text-gray-600">预览中,无翻译块</span>';
|
return '<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-[#ffffff] text-gray-600">预览中,无翻译块</span>';
|
||||||
}
|
}
|
||||||
// 有成功也有失败 → 部分失败
|
// 有成功也有失败 → 部分失败
|
||||||
if (status.failed > 0) {
|
if (status.failed > 0) {
|
||||||
return `<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-amber-100 text-amber-700">部分失败 ${status.success}/${status.total}</span>`;
|
return `<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-[#ffffff] text-amber-700">部分失败 ${status.success}/${status.total}</span>`;
|
||||||
}
|
}
|
||||||
// 全部成功
|
// 全部成功
|
||||||
return `<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-green-100 text-green-700">完成 ${status.success}/${status.total}</span>`;
|
return `<span class="ml-2 inline-block text-[11px] px-2 py-0.5 rounded bg-[#ffffff] text-green-700">完成 ${status.success}/${status.total}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSnippetText(text) {
|
function buildSnippetText(text) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue