diff --git a/src/ai/create/index.jsx b/src/ai/create/index.jsx
index e7adddd2..b077d3ca 100644
--- a/src/ai/create/index.jsx
+++ b/src/ai/create/index.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, Fragment, useRef } from "react";
-import { Input, Select, Upload, message, Form, Checkbox, Tree, Spin } from "antd";
+import { Input, Select, Upload, message, Form, Checkbox, Tree, Spin, Alert } from "antd";
import './index.scss';
import { aiCreateSteps, aiResouceType, aiResouceTypeKey, convertToTreeData } from "../static";
import { Link } from "react-router-dom";
@@ -15,7 +15,7 @@ function CreateResource(props) {
const { getFieldDecorator, getFieldsValue, setFieldsValue, validateFields } = form;
const type = params.type || aiResouceType[0].key;
const sourceId = params.id; //资源id,编辑状态不允许筛选一级分类
- const { user_id } = current_user || {}
+ const { user_id, login } = current_user || {}
const { id: aiZoneId } = aiZoneInfo || {}
const [loading, setLoading] = useState(false);
@@ -28,6 +28,7 @@ function CreateResource(props) {
const [cate, setCate] = useState();
const [info, setInfo] = useState();
const [uploadedFile, setUploadedFile] = useState(null);
+ const [remark, setRemark] = useState('');
const uploadRef = useRef(null);
const typeDetail = type && aiResouceType.find(i => i.key === type);
@@ -38,6 +39,13 @@ function CreateResource(props) {
const skillTreeData = fileTreeJson && convertToTreeData(JSON.parse(fileTreeJson).children)
+ // 登录检查:如果未登录则跳转到登录页面
+ useEffect(() => {
+ if (!login) {
+ history.push(`/login?go_page=${encodeURIComponent(window.location.pathname)}`);
+ }
+ }, [login]);
+
// 自动滚动动画:每 5 秒切换到下一步
useEffect(() => {
document.title = `发布新资源`;
@@ -104,7 +112,11 @@ function CreateResource(props) {
if (sourceId) {
getAISourceById(sourceId).then(res => {
if (res && res.data && res.data.code === 200) {
- const { fileIds, extendData, name, summary, domainId, fileList } = res.data.data || {}
+ const { fileIds, extendData, name, summary, domainId, fileList, auditStatus, remark: remarkText } = res.data.data || {}
+ // 如果被驳回(auditStatus=2),保存驳回理由
+ if (auditStatus === '2') {
+ setRemark(remarkText || "请修改后重新提交");
+ }
const fileInfo = {
fileId: fileList[0]?.fileId,
fileOriginName: fileList[0]?.fileOriginName,
@@ -121,8 +133,8 @@ function CreateResource(props) {
file: {
response: {
fileId: fileIds,
- skillMdContent: extendData.skill.content,
- fileTreeJson: JSON.stringify(extendData.skill.fileTree)
+ skillMdContent: extendData.SKILL.content,
+ fileTreeJson: JSON.stringify(extendData.SKILL.fileTree)
}
}
} : fileValue.fileId = fileIds
@@ -145,7 +157,7 @@ function CreateResource(props) {
const compelete = (response) => {
if (response && response.data && response.data.code === 200) {
message.success("操作成功");
- history.push(`/ai/${type}`);
+ history.push(`/ai/${type}/my`);
}
}
validateFields((err, values) => {
@@ -249,6 +261,7 @@ function CreateResource(props) {
if (!!sourceId) {
e.preventDefault();
e.stopPropagation();
+ return;
}
form.resetFields();
if (uploadRef.current) {
@@ -290,6 +303,17 @@ function CreateResource(props) {
基本信息
{typeDetail.createIntro}
+ {remark && (
+
+ )}
{getFieldDecorator('name', {
rules: [{
@@ -385,13 +410,13 @@ function CreateResource(props) {
{codeCheckBox("ignoreFlag", ".gitignore", ignoreFlag, "ignore", gitignoreList)}
{codeCheckBox("licenseFlag", "开源许可证", licenseFlag, "license", licensesList)}
-
{getFieldDecorator('private')(
将项目设为私有(只有项目所有人或拥有权限的项目成员才能看到)
)}
-
+ */}
{codeCheckBox("categoreFlag", "项目类别", categoreFlag, "project_category", categoryList)}
{codeCheckBox("languageFlag", "项目语言", languageFlag, "project_language", languageList)}
:
@@ -399,7 +424,7 @@ function CreateResource(props) {
{getFieldDecorator('file', {
rules: [{ required: true, message: "请上传文件" }],
})(
- fileByupload ?
+ responseByupload ?
{
form.setFieldsValue({
file: undefined
@@ -408,7 +433,6 @@ function CreateResource(props) {
:
{getFieldDecorator('summary', {
rules: [{
- required: true, message: '请填写简介内容'
+ required: false, message: '请填写简介内容'
}],
})(
@@ -489,9 +513,11 @@ function CreateResource(props) {
})(
{
@@ -520,9 +546,9 @@ function CreateResource(props) {
}
{/* 提交按钮 */}
-
- 提 交
- 取 消
+
+ 取 消
+ 提 交
diff --git a/src/ai/create/index.scss b/src/ai/create/index.scss
index c825c883..79dc91d3 100644
--- a/src/ai/create/index.scss
+++ b/src/ai/create/index.scss
@@ -50,34 +50,6 @@
}
}
- // 工具类
- .mb30 {
- margin-bottom: 30px;
- }
-
- .mb40 {
- margin-bottom: 40px;
- }
-
- .mb5 {
- margin-bottom: 5px;
- }
-
- .mb8 {
- margin-bottom: 8px;
- }
-
- .ml10 {
- margin-left: 10px;
- }
-
- .mr20 {
- margin-right: 20px;
- }
-
- .mt40 {
- margin-top: 40px;
- }
// 主体内容
.ai_create_content {
@@ -151,6 +123,13 @@
.ant-upload.ant-upload-select {
width: 100%;
}
+
+ // 审核驳回提示样式
+ .audit-rejected-wrapper {
+ .ant-alert-error {
+ border-radius: 8px;
+ }
+ }
}
.ai_create_upload {
diff --git a/src/ai/detail/index.jsx b/src/ai/detail/index.jsx
index 1a4f64c1..1080504d 100644
--- a/src/ai/detail/index.jsx
+++ b/src/ai/detail/index.jsx
@@ -1,12 +1,12 @@
-import React, { useState, useEffect } from "react";
-import { Tabs, Tag, Spin, message, Divider, Tree, Tooltip } from "antd";
-import axios from "axios";
+import React, { useState, useEffect, Fragment } from "react";
+import { Tabs, Tag, Spin, message, Divider, Tree, Tooltip, Button, Badge } from "antd";
import RenderHtml from "../../components/render-html";
import "./index.scss";
-import { getlikedSource, getAISourceById, likeAISource } from "../../forge/Information/api";
-import { aiResouceTypeKey, convertToTreeData } from "../static";
+import { getlikedSource, getAISourceById, likeAISource, editModel, editDataset } from "../../forge/Information/api";
+import { aiResouceStatus, aiResouceType, aiResouceTypeKey, convertToTreeData } from "../static";
import skillIcon from '../image/icon7.png';
import CommentsList from "../../components/commentsByZone";
+import TpmMdEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
const { TabPane } = Tabs;
@@ -18,18 +18,26 @@ function Detail(props) {
// 状态管理
const [reload, setReload] = useState(undefined);
const [detail, setDetail] = useState({});
- const [files, setFiles] = useState(undefined);
- const [comments, setComments] = useState(undefined);
const [loading, setLoading] = useState(true);
const [activeTab, setActiveTab] = useState("introduction");
- const [branch, setBranch] = useState("master");
const [liked, setLiked] = useState(false);
+ const [isEditor, setIsEditor] = useState(false);
+ const [editContent, setEditContent] = useState("");
+ const [saving, setSaving] = useState(false);
+
+ const { extendData={}, createBy, auditStatus } = detail;
+ const status = aiResouceStatus[auditStatus] || {};
+
+ const typeDetail = type && aiResouceType.find(i => i.key === type);
+ const name = typeDetail && typeDetail.name
- const { extendData={} } = detail;
const dataByType = extendData[aiResouceTypeKey[type]] || {}
const content = dataByType.content || dataByType.readmeContent
- const introContent = String(content || '暂无 README 内容
').replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, '');
+ const introContent = String(content || `当前${name}未提供详细介绍
`).replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, '');
const treeData = dataByType && dataByType.fileTree && convertToTreeData(dataByType.fileTree.children)
+
+ // 判断当前用户是否为发布者
+ const isPublisher = login && createBy && login === createBy;
// 组件挂载和 ID 变化时加载数据
useEffect(() => {
@@ -60,6 +68,41 @@ function Detail(props) {
})
}
+ // 切换编辑模式
+ const handleToggleEdit = () => {
+ if (isEditor) {
+ // 取消编辑,恢复原内容
+ setEditContent(content || "");
+ setIsEditor(false);
+ } else {
+ // 进入编辑模式
+ setEditContent(content || "");
+ setIsEditor(true);
+ }
+ }
+
+ // 保存编辑内容
+ const handleSave = () => {
+ setSaving(true);
+ const editFun = type === "models" ? editModel : editDataset
+ editFun({
+ id: +id,
+ readmeContent: editContent
+ }).then(response => {
+ if (response && response.data && response.data.code === 200) {
+ message.success("保存成功");
+ setIsEditor(false);
+ setReload(Date.now());
+ } else {
+ message.error(response?.data?.msg || "保存失败");
+ }
+ }).catch(() => {
+ message.error("保存失败,请重试");
+ }).finally(() => {
+ setSaving(false);
+ });
+ }
+
// 格式化下载量
const formatDownloads = (num) => {
if (num >= 10000) {
@@ -124,6 +167,7 @@ function Detail(props) {
if (!login) {
showLoginDialog();
e.stopPropagation();
+ e.preventDefault();
}
}}>下载}
history.goBack()}>返回
@@ -132,6 +176,10 @@ function Detail(props) {
+ {auditStatus !== "1" &&
+
+
+ }
{detail.createUser && detail.createUser.userName || "未知作者"}
@@ -172,11 +220,11 @@ function Detail(props) {
centered
>
{activeTab === "introduction" && (
-
-
-
+ {/* 编辑按钮区域 - 仅发布者可见 */}
+ {isPublisher && ["models", "datasets"].includes(type) && !isEditor &&
+ {auditStatus === "1" ? (
+
trigger.parentNode} title={当前资源是上架状态,请前往
我的资源池页面先进行下架}>
+ 编辑
+
+ ) : (
+
编辑
+ )}
+
}
+ {isEditor ? (
+
+
+ setEditContent(value)}
+ height={600}
+ mdID={`ai_detail_readme_editor_${id}`}
+ />
+
+
+
+
+
+
+ ) : (
+
+
+
+ )}
)}
diff --git a/src/ai/detail/index.scss b/src/ai/detail/index.scss
index fc8d3125..be286aa7 100644
--- a/src/ai/detail/index.scss
+++ b/src/ai/detail/index.scss
@@ -356,5 +356,30 @@
font-size: 15px;
color:#27264d;
}
+ li:not(.ant-tree-treenode-switcher-close):not(.ant-tree-treenode-switcher-open) .ant-tree-node-content-wrapper{
+ cursor: default;
+ }
+ }
+
+ // 编辑工具栏
+ .ai_detail_edit_toolbar {
+ padding: 0 4px;
+ text-align: right;
+ }
+
+ // Markdown 编辑器容器
+ .ai_detail_readme_editor {
+ // min-height: 500px;
+
+ // 覆盖 TpmMdEditor 的默认样式,使其与页面风格一致
+ .markdown-editor {
+ border-radius: 8px;
+
+ .editor-textarea {
+ font-family: "Courier New", monospace;
+ font-size: 15px;
+ line-height: 1.8;
+ }
+ }
}
}
diff --git a/src/ai/index.jsx b/src/ai/index.jsx
index 051e7173..0f9f40ee 100644
--- a/src/ai/index.jsx
+++ b/src/ai/index.jsx
@@ -31,20 +31,29 @@ function AI(props) {
const [aiZoneInfo, setAiZoneInfo] = useState(undefined);
const [roleByZone, setRoleByZone] = useState("Member");
+ const {id} = aiZoneInfo || {}
useEffect(() => {
getMainInfos("AI").then(res => {
if (res && res.data && res.data.data) {
setAiZoneInfo(res.data.data)
- // login && getCurrentRole(res.data.data.id).then(res1 => {
- // if (res1 && res1.data && res1.data.data) { }
- // setRoleByZone(res1.data.data.role)
- // })
+ // 存储deptId,所有专区接口header带上
+ sessionStorage.setItem('deptId', res.data.data.deptId)
}
})
-
}, [])
+ useEffect(()=>{
+ if(id && login){
+ getCurrentRole(id);
+ // login && getCurrentRole(res.data.data.id).then(res1 => {
+ // if (res1 && res1.data && res1.data.data) {
+ // setRoleByZone(res1.data.data.role)
+ // }
+ // })
+ }
+ }, [id, login])
+
return
}
{model.name}{model.isNew && }
-
{model.desc}
+ {model.desc &&
{model.desc}
}
查看
diff --git a/src/ai/my-resources/index.jsx b/src/ai/my-resources/index.jsx
index fe1bd440..eb9a4bde 100644
--- a/src/ai/my-resources/index.jsx
+++ b/src/ai/my-resources/index.jsx
@@ -9,9 +9,10 @@ import moment from "moment";
function MyResources(props) {
const pageSize = 10;
- const { match: { params }, history, aiZoneInfo, roleByZone } = props || {};
+ const { match: { params }, history, aiZoneInfo, roleByZone, current_user } = props || {};
const type = params.type;
const { id: aiZoneId } = aiZoneInfo || {}
+ const { login } = current_user || {}
const [current, setCurrent] = useState(1);
const [total, setTotal] = useState(0);
const [reload, setReload] = useState(undefined);
@@ -24,6 +25,13 @@ function MyResources(props) {
document.title = `我的资源池`
}, [])
+ // 登录检查:如果未登录则跳转到登录页面
+ useEffect(() => {
+ if (!login) {
+ history.push(`/login?go_page=${encodeURIComponent(window.location.pathname)}`);
+ }
+ }, [login]);
+
useEffect(() => {
if (aiZoneId && type) {
if(type === "codes") {
@@ -56,7 +64,7 @@ function MyResources(props) {
}
})
}
- }, [aiZoneId, type])
+ }, [aiZoneId, type, reload])
useEffect(() => {
if(type === "codes" && aiZoneId) {
@@ -176,6 +184,12 @@ function MyResources(props) {
{category.name}
))}
+
+
+
{/* 统计数据 */}
diff --git a/src/ai/my-resources/index.scss b/src/ai/my-resources/index.scss
index 54fcad6e..393b061f 100644
--- a/src/ai/my-resources/index.scss
+++ b/src/ai/my-resources/index.scss
@@ -30,6 +30,7 @@
// 分类标签
.category-tabs {
display: flex;
+ align-items: center;
margin-bottom: 30px;
border: 1px solid #091221;
border-radius: 24px;
@@ -53,6 +54,16 @@
color: #fff;
}
}
+ .category-tab-add{
+ width:34px;
+ height:34px;
+ line-height: 34px;
+ text-align: center;
+ background:#091221;
+ border-radius:17px;
+ color: white;
+ margin-right: 9px;
+ }
}
// 统计数据
diff --git a/src/ai/static.js b/src/ai/static.js
index ef04e9cf..42c9cbee 100644
--- a/src/ai/static.js
+++ b/src/ai/static.js
@@ -61,7 +61,7 @@ export const convertToTreeData = (data) => {
let title = node.name;
if (isLeaf && node.size) {
const sizeStr = formatFileSize(node.size);
- title =
{node.name}{sizeStr};
+ title =
{node.name}{sizeStr};
}
return {
key: node.name,
diff --git a/src/components/ChunkedUpload/index.jsx b/src/components/ChunkedUpload/index.jsx
index 37c5a09e..eb430354 100644
--- a/src/components/ChunkedUpload/index.jsx
+++ b/src/components/ChunkedUpload/index.jsx
@@ -38,7 +38,7 @@ const ChunkedUpload = forwardRef(({
hierarchy = '',
chunkSize = 10 * 1024 * 1024, // 默认 10MB
disabled = false,
- accept = '*',
+ accept = '', // 空字符串表示接受所有文件类型,这是 HTML5 标准写法
maxSize = 1024 * 1024 * 1024, // 默认 1GB
children, // 支持自定义未选择文件状态的内容
defaultFile, // 默认文件信息(已上传的文件),用于回显
diff --git a/src/components/commentsByZone/EditComment.jsx b/src/components/commentsByZone/EditComment.jsx
index dff9a778..384b519e 100644
--- a/src/components/commentsByZone/EditComment.jsx
+++ b/src/components/commentsByZone/EditComment.jsx
@@ -145,6 +145,7 @@ function EditComment(props) {
action={getZoneUrl(`/api/file/common/upload`)}
beforeUpload={beforeUpload}
onChange={changeFileList}
+ withCredentials={true}
headers={{
Authorization: cookie.load('autologin_trustie'),
}}
diff --git a/src/forge/Information/api.js b/src/forge/Information/api.js
index 86c03339..8c3fd2c3 100644
--- a/src/forge/Information/api.js
+++ b/src/forge/Information/api.js
@@ -510,10 +510,9 @@ export function takeUpSourceById(id, role="Member"){
method:"PUT"
})
}
-//
export function drawSourceById(id){
return fetch({
- url: `/zoneFront/resource/${id}/withdraw`,
+ url: `/zone/zoneFront/resource/${id}/withdraw`,
method:"PUT"
})
}