import React, { useEffect, useState } from 'react'; import style from './ReportsDataSourceSetting.less'; import { Row, Space, Form, Button, Card, Input, Avatar, Modal, Select, InputNumber, Spin, message, } from 'antd'; import { sourceIconMap } from './utils/constant'; import { EditOutlined, DeleteOutlined, EyeTwoTone, EyeInvisibleOutlined } from '@ant-design/icons'; import { reportService } from '../api'; import classnames from 'classnames'; const { Search, TextArea } = Input; const { Option } = Select; const { Meta } = Card; const ReportsDataSourceSetting = () => { const [sourceList, setSourceList] = useState([]); const [modalVisible, setModalVisible] = useState(false); const [currentData, setCurrentData] = useState(null); const [type, setType] = useState(''); const [dataSourceType, setDataSourceType] = useState('sqlserver'); const [searchStr, setSearchStr] = useState(null); const [form] = Form.useForm(); const [dbList, setDBList] = useState([]); const [listLoading, setListLoading] = useState(false); const [testLoading, setTestLoading] = useState(false); const [submitLoading, setSubmitLoading] = useState(false); const initValues = { db_sourcesname: '', db_type: 'sqlserver', db_url: '', db_username: '', db_password: '', db_port: 1433, db_name: '', webapiRType: '', webapiRParam: '', }; const getSourceList = () => { setListLoading(true); let _temp = searchStr ? { sourceName: searchStr } : {}; reportService .getDataSources(_temp) .then((res) => { if (res.code === 0) { setSourceList(res.data); } else { setSourceList([]); } setListLoading(false); }) .catch((err) => { setListLoading(false); }); }; const cancelVisible = () => { setCurrentData(null); setModalVisible(false); form.resetFields(); setDataSourceType('sqlserver'); }; const checkCard = (data) => { setModalVisible(true); setCurrentData(data); setType('detail'); }; const editCard = (data) => { setModalVisible(true); setCurrentData(data); setType('edit'); form.setFieldsValue(data); setDataSourceType(data.db_type); }; const addCard = () => { setModalVisible(true); setCurrentData(null); form.resetFields(); }; const deleteCard = (source) => { Modal.confirm({ title: `当前有${source.db_name}正在使用该数据源,删除后会导致该报表无法使用。请确认,是否删除【${source.db_sourcesname}】数据源配置?`, onOk: () => { setSubmitLoading(true); reportService .deleteDbConnection({ sourcesId: source.id }) .then((res) => { if (res.code === 0) { message.success('删除成功!'); getSourceList(); } else { message.error(`删除失败!${res.msg}`); } setSubmitLoading(false); }) .catch((err) => { console.log(err); setSubmitLoading(false); }); }, }); }; const selectType = (e) => { setDataSourceType(e); if (e === 'mysql') form.setFieldsValue({ db_port: 3306 }); if (e === 'sqlserver') form.setFieldsValue({ db_port: 1433 }); }; const onSearch = (e) => { setSearchStr(e); }; const getLoginInfo = () => { let list = form.getFieldsValue([ 'db_url', 'db_username', 'db_password', 'db_port', 'db_sourcesname', 'db_type', ]); let _final = Object.values(list).reduce((final, curr) => { if (curr === undefined) final = false; return final; }, true); return _final ? list : false; }; const getDBList = () => { let info = getLoginInfo(); if (info) { let { db_url, db_username, db_password, db_port, db_sourcesname, db_type } = info; reportService .getDbSources({ db_url, db_username, db_password, db_port, db_sourcesname, db_type, }) .then((res) => { if (res.code === 0) { setDBList(res.data); } else { setDBList([]); message.error(res.msg); } }); } else { message.error(`请完善名称、IP、端口、账号、密码`); } }; const test = () => { form.validateFields().then((value) => { setTestLoading(true); let _value = !currentData ? value : { ...value, id: currentData.id }; reportService .testConnection(_value) .then((res) => { if (res.code === 0) { message.success('测试通过!'); } else { message.error(res.msg); } setTestLoading(false); }) .catch((err) => { setTestLoading(false); }); }); }; const submit = () => { form.validateFields().then((value) => { setSubmitLoading(true); let _value = !currentData ? value : { ...value, id: currentData.id }; reportService .addDbConnection(_value) .then((res) => { if (res.code === 0) { message.success('保存成功!'); setModalVisible(false); getSourceList(); } else { message.error(res.msg); } setSubmitLoading(false); }) .catch((err) => { setSubmitLoading(false); }); }); }; useEffect(() => { getSourceList(); }, []); useEffect(() => { if (searchStr !== null) getSourceList(); }, [searchStr]); return ( <div className={style.reportsDataSourceSetting}> <div className={style.contentWrapper}> <Row className={style.controlRow}> <Space> {/*控制栏左侧部分*/} <Form.Item> <Search onSearch={onSearch} /> </Form.Item> <Form.Item> <Button onClick={addCard} type={'primary'}> 添加 </Button> </Form.Item> </Space> <div>{/* 控制栏右侧部分 */}</div> </Row> <div className={style.content}> <Spin style={{ width: '100%', height: '100%', position: 'absolute', display: 'flex', justifyContent: 'center', alignItems: 'center', background: 'rgba(255,255,255,0.2)', }} spinning={listLoading} /> {sourceList .filter((item) => { return !searchStr ? true : item.db_sourcesname.includes(searchStr); }) .map((item) => { return ( <Card className={style.card} actions={[ // <SettingOutlined onClick={checkCard} key='setting' />, <EditOutlined onClick={() => editCard(item)} key="edit" />, <DeleteOutlined onClick={() => deleteCard(item)} key="delete" />, ]} > <Meta avatar={<Avatar src={sourceIconMap[item.db_type]} />} title={item.db_sourcesname} /> <div className={style.cardInfo}> <p className={style.cardInfoItem}> 类型:{' '} <span className={classnames(style.item, style.blue)}> {item.db_type || '无'} </span> </p> {item.db_type === 'webapi' ? ( <p className={style.cardInfoItem}> 请求类型:{' '} <span className={style.item}> {item.webapiRType === 'post' ? 'POST' : 'GET'} </span> </p> ) : ( <p className={style.cardInfoItem}> 数据库: <span className={style.item}>{item.db_name || '无'}</span> </p> )} <p className={style.cardInfoItem}> 请求地址:{' '} <span title={item.db_url} className={classnames(style.item, style.ellipsis)}> {item.db_url} </span> </p> </div> </Card> ); })} </div> </div> <Modal title={currentData?.id ? '编辑' : '新增'} visible={modalVisible} onCancel={cancelVisible} footer={null} width={600} destroyOnClose > <Form autocomplete={'off'} form={form} initialValues={initValues} labelCol={{ span: 6, }} wrapperCol={{ span: 16, }} > <Form.Item label={'名称'} name={'db_sourcesname'} rules={[ { required: true, message: '名称必填', }, ]} > <Input placeholder={'请输入数据源名称'} /> </Form.Item> <Form.Item label={'类型'} name={'db_type'} rules={[ { required: true, message: '名称必填', }, ]} > <Select onChange={selectType} disabled={!!currentData?.id}> <Option value="mysql">MySQL</Option> <Option value="sqlserver">SQLServer</Option> <Option value="webapi">WebAPI</Option> </Select> </Form.Item> <Form.Item label={['mysql', 'sqlserver'].includes(dataSourceType) ? 'IP' : '请求地址'} name={'db_url'} rules={[ { required: true, message: '名称必填', }, ]} > {['mysql', 'sqlserver'].includes(dataSourceType) ? ( <Input placeholder={'请输入要链接的服务器IP'} /> ) : ( <TextArea placeholder={'请输入API链接'} rows={3} /> )} </Form.Item> {['mysql', 'sqlserver'].includes(dataSourceType) ? ( <> <Form.Item label={'账号'} name={'db_username'} rules={[ { required: true, message: '名称必填', }, ]} > <Input placeholder={'请输入链接账号'} /> </Form.Item> <Form.Item label={'密码'} name={'db_password'} rules={[ { required: true, message: '名称必填', }, ]} > <Input.Password placeholder="请输入密码" iconRender={(visible) => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)} /> </Form.Item> <Form.Item label={'端口'} name={'db_port'} rules={[ { required: true, message: '名称必填', }, ]} > <InputNumber min={0} max={65535} step={1} /> </Form.Item> <Form.Item label={'数据库'} name={'db_name'} rules={[ { required: true, message: '请选择要连接的数据库', }, ]} > <Select onFocus={getDBList} filterOption={(input, option) => option.children.includes(input)} showSearch > {dbList.map((item) => { return <Option value={item}>{item}</Option>; })} </Select> </Form.Item> </> ) : ( '' )} { // webapiRType // webapiRParam ['webapi'].includes(dataSourceType) ? ( <> <Form.Item label={'请求方式'} name={'webapiRType'} rules={[ { required: true, message: '请选择请求方式', }, ]} > <Select> <Option value={'post'}>POST</Option> <Option value={'get'}>GET</Option> </Select> </Form.Item> <Form.Item label={'请求头参数'} name={'requestHeader'}> <TextArea rows={3} placeholder={'请配置请求头参数'} /> </Form.Item> <Form.Item label={'请求参数'} name={'webapiRParam'}> <TextArea rows={3} placeholder={'请填写请求参数,使用&拼接,例:id=0&type=二供泵房'} /> </Form.Item> <Form.Item name={'webapiDataNode'} label={'数据路径'} rules={[{ required: true, message: '数据路径必填!' }]} > <Input placeholder={'仅获取该层级数据'} /> </Form.Item> </> ) : ( '' ) } <Form.Item label={' '} colon={false}> <Space> <Button onClick={test} loading={testLoading}> 测试链接 </Button> <Button onClick={cancelVisible}>取消</Button> <Button onClick={submit} type={'primary'} loading={submitLoading}> 确定 </Button> </Space> </Form.Item> </Form> </Modal> </div> ); }; export default ReportsDataSourceSetting;