diff --git a/back/api/script.ts b/back/api/script.ts index 43f0d90f..60876fc5 100644 --- a/back/api/script.ts +++ b/back/api/script.ts @@ -23,7 +23,8 @@ export default (app: Router) => { return !fs.lstatSync(config.scriptPath + x).isDirectory(); }) .map((x) => { - return { title: x, value: x, key: x }; + const statObj = fs.statSync(config.scriptPath + x); + return { title: x, value: x, key: x, mtime: statObj.mtimeMs }; }), }); } catch (e) { @@ -54,34 +55,46 @@ export default (app: Router) => { celebrate({ body: Joi.object({ filename: Joi.string().required(), - path: Joi.string().required(), - content: Joi.string().required(), + path: Joi.string().allow(''), + content: Joi.string().allow(''), + originFilename: Joi.string().allow(''), }), }), async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { - let { filename, path, content } = req.body as { + let { filename, path, content, originFilename } = req.body as { filename: string; path: string; content: string; + originFilename: string; }; + if (!path) { + path = config.scriptPath; + } if (!path.endsWith('/')) { path += '/'; } if (config.writePathList.every((x) => !path.startsWith(x))) { return res.send({ - code: 400, - data: '文件路径错误,可保存目录/ql/scripts、/ql/config、/ql/jbot、/ql/bak', + code: 430, + data: '文件路径禁止访问', }); } + + const originFilePath = `${path}${originFilename.replace(/\//g, '')}`; const filePath = `${path}${filename.replace(/\//g, '')}`; - const bakPath = '/ql/bak'; - if (fs.existsSync(filePath)) { - if (!fs.existsSync(bakPath)) { - fs.mkdirSync(bakPath); + if (fs.existsSync(originFilePath)) { + if (!fs.existsSync(config.bakPath)) { + fs.mkdirSync(config.bakPath); + } + fs.copyFileSync( + originFilePath, + `${config.bakPath}${originFilename.replace(/\//g, '')}`, + ); + if (filename !== originFilename) { + fs.unlinkSync(originFilePath); } - fs.copyFileSync(filePath, bakPath); } fs.writeFileSync(filePath, content); return res.send({ code: 200 }); @@ -139,4 +152,35 @@ export default (app: Router) => { } }, ); + + route.post( + '/scripts/download', + celebrate({ + body: Joi.object({ + filename: Joi.string().required(), + }), + }), + async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + let { filename } = req.body as { + filename: string; + }; + const filePath = `${config.scriptPath}${filename}`; + // const stats = fs.statSync(filePath); + // res.set({ + // 'Content-Type': 'application/octet-stream', //告诉浏览器这是一个二进制文件 + // 'Content-Disposition': 'attachment; filename=' + filename, //告诉浏览器这是一个需要下载的文件 + // 'Content-Length': stats.size //文件大小 + // }); + // fs.createReadStream(filePath).pipe(res); + return res.download(filePath, filename, (err) => { + return next(err); + }); + } catch (e) { + logger.error('🔥 error: %o', e); + return next(e); + } + }, + ); }; diff --git a/back/config/index.ts b/back/config/index.ts index bd0c3e3b..f3ba748a 100644 --- a/back/config/index.ts +++ b/back/config/index.ts @@ -5,7 +5,7 @@ import { createRandomString } from './util'; process.env.NODE_ENV = process.env.NODE_ENV || 'development'; const envFound = dotenv.config(); -const rootPath = path.resolve(__dirname, '../../'); +const rootPath = process.cwd(); const envFile = path.join(rootPath, 'config/env.sh'); const confFile = path.join(rootPath, 'config/config.sh'); const sampleFile = path.join(rootPath, 'sample/config.sample.sh'); @@ -15,6 +15,7 @@ const authConfigFile = path.join(rootPath, 'config/auth.json'); const extraFile = path.join(rootPath, 'config/extra.sh'); const configPath = path.join(rootPath, 'config/'); const scriptPath = path.join(rootPath, 'scripts/'); +const bakPath = path.join(rootPath, 'bak/'); const samplePath = path.join(rootPath, 'sample/'); const logPath = path.join(rootPath, 'log/'); const authError = '错误的用户名密码,请重试'; @@ -46,6 +47,7 @@ export default { api: { prefix: '/api', }, + rootPath, configString, loginFaild, authError, @@ -72,5 +74,6 @@ export default { 'crontab.list', 'env.sh', ], - writePathList: ['/ql/scripts/', '/ql/config/', '/ql/jbot/', '/ql/bak/'], + writePathList: [configPath, scriptPath], + bakPath, }; diff --git a/bak/bv.log b/bak/bv.log new file mode 100644 index 00000000..d5a819bd --- /dev/null +++ b/bak/bv.log @@ -0,0 +1 @@ +123123123 \ No newline at end of file diff --git a/bak/bv3.log b/bak/bv3.log new file mode 100644 index 00000000..a0e8762a --- /dev/null +++ b/bak/bv3.log @@ -0,0 +1,8 @@ +123123123sdfasdfdjflsdjflad + + + +所肩负的拉三季度福利静安寺两地分居阿临时冻结发了;阿克苏剪短发拉加快速度联发科;就的说法 + +阿斯顿发斯蒂芬是打发斯蒂芬阿斯顿发斯蒂芬 +// 阿斯顿发双方都 \ No newline at end of file diff --git a/src/pages/log/index.tsx b/src/pages/log/index.tsx index c6038307..e0ad75ec 100644 --- a/src/pages/log/index.tsx +++ b/src/pages/log/index.tsx @@ -41,7 +41,7 @@ function getFilterData(keyword: string, data: any) { const Log = ({ headerStyle, isPhone, theme }: any) => { const [title, setTitle] = useState('请选择日志文件'); const [value, setValue] = useState('请选择日志文件'); - const [select, setSelect] = useState(); + const [select, setSelect] = useState(); const [data, setData] = useState([]); const [filterData, setFilterData] = useState([]); const [loading, setLoading] = useState(false); @@ -84,6 +84,9 @@ const Log = ({ headerStyle, isPhone, theme }: any) => { }; const onSelect = (value: any, node: any) => { + if (node.key === select || !value) { + return; + } setValue('加载中...'); setSelect(value); setTitle(node.parent || node.value); @@ -147,6 +150,7 @@ const Log = ({ headerStyle, isPhone, theme }: any) => { treeData={filterData} showIcon={true} height={height} + selectedKeys={[select]} showLine={{ showLeafIcon: true }} onSelect={onTreeSelect} > diff --git a/src/pages/script/editModal.tsx b/src/pages/script/editModal.tsx index 04e8c72e..ccec7b8c 100644 --- a/src/pages/script/editModal.tsx +++ b/src/pages/script/editModal.tsx @@ -41,7 +41,6 @@ const EditModal = ({ const [saveModalVisible, setSaveModalVisible] = useState(false); const [settingModalVisible, setSettingModalVisible] = useState(false); - const [isNewFile, setIsNewFile] = useState(false); const [log, setLog] = useState(''); const { theme } = useTheme(); const editorRef = useRef(null); @@ -54,7 +53,6 @@ const EditModal = ({ const newMode = LangMap[value.slice(-3)] || ''; setFileName(value); setLanguage(newMode); - setIsNewFile(false); getDetail(node); }; @@ -64,23 +62,14 @@ const EditModal = ({ }); }; - const createFile = () => { - setFileName(`未命名${prefixMap[language]}`); - setIsNewFile(true); - setValue(''); - }; - const run = () => {}; useEffect(() => { - if (!currentFile) { - createFile(); - } else { + if (currentFile) { setFileName(currentFile); setValue(content as string); } - setIsNewFile(!currentFile); - }, []); + }, [currentFile, content]); return ( 设置 - , ] : [ - , - , + +