Merge remote-tracking branch 'origin/dev-opt' into dev-opt
This commit is contained in:
commit
de4dcf33e9
|
|
@ -82,6 +82,7 @@
|
||||||
"echarts": "^5.5.0",
|
"echarts": "^5.5.0",
|
||||||
"echarts-gl": "~2.0.9",
|
"echarts-gl": "~2.0.9",
|
||||||
"fabric": "^5.3.0",
|
"fabric": "^5.3.0",
|
||||||
|
"gray-matter": "~4.0.3",
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"motion": "~12.23.12",
|
"motion": "~12.23.12",
|
||||||
|
|
@ -122,7 +123,7 @@
|
||||||
"@testing-library/react": "^14.0.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@types/antd": "^1.0.0",
|
"@types/antd": "^1.0.0",
|
||||||
"@types/express": "^4.17.14",
|
"@types/express": "^4.17.14",
|
||||||
"@types/jest": "^29.5.1",
|
"@types/jest": "~29.5.14",
|
||||||
"@types/lodash": "^4.14.194",
|
"@types/lodash": "^4.14.194",
|
||||||
"@types/react": "^18.0.38",
|
"@types/react": "^18.0.38",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
|
|
|
||||||
|
|
@ -92,11 +92,5 @@
|
||||||
&__content {
|
&__content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
|
||||||
:global {
|
|
||||||
.wmde-markdown {
|
|
||||||
border-radius: 8px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import KFIcon from '@/components/KFIcon';
|
import KFIcon from '@/components/KFIcon';
|
||||||
import KFMdEditor from '@/components/KFMdEditor';
|
import KFMdEditor from '@/components/KFMdEditor';
|
||||||
import DownloadSkillModal from '@/pages/Skill/components/DownloadModal';
|
import DownloadSkillModal from '@/pages/Skill/components/DownloadModal';
|
||||||
|
import FrontmatterCard from '@/pages/Skill/components/FrontmatterCard';
|
||||||
import { SkillData } from '@/pages/Skill/types';
|
import { SkillData } from '@/pages/Skill/types';
|
||||||
import {
|
import {
|
||||||
cancelPraiseSkillReq,
|
cancelPraiseSkillReq,
|
||||||
|
|
@ -16,7 +17,9 @@ import { to } from '@/utils/promise';
|
||||||
import { useModel, useParams } from '@umijs/max';
|
import { useModel, useParams } from '@umijs/max';
|
||||||
import { Button, Flex, message } from 'antd';
|
import { Button, Flex, message } from 'antd';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import matter from 'gray-matter';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import AddSkillModal from '../components/AddSkillModal';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
function SkillInfo() {
|
function SkillInfo() {
|
||||||
|
|
@ -63,35 +66,60 @@ function SkillInfo() {
|
||||||
}
|
}
|
||||||
}, [id, info]);
|
}, [id, info]);
|
||||||
|
|
||||||
// 处理下载
|
const downloadSkill = useCallback(async (url: string) => {
|
||||||
const handleDownload = useCallback(async () => {
|
|
||||||
if (info!.file_tree_json) {
|
|
||||||
const treeData = parseJsonText(info!.file_tree_json);
|
|
||||||
const { close } = openAntdModal(DownloadSkillModal, {
|
|
||||||
treeData,
|
|
||||||
onOk: () => {
|
|
||||||
close();
|
|
||||||
downloadSkill(info!.file_path);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
downloadSkill(info!.file_path);
|
|
||||||
}
|
|
||||||
}, [info]);
|
|
||||||
|
|
||||||
const downloadSkill = async (url: string) => {
|
|
||||||
if (url) {
|
if (url) {
|
||||||
const [res] = await to(downloadSkillReq(url));
|
const [res] = await to(downloadSkillReq(url));
|
||||||
if (res && res.data) {
|
if (res && res.data) {
|
||||||
downloadFileWithUrl(res.data);
|
downloadFileWithUrl(res.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 处理下载
|
||||||
|
const handleDownload = useCallback(async () => {
|
||||||
|
const addLeaf = (treeData: any[]) => {
|
||||||
|
treeData.forEach((item) => {
|
||||||
|
item.isLeaf = !item.children;
|
||||||
|
if (item.children) {
|
||||||
|
addLeaf(item.children);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (info!.file_tree_json) {
|
||||||
|
const treeData = parseJsonText(info!.file_tree_json);
|
||||||
|
if (Array.isArray(treeData) && treeData.length > 0) {
|
||||||
|
addLeaf(treeData);
|
||||||
|
const { close } = openAntdModal(DownloadSkillModal, {
|
||||||
|
treeData,
|
||||||
|
onOk: () => {
|
||||||
|
close();
|
||||||
|
downloadSkill(info!.file_path);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadSkill(info!.file_path);
|
||||||
|
}, [info, downloadSkill]);
|
||||||
|
|
||||||
|
const handleEdit = () => {
|
||||||
|
const { close } = openAntdModal(AddSkillModal, {
|
||||||
|
id: id as string,
|
||||||
|
onOk: () => {
|
||||||
|
close();
|
||||||
|
getSkillInfo();
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { data: frontmatter, content: mdContent } = matter(info!.md_content || '');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles['skill-info']}>
|
<div className={styles['skill-info']}>
|
||||||
<div className={styles['skill-info__top']}>
|
<div className={styles['skill-info__top']}>
|
||||||
|
|
@ -120,17 +148,32 @@ function SkillInfo() {
|
||||||
发布
|
发布
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button color="default" variant="filled" onClick={handleDownload}>
|
{isMine && (
|
||||||
|
<Button
|
||||||
|
color="default"
|
||||||
|
variant="filled"
|
||||||
|
className={styles['skill-info__top__btn']}
|
||||||
|
onClick={handleEdit}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
color="default"
|
||||||
|
variant="filled"
|
||||||
|
className={styles['skill-info__top__btn']}
|
||||||
|
onClick={handleDownload}
|
||||||
|
>
|
||||||
下载
|
下载
|
||||||
</Button>
|
</Button>
|
||||||
<div
|
<div
|
||||||
className={classNames(styles['skill-info__top__praise-btn'], {
|
className={classNames(styles['skill-info__top__praise-btn'], {
|
||||||
[styles['skill-info__top__praise-btn--praised']]: info?.prraised,
|
[styles['skill-info__top__praise-btn--praised']]: info?.praised,
|
||||||
})}
|
})}
|
||||||
onClick={handlePraise}
|
onClick={handlePraise}
|
||||||
>
|
>
|
||||||
<KFIcon
|
<KFIcon
|
||||||
type={info?.prraised ? 'icon-a-dianzanicon1' : 'icon-dianzanicon'}
|
type={info?.praised ? 'icon-a-dianzanicon1' : 'icon-dianzanicon'}
|
||||||
font={16}
|
font={16}
|
||||||
style={{ marginRight: '6px' }}
|
style={{ marginRight: '6px' }}
|
||||||
/>
|
/>
|
||||||
|
|
@ -140,9 +183,10 @@ function SkillInfo() {
|
||||||
</Flex>
|
</Flex>
|
||||||
<div className={styles['skill-info__top__desc']}>{info?.description || ''}</div>
|
<div className={styles['skill-info__top__desc']}>{info?.description || ''}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<FrontmatterCard data={frontmatter} />
|
||||||
<KFMdEditor
|
<KFMdEditor
|
||||||
className={styles['skill-info__content']}
|
className={styles['skill-info__content']}
|
||||||
defaultValue={info?.md_content || ''}
|
defaultValue={mdContent || ''}
|
||||||
canEdit={false}
|
canEdit={false}
|
||||||
noDataTitle={'没有内容'}
|
noDataTitle={'没有内容'}
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { CommonTabKeys } from '@/enums';
|
import { CommonTabKeys } from '@/enums';
|
||||||
import { useCacheState } from '@/hooks/useCacheState';
|
import { useCacheState } from '@/hooks/useCacheState';
|
||||||
import { SkillCategoryData } from '@/pages/Skill/types';
|
import { SkillCategoryData } from '@/pages/Skill/types';
|
||||||
import { getSkillTypesReq } from '@/services/skill/index';
|
import { getAssetIcon } from '@/services/dataset/index.js';
|
||||||
import { to } from '@/utils/promise';
|
import { to } from '@/utils/promise';
|
||||||
import { type TabsProps } from 'antd';
|
import { type TabsProps } from 'antd';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
|
@ -9,11 +9,13 @@ import CategoryList from '../components/CategoryList';
|
||||||
import ResourceList, { ResourceListRef } from '../components/ResourceList';
|
import ResourceList, { ResourceListRef } from '../components/ResourceList';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
|
export const ALL_TYPE = '全部分类';
|
||||||
|
|
||||||
function SkillPage() {
|
function SkillPage() {
|
||||||
const [cacheState, setCacheState] = useCacheState();
|
const [cacheState, setCacheState] = useCacheState();
|
||||||
const [activeTab, setActiveTab] = useState<string>(cacheState?.activeTab ?? CommonTabKeys.Public);
|
const [activeTab, setActiveTab] = useState<string>(cacheState?.activeTab ?? CommonTabKeys.Public);
|
||||||
const [typeList, setTypeList] = useState<SkillCategoryData[]>([]);
|
const [typeList, setTypeList] = useState<SkillCategoryData[]>([]);
|
||||||
const [activeTypes, setActiveTypes] = useState<string[]>(cacheState?.activeType ?? []);
|
const [activeType, setActiveType] = useState<string | undefined>(cacheState?.activeType);
|
||||||
const dataListRef = useRef<ResourceListRef>(null);
|
const dataListRef = useRef<ResourceListRef>(null);
|
||||||
const [typeSearchText, setTypeSearchText] = useState<string>('');
|
const [typeSearchText, setTypeSearchText] = useState<string>('');
|
||||||
|
|
||||||
|
|
@ -23,10 +25,11 @@ function SkillPage() {
|
||||||
name: typeSearchText,
|
name: typeSearchText,
|
||||||
page: 0,
|
page: 0,
|
||||||
size: 10000,
|
size: 10000,
|
||||||
|
category_id: 3,
|
||||||
};
|
};
|
||||||
const [res] = await to(getSkillTypesReq(params));
|
const [res] = await to(getAssetIcon(params));
|
||||||
if (res && res.data) {
|
if (res && res.data) {
|
||||||
setTypeList(res.data);
|
setTypeList([{ id: '', name: ALL_TYPE, path: 'icon-quanbuyuyan' }, ...res.data]);
|
||||||
}
|
}
|
||||||
}, [typeSearchText]);
|
}, [typeSearchText]);
|
||||||
|
|
||||||
|
|
@ -42,14 +45,7 @@ function SkillPage() {
|
||||||
// 选择类型
|
// 选择类型
|
||||||
const chooseType = (type: string) => {
|
const chooseType = (type: string) => {
|
||||||
dataListRef.current?.resetPage();
|
dataListRef.current?.resetPage();
|
||||||
setActiveTypes([type]);
|
setActiveType(type);
|
||||||
// setActiveTypes((prev) => {
|
|
||||||
// if (prev.includes(type)) {
|
|
||||||
// return prev.filter((v) => v !== type);
|
|
||||||
// } else {
|
|
||||||
// return [...prev, type];
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换 Tab,重置数据
|
// 切换 Tab,重置数据
|
||||||
|
|
@ -63,7 +59,7 @@ function SkillPage() {
|
||||||
<div className={styles['skill-page']}>
|
<div className={styles['skill-page']}>
|
||||||
<CategoryList
|
<CategoryList
|
||||||
typeList={typeList}
|
typeList={typeList}
|
||||||
activeTypes={activeTypes}
|
activeType={activeType}
|
||||||
onTypeSelect={chooseType}
|
onTypeSelect={chooseType}
|
||||||
currentTab={activeTab}
|
currentTab={activeTab}
|
||||||
tabItems={[
|
tabItems={[
|
||||||
|
|
@ -81,9 +77,8 @@ function SkillPage() {
|
||||||
/>
|
/>
|
||||||
<ResourceList
|
<ResourceList
|
||||||
ref={dataListRef}
|
ref={dataListRef}
|
||||||
skillTypes={typeList}
|
|
||||||
isPublic={isPublic}
|
isPublic={isPublic}
|
||||||
dataTypes={activeTypes}
|
dataType={activeType}
|
||||||
initialSearchText={cacheState?.searchText}
|
initialSearchText={cacheState?.searchText}
|
||||||
initialPagination={cacheState?.pagination}
|
initialPagination={cacheState?.pagination}
|
||||||
setCacheState={setCacheState}
|
setCacheState={setCacheState}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ import ImagePicker, { ImagePickerServerType } from '@/components/ImagePicker';
|
||||||
import KFModal from '@/components/KFModal';
|
import KFModal from '@/components/KFModal';
|
||||||
import UploadBlock from '@/components/UploadBlock';
|
import UploadBlock from '@/components/UploadBlock';
|
||||||
import { SkillCategoryData } from '@/pages/Skill/types';
|
import { SkillCategoryData } from '@/pages/Skill/types';
|
||||||
import { SkillUploadUrl, createSkillReq } from '@/services/skill';
|
import { getAssetIcon } from '@/services/dataset/index.js';
|
||||||
|
import { SkillUploadUrl, createSkillReq, getSkillInfoReq, updateSkillReq } from '@/services/skill';
|
||||||
import { to } from '@/utils/promise';
|
import { to } from '@/utils/promise';
|
||||||
import { getFileListFromEvent, limitUploadFileType, validateUploadFiles } from '@/utils/ui';
|
import { getFileListFromEvent, limitUploadFileType, validateUploadFiles } from '@/utils/ui';
|
||||||
import {
|
import {
|
||||||
|
|
@ -17,17 +18,17 @@ import {
|
||||||
type UploadProps,
|
type UploadProps,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
interface AddVersionModalProps extends Omit<ModalProps, 'onOk'> {
|
interface AddVersionModalProps extends Omit<ModalProps, 'onOk'> {
|
||||||
skillTypes: SkillCategoryData[];
|
id?: number | string;
|
||||||
onOk: () => void;
|
onOk: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddSkillModal({ skillTypes, onOk, ...rest }: AddVersionModalProps) {
|
function AddSkillModal({ id, onOk, ...rest }: AddVersionModalProps) {
|
||||||
const [uuid] = useState(Date.now());
|
const [uuid] = useState(Date.now());
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
// const [sliptUploadRequest, cancelUpload] = useSplitUpload();
|
const [typeList, setTypeList] = useState<SkillCategoryData[]>([]);
|
||||||
|
|
||||||
// 上传组件参数
|
// 上传组件参数
|
||||||
const uploadProps: UploadProps = {
|
const uploadProps: UploadProps = {
|
||||||
|
|
@ -45,11 +46,46 @@ function AddSkillModal({ skillTypes, onOk, ...rest }: AddVersionModalProps) {
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取分类
|
||||||
|
useEffect(() => {
|
||||||
|
const getSkillTypes = async () => {
|
||||||
|
const params = {
|
||||||
|
page: 0,
|
||||||
|
size: 10000,
|
||||||
|
category_id: 3,
|
||||||
|
};
|
||||||
|
const [res] = await to(getAssetIcon(params));
|
||||||
|
if (res && res.data) {
|
||||||
|
setTypeList(res.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getSkillTypes();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 获取 Skill 详情
|
||||||
|
useEffect(() => {
|
||||||
|
const getSkillInfo = async (id: number | string) => {
|
||||||
|
const [res] = await to(getSkillInfoReq(id));
|
||||||
|
if (res && res.data) {
|
||||||
|
form.setFieldsValue(res.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
getSkillInfo(id);
|
||||||
|
}
|
||||||
|
}, [id, form]);
|
||||||
|
|
||||||
// 上传请求
|
// 上传请求
|
||||||
const createDatasetVersion = async (params: any) => {
|
const createDatasetVersion = async (params: any) => {
|
||||||
const [res] = await to(createSkillReq(params));
|
if (id) {
|
||||||
|
params.id = id;
|
||||||
|
}
|
||||||
|
const request = id ? updateSkillReq : createSkillReq;
|
||||||
|
const [res] = await to(request(params));
|
||||||
if (res) {
|
if (res) {
|
||||||
message.success('创建成功');
|
message.success(id ? '编辑成功' : '创建成功');
|
||||||
onOk?.();
|
onOk?.();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -57,20 +93,24 @@ function AddSkillModal({ skillTypes, onOk, ...rest }: AddVersionModalProps) {
|
||||||
// 提交
|
// 提交
|
||||||
const onFinish = (formData: any) => {
|
const onFinish = (formData: any) => {
|
||||||
const fileList: UploadFile[] = formData['fileList'] ?? [];
|
const fileList: UploadFile[] = formData['fileList'] ?? [];
|
||||||
if (validateUploadFiles(fileList)) {
|
if (id) {
|
||||||
const data = fileList[0]?.response?.data ?? {};
|
createDatasetVersion(formData);
|
||||||
const params = {
|
} else {
|
||||||
...omit(formData, 'fileList'),
|
if (validateUploadFiles(fileList)) {
|
||||||
...data,
|
const data = fileList[0]?.response?.data ?? {};
|
||||||
};
|
const params = {
|
||||||
createDatasetVersion(params);
|
...omit(formData, 'fileList'),
|
||||||
|
...data,
|
||||||
|
};
|
||||||
|
createDatasetVersion(params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KFModal
|
<KFModal
|
||||||
{...rest}
|
{...rest}
|
||||||
title="创建 Skill"
|
title={id ? '编辑 Skill' : '创建 Skill'}
|
||||||
width={608}
|
width={608}
|
||||||
okButtonProps={{
|
okButtonProps={{
|
||||||
htmlType: 'submit',
|
htmlType: 'submit',
|
||||||
|
|
@ -99,7 +139,7 @@ function AddSkillModal({ skillTypes, onOk, ...rest }: AddVersionModalProps) {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder={`请输入 Skill 名称`} />
|
<Input placeholder={`请输入 Skill 名称`} disabled={id !== undefined} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
|
@ -133,7 +173,7 @@ function AddSkillModal({ skillTypes, onOk, ...rest }: AddVersionModalProps) {
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择 Skill 类型"
|
placeholder="请选择 Skill 类型"
|
||||||
options={skillTypes}
|
options={typeList}
|
||||||
fieldNames={{ label: 'name', value: 'name' }}
|
fieldNames={{ label: 'name', value: 'name' }}
|
||||||
optionFilterProp="name"
|
optionFilterProp="name"
|
||||||
showSearch
|
showSearch
|
||||||
|
|
@ -153,22 +193,24 @@ function AddSkillModal({ skillTypes, onOk, ...rest }: AddVersionModalProps) {
|
||||||
<ImagePicker serverType={ImagePickerServerType.Skill} uuid={uuid}></ImagePicker>
|
<ImagePicker serverType={ImagePickerServerType.Skill} uuid={uuid}></ImagePicker>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
{!id && (
|
||||||
label="Skill 文件"
|
<Form.Item
|
||||||
name="fileList"
|
label="Skill 文件"
|
||||||
valuePropName="fileList"
|
name="fileList"
|
||||||
getValueFromEvent={getFileListFromEvent}
|
valuePropName="fileList"
|
||||||
rules={[
|
getValueFromEvent={getFileListFromEvent}
|
||||||
{
|
rules={[
|
||||||
required: true,
|
{
|
||||||
message: '请上传 Skill 文件',
|
required: true,
|
||||||
},
|
message: '请上传 Skill 文件',
|
||||||
]}
|
},
|
||||||
>
|
]}
|
||||||
<Upload {...uploadProps} data={{ uuid: uuid }} className={'common-upload-component'}>
|
>
|
||||||
<UploadBlock desc={'请上传 SKILL.md 或包含 SKILL.md 的 .zip 文件'}></UploadBlock>
|
<Upload {...uploadProps} data={{ uuid: uuid }} className={'common-upload-component'}>
|
||||||
</Upload>
|
<UploadBlock desc={'请上传 SKILL.md 或包含 SKILL.md 的 .zip 文件'}></UploadBlock>
|
||||||
</Form.Item>
|
</Upload>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
</KFModal>
|
</KFModal>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@
|
||||||
color: @text-color;
|
color: @text-color;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(81, 76, 249, 0.1);
|
background-color: rgba(81, 76, 249, 0.1);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import styles from './index.less';
|
||||||
|
|
||||||
type CategoryProps = {
|
type CategoryProps = {
|
||||||
typeList: SkillCategoryData[];
|
typeList: SkillCategoryData[];
|
||||||
activeTypes: string[];
|
activeType: string | undefined;
|
||||||
tabItems: KFRadioItem[];
|
tabItems: KFRadioItem[];
|
||||||
currentTab: string;
|
currentTab: string;
|
||||||
onTabChange: (value: string) => void;
|
onTabChange: (value: string) => void;
|
||||||
|
|
@ -19,7 +19,7 @@ type CategoryProps = {
|
||||||
|
|
||||||
function CategoryList({
|
function CategoryList({
|
||||||
typeList,
|
typeList,
|
||||||
activeTypes,
|
activeType,
|
||||||
tabItems,
|
tabItems,
|
||||||
currentTab,
|
currentTab,
|
||||||
onTabChange,
|
onTabChange,
|
||||||
|
|
@ -53,11 +53,15 @@ function CategoryList({
|
||||||
key={item.id}
|
key={item.id}
|
||||||
align="center"
|
align="center"
|
||||||
className={classNames(styles['category-list__content__title'], {
|
className={classNames(styles['category-list__content__title'], {
|
||||||
[styles['category-list__content__title--active']]: activeTypes.includes(item.name),
|
[styles['category-list__content__title--active']]: activeType === item.name,
|
||||||
})}
|
})}
|
||||||
onClick={() => onTypeSelect(item.name)}
|
onClick={() => {
|
||||||
|
if (item.name !== activeType) {
|
||||||
|
onTypeSelect(item.name);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<KFIcon type={'icon-diancuihuacailiao'} width={16} height={16} />
|
<KFIcon type={item.path} width={16} height={16} />
|
||||||
<div style={{ marginLeft: 8 }}>{item.name}</div>
|
<div style={{ marginLeft: 8 }}>{item.name}</div>
|
||||||
</Flex>
|
</Flex>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,12 @@ function DownloadSkillModal({ treeData, onOk, ...rest }: AddVersionModalProps) {
|
||||||
>
|
>
|
||||||
<DirectoryTree
|
<DirectoryTree
|
||||||
treeData={treeData}
|
treeData={treeData}
|
||||||
defaultExpandAll={true}
|
fieldNames={{
|
||||||
|
title: 'name',
|
||||||
|
key: 'name',
|
||||||
|
}}
|
||||||
|
defaultExpandedKeys={[treeData[0]?.name || '']}
|
||||||
|
selectable={false}
|
||||||
titleRender={(record: DownloadTreeDataNode) => {
|
titleRender={(record: DownloadTreeDataNode) => {
|
||||||
const label = record.name + (record.fileSize ? `(${record.fileSize})` : '');
|
const label = record.name + (record.fileSize ? `(${record.fileSize})` : '');
|
||||||
return <span style={{ fontSize: 14 }}>{label}</span>;
|
return <span style={{ fontSize: 14 }}>{label}</span>;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
.frontmatter-card {
|
||||||
|
padding: 12px;
|
||||||
|
background-color: @background-color;
|
||||||
|
font-size: @font-size-input;
|
||||||
|
color: @text-color;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
border-bottom: 1px solid hsl(210, 18%, 87%);
|
||||||
|
;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
flex: none;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
flex: 1;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Flex } from 'antd';
|
||||||
|
import styles from './index.less';
|
||||||
|
|
||||||
|
type FrontmatterCardProps = {
|
||||||
|
data: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
function FrontmatterCard({ data }: FrontmatterCardProps) {
|
||||||
|
const { name, description } = data;
|
||||||
|
if (!name && !description) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={styles['frontmatter-card']}>
|
||||||
|
<Flex align="flex-start">
|
||||||
|
<span className={styles['frontmatter-card__title']}>name: </span>
|
||||||
|
<span className={styles['frontmatter-card__value']}>{name}</span>
|
||||||
|
</Flex>
|
||||||
|
<Flex align="flex-start">
|
||||||
|
<span className={styles['frontmatter-card__title']}>description: </span>
|
||||||
|
<span className={styles['frontmatter-card__value']}>{description}</span>
|
||||||
|
</Flex>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FrontmatterCard;
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import KFEmpty, { EmptyType } from '@/components/KFEmpty';
|
import KFEmpty, { EmptyType } from '@/components/KFEmpty';
|
||||||
import KFSearch from '@/components/KFSearch';
|
import KFSearch from '@/components/KFSearch';
|
||||||
import { CommonTabKeys } from '@/enums';
|
import { CommonTabKeys } from '@/enums';
|
||||||
import { SkillCategoryData, SkillData } from '@/pages/Skill/types';
|
import { ALL_TYPE } from '@/pages/Skill/List';
|
||||||
|
import { SkillData } from '@/pages/Skill/types';
|
||||||
import { deleteSkillReq, getSkillListReq } from '@/services/skill';
|
import { deleteSkillReq, getSkillListReq } from '@/services/skill';
|
||||||
import { openAntdModal } from '@/utils/modal';
|
import { openAntdModal } from '@/utils/modal';
|
||||||
import { to } from '@/utils/promise';
|
import { to } from '@/utils/promise';
|
||||||
|
|
@ -12,14 +13,14 @@ import { Ref, forwardRef, useCallback, useEffect, useImperativeHandle, useState
|
||||||
import AddSkillModal from '../AddSkillModal';
|
import AddSkillModal from '../AddSkillModal';
|
||||||
import ResourceItem from '../ResourceItem';
|
import ResourceItem from '../ResourceItem';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
export type ResourceListRef = {
|
export type ResourceListRef = {
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
resetPage: () => void;
|
resetPage: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ResourceListProps = {
|
type ResourceListProps = {
|
||||||
skillTypes?: SkillCategoryData[];
|
dataType?: string | undefined;
|
||||||
dataTypes?: string[];
|
|
||||||
isPublic: boolean;
|
isPublic: boolean;
|
||||||
initialSearchText?: string;
|
initialSearchText?: string;
|
||||||
initialPagination?: PaginationProps;
|
initialPagination?: PaginationProps;
|
||||||
|
|
@ -27,14 +28,7 @@ type ResourceListProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function ResourceList(
|
function ResourceList(
|
||||||
{
|
{ dataType, isPublic, initialSearchText, initialPagination, setCacheState }: ResourceListProps,
|
||||||
skillTypes,
|
|
||||||
dataTypes,
|
|
||||||
isPublic,
|
|
||||||
initialSearchText,
|
|
||||||
initialPagination,
|
|
||||||
setCacheState,
|
|
||||||
}: ResourceListProps,
|
|
||||||
ref: Ref<ResourceListRef>,
|
ref: Ref<ResourceListRef>,
|
||||||
) {
|
) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
@ -57,7 +51,7 @@ function ResourceList(
|
||||||
size: pagination.pageSize,
|
size: pagination.pageSize,
|
||||||
is_public: isPublic,
|
is_public: isPublic,
|
||||||
name: searchText || undefined,
|
name: searchText || undefined,
|
||||||
is_hot_stone: true,
|
type: dataType === ALL_TYPE ? undefined : dataType,
|
||||||
};
|
};
|
||||||
const [res] = await to(getSkillListReq(params));
|
const [res] = await to(getSkillListReq(params));
|
||||||
if (res && res.data && res.data.content) {
|
if (res && res.data && res.data.content) {
|
||||||
|
|
@ -67,7 +61,7 @@ function ResourceList(
|
||||||
setDataList([]);
|
setDataList([]);
|
||||||
setTotal(0);
|
setTotal(0);
|
||||||
}
|
}
|
||||||
}, [pagination, searchText, isPublic]);
|
}, [pagination, searchText, isPublic, dataType]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getDataList();
|
getDataList();
|
||||||
|
|
@ -142,7 +136,7 @@ function ResourceList(
|
||||||
activeTab: isPublic ? CommonTabKeys.Public : CommonTabKeys.Private,
|
activeTab: isPublic ? CommonTabKeys.Public : CommonTabKeys.Private,
|
||||||
pagination,
|
pagination,
|
||||||
searchText,
|
searchText,
|
||||||
activeType: dataTypes,
|
activeType: dataType,
|
||||||
});
|
});
|
||||||
navigate(`/dataset/skills/info/${record.id}`);
|
navigate(`/dataset/skills/info/${record.id}`);
|
||||||
};
|
};
|
||||||
|
|
@ -158,7 +152,6 @@ function ResourceList(
|
||||||
// 新建弹框
|
// 新建弹框
|
||||||
const showModal = () => {
|
const showModal = () => {
|
||||||
const { close } = openAntdModal(AddSkillModal, {
|
const { close } = openAntdModal(AddSkillModal, {
|
||||||
skillTypes: skillTypes || [],
|
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
close();
|
close();
|
||||||
getDataList();
|
getDataList();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
export type SkillCategoryData = {
|
export type SkillCategoryData = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
path: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SkillData = {
|
export type SkillData = {
|
||||||
|
|
@ -14,10 +15,8 @@ export type SkillData = {
|
||||||
description: string;
|
description: string;
|
||||||
type: string;
|
type: string;
|
||||||
md_content: string;
|
md_content: string;
|
||||||
prraised: boolean;
|
|
||||||
prraises_count: number;
|
|
||||||
is_public: boolean;
|
|
||||||
praised: boolean;
|
praised: boolean;
|
||||||
|
is_public: boolean;
|
||||||
file_tree_json: string;
|
file_tree_json: string;
|
||||||
file_path: string;
|
file_path: string;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,27 @@ function ApprovalModal({ record, onOk, ...rest }: ApprovalModalProps) {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
|
case ApprovalType.SKILL:
|
||||||
|
items = [
|
||||||
|
{
|
||||||
|
label: 'Skill 名称',
|
||||||
|
value: content.name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Skill 描述',
|
||||||
|
value: content.description,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Skill 类型',
|
||||||
|
value: content.type,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '创建时间',
|
||||||
|
value: content.createTime,
|
||||||
|
format: formatDate,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
items = [];
|
items = [];
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ export enum ApprovalType {
|
||||||
IMAGE = 'IMAGE',
|
IMAGE = 'IMAGE',
|
||||||
CODE = 'CODE',
|
CODE = 'CODE',
|
||||||
SERVICE = 'SERVICE',
|
SERVICE = 'SERVICE',
|
||||||
|
SKILL = 'SKILL',
|
||||||
}
|
}
|
||||||
|
|
||||||
const approvalTypeOptions = [
|
const approvalTypeOptions = [
|
||||||
|
|
@ -55,6 +56,7 @@ const approvalTypeOptions = [
|
||||||
{ label: '镜像', value: ApprovalType.IMAGE },
|
{ label: '镜像', value: ApprovalType.IMAGE },
|
||||||
{ label: '代码配置', value: ApprovalType.CODE },
|
{ label: '代码配置', value: ApprovalType.CODE },
|
||||||
{ label: '应用', value: ApprovalType.SERVICE },
|
{ label: '应用', value: ApprovalType.SERVICE },
|
||||||
|
{ label: 'Skill', value: ApprovalType.SKILL },
|
||||||
];
|
];
|
||||||
|
|
||||||
const statusOptions = [{ label: '全部', value: '' }, ...approvalStatusOptions];
|
const statusOptions = [{ label: '全部', value: '' }, ...approvalStatusOptions];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue