!2807 优化:文件历史记录数据匹配算法优化

pull/2806/MERGE
林三 4 months ago committed by ChenX
parent 2ef0152036
commit 9fd4791230

@ -1,15 +1,11 @@
import { Button, Checkbox, HTMLTable, Intent } from "@blueprintjs/core"; import { Checkbox } from "@blueprintjs/core";
import { observable } from "mobx"; import { observable } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import React from "react"; import React from "react";
import { app } from "../../ApplicationServices/Application";
import { StoreageKeys } from "../../Common/StoreageKeys";
import { FileServer } from "../../DatabaseServices/FileServer";
import { userConfig } from "../../Editor/UserConfig"; import { userConfig } from "../../Editor/UserConfig";
import { BoardModalType } from "../../UI/Components/Board/BoardModalType"; import { BoardModalType } from "../../UI/Components/Board/BoardModalType";
import { ModalState } from "../../UI/Components/Modal/ModalInterface";
import { AppToaster } from "../../UI/Components/Toaster";
import { userConfigStore } from "../../UI/Store/UserConfigStore"; import { userConfigStore } from "../../UI/Store/UserConfigStore";
import { OpenHistoryList } from "./OpenHistoryList";
import { HistoryProp } from "./OperLogsModal"; import { HistoryProp } from "./OperLogsModal";
@observer @observer
@ -60,7 +56,6 @@ export class OpenHistoryBody extends React.Component<HistoryProp, {}>
userName={this.props.userName} userName={this.props.userName}
files={this.props.files} files={this.props.files}
data={this.props.data} data={this.props.data}
OnClickOpenFile={this.props.OnClickOpenFile}
/> />
</div> </div>
</div> </div>
@ -90,204 +85,3 @@ export class OpenHistoryBody extends React.Component<HistoryProp, {}>
); );
} }
} }
@observer
export class OpenHistoryList extends React.Component<HistoryProp, {}>
{
_Index = 0;
_LastOper = "";
_Data = this.props.data;
@observable _CanOpen: boolean = false;
constructor(props)
{
super(props);
if (this.props.newFileId)
this._CanOpen = true;
}
render()
{
return (
<HTMLTable bordered={true} interactive={true} style={{ lineHeight: 0.5, width: "100%", padding: "5px 5px 0px 5px", border: "1px solid #DBDCDD" }}>
<thead>
<tr>
<th style={{ width: 50 }}></th>
<th style={{ width: 190 }}></th>
<th>
<Checkbox
label="只显示能还原记录"
style={{ position: 'absolute', right: "10px", fontSize: "12px", top: "15px" }}
checked={this._CanOpen}
onClick={(e) =>
{
this._Index = 0;
this._LastOper = "";
this._CanOpen = !this._CanOpen;
e.currentTarget.blur();
}}
/>
</th>
</tr>
</thead>
<tbody>
{
this._CanOpen ? this._CanOpenDataList() : this._AllDataList()
}
</tbody>
</HTMLTable>
);
}
_AllDataList = () =>
{
let count = 0;
return (
<>
{
this._Data.map(d =>
{
if (d.oper_type_name === "打开")
if (this._LastOper === "打开")
return;
this._LastOper = d.oper_type_name;
if (d.oper_type_name === "修改")
count++;
if (this.props.newFileId && count > 5) return;
return <tr key={d.oper_date}>
<td>{d.oper_type_name}</td>
<td
style={{
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "nowrap",
maxWidth: 150
}}
title={`${d.oper_user}`}
>
{d.oper_user}
</td>
<td>
{d.oper_date}
{this._ButtonEl(d.oper_type_name, d.oper_date, this.props.files[this._Index])}
</td>
</tr>;
})
}
</>
);
};
_CanOpenDataList = () =>
{
let count = 0;
return (
<>
{
this._Data.map((d, i) =>
{
if (d.oper_type_name !== "新建" && d.oper_type_name !== "修改") return;
if (!this._HasHistoryFile(d.oper_type_name, d.oper_date, this.props.files[this._Index])) return;
count++;
if (this.props.newFileId && count > 5) return;
return <tr>
<td>{d.oper_type_name}</td>
<td
style={{
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "nowrap",
maxWidth: 150
}}
title={`${d.oper_user}`}
>
{d.oper_user}
</td>
<td>
{d.oper_date}
<Button
className="histroyBtn"
value={this._Index++}
text="打开"
onClick={(e) =>
{
let index = e.currentTarget.value;
this.handleOpen(index);
}}
/>
</td>
</tr>;
})
}
</>
);
};
handleOpen = async (index: number) =>
{
const { fileId, newFileId, files, userName } = this.props;
let status: boolean = true;
if (newFileId)
{
let server = FileServer.GetInstance();
if (fileId != newFileId)
{
server._CurrentFilePath = "";
server.m_CurFileId = newFileId;
let info = await server.GetFileInfo(newFileId);
server.CurrentFileMd5 = info.code;
if (info.name)
server.currentFileInfo.name = info.name;
localStorage.setItem(StoreageKeys.LastOpenFileId, info.file_id || "");
}
status = await this.props.OnClickOpenFile(userName, newFileId, files, index);
}
else
{
status = await this.props.OnClickOpenFile(userName, fileId, files, index);
}
if (!status)
{
AppToaster.show({
message: "打开图纸失败,请尝试打开其他历史记录图纸",
timeout: 3000,
intent: Intent.DANGER,
});
return;
}
if (this.props.isNotToaster)
app.Editor.ModalManage.m_PromisRes({ Status: ModalState.Ok });
app.Editor.ModalManage.Destory();
};
_ButtonEl(name: string, oper_date: string, file_date: string): React.ReactElement<any>
{
if (!this._HasHistoryFile(name, oper_date, file_date)) return;
return (
<Button
className="histroyBtn"
value={this._Index++}
text="打开"
onClick={async (e) =>
{
let index = e.currentTarget.value;
this.handleOpen(index);
}}
/>
);
}
//验证是否有可以打开的历史文件
_HasHistoryFile(name: string, oper_date: string, file_date: string)
{
if (this._Index >= this.props.files.length) return;
if (name !== "修改" && name !== "新建") return;
let date = new Date(oper_date);
let operDate = date.getHours() * 60 * 60 + date.getMinutes() * 60 + date.getSeconds(); //时分秒转换number 好比较
let fileDateStr = file_date.split("-");
let fileDate = parseInt(fileDateStr[fileDateStr.length - 3]) * 60 * 60 + parseInt(fileDateStr[fileDateStr.length - 2]) * 60 + parseInt(fileDateStr[fileDateStr.length - 1]); //时分秒转换number 好比较
if (!(operDate - 10 <= fileDate && fileDate <= operDate + 10)) return false; //误差±10秒
else return true;
}
}

