| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- import React, { PureComponent as Component } from 'react';
- import {
- Upload,
- Icon,
- message,
- Select,
- Tooltip,
- Button,
- Spin,
- Switch,
- Modal,
- Radio,
- Input,
- Checkbox
- } from 'antd';
- import PropTypes from 'prop-types';
- import { connect } from 'react-redux';
- import './ProjectData.scss';
- import axios from 'axios';
- import URL from 'url';
- const Dragger = Upload.Dragger;
- import { saveImportData } from '../../../../reducer/modules/interface';
- import { fetchUpdateLogData } from '../../../../reducer/modules/news.js';
- import { handleSwaggerUrlData } from '../../../../reducer/modules/project';
- const Option = Select.Option;
- const confirm = Modal.confirm;
- const plugin = require('client/plugin.js');
- const RadioGroup = Radio.Group;
- const importDataModule = {};
- const exportDataModule = {};
- const HandleImportData = require('common/HandleImportData');
- function handleExportRouteParams(url, status, isWiki) {
- if (!url) {
- return;
- }
- let urlObj = URL.parse(url, true),
- query = {};
- query = Object.assign(query, urlObj.query, { status, isWiki });
- return URL.format({
- pathname: urlObj.pathname,
- query
- });
- }
- // exportDataModule.pdf = {
- // name: 'Pdf',
- // route: '/api/interface/download_crx',
- // desc: '导出项目接口文档为 pdf 文件'
- // }
- @connect(
- state => {
- return {
- curCatid: -(-state.inter.curdata.catid),
- basePath: state.project.currProject.basepath,
- updateLogList: state.news.updateLogList,
- swaggerUrlData: state.project.swaggerUrlData
- };
- },
- {
- saveImportData,
- fetchUpdateLogData,
- handleSwaggerUrlData
- }
- )
- class ProjectData extends Component {
- constructor(props) {
- super(props);
- this.state = {
- selectCatid: '',
- menuList: [],
- curImportType: 'swagger',
- curExportType: null,
- showLoading: false,
- dataSync: 'merge',
- exportContent: 'all',
- isSwaggerUrl: false,
- swaggerUrl: '',
- isWiki: false
- };
- }
- static propTypes = {
- match: PropTypes.object,
- curCatid: PropTypes.number,
- basePath: PropTypes.string,
- saveImportData: PropTypes.func,
- fetchUpdateLogData: PropTypes.func,
- updateLogList: PropTypes.array,
- handleSwaggerUrlData: PropTypes.func,
- swaggerUrlData: PropTypes.string
- };
- componentWillMount() {
- axios.get(`/api/interface/getCatMenu?project_id=${this.props.match.params.id}`).then(data => {
- if (data.data.errcode === 0) {
- let menuList = data.data.data;
- this.setState({
- menuList: menuList,
- selectCatid: menuList[0]._id
- });
- }
- });
- plugin.emitHook('import_data', importDataModule);
- plugin.emitHook('export_data', exportDataModule, this.props.match.params.id);
- }
- selectChange(value) {
- this.setState({
- selectCatid: +value
- });
- }
- uploadChange = info => {
- const status = info.file.status;
- if (status !== 'uploading') {
- console.log(info.file, info.fileList);
- }
- if (status === 'done') {
- message.success(`${info.file.name} 文件上传成功`);
- } else if (status === 'error') {
- message.error(`${info.file.name} 文件上传失败`);
- }
- };
- handleAddInterface = async res => {
- return await HandleImportData(
- res,
- this.props.match.params.id,
- this.state.selectCatid,
- this.state.menuList,
- this.props.basePath,
- this.state.dataSync,
- message.error,
- message.success,
- () => this.setState({ showLoading: false })
- );
- };
- // 本地文件上传
- handleFile = info => {
- if (!this.state.curImportType) {
- return message.error('请选择导入数据的方式');
- }
- if (this.state.selectCatid) {
- this.setState({ showLoading: true });
- let reader = new FileReader();
- reader.readAsText(info.file);
- reader.onload = async res => {
- res = await importDataModule[this.state.curImportType].run(res.target.result);
- if (this.state.dataSync === 'merge') {
- // 开启同步
- this.showConfirm(res);
- } else {
- // 未开启同步
- await this.handleAddInterface(res);
- }
- };
- } else {
- message.error('请选择上传的默认分类');
- }
- };
- showConfirm = async res => {
- let that = this;
- let typeid = this.props.match.params.id;
- let apiCollections = res.apis.map(item => {
- return {
- method: item.method,
- path: item.path
- };
- });
- let result = await this.props.fetchUpdateLogData({
- type: 'project',
- typeid,
- apis: apiCollections
- });
- let domainData = result.payload.data.data;
- const ref = confirm({
- title: '您确认要进行数据同步????',
- width: 600,
- okType: 'danger',
- iconType: 'exclamation-circle',
- className: 'dataImport-confirm',
- okText: '确认',
- cancelText: '取消',
- content: (
- <div className="postman-dataImport-modal">
- <div className="postman-dataImport-modal-content">
- {domainData.map((item, index) => {
- return (
- <div key={index} className="postman-dataImport-show-diff">
- <span className="logcontent" dangerouslySetInnerHTML={{ __html: item.content }} />
- </div>
- );
- })}
- </div>
- <p className="info">温馨提示: 数据同步后,可能会造成原本的修改数据丢失</p>
- </div>
- ),
- async onOk() {
- await that.handleAddInterface(res);
- },
- onCancel() {
- that.setState({ showLoading: false, dataSync: 'normal' });
- ref.destroy();
- }
- });
- };
- handleImportType = val => {
- this.setState({
- curImportType: val,
- isSwaggerUrl: false
- });
- };
- handleExportType = val => {
- this.setState({
- curExportType: val,
- isWiki: false
- });
- };
- // 处理导入信息同步
- onChange = checked => {
- this.setState({
- dataSync: checked
- });
- };
- // 处理swagger URL 导入
- handleUrlChange = checked => {
- this.setState({
- isSwaggerUrl: checked
- });
- };
- // 记录输入的url
- swaggerUrlInput = url => {
- this.setState({
- swaggerUrl: url
- });
- };
- // url导入上传
- onUrlUpload = async () => {
- if (!this.state.curImportType) {
- return message.error('请选择导入数据的方式');
- }
- if (!this.state.swaggerUrl) {
- return message.error('url 不能为空');
- }
- if (this.state.selectCatid) {
- this.setState({ showLoading: true });
- try {
- // 处理swagger url 导入
- await this.props.handleSwaggerUrlData(this.state.swaggerUrl);
- // let result = json5_parse(this.props.swaggerUrlData)
- let res = await importDataModule[this.state.curImportType].run(this.props.swaggerUrlData);
- if (this.state.dataSync === 'merge') {
- // merge
- this.showConfirm(res);
- } else {
- // 未开启同步
- await this.handleAddInterface(res);
- }
- } catch (e) {
- this.setState({ showLoading: false });
- message.error(e.message);
- }
- } else {
- message.error('请选择上传的默认分类');
- }
- };
- // 处理导出接口是全部还是公开
- handleChange = e => {
- this.setState({ exportContent: e.target.value });
- };
- // 处理是否开启wiki导出
- handleWikiChange = e => {
- this.setState({
- isWiki: e.target.checked
- });
- };
- /**
- *
- *
- * @returns
- * @memberof ProjectData
- */
- render() {
- const uploadMess = {
- name: 'interfaceData',
- multiple: true,
- showUploadList: false,
- action: '/api/interface/interUpload',
- customRequest: this.handleFile,
- onChange: this.uploadChange
- };
- let exportUrl =
- this.state.curExportType &&
- exportDataModule[this.state.curExportType] &&
- exportDataModule[this.state.curExportType].route;
- let exportHref = handleExportRouteParams(
- exportUrl,
- this.state.exportContent,
- this.state.isWiki
- );
- // console.log('inter', this.state.exportContent);
- return (
- <div className="g-row">
- <div className="m-panel">
- <div className="postman-dataImport">
- <div className="dataImportCon">
- <div>
- <h3>
- 数据导入
- <a
- target="_blank"
- rel="noopener noreferrer"
- href="https://hellosean1025.github.io/yapi/documents/data.html"
- >
- <Tooltip title="点击查看文档">
- <Icon type="question-circle-o" />
- </Tooltip>
- </a>
- </h3>
- </div>
- <div className="dataImportTile">
- <Select
- placeholder="请选择导入数据的方式"
- value={this.state.curImportType}
- onChange={this.handleImportType}
- >
- {Object.keys(importDataModule).map(name => {
- return (
- <Option key={name} value={name}>
- {importDataModule[name].name}
- </Option>
- );
- })}
- </Select>
- </div>
- <div className="catidSelect">
- <Select
- value={this.state.selectCatid + ''}
- showSearch
- style={{ width: '100%' }}
- placeholder="请选择数据导入的默认分类"
- optionFilterProp="children"
- onChange={this.selectChange.bind(this)}
- filterOption={(input, option) =>
- option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
- }
- >
- {this.state.menuList.map((item, key) => {
- return (
- <Option key={key} value={item._id + ''}>
- {item.name}
- </Option>
- );
- })}
- </Select>
- </div>
- <div className="dataSync">
- <span className="label">
- 数据同步
- <Tooltip
- title={
- <div>
- <h3 style={{ color: 'white' }}>普通模式</h3>
- <p>不导入已存在的接口</p>
- <br />
- <h3 style={{ color: 'white' }}>智能合并</h3>
- <p>
- 已存在的接口,将合并返回数据的 response,适用于导入了 swagger
- 数据,保留对数据结构的改动
- </p>
- <br />
- <h3 style={{ color: 'white' }}>完全覆盖</h3>
- <p>不保留旧数据,完全使用新数据,适用于接口定义完全交给后端定义</p>
- </div>
- }
- >
- <Icon type="question-circle-o" />
- </Tooltip>{' '}
- </span>
- <Select value={this.state.dataSync} onChange={this.onChange}>
- <Option value="normal">普通模式</Option>
- <Option value="good">智能合并</Option>
- <Option value="merge">完全覆盖</Option>
- </Select>
- {/* <Switch checked={this.state.dataSync} onChange={this.onChange} /> */}
- </div>
- {this.state.curImportType === 'swagger' && (
- <div className="dataSync">
- <span className="label">
- 开启url导入
- <Tooltip title="swagger url 导入">
- <Icon type="question-circle-o" />
- </Tooltip>{' '}
-
- </span>
- <Switch checked={this.state.isSwaggerUrl} onChange={this.handleUrlChange} />
- </div>
- )}
- {this.state.isSwaggerUrl ? (
- <div className="import-content url-import-content">
- <Input
- placeholder="http://demo.swagger.io/v2/swagger.json"
- onChange={e => this.swaggerUrlInput(e.target.value)}
- />
- <Button
- type="primary"
- className="url-btn"
- onClick={this.onUrlUpload}
- loading={this.state.showLoading}
- >
- 上传
- </Button>
- </div>
- ) : (
- <div className="import-content">
- <Spin spinning={this.state.showLoading} tip="上传中...">
- <Dragger {...uploadMess}>
- <p className="ant-upload-drag-icon">
- <Icon type="inbox" />
- </p>
- <p className="ant-upload-text">点击或者拖拽文件到上传区域</p>
- <p
- className="ant-upload-hint"
- onClick={e => {
- e.stopPropagation();
- }}
- dangerouslySetInnerHTML={{
- __html: this.state.curImportType
- ? importDataModule[this.state.curImportType].desc
- : null
- }}
- />
- </Dragger>
- </Spin>
- </div>
- )}
- </div>
- <div
- className="dataImportCon"
- style={{
- marginLeft: '20px',
- display: Object.keys(exportDataModule).length > 0 ? '' : 'none'
- }}
- >
- <div>
- <h3>数据导出</h3>
- </div>
- <div className="dataImportTile">
- <Select placeholder="请选择导出数据的方式" onChange={this.handleExportType}>
- {Object.keys(exportDataModule).map(name => {
- return (
- <Option key={name} value={name}>
- {exportDataModule[name].name}
- </Option>
- );
- })}
- </Select>
- </div>
- <div className="dataExport">
- <RadioGroup defaultValue="all" onChange={this.handleChange}>
- <Radio value="all">全部接口</Radio>
- <Radio value="open">公开接口</Radio>
- </RadioGroup>
- </div>
- <div className="export-content">
- {this.state.curExportType ? (
- <div>
- <p className="export-desc">{exportDataModule[this.state.curExportType].desc}</p>
- <a
- target="_blank"
- rel="noopener noreferrer"
- href={exportHref}>
- <Button className="export-button" type="primary" size="large">
- {' '}
- 导出{' '}
- </Button>
- </a>
- <Checkbox
- checked={this.state.isWiki}
- onChange={this.handleWikiChange}
- className="wiki-btn"
- disabled={this.state.curExportType === 'json'}
- >
- 添加wiki
- <Tooltip title="开启后 html 和 markdown 数据导出会带上wiki数据">
- <Icon type="question-circle-o" />
- </Tooltip>{' '}
- </Checkbox>
- </div>
- ) : (
- <Button disabled className="export-button" type="primary" size="large">
- {' '}
- 导出{' '}
- </Button>
- )}
- </div>
- </div>
- </div>
- </div>
- </div>
- );
- }
- }
- export default ProjectData;
|