forked from Gitlink/forgeplus-react
add 项目标签列表页
This commit is contained in:
parent
2462355415
commit
6afb7465f2
|
|
@ -150,6 +150,11 @@ const Badge = Loadable({
|
|||
// loading: Loading,
|
||||
// })
|
||||
|
||||
const Topic = Loadable({
|
||||
loader: () => import('./forge/topic'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
|
||||
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot"];
|
||||
|
||||
|
|
@ -390,6 +395,9 @@ class App extends Component {
|
|||
{/* 查询 */}
|
||||
<Route path="/search" component={Search} mygetHelmetapi={mygetHelmetapi}/>
|
||||
|
||||
{/* 项目标签列表页 */}
|
||||
<Route path="/explore/topic/:id/:name" component={Topic} mygetHelmetapi={mygetHelmetapi}/>
|
||||
|
||||
<Route exact path="/explore/all"
|
||||
render={
|
||||
(props) => (
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ function CoderDepot(props){
|
|||
{desc && <p className="font-14 color-grey-3 mb15 task-hide-2" style={{lineHeight:"24px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}} title={desc}>{desc}</p>}
|
||||
{/* 项目标签 */}
|
||||
{topics && <div className='projectHomeTopics'>
|
||||
{topics.map(item=><span className='proHomeTopic mr15 mb10 font-13 task-hide'>{item.name}</span>)}
|
||||
{topics.map(item=><Link to={`/explore/topic/${item.id}/${encodeURIComponent(item.name)}`} className='proHomeTopic mr15 mb10 font-13 task-hide'>{item.name}</Link>)}
|
||||
</div>}
|
||||
{
|
||||
website &&
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class IndexItem extends Component {
|
|||
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
|
||||
{/* 项目标签 */}
|
||||
{item.topics && <div className='projectHomeTopics myProList'>
|
||||
{item.topics.map(topic=><span className='proHomeTopic mr15 font-13 task-hide'>{topic.name}</span>)}
|
||||
{item.topics.map(topic=><Link to={`/explore/topic/${topic.id}/${encodeURIComponent(topic.name)}`} className='proHomeTopic mr15 font-13 task-hide'>{topic.name}</Link>)}
|
||||
</div>}
|
||||
<div className="p-r-about">
|
||||
<span className="p-r-detail">
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ function Index() {
|
|||
</div>
|
||||
{/* 项目标签 */}
|
||||
{i.topics && <div className='proListTopics'>
|
||||
{i.topics.map(item=><span className='proListTopic mr15 font-13 task-hide'>{item.name}</span>)}
|
||||
{i.topics.map(item=><Link to={`/explore/topic/${item.id}/${encodeURIComponent(item.name)}`} className='proListTopic mr15 font-13 task-hide'>{item.name}</Link>)}
|
||||
</div>}
|
||||
<div className="item-data">
|
||||
{i.category && i.category.id ? <span className="category">{i.category.name}</span> :"" }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,126 @@
|
|||
import React, { useState } from 'react';
|
||||
import { withRouter } from "react-router";
|
||||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
|
||||
import './index.scss';
|
||||
import { useEffect } from 'react';
|
||||
import { Pagination, Select } from 'antd';
|
||||
import axios from 'axios';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import Nodata from '../Nodata';
|
||||
const Option = Select.Option;
|
||||
|
||||
export default withRouter((CNotificationHOC()(SnackbarHOC()(TPMIndexHOC((props) => {
|
||||
console.log('props', props);
|
||||
const {match:{params:{name, id}}, current_user:{user_id}} = props;
|
||||
const [languageList, setLanguageList] = useState(undefined);
|
||||
const [languageId, setLanguageId] = useState(undefined);
|
||||
const [sort, setSort] = useState("praises_count");
|
||||
const [page, setPage] = useState(1);
|
||||
const [limit, setLimit] = useState(15);
|
||||
const [projectsList, setProjectsList] = useState(undefined);
|
||||
const [total, setTotal] = useState(undefined);
|
||||
|
||||
useEffect(()=>{
|
||||
// 设置网页标题
|
||||
name && (document.title = `项目标签-${decodeURIComponent(name)}`);
|
||||
// 获取语言列表
|
||||
axios.get(`/project_languages.json`).then(result=>{
|
||||
result && setLanguageList(result.data.project_languages)
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(()=>{
|
||||
axios.get(`/projects.json`, {
|
||||
params: {
|
||||
user_id: user_id,
|
||||
page,
|
||||
limit,
|
||||
sort_by: sort,
|
||||
language_id:languageId? languageId : undefined,
|
||||
topic_id:id
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
console.log('result', result);
|
||||
setProjectsList(result.data.projects);
|
||||
setTotal(result.data.total_count);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log('error', error);
|
||||
})
|
||||
}, [sort, page, languageId])
|
||||
|
||||
return (
|
||||
<div className='topicRepoList pb50'>
|
||||
<h2 className='mt30 pl15'>#{decodeURIComponent(name)}</h2>
|
||||
<div className='flexBoxTopic topicRepoHead'>
|
||||
<span>平台共6个项目与此标签相匹配</span>
|
||||
<div>
|
||||
<Select defaultValue={0} showSearch placeholder="请选择语言" style={{minWidth:"104px", marginRight: '20px'}} onChange={(value)=>{setLanguageId(value)}} optionFilterProp="children" filterOption={(input,option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}>
|
||||
<Option key={0} value={0}>全部语言</Option>
|
||||
{
|
||||
languageList && languageList.length>0 && languageList.map((item,key)=>{
|
||||
return(
|
||||
<Option key={item.id} value={item.id}>{item.name}</Option>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Select>
|
||||
<Select defaultValue={"praises_count"} onChange={(value)=>{setSort(value)}} style={{minWidth:"104px"}}>
|
||||
<Option value="praises_count">最多点赞</Option>
|
||||
<Option value="updated_on">最近更新</Option>
|
||||
<Option value="forked_count">最多fork</Option>
|
||||
<Option value="watched_count">最多关注</Option>
|
||||
<Option value="created_on">最近创建</Option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
{/* 无数据 */}
|
||||
{projectsList && projectsList.length === 0 && <Nodata _html="暂无数据"/>}
|
||||
{/* 项目列表 */}
|
||||
{projectsList && projectsList.length>0 && projectsList.map(i=>{
|
||||
return <div key={i.id} className='flexBoxTopic repoTopic'>
|
||||
{/* 仓库拥有者头像 */}
|
||||
<Link to={`/${i.author && i.author.login}`}><img src={getImageUrl(`/${i.author && i.author.image_url}`)} alt="" className='repoImg mr10'/></Link>
|
||||
<div className='rightInfo'>
|
||||
<div className="flexBoxTopic">
|
||||
{/* 仓库拥有者名称 */}
|
||||
<Link to={`/${i.author && i.author.login}/${i.identifier}`} className="repoTitle task-hide font-15">{i.author && i.author.name}/{i.name}</Link>
|
||||
{/* 点赞数 */}
|
||||
{i.praises_count > 0 ? <span className='mr10'><i className="iconfont icon-xingzhuang mr3 font-14"></i>{i.praises_count}</span> :"" }
|
||||
{/* fork数 */}
|
||||
{i.forked_count > 0 ? <span><i className="iconfont icon-yifuke_icon mr3 font-14"></i>{i.forked_count}</span>:""}
|
||||
</div>
|
||||
{/* 仓库描述 */}
|
||||
<div className="descTopic task-hide-2 mb5">{i.description}</div>
|
||||
{/* 项目标签 */}
|
||||
{i.topics && <div className='proListTopics'>
|
||||
{i.topics.map(item=><Link to={`/explore/topic/${item.id}/${encodeURIComponent(item.name)}`} className='proListTopic mr15 font-13 task-hide'>{item.name}</Link>)}
|
||||
</div>}
|
||||
<div className="flexBoxTopic info3 font-13 mt5">
|
||||
{/* 仓库类别 */}
|
||||
{i.category && i.category.id ? <span className="category">{i.category.name}</span> :"" }
|
||||
{/* 仓库语言 */}
|
||||
{i.language && i.language.id ? <span className={`language mr30 ${i.category && i.category.id ? 'hasCate' : ''}`}>{i.language.name}</span> :""}
|
||||
{/* 更新时间 */}
|
||||
<span style={{lineHeight:"15px",display:"flex"}}><i className="iconfont icon-shijian font-15 mr5"></i>更新于{i.time_ago}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
})}
|
||||
{/* 分页 */}
|
||||
{total > limit && <Pagination
|
||||
className='mt20 pagTopic'
|
||||
pageSize={limit}
|
||||
showQuickJumper={total > limit}
|
||||
onChange={(page) => { setPage(page) }}
|
||||
current={page}
|
||||
total={total}
|
||||
showTotal={total => `共 ${total} 条`}
|
||||
/>}
|
||||
</div>
|
||||
)}
|
||||
)))))
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
.topicRepoList{
|
||||
width: 900px;
|
||||
margin: 0 auto;
|
||||
.flexBoxTopic{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
&>h2{
|
||||
font-weight: 700;
|
||||
}
|
||||
.topicRepoHead{
|
||||
color:#5f6872;
|
||||
padding: 10px 15px;
|
||||
border-bottom:1px solid rgba(153, 153, 153, 0.16);
|
||||
}
|
||||
.repoImg{
|
||||
width:32px;
|
||||
height: 32px;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.repoTopic{
|
||||
align-items: flex-start;
|
||||
border-bottom:1px solid rgba(153, 153, 153, 0.1);
|
||||
justify-content: flex-start;
|
||||
padding: 20px 0 15px;
|
||||
.rightInfo{
|
||||
flex: 1;
|
||||
}
|
||||
.repoTitle{
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.descTopic{
|
||||
color:#414141;
|
||||
line-height: 24px;
|
||||
}
|
||||
.proListTopics{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.proListTopic{
|
||||
background-color:#f3f8ff;
|
||||
border-radius: 4px;
|
||||
max-width: 158px;
|
||||
padding: 0 10px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
color: #4c5b76;
|
||||
margin-bottom: 5px !important;
|
||||
}
|
||||
}
|
||||
.info3{
|
||||
justify-content: flex-start;
|
||||
color: #7D7D7D;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.category{
|
||||
position: relative;
|
||||
padding-left: 11px;
|
||||
margin-right: 10px;
|
||||
&::before{
|
||||
position: absolute;
|
||||
content: "";
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background-color: #466AFF;
|
||||
top: 7px;
|
||||
left: 0px;
|
||||
}
|
||||
}
|
||||
.language{
|
||||
position: relative;
|
||||
&.hasCate{
|
||||
padding-left: 11px;
|
||||
}
|
||||
&.hasCate::before{
|
||||
position: absolute;
|
||||
content: "";
|
||||
width: 1px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
border-left: 1px solid #9e9e9e;
|
||||
bottom: 5px;
|
||||
left: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pagTopic{
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ function ConcentrateProject({userLogin,current,showCompeleteDialog,completeProfi
|
|||
<p className="task-hide desc">{i.description}</p>
|
||||
{/* 项目标签 */}
|
||||
{i.topics && <div className='viewProListTopics'>
|
||||
{i.topics.map(item=><span className='viewProListTopic mr15 font-13 task-hide'>{item.name}</span>)}
|
||||
{i.topics.map(item=><Link to={`/explore/topic/${item.id}/${encodeURIComponent(item.name)}`} className='viewProListTopic mr15 font-13 task-hide'>{item.name}</Link>)}
|
||||
</div>}
|
||||
<AlignCenter>
|
||||
{ i.category && <span className="tagName">{i.category.name}</span> }
|
||||
|
|
|
|||
Loading…
Reference in New Issue