This commit is contained in:
caishi 2023-04-11 15:32:02 +08:00
commit bd94a31115
17 changed files with 373 additions and 85 deletions

View File

@ -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) => (

View File

@ -81,7 +81,7 @@ class PullRefresh extends Component {
{children}
{
count < 1 && <Nodata _html="暂无未读消息"/>
count < 1 && <Nodata _html="暂无未读消息" small/>
}
{/* 大于分页数据才显示loading */}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 115 KiB

View File

@ -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 &&

View File

@ -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">

View File

@ -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> :"" }

View File

@ -37,10 +37,13 @@ function UpdateDescModal({form , visible , onCancel , onOk,desc,website,lesson_u
//
function checkTopics(rule, value, callback){
const boolLength = value.filter(item=>item.length > 20);
const bool = value.filter(item=>!/^(?![-])[a-zA-Z0-9\u4e00-\u9fa5\\-]+$/.test(item));
if(value.length > 5){
callback("最多创建5个标签");
}else if(boolLength.length){
callback("每个标签最多支持20个汉字");
}else if(bool.length){
callback("标签名只允许包含中文、字母、数字或者中划线(-), 不能以中划线开头");
}
callback();
}

View File

@ -1,5 +1,5 @@
import React from "react";
import { Button, Checkbox, Form, Input, message, Select } from "antd";
import { Button, Checkbox, Form, Input, message, Select, Row, Col } from "antd";
import { useState } from "react";
import '../../new/index.scss';
import './index.scss';
@ -13,12 +13,14 @@ function Jurisdiction(props){
const resource = [{value: 2, name: '无权限'}, {value: 0, name: '只读'}, {value: 1, name: '读写'}];
const [codeSelectValue , setCodeSelectValue ] = useState(undefined);
const [prSelectValue , setPrSelectValue ] = useState(undefined);
const [ issueSelectValue , setIssueSelectValue ] = useState(undefined);
useEffect(()=>{
if(botDetail){
const {limit_and_events:{juris_diction_code, juris_diction_pr}} = botDetail
const {limit_and_events:{juris_diction_code, juris_diction_pr, juris_diction_issue}} = botDetail
setCodeSelectValue(juris_diction_code);
setPrSelectValue(juris_diction_pr);
setIssueSelectValue(juris_diction_issue);
}
}, [botDetail])
@ -32,6 +34,11 @@ function Jurisdiction(props){
return e;
}
function issueControl(e){
setIssueSelectValue(e);
return e;
}
// bot
function submit(e){
e.preventDefault();
@ -39,15 +46,17 @@ function Jurisdiction(props){
if(err){
return;
}
const {juris_diction_code, juris_diction_pr, event_code, event_pr} = fieldsValue;
const {juris_diction_code, juris_diction_pr, event_code, event_pr, event_issue, juris_diction_issue} = fieldsValue;
const params = {
...botDetail,
bot_id: parseInt(id),
limit_and_events: {
event_code: event_code ? event_code.toString() : "",
event_pr: event_pr ? event_pr.toString() : "",
event_code: event_code ? event_code.toString() : '',
event_pr: event_pr ? event_pr.toString() : '',
event_issue: event_issue ? event_issue.toString(): '',
juris_diction_code,
juris_diction_pr
juris_diction_pr,
juris_diction_issue
},
user_id: current_user && current_user.user_id,
}
@ -64,8 +73,8 @@ function Jurisdiction(props){
// 访
function jurisDictionPrValidator(rule, value, callback){
const {juris_diction_code} = getFieldsValue();
if(juris_diction_code === 2 && value === 2){
const {juris_diction_code, juris_diction_pr} = getFieldsValue();
if(juris_diction_code === 2 && value === 2 && juris_diction_pr === 2){
callback('请至少选择一个权限');
return;
}
@ -73,21 +82,13 @@ function Jurisdiction(props){
}
//
function eventValidator(rule, value, callback, type){
const {event_code, event_pr} = getFieldsValue();
const resourceValue = resource[0].value;
const boolPr = (event_code === undefined || (event_code && event_code.length === 0)) && prSelectValue === resourceValue;
const boolCode = (event_pr === undefined || (event_pr && event_pr.length === 0)) && codeSelectValue === resourceValue;
const bool = prSelectValue !== resourceValue && codeSelectValue !== resourceValue && (event_pr === undefined || (event_pr && event_pr.length === 0)) && (event_code === undefined || (event_code && event_code.length === 0))
if(boolPr || boolCode){
callback("请至少选择一个订阅");
return;
function eventValidator(rule, value, callback){
const {event_code, event_pr, event_issue} = getFieldsValue();
if(event_code || event_pr || event_issue){
callback();
}else{
callback("请至少选择一个订阅事件");
}
if(bool && type === "pr"){
callback("请至少选择一个订阅");
return;
}
callback();
}
return <Form className="createExploitForm jurisdictionBox" onSubmit={submit}>
@ -104,7 +105,16 @@ function Jurisdiction(props){
<div className="dashedBor"></div>
<Form.Item label="合并请求(PR)权限" className="resourceBox botItem">
<div className="color-99">合并请求的打开关闭编辑分配</div>
{getFieldDecorator("juris_diction_pr",{rules:[{validator: jurisDictionPrValidator}],initialValue: botDetail.limit_and_events.juris_diction_pr, getValueFromEvent: prControl})(
{getFieldDecorator("juris_diction_pr",{initialValue: botDetail.limit_and_events.juris_diction_pr, getValueFromEvent: prControl})(
<Select>
{resource.map(item=>{return <Option value={item.value} key={item.value}>{item.name}</Option>})}
</Select>
)}
</Form.Item>
<div className="dashedBor"></div>
<Form.Item label="疑修(Issue)权限" className="resourceBox botItem">
<div className="color-99">疑修的打开关闭编辑分配评论</div>
{getFieldDecorator("juris_diction_issue",{rules:[{validator: jurisDictionPrValidator}],initialValue: botDetail.limit_and_events.juris_diction_issue, getValueFromEvent: issueControl})(
<Select>
{resource.map(item=>{return <Option value={item.value} key={item.value}>{item.name}</Option>})}
</Select>
@ -114,12 +124,14 @@ function Jurisdiction(props){
{codeSelectValue !== resource[0].value && <Form.Item label="代码库事件" className="botItem width50 checkBox three dashedBorder">
{getFieldDecorator("event_code", {
initialValue: botDetail.limit_and_events.event_code ? botDetail.limit_and_events.event_code.split(',').map(item=>item = parseInt(item)) : [],
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback, "code")}}]
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback)}}]
})(
<Checkbox.Group>
<Checkbox value={0}>推送<br/><span className="color-99">git推送到存储库</span></Checkbox>
<Checkbox value={1}>创建<br/><span className="color-99">创建分支或标签</span></Checkbox>
<Checkbox value={2}>删除<br/><span className="color-99">删除分支或标签</span></Checkbox>
<Row>
<Col span={16}><Checkbox value={0}>推送<br/><span className="color-99">git推送到存储库</span></Checkbox></Col>
<Col span={8}><Checkbox value={1}>创建<br/><span className="color-99">创建分支或标签</span></Checkbox></Col>
<Col span={16}><Checkbox value={2}>删除<br/><span className="color-99">删除分支或标签</span></Checkbox></Col>
</Row>
</Checkbox.Group>
)}
</Form.Item>}
@ -127,11 +139,30 @@ function Jurisdiction(props){
{prSelectValue !== resource[0].value && <Form.Item label="合并请求事件" className="botItem width50 checkBox">
{getFieldDecorator("event_pr", {
initialValue: botDetail.limit_and_events.event_pr ? botDetail.limit_and_events.event_pr.split(',').map(item=>item = parseInt(item)) : [],
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback, "pr")}}]
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback)}}]
})(
<Checkbox.Group>
<Checkbox value={3}>合并请求<br/><span className="color-99">合并请求被打开被关闭被重新打开或被编辑</span></Checkbox>
<Checkbox value={4}>合并请求分配<br/><span className="color-99">合并请求被分配或取消分配</span></Checkbox>
<Row>
<Col span={16}><Checkbox value={3}>合并请求<br/><span className="color-99">合并请求被打开被关闭被重新打开或被编辑</span></Checkbox></Col>
<Col span={8}><Checkbox value={4}>合并请求分配<br/><span className="color-99">合并请求被分配或取消分配</span></Checkbox></Col>
<Col span={16}><Checkbox value={6}>合并请求被评论<br/><span className="color-99">合并请求评论被创建编辑或删除</span></Checkbox></Col>
</Row>
</Checkbox.Group>
)}
</Form.Item>}
{(codeSelectValue !== resource[0].value || prSelectValue !== resource[0].value) && issueSelectValue !== resource[0].value && <div className="dashedBor"></div>}
{issueSelectValue !== resource[0].value && <Form.Item label="疑修事件" className="botItem width50 checkBox three">
{getFieldDecorator("event_issue",{
initialValue: botDetail.limit_and_events.event_issue ? botDetail.limit_and_events.event_issue.split(',').map(item=>item = parseInt(item)) : [],
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback)}}]
})(
<Checkbox.Group>
<Row>
<Col span={16}><Checkbox value={7}>疑修<br/><span className="color-99">疑修已打开已关闭已重新打开或编辑</span></Checkbox></Col>
<Col span={8}><Checkbox value={8}>疑修已指派<br/><span className="color-99">疑修已被指派或取消指派</span></Checkbox></Col>
<Col span={16}><Checkbox value={9}>已标记疑修<br/><span className="color-99">疑修标记被更新或清除</span></Checkbox></Col>
<Col span={8}><Checkbox value={10}>疑修评论<br/><span className="color-99">疑修评论被创建编辑或删除</span></Checkbox></Col>
</Row>
</Checkbox.Group>
)}
</Form.Item>}

