大家好~我是
米洛
!
我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程
,希望大家多多支持。
欢迎关注我的公众号米洛的测开日记
,获取最新文章教程!
# 回顾
上一节我们讲了完善个人资料
功能,并能够利用oss对我们的用户头像进行管理。
还记得我们之前的configuration.json
文件(系统配置文件)吗?
那这一节我们就来讲下系统配置
功能,也就是能够在前端页面配置configuration.json。
# 回忆细节
之前我们是编写了配置管理
功能的,虽然有更新的操作,但是没有实际的运用。
oss那块读取oss类型和账号密码,以及邮箱部分有用到。
有了实际的方法,那我们编写curd接口就简单很多。
# 实现
# 后端逻辑
修改编辑部分
编辑的地方,我们需要调整一下,写入json文件的时候,注意ensure_ascii这个参数的关闭,以及indent(缩进)。
- 新增app/routers/config/system.py文件
from fastapi import Depends
from app.core.configuration import SystemConfiguration
from app.handler.fatcory import PityResponse
from app.routers import Permission
from app.routers.config.gconfig import router
from config import Config
@router.get("/system", description="获取系统配置")
def get_system_config(_=Depends(Permission(Config.ADMIN))):
configuration = SystemConfiguration.get_config()
return PityResponse.success(configuration)
@router.post("/system/update", description="更新系统配置")
def get_system_config(data: dict, _=Depends(Permission(Config.ADMIN))):
SystemConfiguration.update_config(data)
return PityResponse.success()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
我们把路由写在config下,那么/config/system
是获取配置接口,/config/system/update
是修改接口。
最后我们在app/init.py把编写好的路由注册进去即可。
# 前端逻辑
- 编写service层
分别编写好调用获取/更新的接口即可。
- 编写model层
在models/gconfig.js里面新增2个方法,调用刚才service层编写的2个接口。
编写view层
首先我们将页面拆分为3个tab:
- oss
- yapi
这样就对应3个子组件,先看下理想的效果图:
所以我们新建一个src/pages/Config/SystemConfig.jsx
文件:
import {PageContainer} from "@ant-design/pro-layout";
import {Button, Card, Col, Form, message, Row, Spin, Tabs} from "antd";
import OssConfig from "@/components/System/OssConfig";
import EmailConfig from "@/components/System/EmailConfig";
import YapiConfig from "@/components/System/YapiConfig";
import {SaveOutlined} from "@ant-design/icons";
import {connect} from "umi";
import {useEffect} from "react";
const {TabPane} = Tabs;
const SystemConfig = ({dispatch, gconfig, loading}) => {
const [form] = Form.useForm()
const {configuration} = gconfig;
const onSetField = () => {
const {email, oss, yapi} = configuration;
form.setFieldsValue(email);
form.setFieldsValue(oss);
form.setFieldsValue(yapi);
}
useEffect(() => {
dispatch({
type: 'gconfig/fetchSystemConfig'
})
}, [])
useEffect(() => {
// 这里批量变更表单数据
onSetField()
}, [configuration])
const onSubmit = async () => {
let values;
try {
values = await form.validateFields();
} catch (e) {
message.info("有必填字段未填写,请检查")
return;
}
const requestData = {
email: {
"sender": values.sender,
"password": values.password,
"host": values.host,
"to": values.to
},
yapi: {
"token": values.token,
},
oss: {
"oss_type": values.oss_type,
"access_key_id": values.access_key_id,
"access_key_secret": values.access_key_secret,
"bucket": values.bucket,
"endpoint": values.endpoint
}
}
dispatch({
type: "gconfig/updateConfiguration",
payload: requestData,
})
}
return (
<PageContainer title="系统设置" breadcrumb={null}>
<Spin spinning={loading.effects['gconfig/updateConfiguration'] || loading.effects['gconfig/fetchSystemConfig']}>
<Card>
<Row>
<Col span={24}>
<Tabs tabPosition="left">
<TabPane key="1" tab="邮件设置" forceRender>
<EmailConfig form={form}/>
</TabPane>
<TabPane key="2" tab="OSS设置" forceRender>
<OssConfig form={form}/>
</TabPane>
<TabPane key="3" tab="Yapi设置" forceRender>
<YapiConfig form={form}/>
</TabPane>
</Tabs>
</Col>
</Row>
<Row>
<div style={{margin: '16px auto'}}>
<Button type="primary" icon={<SaveOutlined/>} onClick={onSubmit}>保存</Button>
</div>
</Row>
</Card>
</Spin>
</PageContainer>
)
}
export default connect(({gconfig, loading}) => ({gconfig, loading}))(SystemConfig);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
可以看到,结构很简单,主要是一个tabs
加上具体tab页里面的内容,每个类型的tab又对应了不同的组件:
分别在src/components/System建立下面3个组件的jsx:
- 邮件组件EmailConfig.jsx:
import {Col, Form, Input, Row} from "antd";
import {CONFIG} from "@/consts/config";
export default ({form}) => {
return (
<Row gutter={8}>
<Col span={4}/>
<Col span={16}>
<Form form={form} {...CONFIG.LAYOUT}>
<Form.Item label="发件人" name="sender" rules={[{required: true, message: '请输入发件人邮箱'}]}>
<Input placeholder="请输入发件人邮箱"/>
</Form.Item>
<Form.Item label="host" name="host" rules={[{required: true, message: '请输入服务器host'}]}>
<Input placeholder="请输入服务器host"/>
</Form.Item>
<Form.Item label="邮箱秘钥" name="password" rules={[{required: true, message: '请输入邮箱秘钥'}]}>
<Input placeholder="请输入邮箱秘钥"/>
</Form.Item>
<Form.Item label="收件人名称" name="to" rules={[{required: true, message: '请输入收件人名称'}]}>
<Input placeholder="请输入收件人名称"/>
</Form.Item>
</Form>
</Col>
<Col span={4}/>
</Row>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- yapi组件YapiConfig.jsx
import {Button, Col, Form, Input, Row} from "antd";
import {CONFIG} from "@/consts/config";
export default ({form}) => {
return (
<Row gutter={8}>
<Col span={4}/>
<Col span={16}>
<Form form={form} {...CONFIG.LAYOUT}>
<Form.Item label="token" name="token">
<Input placeholder="请输入yapi token"/>
</Form.Item>
</Form>
</Col>
<Col span={4}/>
</Row>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- OssConfig.jsx
import {Col, Form, Input, Row, Select} from "antd";
import {CONFIG} from "@/consts/config";
export default ({form}) => {
return (
<Row gutter={8}>
<Col span={4}/>
<Col span={16}>
<Form form={form} {...CONFIG.LAYOUT}>
<Form.Item label="类型" name="oss_type" rules={[{required: true, message: '请选择oss类型'}]}>
<Select placeholder="请选择oss类型">
<Select.Option value="aliyun">阿里云</Select.Option>
<Select.Option value="gitee">gitee</Select.Option>
<Select.Option value="cos">腾讯云</Select.Option>
<Select.Option value="qiniu">七牛云</Select.Option>
</Select>
</Form.Item>
<Form.Item label="access_id" name="access_key_id" rules={[{required: true, message: '请输入access_key_id'}]}>
<Input placeholder="请输入access_key_id"/>
</Form.Item>
<Form.Item label="access_secret" name="access_key_secret" rules={[{required: true, message: '请输入access_secret'}]}>
<Input placeholder="请输入access_secret"/>
</Form.Item>
<Form.Item label="bucket" name="bucket" rules={[{required: true, message: '请输入bucket'}]}>
<Input placeholder="请输入bucket"/>
</Form.Item>
<Form.Item label="endpoint" name="endpoint">
<Input placeholder="请输入endpoint, 可不填"/>
</Form.Item>
</Form>
</Col>
<Col span={4}/>
</Row>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
需要注意的是,保存按钮按下的时候,需要获取
3个组件的数据
,所以每个组件都接受了父组件的form
。
forceRender可以强制渲染每个tab页面,就算它没有被打开过。
# 最终效果图
# 结语
系统设置暂时只有这几块
的功能,后续我们也许会有包括主题
,jira账号密码
等的配置项。