提交 ef4b2f41 作者: ZhangLingKun

优化:课程分类、课程列表

上级 c92295a3
流水线 #7490 已通过 于阶段
in 1 分 9 秒
...@@ -43,7 +43,10 @@ ...@@ -43,7 +43,10 @@
"warn", "warn",
{ {
"endOfLine": "auto", "endOfLine": "auto",
"singleQuote": true "singleQuote": true,
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true
} }
], ],
"jsx-a11y/click-events-have-key-events": "off", "jsx-a11y/click-events-have-key-events": "off",
......
...@@ -2,64 +2,67 @@ import { InterFunction, InterItemFunction, InterListFunction } from '~/api/inter ...@@ -2,64 +2,67 @@ import { InterFunction, InterItemFunction, InterListFunction } from '~/api/inter
// V1.0.1课程视频列表 // V1.0.1课程视频列表
export type queryCurriculumInfoListType = InterListFunction< export type queryCurriculumInfoListType = InterListFunction<
{ {
courseAttribute?: number;
curriculumName?: string; curriculumName?: string;
flightSkillsId?: number; oneCourseId?: number;
categoriesId?: number; twoCourseId?: number;
licenseId?: number;
regionId?: number;
}, },
{ {
curriculumDesc: string;
curriculumName: string;
detailContent: null;
flightSkills: number;
flightSkillsName1: string;
flightSkillsName2: string;
free: number;
id: number; id: number;
price: null; oneCourseId: number;
supplierName: string; twoCourseId: number;
surfaceUrl: null; curriculumName: string;
curriculumDesc: string;
surfaceUrl: string;
videoUrl: string; videoUrl: string;
categoriesId: number; courseAttribute: number;
directoryName: null; requireAmout: number;
categoriesName: null; requireIntegral: number;
isHot: number;
detailContent: string;
createTime: string;
updateTime: string;
} }
>; >;
// V1.0.1新增课程 // V1.0.1新增课程
export type addCurriculumType = InterFunction< export type addCurriculumType = InterFunction<
{ {
categoriesId?: number; courseAttribute?: number;
categoriesName?: string; createTime?: string;
curriculumDesc?: string; curriculumDesc?: string;
curriculumName?: string; curriculumName?: string;
detailContent?: string; detailContent?: string;
directoryName?: string; id?: number;
flightSkills?: number; isHot?: number;
free?: number; oneCourseId?: number;
id?: number | null; requireAmout?: number;
price?: number; requireIntegral?: number;
supplierName?: string;
surfaceUrl?: string; surfaceUrl?: string;
twoCourseId?: number;
updateTime?: string;
videoUrl?: string; videoUrl?: string;
courseId?: number[];
}, },
NonNullable<unknown> NonNullable<unknown>
>; >;
// V1.0.1修改课程 // V1.0.1修改课程
export type updateCurriculumType = InterFunction< export type updateCurriculumType = InterFunction<
{ {
courseAttribute?: number;
createTime?: string;
curriculumDesc?: string; curriculumDesc?: string;
curriculumName?: string; curriculumName?: string;
detailContent?: string; detailContent?: string;
flightSkills?: number; id?: number;
flightSkillsName1?: string; isHot?: number;
flightSkillsName2?: string; oneCourseId?: number;
free?: number; requireAmout?: number;
id: number | null; requireIntegral?: number;
price?: number;
supplierName?: string;
surfaceUrl?: string; surfaceUrl?: string;
twoCourseId?: number;
updateTime?: string;
videoUrl?: string; videoUrl?: string;
courseId?: number[];
}, },
NonNullable<unknown> NonNullable<unknown>
>; >;
......
...@@ -111,3 +111,38 @@ export type updateOrgType = InterFunction< ...@@ -111,3 +111,38 @@ export type updateOrgType = InterFunction<
}, },
any any
>; >;
// 所有课程分类列表
export type selectCurriculumClassifyType = InterFunction<
NonNullable<unknown>,
{
classifyDesc: string;
classifyUrl: string;
createTime: string;
id: number;
name: string;
oneCourseId: number;
twoCourseId: number;
updateTime: string;
}[]
>;
// 新增课程分类
export type addCurriculumClassifyType = InterFunction<
{
classifyDesc?: string;
classifyUrl?: string;
createTime?: string;
id?: number;
name?: string;
oneCourseId?: number;
twoCourseId?: number;
updateTime?: string;
},
NonNullable<unknown>
>;
// 删除课程分类
export type removeCurriculumClassifyType = InterFunction<
{
id: number;
},
NonNullable<unknown>
>;
import { import {
addCurriculumClassifyType,
insertOrgType, insertOrgType,
licenceGradeListType, licenceGradeListType,
licenceModelsListType, licenceModelsListType,
licenceScaleList, licenceScaleList,
licenceTypeListType, licenceTypeListType,
listOrgPageType, listOrgPageType,
removeCurriculumClassifyType,
removeOrgType, removeOrgType,
selectCurriculumClassifyType,
updateOrgType, updateOrgType,
} from '~/api/interface/pilotTrainType'; } from '~/api/interface/pilotTrainType';
import axios from '~/api/request'; import axios from '~/api/request';
...@@ -35,4 +38,20 @@ export class PilotTrainAPI { ...@@ -35,4 +38,20 @@ export class PilotTrainAPI {
// 机构更新 // 机构更新
static updateOrg: updateOrgType = (data) => static updateOrg: updateOrgType = (data) =>
axios.post('/release/licence/background/updateOrg', data); axios.post('/release/licence/background/updateOrg', data);
// 所有课程分类列表
static selectCurriculumClassify: selectCurriculumClassifyType = (params) =>
axios.get('/release/curriculum/selectCurriculumClassify', { params });
// 新增课程分类
static addCurriculumClassify: addCurriculumClassifyType = (params) =>
axios.post('/release/curriculum/addCurriculumClassify', params);
// 修改课程分类
static updateCurriculumClassify: addCurriculumClassifyType = (params) =>
axios.post('/release/curriculum/updateCurriculumClassify', params);
// 删除课程分类
static removeCurriculumClassify: removeCurriculumClassifyType = (params) =>
axios.get('/release/curriculum/removeCurriculumClassify', { params });
} }
...@@ -33,6 +33,11 @@ export interface searchColumns { ...@@ -33,6 +33,11 @@ export interface searchColumns {
disable?: boolean; disable?: boolean;
onChange?: any; onChange?: any;
showTime?: { format: 'HH:mm:ss' }; showTime?: { format: 'HH:mm:ss' };
fieldNames?: {
label?: string;
value?: string;
children?: string;
};
} }
// 组件的类型 // 组件的类型
...@@ -52,9 +57,9 @@ interface propsType { ...@@ -52,9 +57,9 @@ interface propsType {
onRef?: any; onRef?: any;
} }
const Index: React.FC<propsType> = (props) => { const SearchBox: React.FC<propsType> = (props) => {
// 组件的默认值 // 组件的默认值
Index.defaultProps = { SearchBox.defaultProps = {
search: [], search: [],
searchData: null, searchData: null,
preFixBtn: null, preFixBtn: null,
...@@ -209,6 +214,7 @@ const Index: React.FC<propsType> = (props) => { ...@@ -209,6 +214,7 @@ const Index: React.FC<propsType> = (props) => {
changeOnSelect changeOnSelect
placeholder={item.placeholder} placeholder={item.placeholder}
options={item.options} options={item.options}
fieldNames={item.fieldNames}
style={{ width: item.width ? `${item.width}px` : '180px' }} style={{ width: item.width ? `${item.width}px` : '180px' }}
/> />
) : ( ) : (
...@@ -253,4 +259,4 @@ const Index: React.FC<propsType> = (props) => { ...@@ -253,4 +259,4 @@ const Index: React.FC<propsType> = (props) => {
); );
}; };
export default Index; export default SearchBox;
import React, { useEffect } from 'react';
import { Form, Input, message, Modal, ModalProps } from 'antd';
import { InterDataType, InterReqType } from '~/api/interface';
import {
addCurriculumClassifyType,
selectCurriculumClassifyType,
} from '~/api/interface/pilotTrainType';
import { PlusOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader';
import { PilotTrainAPI } from '~/api';
// 类型
type customProps = {
data?: InterDataType<selectCurriculumClassifyType>[0];
onCancel?: () => void;
isSub: boolean;
};
// 表单类型
type ReqType = InterReqType<addCurriculumClassifyType>;
const AddEditModalView: React.FC<ModalProps & customProps> = (props) => {
// 表单钩子
const [form] = Form.useForm<ReqType>();
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
// console.log('确认事件 --->', props?.data);
if (!props?.isSub) {
await handleSubmitMain(values);
} else {
await handleSubmitSecond(values);
}
})
.catch(async (err) => {
message.warning({
content: err.errorFields[0].errors[0],
});
});
};
// 主分类提交数据
const handleSubmitMain = async (values: ReqType) => {
const res = await PilotTrainAPI[
props?.data?.id ? 'updateCurriculumClassify' : 'addCurriculumClassify'
]({
...props?.data,
...values,
});
if (res && res.code === '200') {
handleCancel();
message.success('操作成功');
// console.log('提交数据 --->', res);
}
};
// 子分类提交数据
const handleSubmitSecond = async (values: ReqType) => {
const res = await PilotTrainAPI[
!props?.data?.twoCourseId ? 'addCurriculumClassify' : 'updateCurriculumClassify'
]({
...props?.data,
...values,
});
if (res && res.code === '200') {
handleCancel();
message.success('操作成功');
// console.log('提交数据 --->', res);
}
};
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
props.onCancel?.();
};
// 组件挂载
useEffect(() => {
if (!props.open || !props.data) return;
// 新增子分类时不执行
if (props?.isSub) return;
form.setFieldsValue(props.data);
}, [props]);
return (
<Modal {...props} destroyOnClose onOk={handleOk}>
<Form
name='addForm'
form={form}
labelAlign='right'
autoComplete='new-password'
labelCol={{ span: 4 }}
wrapperCol={{ span: 12 }}
style={{ marginBottom: '25px' }}
>
<Form.Item
label='分类名称'
name='name'
rules={[{ required: true, message: '请输入分类名称' }]}
>
<Input placeholder={'请输入分类名称'} maxLength={20} allowClear />
</Form.Item>
{!props?.isSub && (
<Form.Item
label='分类图标'
name='classifyUrl'
rules={[{ required: true, message: '请上传分类图标' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileSize={10}
fileType={['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp']}
onChange={(e) => form.setFieldValue('classifyUrl', e[0].url)}
defaultFileList={props?.data?.classifyUrl ? [{ url: props?.data?.classifyUrl }] : []}
>
<PlusOutlined />
</Uploader>
</Form.Item>
)}
<Form.Item
label='分类描述'
name='classifyDesc'
rules={[{ required: false, message: '请输入分类描述' }]}
>
<Input.TextArea placeholder={'请输入分类描述'} maxLength={50} allowClear showCount />
</Form.Item>
</Form>
</Modal>
);
};
export default AddEditModalView;
import React, { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, Image, message, Modal, Table } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import AddEditModalView from '~/pages/pilotTraining/courseCategory/comp/addEditModal';
import { InterDataType } from '~/api/interface';
import { selectCurriculumClassifyType } from '~/api/interface/pilotTrainType';
import { PilotTrainAPI } from '~/api';
// 列表类型
type ListType = Array<
InterDataType<selectCurriculumClassifyType>[0] & {
children?: InterDataType<selectCurriculumClassifyType>;
}
>;
const CourseCategoryView: React.FC = () => {
// 表格列表
const [tableData, setTableData] = useState<ListType>([]);
// 主分类是否打开变更弹窗
const [isMainShow, setIsMainShow] = useState<boolean>(false);
// 子分类是否打开变更弹窗
const [isSecondShow, setIsSecondShow] = useState<boolean>(false);
// 当前编辑的数据
const [editData, setEditData] = useState<ListType[0]>();
// 获取分类列表
const getTableList = async () => {
// 只需要修改这个地方的接口即可
const res = await PilotTrainAPI.selectCurriculumClassify();
if (res && res.code === '200') {
const list = res.result
?.filter((i) => !i.twoCourseId)
?.map((i) => {
const children = res.result?.filter(
(k) => k.oneCourseId === i.oneCourseId && k.twoCourseId,
);
return {
...i,
children: children?.length ? children : undefined,
};
});
// console.log('列表 --->', list, res.result);
setTableData(list);
}
};
// 删除分类
const handleDelete = (record: ListType[0]) => {
Modal.confirm({
title: '提示',
content: '是否确认删除该分类?',
onOk: async () => {
const res = await PilotTrainAPI.removeCurriculumClassify({ id: record?.id });
if (res && res.code === '200') {
await getTableList();
message.success('操作成功');
}
},
});
};
// 页面挂载
useEffect(() => {
getTableList().then();
}, []);
// 表格列
const columns: ColumnsType<ListType[0]> = [
{
title: '序号',
dataIndex: 'id',
align: 'center',
render: (_value, _record, index) => index + 1,
},
{
title: '分类名称',
dataIndex: 'name',
align: 'center',
},
{
title: '图片',
dataIndex: 'classifyUrl',
align: 'center',
render: (value, record) =>
!record?.twoCourseId && <Image width={35} height={35} src={value} />,
},
{
title: '描述',
dataIndex: 'classifyDesc',
align: 'center',
ellipsis: true,
width: '200px',
},
{
title: '创建时间',
dataIndex: 'createTime',
align: 'center',
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
render: (_value, record) => (
<>
{!record?.twoCourseId && (
<Button
type={'link'}
onClick={() => {
setEditData(record);
setIsSecondShow(true);
}}
>
新增子分类
</Button>
)}
<Button
type={'link'}
onClick={() => {
setEditData(record);
if (!record?.twoCourseId) {
setIsMainShow(true);
} else {
setIsSecondShow(true);
}
}}
>
编辑
</Button>
<Button type={'link'} danger onClick={() => handleDelete(record)}>
删除
</Button>
</>
),
},
];
return (
<>
<SearchBox
preFixBtn={
<Button icon={<PlusOutlined />} type='primary' onClick={() => setIsMainShow(true)}>
新增分类
</Button>
}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
bordered
// scroll={{ x: 1200 }}
pagination={{
// total: pagination.total,
// pageSize: pagination.pageSize,
// current: pagination.current,
// showSizeChanger: true,
// showQuickJumper: true,
// onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
{/*主分类添加编辑*/}
<AddEditModalView
open={isMainShow}
title={editData?.id ? '编辑分类' : '新增分类'}
data={editData}
isSub={false}
onCancel={() => {
setEditData(undefined);
setIsMainShow(false);
getTableList().then();
}}
/>
{/*子分类添加编辑*/}
<AddEditModalView
open={isSecondShow}
title={editData?.twoCourseId ? '编辑子分类' : '新增子分类'}
data={editData}
isSub={true}
onCancel={() => {
setEditData(undefined);
setIsSecondShow(false);
getTableList().then();
}}
/>
</>
);
};
export default CourseCategoryView;
import { InterListType, InterReqType } from '~/api/interface'; import { InterDataType, InterListType, InterReqType } from '~/api/interface';
import React, { useEffect } from 'react'; import React, { useEffect, useState } from 'react';
import { Cascader, Form, Input, message, Modal } from 'antd'; import { Cascader, Form, Input, InputNumber, message, Modal, Radio } from 'antd';
import { Uploader } from '~/components/uploader'; import { Uploader } from '~/components/uploader';
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined } from '@ant-design/icons';
import { MallManageAPI } from '~/api'; import { MallManageAPI, PilotTrainAPI } from '~/api';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType'; import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import RichText from '~/components/richText'; import RichText from '~/components/richText';
import { selectCurriculumClassifyType } from '~/api/interface/pilotTrainType';
// 表格数据类型 // 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>; type TableType = InterListType<queryCurriculumInfoListType>;
// 请求数据的类型 // 请求数据的类型
type ReqType = InterReqType<addCurriculumType>; type ReqType = InterReqType<addCurriculumType>;
// 列表类型
type ListType = Array<
InterDataType<selectCurriculumClassifyType>[0] & {
children?: InterDataType<selectCurriculumClassifyType>;
}
>;
// 课程类型列表
const courseAttributeList = [
{ label: '免费', value: 0 },
{ label: '积分兑换', value: 1 },
{ label: '付费', value: 2 },
];
// 传参类型 // 传参类型
interface propType { interface propType {
...@@ -26,22 +39,16 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -26,22 +39,16 @@ const AddEditModal: React.FC<propType> = (props) => {
}; };
// 参数 // 参数
const { title, open, closed, data } = props; const { title, open, closed, data } = props;
// 课程类型列表 // 分类列表
const [curriculumSkillList, setCurriculumSkillList] = React.useState< const [curriculumClassifyList, setCurriculumClassifyList] = useState<ListType>();
{ // 当前选择的课程类型
value: number; const [courseAttributeSelect, setCourseAttributeSelect] = useState<number>(0);
label: string;
children?: Array<{
value: number;
label: string;
}>;
}[]
>([]);
// 表单钩子 // 表单钩子
const [form] = Form.useForm<ReqType>(); const [form] = Form.useForm<ReqType>();
// 关闭弹窗 // 关闭弹窗
const handleCancel = () => { const handleCancel = () => {
form.resetFields(); form.resetFields();
setCourseAttributeSelect(0);
closed(); closed();
}; };
// 确认事件 // 确认事件
...@@ -62,52 +69,54 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -62,52 +69,54 @@ const AddEditModal: React.FC<propType> = (props) => {
}; };
// 提交事件 // 提交事件
const handleSubmit = async (values: ReqType) => { const handleSubmit = async (values: ReqType) => {
const oneCourseId = curriculumClassifyList?.find((i) => i.id === values?.courseId?.[0]);
const twoCourseId = oneCourseId?.children?.find((i) => i.id === values?.courseId?.[1]);
const res = await MallManageAPI[data?.id ? 'updateCurriculum' : 'addCurriculum']({ const res = await MallManageAPI[data?.id ? 'updateCurriculum' : 'addCurriculum']({
...values, ...values,
flightSkills: Number((values?.flightSkills as unknown as number[])?.at(-1)), oneCourseId: Number(oneCourseId?.oneCourseId),
categoriesId: Number((values?.flightSkills as unknown as number[])?.at(-1)), twoCourseId: Number(twoCourseId?.twoCourseId),
id: data?.id ? data?.id : null, id: data?.id ? data?.id : undefined,
}); });
if (res && res.code === '200') { if (res && res.code === '200') {
message.success('操作成功'); message.success('操作成功');
handleCancel(); handleCancel();
} }
}; };
// 获取课程类型 // 获取课程分类
const getCurriculumSkillList = async () => { const getCurriculumClassify = async () => {
const res = await MallManageAPI.queryCategoryInfoByType({ const res = await PilotTrainAPI.selectCurriculumClassify();
type: 3,
});
if (res && res.code === '200') { if (res && res.code === '200') {
const arr = const list = res.result
res.result ?.filter((i) => !i.twoCourseId)
?.filter((i) => i.categoriesInfoListDTO) ?.map((i) => {
.map((i) => ({ const children = res.result?.filter(
label: i.name, (k) => k.oneCourseId === i.oneCourseId && k.twoCourseId,
value: i.directoryId, );
children: i.categoriesInfoListDTO?.map((j) => ({ label: j.name, value: j.id })), return {
})) || []; ...i,
setCurriculumSkillList(arr); children: children?.length ? children : undefined,
};
});
setCurriculumClassifyList(list);
// 回显数据 // 回显数据
// 加载出数据再操作 // 加载出数据再操作
if (!data) return; if (!data) return;
// console.log(data); // console.log(data);
// 反向找数据回显 const oneCourseId = list?.find((i) => i.oneCourseId === data?.oneCourseId);
const flightSkillsName1 = arr?.find((i) => const twoCourseId = oneCourseId?.children?.find((i) => i.twoCourseId === data?.twoCourseId);
i.children?.find((j) => j.value === data?.categoriesId),
);
// 回显数据 // 回显数据
form.setFieldsValue({ form.setFieldsValue({
...data, ...data,
flightSkills: [flightSkillsName1?.value, data?.categoriesId], courseId: [oneCourseId?.id, twoCourseId?.id],
}); });
setCourseAttributeSelect(data?.courseAttribute || 0);
} }
}; };
// componentDidMount // componentDidMount
useEffect(() => { useEffect(() => {
if (!open) return; if (!open) return;
// 获取课程类型 // 获取课程类型
getCurriculumSkillList().then(); getCurriculumClassify().then();
}, [open]); }, [open]);
return ( return (
<Modal <Modal
...@@ -121,17 +130,22 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -121,17 +130,22 @@ const AddEditModal: React.FC<propType> = (props) => {
<Form <Form
name='addForm' name='addForm'
form={form} form={form}
labelAlign='right' labelAlign='left'
autoComplete='new-password' autoComplete='new-password'
labelCol={{ span: 3 }} labelCol={{ span: 3 }}
wrapperCol={{ span: 10 }} wrapperCol={{ span: 10 }}
> >
<Form.Item <Form.Item
label='课程类型' label='课程类型'
name='flightSkills' name='courseId'
rules={[{ required: true, message: '请选择课程类型' }]} rules={[{ required: true, message: '请选择课程类型' }]}
> >
<Cascader placeholder={'请选择课程类型'} options={curriculumSkillList} allowClear /> <Cascader
placeholder={'请选择课程类型'}
options={curriculumClassifyList}
allowClear
fieldNames={{ label: 'name', value: 'id' }}
/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label='课程名称' label='课程名称'
...@@ -153,6 +167,7 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -153,6 +167,7 @@ const AddEditModal: React.FC<propType> = (props) => {
rules={[{ required: true, message: '请上传课程封面' }]} rules={[{ required: true, message: '请上传课程封面' }]}
style={{ marginBottom: '-40px' }} style={{ marginBottom: '-40px' }}
> >
<div>
<Uploader <Uploader
listType={'picture-card'} listType={'picture-card'}
fileUpload fileUpload
...@@ -169,6 +184,7 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -169,6 +184,7 @@ const AddEditModal: React.FC<propType> = (props) => {
<br /> <br />
建议尺寸750*420或比例16:9,小于5M的 JPG、PNG格式图片 建议尺寸750*420或比例16:9,小于5M的 JPG、PNG格式图片
</div> </div>
</div>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label='课程上传' label='课程上传'
...@@ -176,6 +192,7 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -176,6 +192,7 @@ const AddEditModal: React.FC<propType> = (props) => {
rules={[{ required: false, message: '请上传课程上传' }]} rules={[{ required: false, message: '请上传课程上传' }]}
style={{ marginBottom: '-40px' }} style={{ marginBottom: '-40px' }}
> >
<div>
<Uploader <Uploader
listType={'picture-card'} listType={'picture-card'}
fileUpload fileUpload
...@@ -192,6 +209,55 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -192,6 +209,55 @@ const AddEditModal: React.FC<propType> = (props) => {
<br /> <br />
支持mp4,avi,wmv,mov,flv, rmvb,3gp,m4v,mkv格式; 文件最大不超过1G。 支持mp4,avi,wmv,mov,flv, rmvb,3gp,m4v,mkv格式; 文件最大不超过1G。
</div> </div>
</div>
</Form.Item>
<Form.Item
label='课程属性'
name='courseAttribute'
rules={[{ required: true, message: '请选择课程属性' }]}
wrapperCol={{ span: 20 }}
initialValue={0}
>
<Radio.Group
options={courseAttributeList}
onChange={(e) => setCourseAttributeSelect(e?.target?.value)}
/>
</Form.Item>
{courseAttributeSelect === 1 && (
<Form.Item
label='课程积分'
name='requireIntegral'
rules={[{ required: true, message: '请输入课程积分' }]}
wrapperCol={{ span: 20 }}
initialValue={1}
>
<InputNumber min={1} max={999999} precision={2} />
</Form.Item>
)}
{courseAttributeSelect === 2 && (
<Form.Item
label='课程金额'
name='requireAmout'
rules={[{ required: true, message: '请输入课程金额' }]}
wrapperCol={{ span: 20 }}
initialValue={1}
>
<InputNumber min={1} max={999999} precision={2} />
</Form.Item>
)}
<Form.Item
label='设置为热门课程'
name='isHot'
rules={[{ required: true, message: '请选择是否设置为热门课程' }]}
labelCol={{ span: 5 }}
initialValue={0}
>
<Radio.Group
options={[
{ value: 0, label: '否' },
{ value: 1, label: '是' },
]}
/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label='课程详情' label='课程详情'
...@@ -200,7 +266,7 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -200,7 +266,7 @@ const AddEditModal: React.FC<propType> = (props) => {
wrapperCol={{ span: 20 }} wrapperCol={{ span: 20 }}
> >
<RichText <RichText
richTextContent={form.getFieldValue('detailContent')} richTextContent={form.getFieldValue('detailContent') || data?.detailContent}
onChange={(e) => form.setFieldValue('detailContent', e)} onChange={(e) => form.setFieldValue('detailContent', e)}
height={250} height={250}
/> />
......
...@@ -3,31 +3,34 @@ import SearchBox from '~/components/search-box'; ...@@ -3,31 +3,34 @@ import SearchBox from '~/components/search-box';
import { Button, Table, Image, message, Modal } from 'antd'; import { Button, Table, Image, message, Modal } from 'antd';
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined } from '@ant-design/icons';
import { queryCurriculumInfoListType } from '~/api/interface/mallManageType'; import { queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import { InterListType, InterReqType } from '~/api/interface'; import { InterDataType, InterListType, InterReqType } from '~/api/interface';
import { MallManageAPI } from '~/api'; import { MallManageAPI, PilotTrainAPI } from '~/api';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
import AddEditModal from './comp/addEditModal'; import AddEditModal from './comp/addEditModal';
import { selectCurriculumClassifyType } from '~/api/interface/pilotTrainType';
// 表格数据类型 // 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>; type TableType = InterListType<queryCurriculumInfoListType>;
// 请求数据的类型 // 请求数据的类型
type ReqType = InterReqType<queryCurriculumInfoListType>; type ReqType = InterReqType<queryCurriculumInfoListType>;
// 列表类型
type ListType = Array<
InterDataType<selectCurriculumClassifyType>[0] & {
children?: InterDataType<selectCurriculumClassifyType>;
}
>;
// 课程类型列表
const courseAttributeList = [
{ label: '免费', value: 0 },
{ label: '积分兑换', value: 1 },
{ label: '付费', value: 2 },
];
// 搜索表单的数据 // 搜索表单的数据
let query: ReqType = {}; let query: ReqType = {};
const CourseManageView = () => { const CourseManageView = () => {
const { confirm } = Modal; // 分类列表
// 课程类型列表 const [curriculumClassifyList, setCurriculumClassifyList] = useState<ListType>();
const [curriculumSkillList, setCurriculumSkillList] = useState<
{
value: number;
label: string;
children?: Array<{
value: number;
label: string;
}>;
}[]
>([]);
// 是否打开变更弹窗 // 是否打开变更弹窗
const [isAddEditVisModal, setIsAddEditVisModal] = useState<boolean>(false); const [isAddEditVisModal, setIsAddEditVisModal] = useState<boolean>(false);
// 表格分页配置 // 表格分页配置
...@@ -74,7 +77,7 @@ const CourseManageView = () => { ...@@ -74,7 +77,7 @@ const CourseManageView = () => {
}; };
// 删除数据 // 删除数据
const handleDelete = (value: TableType[0]) => { const handleDelete = (value: TableType[0]) => {
confirm({ Modal.confirm({
title: '提示', title: '提示',
content: '是否删除该课程?', content: '是否删除该课程?',
onOk: async () => { onOk: async () => {
...@@ -89,23 +92,48 @@ const CourseManageView = () => { ...@@ -89,23 +92,48 @@ const CourseManageView = () => {
}, },
}); });
}; };
// 获取课程类型 // 获取课程分类
const getCurriculumSkillList = async () => { const getCurriculumClassify = async () => {
const res = await MallManageAPI.queryCategoryInfoByType({ const res = await PilotTrainAPI.selectCurriculumClassify();
type: 3,
});
if (res && res.code === '200') { if (res && res.code === '200') {
setCurriculumSkillList( const list = res.result
res.result ?.filter((i) => !i.twoCourseId)
?.filter((i) => i.categoriesInfoListDTO) ?.map((i) => {
.map((i) => ({ const children = res.result?.filter(
label: i.name, (k) => k.oneCourseId === i.oneCourseId && k.twoCourseId,
value: i.directoryId,
children: i.categoriesInfoListDTO?.map((j) => ({ label: j.name, value: j.id })),
})) || [],
); );
return {
...i,
children: children?.length ? children : undefined,
};
});
setCurriculumClassifyList(list);
} }
}; };
// 搜索数据
const handleSearch = (value: ReqType & { courseId: number[] }) => {
const oneCourseId = curriculumClassifyList?.find((i) => i.id === value?.courseId?.[0]);
const twoCourseId = oneCourseId?.children?.find((i) => i.id === value?.courseId?.[1]);
onFinish({
...value,
oneCourseId: oneCourseId?.oneCourseId,
twoCourseId: twoCourseId?.twoCourseId,
});
};
// 获取当前课程的类型
const getCurriculumType = (value: TableType[0]) => {
const oneCourseId = curriculumClassifyList?.find((i) => i.oneCourseId === value?.oneCourseId);
const twoCourseId = oneCourseId?.children?.find((i) => i.twoCourseId === value?.twoCourseId);
return twoCourseId?.name ? `${oneCourseId?.name}/${twoCourseId?.name}` : `${oneCourseId?.name}`;
};
// componentDidMount
useEffect(() => {
query = {};
(async () => {
await getCurriculumClassify();
await getTableList();
})();
}, []);
// 表格结构 // 表格结构
const columns: ColumnsType<TableType[0]> = [ const columns: ColumnsType<TableType[0]> = [
{ {
...@@ -116,18 +144,13 @@ const CourseManageView = () => { ...@@ -116,18 +144,13 @@ const CourseManageView = () => {
}, },
{ {
title: '课程类型', title: '课程类型',
dataIndex: 'categoriesId', dataIndex: 'oneCourseId',
align: 'center', align: 'center',
width: '150px', width: '150px',
render: (text) => { render: (_text, record) => getCurriculumType(record),
// 反向找数据回显
const item = curriculumSkillList?.find((i) => i.children?.find((j) => j.value === text));
const childrenItem = item?.children?.find((i) => i.value === text);
return `${item?.label}/${childrenItem?.label}`;
},
}, },
{ {
title: '课程类型', title: '课程描述',
dataIndex: 'curriculumDesc', dataIndex: 'curriculumDesc',
align: 'center', align: 'center',
width: '150px', width: '150px',
...@@ -141,7 +164,7 @@ const CourseManageView = () => { ...@@ -141,7 +164,7 @@ const CourseManageView = () => {
render: (text, record) => ( render: (text, record) => (
<> <>
<Image <Image
src={text ? text : `${record.videoUrl}?x-oss-process=video/snapshot,t_1000,m_fast`} src={text ? text : `${record?.videoUrl}?x-oss-process=video/snapshot,t_1000,m_fast`}
alt={'封面图'} alt={'封面图'}
style={{ width: '35px', height: '35px' }} style={{ width: '35px', height: '35px' }}
/> />
...@@ -149,6 +172,20 @@ const CourseManageView = () => { ...@@ -149,6 +172,20 @@ const CourseManageView = () => {
), ),
}, },
{ {
title: '是否热门',
dataIndex: 'isHot',
align: 'center',
width: '50px',
render: (text) => (text === 1 ? '是' : '否'),
},
{
title: '课程属性',
dataIndex: 'courseAttribute',
align: 'center',
width: '50px',
render: (text) => courseAttributeList?.find((i) => i.value === text)?.label || '免费',
},
{
title: '操作', title: '操作',
dataIndex: 'action', dataIndex: 'action',
align: 'center', align: 'center',
...@@ -172,14 +209,6 @@ const CourseManageView = () => { ...@@ -172,14 +209,6 @@ const CourseManageView = () => {
), ),
}, },
]; ];
// componentDidMount
useEffect(() => {
query = {};
(async () => {
await getCurriculumSkillList();
await getTableList();
})();
}, []);
return ( return (
<> <>
<SearchBox <SearchBox
...@@ -192,18 +221,21 @@ const CourseManageView = () => { ...@@ -192,18 +221,21 @@ const CourseManageView = () => {
}, },
{ {
label: '课程类型', label: '课程类型',
name: 'categoriesId', name: 'courseId',
type: 'Cascader', type: 'Cascader',
placeholder: '请选择课程类型', placeholder: '请选择课程类型',
options: curriculumSkillList, options: curriculumClassifyList,
fieldNames: { label: 'name', value: 'id' },
},
{
label: '课程属性',
name: 'courseAttribute',
type: 'Select',
placeholder: '请选择课程属性',
options: courseAttributeList,
}, },
]} ]}
searchData={(e: any) => { searchData={handleSearch}
onFinish({
...e,
categoriesId: e.categoriesId?.at(-1),
});
}}
child={ child={
<> <>
<Button <Button
...@@ -223,7 +255,8 @@ const CourseManageView = () => { ...@@ -223,7 +255,8 @@ const CourseManageView = () => {
dataSource={tableData} dataSource={tableData}
columns={columns} columns={columns}
rowKey='id' rowKey='id'
// scroll={{ x: 1200 }} bordered
scroll={{ x: 1200 }}
pagination={{ pagination={{
total: pagination.total, total: pagination.total,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
......
...@@ -131,7 +131,7 @@ const MallCategoryListView = React.lazy(() => import('~/pages/categoryManage/mal ...@@ -131,7 +131,7 @@ const MallCategoryListView = React.lazy(() => import('~/pages/categoryManage/mal
const ServiceCategoryListView = React.lazy( const ServiceCategoryListView = React.lazy(
() => import('~/pages/categoryManage/serviceCategoryList'), () => import('~/pages/categoryManage/serviceCategoryList'),
); //服务分类 ); //服务分类
const CategoryManage = React.lazy(() => import('~/pages/categoryManage/category')); // const CategoryManage = React.lazy(() => import('~/pages/categoryManage/category'));
// const CategoryDetail = React.lazy(() => import('~/pages/categoryManage/category/detail')); // const CategoryDetail = React.lazy(() => import('~/pages/categoryManage/category/detail'));
// 目录管理 // 目录管理
// const DirectoryManage = React.lazy(() => import('~/pages/categoryManage/directoryManage')); // const DirectoryManage = React.lazy(() => import('~/pages/categoryManage/directoryManage'));
...@@ -169,6 +169,7 @@ import ActivityListView from '~/pages/activityManage/activityList'; ...@@ -169,6 +169,7 @@ import ActivityListView from '~/pages/activityManage/activityList';
import ActivityListDetailView from '~/pages/activityManage/activityList/detail'; import ActivityListDetailView from '~/pages/activityManage/activityList/detail';
import FlyerTeamView from '~/pages/flyerManage/flyerTeam'; import FlyerTeamView from '~/pages/flyerManage/flyerTeam';
import CompanyMemberView from '~/pages/systemManage/companyManage/companyMember'; import CompanyMemberView from '~/pages/systemManage/companyManage/companyMember';
import CourseCategoryView from '~/pages/pilotTraining/courseCategory';
const AddressManageView = React.lazy(() => import('~/pages/systemManage/addressManage')); const AddressManageView = React.lazy(() => import('~/pages/systemManage/addressManage'));
// const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表 // const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表
...@@ -789,8 +790,8 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -789,8 +790,8 @@ export const routerList: Array<RouteObjectType> = [
}, },
children: [ children: [
{ {
path: '/pilotTraining/jobServicesCategory/3', path: '/pilotTraining/courseCategory',
element: withLoadingComponent(<CategoryManage />), element: withLoadingComponent(<CourseCategoryView />),
errorElement: <ErrorPage />, errorElement: <ErrorPage />,
meta: { meta: {
id: 730, id: 730,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论