From 75fca715e33238ce202bb145de3e9c4f74ab4a8e Mon Sep 17 00:00:00 2001 From: whyour Date: Tue, 11 Oct 2022 22:16:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=8E=AF=E5=A2=83=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/api/env.ts | 46 +++++++++++++++++++++++++++++++++++++++ back/services/cronView.ts | 8 +++---- back/services/env.ts | 8 +++---- src/pages/env/index.tsx | 40 ++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 8 deletions(-) diff --git a/back/api/env.ts b/back/api/env.ts index 4a32b58c..f542339d 100644 --- a/back/api/env.ts +++ b/back/api/env.ts @@ -3,8 +3,21 @@ import { Container } from 'typedi'; import EnvService from '../services/env'; import { Logger } from 'winston'; import { celebrate, Joi } from 'celebrate'; +import multer from 'multer'; +import config from '../config'; +import fs from 'fs'; const route = Router(); +const storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, config.scriptPath); + }, + filename: function (req, file, cb) { + cb(null, file.originalname); + }, +}); +const upload = multer({ storage: storage }); + export default (app: Router) => { app.use('/envs', route); @@ -177,4 +190,37 @@ export default (app: Router) => { } }, ); + + route.post( + '/upload', + upload.single('env'), + async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const envService = Container.get(EnvService); + const fileContent = await fs.promises.readFile(req!.file!.path, 'utf8'); + const parseContent = JSON.parse(fileContent); + const data = Array.isArray(parseContent) + ? parseContent + : [parseContent]; + if (data.every((x) => x.name && x.value)) { + const result = await envService.create( + data.map((x) => ({ + name: x.name, + value: x.value, + remarks: x.remarks, + })), + ); + return res.send({ code: 200, data: result }); + } else { + return res.send({ + code: 400, + message: '文件缺少name或者value字段,参考导出文件格式', + }); + } + } catch (e) { + return next(e); + } + }, + ); }; diff --git a/back/services/cronView.ts b/back/services/cronView.ts index 51a6f6bc..bab86cd6 100644 --- a/back/services/cronView.ts +++ b/back/services/cronView.ts @@ -76,12 +76,12 @@ export default class CronViewService { const views = await this.list(); if (toIndex === 0 || toIndex === views.length - 1) { targetPosition = isUpward - ? views[0].position * 2 - : views[toIndex].position / 2; + ? views[0].position! * 2 + : views[toIndex].position! / 2; } else { targetPosition = isUpward - ? (views[toIndex].position + views[toIndex - 1].position) / 2 - : (views[toIndex].position + views[toIndex + 1].position) / 2; + ? (views[toIndex].position! + views[toIndex - 1].position!) / 2 + : (views[toIndex].position! + views[toIndex + 1].position!) / 2; } const newDoc = await this.update({ id, diff --git a/back/services/env.ts b/back/services/env.ts index be576b4c..266afe90 100644 --- a/back/services/env.ts +++ b/back/services/env.ts @@ -67,12 +67,12 @@ export default class EnvService { const envs = await this.envs(); if (toIndex === 0 || toIndex === envs.length - 1) { targetPosition = isUpward - ? envs[0].position * 2 - : envs[toIndex].position / 2; + ? envs[0].position! * 2 + : envs[toIndex].position! / 2; } else { targetPosition = isUpward - ? (envs[toIndex].position + envs[toIndex - 1].position) / 2 - : (envs[toIndex].position + envs[toIndex + 1].position) / 2; + ? (envs[toIndex].position! + envs[toIndex - 1].position!) / 2 + : (envs[toIndex].position! + envs[toIndex + 1].position!) / 2; } const newDoc = await this.update({ id, diff --git a/src/pages/env/index.tsx b/src/pages/env/index.tsx index e30baa00..dd9e8d3e 100644 --- a/src/pages/env/index.tsx +++ b/src/pages/env/index.tsx @@ -9,6 +9,8 @@ import { Typography, Tooltip, Input, + UploadProps, + Upload, } from 'antd'; import { EditOutlined, @@ -16,6 +18,7 @@ import { SyncOutlined, CheckCircleOutlined, StopOutlined, + UploadOutlined, } from '@ant-design/icons'; import config from '@/utils/config'; import { PageContainer } from '@ant-design/pro-layout'; @@ -250,6 +253,7 @@ const Env = () => { const [selectedRowIds, setSelectedRowIds] = useState([]); const [searchText, setSearchText] = useState(''); const [tableScrollHeight, setTableScrollHeight] = useState(); + const [importLoading, setImportLoading] = useState(false); const getEnvs = () => { setLoading(true); @@ -472,6 +476,33 @@ const Env = () => { setSearchText(value.trim()); }; + const uploadProps: UploadProps = { + accept: 'application/json', + beforeUpload: async (file) => { + const formData = new FormData(); + formData.append('env', file); + setImportLoading(true); + try { + const { code, data } = await request.post( + `${config.apiPrefix}envs/upload`, + { + data: formData, + }, + ); + + if (code === 200) { + message.success(`成功上传${data.length}个环境变量`); + getEnvs(); + } + setImportLoading(false); + } catch (error: any) { + setImportLoading(false); + } + return false; + }, + fileList: [], + }; + useEffect(() => { getEnvs(); }, [searchText]); @@ -497,6 +528,15 @@ const Env = () => { , + + + , ]} header={{ style: headerStyle,