View File

@ -1,5 +1,5 @@
import React, { forwardRef, useState, useEffect } from "react";
import { Button, Checkbox, Form, Input, message, Radio, Select } from "antd";
import { Button, Checkbox, Col, Form, Input, message, Radio, Row, Select } from "antd";
import { Link } from "react-router-dom";
import MDEditor from '../../../../../modules/tpm/challengesnew/tpm-md-editor';
import './index.scss';
@ -14,7 +14,8 @@ function Disposition(props){
const [ content , setContent ] = useState(undefined);
const [ codeSelectValue , setCodeSelectValue ] = useState(resource[0].value);
const [ prSelectValue , setPrSelectValue ] = useState(resource[0].value);
const [ issueSelectValue , setIssueSelectValue ] = useState(resource[0].value);
useEffect(()=>{
document.title='注册新的Bot';
}, [])
@ -33,6 +34,11 @@ function Disposition(props){
return e;
}
function issueControl(e){
setIssueSelectValue(e);
return e;
}
// webhooks
function checkAddr(rule, value, callback) {
let reg = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
@ -47,8 +53,8 @@ function Disposition(props){
// 访
function jurisDictionPrValidator(rule, value, callback){
const {juris_diction_code} = getFieldsValue();
if(juris_diction_code === 2 && value === 2){
const {juris_diction_code, juris_diction_pr} = getFieldsValue();
if(juris_diction_code === 2 && value === 2 && juris_diction_pr === 2){
callback('请至少选择一个权限');
return;
}
@ -56,21 +62,13 @@ function Disposition(props){
}
//
function eventValidator(rule, value, callback, type){
const {event_code, event_pr} = getFieldsValue();
const resourceValue = resource[0].value;
const boolPr = (event_code === undefined || (event_code && event_code.length === 0)) && prSelectValue === resourceValue;
const boolCode = (event_pr === undefined || (event_pr && event_pr.length === 0)) && codeSelectValue === resourceValue;
const bool = prSelectValue !== resourceValue && codeSelectValue !== resourceValue && (event_pr === undefined || (event_pr && event_pr.length === 0)) && (event_code === undefined || (event_code && event_code.length === 0))
if(boolPr || boolCode){
callback("请至少选择一个订阅");
return;
function eventValidator(rule, value, callback){
const {event_code, event_pr, event_issue} = getFieldsValue();
if(event_code || event_pr || event_issue){
callback();
}else{
callback("请至少选择一个订阅事件");
}
if(bool && type === "pr"){
callback("请至少选择一个订阅");
return;
}
callback();
}
// bot
@ -80,17 +78,19 @@ function Disposition(props){
if(err){
return;
}
const {bot_name, bot_des, webhook, is_public, juris_diction_code, juris_diction_pr, event_code, event_pr, oauth_callback_url} = fieldsValue;
const {bot_name, bot_des, webhook, is_public, juris_diction_code, juris_diction_pr, event_code, event_pr, oauth_callback_url, event_issue, juris_diction_issue} = fieldsValue;
const param = {
bot_name, bot_des, webhook, is_public,
login: current_user && current_user.login,
user_id: current_user && current_user.user_id,
logo: `/api/attachments/${window.location.host !== 'www.gitlink.org.cn' ? 347246 : 412603}`,
limit_and_events: {
event_code: event_code ? event_code.toString() : "",
event_pr: event_pr ? event_pr.toString() : "",
event_code: event_code ? event_code.toString() : '',
event_pr: event_pr ? event_pr.toString() : '',
event_issue: event_issue ? event_issue.toString(): '',
juris_diction_code,
juris_diction_pr
juris_diction_pr,
juris_diction_issue
},
oauth_callback_url
}
@ -157,32 +157,61 @@ function Disposition(props){
<div className="dashedBor"></div>
<Form.Item label="合并请求(PR)权限" className="resourceBox botItem">
<div className="color-99">合并请求的打开关闭编辑分配</div>
{getFieldDecorator("juris_diction_pr",{rules:[{validator: jurisDictionPrValidator}],initialValue: resource[0].value, getValueFromEvent: prControl})(
{getFieldDecorator("juris_diction_pr",{initialValue: resource[0].value, getValueFromEvent: prControl})(
<Select>
{resource.map(item=>{return <Option value={item.value} key={item.value}>{item.name}</Option>})}
</Select>
)}
</Form.Item>
<div className="dashedBor"></div>
<Form.Item label="疑修(Issue)权限" className="resourceBox botItem">
<div className="color-99">疑修的打开关闭编辑分配评论</div>
{getFieldDecorator("juris_diction_issue",{rules:[{validator: jurisDictionPrValidator}],initialValue: resource[0].value, getValueFromEvent: issueControl})(
<Select>
{resource.map(item=>{return <Option value={item.value} key={item.value}>{item.name}</Option>})}
</Select>
)}
</Form.Item>
{(codeSelectValue !== resource[0].value || prSelectValue !== resource[0].value) && <div className="resourceTitle font-16 pb15 mb10">订阅事件</div>}
{codeSelectValue !== resource[0].value && <Form.Item label="代码库事件" className="botItem width50 checkBox three dashedBorder">
{codeSelectValue !== resource[0].value && <Form.Item label="代码库事件" className="botItem width50 checkBox dashedBorder">
{getFieldDecorator("event_code",{
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback, "code")}}]
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback)}}]
})(
<Checkbox.Group>
<Checkbox value={0}>推送<br/><span className="color-99">git推送到存储库</span></Checkbox>
<Checkbox value={1}>创建<br/><span className="color-99">创建分支或标签</span></Checkbox>
<Checkbox value={2}>删除<br/><span className="color-99">删除分支或标签</span></Checkbox>
<Row>
<Col span={16}><Checkbox value={0}>推送<br/><span className="color-99">git推送到存储库</span></Checkbox></Col>
<Col span={8}><Checkbox value={1}>创建<br/><span className="color-99">创建分支或标签</span></Checkbox></Col>
<Col span={16}><Checkbox value={2}>删除<br/><span className="color-99">删除分支或标签</span></Checkbox></Col>
</Row>
</Checkbox.Group>
)}
</Form.Item>}
{(codeSelectValue !== resource[0].value && prSelectValue !== resource[0].value) && <div className="dashedBor"></div>}
{prSelectValue !== resource[0].value && <Form.Item label="合并请求事件" className="botItem width50 checkBox">
{getFieldDecorator("event_pr",{
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback, "pr")}}]
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback)}}]
})(
<Checkbox.Group>
<Checkbox value={3}>合并请求<br/><span className="color-99">合并请求被打开被关闭被重新打开或被编辑</span></Checkbox>
<Checkbox value={4}>合并请求分配<br/><span className="color-99">合并请求被分配或取消分配</span></Checkbox>
<Row>
<Col span={16}><Checkbox value={3}>合并请求<br/><span className="color-99">合并请求被打开被关闭被重新打开或被编辑</span></Checkbox></Col>
<Col span={8}><Checkbox value={4}>合并请求分配<br/><span className="color-99">合并请求被分配或取消分配</span></Checkbox></Col>
<Col span={16}><Checkbox value={6}>合并请求被评论<br/><span className="color-99">合并请求评论被创建编辑或删除</span></Checkbox></Col>
</Row>
</Checkbox.Group>
)}
</Form.Item>}
{(codeSelectValue !== resource[0].value || prSelectValue !== resource[0].value) && issueSelectValue !== resource[0].value && <div className="dashedBor"></div>}
{issueSelectValue !== resource[0].value && <Form.Item label="疑修事件" className="botItem width50 checkBox">
{getFieldDecorator("event_issue",{
rules:[{validator: (rule, value, callback)=>{eventValidator(rule, value, callback)}}]
})(
<Checkbox.Group>
<Row>
<Col span={16}><Checkbox value={7}>疑修<br/><span className="color-99">疑修已打开已关闭已重新打开或编辑</span></Checkbox></Col>
<Col span={8}><Checkbox value={8}>疑修已指派<br/><span className="color-99">疑修已被指派或取消指派</span></Checkbox></Col>
<Col span={16}><Checkbox value={9}>已标记疑修<br/><span className="color-99">疑修标记被更新或清除</span></Checkbox></Col>
<Col span={8}><Checkbox value={10}>疑修评论<br/><span className="color-99">疑修评论被创建编辑或删除</span></Checkbox></Col>
</Row>
</Checkbox.Group>
)}
</Form.Item>}

