You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

503 lines
17 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { PlusOutlined } from '@ant-design/icons';
import { Button, message, Image, Modal, } from 'antd';
import React, { useState, useRef } from 'react';
import { history } from 'umi';
import { PageContainer, FooterToolbar } from '@ant-design/pro-layout';
import type { ProColumns, ActionType } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
import { ModalForm, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
import type { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
import ProDescriptions from '@ant-design/pro-descriptions';
import type { FormValueType } from './components/UpdateForm';
import UpdateForm from './components/UpdateForm';
import { copySubject, addSubject, updateSubject, removeSubject, querySubjectList, queryListChapterBySubject } from './service';
import type { TableListItem, TableListPagination } from './data';
import { queryCourseListByTag } from '../option/service';
const { confirm } = Modal;
/** 章节列表项定义 */
const chapterColumns: ProColumns<TableListItem>[] = [
{
title: '序号',
key: 'index',
valueType: 'indexBorder',
width: 48,
},
{
title: '章节名称',
dataIndex: 'chapter_name',
valueType: 'text',
hideInTable: false,
hideInDescriptions: false,
hideInForm: false,
hideInSearch: true,
},
{
title: '简介',
dataIndex: 'chapter_describe',
valueType: 'textarea',
sorter: false,
hideInTable: false,
hideInForm: false,
hideInSearch: true,
renderText: (val: string) => (<div dangerouslySetInnerHTML={{ __html: val }} />),
},
{
title: '课程',
valueType: 'select',
dataIndex: 'course_names',
sorter: false,
hideInTable: false,
hideInForm: false,
hideInSearch: true,
fieldProps: {
mode: "multiple"
},
renderText: (val: string) => `${val}`,
request: async (params) => {
const { tags } = params;
const { data: Items } = await queryCourseListByTag({ tag_ids: tags?.toString() });
console.log('queryCourseListByTag...')
const courses = []
for (let i = 0; i < Items?.length; i++) {
courses.push({ label: Items[i]?.course_name, value: Items[i]?.course_id })
}
console.log(courses, 'courses:::');
return courses;
},
},
{
title: '学时',
dataIndex: 'course_minutes',
valueType: 'text',
sorter: false,
hideInTable: false,
hideInForm: true,
hideInSearch: true,
renderText: (val: string) => `${val}学时`,
},
];
/**
* 添加节点
*
* @param fields
*/
const handleAdd = async (fields: TableListItem) => {
const hide = message.loading('正在添加');
try {
await addSubject({ ...fields });
hide();
message.success('添加成功');
return true;
} catch (error) {
hide();
message.error('添加失败请重试!');
return false;
}
};
/**
* 更新节点
*
* @param fields
*/
const handleUpdate = async (fields: FormValueType, currentRow?: TableListItem) => {
const hide = message.loading('正在更新');
try {
await updateSubject({
...currentRow,
...fields,
});
hide();
message.success('操作成功');
return true;
} catch (error) {
hide();
message.error('操作失败请重试!');
return false;
}
};
/**
* 删除主题
*
* @param selectedRows
*/
const handleRemove = async (selectedRows: TableListItem[]) => {
const hide = message.loading('正在删除');
if (!selectedRows) return true;
try {
const { code, msg } = await removeSubject({
key: selectedRows.map((row) => row.key),
});
hide();
if (code === 2000) {
message.success('删除成功,即将刷新');
} else {
message.warning(msg);
}
return true;
} catch (error) {
hide();
message.error('删除失败,请重试');
return false;
}
};
const TableList: React.FC = () => {
/** 新建窗口的弹窗 */
const [createModalVisible, handleModalVisible] = useState<boolean>(false);
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [detailModalVisible, handleDetailModalVisible] = useState<boolean>(false);
const actionRef = useRef<ActionType>();
const actionChapterRef = useRef<ActionType>();
const [currentRow, setCurrentRow] = useState<TableListItem>();
const [selectedRowsState, setSelectedRows] = useState<TableListItem[]>([]);
const columns: ProColumns<TableListItem>[] = [
{
title: '主题名称',
dataIndex: 'subject_name',
valueType: 'text',
hideInTable: true,
hideInDescriptions: true,
hideInForm: true,
hideInSearch: false,
},
{
title: '图片',
tip: '主题封面',
hideInSearch: true,
render: (dom, entity) => {
// console.log(entity, 'entity')
return (
<Image
src={`/dsideal_yy/html/${entity.attachment_json.url}`}
width={300}
height={200}
fallback="data:image/png;base64,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"
style={{ border: '1px solid #f0f0f0', overflowY: 'hidden' }} />
);
},
},
{
title: '创建日期',
dataIndex: 'create_time',
valueType: 'dateRange',
hideInTable: true,
hideInForm: true,
hideInSearch: false,
},
{
title: '主题',
dataIndex: 'subject_describe',
valueType: 'textarea',
hideInSearch: true,
width: "*",
render: (dom, entity) => {
return (
<div>
<h3>{entity.subject_name}</h3>
<div dangerouslySetInnerHTML={{ __html: entity.subject_describe }} />
</div>
);
},
},
{
title: '信息',
dataIndex: 'total_course_minutes',
sorter: false,
hideInSearch: true,
width: 200,
render: (dom, entity) => {
if (entity.b_use === 0) {
return '待发布'
}
return (
<div>
{entity.total_chapter_number} <br />
{entity.total_course_number} <br />
{entity.total_course_minutes}
</div>
);
},
},
// {
// title: '课程数',
// sorter: true,
// dataIndex: 'total_chapter_number',
// },
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
width: 200,
render: (_, record) => [
<a
key="detail"
onClick={() => {
setCurrentRow(record);
if (actionChapterRef.current) {
actionChapterRef.current.reload();
}
handleDetailModalVisible(true);
}}
>
</a>,
<a
key="edit"
onClick={() => {
history.push(`/course/subject/step/update/${record.subject_id}`)
}}
>
</a>,
<a
key="copyAlert"
onClick={async () => {
const hide = message.loading('正在复制');
// console.log(e, record, 'copy')
const success = await copySubject({ subject_id: record.subject_id });
if (success) {
hide();
// handleModalVisible(false);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
>
</a>,
<a
key="remove"
onClick={() => {
showConfirm(record)
}}>
</a>,
],
},
];
const showConfirm = async (record) => {
confirm({
title: '确认删除主题吗?',
centered: true,
onOk() {
handleRemove([{ key: record?.subject_id }]); // 调用批量删除函数如果接口不支持批量需要在service中处理
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
},
onCancel() {
},
});
};
return (
<PageContainer>
<ProTable<TableListItem, TableListPagination>
headerTitle="主题设置"
actionRef={actionRef}
rowKey="subject_id"
options={false}
search={{
labelWidth: 120,
}}
toolBarRender={() => [
<Button
type="primary"
key="primary"
onClick={() => {
history.push('/course/subject/step/create')
}}
>
<PlusOutlined />
</Button>,
]}
request={async (value) => {
const { create_time } = value;
if (create_time) {
value.begin_time = create_time[0]
value.end_time = create_time[1]
}
const { data } = await querySubjectList({
...value,
page_number: value.current,
page_size: value.pageSize
}); // 解构后不用套data
// console.log('datalist', dataist)
return {
current: data?.page_number,
data: data?.list,
pageSize: data?.page_size,
success: true,
total: data?.total_row || 0,
};
}}
columns={columns}
rowSelection={false}
/>
{selectedRowsState?.length > 0 && (
<FooterToolbar
extra={
<div>
{' '}
<a
style={{
fontWeight: 600,
}}
>
{selectedRowsState.length}
</a>{' '}
&nbsp;&nbsp;
<span>
{selectedRowsState.reduce((pre, item) => pre + item.callNo!, 0)}
</span>
</div>
}
>
<Button
onClick={async () => {
await handleRemove(selectedRowsState);
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
}}
>
</Button>
<Button type="primary"></Button>
</FooterToolbar>
)}
<ModalForm
title="新建主题"
width="400px"
visible={createModalVisible}
onVisibleChange={handleModalVisible}
onFinish={async (value) => {
const success = await handleAdd(value as TableListItem);
if (success) {
handleModalVisible(false);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
>
<ProFormText
rules={[
{
required: true,
message: '主题名称为必填项',
},
]}
width="md"
name="name"
/>
<ProFormTextArea width="md" name="desc" />
</ModalForm>
<Modal
title={'主题信息'}
width="50%"
visible={detailModalVisible}
onCancel={() => {
setCurrentRow(undefined); // 设置当前行
handleDetailModalVisible(false);
}}
footer={null}
centered
>
{currentRow?.subject_id && (
<>
<ProDescriptions
layout='horizontal'
column={1}
//actionRef={actionRef}
title={false}
/*
request={async () => {
console.log('step2 主题信息')
return Promise.resolve({
success: true,
data: { id: '这是一段文本', object: '', date: '2020-07-30 08:00', duration: '', grade: 100, through: '>60', learn: '>20 min', times: 2 },
});
}}*/
extra={false}
>
<ProDescriptions.Item dataIndex="id" hideInDescriptions />
<ProDescriptions.Item dataIndex="subject_name" label="主题名称" valueType="text">{currentRow?.subject_name}</ProDescriptions.Item>
<ProDescriptions.Item dataIndex="subject_describe" label="主题介绍" valueType="text">
<div dangerouslySetInnerHTML={{ __html: currentRow?.subject_describe }} />
</ProDescriptions.Item>
</ProDescriptions>
<ProTable<TableListItem, TableListPagination>
headerTitle={false}
actionRef={actionChapterRef}
rowKey="chapter_id"
options={false}
search={false}
toolBarRender={false}
request={async (value) => {
const { data } = await queryListChapterBySubject({
subject_id: currentRow?.subject_id,
page_number: value?.current || 1,
page_size: value?.pageSize,
});
return {
current: data?.page_number,
data: data?.list,
pageSize: data?.page_size,
success: true,
total: data?.total_row || 0,
};
}}
// dataSource={list}
columns={chapterColumns}
rowSelection={false}
/>
</>
)}
</Modal>
<UpdateForm
onSubmit={async (value) => {
const success = await handleUpdate(value, currentRow);
if (success) {
handleUpdateModalVisible(false);
setCurrentRow(undefined);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
onCancel={() => {
handleUpdateModalVisible(false);
setCurrentRow(undefined);
}}
updateModalVisible={updateModalVisible}
values={currentRow || {}}
/>
</PageContainer>
);
};
export default TableList;