项目列表页面
This commit is contained in:
parent
27883febe1
commit
7e6bb2ada9
|
@ -0,0 +1,40 @@
|
|||
import React , { FC , useEffect } from 'react';
|
||||
import {
|
||||
connect,
|
||||
ProjectHomeState,
|
||||
Dispatch
|
||||
} from 'umi';
|
||||
import styles from './index.less';
|
||||
import Item from './item';
|
||||
|
||||
export interface PageProps{
|
||||
projectHome:ProjectHomeState,
|
||||
dispatch:Dispatch
|
||||
}
|
||||
|
||||
const Categore:FC<PageProps>=({
|
||||
projectHome,
|
||||
dispatch
|
||||
})=>{
|
||||
|
||||
useEffect(()=>{
|
||||
dispatch({
|
||||
type:"projectHome/getCategoryList",
|
||||
payload:{}
|
||||
})
|
||||
},[projectHome.name])
|
||||
|
||||
if(projectHome.categoryList && projectHome.categoryList.length>0){
|
||||
return(
|
||||
<div className={styles.leftListItems}>
|
||||
<p className="leftTitle"><i className="iconfont icon-xiangmuleibie"></i>项目类别</p>
|
||||
<Item list={projectHome.categoryList} />
|
||||
</div>
|
||||
)
|
||||
}else{
|
||||
return <></>
|
||||
}
|
||||
}
|
||||
export default connect(
|
||||
({projectHome}:{projectHome:ProjectHomeState})=>({projectHome})
|
||||
)(Categore)
|
|
@ -0,0 +1,108 @@
|
|||
.listbox{
|
||||
display: flex;
|
||||
}
|
||||
.boxItem{
|
||||
width:208px;
|
||||
margin-right: 30px;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
border: 1px solid #eee;
|
||||
div[class~='mainInfo']{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 160px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
img{
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
span[class~="name"]{
|
||||
margin-top: 12px;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
}
|
||||
span[class~="author"]{
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
div[class~="baseInfo"]{
|
||||
padding: 18px 15px;
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
.leftListItems{
|
||||
border:1px solid #eee;
|
||||
margin-bottom: 15px;
|
||||
p[class~="leftTitle"]{
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding:0px 20px;
|
||||
margin-bottom: 0px;
|
||||
font-size: 16px;
|
||||
i{
|
||||
margin-right: 5px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
div[class~="ant-list"]{
|
||||
font-size: 16px;
|
||||
li[class~="ant-list-item"]{
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
padding-right: 20px;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.rightListData{
|
||||
padding:0px 20px!important;
|
||||
li[class~="ant-list-item"]{
|
||||
padding:22px 0px;
|
||||
align-items: flex-start;
|
||||
&>a>img{
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
margin-right: 18px;
|
||||
}
|
||||
&>div{
|
||||
flex:1;
|
||||
}
|
||||
a[class~="dataTitle"]{
|
||||
font-size: 18px;
|
||||
max-width: 470px;
|
||||
display: block;
|
||||
color: #333;
|
||||
}
|
||||
div[class~="dataDesc"]{
|
||||
max-height: 44px;
|
||||
line-height: 22px;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import React , { FC } from 'react';
|
||||
import { List } from 'antd';
|
||||
|
||||
interface Props{
|
||||
list:any
|
||||
}
|
||||
|
||||
const Item:FC<Props>=({list})=>{
|
||||
if(list && list.length>0){
|
||||
return(
|
||||
<List>
|
||||
{
|
||||
list.map(function(
|
||||
i:any,k:any
|
||||
){
|
||||
return(
|
||||
<List.Item key={k}>
|
||||
<span>{i.name}</span>
|
||||
<span className="blue">{i.projects_count}</span>
|
||||
</List.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
</List>
|
||||
)
|
||||
}else{
|
||||
return <></>
|
||||
}
|
||||
}
|
||||
export default Item;
|
|
@ -0,0 +1,73 @@
|
|||
import React , { FC } from 'react';
|
||||
import styles from './index.less';
|
||||
import {
|
||||
Link
|
||||
}from 'umi';
|
||||
import { List , Tooltip } from 'antd';
|
||||
import ENV from '@/utils/env';
|
||||
|
||||
interface Props{
|
||||
list:any
|
||||
}
|
||||
|
||||
const ListItem:FC<Props>=({list})=>{
|
||||
if(list &&ListItem.length>0){
|
||||
return(
|
||||
<List className={styles.rightListData}>
|
||||
{
|
||||
list.map(function(i:any,k:number){
|
||||
return(
|
||||
<List.Item key={k}>
|
||||
{
|
||||
i.platform === "educoder" ?
|
||||
<a href="javascript:void(0)" style={{cursor:"default"}}>
|
||||
<img alt="" src={i.author && i.author.image_url} />
|
||||
</a>
|
||||
:
|
||||
<Link to={i.author && (i.author.type === "Organization" ? `/organize/${i.author.login}`:`/users/${i.author.login}`)}>
|
||||
<img src={`${ENV.IMG_SERVER}/${i.author && i.author.image_url}`} />
|
||||
</Link>
|
||||
}
|
||||
<div>
|
||||
<div className="alignCenterJSB mb10">
|
||||
<span className="alignCenter">
|
||||
<Link to={`/projects/${i.author && i.author.login}/${i.identifier}`} title={`${i.author && i.author.name}/${i.name}`} className="dataTitle hide">{i.author && i.author.name}/{i.name}</Link>
|
||||
{ !i.is_public && <span className="privateTag ml10">私有</span> }
|
||||
{ i.forked_from_project_id ?<i className="iconfont icon-fork font18 orange ml5" />:""}
|
||||
{
|
||||
i.type && i.type === 2 ?
|
||||
<Tooltip title="该项目是一个镜像">
|
||||
<i className="iconfont icon-banbenku font20 green ml5" />
|
||||
</Tooltip>:""
|
||||
}
|
||||
{ i.type && i.type === 1 ?<i className="iconfont icon-jingxiang font18 green ml5" />:""}
|
||||
</span>
|
||||
<span className="alignCenter">
|
||||
{i.praises_count && i.praises_count>0 ?
|
||||
<span className="pariseTag ml15"><i className="iconfont icon-shoucangyiji mr3 font14 yellow"></i>赞 {i.praises_count}</span>
|
||||
:""}
|
||||
{
|
||||
i.forked_count && i.forked_count>0 ?
|
||||
<span className="forkTag ml15"><i className="iconfont icon-fork mr3 font16 blue" />fork {i.forked_count}</span>
|
||||
:""
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div className="hide2 dataDesc">{i.description}</div>
|
||||
<div className="c-g-9 mt10">
|
||||
<span className="mr30">更新于{i.time_ago}</span>
|
||||
<span>{i.language && i.language.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
</List.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
</List>
|
||||
)
|
||||
}else{
|
||||
return <></>
|
||||
}
|
||||
|
||||
}
|
||||
export default ListItem
|
|
@ -0,0 +1,42 @@
|
|||
import React , { FC , useEffect , useState } from 'react';
|
||||
import {
|
||||
connect,
|
||||
ProjectHomeState,
|
||||
Dispatch
|
||||
}
|
||||
from 'umi';
|
||||
import { List } from 'antd';
|
||||
import styles from './index.less';
|
||||
import Item from './item';
|
||||
|
||||
|
||||
interface PageProps{
|
||||
projectHome:ProjectHomeState,
|
||||
dispatch:Dispatch
|
||||
}
|
||||
|
||||
const type:FC<PageProps>=({
|
||||
projectHome,
|
||||
dispatch
|
||||
})=>{
|
||||
|
||||
useEffect(()=>{
|
||||
dispatch({
|
||||
type:"projectHome/getGroupTypeList",
|
||||
payload:{}
|
||||
})
|
||||
},[projectHome.name])
|
||||
|
||||
if(projectHome.typeList && projectHome.typeList.length>0){
|
||||
return(
|
||||
<div className={styles.leftListItems}>
|
||||
<p className="leftTitle"><i className="iconfont icon-xiangmuleixing"></i>项目类型</p>
|
||||
<Item list={projectHome.typeList} />
|
||||
</div>
|
||||
)
|
||||
}else{
|
||||
return <></>
|
||||
}
|
||||
}
|
||||
export default connect(
|
||||
({projectHome}:{projectHome:ProjectHomeState})=>({projectHome}))(type)
|
|
@ -1,53 +0,0 @@
|
|||
.listbox{
|
||||
display: flex;
|
||||
}
|
||||
.boxItem{
|
||||
width:208px;
|
||||
margin-right: 30px;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
border: 1px solid #eee;
|
||||
div[class~='mainInfo']{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 160px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
img{
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
span[class~="name"]{
|
||||
margin-top: 12px;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
}
|
||||
span[class~="author"]{
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
div[class~="baseInfo"]{
|
||||
padding: 18px 15px;
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,18 @@
|
|||
import { Effect , Reducer , Subscription } from 'umi';
|
||||
import { getProjectList , getRecommand } from '@/service/projectHome';
|
||||
import {
|
||||
getProjectList ,
|
||||
getRecommand ,
|
||||
getGroupType ,
|
||||
getcategory
|
||||
} from '@/service/projectHome';
|
||||
|
||||
export interface ProjectHomeState{
|
||||
name:string,
|
||||
projectList?:any,
|
||||
recommandList?:any
|
||||
total:number,
|
||||
recommandList?:any,
|
||||
typeList?:any,
|
||||
categoryList?:any
|
||||
}
|
||||
|
||||
export interface ProjectHomeType{
|
||||
|
@ -12,7 +20,9 @@ export interface ProjectHomeType{
|
|||
state:ProjectHomeState,
|
||||
effects:{
|
||||
getProjectList:Effect,
|
||||
getRecommandList:Effect
|
||||
getRecommandList:Effect,
|
||||
getGroupTypeList:Effect,
|
||||
getCategoryList:Effect
|
||||
},
|
||||
reducers:{
|
||||
save:Reducer<ProjectHomeState>
|
||||
|
@ -24,6 +34,7 @@ const ProjectHomeModel:ProjectHomeType = {
|
|||
namespace:"projectHome",
|
||||
state:{
|
||||
name:"项目列表",
|
||||
total:0,
|
||||
projectList:{}
|
||||
},
|
||||
effects:{
|
||||
|
@ -32,7 +43,7 @@ const ProjectHomeModel:ProjectHomeType = {
|
|||
const response = yield call(getProjectList,params);
|
||||
yield put({
|
||||
type: 'save',
|
||||
payload: { projectList: response },
|
||||
payload: { projectList: response.projects , total: response.total_count},
|
||||
});
|
||||
},
|
||||
*getRecommandList({payload},{call,put}){
|
||||
|
@ -41,6 +52,20 @@ const ProjectHomeModel:ProjectHomeType = {
|
|||
type:"save",
|
||||
payload:{ recommandList : response}
|
||||
})
|
||||
},
|
||||
*getGroupTypeList({payload},{call,put}){
|
||||
const response = yield call(getGroupType,payload);
|
||||
yield put({
|
||||
type:"save",
|
||||
payload:{ typeList : response}
|
||||
})
|
||||
},
|
||||
*getCategoryList({payload},{call,put}){
|
||||
const response = yield call(getcategory,payload);
|
||||
yield put({
|
||||
type:"save",
|
||||
payload:{ categoryList : response}
|
||||
})
|
||||
}
|
||||
},
|
||||
reducers:{
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
.slickBox {
|
||||
}
|
||||
.boxwidth{
|
||||
padding:20px 0px;
|
||||
}
|
||||
.datas{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding:20px 0px;
|
||||
align-items: flex-start;
|
||||
div[class=~"leftList"]{
|
||||
width: 26%;
|
||||
}
|
||||
div[class=~"rightList"]{
|
||||
width:72%;
|
||||
border:1px solid #eee;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,11 @@ import { Loading ,
|
|||
Dispatch,
|
||||
ProjectHomeState
|
||||
} from 'umi';
|
||||
import Recommand from '@/components/Recommand';
|
||||
import Recommand from '@/components/ProjectHome/recommand';
|
||||
import Type from '@/components/ProjectHome/type';
|
||||
import Category from '@/components/ProjectHome/category';
|
||||
import banner from '@/images/banner.jpg';
|
||||
import ListItem from '@/components/ProjectHome/listItem';
|
||||
|
||||
const setting={
|
||||
dots: true,
|
||||
|
@ -42,12 +45,24 @@ const Projectlist:FC<PageProps>=({
|
|||
payload:{page,limit}
|
||||
})
|
||||
},[page])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<img src={banner} width="100%"/>
|
||||
<div className={`${styles.boxwidth} boxWidth`}>
|
||||
<Recommand />
|
||||
<div className={styles.datas}>
|
||||
<div className={"leftList"}>
|
||||
<Type />
|
||||
<Category />
|
||||
</div>
|
||||
<div className={"rightList"}>
|
||||
{
|
||||
projectHome.projectList && projectHome.projectList.length>0 ?
|
||||
<ListItem list={projectHome.projectList} />
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -5,18 +5,12 @@ export async function getProjectList(params: any) {
|
|||
return get('/api/projects.json' , params );
|
||||
}
|
||||
// 项目类型
|
||||
export async function getGroupTypeList(params: any) {
|
||||
return Fetch('/api/projects/group_type_list.json', {
|
||||
method: 'get',
|
||||
body: params ,
|
||||
});
|
||||
export async function getGroupType(params: any) {
|
||||
return get('/api/projects/group_type_list.json', params );
|
||||
}
|
||||
// 项目类别
|
||||
export async function getGroupList(params: any) {
|
||||
return Fetch('/api/project_categories/group_list.json', {
|
||||
method: 'get',
|
||||
body: params ,
|
||||
});
|
||||
export async function getcategory(params: any) {
|
||||
return get('/api/project_categories/group_list.json',params);
|
||||
}
|
||||
// 项目语言
|
||||
export async function getLanguages(params: any) {
|
||||
|
|
|
@ -4,10 +4,56 @@
|
|||
[class*=' icon-'] {
|
||||
font-size: 16px;
|
||||
}
|
||||
.blue{
|
||||
color: @primary;
|
||||
}
|
||||
.orange{
|
||||
color: @light-orange;
|
||||
}
|
||||
.green{
|
||||
color: @green-29b;
|
||||
}
|
||||
.yellow{
|
||||
color: @yellow;
|
||||
}
|
||||
|
||||
.font12 {
|
||||
font-size: 12px;
|
||||
}
|
||||
.privateTag {
|
||||
display: inline-block;
|
||||
padding: 0px 6px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid @green-29b;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
font-size: 12px;
|
||||
color: @green-29b;
|
||||
}
|
||||
.pariseTag{
|
||||
padding: 0px 10px;
|
||||
border-radius: 15px;
|
||||
background: @little-orange;
|
||||
color: #333;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
.forkTag{
|
||||
padding: 0px 10px;
|
||||
border-radius: 15px;
|
||||
background: @little-blue;
|
||||
color: #333;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.font13 {
|
||||
font-size: 13px;
|
||||
|
@ -322,3 +368,24 @@
|
|||
width: 1200px;
|
||||
margin:0px auto;
|
||||
}
|
||||
.hide{
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.hide2{
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
.alignCenter{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.alignCenterJSB{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
|
@ -15,20 +15,23 @@
|
|||
@cyan: #006b75;
|
||||
@grey-ede: #ededed;
|
||||
// @light-green: #7ad58b;
|
||||
@light-orange: #e99695;
|
||||
@light-orange: #ff6800;
|
||||
@light-blue-purple: #5e5fb9;
|
||||
@light-blue: #84b6eb;
|
||||
@little-blue:#EBF4FE;
|
||||
|
||||
@sky-blue: #f4faff;
|
||||
@cyan-blue: #18d0e7;
|
||||
@brilliant-blue: #aed5ff;
|
||||
@light-pink: #fc2b6a;
|
||||
@orange: #ff6800;
|
||||
@yellow:#ffc14b;
|
||||
|
||||
@purple-8C1: #8c18ff;
|
||||
|
||||
@orange-ff9: #ff954c;
|
||||
@orange-ff7: #ff7500;
|
||||
@little-orange:#FFF3DC;
|
||||
|
||||
@red-ee4: #ee4a1f;
|
||||
|
||||
|
|
Loading…
Reference in New Issue