Commit 77262da6 authored by chenshouchao's avatar chenshouchao

feat: 日志完成

parent 249b692d
...@@ -260,13 +260,14 @@ class CloudEController { ...@@ -260,13 +260,14 @@ class CloudEController {
} }
// 获取文件文本内容(字符串) // 获取文件文本内容(字符串)
static JobFileDownloadText(url: any, filetoken: string, projectId: string) { static JobFileDownloadText(url: any, filetoken: string, projectId: string, fileServerEndPoint: string = '') {
if (ApiUtils.getAuthorizationHeaders(headers)) { if (ApiUtils.getAuthorizationHeaders(headers)) {
url = url + urlToken(filetoken, projectId); url = url + urlToken(filetoken, projectId);
headers["Cache-Control"] = "no-cache"; headers["Cache-Control"] = "no-cache";
headers["Content-Type"] = "multipart/form-data"; headers["Content-Type"] = "multipart/form-data";
let origin = fileServerEndPoint ? fileServerEndPoint : APIOPTION()
return axios.get( return axios.get(
APIOPTION() + "/download" + url + "&showhidden=false", origin + "/download" + url + "&showhidden=false",
{ {
headers: headers, headers: headers,
} }
......
...@@ -57,3 +57,7 @@ ...@@ -57,3 +57,7 @@
.status { .status {
margin-left: 4px; margin-left: 4px;
} }
.LogViewBox {
margin: 0 24px;
position: relative;
}
import style from "./index.module.css"; import style from "./index.module.css";
import React, { useState, useEffect, useMemo } from "react"; import React, { useState, useEffect, useMemo } from "react";
import LogView from "@/views/Project/ProjectJobDetail/LogView"; import LogView from "@/views/ResourceCenter/components/LogView";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import BasicInfo, { import BasicInfo, {
IInfoItem, IInfoItem,
...@@ -20,6 +20,7 @@ const SeeEnv = () => { ...@@ -20,6 +20,7 @@ const SeeEnv = () => {
const [info, setInfo] = useState<any>({}); const [info, setInfo] = useState<any>({});
const [infoListTop, setInfoListTop] = useState<Array<IInfoItem>>([]); const [infoListTop, setInfoListTop] = useState<Array<IInfoItem>>([]);
const [infoListBot, setInfoListBot] = useState<Array<IInfoItem>>([]); const [infoListBot, setInfoListBot] = useState<Array<IInfoItem>>([]);
const [logs, setLogs] = useState<Array<any>>([]);
const getStatus = (item: any) => { const getStatus = (item: any) => {
if (item.status === "PENDING") { if (item.status === "PENDING") {
...@@ -88,6 +89,14 @@ const SeeEnv = () => { ...@@ -88,6 +89,14 @@ const SeeEnv = () => {
value: data.desc, value: data.desc,
}, },
]); ]);
setLogs(
data.tasks
.filter((task: any) => task.outLog)
.map((task: any) => ({
logName: `${task.title}.log`,
logPath: task.outLog,
}))
);
}, },
}); });
useEffect(() => { useEffect(() => {
...@@ -124,6 +133,9 @@ const SeeEnv = () => { ...@@ -124,6 +133,9 @@ const SeeEnv = () => {
</div> </div>
<div className={style.logsBox}> <div className={style.logsBox}>
<div className={style.logsTitle}>日志</div> <div className={style.logsTitle}>日志</div>
<div className={style.LogViewBox}>
<LogView logs={logs}></LogView>
</div>
</div> </div>
</div> </div>
); );
......
.logView {
position: absolute;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1002;
}
.logViewBox {
background: #282c34;
}
.close {
position: absolute;
right: 0;
top: -28px;
cursor: pointer;
color: #fff;
}
.logViewTop {
position: relative;
width: 100%;
background-color: #1d2126;
display: flex;
font-size: 12px;
color: #8a9099;
overflow: hidden;
}
.leftButton {
width: 48px;
height: 32px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-right: 1px solid #10141a;
background-color: #1d2126;
}
.rightButton {
width: 48px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-left: 1px solid #10141a;
background-color: #1d2126;
}
.middleFixed {
width: calc(100% - 98px);
position: relative;
overflow: hidden;
}
.middleDynamic {
display: flex;
position: absolute;
left: 0;
transition: left 0.4s ease-in-out;
}
.logTitle {
display: flex;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex-shrink: 0;
align-items: center;
height: 32px;
line-height: 20px;
padding: 0 20px;
cursor: pointer;
border-right: 1px solid #10141a;
}
.logTitle:hover {
background-color: #23272e;
}
.logName {
max-width: 90px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.logTitleSelected {
background: #282c34;
color: #ffffff;
}
.fileIcon {
width: 14px !important;
margin-right: 4px;
}
.logViewContent {
position: relative;
box-sizing: border-box;
height: calc(100vh - 148px);
padding: 24px 32px 0;
color: #d1d6de;
white-space: pre-wrap;
word-break: break-word;
overflow: overlay;
font-size: 14px;
line-height: 22px;
}
.logViewContentMask {
height: 24px;
width: calc(100% - 64px);
background-color: #282c34;
position: absolute;
top: 32px;
left: 32px;
z-index: 1005;
}
.logViewContent::-webkit-scrollbar-track {
background-color: #282c34;
}
.logViewBottom {
display: flex;
align-items: center;
justify-content: end;
height: 76px;
padding-right: 24px;
}
.gradientBox {
position: absolute;
right: 49px;
width: 28px;
height: 32px;
background: linear-gradient(90deg, rgba(29, 33, 38, 0) 0%, #1d2126 100%);
}
import { useState, useEffect } from "react";
import classnames from "classnames";
import style from "./index.module.css";
import MyTooltip from "@/components/mui/MyTooltip";
import InsertDriveFileOutlinedIcon from "@mui/icons-material/InsertDriveFileOutlined";
import CloudEController from "@/api/fileserver/CloudEController";
import useMyRequest from "@/hooks/useMyRequest";
import { getPublicProject } from "@/api/resourceCenter";
import { getDataFileToken, hpczone } from "@/api/project_api";
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import useWindowSize from "@/hooks/useWindowSize";
type LogViewProps = {
logs: any[];
};
const LogView = (props: LogViewProps) => {
const { logs } = props;
const [hpczoneList, setHpczoneList] = useState<Array<any>>([]);
const [publicProjectId, setPublicProjectId] = useState("");
const [publicZoneId, setPublicZoneId] = useState("");
const [fileToken, setFileToken] = useState("");
const { width, height } = useWindowSize();
// 当前选择的日志
const [logCurrent, setLogCurrent] = useState<number>(0);
// 当前日志的内容文本
const [logText, setLogText] = useState("");
// 当前日志路径
const [logPath, setLogPath] = useState("");
const [displacement, setDisplacement] = useState(0);
const [middleDynamicWidth, setMiddleDynamicWidth] = useState(0);
const [leftButtonColor, setLeftButtonColor] = useState("#585D62");
const [rightButtonColor, setRightButtonColor] = useState("#585D62");
const { run: getPublicProjectFn } = useMyRequest(getPublicProject, {
onSuccess: (res: any) => {
setPublicProjectId(res.data[0].id);
setPublicZoneId(res.data[0].zoneId);
getDataFileTokenFn({ id: res.data[0].id });
},
});
const { run: getDataFileTokenFn } = useMyRequest(getDataFileToken, {
onSuccess: (res: any) => {
setFileToken(res.data);
},
});
useEffect(() => {
getPublicProjectFn();
}, [getPublicProjectFn]);
const { run: hpczoneFn } = useMyRequest(hpczone, {
onSuccess: (res: any) => {
setHpczoneList(res.data);
},
});
useEffect(() => {
hpczoneFn();
}, [hpczoneFn]);
useEffect(() => {
setLogPath(logs[logCurrent]?.logPath);
}, [logs, logCurrent]);
// 请求日志文本
useEffect(() => {
if (logPath) {
const path = logPath.slice(12);
let origin = "";
hpczoneList.forEach((item) => {
if (item.id === publicZoneId) {
origin = item?.storageConfig?.fileServerEndPoint;
}
});
if (path && fileToken && publicProjectId && origin) {
CloudEController.JobFileDownloadText(
path,
fileToken as string,
publicProjectId as string,
origin
)?.then((res) => {
setLogText(res.data);
});
} else {
setLogText("");
}
} else {
setLogText("");
}
}, [logPath, fileToken, hpczoneList, publicProjectId, publicZoneId]);
// 选择日志时改变日志路径
useEffect(() => {
setLogPath(logs[logCurrent]?.logPath);
}, [logCurrent, logs]);
//获取盒子的总宽度,用于滑动效果判断
useEffect(() => {
const box = document.getElementById("middleDynamic");
setMiddleDynamicWidth(box ? box.offsetWidth : 0);
}, []);
useEffect(() => {
if (middleDynamicWidth < width - 97) {
setLeftButtonColor("#585D62");
setRightButtonColor("#585D62");
}
if (displacement === 0) {
setLeftButtonColor("#585D62");
} else {
setLeftButtonColor("#C0C5CD");
}
if (
middleDynamicWidth > width - 97 &&
displacement !== -middleDynamicWidth + width - 97
) {
setRightButtonColor("#C0C5CD");
} else {
setRightButtonColor("#585D62");
}
}, [width, middleDynamicWidth, displacement]);
// 下载当前日志
// const handleDownLoad = () => {
// const path = logPath.slice(12);
// CloudEController.JobFileDownload(
// path,
// fileToken as string,
// publicProjectId as string
// );
// };
const rightClick = () => {
if (middleDynamicWidth < width - 97) {
return;
}
if (-displacement > middleDynamicWidth - width * 1.8 + 97) {
setDisplacement(-middleDynamicWidth + width - 97);
return;
}
const newDisplacement = displacement - width * 0.8;
setDisplacement(newDisplacement);
};
const leftClick = () => {
if (-displacement < width * 0.8) {
setDisplacement(0);
return;
}
const newDisplacement = displacement + width * 0.8;
setDisplacement(newDisplacement);
};
return (
<div className={style.logViewBox}>
<div className={style.logViewContentMask}></div>
<div className={style.logViewTop}>
<div
className={style.leftButton}
onClick={leftClick}
style={{
color: leftButtonColor,
cursor: leftButtonColor === "#585D62" ? "default" : "pointer",
}}
>
<ChevronLeftIcon />
</div>
<div className={style.middleFixed}>
<div
className={style.middleDynamic}
id="middleDynamic"
style={{ left: `${displacement}px` }}
>
{logs.map((item: any, index: number) => {
return (
<MyTooltip
title={item.logName}
placement="bottom"
arrow={false}
enterDelay={1000}
>
<div
key={index}
onClick={() => {
setLogCurrent(index);
}}
className={classnames({
[style.logTitle]: true,
[style.logTitleSelected]: index === logCurrent,
})}
>
<InsertDriveFileOutlinedIcon className={style.fileIcon} />
<span className={style.logName}>{item.logName}</span>
</div>
</MyTooltip>
);
})}
</div>
</div>
<div className={style.gradientBox}></div>
<div
className={style.rightButton}
onClick={rightClick}
style={{
color: rightButtonColor,
cursor: rightButtonColor === "#585D62" ? "default" : "pointer",
}}
>
<ChevronRightIcon />
</div>
</div>
<div className={style.logViewContent}>{logText}</div>
{/* <div className={style.logViewBottom}>
<MyButton text="下载当前日志" onClick={handleDownLoad} />
</div> */}
</div>
);
};
export default LogView;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment