feat: 优化历史记录样式
This commit is contained in:
@@ -490,6 +490,26 @@ ipcMain.handle('open-url', async (_event, url: string) => {
|
||||
}
|
||||
})
|
||||
|
||||
// 打开文件
|
||||
ipcMain.handle('open-file', async (_event, filePath: string) => {
|
||||
try {
|
||||
await shell.openPath(filePath)
|
||||
} catch (error) {
|
||||
console.error('打开文件失败:', error)
|
||||
throw error
|
||||
}
|
||||
})
|
||||
|
||||
// 显示文件所在目录并选中文件
|
||||
ipcMain.handle('show-item-in-folder', async (_event, filePath: string) => {
|
||||
try {
|
||||
shell.showItemInFolder(filePath)
|
||||
} catch (error) {
|
||||
console.error('显示文件所在目录失败:', error)
|
||||
throw error
|
||||
}
|
||||
})
|
||||
|
||||
// 环境检查
|
||||
ipcMain.handle('check-environment', async () => {
|
||||
const appRoot = getAppRoot()
|
||||
|
||||
@@ -50,6 +50,10 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
saveLogsToFile: (logs: string) => ipcRenderer.invoke('save-logs-to-file', logs),
|
||||
loadLogsFromFile: () => ipcRenderer.invoke('load-logs-from-file'),
|
||||
|
||||
// 文件系统操作
|
||||
openFile: (filePath: string) => ipcRenderer.invoke('open-file', filePath),
|
||||
showItemInFolder: (filePath: string) => ipcRenderer.invoke('show-item-in-folder', filePath),
|
||||
|
||||
// 监听下载进度
|
||||
onDownloadProgress: (callback: (progress: any) => void) => {
|
||||
ipcRenderer.on('download-progress', (_, progress) => callback(progress))
|
||||
|
||||
4
frontend/src/types/electron.d.ts
vendored
4
frontend/src/types/electron.d.ts
vendored
@@ -40,6 +40,10 @@ export interface ElectronAPI {
|
||||
saveLogsToFile: (logs: string) => Promise<void>
|
||||
loadLogsFromFile: () => Promise<string | null>
|
||||
|
||||
// 文件系统操作
|
||||
openFile: (filePath: string) => Promise<void>
|
||||
showItemInFolder: (filePath: string) => Promise<void>
|
||||
|
||||
// 监听下载进度
|
||||
onDownloadProgress: (callback: (progress: any) => void) => void
|
||||
removeDownloadProgressListener: () => void
|
||||
|
||||
@@ -90,32 +90,6 @@
|
||||
<div v-else class="history-layout">
|
||||
<!-- 左侧日期列表 -->
|
||||
<div class="date-sidebar">
|
||||
<!-- <!– 数据总览 –>-->
|
||||
<!-- <div class="overview-section">-->
|
||||
<!-- <a-card size="small" title="数据总览" class="overview-card">-->
|
||||
<!-- <div class="overview-stats">-->
|
||||
<!-- <a-statistic-->
|
||||
<!-- title="总公招数"-->
|
||||
<!-- :value="totalOverview.totalRecruit"-->
|
||||
<!-- :value-style="{ color: '#1890ff', fontSize: '18px' }"-->
|
||||
<!-- >-->
|
||||
<!-- <template #prefix>-->
|
||||
<!-- <UserOutlined />-->
|
||||
<!-- </template>-->
|
||||
<!-- </a-statistic>-->
|
||||
<!-- <a-statistic-->
|
||||
<!-- title="总掉落数"-->
|
||||
<!-- :value="totalOverview.totalDrop"-->
|
||||
<!-- :value-style="{ color: '#52c41a', fontSize: '18px' }"-->
|
||||
<!-- >-->
|
||||
<!-- <template #prefix>-->
|
||||
<!-- <GiftOutlined />-->
|
||||
<!-- </template>-->
|
||||
<!-- </a-statistic>-->
|
||||
<!-- </div>-->
|
||||
<!-- </a-card>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- 日期折叠列表 -->
|
||||
<div class="date-list">
|
||||
<a-collapse v-model:activeKey="activeKeys" ghost>
|
||||
@@ -187,7 +161,21 @@
|
||||
<div class="record-info">
|
||||
<div class="record-header">
|
||||
<span class="record-time">{{ record.date }}</span>
|
||||
<a-tooltip
|
||||
v-if="record.status === '异常' && selectedUserData?.error_info && selectedUserData.error_info[record.date]"
|
||||
:title="selectedUserData.error_info[record.date]"
|
||||
placement="topLeft"
|
||||
>
|
||||
<a-tag
|
||||
color="error"
|
||||
size="small"
|
||||
class="error-tag-with-tooltip"
|
||||
>
|
||||
{{ record.status }}
|
||||
</a-tag>
|
||||
</a-tooltip>
|
||||
<a-tag
|
||||
v-else
|
||||
:color="record.status === '完成' ? 'success' : 'error'"
|
||||
size="small"
|
||||
>
|
||||
@@ -287,6 +275,30 @@
|
||||
<a-card size="small" title="详细日志" class="log-card">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-tooltip title="打开日志文件">
|
||||
<a-button
|
||||
size="small"
|
||||
type="text"
|
||||
:disabled="!currentJsonFile"
|
||||
@click="handleOpenLogFile"
|
||||
>
|
||||
<template #icon>
|
||||
<FileOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip title="打开日志文件所在目录">
|
||||
<a-button
|
||||
size="small"
|
||||
type="text"
|
||||
:disabled="!currentJsonFile"
|
||||
@click="handleOpenLogDirectory"
|
||||
>
|
||||
<template #icon>
|
||||
<FolderOpenOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<FileTextOutlined />
|
||||
</a-space>
|
||||
</template>
|
||||
@@ -316,13 +328,14 @@ import {
|
||||
HistoryOutlined,
|
||||
UserOutlined,
|
||||
GiftOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
FileSearchOutlined,
|
||||
FileTextOutlined,
|
||||
RightOutlined,
|
||||
FolderOpenOutlined,
|
||||
FileOutlined,
|
||||
} from '@ant-design/icons-vue'
|
||||
import { Service } from '@/api/services/Service'
|
||||
import type { HistorySearchIn, HistoryData, HistoryDataGetIn } from '@/api/models'
|
||||
import type { HistorySearchIn, HistoryData } from '@/api'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
// 响应式数据
|
||||
@@ -565,6 +578,70 @@ const loadUserLog = async (jsonFile: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 打开日志文件
|
||||
const handleOpenLogFile = async () => {
|
||||
if (!currentJsonFile.value) {
|
||||
message.warning('请先选择一条记录')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 将 .json 扩展名替换为 .log
|
||||
const logFilePath = currentJsonFile.value.replace(/\.json$/, '.log')
|
||||
|
||||
console.log('尝试打开日志文件:', logFilePath)
|
||||
console.log('electronAPI 可用性:', !!window.electronAPI)
|
||||
console.log('openFile 方法可用性:', !!(window.electronAPI && (window.electronAPI as any).openFile))
|
||||
|
||||
// 调用系统API打开文件
|
||||
if (window.electronAPI && (window.electronAPI as any).openFile) {
|
||||
await (window.electronAPI as any).openFile(logFilePath)
|
||||
message.success('日志文件已打开')
|
||||
} else {
|
||||
const errorMsg = !window.electronAPI
|
||||
? '当前环境不支持打开文件功能(electronAPI 不可用)'
|
||||
: '当前环境不支持打开文件功能(openFile 方法不可用)'
|
||||
console.error(errorMsg)
|
||||
message.error(errorMsg)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('打开日志文件失败:', error)
|
||||
message.error(`打开日志文件失败: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// 打开日志文件所在目录
|
||||
const handleOpenLogDirectory = async () => {
|
||||
if (!currentJsonFile.value) {
|
||||
message.warning('请先选择一条记录')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 将 .json 扩展名替换为 .log
|
||||
const logFilePath = currentJsonFile.value.replace(/\.json$/, '.log')
|
||||
|
||||
console.log('尝试打开日志文件目录:', logFilePath)
|
||||
console.log('electronAPI 可用性:', !!window.electronAPI)
|
||||
console.log('showItemInFolder 方法可用性:', !!(window.electronAPI && (window.electronAPI as any).showItemInFolder))
|
||||
|
||||
// 调用系统API打开目录并选中文件
|
||||
if (window.electronAPI && (window.electronAPI as any).showItemInFolder) {
|
||||
await (window.electronAPI as any).showItemInFolder(logFilePath)
|
||||
message.success('日志文件目录已打开')
|
||||
} else {
|
||||
const errorMsg = !window.electronAPI
|
||||
? '当前环境不支持打开目录功能(electronAPI 不可用)'
|
||||
: '当前环境不支持打开目录功能(showItemInFolder 方法不可用)'
|
||||
console.error(errorMsg)
|
||||
message.error(errorMsg)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('打开日志文件目录失败:', error)
|
||||
message.error(`打开日志文件目录失败: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取日期状态颜色
|
||||
const getDateStatusColor = (users: Record<string, HistoryData>) => {
|
||||
const hasError = Object.values(users).some(
|
||||
@@ -612,7 +689,7 @@ const getDateStatusColor = (users: Record<string, HistoryData>) => {
|
||||
|
||||
/* 左侧日期栏 */
|
||||
.date-sidebar {
|
||||
width: 320px;
|
||||
width: 200px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -947,6 +1024,16 @@ const getDateStatusColor = (users: Record<string, HistoryData>) => {
|
||||
}
|
||||
}
|
||||
|
||||
/* 带tooltip的错误tag样式 */
|
||||
.error-tag-with-tooltip {
|
||||
cursor: help;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.error-tag-with-tooltip:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 统计数据标题样式 */
|
||||
.stat-subtitle {
|
||||
font-size: 12px;
|
||||
|
||||
Reference in New Issue
Block a user