ффффффффффикс

This commit is contained in:
dv 2026-05-28 16:27:13 +03:00
parent b3b0bd2190
commit abbdfb41f2

View file

@ -28,7 +28,7 @@ import type { ColumnsType } from 'antd/es/table'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime' import relativeTime from 'dayjs/plugin/relativeTime'
import 'dayjs/locale/ru' import 'dayjs/locale/ru'
import { useMemo, useCallback, useRef, useState } from 'react' import { useMemo, useState } from 'react'
import { import {
useSnapshotDashboard, useSnapshotDashboard,
useSnapshotPolicies, useSnapshotPolicies,
@ -486,6 +486,31 @@ function ObjectDevicesExpanded({
) )
} }
function highlightIni(text: string): React.ReactNode[] {
return text.split('\n').map((line, i) => {
let node: React.ReactNode
if (/^\s*[#;]/.test(line)) {
node = <span style={{ color: '#6a9955' }}>{line}</span>
} else if (/^\s*\[.+\]/.test(line)) {
node = <span style={{ color: '#ce9178', fontWeight: 600 }}>{line}</span>
} else if (line.includes('=')) {
const eqIdx = line.indexOf('=')
const key = line.slice(0, eqIdx)
const value = line.slice(eqIdx)
node = (
<>
<span style={{ color: '#9cdcfe' }}>{key}</span>
<span style={{ color: '#d4d4d4' }}>{value.charAt(0)}</span>
<span style={{ color: '#dcdcaa' }}>{value.slice(1)}</span>
</>
)
} else {
node = <span>{line}</span>
}
return <span key={i}>{node}{'\n'}</span>
})
}
function DevicesList({ function DevicesList({
objId, objId,
objName, objName,
@ -498,7 +523,6 @@ function DevicesList({
const { data: devices, isLoading } = useDashboardDevices(objId, policyId, true) const { data: devices, isLoading } = useDashboardDevices(objId, policyId, true)
const [viewContent, setViewContent] = useState<string | null>(null) const [viewContent, setViewContent] = useState<string | null>(null)
const [viewTitle, setViewTitle] = useState('') const [viewTitle, setViewTitle] = useState('')
const contentRef = useRef<HTMLPreElement>(null)
const handleCopy = async (snapshotId: number) => { const handleCopy = async (snapshotId: number) => {
try { try {
@ -537,18 +561,12 @@ function DevicesList({
} }
} }
const handleSelectAll = useCallback((e: React.KeyboardEvent) => { const handleViewCopy = async () => {
if ((e.ctrlKey || e.metaKey) && e.key === 'a') { if (viewContent) {
e.preventDefault() await navigator.clipboard.writeText(viewContent)
if (contentRef.current) { message.success('Скопировано в буфер обмена')
const range = document.createRange()
range.selectNodeContents(contentRef.current)
const sel = window.getSelection()
sel?.removeAllRanges()
sel?.addRange(range)
}
} }
}, []) }
if (isLoading) return <Typography.Text type="secondary">Загрузка...</Typography.Text> if (isLoading) return <Typography.Text type="secondary">Загрузка...</Typography.Text>
if (!devices || devices.length === 0) return <Typography.Text type="secondary">Нет устройств</Typography.Text> if (!devices || devices.length === 0) return <Typography.Text type="secondary">Нет устройств</Typography.Text>
@ -637,31 +655,33 @@ function DevicesList({
title={viewTitle} title={viewTitle}
open={viewContent !== null} open={viewContent !== null}
onCancel={() => setViewContent(null)} onCancel={() => setViewContent(null)}
footer={null} footer={
<Button icon={<CopyOutlined />} onClick={handleViewCopy}>
Скопировать
</Button>
}
width={800} width={800}
maskClosable maskClosable
destroyOnClose destroyOnClose
> >
<div onKeyDown={handleSelectAll} tabIndex={0} style={{ outline: 'none' }}> <pre
<pre style={{
ref={contentRef} background: '#1e1e1e',
style={{ color: '#d4d4d4',
background: '#1e1e1e', padding: 16,
color: '#d4d4d4', borderRadius: 6,
padding: 16, fontSize: 12,
borderRadius: 6, lineHeight: 1.5,
fontSize: 12, maxHeight: '70vh',
lineHeight: 1.5, overflow: 'auto',
maxHeight: '70vh', whiteSpace: 'pre-wrap',
overflow: 'auto', wordBreak: 'break-all',
whiteSpace: 'pre-wrap', margin: 0,
wordBreak: 'break-all', fontFamily: "'Consolas', 'Monaco', 'Courier New', monospace",
margin: 0, }}
}} >
> {viewContent && highlightIni(viewContent)}
{viewContent} </pre>
</pre>
</div>
</Modal> </Modal>
</> </>
) )