@ -0,0 +1,265 @@
import { Button, Checkbox, HTMLTable, Intent } from "@blueprintjs/core";
import { observable } from "mobx";
import { observer } from "mobx-react";
import React from "react";
import { app } from "../../ApplicationServices/Application";
import { FileHistoryFilesUrl, FileUrls } from "../../Common/HostUrl";
import { PostJson, RequestStatus } from "../../Common/Request";
import { StoreageKeys } from "../../Common/StoreageKeys";
import { FileServer } from "../../DatabaseServices/FileServer";
import { ModalState } from "../../UI/Components/Modal/ModalInterface";
import { AppToaster } from "../../UI/Components/Toaster";
import { FetchFile1 } from "./OperLog";
import { HistoryProp } from "./OperLogsModal";
@observer
export class OpenHistoryList extends React.Component<HistoryProp, {}>
{
LastOper = "";
CanOpenFileDataMap: Map<number, number> = new Map(); //this.props.data -> this.props.files
@observable CanOpen: boolean = false;
constructor(props)
{
super(props);
if (this.props.newFileId)
this.CanOpen = true;
this.ParseData();
}
ParseData = () =>
{
for (let i = 0, j = 0; j < this.props.data.length; j++)
{
if (i >= this.props.files.length)
break;
let data = this.props.data[j];
if (data.oper_type_name !== "修改" && data.oper_type_name !== "新建")
continue;
let date = new Date(data.oper_date);
let timeNum =
(date.getMonth() + 1) * Math.pow(60, 4) +
date.getDate() * Math.pow(60, 3) +
date.getHours() * Math.pow(60, 2) +
date.getMinutes() * 60 +
date.getSeconds(); //时分秒转换number 好比较
for (; i < this.props.files.length; i++)
{
let canOpenFile = this.props.files[i];
let str = canOpenFile.split("-");
let canOpenFileDateNum =
parseInt(str[str.length - 5]) * Math.pow(60, 4) +
parseInt(str[str.length - 4]) * Math.pow(60, 3) +
parseInt(str[str.length - 3]) * Math.pow(60, 2) +
parseInt(str[str.length - 2]) * 60 +
parseInt(str[str.length - 1]); //时分秒转换number 好比较
if (canOpenFileDateNum - 10 > timeNum)
continue;
if (Math.abs(timeNum - canOpenFileDateNum) < 10)
this.CanOpenFileDataMap.set(j, i++);
break;
}
}
};
AllDataList = () =>
{
let count = 0;
return (
<>
{
this.props.data.map((data, i) =>
{
if (data.oper_type_name === "打开")
if (this.LastOper === "打开")
return;
this.LastOper = data.oper_type_name;
if (data.oper_type_name === "修改")
count++;
if (this.props.newFileId && count > 20) return;
let canOpenFileIndex = this.CanOpenFileDataMap.get(i);
let file = this.props.files[canOpenFileIndex];
return <tr key={data.oper_date}>
<td>{data.oper_type_name}</td>
<td
style={{
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "nowrap",
maxWidth: 150
}}
title={`${data.oper_user}`}
>
{data.oper_user}
</td>
<td>
{data.oper_date}
{
file && <Button
className="histroyBtn"
value={file}
text="打开"
onClick={async (e) =>
{
this.HandleOpen(e.currentTarget.value);
}}
/>
}
</td>
</tr>;
})
}
</>
);
};
CanOpenDataList = () =>
{
let count = 0;
return (
<>
{
this.props.data.map((data, i) =>
{
if (data.oper_type_name !== "新建" && data.oper_type_name !== "修改") return;
let canOpenFileIndex = this.CanOpenFileDataMap.get(i);
let file = this.props.files[canOpenFileIndex];
if (file)
{
count++;
if (this.props.newFileId && count > 20) return;
return <tr>
<td>{data.oper_type_name}</td>
<td
style={{
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "nowrap",
maxWidth: 150
}}
title={`${data.oper_user}`}
>
{data.oper_user}
</td>
<td>
{data.oper_date}
<Button
className="histroyBtn"
value={file}
text="打开"
onClick={(e) =>
{
this.HandleOpen(e.currentTarget.value);
}} />
</td>
</tr>;
}
})
}
</>
);
};
HandleOpen = async (fileTitle: string) =>
{
const { fileId, newFileId, files, userName } = this.props;
let status: boolean = true;
if (newFileId)
{
let server = FileServer.GetInstance();
if (fileId != newFileId)
{
server._CurrentFilePath = "";
server.m_CurFileId = newFileId;
let code = await server.GetFileMD5(newFileId);
if (code)
{
let data = await PostJson(FileUrls.detail, { file_id: newFileId });
if (data.err_code === RequestStatus.Ok && data.files?.name)
{
server.currentFileInfo.name = data.files.name;
server.CurrentFileMd5 = code;
}
localStorage.setItem(StoreageKeys.LastOpenFileId, data.files?.file_id || "");
}
}
status = await this.OnClickOpenFile(userName, newFileId, fileTitle);
}
else
{
status = await this.OnClickOpenFile(userName, fileId, fileTitle);
}
if (!status)
{
AppToaster.show({
message: "打开图纸失败,请尝试打开其他历史记录图纸",
timeout: 3000,
intent: Intent.DANGER,
});
return;
}
if (this.props.isNotToaster)
app.Editor.ModalManage.m_PromisRes({ Status: ModalState.Ok });
app.Editor.ModalManage.Destory();
};
OnClickOpenFile = async (userName: string, fileId: string, fileTitle: string) =>
{
try
{
let url = FileHistoryFilesUrl + encodeURIComponent(userName + "//" + fileId + "//" + fileTitle);
let cadf = await FetchFile1(url + ".cad");
app.OpenFile(cadf);
return true;
}
catch {
return false;
}
};
render()
{
return (
<HTMLTable bordered={true} interactive={true} style={{ lineHeight: 0.5, width: "100%", padding: "5px 5px 0px 5px", border: "1px solid #DBDCDD" }}>
<thead>
<tr>
<th style={{ width: 50 }}></th>
<th style={{ width: 190 }}></th>
<th>
<Checkbox
label="只显示能还原记录"
style={{ position: 'absolute', right: "10px", fontSize: "12px", top: "15px" }}
checked={this.CanOpen}
onClick={(e) =>
{
this.LastOper = "";
this.CanOpen = !this.CanOpen;
e.currentTarget.blur();
}} />
</th>
</tr>
</thead>
<tbody>
{this.CanOpen ? this.CanOpenDataList() : this.AllDataList()}
</tbody>
</HTMLTable>
);
}
}

