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.

795 lines
26 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 React, { useEffect, useRef, useState } from 'react';
import { history, useParams, useRequest } from 'umi';
import type { ProFormInstance } from '@ant-design/pro-form';
import { BetaSchemaForm, ProFormRadio, ProFormUploadButton } from '@ant-design/pro-form';
import ProForm, {
StepsForm,
ProFormText,
ProFormDatePicker,
ProFormSelect,
ProFormTextArea,
ProFormCheckbox,
ProFormDateRangePicker,
} from '@ant-design/pro-form';
import ProCard from '@ant-design/pro-card';
import { Button, Checkbox, Col, Divider, List, Menu, message, Modal, Radio, Result, Row, Space, Typography } from 'antd';
import { PageContainer } from '@ant-design/pro-layout';
import ProDescriptions from '@ant-design/pro-descriptions';
import styles from './index.less'
import { MailOutlined, AppstoreOutlined, PlusOutlined, TagsOutlined } from '@ant-design/icons';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css'
import ProFormRichEdit from '../components/ProFormRichEdit';
import type { ActionType, ProColumns } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
import type { TableListItem, TableListPagination } from '../../option/data';
import { queryCourseList, queryCourseListByTag, queryTagList, removeCourse, saveSubject } from '../../option/service';
import { commitSubject, getSubjectInfo, queryListChapterBySubject, saveChapter, deleteChapter,getChapterAndCourseList } from '../service';
import { v4 as uuidv4 } from 'uuid';
import type { DataItem } from "@antv/data-set/lib/transform/tag-cloud";
import { removeTrain } from "@/pages/training/option/service";
import { listMyLearningChapterCourse } from "../../../../../../web/src/pages/course/list/service";
import course from "../../../../../../web/mock/course";
const { confirm } = Modal;
//编辑章节 handleUpdateChapter
const handleUpdateChapter = async (fields: TableListItem) => {
try {
const { course_ids } = fields;
const { tag_ids } = fields;
const { code, msg } = await saveChapter({ ...fields, course_ids: course_ids.toString(), tag_ids: tag_ids.toString() });
if (code === 2000) {
message.success('编辑成功');
return true;
} else {
message.warn(msg);
return false;
}
} catch (error) {
message.error('编辑失败请重试!');
return false;
}
};
/**
* 添加章节
*
* @param fields
*/
const handleAddChapter = async (fields: TableListItem) => {
const hide = message.loading('正在添加');
try {
const { course_ids } = fields;
const { tag_ids } = fields;
const { code, msg } = await saveChapter({ ...fields, course_ids: course_ids.toString(), tag_ids: tag_ids.toString() });
if (code === 2000) {
hide();
message.success('添加成功');
return true;
} else {
hide();
message.warn(msg);
return false;
}
} catch (error) {
hide();
message.error('添加失败请重试!');
return false;
}
};
export default () => {
const uuid = uuidv4();
const formRef = useRef<ProFormInstance>();
const actionRef = useRef<ActionType>();
const actionRef1 = useRef<ActionType>();
/** 更新窗口的弹窗 */
const [createModalVisible, handleCreateModalVisible] = useState<boolean>(false);
const [detailModalVisible, handleDetailModalVisible] = useState<boolean>(false);
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [selectedRowsState, setSelectedRows] = useState<TableListItem[]>([]);
const [uploadFileName, SetUploadFileName] = useState<string>();
const [uploadFileExt, SetUploadFileExt] = useState<string>();
const [subjectIntro, setSubjectIntro] = useState({});
const [subjectId, setSubjectId] = useState({});
const [list,setList] = useState({});
const [chapterList, setChapterList] = useState({});
const [currentRow, setCurrentRow] = useState<TableListItem>();
const formMapRef = useRef<React.MutableRefObject<ProFormInstance<any> | undefined>[]>([]);
/** 列表项定义 */
const columns: ProColumns<TableListItem>[] = [
{
title: '序号',
key: 'index',
valueType: 'indexBorder',
width: 48,
align: 'center'
},
{
title: '章节名称',
dataIndex: 'chapter_name',
valueType: 'text',
hideInTable: false,
hideInDescriptions: false,
hideInForm: false,
hideInSearch: true,
formItemProps: {
rules: [
{
required: true,
message: '请填写章节名称',
},
]
},
align: 'center'
},
{
title: '简介',
dataIndex: 'chapter_describe',
valueType: 'textarea',
sorter: false,
hideInTable: false,
hideInForm: false,
hideInSearch: true,
formItemProps: {
required: true,
message: '请填写简介',
},
renderText: (val: string) => (<div dangerouslySetInnerHTML={{ __html: val }} />),
renderFormItem: (item, { defaultRender, ...rest }, form) => (
<ProFormRichEdit
name="chapter_describe"
label=""
width="xl"
// tooltip="最长为 6 位汉字,需要与考生身份证一致"
placeholder="请输入介绍"
// rules={[{ required: true }]}
value=""
// disabled
/>
),
align: 'center'
},
{
title: '标签',
valueType: 'select',
dataIndex: 'tag_ids',
sorter: false,
hideInTable: true,
hideInForm: false,
hideInSearch: true,
fieldProps: {
mode: "multiple"
},
formItemProps: {
rules: [
{
required: true,
message: '请填选择标签',
},
]
},
renderText: (val: string) => `${val}`,
request: async () => {
const { data: Items } = await queryTagList({});
const tags = []
for (let i = 0; i < Items.length; i++) {
tags.push({ label: Items[i].tag_name, value: Items[i].tag_id })
}
return tags;
},
align: 'center'
},
{
title: '课程',
valueType: 'select',
dataIndex: 'course_ids',
sorter: false,
hideInTable: false,
hideInForm: false,
hideInSearch: true,
fieldProps: {
mode: "multiple"
},
formItemProps: {
rules: [
{
required: true,
message: '请填选择课程',
},
]
},
render: (_dom: any, record: React.SetStateAction<TableListItem | undefined>) => [
<div>
{
record.course_names.length !== 0 ? record.course_names.map((i, index) => {
if (index + 1 === record.course_names.length) {
return i
} else {
return i + ''
}
}) : '--'
}
</div>
],
// renderText: (val: string) => `${val}`,
dependencies: ['tag_ids'],
request: async (arr) => {
// console.log('arr',arr)
// const {tags} = arr;
const { data: Items } = await queryCourseListByTag({ tag_ids: arr?.tag_ids?.toString() });
const courses = []
for (let i = 0; i < Items?.length; i++) {
courses.push({ label: Items[i]?.course_name, value: Items[i]?.course_id })
}
return courses;
},
align: 'center'
},
{
title: '学时',
dataIndex: 'course_minutes',
valueType: 'text',
sorter: false,
hideInTable: false,
hideInForm: true,
hideInSearch: true,
renderText: (val: string) => `${val}`,
align: 'center'
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
width: 200,
align: 'center',
render: (_dom: any, record: React.SetStateAction<TableListItem | undefined>) => [
<a
key="update"
style={{ marginRight: '1rem' }}
onClick={async() => {
const info= await getChapterAndCourseList({
chapter_id:record.chapter_id
})
console.log('info',info)
console.log('record',record)
setCurrentRow(record);
handleUpdateModalVisible(true);
}}
>
</a>,
<a key="remove" onClick={() => {
showConfirm(record)
}}>
</a>,
],
},
];
const params = useParams();
const { data: subjectInfo } = useRequest(() => {
return getSubjectInfo({ subject_id: params?.id });
});
const showConfirm = async (record) => {
confirm({
title: '确认删除章节吗?',
centered: true,
onOk() {
handleRemove([record]);
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
},
onCancel() {
},
});
};
const handleRemove = async (selectedRows: TableListItem[]) => {
const hide = message.loading('正在删除');
if (!selectedRows) return true;
try {
const { code, msg } = await deleteChapter({
key: selectedRows,
});
hide();
if (code === 2000) {
message.success('删除成功,即将刷新');
} else {
message.warning(msg);
}
return true;
} catch (error) {
hide();
message.error('删除失败,请重试');
return false;
}
};
useEffect(() => {
setSubjectId(params?.id)
}, [])
useEffect(() => {
// 编辑场景下需要使用formMapRef循环设置formData
formMapRef.current.forEach((formInstanceRef) => {
let fieldsValue;
const subjectValue = {
subject_name: subjectInfo?.subject_name,
subject_describe: subjectInfo?.subject_describe,
}
if (params?.id && subjectInfo?.attachment_json?.url) {
fieldsValue = {
...subjectValue,
upload: [
{
name: subjectInfo?.attachment_json?.name,
status: 'done',
url: `/dsideal_yy/html/${subjectInfo?.attachment_json?.url}`
}
]
}
} else {
// 无附件
fieldsValue = subjectValue;
}
formInstanceRef.current?.setFieldsValue(fieldsValue);
});
}, [subjectInfo]);
/** 获取列数据初始值 */
const getInitialValues = (cols: any[], vals: any) => {
const initialValues: any[] = [];
cols.forEach((column: { dataIndex: string }) => {
const key: any = column?.dataIndex || '';
initialValues.push({ ...column, initialValue: key ? vals[key] : '' });
});
return initialValues || [];
};
return (
<PageContainer content={''} extraContent={''}>
<ProCard className={styles.examinationrules}>
<StepsForm<{
name: string;
}>
formMapRef={formMapRef}
formRef={formRef}
onFinish={async (values) => {
message.success('提交成功');
}}
formProps={{
layout: "horizontal",
labelCol: { span: 8 },
wrapperCol: { span: 12 },
validateMessages: {
required: '此项为必填项',
},
}}
>
<StepsForm.StepForm<{
name: string;
}>
name="base"
title="培训主题基本信息"
stepProps={{
description: false,
}}
/*
request={async () => {
const data = await getSubjectInfo(5);
// return { data: bean }
}}*/
onFinish={async (value: any) => {
console.log(value, 'subjectId')
const url = value?.upload[0]?.url?.replace('/dsideal_yy/html/', '') || value?.upload[0]?.response?.url;
const info = await saveSubject({
...value,
subject_id: subjectId,
attachment_json: `{ "url": "${url}"}`
});
if (info.code !== 2000) {
message.warning(info.msg);
return false;
} else {
setSubjectId(info?.data.subject_id)
setSubjectIntro({ subject_id: info?.data.subject_id, subject_name: value?.subject_name, subject_describe: value?.subject_describe });
return true;
}
}}
>
<Row gutter={24}>
<Col lg={24} md={24} sm={24}>
<ProFormText
name="subject_name"
label="主题名称"
width="xl"
// tooltip="最长为 6 位汉字,需要与考生身份证一致"
placeholder="请输入名称"
rules={[{ required: true }]}
// value="锦书"
// disabled
/>
<ProFormRichEdit
name="subject_describe"
label="主题介绍"
width="xl"
placeholder="请输入介绍"
// rules={[{ required: true }]}
/>
<ProFormUploadButton
name="upload"
label="主题图片"
max={2}
fieldProps={{
accept: '.jpg,.jpeg,.git,.png',
name: 'file',
listType: 'picture-card',
maxCount: 1,
beforeUpload: (file) => {
//限制图片 格式、size、分辨率
const isJPG = file.type === 'image/jpeg';
const isJPEG = file.type === 'image/jpeg';
const isGIF = file.type === 'image/gif';
const isPNG = file.type === 'image/png';
if (!(isJPG || isJPEG || isGIF || isPNG)) {
message.error('只能上传JPG 、JPEG 、GIF、 PNG格式的图片~');
return false;
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('超过2M限制不允许上传~');
return false;
}
// 获取文件名
SetUploadFileName(file?.name);
// 获取最后一个.的位置
const index = file?.name.lastIndexOf(".");
// 获取后缀
SetUploadFileExt(file?.name.substr(index + 1));
},
data: {
name: uploadFileName,
chunk: 0,
chunks: 1,
key: `down/Syzx/${uuid?.substr(0, 2)}/${uuid}.${uploadFileExt}`
}
}}
rules={[{ required: true }]}
action="/dsideal_yy/res/plupload/"
extra=""
/>
</Col>
</Row>
</StepsForm.StepForm>
<StepsForm.StepForm<{
checkbox: string;
}>
name="object"
title="章节信息"
stepProps={{
description: false,
}}
onFinish={async (fileds) => {
console.log('setChapterList',chapterList)
if(chapterList.list.length!==0){
return true;
}else {
message.warning('章节列表不能为空!');
return false;
}
}}
>
<div style={{ margin: '0' }}>
<ProDescriptions
layout='horizontal'
column={1}
//actionRef={actionRef}
title="主题信息"
/*
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="subject_id" hideInDescriptions />
<ProDescriptions.Item dataIndex="subject_name" label="主题名称" valueType="text">{subjectIntro?.subject_name}</ProDescriptions.Item>
<ProDescriptions.Item dataIndex="subject_describe" label="主题介绍" valueType="text" maxLength="2">
<div dangerouslySetInnerHTML={{ __html: subjectIntro?.subject_describe }} />
</ProDescriptions.Item>
</ProDescriptions>
<ProTable<TableListItem, TableListPagination>
headerTitle={false}
actionRef={actionRef}
rowKey="chapter_id1"
options={false}
search={false}
params={subjectIntro}
toolBarRender={() => [
<Button
type="primary"
key="primary"
onClick={() => {
handleCreateModalVisible(true);
}}
>
<PlusOutlined />
</Button>,
]}
request={async (value) => {
console.log('subjectIntro',subjectIntro)
const { data } = await queryListChapterBySubject({
subject_id: subjectIntro.subject_id,
page_number: value?.current || 1,
page_size: value?.pageSize,
});
console.log('data',data.list)
setChapterList(data)
console.log('ChapterList',chapterList)
if (data.list.length !== 0) {
data.list.forEach((i) => {
console.log('i.tag_ids',i.tag_ids)
console.log('i.tag_names',i.tag_names)
i.course_ids = i.course_ids.split(',')
i.course_names = i.course_names.split(',');
if(i.tag_ids&&i.tag_ids!==null){
i.tag_ids = i.tag_ids.split(',')
}
if( i.tag_names){
i.tag_names = i.tag_names.split(',')
}
})
}
if (data.list.length !== 0) {
data.list.forEach((item) => {
if(item.tag_ids&&item.tag_ids!==null){
item.tag_ids = item.tag_ids.map(i => i * 1);
}
item.course_ids = item.course_ids.map(a => a * 1);
})
}
setList({
current: data?.page_number,
data: data?.list,
pageSize: data?.page_size,
success: true,
total: data?.total_row || 0,
})
return {
current: data?.page_number,
data: data?.list,
pageSize: data?.page_size,
success: true,
total: data?.total_row || 0,
};
}}
// dataSource={list}
columns={columns}
rowSelection={false}
/>
<Modal
title="新建章节"
//
width="60%"
visible={createModalVisible}
destroyOnClose
onCancel={() => {
handleCreateModalVisible(false);
}}
footer={null}
>
<BetaSchemaForm<DataItem>
layout="horizontal"
layoutType="Form"
labelCol={{ span: 8 }}
wrapperCol={{ span: 12 }}
onFinish={async (values: any) => {
// 表单处理
// console.log('columns:', columns);
console.log('values:新建', values);
const success = await handleAddChapter({
...values,
subject_id:subjectId,
});
if (success) {
handleCreateModalVisible(false);
actionRef.current?.reloadAndRest?.();
}
}}
submitter={{
render: (props, doms) => (
<Row>
<Col span={12} offset={8}>
<Space>{doms}</Space>
</Col>
</Row>
),
}}
// action = ''
title="新建"
columns={columns}
/>
</Modal>
<Modal
title="编辑章节"
//
width="60%"
visible={updateModalVisible}
destroyOnClose
onCancel={() => {
handleUpdateModalVisible(false);
}}
footer={null}
>
{currentRow?.chapter_id && (
<BetaSchemaForm<DataItem>
layout="horizontal"
layoutType="Form"
labelCol={{ span: 8 }}
wrapperCol={{ span: 12 }}
onFinish={async (values) => {
console.log('values编辑', values)
// console.log('currentRow', currentRow)
const success = await handleUpdateChapter({
...values,
subject_id: subjectId,
chapter_id: currentRow.chapter_id
});
if (success) {
handleUpdateModalVisible(false);
actionRef.current?.reloadAndRest?.();
}
}}
submitter={{
render: (props, doms) => (
<Row>
<Col span={12} offset={8}>
<Space>{doms}</Space>
</Col>
</Row>
),
}}
// action = ''
title="编辑"
columns={getInitialValues(columns, currentRow)}
/>
)}
</Modal>
</div>
</StepsForm.StepForm>
<StepsForm.StepForm
name="time"
title="完成"
stepProps={{
description: false,
}}
onFinish={async (values) => {
await commitSubject({ subject_id: subjectIntro?.subject_id });
// 跳转到指定路由
history.push('/course/subject');
return true;
}}
>
<ProDescriptions
layout='horizontal'
column={1}
//actionRef={actionRef}
title="主题信息"
/*
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="subject_id" hideInDescriptions />
<ProDescriptions.Item dataIndex="subject_name" label="主题名称" valueType="text">{subjectIntro?.subject_name}</ProDescriptions.Item>
<ProDescriptions.Item dataIndex="subject_describe" label="主题介绍" valueType="text" maxLength="2">
<div dangerouslySetInnerHTML={{ __html: subjectIntro?.subject_describe }} />
</ProDescriptions.Item>
</ProDescriptions>
<ProTable<TableListItem, TableListPagination>
headerTitle={false}
actionRef={actionRef1}
rowKey="chapter_id"
options={false}
search={false}
// params={subjectIntro}
toolBarRender={null}
request={async (value) => {
console.log('sssssssss',value)
const { data } = await queryListChapterBySubject({
subject_id: subjectIntro.subject_id,
page_number: value?.current || 1,
page_size: value?.pageSize,
});
if (data.list.length !== 0) {
data.list.forEach((i) => {
i.course_ids = i.course_ids.split(',')
i.course_names = i.course_names.split(',');
if(i.tag_ids&&i.tag_ids!==null){
i.tag_ids = i.tag_ids.split(',')
}
if( i.tag_names){
i.tag_names = i.tag_names.split(',')
}
})
}
if (data.list.length !== 0) {
data.list.forEach((item) => {
if(item.tag_ids&&item.tag_ids!==null){
item.tag_ids = item.tag_ids.map(i => i * 1);
}
item.course_ids = item.course_ids.map(a => a * 1);
})
}
return {
current: data?.page_number,
data: data?.list,
pageSize: data?.page_size,
success: true,
total: data?.total_row || 0,
};
}}
dataSource={list.data}
columns={columns}
rowSelection={false}
/>
</StepsForm.StepForm>
</StepsForm>
</ProCard>
</PageContainer >
);
};