View File

@ -24,7 +24,7 @@
.width50{
width: 60%;
&.checkBox{
width: 68%;
width: 75%;
}
.height36{
height: 36px;
@ -50,23 +50,15 @@
margin-bottom: 0;
}
&.checkBox .ant-checkbox-group{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 100%;
.ant-row{width: 100%;}
.color-99{padding-left: 24px;}
}
&.three .ant-checkbox-wrapper{
width: 34%;
margin-left: 0px;
padding-left: 12px;
&:first-child, &:last-child{
padding-left: 0px;
}
}
}
.dashedBor{
border-bottom: 1px dashed #e0e6f5;
margin-bottom: 12px;
margin-top: -20px;
}
.resourceBox + .dashedBor{
margin-top: -15px;

View File

@ -289,10 +289,10 @@ function New({ form , match , showNotification , history, projectDetail }) {
<Checkbox value="pull_request_assign">合并请求分配</Checkbox>
<span>合并请求被分配或取消分配</span>
</span>
{/* <span>
<span>
<Checkbox value="pull_request_comment">合并请求被评论</Checkbox>
<span>合并请求评论被创建编辑或删除</span>
</span> */}
</span>
{/* <span>
<Checkbox value="pull_request_milestone">合并请求收入里程碑</Checkbox>
<span>合并请求被记录或取消记录于里程碑中</span>
@ -310,7 +310,7 @@ function New({ form , match , showNotification , history, projectDetail }) {
<span>合并请求被同步</span>
</span> */}
</div>
{/* <p className="color-grey-3 mt10 mb10"></p>
<p className="color-grey-3 mt10 mb10">疑修事件</p>
<div className="colSpan">
<span>
<Checkbox value="issues_only">疑修</Checkbox>
@ -328,7 +328,7 @@ function New({ form , match , showNotification , history, projectDetail }) {
<Checkbox value="issue_comment">疑修评论</Checkbox>
<span>疑修评论被创建编辑或删除</span>
</span>
</div> */}
</div>
</Checkbox.Group>
{ eventFlag && <span style={{color:"#DF0002"}}>请选择自定义事件</span>}
</div>

View File

@ -170,10 +170,11 @@ ul,ol,dl{
&.small{
height: 120px;
img{
width:50px;
width:200px;
}
}
img{
width:300px;
margin-bottom: 15px;
}
}

124
src/forge/topic/index.jsx Normal file
View File

@ -0,0 +1,124 @@
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) => {
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) {
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>平台共{total}个公开项目与此标签相匹配</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 && <div className='repoByTopicNodata'><Nodata _html="暂无数据"/></div>}
{/* 项目列表 */}
{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>
)}
)))))