@ -1,7 +1,7 @@
import { Intent, Toaster } from "@blueprintjs/core"; import { Intent, Toaster } from "@blueprintjs/core";
import React from "react"; import React from "react";
import { app } from "../../ApplicationServices/Application"; import { app } from "../../ApplicationServices/Application";
import { FileHistoryFilesUrl, FileHistoryUrl, SignUrl } from "../../Common/HostUrl"; import { FileHistoryUrl, SignUrl } from "../../Common/HostUrl";
import { PostJson, RequestStatus } from "../../Common/Request"; import { PostJson, RequestStatus } from "../../Common/Request";
import { StoreageKeys } from "../../Common/StoreageKeys"; import { StoreageKeys } from "../../Common/StoreageKeys";
import { inflateBase64 } from "../../Common/inflate"; import { inflateBase64 } from "../../Common/inflate";
@ -109,7 +109,6 @@ export class OperLogs implements Command
files: allFiles, files: allFiles,
data: data, data: data,
fileName: this.fileName, fileName: this.fileName,
OnClickOpenFile: this.OnClickOpenFile,
isNotToaster: true, isNotToaster: true,
}); });
let Rm = await app.Editor.ModalManage.Wait(); let Rm = await app.Editor.ModalManage.Wait();
@ -131,30 +130,12 @@ export class OperLogs implements Command
time={time} time={time}
isOpenFile={this._IsOpenFile} isOpenFile={this._IsOpenFile}
Toaster={HistoryToaster} Toaster={HistoryToaster}
OnClickOpenFile={this.OnClickOpenFile}
/>, />,
timeout: time + 500, timeout: time + 500,
intent: Intent.NONE, intent: Intent.NONE,
}); });
return true; return true;
} }
//打开历史保存的文件图纸
private async OnClickOpenFile(userName: string, fileId: string, files: string[], number: number)
{
try
{
let fileName = files[number];
let url = FileHistoryFilesUrl + encodeURIComponent(userName + "//" + fileId + "//" + fileName);
let cadf = await FetchFile1(url + ".cad");
app.OpenFile(cadf);
return true;
}
catch
{
return false;
}
}
} }
export async function FetchFile1(url: string): Promise<CADFiler> export async function FetchFile1(url: string): Promise<CADFiler>

