ai资源-模型库数据库联调

This commit is contained in:
谢思 2026-05-25 10:28:09 +08:00
parent 876b4f8076
commit eccc49cf30
9 changed files with 269 additions and 184 deletions

View File

@ -1,15 +1,20 @@
import { message, Modal } from "antd"
import { deleteProjectInZoneById, deleteSourceById, takeDownSourceById } from "../forge/Information/api";
import { useState } from "react";
export const DeleteModal = ({type, id, cancel, roleByZone, reload}) =>{
return <Modal className="purpleGradient" title="删除模型" visible={!!id} onCancel={cancel} onOk={()=>{
const [loading, setLoading] = useState(false)
return <Modal className="purpleGradient" title="删除模型" visible={!!id} onCancel={cancel} okButtonProps={{loading: loading}} onOk={()=>{
const deleteFn = type === "codes" ? deleteProjectInZoneById : deleteSourceById;
setLoading(true);
deleteFn(id, roleByZone).then(res=>{
if(res && res.data && res.data.code === 200){
message.success(`操作成功`);
cancel();
reload(Math.random());
}
}).finally(()=>{
setLoading(false);
})
}}>
<div className="center pt20">
@ -21,13 +26,17 @@ export const DeleteModal = ({type, id, cancel, roleByZone, reload}) =>{
}
export const TakeDownModal = ({id, cancel, roleByZone, reload}) =>{
return <Modal key="down" className="purpleGradient" title="下架资源" visible={!!id} onCancel={cancel} onOk={()=>{
const [loading, setLoading] = useState(false)
return <Modal key="down" className="purpleGradient" title="下架资源" visible={!!id} onCancel={cancel} okButtonProps={{loading: loading}} onOk={()=>{
setLoading(true);
takeDownSourceById(id, roleByZone).then(res=>{
if(res && res.data && res.data.code === 200){
message.success(`操作成功`);
cancel();
reload(Math.random());
}
}).finally(()=>{
setLoading(false);
})
}}>
<div className="center pt20">

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, Fragment } from "react";
import React, { useState, useEffect, Fragment, useRef } from "react";
import { Input, Select, Upload, message, Form, Checkbox, Tree, Spin } from "antd";
import './index.scss';
import { aiCreateSteps, aiResouceType, aiResouceTypeKey, convertToTreeData } from "../static";
@ -6,7 +6,8 @@ import { Link } from "react-router-dom";
import { AlignCenter } from "../../forge/Component/layout";
import DorpChooseMenus from "../../forge/Component/licenseModal/dorpChooseMenus";
import axios from "axios";
import { addProjectInZone, addSkill, editSkill, getProjectsTypeLists, getSkillById, getSourceZoneList, parseFileBySkill } from "../../forge/Information/api";
import { addDataset, addModel, addProjectInZone, addSkill, editDataset, editModel, editSkill, getProjectsTypeLists, getAISourceById, getSourceZoneList, parseFileBySkill } from "../../forge/Information/api";
import ChunkedUpload from "../../components/ChunkedUpload";
const { Option } = Select;
function CreateResource(props) {
@ -18,7 +19,6 @@ function CreateResource(props) {
const { id: aiZoneId } = aiZoneInfo || {}
const [loading, setLoading] = useState(false);
const [resourceType, setResourceType] = useState("models");
const [currentStep, setCurrentStep] = useState(0);
const [categoryList, setCategoryList] = useState();
const [languageList, setLanguageList] = useState();
@ -27,6 +27,8 @@ function CreateResource(props) {
const [ownerList, setOwnerList] = useState();
const [cate, setCate] = useState();
const [info, setInfo] = useState();
const [uploadedFile, setUploadedFile] = useState(null);
const uploadRef = useRef(null);
const typeDetail = type && aiResouceType.find(i => i.key === type);
const { ignoreFlag, licenseFlag, categoreFlag, languageFlag, file } = getFieldsValue();
@ -100,23 +102,31 @@ function CreateResource(props) {
useEffect(() => {
if (sourceId) {
getSkillById(sourceId).then(res => {
getAISourceById(sourceId).then(res => {
if (res && res.data && res.data.code === 200) {
const { fileIds, extendData, name, summary, domainId } = res.data.data || {}
setFieldsValue({
file: {
file: {
response: {
fileId: fileIds,
skillMdContent: extendData.skill.content,
fileTreeJson: JSON.stringify(extendData.skill.fileTree)
}
}
},
const { fileIds, extendData, name, summary, domainId, fileList } = res.data.data || {}
const fileInfo = {
fileId: fileList[0]?.fileId,
fileOriginName: fileList[0]?.fileOriginName,
fileSize: fileList[0]?.fileSizeInfo,
url: fileList[0]?.downloadUrl
}
setUploadedFile(fileInfo)
const fileValue = {
name,
summary,
domainId
})
}
type === "skills" ? fileValue.file = {
file: {
response: {
fileId: fileIds,
skillMdContent: extendData.skill.content,
fileTreeJson: JSON.stringify(extendData.skill.fileTree)
}
}
} : fileValue.fileId = fileIds
setFieldsValue(fileValue)
}
})
}
@ -135,7 +145,6 @@ function CreateResource(props) {
const compelete = (response) => {
if (response && response.data && response.data.code === 200) {
message.success("操作成功");
// ${type === "codes" ? '' : "/" + sourceId || response.data.data.id}
history.push(`/ai/${type}`);
}
}
@ -171,6 +180,18 @@ function CreateResource(props) {
submitFn(param, roleByZone).then(response => { compelete(response) })
break;
default:
// models/datasets 使 fileId
const { fileId: formFileId } = getFieldsValue() || {};
const submitParam = {
...values,
fileId: formFileId,
zoneId: aiZoneId
}
if (sourceId) {
submitParam.id = sourceId;
}
const submitFn1 = type === "models" ? sourceId ? editModel : addModel : sourceId ? editDataset : addDataset;
submitFn1(submitParam).then(response => { compelete(response) })
break;
}
}
@ -229,6 +250,10 @@ function CreateResource(props) {
e.preventDefault();
e.stopPropagation();
}
form.resetFields();
if (uploadRef.current) {
uploadRef.current.cancelUpload();
}
}}
>
<i className={`${type === item.key ? 'iconfont icon-' : 'iconfont-color icon-color'}${item.icon} font-20`}></i>
@ -277,7 +302,6 @@ function CreateResource(props) {
<Form.Item
label="拥有者"
style={{ width: "260px" }}
className="explainPos"
>
{getFieldDecorator('user_id', {
rules: [{
@ -307,7 +331,6 @@ function CreateResource(props) {
<span className="ml10 mr10 mt10 font-18">/</span>
<Form.Item
label="项目名称"
className="flex1 explainPos"
>
{getFieldDecorator('name', {
rules: [{
@ -372,7 +395,7 @@ function CreateResource(props) {
{codeCheckBox("categoreFlag", "项目类别", categoreFlag, "project_category", categoryList)}
{codeCheckBox("languageFlag", "项目语言", languageFlag, "project_language", languageList)}
</Fragment> : <Fragment>
<Form.Item label={`${typeDetail.name}文件`}>
{type === "skills" && <Form.Item label={`${typeDetail.name}文件`}>
{getFieldDecorator('file', {
rules: [{ required: true, message: "请上传文件" }],
})(
@ -420,14 +443,14 @@ function CreateResource(props) {
</div>
</Upload>
)}
</Form.Item>
</Form.Item>}
<Form.Item label="名称">
{getFieldDecorator('name', {
rules: [{
required: true, message: '请填写资源名称'
required: true, message: '请填写名称'
}],
})(
<Input placeholder="请输入资源名称" maxLength={50} />
<Input placeholder="请输入名称" maxLength={50} />
)}
</Form.Item>
<Form.Item label="简介">
@ -443,10 +466,10 @@ function CreateResource(props) {
<Form.Item label="类别">
{getFieldDecorator('domainId', {
rules: [{
required: true, message: '请选择模型类别'
required: true, message: '请选择类别'
}],
})(
<Select placeholder="请选择模型类别" className="font-15">
<Select placeholder="请选择类别" className="font-15">
{cate && cate.length > 0 &&
cate.map((i, k) => {
return (
@ -456,8 +479,44 @@ function CreateResource(props) {
}
</Select>
)}
</Form.Item>
{/* models/datasets 类型使用分片上传 */}
{type !== "skills" && <Form.Item label={`${typeDetail.name}文件`} required>
{getFieldDecorator('fileId', {
rules: [{
required: true, message: `请上传${typeDetail.name}文件`
}],
})(
<div>
<ChunkedUpload
defaultFile={uploadedFile}
ref={uploadRef}
fileType={aiResouceTypeKey[type] || 'resource'}
disabled={loading}
maxSize={50 * 1024 * 1024 * 1024} // 50GB
onUploadComplete={(fileInfo) => {
// fileId
setFieldsValue({
fileId: fileInfo.fileId
});
}}
onCancel={() => {
setUploadedFile(null);
setFieldsValue({
fileId: undefined
});
}}
>
<span className="ai_create_upload_icon">
<i className="iconfont icon-shangchuanicon color091"></i>
</span>
<div className="color091 mt15 mb15">请上传{typeDetail.name}压缩包支持 .zip 格式</div>
<div className="coloraeb mb10">请确保压缩包内包含{typeDetail.name}文件及 README.md系统将自动解析说明文档</div>
<div className="coloraeb">单文件最大支持 50GB系统支持断点续传</div>
</ChunkedUpload>
</div>
)}
</Form.Item>}
</Fragment>}
{/* 提交按钮 */}

View File

@ -157,15 +157,14 @@
padding: 30px 0;
border: 1px dashed rgba(22, 76, 228, 0.17);
border-radius: 6px;
.ai_create_upload_icon {
display: inline-block;
width: 45px;
height: 45px;
background: #f3f4f8;
border-radius: 50%;
line-height: 45px;
}
}
.ai_create_upload_icon {
display: inline-block;
width: 45px;
height: 45px;
background: #f3f4f8;
border-radius: 50%;
line-height: 45px;
}
.ai_tree_file{
border: 1px solid #D9D9D9;

View File

@ -3,8 +3,8 @@ import { Tabs, Tag, Spin, message, Divider, Tree, Tooltip } from "antd";
import axios from "axios";
import RenderHtml from "../../components/render-html";
import "./index.scss";
import { getlikedSource, getSkillById, likeAISource } from "../../forge/Information/api";
import { convertToTreeData } from "../static";
import { getlikedSource, getAISourceById, likeAISource } from "../../forge/Information/api";
import { aiResouceTypeKey, convertToTreeData } from "../static";
import skillIcon from '../image/icon7.png';
import CommentsList from "../../components/commentsByZone";
@ -13,7 +13,7 @@ const { TabPane } = Tabs;
function Detail(props) {
//
const { history, match: { params }, current_user: { login }, current_user, showLoginDialog, showNotification } = props;
const { id } = params || {};
const { id, type } = params || {};
//
const [reload, setReload] = useState(undefined);
@ -25,10 +25,11 @@ function Detail(props) {
const [branch, setBranch] = useState("master");
const [liked, setLiked] = useState(false);
const { extendData: { skill: { content, fileTree } = {} } = {} } = detail;
const skillTreeData = fileTree && convertToTreeData(fileTree.children)
const skillContent = String(content).replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, '');
const { extendData={} } = detail;
const dataByType = extendData[aiResouceTypeKey[type]] || {}
const content = dataByType.content || dataByType.readmeContent
const introContent = String(content || '<div className="ai_detail_nodata_text">暂无 README 内容</div>').replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, '');
const treeData = dataByType && dataByType.fileTree && convertToTreeData(dataByType.fileTree.children)
// ID
useEffect(() => {
@ -40,7 +41,7 @@ function Detail(props) {
const getDetail = () => {
id && getSkillById(id).then(response => {
id && getAISourceById(id).then(response => {
if (response && response.data && response.data.code === 200) {
const { name } = response.data.data
document.title = `${name}-AI资源`;
@ -59,21 +60,6 @@ function Detail(props) {
})
}
//
const handleBranchChange = (value) => {
setBranch(value);
//
axios.get(`/api/ai/models/${id}/files.json`, { params: { branch: value } })
.then(res => {
if (res && res.data) {
setFiles(res.data);
}
})
.catch(error => {
console.error(error);
});
};
//
const formatDownloads = (num) => {
if (num >= 10000) {
@ -82,17 +68,6 @@ function Detail(props) {
return num;
};
//
const formatFileSize = (size) => {
if (!size) return "0KB";
const num = parseFloat(size);
if (isNaN(num)) return size;
if (num >= 1024) {
return (num / 1024).toFixed(2) + "MB";
}
return Math.round(num) + "KB";
};
if (loading) {
return (
<div className="ai_detail_loading">
@ -116,7 +91,7 @@ function Detail(props) {
<div className="ai_detail_header_inner">
<div className="df-start">
<img src={skillIcon} width={40} className="mr15" />
<div className="mt-10">
<div className="mt-10 flex1">
<div className="df-start">
<div className="ai_detail_header_info mrat">
<div className="font-20 font-bd">{detail.name}</div>
@ -137,16 +112,21 @@ function Detail(props) {
{detail.domainName}
</Tag>
)}
{dataByType && dataByType.fileSize && (
<Tag className="ai_detail_header_tag">
{dataByType.fileSize}
</Tag>
)}
</div>
</div>
<div className="shrink0 mt20 ml20">
<a className="btn-outline font-15 mr20" onClick={() => history.goBack()}>返回</a>
{detail.fileList && detail.fileList[0] && <a className="btn-black font-15" href={detail.fileList[0].downloadUrl} download onClick={(e) => {
{detail.fileList && detail.fileList[0] && <a className="btn-black font-15 mr20" href={detail.fileList[0].downloadUrl} download onClick={(e) => {
if (!login) {
showLoginDialog();
e.stopPropagation();
}
}}>下载</a>}
<a className="btn-outline font-15" onClick={() => history.goBack()}>返回</a>
</div>
</div>
<div>
@ -210,11 +190,7 @@ function Detail(props) {
{activeTab === "introduction" && (
<div className="ai_detail_tab_panel">
<div className="ai_detail_readme">
{skillContent ? (
<RenderHtml value={skillContent} />
) : (
<div className="ai_detail_nodata_text">暂无 README 内容</div>
)}
<RenderHtml value={introContent} />
</div>
</div>
)}
@ -222,78 +198,12 @@ function Detail(props) {
{activeTab === "files" && (
<div className="ai_detail_tab_panel">
<Tree.DirectoryTree
treeData={skillTreeData}
defaultExpandAll={true}
className="ai_detail_tree_node"
defaultExpandAll={false}
treeData={treeData}
selectable={false}
blockNode={true}
/>
{/* <div className="ai_detail_files_header">
<Select
value={branch}
onChange={handleBranchChange}
className="ai_detail_branch_select"
dropdownMatchSelectWidth={false}
style={{ width: 150 }}
>
<Option value="master">master</Option>
{detail.branches && detail.branches.map((b) => (
<Option key={b} value={b}>{b}</Option>
))}
</Select>
{files?.lastCommit && (
<div className="ai_detail_commit_info">
<span className="ai_detail_commit_message">
{files.lastCommit.message || "暂无提交信息"}
</span>
<span className="ai_detail_commit_author ml10">
{files.lastCommit.author || "unknown"}
</span>
<span className="ai_detail_commit_sha ml10 font-12 color768">
{files.lastCommit.sha?.substring(0, 7) || "unknown"}
</span>
<span className="ai_detail_commit_time ml10 font-12 color768">
{files.lastCommit.time || "刚刚"}
</span>
</div>
)}
<div className="ai_detail_commit_count font-12 color768">
{files?.commitCount || 0} 次提交
</div>
</div>
<div className="ai_detail_files_list">
{files?.files && files.files.length > 0 ? (
files.files.map((file, index) => (
<div key={index} className="ai_detail_file_item">
<div className="ai_detail_file_info">
<i className={`iconfont ${file.type === "dir" ? "icon-wenjianjia4" : "icon-wenjian6"} font-16 mr10 color-blue`}></i>
<span className="ai_detail_file_name font-14">{file.name}</span>
<span className="ai_detail_file_size font-12 color768 ml10">
{formatFileSize(file.size)}
</span>
</div>
<div className="ai_detail_file_meta">
<span className="ai_detail_file_message font-12 color768">
{file.lastMessage || "暂无信息"}
</span>
<span className="ai_detail_file_time font-12 color768 ml10">
{timeAgo(file.updateTime || new Date())}
</span>
</div>
<Button
type="text"
className="ai_detail_file_download"
icon={<i className="iconfont icon-xiazai font-14"></i>}
>
下载
</Button>
</div>
))
) : (
<div className="ai_detail_nodata_text">暂无文件</div>
)}
</div> */}
</div>
)}

View File

@ -4,6 +4,7 @@
background-size: 100% auto;
padding-top: 45px;
padding-bottom: 50px;
min-height: 89vh;
}
// 加载状态
@ -345,4 +346,15 @@
--light-color-2: rgba(70,106,255,0.23);
--light-color-3: rgba(70,106,255,0.55);
}
// 文件树节点样式
.ai_detail_tree_node {
.ant-tree-title{
width: calc(100% - 42px);
display: inline-flex;
justify-content: space-between;
font-size: 15px;
color:#27264d;
}
}
}

View File

@ -9,15 +9,16 @@ import icon6 from '../image/icon6.png';
import { Divider, Input, Pagination } from "antd";
import ActionItem from "../../factory/resource/components/ActionItem";
import { Link } from "react-router-dom";
import { getProjectsLists, getProjectsTypeLists, getSkillList, getSourceZoneList } from "../../forge/Information/api";
import { getAISourceList, getProjectsLists, getProjectsTypeLists, getSourceZoneList } from "../../forge/Information/api";
import moment from "moment";
import Nodata from "../../forge/Nodata";
function List(props) {
const { match: { params }, history, aiZoneInfo, current_user } = props || {};
const type = params.type || aiResouceType[0].key
const [activeCategory, setActiveCategory] = useState();
const [page, setPage] = useState(1);
const [total, setTotal] = useState(20);
const [total, setTotal] = useState(0);
const [cate, setCate] = useState([]);
const [list, setList] = useState();
const [search, setSearch] = useState();
@ -51,9 +52,10 @@ function List(props) {
}, [type, aiZoneId])
useEffect(() => {
if(!aiZoneId) return
switch (type) {
case "codes":
aiZoneId && getProjectsLists(aiZoneId, {
getProjectsLists(aiZoneId, {
pageNum: page,
pageSize: 10,
projectTypeId: activeCategory,
@ -72,20 +74,20 @@ function List(props) {
date: projectProperties.timeAgo,
forkedCount: projectProperties.forkedCount,
likes: projectProperties.praisesCount,
topics: projectProperties.topics ? projectProperties.topics.split(",") : []
language: projectProperties.language ? projectProperties.language.split(",") : []
}
}))
setTotal(res.data.total)
}
})
break;
case "skills":
getSkillList({
auditStatus: 1,
default:
getAISourceList(aiZoneId, {
domainId: activeCategory,
pageNum: page,
pageSize: 10,
name: search
name: search,
resourceCategory: aiResouceTypeKey[type]
}).then(res => {
if (res && res.data && res.data.rows) {
setList(res.data.rows.map(row => {
@ -104,10 +106,9 @@ function List(props) {
setTotal(res.data.total)
}
})
default:
break;
}
}, [activeCategory, aiZoneId, page, search, type])
}, [type, aiZoneId, activeCategory, page, search])
const aiCard = (model) => {
return <Fragment>
@ -202,8 +203,8 @@ function List(props) {
</div>
{/* 模型列表 */}
<div className={`ai_home_list ${type}_pattern`}>
{list && list.map((model) => (
{list && !!list.length ? <div className={`ai_home_list ${type}_pattern`}>
{list.map((model) => (
<ActionItem key={model.id} className="ai_home_card" padding="1px" borderRadius="12px">
<div>
<div className="df-center">
@ -224,23 +225,22 @@ function List(props) {
<div className="df-center color828">
{aiCard(model)}
{type === "codes" ? <div className="df-center mlat">
{model.topics && !!model.topics.length && <Fragment>
{model.language && !!model.language.length && <Fragment>
<img src={icon5} className="mr8 mt1" width={18} />
{model.topics.map((topic, index) => {
{model.language.map((topic, index) => {
return <Fragment>
{topic}
{index < model.topics.length - 1 && <Divider type="vertical" style={{ height: '7px' }} className="mt5" />}
<span className="color091">{topic}</span>
{index < model.language.length - 1 && <Divider type="vertical" style={{ height: '7px' }} className="mt5" />}
</Fragment>
})}
</Fragment>}
</div> : <span className="ai_home_card_tag mlat">大语言模型</span>}
</div> : <span className="ai_home_card_tag mlat">{model.domainName}</span>}
</div>
</Fragment>}
</div>
</ActionItem>
))}
</div>
</div> : <div className="pt80"><Nodata _html="暂无数据"/></div>}
{/* 分页 */}
<Pagination className="edu-txt-right ai_list_Pagination mb70 black_active_Pagination" current={page} onChange={(p) => { setPage(p) }} pageSize={10} total={total} showQuickJumper hideOnSinglePage />

View File

@ -3,7 +3,7 @@ import { Link } from "react-router-dom";
import { Table, Pagination, Badge, message } from "antd";
import './index.scss';
import { aiResouceStatus, aiResouceType, aiResouceTypeKey } from "../static";
import { drawSourceById, getMyCodeList, getMyResourceList, takeUpSourceById } from "../../forge/Information/api";
import { drawSourceById, getAIProjectStatistics, getAIResourceStatistics, getMyCodeList, getMyResourceList, takeUpSourceById } from "../../forge/Information/api";
import { DeleteModal, TakeDownModal } from "../component";
import moment from "moment";
@ -18,11 +18,43 @@ function MyResources(props) {
const [list, setList] = useState([]);
const [deleteId, setDeleteId] = useState();
const [downId, setDownId] = useState();
const [stats, setStats] = useState([]);
useEffect(() => {
document.title = `我的资源池`
}, [])
useEffect(() => {
if (aiZoneId && type) {
if(type === "codes") {
getAIProjectStatistics().then(res => {
if (res && res.data && res.data.code === 200) {
const { likeCount, publishedCount, pendingCount } = res.data.data || {};
setStats([
{ key: 'likes', label: '累计获得点赞', value: likeCount || 0 },
{ key: 'published', label: '已发布', value: publishedCount || 0 },
{ key: 'reviewing', label: '审核中', value: pendingCount || 0 },
]);
}
})
}
getAIResourceStatistics({
isMine: true,
resourceCategory: aiResouceTypeKey[type],
zoneId: aiZoneId,
}).then(res => {
if (res && res.data && res.data.code === 200) {
const { likeCount, publishedCount, pendingCount } = res.data.data || {};
setStats([
{ key: 'likes', label: '累计获得点赞', value: likeCount || 0 },
{ key: 'published', label: '已发布', value: publishedCount || 0 },
{ key: 'reviewing', label: '审核中', value: pendingCount || 0 },
]);
}
})
}
}, [aiZoneId, type])
useEffect(() => {
if(type === "codes" && aiZoneId) {
//
@ -50,13 +82,7 @@ function MyResources(props) {
setTotal(res.data.total)
}
})
}, [type, aiZoneId, current, reload])
const stats = [
{ key: 'likes', label: '累计获得点赞', value: '123' },
{ key: 'published', label: '已发布', value: '17' },
{ key: 'reviewing', label: '审核中', value: '25' },
];
}, [type, aiZoneId, current, reload, roleByZone])
const columns = [
{

View File

@ -1,3 +1,5 @@
import { Fragment } from "react";
export const aiResouceType = [
{ key: "models", name: "模型库", icon: "moxingku", intro: "行业算法模型", desc: "收录多模态原生大模型矩阵,开箱即用灵活调度,全方位支撑企业 AI 业务研发与智能化升级", createIntro: "上传您的模型文件审核通过后将同步展示在AI广场" },
{ key: "datasets", name: "数据集", icon: "shujuji", intro: "高精训练数据", desc: "精心策划的多模态数据集,覆盖 NLP、CV、语音、多模态等核心方向助力模型快速迭代。", createIntro: "上传您的数据集文件审核通过后将同步展示在AI广场" },
@ -36,13 +38,37 @@ export const aiCreateSteps = [
}
];
// 格式化文件大小
const formatFileSize = (size) => {
if (!size || size === 0) return "";
const num = parseFloat(size);
if (isNaN(num)) return "";
const units = ["B", "KB", "MB", "GB", "TB"];
let unitIndex = 0;
let fileSize = num;
while (fileSize >= 1024 && unitIndex < units.length - 1) {
fileSize /= 1024;
unitIndex++;
}
const formatted = fileSize.toFixed(2);
// 如果两位小数都是0则显示整数
return formatted.endsWith('.00') ? `${parseInt(formatted, 10)}${units[unitIndex]}` : `${formatted}${units[unitIndex]}`;
};
export const convertToTreeData = (data) => {
return data.map(node => {
const isLeaf = !node.children || node.children.length === 0;
let title = node.name;
if (isLeaf && node.size) {
const sizeStr = formatFileSize(node.size);
title = <Fragment><span>{node.name}</span><span>{sizeStr}</span></Fragment>;
}
return {
key: node.name,
title: node.name,
isLeaf: node.type === 'file',
children: node.children ? convertToTreeData(node.children) : undefined
title,
isLeaf,
size: isLeaf ? node.size : undefined,
children: node.children && node.children.length > 0 ? convertToTreeData(node.children) : undefined
};
});
};

View File

@ -513,7 +513,7 @@ export function takeUpSourceById(id, role="Member"){
//
export function drawSourceById(id){
return fetch({
url: `/zoneFront/skillResource/${id}/withdraw`,
url: `/zoneFront/resource/${id}/withdraw`,
method:"PUT"
})
}
@ -540,17 +540,17 @@ export function getMyCodeList(params, role="Member"){
})
}
export function getSkillList(params){
export function getAISourceList(zoneId, params){
return fetch({
url:`/zone/open/ai-square/skill/list`,
url:`/zone/open/${zoneId}/resource/list`,
method: 'get',
params
})
}
export function getSkillById(id){
export function getAISourceById(id){
return fetch({
url:`/zone/open/ai-square/skill/${id}`,
url:`/zone/open/resource/detail/${id}`,
method: 'get'
})
}
@ -607,4 +607,48 @@ export function uploadFileBySourceJournal(data) {
method: 'POST',
data: data
})
}
export function addModel(data) {
return fetch({
url: `/zone/zoneFront/resource/model`,
method: 'POST',
data: data
})
}
export function editModel(data) {
return fetch({
url: `/zone/zoneFront/resource/model`,
method: 'PUT',
data: data
})
}
export function addDataset(data) {
return fetch({
url: `/zone/zoneFront/resource/dataset`,
method: 'POST',
data: data
})
}
export function editDataset(data) {
return fetch({
url: `/zone/zoneFront/resource/dataset`,
method: 'PUT',
data: data
})
}
export function getAIResourceStatistics(params){
return fetch({
url:`/zone/zoneFront/resourceStatistics`,
method: 'get',
params
})
}
export function getAIProjectStatistics(params){
return fetch({
url:`/zone/zoneFront/myProjectStatistics`,
method: 'get',
params
})
}