feat: 数据提升

This commit is contained in:
381848900@qq.com 2024-12-11 19:47:32 +08:00
parent 90e3e22e44
commit 25529dd73d
13 changed files with 231 additions and 176 deletions

View File

@ -5,5 +5,4 @@
background-color: white;
border-radius: 5px;
padding: 16px;
overflow: scroll;
}

View File

@ -1,8 +1,13 @@
import { useEffect, useState } from "react";
import NodeTableComponent, {
DataTemplateInterface,
} from "../NodeTableComponent/NodeTableComponent";
import { invoke } from '@tauri-apps/api/core';
export default function DosHeader() {
const [data, setData] = useState<any[]>([]);
const dataTemplate: DataTemplateInterface = {
e_magic: {
name: "e_magic",
@ -149,17 +154,20 @@ export default function DosHeader() {
title: "字段名",
dataIndex: "name",
key: "name",
width: 120
},
{
title: "偏移",
dataIndex: "offset",
key: "offset",
hexSwitch: true,
width: 80
},
{
title: "大小",
dataIndex: "size",
key: "size",
width: 80
},
{
title: "值",
@ -167,18 +175,27 @@ export default function DosHeader() {
key: "value",
hexSwitch: true,
editable: true,
minWidth: 200
},
{
title: "描述信息",
dataIndex: "description",
key: "description",
width: 250
},
];
useEffect(()=>{
invoke(command).then(res => {
console.log("asdfsadf",res);
setData(res as any);
})
}, [])
return (
<NodeTableComponent
dataTemplate={dataTemplate}
command={command}
defaultData={data}
columns={columns as any}
></NodeTableComponent>
);

View File

@ -5,5 +5,4 @@
background-color: white;
border-radius: 5px;
padding: 16px;
overflow: scroll;
}

View File

@ -1,119 +1,195 @@
import NodeTableComponent, {
DataTemplateInterface,
} from "../NodeTableComponent/NodeTableComponent";
import { invoke } from "@tauri-apps/api/core";
import { Select, Space } from "antd";
import { useEffect, useMemo, useState } from "react";
// 写一个组件,用于展示位枚举值
interface BitEnumComponentProps {
value: number;
enum: {
[key: number]: {
enum_name: string; // 枚举值名称
description?: string; // 枚举值描述
};
};
onChange?: (value: any, options: any) => void;
}
const BitEnumComponent = (props: BitEnumComponentProps) => {
const formatOptions = useMemo(() => {
const options = Object.entries(props.enum).map(([key, value]) => {
return {
label: value.enum_name,
value: key,
title: value.description,
};
});
return options;
}, [props.enum, props.value]);
const formatValue = useMemo(() => {
const value = [];
for (const key in props.enum) {
if (props.value & parseInt(key)) {
value.push(key);
}
}
return value;
}, [props.value]);
const handleChange = (value: number[], options) => {
// 如果props.onChange存在那么调用
props.onChange?.(value, options);
// TODO: 做一些自己的事
};
return (
<>
<Space style={{ width: "100%" }} direction="vertical">
<Select
mode="multiple"
allowClear
style={{ width: "100%" }}
options={formatOptions}
value={formatValue}
onChange={handleChange}
/>
</Space>
</>
);
};
export default function FileHeader() {
const [data, setData] = useState<any[]>([]);
const [valueHex, setValueHex] = useState(false);
const handleChangeBitEnum = (record: any, value: number[], _options) => {
const { name } = record;
const newData: any = { ...data };
newData.fields[name] = value.reduce(
(prev, cur: any) => prev | parseInt(cur),
0
);
setData(newData);
};
const dataTemplate: DataTemplateInterface = {
machine: {
name: "Machine",
name: "machine",
description: "目标机器类型,例如 x86 或 x64。",
offset: 0,
size: 2,
value: null,
data_type: "hex",
},
number_of_sections: {
name: "Number of Sections",
name: "number_of_sections",
description: "节的数量,表示文件中包含的段数量。",
offset: 2,
size: 2,
value: null,
data_type: "hex",
},
time_date_stamp: {
name: "Time Date Stamp",
name: "time_date_stamp",
description: "文件的创建时间戳,以自 1970-01-01 的秒数表示。",
offset: 4,
size: 4,
value: null,
data_type: "hex",
},
pointer_to_symbol_table: {
name: "Pointer to Symbol Table",
name: "pointer_to_symbol_table",
description: "符号表的文件偏移(通常为 0 表示未使用)。",
offset: 8,
size: 4,
value: null,
data_type: "hex",
},
number_of_symbols: {
name: "Number of Symbols",
name: "number_of_symbols",
description: "符号表中符号的数量(通常为 0 表示未使用)。",
offset: 12,
size: 4,
value: null,
data_type: "hex",
},
size_of_optional_header: {
name: "Size of Optional Header",
name: "size_of_optional_header",
description: "可选头的大小,用于进一步描述文件。",
offset: 16,
size: 2,
value: null,
data_type: "hex",
},
characteristics: {
name: "Characteristics",
name: "characteristics",
description: "文件特性标志例如可执行、DLL、移除调试信息等。",
offset: 18,
size: 2,
value: null,
data_type: "enum",
data_type: "bit_enum",
enum: {
0x1: {
enum_name: "RELOCS_STRIPPED",
description: "Relocation info stripped from file.",
description: "已从文件中移除重定位信息。",
},
0x2: {
enum_name: "EXECUTABLE_IMAGE",
description:
"File is executable (i.e. no unresolved external references).",
description: "文件是可执行的(例如,没有未解析的外部引用)。",
},
0x4: {
enum_name: "LINE_NUMS_STRIPPED",
description: "Line nunbers stripped from file.",
description: "已从文件中移除行号信息。",
},
0x8: {
enum_name: "LOCAL_SYMS_STRIPPED",
description: "Local symbols stripped from file.",
description: "已从文件中移除本地符号信息。",
},
0x10: {
enum_name: "AGGRESSIVE_WS_TRIM",
description: "Aggressively trim working set",
description: "积极地减少工作集。",
},
0x20: {
enum_name: "LARGE_ADDRESS_AWARE",
description: "App can handle >2gb addresses",
description: "应用程序可以处理大于 2GB 的地址。",
},
0x80: {
enum_name: "BYTES_REVERSED_LO",
description: "Bytes of machine word are reversed.",
description: "机器字的字节顺序被颠倒(低位字节)。",
},
0x100: {
enum_name: "MACHINE_32BIT",
description: "32 bit word machine.",
description: "32 位字长的机器。",
},
0x200: {
enum_name: "DEBUG_STRIPPED",
description: "Debugging info stripped from file in .DBG file",
description: "调试信息已被移到 .DBG 文件中。",
},
0x400: {
enum_name: "REMOVABLE_RUN_FROM_SWAP",
description:
"If Image is on removable media, copy and run from the swap file.",
description: "如果映像位于可移动介质上,则复制并从交换文件运行。",
},
0x800: {
enum_name: "NET_RUN_FROM_SWAP",
description: "If Image is on Net, copy and run from the swap file.",
description: "如果映像位于网络上,则复制并从交换文件运行。",
},
0x1000: {
enum_name: "SYSTEM",
description: "System File.",
description: "系统文件。",
},
0x2000: {
enum_name: "DLL",
description: "File is a DLL.",
description: "文件是一个 DLL。",
},
0x4000: {
enum_name: "UP_SYSTEM_ONLY",
description: "File should only be run on a UP machine",
description: "文件只能在单处理器机器上运行。",
},
0x8000: {
enum_name: "BYTES_REVERSED_HI",
description: "Bytes of machine word are reversed.",
description: "机器字的字节顺序被颠倒(高位字节)。",
},
},
},
@ -140,19 +216,51 @@ export default function FileHeader() {
title: "值",
dataIndex: "value",
key: "value",
hexSwitch: true,
editable: true,
render: (text: any, record: any) => {
if (record.data_type === "bit_enum") {
return (
<BitEnumComponent
value={text}
enum={record.enum}
onChange={(value, options) =>
handleChangeBitEnum(record, value, options)
}
/>
);
} else if (record.data_type === "hex") {
return (
<span style={{ cursor: "pointer" }}>
{valueHex ? `0x${text.toString(16).toUpperCase()}` : text}
</span>
);
}
return <span>{text}</span>;
},
onHeaderCell: () => ({
onClick: () => {
setValueHex(!valueHex);
},
}),
},
{
title: "描述信息",
dataIndex: "description",
key: "description",
minWidth: 200,
},
];
useEffect(() => {
invoke(command).then((res) => {
setData(res as any);
});
}, []);
return (
<NodeTableComponent
dataTemplate={dataTemplate}
command={command}
defaultData={data}
columns={columns as any}
></NodeTableComponent>
);

View File

@ -1,8 +1,11 @@
import { useEffect, useState } from "react";
import NodeTableComponent, {
DataTemplateInterface,
} from "../NodeTableComponent/NodeTableComponent";
import { invoke } from "@tauri-apps/api/core";
export default function NTHeader() {
const [data, setData] = useState<any[]>([]);
// TODO: 这里要分64位和32位最好让后端返回
const dataTemplate: DataTemplateInterface = {
signature: {
@ -44,10 +47,17 @@ export default function NTHeader() {
key: "description",
},
];
useEffect(() => {
invoke(command).then((res) => {
setData(res as any);
});
}, []);
return (
<NodeTableComponent
defaultData={data}
dataTemplate={dataTemplate}
command={command}
columns={columns as any}
></NodeTableComponent>
);

View File

@ -1,14 +1,7 @@
.NodeTableComponentRootFlex {
background-color: white;
border-radius: 5px;
padding: 8px;
margin-right: 8px;
overflow-y: scroll;
height: 100%;
padding-bottom: 16px;
min-width: calc(100% - 16px);
}
.NodeTableComponentTable{
height: calc(100% - 16px);
width: 100%;
}

View File

@ -2,7 +2,6 @@ import { Table, Flex } from "antd/lib";
import { ColumnType } from "antd/lib/table";
import { useState, useMemo, useEffect, useRef, useContext } from "react";
import styles from "./NodeTableComponent.module.scss";
import { invoke } from "@tauri-apps/api/core";
import { cloneDeep } from "lodash-es";
import { Form, FormInstance, Input, InputRef } from "antd";
import React from "react";
@ -33,10 +32,11 @@ export interface DataType {
};
array_element_size?: number; // 数组元素大小
// hex: 16进制
// enum: 枚举值,对于枚举的处理一律按位处理
// enum: 枚举值
// bit_enum: 位枚举值
// array: 数组
// char_array: 字符数组
data_type: "hex" | "enum" | "array"| "char_array";
data_type: "hex" | "enum" | "array" | "char_array" | "bit_enum";
children?: DataType[];
}
@ -52,8 +52,9 @@ export interface NodeTableColumnInterface<T> extends ColumnType<T> {
interface NodeTableComponentProps {
dataTemplate: DataTemplateInterface; // 数据模板
command: string; // 请求数据的命令
// command: string; // 请求数据的命令
columns: NodeTableColumnInterface<DataType>[];
defaultData?: DataType[];
}
interface EditableRowProps {
@ -92,7 +93,6 @@ const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
const [editing, setEditing] = useState(false);
const inputRef = useRef<InputRef>(null);
const form = useContext(EditableContext)!;
useEffect(() => {
if (editing) {
inputRef.current?.focus();
@ -116,7 +116,7 @@ const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
let childNode = children;
if (editable) {
if (editable && record?.data_type == "hex") {
childNode = editing ? (
<Form.Item
style={{ margin: 0 }}
@ -140,7 +140,6 @@ const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
};
export default function NodeTableComponent(props: NodeTableComponentProps) {
const [data, setData] = useState<DataType[]>([]);
// 需要搞一个状态用来保存不同列的hex显示状态
const [hexSwitchStatus, setHexSwitchStatus] = useState<{
[key: string]: boolean;
@ -152,7 +151,7 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
setHexSwitchStatus(newHexSwitchStatus);
};
const handleSave = (row: DataType) => {
const handleSave = (_row: DataType) => {
// TODO: 保存逻辑
};
@ -194,8 +193,8 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
});
}
return {
...col,
...extraCol,
...col,
};
});
}, [props.columns, hexSwitchStatus]);
@ -205,6 +204,10 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
const cloneData = cloneDeep(props.dataTemplate);
// 2. 遍历resData更新cloneData
for (let key in cloneData) {
if(!resData || !resData.fields){
continue;
}
cloneData[key].value = resData.fields[key];
cloneData[key].offset += resData.base_offset;
// 如果是array
@ -244,23 +247,30 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
cloneData[key].children = children;
}
// TODO: 字符数组处理
}
// TODO: 应该从columns中获需要排序的字段来进行排序
// 如果cloneData的成员中有offset字段那么需要按照offset排序
let cloneDataArray = Object.values(cloneData);
if(cloneDataArray[0].offset){
if (cloneDataArray[0].offset) {
cloneDataArray.sort((a, b) => a.offset - b.offset);
}
setData(cloneDataArray);
return cloneDataArray;
};
useEffect(() => {
// 请求数据
invoke(props.command).then((resData: ResponsData) => {
handleData(resData);
});
}, []);
const formatData = useMemo(()=>{
return handleData(props.defaultData as any);
}, [props.defaultData])
// useEffect(() => {
// // 请求数据
// invoke(props.command).then((resData: ResponsData) => {
// handleData(resData);
// });
// }, []);
return (
<Flex className={styles.NodeTableComponentRootFlex}>
<Table
@ -268,12 +278,13 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
className={styles.NodeTableComponentTable}
rowClassName={() => "editable-row"}
columns={formatCol}
dataSource={data}
dataSource={formatData}
pagination={false}
tableLayout="auto"
rowKey={"name"}
bordered
size="small"
sticky={{ offsetHeader: -8 }}
sticky={{ offsetHeader: -16 }}
/>
</Flex>
);

View File

@ -1,8 +1,11 @@
import { useEffect, useState } from "react";
import NodeTableComponent, {
DataTemplateInterface,
} from "../NodeTableComponent/NodeTableComponent";
import { invoke } from "@tauri-apps/api/core";
export default function OptionalHeader() {
const [data, setData] = useState<any[]>([]);
const dataTemplate: DataTemplateInterface = {
magic: {
name: "magic",
@ -268,10 +271,17 @@ export default function OptionalHeader() {
key: "description",
},
];
useEffect(() => {
invoke(command).then((res) => {
setData(res as any);
});
}, []);
return (
<NodeTableComponent
dataTemplate={dataTemplate}
command={command}
defaultData={data}
columns={columns as any}
></NodeTableComponent>
);

View File

@ -54,7 +54,6 @@ import NodeTableComponent, {
return (
<NodeTableComponent
dataTemplate={dataTemplate}
command={command}
columns={columns as any}
></NodeTableComponent>
);

View File

@ -1,6 +1,6 @@
.root {
background-color: white;
width: 100%;
width: 200px;
margin: 8px;
margin-top: 0;
border-radius: 5px;

View File

@ -2,7 +2,6 @@ import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { invoke } from "@tauri-apps/api/core";
import { delay} from "lodash-es"
async function setup() {
invoke('set_complete')

View File

@ -2,16 +2,13 @@
display: flex;
height: 100vh;
overflow: hidden;
background-color: #e3e3e3;
}
.sider {
flex-shrink: 0;
width: 260px;
height: calc(100% - 64px);
margin: 8px;
margin-top: 0;
margin-right: 8px;
padding: 8px;
background-color: white;
// 圆角
@ -27,5 +24,19 @@
}
.content{
height: calc(100% - 64px);
background-color: white;
display: flex;
justify-content: center;
border-radius: 5px;
overflow: scroll;
padding: 16px;
}
.mainContent {
margin: 8px;
margin-top: 0;
height: calc(100% - 16px);
background-color: #e3e3e3;
border-radius: 5px;
min-height: 500px;
}

View File

@ -10,9 +10,6 @@ import DosHeader from "../components/DosHeader/DosHeader";
import NtHeader from "../components/NTHeader/NTHeader";
import FileHeader from "../components/FileHeader/FileHeader";
import OptionalHeader from "../components/OptionalHeader/OptionalHeader";
import NodeTableComponent, {
DataTemplateInterface,
} from "../components/NodeTableComponent/NodeTableComponent";
import { open } from "@tauri-apps/plugin-dialog";
const SelectNodeMap = {
@ -85,15 +82,10 @@ export default function MainPage() {
</Button>
</Flex>
<Flex
style={{
backgroundColor: "#e5e5e5",
paddingBottom: "16px",
height: "100%",
}}
>
<Flex className={styles.mainContent}>
<Flex className={styles.sider}>
<SiderTree
treeData={treeData}
defaultSelectedKey={treeData[0]?.key || ""}
onSelect={onSelect}
@ -103,105 +95,12 @@ export default function MainPage() {
{selectedKey && SelectNodeMap[selectedKey] ? (
SelectNodeMap[selectedKey]
) : (
<Empty description={"请选择一个节点"} />
<Empty style={{
alignSelf: "center",
}} description={"请选择一个节点"} />
)}
{/* <TestNodeTableComponent></TestNodeTableComponent> */}
</Content>
</Flex>
</Layout>
);
}
const TestNodeTableComponent = () => {
const [sortStatus, setSortStatus] = useState<"ascend" | "descend" | null>(
"ascend"
);
const dataTemplate: DataTemplateInterface = {
e_magic: {
name: "e_magic",
value: 0,
size: 2,
offset: 0,
description: "Magic number",
data_type: "hex",
},
e_res: {
name: "e_res",
value: null,
size: 8,
offset: 28,
description: "Reserved",
data_type: "array",
array_element_size: 2,
},
test_enum: {
name: "test_enum",
value: 0,
size: 2,
offset: 10,
description: "Test enum",
data_type: "enum",
enum: {
1: {
enum_name: "enum1",
description: "enum1 description",
},
2: {
enum_name: "enum2",
description: "enum2 description",
},
4: {
enum_name: "enum4",
description: "enum4 description",
},
8: {
enum_name: "enum8",
description: "enum8 description",
},
},
},
};
const command = "test_command";
const columns = [
{
title: "Name",
dataIndex: "name",
key: "name",
},
{
title: "偏移",
dataIndex: "offset",
hexSwitch: true,
key: "offset",
sortOrder: sortStatus,
},
{
title: "大小",
dataIndex: "size",
key: "size",
},
{
title: "值",
dataIndex: "value",
hexSwitch: true,
editable: true,
key: "value",
},
{
title: "描述",
dataIndex: "description",
key: "description",
},
];
return (
<>
<NodeTableComponent
dataTemplate={dataTemplate}
command={command}
columns={columns as any}
></NodeTableComponent>
</>
);
};