专区添加项目+资源文章增加管理员删除和编辑操作

This commit is contained in:
caishi 2026-04-20 10:05:32 +08:00
parent e98b3a56a0
commit d3570b88bb
16 changed files with 846 additions and 84 deletions

View File

@ -32,9 +32,9 @@ export function initAxiosInterceptors(props) {
// 判断网络是否连接
initOnlineOfflineListener();
// var proxy = "https://testforgeplus.trustie.net";
var proxy = "https://testforgeplus.trustie.net";
// var proxy = "http://172.20.32.201:4000";
var proxy = "https://www.gitlink.org.cn";
// var proxy = "https://www.gitlink.org.cn";
//响应前的设置
axios.interceptors.request.use(

View File

@ -0,0 +1,155 @@
import React, { useEffect, useState } from 'react';
import { Modal , Table , Input , Button , Select , message , Popconfirm } from 'antd';
import { getManageProjects , getMemberProjectList , addProjects , addMemberProject , removeProject } from '../api';
const { Option } = Select;
function AddProjects({id,visible,typeList,role,onCancel,onFresh}){
const [ dataSource , setDataSource ]= useState([]);
const [ searchValue , setSearchValue ] = useState(null);
const [ page ,setPage ] = useState(1);
const [ total ,setTotal ] = useState(1);
const [ loading ,setLoading ] = useState(false);
const [repoTypeIds, setRepoTypeIds] = useState({});
const limit = 10;
useEffect(()=>{
if(id && visible && role){
Init(1,searchValue);
}
},[visible,id,role])
async function Init(page,search){
setLoading(true);
let response = {};
if(role==="Manager"){
//
response = await getManageProjects(id,{search,page,limit})
}else{
//
response = await getMemberProjectList(id,{search,page,limit})
}
if(response){
setDataSource(response.data.rows);
setTotal(response.data.total);
setLoading(false);
}
}
//
function SearchFunc(e){
setSearchValue(e.target.value);
setPage(1);
Init(1,e.target.value);
}
const columns=[
{
title:"项目名称",
key:"name",
dataIndex:"name",
ellipsis:true,
render:(value,item)=>{
return <span title={value}>{item.author && item.author.name}/{value}</span>
}
}, {
title:"最近更新时间",
key:"time",
dataIndex:"time_ago",
width:"15%",
}, {
title:"项目分类",
key:"cate",
dataIndex:"status",
width:"20%",
render:(value,item)=>{
return <Select
defaultValue={typeList && typeList[0].id}
style={{width:"90%"}}
onChange={(v) => {
const map = repoTypeIds;
map[item.id] = v;
setRepoTypeIds(map);
}}>
{typeList && typeList.map(e=>{return <Option key={e.id} value={e.id}>{e.name}</Option>})}
</Select>
}
}, {
title:"操作",
key:"name",
width:"12%",
render:(value,item)=>{
let addArr={
gitlinkProjectId: item.id,
projectTypeId: repoTypeIds[item.id] || typeList[0].id,
zoneId:id
}
return item.isChoose ?
<Button size='small' disabled={true}>已添加</Button>
:
<Button size='small' type="primary" onClick={()=>addProjectsFunc(item.id,id)}>+ 添加</Button>
}
}
]
async function addProjectsFunc(itemId,id){
let item={
gitlinkProjectId: itemId,
projectTypeId: repoTypeIds[itemId] || typeList[0].id,
zoneId:id
}
let response = {};
if(role==="Manager"){
//
response = await addProjects([item]);
}else{
//
response = await addMemberProject([item])
}
const res = response.data;
if(res && res.code === 200){
message.success("操作成功");
Init(page,searchValue);
onFresh();
}else{
message.error(res.msg);
}
}
function cancelFunc(){
setRepoTypeIds({});
onCancel();
setSearchValue(null);
}
return(
<Modal
visible={visible}
width={900}
footer={null}
onCancel={cancelFunc}
title="添加项目"
>
<div>
<span>项目/所有者名称</span>
<Input placeholder='请输入项目名称回车搜索'
allowClear
value={searchValue}
style={{width:"200px"}}
onChange={(e)=>{setSearchValue(e.target.value);if(!e.target.value)Init(1);}}
onPressEnter={SearchFunc}
/>
</div>
<Table
columns={columns}
className='mt20 aboutProjects'
size='small'
loading={loading}
dataSource={dataSource}
pagination={{current:page,pageSize:limit,onChange:(e)=>{setPage(e);Init(e,searchValue)},total:total,size:"small",hideOnSinglePage:true}}
/>
</Modal>
)
}
export default AddProjects;

View File

@ -1,5 +1,5 @@
import React,{ useState , useEffect, useRef } from 'react';
import { Badge, Breadcrumb , Divider, Spin } from 'antd';
import { Badge, Breadcrumb , Divider, Spin , Modal , message } from 'antd';
import liulan from '../img/liulan.png';
import RenderHtml from '../../../components/render-html';
import { Base64 } from 'js-base64';
@ -13,9 +13,10 @@ import { connect } from 'react-redux';
import { withRouter } from "react-router";
import { setZoneDetail, setNewsDetail } from '../../../redux/actions/server';
import {getUniqueIdentifier,getUserName,getBrowserPlatform,getBrowserBrand} from '../utils';
import {setZoneVisits} from '../api'
import { setZoneVisits , delNews } from '../api';
import { Link } from 'react-router-dom';
function NewsDetail(props){
const { deptId , id } = props.match.params;
const [ detail , setDetail ] = useState(props.newsDetail || undefined);
@ -24,8 +25,8 @@ function NewsDetail(props){
const [ isSpin , setIsSpin]=useState(false);
const [ commentReload, setCommentReload] = useState(undefined);
const temp = props.temp;
const { role } = props;
const zonedetail = props.zoneDetail || props.data;
if (__SERVER__ && detail) {
setMeta()
}
@ -106,6 +107,24 @@ function NewsDetail(props){
})
}
//
function deleteFunc() {
Modal.confirm({
title: '删除',
content: `确定删除文章"${detail.name}"`,
okText: '确认',
cancelText: '取消',
onOk:async() => {
const success = await delNews(id);
if (success) {
message.success("删除成功!");
setTimeout(() => {
props.history.push(`/zone/${deptId}/news`);
}, 400);
}
},
});
}
return(
<React.Fragment>
{
@ -133,7 +152,11 @@ function NewsDetail(props){
}
<div className="info_text">
<div className="info_text_main">
<p className="i_name">{detail.name}</p>
<div className='df mb15'>
<p className="i_name">{detail.name}</p>
{ role === "Manager" && <Link to={`/zone/${deptId}/news/${id}/edit`} style={{marginLeft:"auto"}} className='color-blue mr20'>编辑</Link> }
{ role === "Manager" && <a className='color-red' onClick={deleteFunc}>删除</a> }
</div>
<ul className="i_ul_value">
{ cmsDir && <li><a href={ detail.publishUserUrl } ><img src={ detail.publishUserImage } alt="" className="headimg" /> { detail.publishUserNickname }</a></li> }
{ cmsDir && <li>{ detail.isFirstPublish ? '创建于' : '更新于' }{detail.publishTime}</li> }

View File

@ -1,15 +1,16 @@
import React , { useEffect , useState } from 'react';
import Banner from '../Component/publicBanner';
import "../index.scss";
import { Box , LongWidth } from '../../Component/layout';
import { Input , Menu , Pagination , Spin } from 'antd';
import { Link } from 'react-router-dom';
import { Input , Menu , Pagination , Spin , Button } from 'antd';
import Nodata from '../../Nodata';
import axios from 'axios';
import { getProjectsLists , getProjectsTypeLists } from '../api';
import nodata from '../img/nodata.png';
import { tempEnum } from '../tempInfo';
import {getUniqueIdentifier,getUserName,getBrowserPlatform,getBrowserBrand} from '../utils'
import {setZoneVisits} from '../api'
import {setZoneVisits , getAuditStatus} from '../api';
import { memberStatusEnum } from '../Pages/zoneVIP';
import AddProjects from '../Component/addProjects';
import { Link } from 'react-router-dom';
const { Search } = Input;
function ProjectSource(props){
@ -19,22 +20,37 @@ function ProjectSource(props){
const [ lists , setLists ] = useState(undefined);
const [ page, setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ visible ,setVisible ] =useState(false);
const pageSize = 20;
const [ searchName , setSearchName ] = useState(undefined);
const [ value , setValue ] = useState(undefined);
const [ loading , setLoading ] = useState(false);
const { id, temp, sectionProjectTitle } = props;
const [ memberStatus , setMemberStatus] = useState(memberStatusEnum.notMember);
const { id, temp, sectionProjectTitle , role } = props;
useEffect(()=>{
let uuid = getUniqueIdentifier()
let url = props.location.pathname
let platform = getBrowserPlatform()
let browser = getBrowserBrand()
let username = getUserName(props.current_user)
let username = getUserName(props.current_user);
getMemberStatus();
// if(!username) uuid = getUniqueIdentifier()
let remark = ` 操作系统:${platform};浏览器:${browser};`
setZoneVisits({url,username,uuid,remark})
},[])
//
function getMemberStatus() {
getAuditStatus(id).then(res => {
if (res && res.data && res.data.code === 200) {
setMemberStatus(res.data.data)
} else {
setMemberStatus(memberStatusEnum.notMember)
}
}).catch(() => { setMemberStatus(memberStatusEnum.notMember) })
}
useEffect(()=>{
if(id){
getTypeList();
@ -88,10 +104,16 @@ function ProjectSource(props){
}
return(
<div className="in_pro">
{/* <Banner {...props}/> */}
<AddProjects id={id} visible={visible} typeList={typeList} onCancel={()=>setVisible(false)} role={role && role.role} onFresh={getLists}/>
<div className="boxmain" style={{paddingTop:"56px"}}>
<p className="in_title">{sectionProjectTitle}</p>
{ temp === tempEnum.zone1 && <p className="project_sub_title">聚合开源特色项目搭建硬件开源服务桥梁</p> }
<div className='titleButBox'>
<p className="in_title">{sectionProjectTitle}</p>
{role && role.role !== "None" && <div className='createButs mt10'>
<Button type="primary" ghost className='mr20'><Link to={`/zone/${deptId}/projects/self`}>{role.role === "Member" ? "我的项目" : "管理项目" }</Link></Button>
<Button type="primary" ghost onClick={()=>setVisible(true)}>{role.role === "Member" ? "添加我的项目" : "添加项目" }</Button>
</div>}
{ temp === tempEnum.zone1 && <p className="project_sub_title">聚合开源特色项目搭建硬件开源服务桥梁</p> }
</div>
<Box>
<ul className="in_pro_menu">
<li className="u_t"><i className="iconfont icon-muluicon font-15 mr10 mt2" style={{color:"#1f2329"}} />项目分类</li>

View File

@ -0,0 +1,134 @@
import React,{ useEffect , useState } from 'react';
import "./index.scss";
import { Input , Pagination } from 'antd';
import { Link } from 'react-router-dom';
import { getGlobal , getSearchNews } from '../../api';
const { Search } = Input;
function SearchIndex(props){
const { search , pathname } = props.location;
const [ value , setValue ] = useState(null)
const [ type , setType ] = useState("zone_project");
const [ pageNum , setPageNum ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ lists , seLists ] = useState([]);
const pageSize = 16;
const id = props && props.data && props.data.id;
useEffect(()=>{
if(search){
setValue(decodeURI(search.replaceAll("?s=","")));
}
},[search])
useEffect(()=>{
if(type && id){
Initlist(value)
}
},[type,pageNum,id])
async function Initlist(keyword){
let res={};
let params={
keyword,zoneId:id,pageNum,pageSize
}
if(type==="news"){
res= await getSearchNews(params);
}else{
res= await getGlobal({...params,types:type});
}
console.log(res);
setTotal(res.data.total);
seLists(res.data.rows);
}
return(
<div className='findPage'>
<div className='findBox'>
<div className='searchBox'>
<Search
style={{flex:1}}
prefix={<i className="iconfont icon-sousuo5 font-15"/>}
value={value}
onChange={(e)=>setValue(e.target.value)}
onPressEnter={(e)=>{window.history.pushState('','',pathname+`?s=`+e.target.value);Initlist(e.target.value);}}
/>
<span className='searchCount'>共找到<span>142</span>个结果</span>
</div>
<ul className='findResultType'>
<li className={type==="zone_project" ? 'active':""} onClick={()=>{setType("zone_project")}}>开源项目</li>
<li className={type==="resource" ? 'active':""} onClick={()=>{setType("resource")}}>资源聚合</li>
<li className={type==="news" ? 'active':""} onClick={()=>{setType("news")}}>新闻动态</li>
<li className={type==="member" ? 'active':""} onClick={()=>{setType("member")}}>社区会员</li>
</ul>
<div className='findListBox'>
{
lists && lists.length>0 &&
<div className='findLists'>
{
lists.map((i,k)=>{
return type==="zone_project" ? <div key={k}>
{/* 开源项目 */}
<div className='findName task-hide' dangerouslySetInnerHTML={{__html:i.title}} />
<p className='findDesc task-hide-2'>{i.content}</p>
<div className='findInfo mt30'>
<ul>
<li>并行算法</li>
<li>C++</li>
</ul>
<span>2026-02-03</span>
</div>
<Link to={``} className="rnLink">立即查看<i className="iconfont font-12 icon-jiantou1 ml5" /></Link>
</div>:""
})
}
<div>
{/* #社区会员 */}
<div className='vipBox'>
<img className='vipPhoto' src={``} alt="" />
<div className='vipInfo'>
<div><span className='vipname'>李向辉</span><span className='vipschool'>湖南大学</span></div>
<p className='viptitle task-hide'>面向新一代国产超算系统的多领域共性算法大规模并行技术与应用服务平台课题负责人</p>
</div>
</div>
<Link to={``} className="rnLink">立即查看<i className="iconfont font-12 icon-jiantou1 ml5" /></Link>
</div>
<div>
{/* #资源聚合 */}
<p className='findName task-hide'>资源聚合---------ParallelCFD · 高性能并行计算流体仿真框架</p>
<p className='findDesc task-hide-2'>基于 MPI/OpenMP 的开源流体力学并行计算框架支持结构网格与非结构网格已在天河二号神威·太湖之光等国产超算上完成百万核规模验证</p>
<p className='sourcelist'>包含资源并行计算基础讲义.pdf</p>
<div className='findInfo mt20'>
<ul>
<li>6</li>
<li>1880</li>
</ul>
<span>2026-02-03</span>
</div>
<Link to={``} className="rnLink">立即查看<i className="iconfont font-12 icon-jiantou1 ml5" /></Link>
</div>
<div>
{/* #新闻动态 */}
<p className='findName task-hide'>新闻动态---------ParallelCFD · 高性能并行计算流体仿真框架</p>
<p className='findDesc task-hide-2'>基于 MPI/OpenMP 的开源流体力学并行计算框架支持结构网格与非结构网格已在天河二号神威·太湖之光等国产超算上完成百万核规模验证</p>
<div className='findInfo mt30'>
<ul>
<li>6</li>
<li>1880</li>
</ul>
<span>2026-02-03</span>
</div>
<Link to={``} className="rnLink">立即查看<i className="iconfont font-12 icon-jiantou1 ml5" /></Link>
</div>
</div>
}
<div className='findPageBox'>
<Pagination className='mt20' pageSize={pageSize} current={pageNum} total={total} onChange={(p)=>setPageNum(p)} />
</div>
</div>
</div>
</div>
)
}
export default SearchIndex;

View File

@ -0,0 +1,215 @@
@import '../../theme.scss';
.findPage{
background:url(../../img/search/bc.png) #f7faff;
background-size: 100%;
background-repeat: no-repeat;
min-height: 100vh;
padding-bottom: 60px;
.findBox{
padding-top: 60px;
width: 1600px;
margin:0 auto;
.searchBox{
height:52px;
background:#ffffff;
border-radius:26px;
display: flex;
justify-content: space-between;
padding:0 6px;
align-items: center;
.ant-input-affix-wrapper .ant-input{
color:#1f2329;
padding-left: 40px;
}
.ant-input-affix-wrapper .ant-input,.ant-input:focus{
border:none!important;
font-size: 15px;
}
.ant-input-prefix i{
background-color: #fff;
}
.ant-input-suffix{
opacity: 0;
}
.searchCount{
width:138px;
height:40px;
line-height:40px;
background:rgba(76, 88, 118, 0.08);
color:rgba(9, 18, 33, 0.8);
border-radius:26px;
padding:0 12px;
width: max-content;
margin-left: 20px;
>span{
margin:0 3px;
}
}
}
.findResultType{
margin-top: 30px;
display: flex;
align-items: center;
li{
display: flex;
align-items: center;
height:32px;
line-height:32px;
background:#ffffff;
border-radius:6px;
padding:0px 10px;
color:#091221;
margin-right: 15px;
cursor: pointer;
span{
height:16px;
line-height:16px;
background:rgba(76, 88, 118, 0.08);
border-radius:8px;
color:#091221;
opacity:80%;
font-size:12px;
padding:0 3px;
margin-left: 2px;
}
&.active{
background:#091221;
color: #fff;
span{
background:rgba(76, 88, 118, 0.2);
color:#ffffff;
}
}
}
}
.findListBox{
background-color: #fff;
padding:25px 0 25px 25px;
margin-top: 30px;
border-radius:15px;
box-shadow:0px 3px 12px rgba(130, 132, 164, 0.05);
.findLists{
display: flex;
flex-wrap: wrap;
gap: 25px;
>div{
background:rgba(76, 88, 118, 0.03);
border-radius:12px;
flex: 0 0 calc(50% - 25px);
padding:20px;
box-sizing: border-box;
position: relative;
overflow: hidden;
font-family: "alibabaReg";
&:hover{
background-image: url(../../img/search/itembc.png);
background-size: 100% 100%;
.rnLink{
bottom: 20px;
opacity: 1;
}
}
.rnLink{
position: absolute;
bottom: -100%;
left: 20px;
right: 20px;
height:32px;
line-height:32px;
background:#091221;
border-radius:6px;
color: #fff;
text-align: center;
font-size:15px;
z-index: 1;
opacity: 0;
transition: 0.5s;
}
.findName{
color:#091221;
font-size:18px;
font-family: "alibaba";
}
.findDesc{
color:#091221;
font-size:15px;
line-height:26px;
margin-top: 15px;
}
.sourcelist{
margin-top: 20px;
color:#466aff;
font-size:15px;
}
.findInfo{
display: flex;
align-items: center;
justify-content: space-between;
color:#191919;
font-size:13px;
ul{
display: flex;
align-items: center;
li{
margin-right: 10px;
height:24px;
line-height:24px;
background:#f3f5fb;
border-radius:4px;
color:#091221;
padding:0px 10px;
}
}
}
.vipBox{
display: flex;
.vipPhoto{
width:40px;
height:40px;
border-radius: 50%;
margin-right: 15px;
}
.vipInfo{
flex: 1;
width: 0;
.vipname{
font-family: "alibaba";
font-size:18px;
margin-right: 10px;
}
.vipschool{
background-image: url(../../img/search/schoolBc.png);
background-size: 100% 100%;
color:#466aff;
width: max-content;
padding:0 5px;
height: 22px;
line-height: 20px;
font-size: 12px;
display: inline-block;
text-align: center;
}
.viptitle{
margin-top: 15px;
text-align: center;
}
}
}
}
}
.findPageBox{
text-align: right;
padding-right: 25px;
}
}
}
}
@media screen and (max-width:1400px) {
.findPage{
.findBox{
width: 1400px;
}
}
}

View File

@ -1,7 +1,7 @@
import React,{ useState, useEffect } from 'react';
import { Breadcrumb , Spin , Pagination , Modal, Button } from 'antd';
import { Link } from 'react-router-dom';
import { getNewsMyList , getSourceMyList , delNewsMyList , delSourceMyList } from '../api';
import { getNewsMyList , getSourceMyList , delNewsMyList , delSourceMyList , getProjectMyList , removeProject , getManageProjectMyList , deleteMemberProject } from '../api';
import moment from 'moment';
import nodata from '../img/nodata.png';
import { tempEnum } from '../tempInfo';
@ -21,11 +21,23 @@ function SelfList(props){
const [ deleId , setDeleId] = useState(undefined);
const pathname = props.location.pathname;
const { deptId} = props.match.params;
const { id , temp , data } = props;
// const { sectionCmsTitle } = data;
const sectionCmsTitle = data && data.sectionCmsTitle;
const { id , temp , data , role } = props;
const { sectionCmsTitle, sectionResourceTitle , sectionProjectTitle } = data||{};
const limit = 15;
useEffect(()=>{
if(pathname){
if(pathname.indexOf("/source/self")>-1){
setSource("source");
}else if(pathname.indexOf("/news/self")>-1){
setSource("news");
}else{
setSource("projects");
}
}
},[pathname])
useEffect(()=>{
if(id){
setIsSpin(true);
@ -44,23 +56,35 @@ function SelfList(props){
},[status])
function getFunc(s){
if(s===true){
if(s==="source"){
getSource();
}
if(s===false){
if(s==="news"){
getNew();
}
if(s==="projects"){
getProjects();
}
}
useEffect(()=>{
if(pathname){
if(pathname.indexOf("/source/self")>-1){
setSource(true);
}else{
setSource(false);
}
async function getProjects(){
setIsSpin(false);
let result = {};
if(role && role.role === "Member"){
result = await getProjectMyList({auditStatus:status,zoneId:id,pageSize:limit,pageNum:page})
}else{
result = await getManageProjectMyList({auditStatus:status,zoneId:id,pageSize:limit,pageNum:page})
}
},[pathname])
let rows = result.data && result.data.rows;
if(rows && rows.length>0){
setList(rows.map(i=>{return {...i,name:i.projectProperties.name,domainName:i.projectType,timeAgo:i.projectProperties.timeAgo}}));
}else{
setList([]);
}
setTotal(result.data.total);
setIsSpin(false);
}
function getSource(){
getSourceMyList({
@ -121,12 +145,26 @@ function SelfList(props){
}
}
async function handleRemove(name,id){
Modal.confirm({
title: '移除',
content: `确定从专区中移除项目"${name}"`,
okText: '确认',
cancelText: '取消',
onOk:async() => {
const success =role && role.role==="Member" ? await deleteMemberProject(id+"") : await removeProject(id+"");
if (success) {
getFunc(source);
}
},
});
}
return(
<div className="selfBoxContent">
<Modal
visible={visible}
width="456px"
title={`申请删除${source?"资源":"文章"}`}
title={`申请删除${source==="source"?"资源":source==="news"?"文章":"项目"}`}
onCancel={cancelFunc}
footer={null}
className="delSModal"
@ -134,7 +172,7 @@ function SelfList(props){
<div className="delBoxCon">
<i className="iconfont icon-shanchu_tc_icon font-22 mr15" style={{color:"#ca0002"}}></i>
<div>
<p className="font-15 mb15 mt5" style={{color:"#202d40"}}>确定删除该{source?"资源":"文章"}?</p>
<p className="font-15 mb15 mt5" style={{color:"#202d40"}}>确定删除该{source==="source"?"资源":source==="news"?"文章":"项目"}?</p>
{(source || (!source && status === 1 && (data && data.docNeedAudit===1))) && <p style={{color:"#5f6872"}}>{source?"删除后所有资源文件将被清除,请谨慎操作":"此操作将提交删除申请,管理员同意申请后该文章将被删除"}</p> }
</div>
</div>
@ -144,8 +182,8 @@ function SelfList(props){
</div>
</Modal>
<Breadcrumb separator=">" style={{paddingTop:"20px"}}>
<Breadcrumb.Item><Link className="primaryColor" to={pathname.replace("/self","")}>{ sectionCmsTitle }</Link></Breadcrumb.Item>
<Breadcrumb.Item>我的{source ? "资源":"文章"}</Breadcrumb.Item>
<Breadcrumb.Item><Link className="primaryColor" to={pathname.replace("/self","")}>{ source==="source"?sectionResourceTitle:source==="news"?sectionCmsTitle:sectionProjectTitle }</Link></Breadcrumb.Item>
<Breadcrumb.Item>我的{source==="source"?"资源":source==="news"?"文章":"项目"}</Breadcrumb.Item>
</Breadcrumb>
<ul className="selfMenu">
<li onClick={()=>setStatus(1)} className={status===1?"active":""}>已发布</li>
@ -167,16 +205,25 @@ function SelfList(props){
return(
<li>
<div>
<Link to={`/zone/${deptId}/${source?"source":"newdetail"}/${i.id}`} className="s-name task-hide">{i.name}</Link>
{
source==="projects"?<a href={i.projectURL}>{i.name}</a>
:
<Link to={`/zone/${deptId}/${source==="source"?"source":"newdetail"}/${i.id}`} className="s-name task-hide">{i.name}</Link>
}
<div className="s-info">
<span>
<span>{i.domainName || i.dirName}</span>
<span className="ml10 mr15">|</span>
<span><i className="iconfont icon-a-31shijian mr5 font-15"></i>{moment(i.createTime).format("YYYY/MM/DD")}</span>
<span><i className="iconfont icon-a-31shijian mr5 font-15"></i>{i.timeAgo || moment(i.createTime).format("YYYY/MM/DD")}</span>
</span>
<span className="s-info-right">
<a href={`/zone/${deptId}/${source ? 'source' : 'news'}/${i.id}/edit`} style={{color:"#466aff"}}><i className="iconfont icon-a-bianji12 mr5 font-14"></i>编辑</a>
<a style={{color:"#d81017",marginLeft:"25px"}}onClick={()=>{setVisible(true);setDeleId(i.id)}}><i className="iconfont icon-fuzhi-shanchu mr5 font-14"></i>删除</a>
{source!=="projects" && <a href={`/zone/${deptId}/${source}/${i.id}/edit`} style={{color:"#466aff"}}><i className="iconfont icon-a-bianji12 mr5 font-14"></i>编辑</a> }
{
source==="projects"?
<a style={{color:"#d81017",marginLeft:"25px"}} onClick={()=>handleRemove(i.name,i.id)}><i className="iconfont icon-fuzhi-shanchu mr5 font-14"></i>移除</a>
:
<a style={{color:"#d81017",marginLeft:"25px"}}onClick={()=>{setVisible(true);setDeleId(i.id)}}><i className="iconfont icon-fuzhi-shanchu mr5 font-14"></i>删除</a>
}
</span>
</div>
</div>

View File

@ -3,7 +3,7 @@ import { Breadcrumb, Button, Form, Icon, Input, message, Select, Upload } from '
import { getZoneUrl } from 'educoder';
import '../index.scss';
import { Link } from 'react-router-dom';
import { getTypeByFileId, getSourceZoneList, addResource, getSourceDetailByAu, updateMyResource } from '../api';
import { getTypeByFileId, getSourceZoneList, addResource, getSourceDetailByAu , getSourceDetailByM , updateMyResource , updateManageResource } from '../api';
function SourceCreate(props){
const {history, id, role, current_user} = props;
@ -41,29 +41,33 @@ function SourceCreate(props){
}
},[pathname])
function getSourceDetail() {
getSourceDetailByAu(sourceid).then(res=>{
if(res && res.data){
const {name, domainId, summary, fileList} = res.data.data;
const fileMap = fileList.map(item=>{
const {fileId, fileSizeInfo, fileOriginName, zoneResourceType: {id, name}} = item;
return {
uid: fileId,
status: "done",
response: {fileId: fileId, fileSize: fileSizeInfo},
name: fileOriginName,
zoneResourceType:{id, name}
}
})
setFiles(fileMap);
setFieldsValue({
name,
domainId,
summary,
fileList: fileMap
});
}
})
async function getSourceDetail() {
let res = {};
if(role && role.role ==="Member"){
res= await getSourceDetailByAu(sourceid)
}else{
res= await getSourceDetailByM(sourceid)
}
if(res && res.data){
const {name, domainId, summary, fileList} = res.data.data;
const fileMap = fileList.map(item=>{
const {fileId, fileSizeInfo, fileOriginName, zoneResourceType: {id, name}} = item;
return {
uid: fileId,
status: "done",
response: {fileId: fileId, fileSize: fileSizeInfo},
name: fileOriginName,
zoneResourceType:{id, name}
}
})
setFiles(fileMap);
setFieldsValue({
name,
domainId,
summary,
fileList: fileMap
});
}
}
function getZoneList(){
@ -77,7 +81,7 @@ function SourceCreate(props){
// /
function submit(e){
e.preventDefault();
validateFields((err, fieldsValue)=>{
validateFields(async (err, fieldsValue)=>{
if(err || !files.length){
!files.length && setFields({fileList: {value:undefined,errors:[new Error('请上传资源附件!')]}});
return;
@ -92,15 +96,19 @@ function SourceCreate(props){
if(isEdit){
delete params.zoneId;
params.id= parseInt(sourceid, 10);
updateMyResource(params).then((res)=>{
const {data:{code, msg}} = res;
if(code === 200){
message.success("提交成功");
history.push(`/zone/${deptId}/source/${sourceid}`);
}else{
message.error(msg || '提交失败,请联系管理员!')
}
})
let res = {};
if(role && role.role ==="Member"){
res= await updateMyResource(params)
}else{
res= await updateManageResource(params)
}
const {data:{code, msg}} = res;
if(code === 200){
message.success("提交成功");
history.push(`/zone/${deptId}/source/${sourceid}`);
}else{
message.error(msg || '提交失败,请联系管理员!')
}
return;
}
addResource(params).then((res)=>{

View File

@ -1,7 +1,7 @@
import React , { useEffect , useState } from 'react';
import { Badge, Breadcrumb } from 'antd';
import { Badge, Breadcrumb , Modal , message } from 'antd';
import SourceFile from '../img/sourceFile.png';
import { getSourceDetail } from '../api';
import { getSourceDetail , delManageSource } from '../api';
import { Link } from 'react-router-dom';
import { httpUrl } from '../fetch';
import { AlignCenter, FlexAJ } from '../../Component/layout';
@ -15,7 +15,7 @@ function SourceDetail(props){
const { deptId , sourceid } = props.match.params;
const [ detail , setDetail ] = useState(undefined);
const zonedetail = props.data;
const {temp} = props;
const {temp , role} = props;
useEffect(()=>{
let uuid = getUniqueIdentifier()
@ -59,6 +59,25 @@ function SourceDetail(props){
}).catch(error=>{})
}
//
function deleteFunc() {
Modal.confirm({
title: '删除',
content: `确定删除该资源"${detail.name}"`,
okText: '确认',
cancelText: '取消',
onOk:async() => {
const success = await delManageSource(sourceid);
if (success) {
message.success("删除成功!");
setTimeout(() => {
props.history.push(`/zone/${deptId}/source`);
}, 400);
}
},
});
}
return(
<div className="boxmain"style={{paddingBottom:"40px"}}>
<Breadcrumb separator=">" style={{paddingTop:"20px"}}>
@ -74,6 +93,8 @@ function SourceDetail(props){
<span className='domainNameBoxD font-13 mr15'>{detail.domainName}</span>
<span className='font-22' style={{flex: 1}}>{detail.name}</span>
</AlignCenter>
{ role === "Manager" && <Link to={`/zone/${deptId}/source/${sourceid}/edit`} style={{marginLeft:"auto"}} className='color-blue mr20'>编辑</Link> }
{ role === "Manager" && <a className='color-red mr20' onClick={deleteFunc}>删除</a> }
<div className="load_count">
<img src={SourceIcon} alt="" width="18px" className="mr5" style={{marginTop: '-4px'}}/><span style={{color:"#5e6685"}}>{detail.downloadCount}</span>
</div>

View File

@ -110,6 +110,12 @@ export function getNewsDetail(id){
method: 'get',
})
}
export function delNews(id){
return fetch({
url:`/cms/doc/${id}`,
method: 'delete'
})
}
export function getNewsMyList(id,params){
return fetch({
url:`/cms/doc/zone/${id}/myDocList`,
@ -124,6 +130,22 @@ export function delNewsMyList(id){
})
}
// 搜索(文章)
export function getSearchNews(params){
return fetch({
url:`/cms/doc/open/search`,
method:"get",
params
})
}
export function getGlobal(params){
return fetch({
url:`/zone/open/global`,
method:"get",
params
})
}
/**开源项目 */
export function getProjectsLists(id,params){
return fetch({
@ -138,6 +160,29 @@ export function getProjectsTypeLists(id){
method: 'get',
})
}
// 获取管理员身份对应的项目列表(所有)
export function getManageProjects(id,params){
return fetch({
url:`/zone/project/zone/${id}/gitlinkProjectList`,
method: 'get',
params
})
}
//从专区移除项目
export function removeProject(id){
return fetch({
url:`/zone/project/${id}`,
method: 'delete',
})
}
// 批量新增项目聚合
export async function addProjects(data) {
return fetch({
url:"/zone/project",
method: 'POST',
data,
});
}
/**专区会员 */
export function getVIPLists(id, params){
return fetch({
@ -210,6 +255,13 @@ export function delSourceMyList(id){
method:"delete"
})
}
// 删除资源(管理员)
export function delManageSource(id){
return fetch({
url:`/zone/resource/${id}`,
method:"delete"
})
}
// 创建专区
export function postCreateZone(data) {
@ -287,6 +339,13 @@ export function getSourceDetailByAu(id){
method: 'get',
})
}
// 获取资源详细信息(需要管理员权限)
export function getSourceDetailByM(id){
return fetch({
url:`/zone/resource/${id}`,
method: 'get',
})
}
// 修改资源详细信息(需要用户权限)
export function updateMyResource(data) {
@ -296,7 +355,14 @@ export function updateMyResource(data) {
data: data
});
}
// 修改资源详细信息(需要管理员权限)
export function updateManageResource(data) {
return fetch({
url: `/zone/resource`,
method: 'PUT',
data: data
});
}
// 评论相关
// 评论列表
export function getCommentList(id, params) {
@ -447,3 +513,42 @@ export function setZoneVisits(data) {
data
})
}
// 专区下我已添加或待审核的项目列表
export function getProjectMyList(params){
return fetch({
url: `/zone/zoneFront/myProjectList`,
method: 'get',
params
})
}
// 专区下我的GitLink项目列表(管理员身份)
export function getManageProjectMyList(params) {
return fetch({
url: `/zone/project/list`,
method: 'get',
params
})
}
// 专区下我的GitLink项目列表(会员身份)
export function getMemberProjectList(zoneId,params) {
return fetch({
url: `/zone/zoneFront/zone/${zoneId}/myGitlinkProjectList`,
method: 'get',
params
})
}
//添加项目聚合(会员身份)
export function addMemberProject(data) {
return fetch({
url: `/zone/zoneFront/addProject `,
method: 'POST',
data,
})
}
// 删除项目聚合(会员身份)
export function deleteMemberProject(ids){
return fetch({
url: `/zone/zoneFront/removeProject/${ids}`,
method: 'delete',
})
}

View File

@ -15,7 +15,7 @@ function beforeFetch(actionUrl){
service.interceptors.request.use(request => {
let deptId = sessionStorage.getItem('deptId')
// request.headers.Authorization = 'be06b98eb11dc58de93ab4d9de5b673ebae935bd'
request.headers.Authorization = '58e93a7236f239c3805ab0bbc91bacb8de9b1811'
if (deptId) {
// 用于权限区分
request.headers['Dept-Id'] = deptId

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -94,6 +94,10 @@ const Help = Loadable({
loader: () => import("./Pages/help"),
loading: Loading,
});
const SearchPage = Loadable({
loader: () => import("./Pages/search"),
loading: Loading,
});
const HomePageByJCC = Loadable({
loader : () => import("./Pages/JCC/homePage"),
@ -127,6 +131,8 @@ function Index(props){
const [ role , setRole ] = useState(undefined);
const { pathname } = props.history.location;
const sourcedetail = pathname.indexOf(`/zone/${deptId}/newdetail/`)>-1 && isPhone();
const isSearch = pathname ===`/zone/${deptId}/search`;
const {current_user} = props;
@ -196,12 +202,12 @@ function Index(props){
return(
<div className="information_main">
{ (!sourcedetail && deptId!=="apply") && (id ? <PublicBanner {...props} data={data} temp={ temp } adminUrl={adminUrl} id={id}/> : <div style={{ width: '100%', height: '450px' }}></div>)}
{ ((!isSearch && !sourcedetail && deptId!=="apply")) && (id ? <PublicBanner {...props} data={data} temp={ temp } adminUrl={adminUrl} id={id}/> : <div style={{ width: '100%', height: '450px' }}></div>)}
<Switch>
<Route
path="/zone/:deptId/news/self"
render={(p) => (
<SourceSelfList {...props} {...p} id={id} temp={ temp } data={data}/>
<SourceSelfList {...props} {...p} id={id} temp={ temp } data={data} role={role}/>
)}
></Route>
<Route
@ -225,7 +231,7 @@ function Index(props){
<Route
path="/zone/:deptId/newdetail/:id"
render={(p) => (
<NewsDetail {...props} {...p} id={id} temp={ temp } data={data}/>
<NewsDetail {...props} {...p} id={id} temp={ temp } data={data} role={role && role.role}/>
)}
></Route>
<Route
@ -249,7 +255,7 @@ function Index(props){
<Route
path="/zone/:deptId/source/:sourceid"
render={(p) => (
<SourceDetail {...props} {...p} id={id} temp={ temp } data={data}/>
<SourceDetail {...props} {...p} id={id} temp={ temp } data={data} role={role && role.role}/>
)}
></Route>
<Route
@ -282,10 +288,16 @@ function Index(props){
<VIP {...props} {...p} id={id} temp={ temp } sectionMemberTitle={data && data.sectionMemberTitle}/>
)}
></Route>
<Route
path="/zone/:deptId/projects/self"
render={(p) => (
<SourceSelfList {...props} {...p} id={id} temp={ temp } data={data}/>
)}
></Route>
<Route
path="/zone/:deptId/projects"
render={(p) => (
<ProjectSource {...props} {...p} id={id} temp={ temp } sectionProjectTitle={data && data.sectionProjectTitle}/>
<ProjectSource {...props} {...p} id={id} temp={ temp } role={role} sectionProjectTitle={data && data.sectionProjectTitle}/>
)}
></Route>
<Route
@ -300,6 +312,12 @@ function Index(props){
<Help {...props} {...p} id={id} temp={ temp } data={data} adminUrl={adminUrl}/>
)}
></Route>
<Route
path="/zone/:deptId/search"
render={(p) => (
<SearchPage {...props} {...p} id={id} temp={ temp } data={data} adminUrl={adminUrl}/>
)}
></Route>
<Route
path="/zone/apply"
render={(p) => (

View File

@ -723,7 +723,6 @@
color:#1f2329;
font-size:22px;
line-height: 30px;
margin-bottom: 14px!important;
word-break: break-all;
}
.i_ul_value{
@ -1810,6 +1809,9 @@
.pass .ant-badge-status-text{
color: var(--primary-color);
}
.setIndex{
z-index: 10000;
}
// --------------新建专区
.applyBox{
background-color: #fff;
@ -2155,6 +2157,18 @@
}
}
.aboutProjects{
border:none;
.ant-table{
.ant-table-thead{
background-color: #f7f7f7;
}
&>.ant-table-content > .ant-table-body{
margin:0px;
}
}
}
.color-grey-70{
color: #707992;
}