From be55a173844f40d79405a319a06651c2531ef59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E6=80=9D?= Date: Tue, 20 Jan 2026 16:32:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=BA=93=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/forge/Branch/Select.jsx | 18 +++--- src/forge/Component/PublicModal/Index.jsx | 3 +- src/forge/Main/tag/Empty.jsx | 22 +++++++ src/forge/Main/tag/Index.jsx | 58 +++++++++--------- src/forge/Main/tag/Index.scss | 30 ++++++++- src/forge/Main/tag/New.jsx | 74 +++++++++++++++++++++++ src/forge/Main/version/version.js | 2 +- 7 files changed, 167 insertions(+), 40 deletions(-) create mode 100644 src/forge/Main/tag/Empty.jsx create mode 100644 src/forge/Main/tag/New.jsx diff --git a/src/forge/Branch/Select.jsx b/src/forge/Branch/Select.jsx index 97f8bcf51..eb69af3ff 100644 --- a/src/forge/Branch/Select.jsx +++ b/src/forge/Branch/Select.jsx @@ -1,4 +1,4 @@ -import React , { useState , useEffect , useRef } from 'react'; +import React , { useState , useEffect , useRef, Fragment } from 'react'; import { Dropdown} from 'antd'; import './branch.scss'; import SelectOverlay from './SelectOverlay'; @@ -6,7 +6,7 @@ import { findDOMNode } from 'react-dom'; import { turnbar } from 'educoder'; import { truncateCommitId } from "../common/util"; -export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true , commitflag=false })=>{ +export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true , commitflag=false, children })=>{ const [ showValue , setShowValue ] = useState(branch); const [ visible , setVisible ] = useState(false); @@ -56,14 +56,16 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag ); return( - + trigger.parentNode}>
setVisible(visible ? false : true)}> {/* {nav === 0 ?"分支":"标签"} */} - - - {showValue} - - + {children || + + + {showValue} + + + }
) diff --git a/src/forge/Component/PublicModal/Index.jsx b/src/forge/Component/PublicModal/Index.jsx index 945c32ba8..df5463d61 100644 --- a/src/forge/Component/PublicModal/Index.jsx +++ b/src/forge/Component/PublicModal/Index.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { Modal } from 'antd'; import './Index.scss'; -function Modals({title,children,btn,onCancel,visible, width}) { +function Modals({title,children,btn,onCancel,visible, width, destroyOnClose=false}) { return( {children} diff --git a/src/forge/Main/tag/Empty.jsx b/src/forge/Main/tag/Empty.jsx new file mode 100644 index 000000000..f65258876 --- /dev/null +++ b/src/forge/Main/tag/Empty.jsx @@ -0,0 +1,22 @@ +import { Button } from 'antd'; +import React from 'react'; +import './Index.scss'; + +function Empty({operation,addFunc}) { + return( +
+ + 这里还没有任何标签 + 标签(Tags)是对代码库中特定提交的引用,通常用于标识发布版本(如 V1.0)或重要节点
您可以在提交记录或发行版功能中创建和管理标签
+
+ { + operation ? + + : + 该项目暂时还没有任何标签 + } +
+
+ ) +} +export default Empty; \ No newline at end of file diff --git a/src/forge/Main/tag/Index.jsx b/src/forge/Main/tag/Index.jsx index 838072583..2c8d4fa6c 100644 --- a/src/forge/Main/tag/Index.jsx +++ b/src/forge/Main/tag/Index.jsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; import SubMenu from '../sub/SubMenu'; -import { Table, Tooltip, Spin,Pagination, Button, message } from 'antd'; +import { Table, Tooltip, Spin,Pagination, Button, message, Form } from 'antd'; import axios from 'axios'; import { Link } from 'react-router-dom'; import { truncateCommitId } from '../../common/util'; @@ -11,6 +11,8 @@ import Tree from '../img/tree.png' import moment from 'moment'; import CopyTool from '../../Component/CopyTool'; import Modals from '../../Component/PublicModal/Index'; +import Empty from './Empty'; +import New from './New'; function Tags(props) { const [reload, setReload] = useState(undefined); @@ -21,9 +23,12 @@ function Tags(props) { const [limit,setLimit] =useState(10); // 删除标签 const [visible, setVisible] = useState(false); + // 新建标签 + const [visibleByAdd, setVisibleByAdd] = useState(false); const { projectsId, owner } = props.match.params; const { projectDetail, current_user} = props; const permission = projectDetail && projectDetail.permission; + const hasPermission = (current_user && current_user.login) && (permission && permission!=="Reporter"); useEffect(()=>{ if(projectDetail && document.title.indexOf('所有标签-') === -1){ @@ -173,8 +178,16 @@ function Tags(props) { return (
+
+ { + (current_user && current_user.login) && (permission && permission!=="Reporter") && (source && source.length > 0) && +
+ +
+ } +
-
+
{ source && source.length > 0 &&
} -
- {total > limit && {setPage(e)}} - showSizeChanger={true} - onShowSizeChange={(current, pageSize)=>{setPage(1);setLimit(pageSize);}} - showQuickJumper={true} - >} -
- {/* {total > limit ? ( -
- {total > limit && {setPage(e)}} - showSizeChanger={true} - onShowSizeChange={(current, pageSize)=>{setPage(1);setLimit(pageSize);}} - showQuickJumper={true} - >} -
- ) : ( - "" - )} */} + {source && source.length > 0 &&
+ {setPage(e)}} + showSizeChanger={true} + onShowSizeChange={(current, pageSize)=>{setPage(1);setLimit(pageSize);}} + showQuickJumper={true} + hideOnSinglePage={true} + > +
} { - source && source.length === 0 && + source && source.length === 0 && {setVisibleByAdd(true)}}/> }
@@ -230,6 +229,7 @@ function Tags(props) {

确定删除{visible.name}标签?

+ {setReload(Math.random())}} projectsId={projectsId} owner={owner} />
) } diff --git a/src/forge/Main/tag/Index.scss b/src/forge/Main/tag/Index.scss index d3931f869..0c275b7cb 100644 --- a/src/forge/Main/tag/Index.scss +++ b/src/forge/Main/tag/Index.scss @@ -1,5 +1,4 @@ .tagTable{ - margin-top: 9px; thead tr th{ display: none; } @@ -112,4 +111,33 @@ top: 65px; } } +} +.emptyPanel_tag{ + width: 100%; + background: #FAFCFF; + border-radius: 4px; + border: 1px solid rgba(42, 97, 255, 0.23); + min-height: 418px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + .operation{ + width: 400px; + border-top: 1px solid #eee; + padding-top: 34px; + text-align: center; + margin-top: 30px; + } +} +.tag_target_select .ant-select-arrow{ + display: none; +} +.tag_target{ + .branch-tagBox{ + border: none; + } + .overlayBranch{ + width: 456px; + } } \ No newline at end of file diff --git a/src/forge/Main/tag/New.jsx b/src/forge/Main/tag/New.jsx new file mode 100644 index 000000000..04f35106d --- /dev/null +++ b/src/forge/Main/tag/New.jsx @@ -0,0 +1,74 @@ +import { Button, Form, Input, message, Select } from 'antd'; +import React, { Fragment, useState } from 'react'; +import './Index.scss'; +import Modals from '../../Component/PublicModal/Index'; +import SelectOverlay from '../../Branch/SelectOverlay'; +import SelectByBranch from '../../Branch/Select'; +import axios from 'axios'; + +function NewTag({ form, visibleByAdd, setVisibleByAdd, owner, projectsId, onOK }) { + const { getFieldDecorator, validateFields, setFieldsValue, getFieldsValue } = form; + const { target} = getFieldsValue(); + + // 新建标签确认函数 + function addTag(){ + validateFields((error,values)=>{ + if(!error){ + axios.post(`/v1/${owner}/${projectsId}/tags`,values).then(result=>{ + if(result && result.data){ + message.success("新增成功"); + setVisibleByAdd(false); + onOK && onOK(); + } + }).catch(error=>{}) + } + }) + } + + return ( + { setVisibleByAdd(false) }} + visible={Boolean(visibleByAdd)} + width="556px" + btn={ +
+ + +
+ } + destroyOnClose={true} + > +
+ + {getFieldDecorator("tag_name",{ + rules:[{ required: true, message: '请输入标签名称' }] + })( + + )} + + + {getFieldDecorator("target", { + rules:[{ required: true, message: '请选择标签起点' }] + })( + { + setFieldsValue({ + target: branch + }) + }}> +