resource mock data show

This commit is contained in:
penpenwang 2025-12-02 22:09:13 +08:00
parent 0d5781d07a
commit e0b27ad257
6 changed files with 483 additions and 255 deletions

View File

@ -104,7 +104,7 @@ export function GetResourceListApi(
//删除+ 批量删除
export function DelResourceItemApi(idList: string) {
return client.destroy(`/backend/v1/jc/softwareInfo?idList=${idList}`);
return client.destroy(`/backend/v1/jc/resource/delIds?idList=${idList}`);
}
//根据id查详情
@ -258,8 +258,7 @@ export function AddResourceItemApi(
txtDesc: string,
extension: string,
size: number,
path: string,
chapterId?: string
path: string
) {
return client.post(`/jc/resource`, {
bookId,
@ -269,6 +268,27 @@ export function AddResourceItemApi(
extension,
size,
path,
chapterId,
});
}
export function UpdateResourceItemApi(
editId: number,
bookId: number,
name: string,
knowledgeCode: string,
txtDesc: string,
extension: string,
size: number,
path: string
) {
return client.put(`/jc/resource`, {
id: editId,
bookId,
name,
knowledgeCode,
txtDesc,
extension,
size,
path,
});
}

View File

@ -1,8 +1,13 @@
import React, { useState, useEffect } from 'react';
import { Modal, Form, Input, message, Spin, Select } from 'antd';
import { Modal, Form, Input, message, Spin, Select, SelectProps } from 'antd';
import { useTranslation } from 'react-i18next';
import TextArea from 'antd/es/input/TextArea';
import { AddResourceItemApi } from '../../../../api/textbook';
import {
AddResourceItemApi,
GetDetailApi,
getKnowledgeListApi,
UpdateResourceItemApi,
} from '../../../../api/textbook';
import { DraggerUpload } from '../Upload/DraggerUpload';
interface ModalPropsType {
@ -13,18 +18,95 @@ interface ModalPropsType {
resourceId: number;
}
interface Option {
value: string | number;
title: string;
children?: Option[];
}
const defaultData = [
{
createTime: '2025-11-29 16:37:08',
updateTime: '2025-12-02 15:42:09',
creator: null,
updater: null,
tenantId: '-1',
id: 1,
bookId: 46,
parentId: 0,
name: '高等数学基础',
knowledgeCode: 'MATH001',
desc: '高等数学的基础知识点,包含极限、导数、积分等',
level: 1,
type: '基础',
isReal: '1',
orderNum: 1,
extraJson: null,
children: null,
},
{
createTime: '2025-11-29 16:37:08',
updateTime: '2025-12-02 15:42:09',
creator: null,
updater: null,
tenantId: '-1',
id: 2,
bookId: 46,
parentId: 1,
name: '极限与连续',
knowledgeCode: 'MATH001001',
desc: '函数极限的定义与性质,连续函数的特征',
level: 2,
type: '基础',
isReal: '1',
orderNum: 1,
extraJson: null,
children: null,
},
{
createTime: '2025-11-29 16:37:08',
updateTime: '2025-12-02 15:42:09',
creator: null,
updater: null,
tenantId: '-1',
id: 3,
bookId: 46,
parentId: 1,
name: '导数与微分',
knowledgeCode: 'MATH001002',
desc: '导数的定义、计算方法及应用',
level: 2,
type: '基础',
isReal: '1',
orderNum: 2,
extraJson: null,
children: null,
},
{
createTime: '2025-11-29 16:37:08',
updateTime: '2025-12-02 15:42:09',
creator: null,
updater: null,
tenantId: '-1',
id: 4,
bookId: 46,
parentId: 1,
name: '积分学',
knowledgeCode: 'MATH001003',
desc: '不定积分与定积分的计算方法',
level: 2,
type: '基础',
isReal: '1',
orderNum: 3,
extraJson: null,
children: null,
},
];
const CreateResourceModal = (props: ModalPropsType) => {
const { t } = useTranslation();
const { isOpen, onCancel, bookId, resourceId, isEdit } = props;
const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(false);
const [spinInit, setSpinInit] = useState(false);
const [knowledgeOption, setKnowledgeOption] = useState<Option[]>([]);
const [spinInit, setSpinInit] = useState<boolean>(false);
const [knowledgeOption, setKnowledgeOption] = useState<
{
label: string;
value: number;
}[]
>([]);
const [fileSize, setFileSize] = useState<number>(0);
const [fileName, setFileName] = useState<string>('');
const [filePath, setFilePath] = useState<string>('');
@ -36,77 +118,87 @@ const CreateResourceModal = (props: ModalPropsType) => {
if (isEdit && resourceId) {
getDetail();
} else {
form.resetFields();
setSpinInit(false);
form.setFieldsValue({
type: '视频',
});
}
}, [isEdit, resourceId]);
/* useEffect(() => {
getChapterTreeData();
}, []);*/
useEffect(() => {
getKnowledgeOptionData();
}, []);
/* const getKnowledgeOptionData = () => {
GetChapterTreeApi({ bookId }).then((res: any) => {
useEffect(() => {
return () => {
form.resetFields();
setFileName('');
setFilePath('');
setFileSize(0);
setKnowledgeCode('');
};
}, []);
const getKnowledgeOptionData = () => {
getKnowledgeListApi(bookId).then((res: any) => {
const resData: any = res.data;
// console.log(resData, '>>>');
setKnowledgeOption(resData);
const knowledgeOption: { label: string; value: number }[] = defaultData.map(
(item: { name: string; id: number }) => ({
label: `${item.name}`, // 如:"极限与连续 (基础)" (${item.type})
value: item.id,
})
);
setKnowledgeOption(knowledgeOption);
});
};*/
};
const getDetail = () => {
setSpinInit(false);
GetDetailApi(resourceId)
.then((res: any) => {
if (!res || !res.data) {
message.error('获取详情失败');
setSpinInit(false);
return;
}
})
.catch((err) => {
message.error('获取详情失败');
setSpinInit(false);
console.error('获取详情失败:', err);
});
};
const onFinish = (values: any) => {
console.log('表单提交:', values);
const { name = '', txtDesc = '', chapterId = '' } = values;
const { name = '', txtDesc = '', knowledgeCode = '' } = values;
try {
if (isEdit) {
/*UpdateTextbookApi(
editId,
values.title,
thumb,
values.short_desc,
values.author,
values.major,
dep_ids,
group_ids,
user_ids,
values.publish_time,
values.publish_unit,
values.create_time,
values.isbn
)
.then((res: any) => {
setLoading(false);
message.success(t('commen.saveSuccess'));
onCancel();
})
.catch((e) => {
setLoading(false);
});*/
} else {
AddResourceItemApi(
UpdateResourceItemApi(
resourceId,
bookId,
name,
knowledgeCode,
txtDesc,
fileExtension,
fileSize,
filePath,
chapterId
filePath
)
.then((res: any) => {
setLoading(false);
setSpinInit(false);
message.success(t('commen.saveSuccess'));
onCancel();
})
.catch((e) => {
setLoading(false);
setSpinInit(false);
});
} else {
console.log(bookId, name, knowledgeCode, txtDesc, fileExtension, fileSize, filePath);
AddResourceItemApi(bookId, name, knowledgeCode, txtDesc, fileExtension, fileSize, filePath)
.then((res: any) => {
setSpinInit(false);
message.success(t('commen.saveSuccess'));
onCancel();
})
.catch((e) => {
console.log(e, 'error');
setSpinInit(false);
});
}
onCancel();
@ -117,6 +209,7 @@ const CreateResourceModal = (props: ModalPropsType) => {
const handleSelectChange = (e: any) => {
console.log(e, '>>.select e');
setKnowledgeCode(e.join(','));
};
const onFinishFailed = (errorInfo: any) => {
@ -160,14 +253,6 @@ const CreateResourceModal = (props: ModalPropsType) => {
>
<TextArea allowClear placeholder={t('textbook.resource.descPlaceholder')} />
</Form.Item>
{/* <Dragger {...uploadProps}>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">{t('textbook.resource.uploadTips')}</p>
<p className="ant-upload-hint">{t('textbook.resource.uploadTips2')}</p>
</Dragger>*/}
<Form.Item
name="path"
label={t('textbook.resource.upload')}
@ -215,15 +300,20 @@ const CreateResourceModal = (props: ModalPropsType) => {
<Form.Item
name="knowledge"
label={t('textbook.resource.knowledgeId')}
rules={[{ required: true, message: t('textbook.resource.konwledgePlaceholder') }]}
rules={[{ required: true, message: t('textbook.resource.knowledgePlaceholder') }]}
>
<Select
mode="multiple"
placeholder="Please select"
defaultValue={[]}
placeholder={t('textbook.resource.knowledgePlaceholder')}
defaultValue={knowledgeCode ? [knowledgeCode] : []}
onChange={handleSelectChange}
style={{ width: '100%' }}
options={knowledgeOption}
showSearch
//@ts-ignore
filterOption={(input: string, option: { label: string; value: number }) =>
(option?.label ?? '')?.toLowerCase().includes(input.toLowerCase())
}
/>
</Form.Item>
</Form>

View File

@ -2,7 +2,7 @@ import { useEffect, useState, useRef } from 'react';
import { Upload, message, Progress, List, Button, Space } from 'antd';
import { InboxOutlined, CloseOutlined, FileOutlined } from '@ant-design/icons';
import type { UploadProps } from 'antd';
import { getTenant, getToken } from '../../../../utils';
import { formatFileSize, getTenant, getToken } from '../../../../utils';
import { useTranslation } from 'react-i18next';
import config from '../../../../js/config';
@ -92,7 +92,6 @@ export const DraggerUpload = (props: IProps) => {
// 检查文件类型(仅对其他类型做限制)
const checkFileType = (file: File): boolean => {
if (typeId && typeId !== 5) return true;
const extension = getFileExtension(file.name);
const restrictedExtensions = [
'mp4',
@ -119,7 +118,6 @@ export const DraggerUpload = (props: IProps) => {
message.error(t('textbook.resource.restrictedFileType'));
return false;
}
return true;
};
@ -285,19 +283,13 @@ export const DraggerUpload = (props: IProps) => {
return false;
}
return checkFileType(file);
if (typeId) {
checkFileType(file);
}
return true;
},
};
// 格式化文件大小
const formatFileSize = (bytes: number) => {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
// 获取状态对应的文本和颜色
const getStatusInfo = (status: UploadFileItem['status']) => {
switch (status) {

View File

@ -25,14 +25,15 @@
justify-content: space-between;
margin-bottom: 16px;
.btns{
width: 70%;
width: 56%;
display: flex;
flex-direction: row;
justify-content: end;
align-items: baseline;
}
.types{
width: 30%;
min-width: 475px;
width: 44%;
display: flex;
flex-direction: row;
justify-content: start;

View File

@ -1,4 +1,4 @@
import { Button, Input, message, Modal, Radio, Space, Table, TableProps } from 'antd';
import { Button, Image, Input, message, Modal, Radio, Space, Table, TableProps, Tag } from 'antd';
import React, { useEffect, useState } from 'react';
import { GetResourceListApi, DelResourceItemApi, GetDetailApi } from '../../api/textbook';
import styles from './resource.module.less';
@ -7,28 +7,54 @@ import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import LoadingPage from '../loading';
import { BackBartment } from '../../compenents';
import { useTranslation } from 'react-i18next';
import { DeleteOutlined, UploadOutlined } from '@ant-design/icons';
const MusicSvg: React.FC = () => (
<svg
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="30"
height="30"
>
<path
d="M320 192 1024 0 1024 64 1024 192 1024 736C1024 824.352 923.712 896 800 896 676.288 896 576 824.352 576 736 576 647.648 676.288 576 800 576 834.368 576 866.912 581.536 896 591.392L896 261.824 448 384 448 864C448 952.352 347.712 1024 224 1024 100.288 1024 0 952.352 0 864 0 775.648 100.288 704 224 704 258.368 704 290.912 709.536 320 719.392L320 384 320 192Z"
fill="#628eee"
></path>
</svg>
);
import {
DeleteOutlined,
EyeOutlined,
FileTextFilled,
FileTextTwoTone,
FileUnknownTwoTone,
PlayCircleOutlined,
UploadOutlined,
VideoCameraFilled,
} from '@ant-design/icons';
import CreateResourceModal from './compenents/Resource/CreateResourceModal';
import { dateFormatNoTime, formatFileSize } from '../../utils';
import defaultThumb1 from '../../assets/thumb/thumb1.png';
interface ResourceBase {
id: number | null | string | undefined; // 资源id
typeId: number; // 分类Id
id: string; // 资源id
typeId?: number | string; // 分类Id
bookId: 0;
chapterId: 0;
chapterId?: 0;
chapterTitle?: string;
name: string;
type: string;
ext: string;
ext?: string;
size: 0;
duration: 0;
duration?: 0;
url: string;
cover: string;
status: 0;
creator: string;
updater: string;
cover?: string;
status?: 0;
creator?: string;
updater?: string;
createTime: string;
updateTime: string;
tenantId: string;
updateTime?: string;
tenantId?: string;
}
// 列表展示
@ -51,6 +77,8 @@ const ResourcePage = () => {
const { bookId } = useParams();
const [isEdit, setIsEdit] = useState(false); // 是否编辑模式
const [editId, setEditId] = useState<number>(0);
const [itemDetailData, setItemDetailData] = useState<ResourceBase>();
const [loading, setLoading] = useState<boolean>(false);
const [isAddModalOpen, setIsAddModalOpen] = useState<boolean>(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
@ -76,136 +104,218 @@ const ResourcePage = () => {
{ label: t('textbook.resource.typeList.audio'), value: 4, color: '#f3e8ff' },
{ label: t('textbook.resource.typeList.other'), value: 5, color: '#f3f4f6' },
];
const bgColors = ['#dbeafe', '#dcfce7', '#fef9c3', '#f3e8ff', '#f3f4f6'];
const fontColors = ['#4649c1', '#1a6838', '#98692b', '#6e26aa', '#434b57'];
// 排序字段/**/
/* name
size createTime这三个*/
// 列表数据
const columns: TableProps<ResourceBase>['columns'] = [
const demoData = [
{
title: t('textbook.resource.title1'),
dataIndex: 'softNo',
align: 'left',
width: 300,
sorter: true,
key: '1',
id: '1',
name: '课程介绍视频.mp4',
chapterTitle: '第1章 课程概述 - 1.1 课程简介',
type: '视频',
typeId: '1',
createTime: '2024-01-15',
size: 12500000, // 用于排序的数值
},
{
title: t('textbook.resource.title2'),
dataIndex: 'softwareName',
align: 'left',
},
key: '2',
id: '2',
{
title: t('textbook.resource.title3'),
dataIndex: 'company',
ellipsis: true,
sorter: true,
name: '课程大纲图.jpg',
chapterTitle: '第1章 课程概述 - 1.1 课程简介',
type: '图片',
typeId: '2',
url: '',
createTime: '2024-01-10',
size: 2400000,
},
{
title: t('textbook.resource.title4'),
dataIndex: 'version',
align: 'left',
ellipsis: true,
width: 140,
sorter: true,
id: '3',
key: '3',
name: '第一套练习题.pdf',
chapterTitle: '第1章 课程概述',
type: '文档',
typeId: '3',
createTime: '2024-01-12',
size: 1800000,
},
{
title: t('textbook.resource.title5'),
// align: 'center',
render: (_, record) => (
<Space
size="middle"
style={{ display: 'flex', justifyContent: 'space-around', alignItems: 'center' }}
>
<a
key="pre"
onClick={() => {
console.log('预览');
}}
>
{/*<EyeOutlined />*/}
{t('commen.preview')}
</a>
<a
key={'edit'}
//@ts-ignore
onClick={() => {
getDetail(Number(record.id));
}}
>
{t('commen.edit')}
</a>
<a
key={'del'}
className="b-link c-red"
onClick={() => showDeleteConfirm(Number(record.id))}
>
{/*<DeleteOutlined />*/}
{t('commen.del')}
</a>
</Space>
),
id: '4',
key: '4',
name: '课程导入音频.mp3',
chapterTitle: '第1章 课程概述 - 1.1 课程简介',
type: '音频',
typeId: '4',
createTime: '2024-01-14',
size: 5200000,
},
];
// @ts-ignore
const getResourceList = async () => {
try {
const res = (await GetResourceListApi(
page,
pageSize,
type,
searchData,
sortOrder,
sortField
)) as ResourceResData;
if (res && 'data' in res && 'records' in res.data) {
setResource(res.data.records);
const columns: TableProps<ResourceBase>['columns'] = [
{
title: t('textbook.resource.title1'),
dataIndex: 'name',
align: 'left',
width: 500,
sorter: true,
render: (name: string, record) => (
<div className="d-flex">
<div
style={{
width: 58,
height: 58,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
borderRadius: '6px',
background: '#f3f4f6',
textAlign: 'center',
marginRight: 15,
overflow: 'hidden',
}}
>
{record.typeId == '1' && (
<VideoCameraFilled style={{ fontSize: 30, color: '#628eee' }} />
)}{' '}
{record.typeId == '2' && (
<Image
src={record.url}
width={58}
height={58}
preview={false}
fallback={defaultThumb1}
/>
)}
{record.typeId == '3' && <FileTextFilled style={{ fontSize: 30, color: '#628eee' }} />}
{record.typeId == '4' && <MusicSvg />}
{record.typeId == '5' && (
<FileUnknownTwoTone style={{ fontSize: 30, color: '#628eee' }} />
)}
</div>
<div>
<div style={{ fontWeight: 'bold', fontSize: '14px', marginBottom: '4px' }}>{name}</div>
<div style={{ color: '#666', fontSize: '12px' }}>{record?.chapterTitle}</div>
</div>
</div>
),
},
{
title: t('textbook.resource.title2'),
dataIndex: 'typeId',
key: 'typeId',
align: 'center',
width: 100,
render: (typeId: number, record) => {
return (
<div
style={{
borderRadius: '20px',
width: 60,
height: 30,
lineHeight: '30px',
backgroundColor: bgColors[Number(typeId) - 1],
color: fontColors[Number(typeId) - 1],
}}
>
{record.type}
</div>
);
},
},
{
title: t('textbook.resource.title3'),
dataIndex: 'size',
ellipsis: true,
sorter: true,
key: 'size',
width: 150,
align: 'center',
render: (size) => <span style={{ fontWeight: 500 }}>{formatFileSize(size)}</span>,
},
{
title: t('textbook.resource.title4'),
align: 'left',
ellipsis: true,
width: 180,
sorter: true,
dataIndex: 'createTime',
key: 'createTime',
render: (createTime: string) => {
return <span style={{ color: 'gray' }}>{dateFormatNoTime(createTime)}</span>;
},
},
{
title: t('textbook.resource.title5'),
align: 'center',
width: 240,
render: (_, record) => {
return (
<Space
size="middle"
style={{ display: 'flex', justifyContent: 'space-around', alignItems: 'center' }}
>
<a
key="pre"
onClick={() => {
console.log('预览');
}}
>
{t('commen.preview')}
</a>
<a
key={'edit'}
onClick={() => {
setEditId(Number(record.id));
setIsAddModalOpen(true);
}}
>
{t('commen.edit')}
</a>
<a key={'del'} className="b-link c-red" onClick={() => showDeleteConfirm(record.id)}>
{/*<DeleteOutlined />*/}
{t('commen.del')}
</a>
</Space>
);
},
},
];
const getResourceList = () => {
GetResourceListApi(page, pageSize, type, sortOrder, sortField, searchData)
.then((res: any) => {
// @ts-ignore
setResource(demoData);
setResourceTotal(demoData.length);
setResourceTotal(res.data.total);
} else {
console.warn('接口返回数据结构异常:', res);
setResource([]); // 设置为空数组防止崩溃
}
} catch (error) {
console.error('获取列表失败:', error);
}
setLoading(false);
})
.catch((error) => {
setLoading(false);
setResource([]);
});
};
const resetVirtualList = async () => {
try {
const res = (await GetResourceListApi(1, 10, null, null, null, null)) as ResourceResData;
if (res && 'data' in res && 'records' in res.data) {
const resetVirtualList = () => {
GetResourceListApi(1, 10, null, null, null, null)
.then((res: any) => {
setResource(res.data.records || []);
setResourceTotal(res.data.total);
} else {
console.warn('接口返回数据结构异常:', res);
setResource([]); // 设置为空数组防止崩溃
}
} catch (error) {
console.error('获取列表失败:', error);
}
})
.catch((error) => {
console.warn('接口返回数据结构异常:', error);
setResource([]);
});
};
const getDetail = async (id: number) => {
try {
const res = (await GetDetailApi(id)) as VirtualResDetail | undefined;
if (!res || !res.data) {
message.error('获取详情失败');
return;
}
setIsEdit(true);
//@ts-ignore
setItemDetailData(res.data);
setSelectedId(res.data.id);
// 打开弹窗
setIsAddModalOpen(true);
} catch (error) {
message.error('获取详情失败');
setPageLoading(false);
console.error('获取详情失败:', error);
}
};
const showDeleteConfirm = (id: number) => {
const showDeleteConfirm = (id: string) => {
setSelectedId(id);
setModalVisible(true);
};
@ -213,31 +323,33 @@ const ResourcePage = () => {
const handleDeleteItem = async () => {
if (selectedId === null) return;
setConfirmLoading(true);
try {
await DelResourceItemApi(selectedId.toString());
message.success('删除成功');
// @ts-ignore
await getVirtualList();
} catch (error) {
message.error('删除失败');
console.error('删除失败:', error);
} finally {
setConfirmLoading(false);
setModalVisible(false);
setSelectedId(null);
}
DelResourceItemApi(selectedId.toString())
.then(() => {
message.success('删除成功');
getResourceList();
setConfirmLoading(false);
setModalVisible(false);
setSelectedId(null);
})
.catch((err) => {
setConfirmLoading(false);
setModalVisible(false);
setSelectedId(null);
message.error('删除失败');
console.error('删除失败:', err);
});
};
//弹窗取消
const showAddSoftModal = () => {
setIsEdit(false); // 设置为新增模式
setSelectedId(null); // 清除选中 ID
setIsEdit(false);
setSelectedId(null);
setIsAddModalOpen(true);
};
const handleCancelDeleteItem = () => {
setModalVisible(false);
};
const handleCancelDeleteItems = () => {
setIsConfirmModalOpen(false);
};
@ -247,6 +359,8 @@ const ResourcePage = () => {
setType(0);
setSelectedIdList([]);
setSearchData('');
setSortOrder('');
setSortField('');
resetVirtualList();
};
// 批量删除
@ -254,22 +368,25 @@ const ResourcePage = () => {
toDeleteSoftwareList();
};
const toDeleteSoftwareList = async () => {
try {
const selectedIdListString = selectedIdList.join(',');
const res = await DelResourceItemApi(selectedIdListString);
message.success('删除成功');
// @ts-ignore
await getVirtualList();
} catch (error) {
message.error('删除失败');
console.error('删除失败:', error);
} finally {
setConfirmLoading(false);
setIsConfirmModalOpen(false);
setSelectedId(null);
setSelectedIdList([]);
}
const toDeleteSoftwareList = () => {
const selectedIdListString = selectedIdList.join(',');
DelResourceItemApi(selectedIdListString)
.then(() => {
message.success('删除成功');
setConfirmLoading(false);
setIsConfirmModalOpen(false);
setSelectedId(null);
setSelectedIdList([]);
getResourceList();
})
.catch((err) => {
message.error('删除失败');
console.error('删除失败:', err);
setConfirmLoading(false);
setIsConfirmModalOpen(false);
setSelectedId(null);
setSelectedIdList([]);
});
};
const handleAddCancel = () => {
@ -282,7 +399,7 @@ const ResourcePage = () => {
useEffect(() => {
setResource([]);
getResourceList();
}, [refresh, page, pageSize, type, searchData]);
}, [refresh, page, pageSize, type, sortOrder, sortField]);
const onSelectChange = (newSelectedRowKeys: any[]) => {
setSelectedIdList(newSelectedRowKeys);
@ -294,26 +411,21 @@ const ResourcePage = () => {
onChange: onSelectChange,
};
useEffect(() => {
getResourceList();
}, [page, pageSize, type, sortOrder, sortField, searchData]);
const handleTableChange = (
pagination: { current: number; pageSize: number },
filters: any,
sorter: { field: string; order: string }
) => {
// 统一处理分页
// if (pagination.current !== page || pagination.pageSize !== pageSize) {
setPage(pagination.current);
setPageSize(pagination.pageSize);
// }
// 处理排序
if (sorter && sorter.field) {
const sortField = sorter.field as string;
const sortOrder =
sorter.order === 'ascend' ? 'asc' : sorter.order === 'descend' ? 'desc' : '';
const sField = sorter.field as string;
const sOrder = sorter.order === 'ascend' ? 'asc' : sorter.order === 'descend' ? 'desc' : '';
console.log('排序字段:', sortField, '排序方向:', sortOrder);
setSortField(sField);
setSortOrder(sOrder);
}
};
@ -363,7 +475,7 @@ const ResourcePage = () => {
<div className={styles.btns}>
<Input
placeholder={t('textbook.resource.searchPlaceholder')}
style={{ marginRight: 15, width: 360 }}
style={{ marginRight: 15, width: 220 }}
value={searchData}
allowClear
onChange={(e) => setSearchData(e.target.value)}
@ -405,8 +517,8 @@ const ResourcePage = () => {
current: page,
total: resourceTotal,
showSizeChanger: true,
align: 'start',
showTotal: (total) => `${resourceTotal} 条记录`,
align: 'end',
showTotal: () => `${resourceTotal} 条记录`,
}}
// @ts-ignore
onChange={handleTableChange}
@ -431,7 +543,7 @@ const ResourcePage = () => {
onCancel={handleCancelDeleteItem}
confirmLoading={confirmLoading}
>
<p></p>
<p></p>
</Modal>
{/*多个删除确认*/}
<Modal
@ -441,7 +553,7 @@ const ResourcePage = () => {
onCancel={handleCancelDeleteItems}
confirmLoading={confirmLoading}
>
<p></p>
<p></p>
</Modal>
</>
);

View File

@ -408,3 +408,16 @@ export const dataURLtoBlob = (dataurl: string): Blob => {
export const getFileExtension = (filename: string): string => {
return filename.slice(((filename.lastIndexOf('.') - 1) >>> 0) + 2);
};
/**
*
*/
// 格式化文件大小
export const formatFileSize = (bytes: number) => {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};