提交 6579d6bf 作者: ZhangLingKun

功能:课程管理列表

上级 22f1d493
...@@ -9,6 +9,7 @@ import { MakeManageAPI } from './modules/makeManage'; ...@@ -9,6 +9,7 @@ import { MakeManageAPI } from './modules/makeManage';
import { CategoryManageAPI } from './modules/categoryManage'; import { CategoryManageAPI } from './modules/categoryManage';
import { SystemManageAPI } from './modules/systemManage'; import { SystemManageAPI } from './modules/systemManage';
import { CustomManageAPI } from './modules/customManage'; import { CustomManageAPI } from './modules/customManage';
import { MallManageAPI } from './modules/mallManage';
export { export {
CommonAPI, CommonAPI,
...@@ -22,4 +23,5 @@ export { ...@@ -22,4 +23,5 @@ export {
CategoryManageAPI, CategoryManageAPI,
SystemManageAPI, SystemManageAPI,
CustomManageAPI, CustomManageAPI,
MallManageAPI,
}; };
import { InterFunction, InterListFunction } from '~/api/interface';
// V1.0.1课程视频列表
export type queryCurriculumInfoListType = InterListFunction<
{
curriculumName?: string;
flightSkillsId?: number;
licenseId?: number;
regionId?: number;
},
{
curriculumDesc: string;
curriculumName: string;
detailContent: null;
flightSkills: number;
flightSkillsName1: string;
flightSkillsName2: string;
free: number;
id: number;
price: null;
supplierName: string;
surfaceUrl: null;
videoUrl: string;
}
>;
// V1.0.1新增课程
export type addCurriculumType = InterFunction<
{
curriculumDesc?: string;
curriculumName: string;
detailContent?: string;
flightSkills: number;
flightSkillsName1: string;
flightSkillsName2: string;
free: number;
id: number;
price: number;
supplierName: string;
surfaceUrl: string;
videoUrl: string;
},
NonNullable<unknown>
>;
import axios from '~/api/request';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
export class MallManageAPI {
// V1.0.1课程视频列表
static queryCurriculumInfoList: queryCurriculumInfoListType = (params) =>
axios.post('/release/curriculum/queryCurriculumInfoList', params);
// V1.0.1新增课程
static addCurriculum: addCurriculumType = (params) =>
axios.post('/release/curriculum/addCurriculum', params);
}
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
// min-width: 200px; // min-width: 200px;
//} //}
.ant-form-item { .ant-form-item {
margin-inline-end: 20px; margin-inline-end: 15px;
} }
.ant-row { .ant-row {
......
import { Form, Input, Button, Select, DatePicker } from 'antd'; import { Form, Input, Button, Select, DatePicker, TreeSelect, Cascader } from 'antd';
import moment from 'dayjs'; import moment from 'dayjs';
import { SearchOutlined, ReloadOutlined, ExportOutlined } from '@ant-design/icons'; import { SearchOutlined, ReloadOutlined, ExportOutlined } from '@ant-design/icons';
import React, { useImperativeHandle } from 'react'; import React, { useImperativeHandle } from 'react';
...@@ -8,7 +8,7 @@ const { RangePicker } = DatePicker; ...@@ -8,7 +8,7 @@ const { RangePicker } = DatePicker;
// 搜索列表的类型 // 搜索列表的类型
export interface searchColumns { export interface searchColumns {
type: 'input' | 'select' | 'rangePicker' | 'DatePicker' | 'Select'; type: 'input' | 'select' | 'rangePicker' | 'DatePicker' | 'Select' | 'TreeSelect' | 'Cascader';
label?: string; label?: string;
name: string; name: string;
placeholder: string; placeholder: string;
...@@ -155,6 +155,33 @@ const Index: React.FC<propsType> = (props) => { ...@@ -155,6 +155,33 @@ const Index: React.FC<propsType> = (props) => {
showTime={item.showTime} showTime={item.showTime}
style={{ width: item.width ? `${item.width}px` : '180px' }} style={{ width: item.width ? `${item.width}px` : '180px' }}
/> />
) : item.type === 'TreeSelect' ? (
<TreeSelect
allowClear
treeDefaultExpandAll
placeholder={item.placeholder}
treeData={item.options}
fieldNames={{
label: 'name',
value: 'id',
children: 'childNodes',
}}
popupClassName='head-search-treeSelect'
style={{ width: item.width ? `${item.width}px` : '180px' }}
/>
) : item.type === 'Cascader' ? (
<Cascader
allowClear
changeOnSelect
placeholder={item.placeholder}
options={item.options}
fieldNames={{
label: 'name',
value: 'id',
children: 'childNodes',
}}
style={{ width: item.width ? `${item.width}px` : '180px' }}
/>
) : ( ) : (
'' ''
)} )}
......
import { InterListType, InterReqType } from '~/api/interface';
import React, { useEffect } from 'react';
import { Col, Form, Input, message, Modal, Radio, Row, Select } from 'antd';
import { Uploader } from '~/components/uploader';
import { PlusOutlined } from '@ant-design/icons';
import { OrderManageAPI } from '~/api';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
// 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>;
// 请求数据的类型
type ReqType = InterReqType<addCurriculumType>;
// 传参类型
interface propType {
title: string;
open: boolean;
closed: any;
data?: TableType[0];
}
const AddEditModal: React.FC<propType> = (props) => {
AddEditModal.defaultProps = {
data: undefined,
};
// 参数
const { title, open, closed, data } = props;
// 物流列表
const [expressList, setExpressList] = React.useState<{ label: string; value: string }[]>([]);
// 表单钩子
const [form] = Form.useForm<ReqType>();
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
closed();
};
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
// console.log('确认事件 --->', values);
await handleSubmit(values);
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await OrderManageAPI.sendOrderWare({
...values,
orderInfoId: Number(data?.id),
});
if (res && res.code === '200') {
message.success('操作成功');
handleCancel();
}
};
// 获取物流信息
const getListExpressInfo = async () => {
const res = await OrderManageAPI.listExpressInfo({});
if (res && res.code === '200') {
setExpressList(res.result.map((item) => ({ label: item.exName, value: item.exCode })));
// console.log(res);
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
getListExpressInfo().then();
// console.log('data --->', data);
}, [open]);
return (
<Modal
open={open}
title={title}
onCancel={handleCancel}
onOk={handleOk}
destroyOnClose
width={600}
>
<Form
name='addForm'
form={form}
labelAlign='right'
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
autoComplete='new-password'
>
<Form.Item label='收货地址' labelCol={{ span: 4 }}>
{data?.receipt?.takeName} {data?.receipt?.takePhone} {data?.receipt?.detailAddress}
</Form.Item>
<Form.Item label='发货方式' labelCol={{ span: 4 }}>
物流发货
</Form.Item>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='物流单号'
name='sendExNo'
rules={[{ required: true, message: '请输入物流单号' }]}
>
<Input placeholder={'请输入物流单号'} maxLength={20} allowClear />
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='物流公司'
name='sendExCode'
rules={[{ required: true, message: '请选择物流公司' }]}
>
<Select placeholder={'请选择物流公司'} options={expressList} allowClear />
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='归还联系人'
name='renName'
rules={[{ required: true, message: '请输入归还联系人' }]}
>
<Input placeholder={'请输入归还联系人'} maxLength={20} allowClear />
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='归还电话'
name='renPhone'
rules={[
{ required: true, message: '请输入归还联系人电话' },
// 校验手机号
() => ({
validator(_, value) {
if (!value || /^1[3-9]\d{9}$/.test(value)) {
return Promise.resolve();
}
return Promise.reject('请输入正确的手机号');
},
}),
]}
>
<Input
placeholder={'请输入归还联系人电话'}
maxLength={20}
allowClear
type={'number'}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='归还地址'
name='renAddress'
rules={[{ required: true, message: '请输入归还地址' }]}
>
<Input placeholder={'请输入归还地址'} maxLength={20} allowClear />
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='质检照片'
name='imgs'
rules={[{ required: true, message: '请上传质检照片' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={3}
onChange={(e) => {
form.setFieldValue(
'imgs',
e.map((item) => item.url),
);
}}
>
<PlusOutlined />
</Uploader>
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='质检视频'
name='videoUrl'
rules={[{ required: true, message: '请上传质检视频' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileType={['video/mp4', 'video/avi', 'video/wmv', 'video/rmvb']}
fileSize={10}
onChange={(e) => {
form.setFieldValue('videoUrl', e[0].url);
}}
>
<PlusOutlined />
</Uploader>
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='设备状态'
name='vcuSatus'
rules={[{ required: true, message: '请选择设备状态' }]}
initialValue={0}
>
<Radio.Group
options={[
{ label: '正常', value: 0 },
{ label: '故障', value: 1 },
]}
onChange={(e) => {
form.setFieldValue('vcuSatus', e.target.value);
}}
/>
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='操作密码'
name='authPwd'
rules={[{ required: true, message: '请输入操作密码' }]}
>
<Input.Password
placeholder={'请输入操作密码'}
maxLength={20}
allowClear
autoComplete='new-password'
/>
</Form.Item>
</Col>
</Row>
</Form>
</Modal>
);
};
export default AddEditModal;
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, Table, Image } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import { InterListType, InterReqType } from '~/api/interface';
import { MallManageAPI } from '~/api';
import { ColumnsType } from 'antd/es/table';
import AddEditModal from './comp/addEditModal';
// 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>;
// 请求数据的类型
type ReqType = InterReqType<queryCurriculumInfoListType>;
// 搜索表单的数据
let query: ReqType = {};
const CourseManageView = () => {
// 是否打开变更弹窗
const [isAddEditVisModal, setIsAddEditVisModal] = useState<boolean>(false);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 需要编辑的数据
const [editData, setEditData] = useState<TableType[0]>();
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await MallManageAPI.queryCurriculumInfoList({
pageNo: pagination.current,
pageSize: pagination.pageSize,
...value,
...query,
});
if (res && res.code === '200') {
const { list, pageNo, totalCount, pageSize, totalPage } = res.result; // 解构
setPagination({
total: totalCount,
current: pageNo,
pageSize,
totalPage,
});
setTableData(list);
// console.log('加载列表 --->', list);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType) => {
pagination.current = 1;
query = data;
getTableList(data).then();
};
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '课程名称',
dataIndex: 'curriculumName',
align: 'center',
width: '150px',
},
{
title: '课程类型',
dataIndex: 'flightSkillsName1',
align: 'center',
width: '150px',
render: (text, record) => `${text}/${record.flightSkillsName2}`,
},
{
title: '课程类型',
dataIndex: 'curriculumDesc',
align: 'center',
width: '150px',
ellipsis: true,
},
{
title: '封面图',
dataIndex: 'surfaceUrl',
align: 'center',
width: '150px',
render: (text, record) => (
<>
<Image
src={text ? text : `${record.videoUrl}?x-oss-process=video/snapshot,t_1000,m_fast`}
alt={'封面图'}
style={{ width: '35px', height: '35px' }}
/>
</>
),
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: '100px',
render: (_text, record) => (
<>
<Button
type={'link'}
onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setIsAddEditVisModal(true);
}}
>
编辑
</Button>
<Button type={'link'} danger>
删除
</Button>
</>
),
},
];
// componentDidMount
useEffect(() => {
query = {};
(async () => {
await getTableList();
})();
}, []);
return (
<>
<SearchBox
search={[
{
label: '课程名称',
name: 'keyword',
type: 'input',
placeholder: '请输入课程名称',
},
{
label: '课程类型',
name: 'companyAuthStatus',
type: 'Select',
placeholder: '请选择是否认证',
options: [
{ value: 0, label: '未认证' },
{ value: 1, label: '已认证' },
],
},
]}
searchData={onFinish}
child={
<>
<Button
type={'primary'}
icon={<PlusOutlined />}
onClick={() => {
setIsAddEditVisModal(true);
}}
>
新建课程
</Button>
</>
}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// 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} 条数据`,
}}
// rowSelection={{ selectedRowKeys, onChange: onSelectChange }}
/>
<AddEditModal
open={isAddEditVisModal}
closed={() => {
setIsAddEditVisModal(false);
paginationChange(pagination.current, pagination.pageSize);
}}
data={editData}
title={editData?.id ? '编辑' : '新增'}
/>
</>
);
};
export default CourseManageView;
...@@ -24,6 +24,7 @@ import { ...@@ -24,6 +24,7 @@ import {
AppstoreOutlined, AppstoreOutlined,
CoffeeOutlined, CoffeeOutlined,
UnorderedListOutlined, UnorderedListOutlined,
BookOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
...@@ -44,6 +45,7 @@ import CustomListView from '~/pages/customManage/customList'; ...@@ -44,6 +45,7 @@ import CustomListView from '~/pages/customManage/customList';
import CustomMoneyView from '~/pages/customManage/customMoney'; import CustomMoneyView from '~/pages/customManage/customMoney';
import CustomMoneyDetail from '~/pages/customManage/customMoney/detail'; import CustomMoneyDetail from '~/pages/customManage/customMoney/detail';
import AccountManageView from '~/pages/systemManage/accountManage'; import AccountManageView from '~/pages/systemManage/accountManage';
import CourseManageView from '~/pages/mallManage/courseManage';
// 活动 // 活动
const ActivityList = React.lazy(() => import('src/pages/activityManage/activityList')); //活动管理 const ActivityList = React.lazy(() => import('src/pages/activityManage/activityList')); //活动管理
...@@ -226,6 +228,15 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -226,6 +228,15 @@ export const routerList: Array<RouteObjectType> = [
}, },
children: [ children: [
{ {
path: '/mallManage/courseManage',
element: withLoadingComponent(<CourseManageView />),
meta: {
id: 10190,
icon: <BookOutlined />,
title: '课程管理',
},
},
{
path: '/mallManage/serviceList', path: '/mallManage/serviceList',
element: withLoadingComponent(<ServiceListView />), element: withLoadingComponent(<ServiceListView />),
meta: { meta: {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论