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')}`;
|
||||
|
||||
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="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>
|
||||
`;
|
||||
}).join('');
|
||||
|
|
@ -854,18 +854,18 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
|
||||
function renderFolderListItem({ id, name, count, system }) {
|
||||
const isActive = historyUIState.activeFolder === id;
|
||||
const baseClasses = 'group flex items-center justify-between px-2 py-1.5 rounded-lg 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 baseClasses = 'group flex items-center justify-between px-2 py-1.5 rounded-[5px] border transition-colors';
|
||||
const activeClasses = isActive ? ' bg-[#E4E6EA] text-[#000F33]' : 'border-transparent hover:bg-gray-100 text-[#666666]';
|
||||
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 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>
|
||||
${countBadge}
|
||||
</button>`;
|
||||
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">
|
||||
<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>
|
||||
</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="删除">
|
||||
|
|
@ -1059,10 +1059,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
preserve: 'preserve',
|
||||
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_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');
|
||||
if (historyListElement) {
|
||||
historyListElement.addEventListener('click', handleHistoryListAction);
|
||||
|
|
@ -1222,39 +1222,36 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
const escapedRecordId = escapeAttr(record.id || '');
|
||||
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="配置导出">
|
||||
<iconify-icon icon="carbon:share" width="18"></iconify-icon>
|
||||
导出
|
||||
</button>`;
|
||||
const downloadBtnHtml = `
|
||||
<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>`;
|
||||
const recordDisplayName = record.name || relativePathLabel || record.id || '历史记录';
|
||||
const escapedRecordNameAttr = escapeAttr(recordDisplayName);
|
||||
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="删除记录">
|
||||
<iconify-icon icon="carbon:trash-can" width="18"></iconify-icon>
|
||||
删除
|
||||
</button>`;
|
||||
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}')">
|
||||
<iconify-icon icon="carbon:document-view" width="18"></iconify-icon>
|
||||
<button type="button" class="inline-flex items-center gap-2 px-5 py-2 bg-[#000F33] text-white rounded-md " onclick="showHistoryDetail('${escapedRecordId}')">
|
||||
<span>开始阅读</span>
|
||||
</button>`;
|
||||
|
||||
const containerClasses = withinBatch
|
||||
? 'border border-slate-200 rounded-xl p-3 bg-white shadow-sm 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-3 bg-[#F8F9FA] hover:border-blue-200 transition'
|
||||
: 'rounded-[20px] p-4 bg-[#F8F9FA] hover:border-blue-200 transition';
|
||||
|
||||
return `
|
||||
<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-3 md:flex-row md:items-start md:justify-between md:gap-4">
|
||||
<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}
|
||||
</div>
|
||||
<div class="text-xs text-gray-500 mt-1">
|
||||
${timeLabel}${targetLang ? ` · 语言:${escapeHtml(targetLang)}` : ''}
|
||||
</div>
|
||||
|
||||
${(ocrLabel || (transLabel && transLabel !== '未翻译')) ? `
|
||||
<div class="text-xs text-gray-500">
|
||||
${ocrLabel ? `OCR:${ocrLabel}` : ''}
|
||||
|
|
@ -1269,7 +1266,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
</div>
|
||||
<div class="hidden md:flex flex-wrap gap-2 text-xs text-gray-600 justify-end md:text-sm items-center">
|
||||
${exportBtnHtml}
|
||||
${startReadingBtnHtml}
|
||||
${downloadBtnHtml}
|
||||
${deleteBtnHtml}
|
||||
</div>
|
||||
|
|
@ -1282,7 +1278,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
</summary>
|
||||
<div class="mt-2 flex flex-wrap gap-2 text-xs text-gray-600">
|
||||
${exportBtnHtml}
|
||||
${startReadingBtnHtml}
|
||||
${downloadBtnHtml}
|
||||
${deleteBtnHtml}
|
||||
</div>
|
||||
|
|
@ -1290,10 +1285,16 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
</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="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-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>
|
||||
</div>
|
||||
</div>
|
||||
${renderExportConfigPanel({
|
||||
id: configId,
|
||||
|
|
@ -1501,22 +1502,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
|
||||
function buildStatusBadge(status) {
|
||||
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),改为“预览中,无翻译块”
|
||||
if (status.success === 0) {
|
||||
// 结构化翻译下,将提示文案替换为“PDF对照”
|
||||
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) {
|
||||
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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue