This commit is contained in:
2024-03-01 20:28:14 +08:00
commit 076c21dc36
491 changed files with 84482 additions and 0 deletions

View File

@@ -0,0 +1,287 @@
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
});
};
UNSAFE_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 ? methodColor.color : '#cfefdf', backgroundColor: methodColor ? methodColor.bac : '#00a854', 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;

View File

@@ -0,0 +1,206 @@
.project-interface-change-content{
min-height: 350px;
max-height: 1000px;
min-width: 784px;
overflow-y: scroll;
.item-content{
.title{
margin: 10px 0;
}
.content{
}
}
}
.news-box {
display: -webkit-box;
-webkit-box-flex: 1;
margin: 0px auto 0 auto;
font-size: 0.14rem;
background: #FFF;
display: block;
min-height: 550px;
border-radius: 4px;
.news-timeline{
padding-left: 125px;
color: #6b6c6d;
.news-search{
height:35px;
line-height: 30px;
margin-top: 10px;
}
.news-content{
margin-top: 20px;
}
.ant-timeline-item{
min-height: 60px;
.ant-timeline-item-head-custom {
padding: 0;
width: 0;
left: -14px;
}
.ant-timeline-item-head{
// width: 40px;
// height: 40px;
// left: -13px;
top: 13px;
// // border-color:#e1e3e4;
// border:2px solid #e1e3e4;
// border-radius: 50%;
.anticon{
display: none;
}
}
.ant-timeline-item-tail{
// top: 30px;
}
.ant-avatar {
border: 2px solid #e1e3e4;
box-sizing: content-box;
border-radius: 50%;
width: 36px;
height: 36px;
}
}
.ant-avatar{
// border:2px solid gray;
}
.logusername{
color: #4eaef3;
padding: 0px 16px 0px 8px;
cursor: pointer;
}
.logtype{
padding-right: 16px;
}
.logtime{
padding-right: 16px;
}
.logcontent{
display: block;
padding-left: 8px;
line-height: 24px;
}
.logoTimeago{
position: absolute;
left: -80px;
top: 5px;
color: #c0c1c1;
}
.logbidden{
color: #c0c1c1;
cursor: default;
padding: 8px !important;
}
.loggetMore{
line-height: 30px;
color: #4eaef3;
}
.ant-timeline-item{
&:after{
content: "";
width: 0px;
height: 0px;
display: block;
clear: both;
}
.ant-timeline-item-content{
background-color: #fafafa;
float: left;
width: auto;
margin-left: 40px;
padding: 0px;
padding-bottom: 10px;
// min-width: 300px;
// max-width: 600px;
width: 625px;
border-radius: 8px;
.logMesHeade{
padding: 8px 8px 8px 8px;
line-height: 24px;
background-color: #eceef1;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.logoTimeago{
left: -120px;
}
.logcontent{
// text-indent: 2em;
line-height: 1.5em;
margin-top: 16px;
padding: 0px 16px;
}
}
}
.ant-timeline-item-pending{
padding: 0px;
.ant-timeline-item-content{
padding: 0px;
width: auto;
margin-top: 16px;
.loggetMore{
margin: 0px;
padding: 8px;
}
}
}
}
.logHead{
height: 80px;
width: 100%;
border-bottom: 1px solid #e9e9e9;
padding: 24px 0px;
overflow: hidden;
.breadcrumb-container{
float: left;
min-width:100px;
}
.projectDes{
color: #7b7b7b;
font-size: 25px;
float: left;
line-height: 0.9em;
}
.Mockurl{
width: 600px !important;
float: right;
color: #7b7b7b;
>span{
float: left;
line-height: 30px;
}
p{
width: 65%;
display: inline-block;
position: relative;
padding: 4px 7px;
height: 28px;
cursor: text;
font-size: 13px;
color: rgba(0,0,0,.65);
background-color: #fff;
background-image: none;
border: 1px solid #d9d9d9;
border-radius: 4px;
-webkit-transition: all .3s;
transition: all .3s;
overflow-x:auto;
}
button{
float: right;
}
}
}
}