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 () => {
|
ipcMain.handle('check-environment', async () => {
|
||||||
const appRoot = getAppRoot()
|
const appRoot = getAppRoot()
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||||||
saveLogsToFile: (logs: string) => ipcRenderer.invoke('save-logs-to-file', logs),
|
saveLogsToFile: (logs: string) => ipcRenderer.invoke('save-logs-to-file', logs),
|
||||||
loadLogsFromFile: () => ipcRenderer.invoke('load-logs-from-file'),
|
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) => {
|
onDownloadProgress: (callback: (progress: any) => void) => {
|
||||||
ipcRenderer.on('download-progress', (_, progress) => callback(progress))
|
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>
|
saveLogsToFile: (logs: string) => Promise<void>
|
||||||
loadLogsFromFile: () => Promise<string | null>
|
loadLogsFromFile: () => Promise<string | null>
|
||||||
|
|
||||||
|
// 文件系统操作
|
||||||
|
openFile: (filePath: string) => Promise<void>
|
||||||
|
showItemInFolder: (filePath: string) => Promise<void>
|
||||||
|
|
||||||
// 监听下载进度
|
// 监听下载进度
|
||||||
onDownloadProgress: (callback: (progress: any) => void) => void
|
onDownloadProgress: (callback: (progress: any) => void) => void
|
||||||
removeDownloadProgressListener: () => void
|
removeDownloadProgressListener: () => void
|
||||||
|
|||||||
@@ -90,32 +90,6 @@
|
|||||||
<div v-else class="history-layout">
|
<div v-else class="history-layout">
|
||||||
<!-- 左侧日期列表 -->
|
<!-- 左侧日期列表 -->
|
||||||
<div class="date-sidebar">
|
<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">
|
<div class="date-list">
|
||||||
<a-collapse v-model:activeKey="activeKeys" ghost>
|
<a-collapse v-model:activeKey="activeKeys" ghost>
|
||||||
@@ -187,7 +161,21 @@
|
|||||||
<div class="record-info">
|
<div class="record-info">
|
||||||
<div class="record-header">
|
<div class="record-header">
|
||||||
<span class="record-time">{{ record.date }}</span>
|
<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
|
<a-tag
|
||||||
|
v-else
|
||||||
:color="record.status === '完成' ? 'success' : 'error'"
|
:color="record.status === '完成' ? 'success' : 'error'"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
@@ -287,6 +275,30 @@
|
|||||||
<a-card size="small" title="详细日志" class="log-card">
|
<a-card size="small" title="详细日志" class="log-card">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<a-space>
|
<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 />
|
<FileTextOutlined />
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
@@ -316,13 +328,14 @@ import {
|
|||||||
HistoryOutlined,
|
HistoryOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
GiftOutlined,
|
GiftOutlined,
|
||||||
ExclamationCircleOutlined,
|
|
||||||
FileSearchOutlined,
|
FileSearchOutlined,
|
||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
RightOutlined,
|
RightOutlined,
|
||||||
|
FolderOpenOutlined,
|
||||||
|
FileOutlined,
|
||||||
} from '@ant-design/icons-vue'
|
} from '@ant-design/icons-vue'
|
||||||
import { Service } from '@/api/services/Service'
|
import { Service } from '@/api/services/Service'
|
||||||
import type { HistorySearchIn, HistoryData, HistoryDataGetIn } from '@/api/models'
|
import type { HistorySearchIn, HistoryData } from '@/api'
|
||||||
import dayjs from 'dayjs'
|
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 getDateStatusColor = (users: Record<string, HistoryData>) => {
|
||||||
const hasError = Object.values(users).some(
|
const hasError = Object.values(users).some(
|
||||||
@@ -612,7 +689,7 @@ const getDateStatusColor = (users: Record<string, HistoryData>) => {
|
|||||||
|
|
||||||
/* 左侧日期栏 */
|
/* 左侧日期栏 */
|
||||||
.date-sidebar {
|
.date-sidebar {
|
||||||
width: 320px;
|
width: 200px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
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 {
|
.stat-subtitle {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|||||||
Reference in New Issue
Block a user