View File

@ -0,0 +1,99 @@
.topicRepoList{
width: 900px;
margin: 0 auto;
min-height: 700px;
.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;
}
.repoByTopicNodata .none_panels{
min-height: 520px;
}
}

View File

@ -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> }

View File

@ -221,7 +221,8 @@ function SoftBotDEtail(props){
</div>
<div className="installTil font-18 mt20 mb10">权限信息</div>
{detail && <div className="mb10 font-16 greenCol"><i className={`mr8 iconfont ${detail.limit_and_events.juris_diction_code !== 2 ? 'icon-wanchenggouxuan' : 'icon-tishi1 font-16'}`}></i>代码库{detail.limit_and_events.juris_diction_code === 2 ? '无' : detail.limit_and_events.juris_diction_code === 1 ? '读写' : '只读'}权限</div>}
{detail && <div className="mb20 font-16 greenCol"><i className={`mr8 iconfont ${detail.limit_and_events.juris_diction_pr !== 2 ? 'icon-wanchenggouxuan' : 'icon-tishi1 font-16'}`}></i>合并请求(PR){detail.limit_and_events.juris_diction_pr === 2 ? '无' : detail.limit_and_events.juris_diction_pr === 1 ? '读写' : '只读'}权限</div>}
{detail && <div className="mb10 font-16 greenCol"><i className={`mr8 iconfont ${detail.limit_and_events.juris_diction_pr !== 2 ? 'icon-wanchenggouxuan' : 'icon-tishi1 font-16'}`}></i>合并请求(PR){detail.limit_and_events.juris_diction_pr === 2 ? '无' : detail.limit_and_events.juris_diction_pr === 1 ? '读写' : '只读'}权限</div>}
{detail && <div className="mb20 font-16 greenCol"><i className={`mr8 iconfont ${detail.limit_and_events.juris_diction_issue !== 2 ? 'icon-wanchenggouxuan' : 'icon-tishi1 font-16'}`}></i>疑修(Issue){detail.limit_and_events.juris_diction_issue === 2 ? '无' : detail.limit_and_events.juris_diction_issue === 1 ? '读写' : '只读'}权限</div>}
</div>
</Modal>
</div>

View File

@ -132,7 +132,7 @@
flex-wrap: wrap;
justify-content: flex-start;
&>.none_panels{
margin: 0 auto;
margin: 125px auto;
}
.botLoading{
margin: 200px auto;