UNPKG

@daiyu-5577/quickbuild

Version:

front-end build service

275 lines (274 loc) 18.2 kB
var _a; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React, { useState, useRef, useEffect } from "react"; import { io } from "socket.io-client"; import dayjs from "dayjs"; let baseRoute = '/quick'; if (((_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.NODE_ENV) == 'development') { baseRoute = ''; } const getFromatTime = (t = +dayjs(), format = 'YYYY-MM-DD HH:mm:ss') => { return dayjs(t).format(format); }; function replaceErrorMsg(msg) { const txt = msg .replace(/warn/ig, `<b style="color: yellow;">Warn</b>`) .replace(/error/ig, `<b style="color: red;">Error</b>`); return txt; } const useIsScrollBottom = (dom, onScrollEnd) => { const isScroll = useRef(true); const buildScrollToBottom = (isForce = false) => { if (!isScroll.current && !isForce) return; setTimeout(() => { var _a, _b; (_a = dom === null || dom === void 0 ? void 0 : dom.current) === null || _a === void 0 ? void 0 : _a.scrollTo({ left: 0, top: (_b = dom === null || dom === void 0 ? void 0 : dom.current) === null || _b === void 0 ? void 0 : _b.scrollHeight, behavior: 'smooth' }); }, 200); }; useEffect(() => { var _a; if (!dom) return; const chatScrollFn = () => { const { offsetHeight, scrollHeight, scrollTop } = dom.current; isScroll.current = scrollHeight - offsetHeight - scrollTop < 100; if (isScroll.current) { onScrollEnd === null || onScrollEnd === void 0 ? void 0 : onScrollEnd(); } }; (_a = dom === null || dom === void 0 ? void 0 : dom.current) === null || _a === void 0 ? void 0 : _a.addEventListener('scroll', chatScrollFn); }, []); return [isScroll, buildScrollToBottom]; }; export default function Home() { var _a, _b, _c; const userId = useRef(''); const chatScrollDOM = useRef(null); const buildScrollDOM = useRef(null); const socket = useRef(null); const [unreaChatMsg, setUnreaChatMsg,] = useState(0); const [unreaCBuildMsg, setUnreaBuilddMsg] = useState(0); const [isChatScroll, chatScrollToBottom] = useIsScrollBottom(chatScrollDOM, () => setUnreaChatMsg(0)); const [isBuildScroll, buildScrollToBottom] = useIsScrollBottom(buildScrollDOM, () => setUnreaBuilddMsg(0)); const [ipt, setIpt] = useState(''); const [chatMsgList, setChatMsgList] = useState([]); const [buildMsgList, setBuildMsgList] = useState([]); const [commandList, setCommandList] = useState([]); const [isShowImgUrl, setIsShowImgUrl] = useState(''); const [pkgList, setPkgList] = useState([]); const [choosePkgs, setChoose] = useState(new Set()); const [chooseBranch, setChooseBranch] = useState(((_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.NODE_ENV) == 'development' ? 'dev' : 'master'); const [isShowPkg, setIsShowPkg] = useState(false); const [logList, setlogList] = useState([]); const [curLogTab, setCurLogTab] = useState(0); const [isShowLog, setisShowLog] = useState(false); const handleCommand = (command) => { var _a; if (!((_a = socket.current) === null || _a === void 0 ? void 0 : _a.id) && !command) return; handleSend(command); }; const handleSend = (val) => { var _a; const msg = val || ipt; if (!((_a = socket.current) === null || _a === void 0 ? void 0 : _a.id) || !msg) return; socket.current.emit('on:msg-chat', { ctxType: 'ctx:txt', msg: msg || ipt }); setIpt(''); }; const handleSendImg = (e) => { var _a; const files = e.target.files; if (!((_a = socket.current) === null || _a === void 0 ? void 0 : _a.id) || !(files === null || files === void 0 ? void 0 : files.length)) return; const list = Array.from(files).map(v => ({ file: v, name: v.name, size: v.size, type: v.type, })); socket.current.emit('on:msg-chat', { ctxType: 'ctx:imgs', files: list, }); e.target.value = ''; }; const handleShowPkg = (v) => { setIsShowPkg(v); }; const handleBuild = () => { if (choosePkgs.size == 0) { alert('请选择仓库'); return; } if (chooseBranch == '') { alert('请选择分支'); return; } fetch(`${baseRoute}/api/addTask`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ packagePaths: Array.from(choosePkgs), branch: chooseBranch, }) }) .then(res => res.json()) .then(res => { if (!(res === null || res === void 0 ? void 0 : res.success)) { alert(`${(res === null || res === void 0 ? void 0 : res.message) || '任务添加失败'}`); return; } setIsShowPkg(false); setChoose(new Set()); }) .catch(err => { alert(`${(err === null || err === void 0 ? void 0 : err.message) || '任务添加失败'}`); }); }; const httpGetAllPkg = () => { fetch(`${baseRoute}/api/getAllPackage`) .then(res => res.json()) .then(res => { var _a; setPkgList(((_a = res === null || res === void 0 ? void 0 : res.list) === null || _a === void 0 ? void 0 : _a.sort()) || []); }); }; const httpGetAllLog = () => { fetch(`${baseRoute}/api/getLogFiles`) .then(res => res.json()) .then(res => { setlogList((res === null || res === void 0 ? void 0 : res.tabs) || []); }); }; const httpGetAllCommand = () => { fetch(`${baseRoute}/api/getAllCommand`) .then(res => res.json()) .then(res => { setCommandList((res === null || res === void 0 ? void 0 : res.list) || []); }); }; useEffect(() => { console.log('useEffect - home'); const localToken = localStorage.getItem('token'); const localUserId = localStorage.getItem('userId'); userId.current = localUserId || ''; socket.current = io('/', { path: `${baseRoute}/ws/`, reconnectionDelayMax: 10000, auth: { lastChatId: 0, lastMBuildId: 0, token: localToken } }); socket.current.on('connect_error', (error) => { console.log('connect_error', error); if ((error === null || error === void 0 ? void 0 : error.message) == 'invalid token') { localStorage.removeItem('token'); localStorage.removeItem('userId'); window.location.href = `${baseRoute}/page/login`; } }); socket.current.on('on:msg-getAllChat', (res) => { setChatMsgList([...chatMsgList, ...res]); chatScrollToBottom(); }); socket.current.on('on:msg-getAllBuild', (res) => { setBuildMsgList([...buildMsgList, ...res]); buildScrollToBottom(); }); socket.current.on('on:msg-chat', (res) => { setChatMsgList((old => { if (isChatScroll.current) { chatScrollToBottom(); } else { setUnreaChatMsg(v => v + 1); } socket.current.auth.lastChatId = res.id; return [...old, res]; })); }); socket.current.on('on:msg-build', (res) => { setBuildMsgList((old => { const curMsg = old.find(v => v.taskId == res.taskId); if (curMsg) { curMsg.msg = curMsg.msg + res.msg; curMsg.status = res.status; return [...old]; } if (isBuildScroll.current) { buildScrollToBottom(); } else { setUnreaBuilddMsg(v => v + 1); } socket.current.auth.lastMBuildId = res.id; return [...old, res]; })); }); }, []); useEffect(() => { const enterFn = (e) => { if (e.keyCode == 13 && e.ctrlKey) { handleSend(); } }; window.addEventListener('keydown', enterFn); return () => { window.removeEventListener('keydown', enterFn); }; }, [ipt]); useEffect(() => { httpGetAllPkg(); httpGetAllCommand(); }, []); return (_jsxs(React.Fragment, { children: [_jsxs("div", { className: "home", children: [_jsx("div", { className: "opts", children: _jsxs("div", { className: "opt-scroll", children: [_jsx("div", { onClick: () => { location.reload(); }, className: "opt-item cursor", children: "\u5237\u65B0" }), _jsx("div", { onClick: () => { handleShowPkg(true); }, className: "opt-item cursor", children: "\u6784\u5EFA" }), _jsx("div", { onClick: () => { httpGetAllLog(); setisShowLog(true); }, className: "opt-item cursor", children: "logs" })] }) }), _jsxs("div", { className: "buildBox", children: [_jsx("div", { className: "title", children: _jsx("span", { children: "build notice" }) }), _jsxs("div", { className: "buildNoticeBox", children: [!isBuildScroll.current && unreaCBuildMsg > 0 && _jsxs("div", { onClick: () => { setUnreaBuilddMsg(0); buildScrollToBottom(true); }, className: "unreadChatMsg", children: ["\u672A\u8BFB\u6D88\u606F x", unreaCBuildMsg] }), _jsx("div", { ref: buildScrollDOM, className: "buildNoticeBoxScroll", children: buildMsgList.map((v, i) => (_jsxs("div", { className: "msg-item", children: [_jsxs("div", { className: "item-name", children: [_jsxs("div", { className: "item-name-txt", children: [_jsx("span", { children: v.name }), " - ", _jsxs("span", { className: "name-txt-branch", children: [v.branch, "\u5206\u652F"] })] }), _jsx("div", { className: "item-time-txt", children: getFromatTime(v.timestamp) })] }), _jsxs("div", { className: "item-ctx-wrap", children: [_jsxs("div", { className: "item-info", children: [_jsxs("div", { className: "info-txt", children: ["\u5206\u652F\uFF1A", v.branch] }), _jsxs("div", { className: "info-txt", children: ["\u6784\u5EFAtaskId\uFF1A", v.taskId] }), _jsxs("div", { className: "info-txt", children: ["\u6784\u5EFApackagePath\uFF1A", v.task.packagePath] }), _jsxs("div", { className: "info-txt", children: ["\u6784\u5EFAcommit\uFF1A", v.task.commit] }), _jsxs("div", { className: "info-txt", children: ["\u4EFB\u52A1\u521B\u5EFA\u65F6\u95F4\uFF1A", v.task.time] }), v.buildLogPath && _jsxs("div", { className: "info-txt", children: ["\u6784\u5EFAlog\uFF1A", _jsx("a", { target: "_blank", href: v.buildLogPath, children: "\u67E5\u770B\u65E5\u5FD7" })] })] }), _jsx("pre", { dangerouslySetInnerHTML: { __html: replaceErrorMsg(v.msg) }, className: "item-msg" }), _jsx("div", { className: `status status-${v.status}`, children: v.status == 1 ? '构建中...' : v.status == 2 ? '构建成功' : '构建失败' })] })] }, i))) })] })] }), _jsxs("div", { className: "chatBox", children: [_jsx("div", { className: "title", children: "chat room" }), _jsxs("div", { className: "msgBox", children: [!isChatScroll.current && unreaChatMsg > 0 && _jsxs("div", { onClick: () => { setUnreaChatMsg(0); chatScrollToBottom(true); }, className: "unreadChatMsg", children: ["\u672A\u8BFB\u6D88\u606F x", unreaChatMsg] }), _jsx("div", { ref: chatScrollDOM, className: "msgBoxScroll", children: chatMsgList.map((v, i) => { var _a, _b; return (_jsxs("div", { className: `msg-item ${v.userId == userId.current ? 'msg-item-self' : ''}`, children: [_jsxs("div", { className: "item-name", children: [_jsx("div", { className: "item-name-txt", children: v.name || v.id }), _jsx("div", { className: "item-time-txt", children: getFromatTime(v.timestamp) })] }), (v === null || v === void 0 ? void 0 : v.msg) && _jsx("pre", { className: "item-msg", children: v.msg }), !!((_a = v === null || v === void 0 ? void 0 : v.files) === null || _a === void 0 ? void 0 : _a.length) && _jsx("div", { className: "item-imgs", children: v.ctxType == 'ctx:imgs' && ((_b = v.files) === null || _b === void 0 ? void 0 : _b.map((v, i) => { return ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv'].some(suffix => v.endsWith(suffix)) ? _jsx("video", { loop: true, muted: true, autoPlay: true, "webkit-playsinline": 'true', playsInline: true, onClick: () => setIsShowImgUrl(v), src: v }, i) : _jsx("img", { onClick: () => setIsShowImgUrl(v), src: v }, i); })) })] }, i)); }) })] }), _jsxs("div", { className: "command-list", children: [_jsxs("select", { onChange: (e) => handleCommand(e.target.value), value: 0, className: "commands", children: [_jsx("option", { value: "", children: "\u5FEB\u6377\u547D\u4EE4" }), commandList.map((v, i) => { return _jsxs("option", { value: v.command, children: [v.command, "-", v.desc] }, i); })] }), _jsx("div", { onClick: () => handleShowPkg(true), className: "aad-build aad-img cursor atouch", children: "\u9009\u62E9\u6784\u5EFA" }), _jsxs("div", { className: "aad-img cursor atouch", children: ["\u9009\u62E9\u56FE\u7247", _jsx("input", { onChange: (e) => handleSendImg(e), type: "file", accept: "image/*", multiple: true })] })] }), _jsxs("div", { className: "textareaBox", children: [_jsx("pre", { className: "textarea-auto-height", children: ipt }), _jsxs("div", { className: "textarea-ctx", children: [_jsx("textarea", { onChange: (e) => setIpt(e.currentTarget.value), value: ipt }), _jsxs("button", { onClick: () => handleSend(), className: `btn-send ${!!ipt.length ? '' : 'btn-disabled'}`, children: ["\u53D1\u9001", _jsx("br", {}), "ctr + enter"] })] })] })] }), !!isShowImgUrl && _jsxs("div", { className: "showImg", children: [_jsx("div", { className: "prewiew", children: ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv'].some(suffix => isShowImgUrl.endsWith(suffix)) ? _jsx("video", { loop: true, autoPlay: true, "webkit-playsinline": 'true', playsInline: true, src: isShowImgUrl }) : _jsx("img", { src: isShowImgUrl }) }), _jsx("div", { onClick: () => setIsShowImgUrl(''), className: "exit cursor", children: "X" })] }), !!isShowPkg && _jsx("div", { className: "pkgBox", children: _jsxs("div", { className: "pkgBox-cnt", children: [_jsx("div", { className: "pkgBox-title", children: "\u5206\u652F" }), _jsx("div", { className: "pkgBox-ipt", children: _jsx("input", { value: chooseBranch, onInput: e => setChooseBranch(e.currentTarget.value.trim()), type: "text" }) }), _jsx("div", { className: "pkgBox-title", children: "\u4ED3\u5E93" }), _jsx("div", { className: "pkgBox-list", children: pkgList.map((v, i) => { return _jsx("div", { onClick: () => { if (choosePkgs.has(v)) { choosePkgs.delete(v); } else { choosePkgs.add(v); } setChoose(new Set(choosePkgs)); }, className: `pkgBox-list-item cursor ${choosePkgs.has(v) ? 'active' : ''}`, children: v }, i); }) }), _jsx("div", { onClick: handleBuild, className: "btn-build cursor", children: "\u6784\u5EFA" }), _jsx("div", { onClick: () => setIsShowPkg(false), className: "exit cursor", children: "X" })] }) }), !!isShowLog && _jsx("div", { className: "logBox", children: _jsxs("div", { className: "pkgBox-cnt", children: [_jsx("div", { className: "pkgBox-title", children: "logs" }), _jsx("div", { className: "tabs", children: logList.map((v, i) => (_jsx("div", { onClick: () => setCurLogTab(i), className: `tab-item cursor ${curLogTab == i ? 'active' : ''}`, children: v.title }, i))) }), _jsx("div", { className: "pkgBox-list", children: (_c = (_b = logList[curLogTab]) === null || _b === void 0 ? void 0 : _b.list) === null || _c === void 0 ? void 0 : _c.map((cv, ci) => (_jsx("div", { className: `pkgBox-list-item`, children: _jsx("a", { target: "_blank", href: cv.path, children: cv === null || cv === void 0 ? void 0 : cv.name }) }, ci))) }), _jsx("div", { onClick: () => setisShowLog(false), className: "exit cursor", children: "X" })] }) })] }), _jsx("link", { rel: "stylesheet/less", type: "text/css", href: `${baseRoute}/static/pages/home.less` })] })); }