mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-22 22:36:06 +08:00
增加环境变量导入
This commit is contained in:
parent
6e9a4a29ef
commit
75fca715e3
|
@ -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);
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
40
src/pages/env/index.tsx
vendored
40
src/pages/env/index.tsx
vendored
|
@ -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<string[]>([]);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [tableScrollHeight, setTableScrollHeight] = useState<number>();
|
||||
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 = () => {
|
|||
<Button key="2" type="primary" onClick={() => addEnv()}>
|
||||
新建变量
|
||||
</Button>,
|
||||
<Upload {...uploadProps}>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<UploadOutlined />}
|
||||
loading={importLoading}
|
||||
>
|
||||
导入
|
||||
</Button>
|
||||
</Upload>,
|
||||
]}
|
||||
header={{
|
||||
style: headerStyle,
|
||||
|
|
Loading…
Reference in New Issue
Block a user