Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
811361a1a3 | ||
|
|
ffbda4c618 | ||
|
|
348b02600d | ||
|
|
d004f8e9f8 |
6
docs/releases/1.7.2.md
Normal file
6
docs/releases/1.7.2.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# 1.7.2
|
||||||
|
|
||||||
|
## 问题修复
|
||||||
|
|
||||||
|
- 修复操作历史时间显示错误(时区转换导致时间快8小时)。
|
||||||
|
- 操作历史支持一键复制总排号和订单号。
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "erpauto",
|
"name": "erpauto",
|
||||||
"version": "1.7.1",
|
"version": "1.7.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "erpauto",
|
"name": "erpauto",
|
||||||
"version": "1.7.1",
|
"version": "1.7.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.929.0",
|
"@aws-sdk/client-s3": "^3.929.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "erpauto",
|
"name": "erpauto",
|
||||||
"version": "1.7.1",
|
"version": "1.7.2",
|
||||||
"description": "An Electron application with React and TypeScript",
|
"description": "An Electron application with React and TypeScript",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "example.com",
|
"author": "example.com",
|
||||||
|
|||||||
@@ -21,6 +21,17 @@ import type {
|
|||||||
|
|
||||||
const log = createLogger('ExtractorOperationHistoryDAO')
|
const log = createLogger('ExtractorOperationHistoryDAO')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format datetime value from database to ISO string
|
||||||
|
* mssql driver returns Date objects in UTC format
|
||||||
|
*/
|
||||||
|
function formatDateTime(value: unknown): string {
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return value.toISOString()
|
||||||
|
}
|
||||||
|
return value ? String(value) : new Date().toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for ExtractorOperationHistory table
|
* Configuration for ExtractorOperationHistory table
|
||||||
*/
|
*/
|
||||||
@@ -324,9 +335,7 @@ export class ExtractorOperationHistoryDAO {
|
|||||||
batchId: row.BatchId as string,
|
batchId: row.BatchId as string,
|
||||||
userId: row.UserId as number,
|
userId: row.UserId as number,
|
||||||
username: row.Username as string,
|
username: row.Username as string,
|
||||||
operationTime: row.OperationTime
|
operationTime: formatDateTime(row.OperationTime),
|
||||||
? new Date(row.OperationTime as string).toISOString()
|
|
||||||
: new Date().toISOString(),
|
|
||||||
status: row.Status as string,
|
status: row.Status as string,
|
||||||
totalOrders: row.TotalOrders as number,
|
totalOrders: row.TotalOrders as number,
|
||||||
totalRecords: (row.TotalRecords as number) || 0,
|
totalRecords: (row.TotalRecords as number) || 0,
|
||||||
@@ -432,9 +441,7 @@ export class ExtractorOperationHistoryDAO {
|
|||||||
batchId: row.BatchId as string,
|
batchId: row.BatchId as string,
|
||||||
userId: row.UserId as number,
|
userId: row.UserId as number,
|
||||||
username: row.Username as string,
|
username: row.Username as string,
|
||||||
operationTime: row.OperationTime
|
operationTime: formatDateTime(row.OperationTime),
|
||||||
? new Date(row.OperationTime as string).toISOString()
|
|
||||||
: new Date().toISOString(),
|
|
||||||
status: row.Status as string,
|
status: row.Status as string,
|
||||||
totalOrders: row.TotalOrders as number,
|
totalOrders: row.TotalOrders as number,
|
||||||
totalRecords: (row.TotalRecords as number) || 0,
|
totalRecords: (row.TotalRecords as number) || 0,
|
||||||
|
|||||||
@@ -14,13 +14,15 @@ import {
|
|||||||
ChevronRight,
|
ChevronRight,
|
||||||
CheckCircle,
|
CheckCircle,
|
||||||
XCircle,
|
XCircle,
|
||||||
Clock
|
Clock,
|
||||||
|
Copy
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
import type { UserInfo } from './UserSelectionDialog'
|
import type { UserInfo } from './UserSelectionDialog'
|
||||||
import type {
|
import type {
|
||||||
BatchStats,
|
BatchStats,
|
||||||
OperationHistoryRecord
|
OperationHistoryRecord
|
||||||
} from '../../../main/types/operation-history.types'
|
} from '../../../main/types/operation-history.types'
|
||||||
|
import { showSuccess, showError, showWarning } from '../stores/useAppStore'
|
||||||
|
|
||||||
interface ExtractorOperationHistoryModalProps {
|
interface ExtractorOperationHistoryModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
@@ -51,13 +53,20 @@ const statusIcons: Record<string, React.ReactNode> = {
|
|||||||
|
|
||||||
const formatDateTime = (dateStr: string) => {
|
const formatDateTime = (dateStr: string) => {
|
||||||
const date = new Date(dateStr)
|
const date = new Date(dateStr)
|
||||||
return date.toLocaleString('zh-CN', {
|
|
||||||
year: 'numeric',
|
// Check if the date is valid
|
||||||
month: '2-digit',
|
if (isNaN(date.getTime())) {
|
||||||
day: '2-digit',
|
return dateStr // Return original if invalid
|
||||||
hour: '2-digit',
|
}
|
||||||
minute: '2-digit'
|
|
||||||
})
|
// Use UTC methods to display the time as stored in database (without timezone conversion)
|
||||||
|
const year = date.getUTCFullYear()
|
||||||
|
const month = String(date.getUTCMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getUTCDate()).padStart(2, '0')
|
||||||
|
const hours = String(date.getUTCHours()).padStart(2, '0')
|
||||||
|
const minutes = String(date.getUTCMinutes()).padStart(2, '0')
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ExtractorOperationHistoryModal: React.FC<ExtractorOperationHistoryModalProps> = ({
|
export const ExtractorOperationHistoryModal: React.FC<ExtractorOperationHistoryModalProps> = ({
|
||||||
@@ -167,6 +176,26 @@ export const ExtractorOperationHistoryModal: React.FC<ExtractorOperationHistoryM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleCopyColumn = async (field: 'productionId' | 'orderNumber', batchId: string) => {
|
||||||
|
const details = batchDetails.get(batchId) || []
|
||||||
|
const values = details
|
||||||
|
.map((d) => (field === 'productionId' ? d.productionId : d.orderNumber))
|
||||||
|
.filter(Boolean) // 移除空值
|
||||||
|
.join('\n') // 使用换行符分隔
|
||||||
|
|
||||||
|
if (!values) {
|
||||||
|
showWarning('没有可复制的数据')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(values)
|
||||||
|
showSuccess(`已复制 ${values.split('\n').length} 条数据`)
|
||||||
|
} catch {
|
||||||
|
showError('复制失败,请手动复制')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!isOpen) return null
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -301,10 +330,38 @@ export const ExtractorOperationHistoryModal: React.FC<ExtractorOperationHistoryM
|
|||||||
<thead className="bg-gray-50">
|
<thead className="bg-gray-50">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="px-4 py-2 text-left font-medium text-gray-600">
|
<th className="px-4 py-2 text-left font-medium text-gray-600">
|
||||||
总排号
|
<div className="flex items-center gap-2">
|
||||||
|
总排号
|
||||||
|
<button
|
||||||
|
className="p-1 hover:bg-gray-200 rounded transition-colors"
|
||||||
|
onClick={() =>
|
||||||
|
void handleCopyColumn('productionId', batch.batchId)
|
||||||
|
}
|
||||||
|
title="复制所有总排号"
|
||||||
|
>
|
||||||
|
<Copy
|
||||||
|
size={14}
|
||||||
|
className="text-gray-500 hover:text-gray-700"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th className="px-4 py-2 text-left font-medium text-gray-600">
|
<th className="px-4 py-2 text-left font-medium text-gray-600">
|
||||||
订单号
|
<div className="flex items-center gap-2">
|
||||||
|
订单号
|
||||||
|
<button
|
||||||
|
className="p-1 hover:bg-gray-200 rounded transition-colors"
|
||||||
|
onClick={() =>
|
||||||
|
void handleCopyColumn('orderNumber', batch.batchId)
|
||||||
|
}
|
||||||
|
title="复制所有订单号"
|
||||||
|
>
|
||||||
|
<Copy
|
||||||
|
size={14}
|
||||||
|
className="text-gray-500 hover:text-gray-700"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th className="px-4 py-2 text-left font-medium text-gray-600">
|
<th className="px-4 py-2 text-left font-medium text-gray-600">
|
||||||
状态
|
状态
|
||||||
|
|||||||
Reference in New Issue
Block a user