合并请求+commit详情文件加载方式

This commit is contained in:
caishi 2024-11-16 10:53:04 +08:00 committed by 黄心宇
parent 8ec2aefdce
commit fb44bdd1d2
12 changed files with 375 additions and 151 deletions

View File

@ -2,6 +2,7 @@ import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import './activity.css';
import { getImageUrl } from 'educoder';
import { truncateCommitId } from "../common/util";
class ActivityItem extends Component {
@ -25,9 +26,16 @@ class ActivityItem extends Component {
<span className="activity_type">{item.trend_type}</span>
</p >
:
// 如果是commit--CommitLog
item.trend_type === "CommitLog" ?
<p className="itemLine">
<Link to={`/${owner}/${projectsId}/commits/${item.commit_log && truncateCommitId(item.commit_log.commit_id)}`} className="font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
:
// 如果是合并请求
<p className="itemLine">
<Link to={`/${owner}/${projectsId}/pulls/${item.trend_id}`} className="font-16">{item.name}</Link>
<Link to={`/${item.project && item.project.owner&& item.project.owner.login}/${item.project && item.project.identifier}/pulls/${item.trend_id}`} className="font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
}

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useState , useRef } from "react";
import styled from "styled-components";
import { Button ,Spin } from "antd";
import { timeFormat, truncateCommitId } from '../common/util';
@ -57,6 +57,24 @@ export default (props) => {
const [isSpin, setIsSpin] = useState(true);
const { sha , projectsId, owner } = match.params;
const [ dropLoading, setDropLoading] = useState(false); //loading
const limit = 100;
const fRef = useRef();
useEffect(()=>{
window.addEventListener("scroll",scrollListener);
return ()=>{window.removeEventListener("scroll",scrollListener);}
},[])
const scrollListener=()=>{
let scrollHeight = document.documentElement.scrollHeight;
let clientHeight = document.documentElement.clientHeight;
let scrollTop = document.documentElement.scrollTop;
if(Math.ceil(scrollTop+clientHeight) >= scrollHeight-5){
InitDiffData();
}
}
useEffect(()=>{
if(projectDetail){
const { author, name} = projectDetail;
@ -66,17 +84,18 @@ export default (props) => {
useEffect(() => {
if (projectsId && owner && sha) {
InitDiffData();
const url = `/${owner}/${projectsId}/commits/${sha}.json`;
axios
.get(url)
.then(result => {
if (result) {
setData(result.data);
// setData(result.data);
setCommit(result.data.commit);
setParents(result.data.parents);
setCommitter(result.data.committer || (result.data.commit && result.data.commit.committer));
setIsSpin(false);
}
})
.catch(error => {
@ -84,6 +103,28 @@ export default (props) => {
});
}
}, [projectsId , owner, sha]);
async function InitDiffData (){
let f = fRef.current ? fRef.current.files : [];
let p = fRef.current ? fRef.current.page : 1;
let hm = fRef.current ? fRef.current.hasMore : true;
if (!hm || dropLoading || !isSpin) {
return;
}
setDropLoading(true);
const url = `/v1/${owner}/${projectsId}/commits/${sha}/files.json`;
await axios.get(url,{
params:{page:p,limit}
}).then(res=>{
if(res && res.status === 200){
let arr = p === 1 ? res.data.files : [...f,...res.data.files];
setData(res.data);
fRef.current = {files:arr,page:p+1,hasMore:arr.length === limit};
setDropLoading(false);
}
})
}
return (
<div className="main" style={{padding:"0px",border:"none"}}>
<Spin spinning={isSpin}>
@ -132,10 +173,13 @@ export default (props) => {
<Files
history={history}
data={data}
filesData={fRef.current && fRef.current.files}
owner={owner}
projectsId={projectsId}
parentsSha={parents && parents.length > 0 && parents[0].sha}
mergeId={`commits/${sha}`}
/>
{ dropLoading && <p style={{textAlign:"center",color:"#999",padding:"10px"}}>文件加载中...</p>}
</Spin>
</div>
);

View File

@ -513,6 +513,7 @@ class CreateMerge extends Component {
changeCommitFunc={this.changeCommitFunc}
comparesData={comparesData}
pullOwnerLogin={pullOwnerLogin}
branchParams = {getBranchParams(this.props.location.pathname)}
></MergeFooter>
)}
</Spin>

View File

@ -1,61 +1,40 @@
import React ,{useEffect,useState } from 'react';
import { truncateCommitId } from '../common/util';
import { AlignCenter , FlexAJ } from '../Component/layout';
import { Tooltip,Progress } from 'antd';
import { Tooltip , Progress } from 'antd';
import './merge.css';
import './Index.scss';
import FileDrop from './components/fileDrop';
function Files({ data,history,owner,projectsId , parentsSha }){
const [ files , setFiles ] = useState(data && data.files);
const [ copyfileTipTitle, setCopyfileTipTitle] = useState("复制文件路径");
function Files({ data , filesData , history,owner,projectsId , parentsSha , mergeId }){
const [ files , setFiles ] = useState(filesData);
const [ isOpen, setIsOpen] = useState(false);
useEffect(()=>{
if(data){
setFiles(data.files);
if(filesData){
setFiles(filesData);
}
},[data]);
},[filesData]);
useEffect(()=>{
document.addEventListener('click',()=>{setIsOpen(false)})
},[])
function showDown(flag,index,isBin){
if(!isBin){
var lists = files.concat();
lists[index].flag = !flag ? true : false;
lists.splice();
setFiles(lists);
}
}
function copyFileName(fileName){
var copyCont = document.createElement('input');
copyCont.defaultValue = fileName;
document.body.appendChild(copyCont);
copyCont.select(); //
document.execCommand("Copy"); //
copyCont.className = 'copyCont';
copyCont.style.display='none';
setCopyfileTipTitle("复制成功");
}
const folderOpen = (
<div className="folders">
<div className="folderList">
{files && files.map((item, key) => {
return (
<a href={`#value${key}`}>
<FlexAJ className="filesInfo" key={key} onClick={() => {item.flag && showDown(item.flag, key, item.isBin);setIsOpen(false);}}>
<FlexAJ className="filesInfo" key={key} onClick={() => {item.flag && showDown(item.flag, key, item.is_bin);setIsOpen(false);}}>
<AlignCenter>
<i className="iconfont icon-wenjianicon mr4"></i>
<span className="cursor-pointer" data-clipboard-text={item.name}>{item.name}</span>
<span className="cursor-pointer" data-clipboard-text={item.filename}>{item.filename}</span>
</AlignCenter>
<div className="see-file">
<Tooltip placement="top" title={`${item.addition+item.deletion}处更改${item.addition + item.deletion > 0 ? "":""}${item.addition>0?item.addition+"处添加":""}${item.addition>0 && item.deletion>0 ?"和":""}${item.deletion>0?item.deletion+"处删除":""}`}>
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
{item.addition >0 && <span className="color-green ml10">+{item.addition}</span>}
{item.deletion >0 && <span className="color-red ml10">-{item.deletion}</span>}
<Tooltip placement="top" title={`${item.additions+item.deletions}处更改${item.additions + item.deletions > 0 ? "":""}${item.additions>0?item.additions+"处添加":""}${item.additions>0 && item.deletions>0 ?"和":""}${item.deletions>0?item.deletions+"处删除":""}`}>
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.additions/(item.additions+item.deletions)*100} />
{item.additions >0 && <span className="color-green ml10">+{item.additions}</span>}
{item.deletions >0 && <span className="color-red ml10">-{item.deletions}</span>}
</Tooltip>
</div>
</FlexAJ>
@ -66,22 +45,17 @@ function Files({ data,history,owner,projectsId , parentsSha }){
</div>
)
function subStrContent(content){
return content ? content.slice(1) :"";
}
return(
<div onClick={(e)=>{e.nativeEvent.stopImmediatePropagation()}}>
<AlignCenter className="color-grey-9" style={{position:'relative'}}>
<div onClick={()=>{setIsOpen(!isOpen)}}>
<i className={`iconfont mr5 ${isOpen? "font-18 icon-sanjiaoxing-down":"font-16 icon-triangle"}`}></i>
<span className="color-grey-6 update-file-count">
共有<span className="color-grey-3"> {data && data.files_count} 个文件 </span>被更改
{ data && data.total_addition ? <span>包括 <span className="color-green">{data && data.total_addition} 次插入</span></span>:"" }
{ data && data.total_addition && data.total_deletion ? " 和 ":""}
{ data && data.total_deletion ? <span className="color-red"> {data && data.total_deletion} 次删除</span>:""}
</span>
</div>
<AlignCenter className="color-grey-9" style={{position:'relative'}} onClick={()=>{setIsOpen(!isOpen)}}>
<div style={{width:20}}><i className={`iconfont mr5 ${isOpen? "font-18 icon-sanjiaoxing-down":"font-16 icon-triangle"}`}></i></div>
<span className="color-grey-6 update-file-count">
共有<span className="color-grey-3"> {data && data.file_nums} 个文件 </span>被更改
{ data && data.total_addition ? <span>包括 <span className="color-green">{data && data.total_addition} 次插入</span></span>:"" }
{ data && data.total_addition && data.total_deletion ? " 和 ":""}
{ data && data.total_deletion ? <span className="color-red"> {data && data.total_deletion} 次删除</span>:""}
</span>
{isOpen && folderOpen}
</AlignCenter>
{
@ -92,57 +66,7 @@ function Files({ data,history,owner,projectsId , parentsSha }){
return(
<div className="files" key={key}>
<a id= {`value${key}`} className="anchorPoint"></a>
<FlexAJ className="filesInfo">
<AlignCenter>
{!item.isBin ? <i className={!item.flag?"iconfont icon-sanjiaoxing-down color-grey-9":"iconfont icon-triangle font-15 color-grey-9"} onClick={()=>showDown(item.flag,key,item.isBin)}></i>:""}
<span className="cursor-pointer" data-clipboard-text={item.name} onClick={()=>showDown(item.flag,key,item.isBin)}>
{ item.isRenamed && item.old_name}
{ item.isRenamed && <i className="iconfont icon-youjiang font-12 color-grey-8 ml5 mr5"></i> }
{item.name}
</span>
<Tooltip
title={copyfileTipTitle}
onVisibleChange={()=>setCopyfileTipTitle("复制文件路径")}
>
<i className="iconfont icon-fuzhiicon ml6" onClick={()=>copyFileName(item.name)}></i>
</Tooltip>
</AlignCenter>
<div className="see-file">
<Tooltip placement="top" title={`${item.addition + item.deletion}处更改${item.addition + item.deletion > 0 ? "":""} ${item.addition > 0 ? item.addition + "处添加" : ""}${item.addition > 0 && item.deletion > 0 ? "和" : ""}${item.deletion > 0 ? item.deletion + "处删除" : ""}`}>
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
<span className="ml10">{item.addition+item.deletion}</span>
</Tooltip>
{
!item.isSubmodule &&
<span className="see-file-btn" onClick={()=>{history.push(`/${owner}/${projectsId}${item.isDeleted ? `/commits/${truncateCommitId(parentsSha)}`:`/tree/${truncateCommitId(item.sha)}/${item.name}`}`)}}>查看文件</span>
}
</div>
</FlexAJ>
{
item.sections && item.sections.length >= 1 && !item.flag &&
<div className="filesContent">
{
item.sections.map((i,k)=>{
return(
i.lines && i.lines.length>0 && i.lines.map((item,key)=>{
return(
<div key={k+key} className={(item.type === 2) ? "linesContent add" : item.type === 3 ? "linesContent reduce": item.type===4?"linesContent translate":"linesContent"}>
<span className="lines">
<span>{item.leftIdx && item.leftIdx !=="0" ? item.leftIdx :"" }</span>
<span>{item.rightIdx && item.rightIdx !=="0" ? item.rightIdx :"" }</span>
</span>
<p style={{display:"flex"}}>
<span className="linetype">{item.type===2 ? "+" : item.type===3 ? "-" :""}</span>
{ (item.type===3 || item.type===2) ? subStrContent(item.content) : item.content}
</p>
</div>
)
})
)
})
}
</div>
}
<FileDrop item={item} prekey={key} projectsId={projectsId} owner={owner} history={history} parentsSha={parentsSha} mergeId={mergeId}/>
</div>
)
})

View File

@ -118,4 +118,11 @@
width:30px;
text-align: center;
display: inline-block;
}
.diffDesc{
padding:30px 0px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}

View File

@ -22,14 +22,21 @@ class MergeFooter extends Component {
activeKey: '1',
commitCount: 0,
filesCount: 0,
unitData:undefined,
//
commentsTotalCount: 0,
page:1,
hasMore:true,
dropLoading:false,
limit:100
};
}
componentDidMount() {
this.Init();
// 便
this.props.bindFootRef && this.props.bindFootRef(this);
window.addEventListener("scroll",this.scrollListener);
return ()=>{window.removeEventListener("scroll",this.scrollListener);}
}
componentDidUpdate(prevProps) {
@ -41,6 +48,18 @@ class MergeFooter extends Component {
}
}
scrollListener=()=>{
let scrollHeight = document.documentElement.scrollHeight;
let clientHeight = document.documentElement.clientHeight;
let scrollTop = document.documentElement.scrollTop;
if(Math.ceil(scrollTop+clientHeight) >= scrollHeight-5){
const { match } = this.props;
const { projectsId, owner, mergeId } = match.params;
this.getFile(owner, projectsId, mergeId);
}
}
Init = (isTabChange) => {
const { data, location, match } = this.props;
const { pathname } = location;
@ -60,7 +79,7 @@ class MergeFooter extends Component {
this.setState({
activeKey: activeKey,
commitCount: data && data.commits_count,
filesCount: data && data.files_count,
filesCount:data && data.files_count
});
};
@ -81,7 +100,7 @@ class MergeFooter extends Component {
if (result) {
this.setState({
commitsData: result.data.commits,
commitCount: result.data.commits_count,
commitCount: result.data.commits_count
});
}
this.setState({ isSpin: false });
@ -91,29 +110,38 @@ class MergeFooter extends Component {
});
};
getFile = (owner, projectsId, mergeId) => {
this.setState({ isSpin: true });
const url = `/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
axios
.get(url)
.then((result) => {
if (result) {
this.setState({
filesData: result.data,
filesCount: result.data.files_count,
});
}
this.setState({ isSpin: false });
})
.catch((error) => {
this.setState({ isSpin: false });
});
getFile = async(owner, projectsId, mergeId) => {
const { page,limit , hasMore , dropLoading , filesData } = this.state;
if(!hasMore || dropLoading){
return;
}
this.setState({ isSpin: page === 1 , dropLoading:page > 1 });
const url = `/v1/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
await axios.get(url,{
params:{page,limit}
}).then((result) => {
if (result) {
let datas = result.data;
let files = page === 1 ? datas.files : filesData.concat(datas.files);
this.setState({
unitData:datas,
filesData: files,
hasMore:datas.files && datas.files.length === limit,
page:page+1
});
}
this.setState({ dropLoading:false,isSpin: false });
})
.catch((error) => {
this.setState({ isSpin: false });
});
};
render() {
const { projectsId, owner, mergeId } = this.props.match.params;
const { order_id, data = {} } = this.props;
const { order_id, data = {} , pullOwnerLogin } = this.props;
const {
isSpin,
activeKey,
@ -121,6 +149,8 @@ class MergeFooter extends Component {
commitCount,
filesData,
commitsData = [],
unitData,
dropLoading
} = this.state;
// Comment0
@ -128,7 +158,6 @@ class MergeFooter extends Component {
this.state.commentsTotalCount || data.comments_total_count || 0,
10
);
return (
<div className="main mergeRequest" style={{ paddingTop: '0px' }}>
<Spin spinning={isSpin}>
@ -193,12 +222,17 @@ class MergeFooter extends Component {
}
key="3"
>
<Files
{...this.props}
data={filesData}
projectsId={projectsId}
owner={owner}
/>
<div>
<Files
{...this.props}
data={unitData}
filesData={filesData}
projectsId={projectsId}
owner={owner}
mergeId={`pulls/${mergeId}`}
/>
{ dropLoading && <p style={{textAlign:"center",color:"#999",padding:"10px"}}>文件加载中...</p>}
</div>
</TabPane>
)}
</Tabs>

View File

@ -404,12 +404,20 @@ class MessageCount extends Component {
{
<div className="mt15">
<Tag className="pr-branch-tag">
<Link
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}
>
{data.pull_request && data.pull_request.fork_project_user}: {data.pull_request && data.pull_request.head}
</Link>
{
(data.pull_request.fork_project_user || data.issue.author_name!=="已注销") ?
<Link
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}
>
{data.pull_request && (data.pull_request.is_original ? data.pull_request.fork_project_user:data.issue.author_name)}: {data.pull_request && data.pull_request.head}
</Link>
:
<span className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}>
{data.pull_request && (data.pull_request.is_original ? data.pull_request.fork_project_user:data.issue.author_name)}: {data.pull_request && data.pull_request.head}
</span>
}
</Tag>
<span className="mr8 ver-middle">
<i
@ -638,7 +646,7 @@ class MessageCount extends Component {
{...this.props}
{...this.state}
bindFootRef={this.bindFootRef}
pullOwnerLogin={data.pull_request && data.pull_request.fork_project_user}
pullOwnerLogin={data.pull_request && (data.pull_request.is_original ? data.pull_request.fork_project_user:data.issue.project_author)}
></MergeLinkFooter>
</div>
) : (

View File

@ -281,7 +281,6 @@ class NewMerge extends Component {
id,
comparesData
} = this.state;
const renderBrances = (list, type) => {
if (list && list.length > 0) {
return list.map((item, key) => {
@ -313,7 +312,9 @@ class NewMerge extends Component {
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
};
let { project } = this.props;
// 源仓库所有者login
const pullOwnerLogin = projects_names && projects_names.filter(item=>{return item.id === id})[0].project_user_login;
console.log("-------------",pullOwnerLogin,projects_names);
return (
<div>
<div className="main">

View File

@ -4,7 +4,6 @@ import axios from "axios";
import "../Order/order.scss";
import "./merge.css";
import MergeForm from "./merge_form";
import MergeFooter from "./merge_footer";
const Option = Select.Option;
class UpdateMerge extends Component {
constructor(props) {

View File

@ -0,0 +1,117 @@
import React ,{useEffect,useState } from 'react';
import { truncateCommitId } from '../../common/util';
import { AlignCenter , FlexAJ } from '../../Component/layout';
import { Tooltip , Progress , Spin } from 'antd';
import "../Index.scss";
import axios from 'axios';
function FileDrop({prekey,item,projectsId,owner , history , mergeId,parentsSha}){
const [ copyfileTipTitle, setCopyfileTipTitle] = useState("复制文件路径");
const [ sections, setSections ] = useState(undefined);
const [ show, setShow ] = useState(true);
const [ isSpin, setIsSpin ] = useState(false);
useEffect(()=>{
if(prekey < 3 && item && item.filename){
showDown(item.filename);
}
},[prekey,item])
function copyFileName(fileName){
var copyCont = document.createElement('input');
copyCont.defaultValue = fileName;
document.body.appendChild(copyCont);
copyCont.select(); //
document.execCommand("Copy"); //
copyCont.className = 'copyCont';
copyCont.style.display='none';
setCopyfileTipTitle("复制成功");
}
function subStrContent(content){
return content ? " " + content.slice(1) :"";
}
function showDown(filename){
if(!sections){
setIsSpin(true);
const url = `/v1/${owner}/${projectsId}/${mergeId}/files.json`;
axios.get(url,{
params:{filepath:filename}
}).then(res=>{
if(res){
let files = res.data && res.data.files && res.data.files.length>0 && res.data.files[0];
setSections(files.sections);
setShow(true);
setIsSpin(false);
}
})
}else{
setShow(!show);
}
}
return(
<div key={prekey}>
<Spin spinning={isSpin}>
<FlexAJ className="filesInfo">
<AlignCenter onClick={()=>setShow(!show)} style={{cursor:!item.is_bin && item.changes !== 0?"pointer":"default"}}>
{(!item.is_bin && item.changes !== 0) ? <div style={{width:20}}><i className={show ?"iconfont icon-sanjiaoxing-down color-grey-9":"iconfont icon-triangle font-15 color-grey-9"}></i></div>:""}
<span className="cursor-pointer" data-clipboard-text={item.name}>
{ item.is_renamed && item.old_name}
{ item.is_renamed && <i className="iconfont icon-youjiang font-12 color-grey-8 ml5 mr5"></i> }
{item.filename}
</span>
<Tooltip
title={copyfileTipTitle}
onVisibleChange={()=>setCopyfileTipTitle("复制文件路径")}
>
<i className="iconfont icon-fuzhiicon ml6" onClick={(e)=>{e.stopPropagation();copyFileName(item.filename);}}></i>
</Tooltip>
</AlignCenter>
<div className="see-file">
<Tooltip placement="top" title={`${item.additions + item.deletions}处更改${item.additions + item.deletions > 0 ? "":""} ${item.additions > 0 ? item.additions + "处添加" : ""}${item.additions > 0 && item.deletions > 0 ? "和" : ""}${item.deletions > 0 ? item.deletions + "处删除" : ""}`}>
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.additions/(item.additions+item.deletions)*100} />
<span className="ml10">{item.additions+item.deletions}</span>
</Tooltip>
{
!item.is_submodule &&
<span className="see-file-btn" onClick={()=>{history.push(`/${owner}/${projectsId}${item.is_deleted ? `/commits/${truncateCommitId(parentsSha)}`:`/tree/${truncateCommitId(item.sha)}/${item.filename}`}`)}}>查看文件</span>
}
</div>
</FlexAJ>
{
(!item.is_bin && item.changes !== 0) && show &&
<div className="filesContent">
{
(sections && sections.length > 0) ? sections.map((i,k)=>{
return(
i.lines && i.lines.length>0 && i.lines.map((item,keys)=>{
return(
<div key={k+keys} className={(item.type === 2) ? "linesContent add" : item.type === 3 ? "linesContent reduce": item.type===4?"linesContent translate":"linesContent"}>
<span className="lines">
<span>{item.left_index && item.left_index !=="0" ? item.left_index :"" }</span>
<span>{item.right_index && item.right_index !=="0" ? item.right_index :"" }</span>
</span>
<div style={{display:"flex"}}>
<span className="linetype">{item.type===2 ? "+" : item.type===3 ? "-" :""}</span>
<div>
<span style={{whiteSpace:"pre-wrap"}}>{(item.type===3 || item.type===2) ? subStrContent(item.content) : item.content}</span>
</div>
</div>
</div>
)
})
)
})
:
<div className='diffDesc'>
<a onClick={()=>showDown(item.filename)} className='color-blue'>加载差异</a>差异被折叠
</div>
}
</div>
}
</Spin>
</div>
)
}
export default FileDrop;

View File

@ -197,6 +197,12 @@ form .ant-cascader-picker, form .ant-select {
.linesContent .lines > span:first-child{
margin-right: 0px;
}
.linesContent .lines,.linesContent .linetype,.no-select,.filesInfo{
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none; /* 标准语法 */
}
.linesContent .lines > span{
width: 50%;
text-align: right;

View File

@ -1,10 +1,12 @@
import React, { Component } from 'react';
import { Tabs } from 'antd';
import { Tabs , Spin } from 'antd';
import Commits from './Commits';
import Files from './Files';
import { returnbar , turnbar } from 'educoder';
import '../Order/order.scss';
import './merge.css';
import axios from 'axios';
const { TabPane } = Tabs;
@ -13,9 +15,30 @@ class MergeFooter extends Component {
super(props);
this.state = {
activeKey: '1',
diff:undefined,
filesData: undefined,
page:1,
hasMore:true,
dropLoading:false,
limit:100
};
}
componentDidMount(){
this.getFilesInfo();
window.addEventListener("scroll",this.scrollListener);
return ()=>{window.removeEventListener("scroll",this.scrollListener);}
}
scrollListener=()=>{
let scrollHeight = document.documentElement.scrollHeight;
let clientHeight = document.documentElement.clientHeight;
let scrollTop = document.documentElement.scrollTop;
if(Math.ceil(scrollTop+clientHeight) >= scrollHeight-5){
this.getFilesInfo();
}
}
changeTab = (index) => {
this.setState({
activeKey: index,
@ -27,11 +50,58 @@ class MergeFooter extends Component {
changeCommitFunc&& changeCommitFunc(page);
}
componentDidUpdate(prevProps) {
// 解决切换tab后浏览器回退不刷新的问题、点击tab后url变化但tab未切换的问题
const newPathname = this.props.location.pathname;
const prevPathname = prevProps.location.pathname;
if (newPathname !== prevPathname) {
this.getFilesInfo();
}
}
getFilesInfo=()=>{
const { hasMore , dropLoading , filesData , page , limit } = this.state;
if(!hasMore || dropLoading){
return;
}
this.setState({dropLoading:page>1})
const { branchParams = {} } = this.props;
const { mergeOwner, projectId } = branchParams;
let url = `/v1/${mergeOwner}/${projectId}/${this.getUrl()}/files.json`;
axios.get(url,{
params:{page,limit}
}).then(res=>{
if(res){
let datas = res.data;
let files = page === 1 ? datas.files : filesData.concat(datas.files);
this.setState({
diff:res.data ,
filesData: files,
hasMore:datas.files && datas.files.length === limit,
dropLoading:false,page:page+1
})
}
})
}
getUrl = ()=>{
const { branchParams = {} } = this.props;
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId , pullIdentity } = branchParams;
let url = `compare`;
if (mergeOwner === pullOwner) {
url += `/${Base64.encode(returnbar(pullBranch))}...${Base64.encode(returnbar(mergeBranch))}`;
} else {
url += `/${Base64.encode(returnbar(mergeBranch))}...${pullOwner}/${pullIdentity || projectId}:${Base64.encode(returnbar(pullBranch))}`;
}
return url;
}
render() {
const { projectsId, owner } = this.props.match.params;
const { comparesData = {} ,limit } = this.props;
const { commits, diff, commits_count } = comparesData;
const { activeKey } = this.state;
const { comparesData = {} ,limit ,branchParams } = this.props;
const { commits,commits_count } = comparesData;
const { activeKey , diff , filesData , dropLoading } = this.state;
return (commits && commits.length === 0) || !diff ? (
''
@ -71,19 +141,24 @@ class MergeFooter extends Component {
tab={
<span>
<span className="font-16">文件</span>
{diff.files_count > 0 && (
<span className="tabNum">{diff.files_count}</span>
{diff.file_nums > 0 && (
<span className="tabNum">{diff.file_nums}</span>
)}
</span>
}
key="3"
>
<Files
{...this.props}
data={diff}
projectsId={projectsId}
owner={owner}
/>
<div>
<Files
{...this.props}
data={diff}
filesData={filesData}
projectsId={projectsId}
owner={owner}
mergeId={this.getUrl()}
/>
{ dropLoading && <p style={{textAlign:"center",color:"#999",padding:"10px"}}>文件加载中...</p>}
</div>
</TabPane>
)}
</Tabs>