@ -2,7 +2,7 @@ import { Button, Classes, Icon, IToaster } from "@blueprintjs/core";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import React from "react"; import React from "react";
import { app } from "../../ApplicationServices/Application"; import { app } from "../../ApplicationServices/Application";
import { OpenHistoryList } from "./OpenHistoryBody"; import { OpenHistoryList } from "./OpenHistoryList";
export interface OperInfo export interface OperInfo
{ {
@ -23,7 +23,6 @@ export interface HistoryProp
time?: number, time?: number,
Toaster?: IToaster; Toaster?: IToaster;
newFileId?: string;//右键打开历史记录时文件id newFileId?: string;//右键打开历史记录时文件id
OnClickOpenFile: (userName: string, fileId: string, files: string[], number: number) => Promise<boolean>;
} }
@observer @observer
@ -60,7 +59,6 @@ export class OperLogsModal extends React.Component<HistoryProp, {}>
files={this.props.files} files={this.props.files}
newFileId={this.props.newFileId} newFileId={this.props.newFileId}
data={this.props.data} data={this.props.data}
OnClickOpenFile={this.props.OnClickOpenFile}
isNotToaster={this.props.isNotToaster} isNotToaster={this.props.isNotToaster}
/> />
</div> </div>

@ -295,7 +295,7 @@ export class FileServer extends Singleton
else else
{ {
let data = await PostJson(FileUrls.detail, { file_id: fid }); let data = await PostJson(FileUrls.detail, { file_id: fid });
if (data.err_code === RequestStatus.Ok && data.files) if (data.err_code === RequestStatus.Ok && data.files?.file)
{ {
let f: IFileInfo = { let f: IFileInfo = {
name: data.files.name, name: data.files.name,

Loading…
Cancel
Save