| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- import React, { PureComponent as Component } from 'react';
- import { Timeline, Spin, Row, Col, Tag, Avatar, Button, Modal, AutoComplete } from 'antd';
- import PropTypes from 'prop-types';
- import { connect } from 'react-redux';
- import { formatTime } from '../../common.js';
- import showDiffMsg from '../../../common/diff-view.js';
- import variable from '../../constants/variable';
- import { Link } from 'react-router-dom';
- import { fetchNewsData, fetchMoreNews } from '../../reducer/modules/news.js';
- import { fetchInterfaceList } from '../../reducer/modules/interface.js';
- import ErrMsg from '../ErrMsg/ErrMsg.js';
- const jsondiffpatch = require('jsondiffpatch/dist/jsondiffpatch.umd.js');
- const formattersHtml = jsondiffpatch.formatters.html;
- import 'jsondiffpatch/dist/formatters-styles/annotated.css';
- import 'jsondiffpatch/dist/formatters-styles/html.css';
- import './TimeLine.scss';
- import { timeago } from '../../../common/utils.js';
- // const Option = AutoComplete.Option;
- const { Option, OptGroup } = AutoComplete;
- const AddDiffView = props => {
- const { title, content, className } = props;
- if (!content) {
- return null;
- }
- return (
- <div className={className}>
- <h3 className="title">{title}</h3>
- <div dangerouslySetInnerHTML={{ __html: content }} />
- </div>
- );
- };
- AddDiffView.propTypes = {
- title: PropTypes.string,
- content: PropTypes.string,
- className: PropTypes.string
- };
- // timeago(new Date().getTime() - 40);
- @connect(
- state => {
- return {
- newsData: state.news.newsData,
- curpage: state.news.curpage,
- curUid: state.user.uid
- };
- },
- {
- fetchNewsData,
- fetchMoreNews,
- fetchInterfaceList
- }
- )
- class TimeTree extends Component {
- static propTypes = {
- newsData: PropTypes.object,
- fetchNewsData: PropTypes.func,
- fetchMoreNews: PropTypes.func,
- setLoading: PropTypes.func,
- loading: PropTypes.bool,
- curpage: PropTypes.number,
- typeid: PropTypes.number,
- curUid: PropTypes.number,
- type: PropTypes.string,
- fetchInterfaceList: PropTypes.func
- };
- constructor(props) {
- super(props);
- this.state = {
- bidden: '',
- loading: false,
- visible: false,
- curDiffData: {},
- apiList: []
- };
- this.curSelectValue = '';
- }
- getMore() {
- const that = this;
- if (this.props.curpage <= this.props.newsData.total) {
- this.setState({ loading: true });
- this.props
- .fetchMoreNews(
- this.props.typeid,
- this.props.type,
- this.props.curpage + 1,
- 10,
- this.curSelectValue
- )
- .then(function() {
- that.setState({ loading: false });
- if (that.props.newsData.total === that.props.curpage) {
- that.setState({ bidden: 'logbidden' });
- }
- });
- }
- }
- handleCancel = () => {
- this.setState({
- visible: false
- });
- };
- componentWillMount() {
- this.props.fetchNewsData(this.props.typeid, this.props.type, 1, 10);
- if (this.props.type === 'project') {
- this.getApiList();
- }
- }
- openDiff = data => {
- this.setState({
- curDiffData: data,
- visible: true
- });
- };
- async getApiList() {
- let result = await this.props.fetchInterfaceList({
- project_id: this.props.typeid,
- limit: 'all'
- });
- this.setState({
- apiList: result.payload.data.data.list
- });
- }
- handleSelectApi = selectValue => {
- this.curSelectValue = selectValue;
- this.props.fetchNewsData(this.props.typeid, this.props.type, 1, 10, selectValue);
- };
- render() {
- let data = this.props.newsData ? this.props.newsData.list : [];
- const curDiffData = this.state.curDiffData;
- let logType = {
- project: '项目',
- group: '分组',
- interface: '接口',
- interface_col: '接口集',
- user: '用户',
- other: '其他'
- };
- const children = this.state.apiList.map(item => {
- let methodColor = variable.METHOD_COLOR[item.method ? item.method.toLowerCase() : 'get'];
- return (
- <Option title={item.title} value={item._id + ''} path={item.path} key={item._id}>
- {item.title}{' '}
- <Tag
- style={{ color: methodColor.color, backgroundColor: methodColor.bac, border: 'unset' }}
- >
- {item.method}
- </Tag>
- </Option>
- );
- });
- children.unshift(
- <Option value="" key="all">
- 选择全部
- </Option>
- );
- if (data && data.length) {
- data = data.map((item, i) => {
- let interfaceDiff = false;
- // 去掉了 && item.data.interface_id
- if (item.data && typeof item.data === 'object') {
- interfaceDiff = true;
- }
- return (
- <Timeline.Item
- dot={
- <Link to={`/user/profile/${item.uid}`}>
- <Avatar src={`/api/user/avatar?uid=${item.uid}`} />
- </Link>
- }
- key={i}
- >
- <div className="logMesHeade">
- <span className="logoTimeago">{timeago(item.add_time)}</span>
- {/*<span className="logusername"><Link to={`/user/profile/${item.uid}`}><Icon type="user" />{item.username}</Link></span>*/}
- <span className="logtype">{logType[item.type]}动态</span>
- <span className="logtime">{formatTime(item.add_time)}</span>
- </div>
- <span className="logcontent" dangerouslySetInnerHTML={{ __html: item.content }} />
- <div style={{ padding: '10px 0 0 10px' }}>
- {interfaceDiff && <Button onClick={() => this.openDiff(item.data)}>改动详情</Button>}
- </div>
- </Timeline.Item>
- );
- });
- } else {
- data = '';
- }
- let pending =
- this.props.newsData.total <= this.props.curpage ? (
- <a className="logbidden">以上为全部内容</a>
- ) : (
- <a className="loggetMore" onClick={this.getMore.bind(this)}>
- 查看更多
- </a>
- );
- if (this.state.loading) {
- pending = <Spin />;
- }
- let diffView = showDiffMsg(jsondiffpatch, formattersHtml, curDiffData);
- return (
- <section className="news-timeline">
- <Modal
- style={{ minWidth: '800px' }}
- title="Api 改动日志"
- visible={this.state.visible}
- footer={null}
- onCancel={this.handleCancel}
- >
- <i>注: 绿色代表新增内容,红色代表删除内容</i>
- <div className="project-interface-change-content">
- {diffView.map((item, index) => {
- return (
- <AddDiffView
- className="item-content"
- title={item.title}
- key={index}
- content={item.content}
- />
- );
- })}
- {diffView.length === 0 && <ErrMsg type="noChange" />}
- </div>
- </Modal>
- {this.props.type === 'project' && (
- <Row className="news-search">
- <Col span="3">选择查询的 Api:</Col>
- <Col span="10">
- <AutoComplete
- onSelect={this.handleSelectApi}
- style={{ width: '100%' }}
- placeholder="Select Api"
- optionLabelProp="title"
- filterOption={(inputValue, options) => {
- if (options.props.value == '') return true;
- if (
- options.props.path.indexOf(inputValue) !== -1 ||
- options.props.title.indexOf(inputValue) !== -1
- ) {
- return true;
- }
- return false;
- }}
- >
- {/* {children} */}
- <OptGroup label="other">
- <Option value="wiki" path="" title="wiki">
- wiki
- </Option>
- </OptGroup>
- <OptGroup label="api">{children}</OptGroup>
- </AutoComplete>
- </Col>
- </Row>
- )}
- {data ? (
- <Timeline className="news-content" pending={pending}>
- {data}
- </Timeline>
- ) : (
- <ErrMsg type="noData" />
- )}
- </section>
- );
- }
- }
- export default TimeTree;
|