/* eslint-disable spaced-comment */ /* eslint-disable eqeqeq */ import React, { useEffect, useRef, useState } from 'react'; import { Card, Form, Input, Button, Select, Table, Space, notification, Modal, Row, Col, Popconfirm, Spin, Tabs, Radio, } from 'antd'; import PageContainer from '@/components/BasePageContainer'; import RadioBox from '@/components/RadioGroup'; import { connect } from 'react-redux'; import { setTableSQLDirName, deleteConnNew, initDBv4new, getInitDBLogNew, getConnRecordNew, getDataBaseConfigNew, saveConnectionNew, getDataBaseList, updateConnDescNew, deleteInitDBLogNew, connectionTest, GetProductList, // 获取产品列表 GetDbProduct, // 获取产品方案配置 InitAddDataBase, // 数据库初始化 InitEditDataBase, // 二次初始化 } from '@/services/database/api'; import CryptoJS from 'crypto-js'; import styles from './InitDataBase.less'; import InitModal from './initModal'; const { TabPane } = Tabs; const { Option } = Select; const formLables = { ip: '服务器名或IP地址', userName: '数据库用户名称', password: '数据库用户密码', dbName: '数据库名称', }; let time = null; const InitDataBase = props => { const [form] = Form.useForm(); const [tableLoading, setTableLoading] = useState(false); // 连接记录 const [dbForm, setDbForm] = useState({ ip: '', dbName: '', password: '', userName: '', providerType: '', inUse: '', }); const [data, setData] = useState([]); // 数据库链接记录 const [option, setOption] = useState([]); // 下拉列表数据 const [desc, setDesc] = useState(''); // 修改描述 const [modalVisible, setModalVisible] = useState({ describeVisible: false, // 描述弹窗 versionVisible: false, // 检查版本弹窗 initVisible: false, // 初始化选择产品弹窗 }); // 修改弹窗 const [cardLoading, setCardLoading] = useState(false); // 初始化card Loading const [flag, setFlag] = useState(0); const [keepData, setKeepData] = useState({}); const chooseDb = useRef({}); const key = CryptoJS.enc.Utf8.parse('1p2a3n4d5a6o7m8s9a10n1e2t3c4o5re'); //十六位十六进制数作为密钥 const iv = CryptoJS.enc.Utf8.parse('1234567890000000'); const [pickItem, setPickItem] = useState(); // 获取数据库配置信息 useEffect(() => { setCardLoading(true); // 数据库连接记录初始化 getConnRecordData(); getDataBaseConfigNew().then(resnew => { setCardLoading(false); let res = resnew.data; if (resnew.code === 0) { const { inUse } = res; let obj = {}; Object.keys(dbForm).forEach(k => { obj[k] = res[k]; }); form.setFieldsValue({ ...obj }); setDbForm(val => ({ ...val, ...obj })); } }); return () => { if (time) { clearTimeout(time); time = null; } }; }, []); // 解密 const Decrypt = word => { let encryptedHexStr = CryptoJS.enc.Hex.parse(word); let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr); let decrypt = CryptoJS.AES.decrypt(srcs, key, { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, }); let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8); return decryptedStr?.toString(); }; //加密 const Encrypt = word => { let srcs = CryptoJS.enc.Utf8.parse(word); let encrypted = CryptoJS.AES.encrypt(srcs, key, { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, }); return encrypted.ciphertext.toString().toUpperCase(); }; // 弹出模态框 const handleShowModal = (key, value) => { setModalVisible({ ...modalVisible, [key]: value }); }; // 获取数据库连接记录 const getConnRecordData = () => { setTableLoading(true); getConnRecordNew() .then(resnew => { setTableLoading(false); if (resnew.code === 0) { let res = resnew.data; let arr = res.map((item, index) => { item.key = index; return item; }); setData(arr); } }) .catch(err => { setTableLoading(false); }); }; const onValuesChange = (value, b) => { form.setFieldsValue(value); }; const onChange = value => { const { length } = value; form.setFieldsValue({ dbName: value[length - 1], }); }; // 保存连接 const onFinish = values => { setCardLoading(true); const obj = values; let pwd = obj.password; if (obj.password.length < 32 || !isAlphanumeric(obj.password)) { pwd = Encrypt(obj.password); } saveConnectionNew({ ip: obj.ip, dbName: obj.dbName, userName: obj.userName, password: pwd, providerType: obj.providerType, desc: chooseDb.current.desc, }) .then(resnew => { setCardLoading(false); if (resnew.code === 0) { setFlag(flag + 1); setKeepData({ ip: obj.ip, dbName: obj.dbName, userName: obj.userName, password: pwd, }); // setUpData(upData + 1); getConnRecordData(); notification.success({ message: '提示', duration: 3, description: '保存成功', }); } else { notification.error({ message: '提示', duration: 15, description: resnew.msg, }); } }) .catch(err => { setCardLoading(false); notification.error({ message: '提示', duration: 15, description: err, }); }); }; // 测试连接 const onCheck = e => { setCardLoading(true); const obj = form.getFieldsValue(); let pwd = obj.password; if (obj.password.length < 32 || !isAlphanumeric(obj.password)) { pwd = Encrypt(obj.password); } connectionTest({ ip: obj.ip, dbName: obj.dbName, userName: obj.userName, providerType: obj.providerType, password: pwd, }) .then(res => { setCardLoading(false); if (res.code == 0 && res.data == true) { notification.success({ message: '提示', duration: 3, description: '连接成功', }); } else { notification.error({ message: '提示', duration: 15, description: res.msg, }); } }) .catch(err => { setCardLoading(false); console.log(err); }); }; const isAlphanumeric = str => { return /^[A-Za-z0-9]+$/.test(str); }; // 获取数据库列表 const selectFocus = e => { let params = form.getFieldsValue(); let pwd = params.password; if (params.password.length < 32 || !isAlphanumeric(params.password)) { pwd = Encrypt(params.password); } getDataBaseList({ userName: params.userName || '', password: pwd || '', ip: params.ip || '', providerType: params.providerType || '', }) .then(res => { if (res.code == 0) { setOption(res.data.root); } else { notification.error({ message: '提示', duration: 15, description: res.msg, }); setOption([]); } }) .catch(err => { console.error(err); }); }; // 点击表格回显到表单 const tableClick = item => { let obj = { ...dbForm }; Object.keys(obj).forEach(k => { obj[k] = item[k]; }); chooseDb.current = item; form.setFieldsValue({ ...obj }); }; // 展示修改描述 const changeDesc = val => { setDesc(val); handleShowModal('describeVisible', true); }; const descChange = e => { const { value } = e.target; setDesc(value); }; // 弹窗确认回调 const modalOkCallback = () => { // 更新描述 updateConnDescNew({ ip: pickItem.ip, dbName: pickItem.dbName, userName: pickItem.userName, password: pickItem.password, providerType: pickItem.providerType, desc, }) .then(res => { if (res.code === 0) { handleShowModal('describeVisible', false); getConnRecordData(); } else { notification.error({ message: '提示', duration: 5, description: res.msg, }); } }) .catch(err => { handleShowModal('describeVisible', false); }); }; const columns = [ { title: '服务器名或IP地址', dataIndex: 'ip', key: 'ip', width: 180, ellipsis: true, align: 'center', }, { title: '数据库名称', dataIndex: 'dbName', key: 'dbName', width: 180, ellipsis: true, align: 'center', }, { title: '数据库用户名称', dataIndex: 'userName', key: 'userName', width: 180, ellipsis: true, align: 'center', }, { title: '保存时间', dataIndex: 'saveTime', key: 'saveTime', width: 180, ellipsis: true, align: 'center', }, { title: '数据库类型', dataIndex: 'providerType', key: 'providerType', width: 180, ellipsis: true, align: 'center', }, { title: '描述', dataIndex: 'desc', key: 'desc', ellipsis: true, align: 'center', }, { title: '操作', dataIndex: 'action', key: 'action', width: 250, ellipsis: true, align: 'center', render: (text, record) => ( <Space> <Button type="primary" size="small" onClick={e => { e.stopPropagation(); changeDesc(record.desc); setPickItem(record); }} > 修改描述 </Button> </Space> ), }, ]; return ( <> <PageContainer className={styles.InitDataBaseContainer}> <Card className={styles.cardTop}> <Spin tip="loading..." spinning={cardLoading}> {/* <div className={styles.tableTitle}>数据库初始化</div> */} <Form className={styles.cardBottom} layout="horizontal" labelAlign="left" labelCol={{ span: 3 }} form={form} onFinish={onFinish} onValuesChange={onValuesChange} autoComplete="off" > <Form.Item label="数据库类型" name="providerType" rules={[ { validator: (rule, value) => { if (form.getFieldValue().providerType == '') { return Promise.reject('ip必填'); } return Promise.resolve(); }, }, ]} > <Select placeholder="请选择数据库类型"> <Select.Option value="SqlServer">SqlServer</Select.Option> <Select.Option value="Dm">Dm</Select.Option> </Select> </Form.Item> <Form.Item label={`${formLables.ip}:`} name="ip" rules={[ { validator: (rule, value) => { if (form.getFieldValue().ip == '') { return Promise.reject('ip必填'); } return Promise.resolve(); }, }, ]} > <Input placeholder="请输入服务器名或IP地址" /> </Form.Item> <Form.Item label={`${formLables.userName}:`} name="userName" rules={[ { validator: (rule, value) => { if (form.getFieldValue().userName == '') { return Promise.reject('用户名称必填'); } return Promise.resolve(); }, }, ]} > <Input placeholder="请输入用户名称" autoComplete="off" /> </Form.Item> <Form.Item label="数据库用户密码" name="password" rules={[ { validator: (rule, value) => { console.log(form.getFieldValue().password); if (form.getFieldValue().password == '') { return Promise.reject('用户密码必填'); } return Promise.resolve(); }, }, ]} > <Input placeholder="请输入用户密码" type="password" autoComplete="new-password" id="pwd" /> </Form.Item> <Form.Item label="数据库名称" name="dbName" rules={[ { validator: (rule, value) => { if ( form.getFieldValue().dbName == '' || form.getFieldValue().dbName == undefined ) { return Promise.reject('数据库名称必填'); } return Promise.resolve(); }, }, ]} > <Select showSearch mode="tags" placeholder="请选择数据库" optionFilterProp="children" onFocus={() => { selectFocus(); }} onChange={e => { onChange(e); }} // eslint-disable-next-line no-shadow filterOption={(input, option) => { return ( option.children && option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 ); }} > {option && option.length > 0 && option.map((item, index) => ( <Option value={item.value} key={item.value + index}> {item.value} </Option> ))} </Select> </Form.Item> <Form.Item wrapperCol={{ offset: 3 }}> <div className={styles.tCenter}> <Space size="large" className={styles.btnBox}> <Space> <Button onClick={onCheck}>测试连接</Button> <Button type="primary" htmlType="submit" loading={tableLoading}> 保存连接 </Button> </Space> </Space> </div> </Form.Item> </Form> </Spin> </Card> <Card className={styles.cardBottom}> <div className={styles.recordBox}> <div className={styles.tableTitle}>近期保存的数据库连接</div> <Table style={{ marginTop: '20px', marginBottom: '20px' }} scroll={{ x: 'max-content', y: 'calc(100vh - 550px)' }} columns={columns} dataSource={data} pagination={false} bordered loading={tableLoading} size="small" onRow={record => ({ onClick: () => { tableClick(record); setFlag(0); }, // 点击行 })} /> </div> </Card> <Modal title="修改链接描述" visible={modalVisible.describeVisible} onOk={() => modalOkCallback()} onCancel={() => handleShowModal('describeVisible', false)} width="800px" bodyStyle={{ minHeight: '100px', }} cancelText="取消" okText="确认" destroyOnClose > <Row> <Col span={2} className={styles.decsBox}> 描述: </Col> <Col span={22}> <Input placeholder="请输入描述" allowClear defaultValue={desc} onChange={value => { descChange(value); }} /> </Col> </Row> </Modal> </PageContainer> </> ); }; export default connect()(InitDataBase);