提交 10cebae0 作者: ZhangLingKun

功能:课程管理联调完成

上级 22137be3
...@@ -26,17 +26,50 @@ export type queryCurriculumInfoListType = InterListFunction< ...@@ -26,17 +26,50 @@ export type queryCurriculumInfoListType = InterListFunction<
export type addCurriculumType = InterFunction< export type addCurriculumType = InterFunction<
{ {
curriculumDesc?: string; curriculumDesc?: string;
curriculumName: string; curriculumName?: string;
detailContent?: string; detailContent?: string;
flightSkills: number; flightSkills?: number;
flightSkillsName1: string; flightSkillsName1?: string;
flightSkillsName2: string; flightSkillsName2?: string;
free: number; free?: number;
id: number; id?: number | null;
price: number; price?: number;
supplierName: string; supplierName?: string;
surfaceUrl: string; surfaceUrl?: string;
videoUrl: string; videoUrl?: string;
}, },
NonNullable<unknown> NonNullable<unknown>
>; >;
// V1.0.1修改课程
export type updateCurriculumType = InterFunction<
{
curriculumDesc?: string;
curriculumName?: string;
detailContent?: string;
flightSkills?: number;
flightSkillsName1?: string;
flightSkillsName2?: string;
free?: number;
id: number | null;
price?: number;
supplierName?: string;
surfaceUrl?: string;
videoUrl?: string;
},
NonNullable<unknown>
>;
// V1.0.1课程技能列表
export type treeCurriculumSkillType = InterFunction<
NonNullable<unknown>,
{
id: number;
skillsName: string;
flightSkills: Array<{
id: number;
skillsName: string;
flightSkills: null;
}>;
}[]
>;
// V1.0.1删除课程
export type removeCurriculumType = InterFunction<{ id: number }, NonNullable<unknown>>;
import axios from '~/api/request'; import axios from '~/api/request';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType'; import {
addCurriculumType,
queryCurriculumInfoListType,
removeCurriculumType,
treeCurriculumSkillType,
updateCurriculumType,
} from '~/api/interface/mallManageType';
export class MallManageAPI { export class MallManageAPI {
// V1.0.1课程视频列表 // V1.0.1课程视频列表
...@@ -8,4 +14,13 @@ export class MallManageAPI { ...@@ -8,4 +14,13 @@ export class MallManageAPI {
// V1.0.1新增课程 // V1.0.1新增课程
static addCurriculum: addCurriculumType = (params) => static addCurriculum: addCurriculumType = (params) =>
axios.post('/release/curriculum/addCurriculum', params); axios.post('/release/curriculum/addCurriculum', params);
// V1.0.1修改课程
static updateCurriculum: updateCurriculumType = (params) =>
axios.post('/release/curriculum/updateCurriculum', params);
// V1.0.1课程技能列表
static treeCurriculumSkill: treeCurriculumSkillType = (params) =>
axios.get('/release/curriculum/treeCurriculumSkill', { params });
// V1.0.1删除课程
static removeCurriculum: removeCurriculumType = (params) =>
axios.get('/release/curriculum/removeCurriculum', { params });
} }
...@@ -11,15 +11,16 @@ interface PropsType { ...@@ -11,15 +11,16 @@ interface PropsType {
value: string; value: string;
// eslint-disable-next-line react/require-default-props // eslint-disable-next-line react/require-default-props
isDetail?: boolean; isDetail?: boolean;
height?: number;
} }
const RichText: React.FC<PropsType> = ({ onChange, value, isDetail }) => { const RichText: React.FC<PropsType> = ({ onChange, value, isDetail, height }) => {
useEffect(() => { useEffect(() => {
// 注:class写法需要在componentDidMount 创建编辑器 // 注:class写法需要在componentDidMount 创建编辑器
editor = new E('.edit'); editor = new E('.edit');
editor.config.uploadImgShowBase64 = false; editor.config.uploadImgShowBase64 = false;
editor.config.zIndex = 1; editor.config.zIndex = 1;
editor.config.height = 550; editor.config.height = height ? height : 550;
editor.config.uploadImgMaxLength = 5; editor.config.uploadImgMaxLength = 5;
editor.config.uploadImgMaxSize = 1024 * 1024 * 3; // 2M editor.config.uploadImgMaxSize = 1024 * 1024 * 3; // 2M
editor.config.customUploadImg = async (resultFiles: any, insertImgFn: any) => { editor.config.customUploadImg = async (resultFiles: any, insertImgFn: any) => {
......
...@@ -22,7 +22,7 @@ interface PropsType { ...@@ -22,7 +22,7 @@ interface PropsType {
} }
export const Uploader: React.FC<PropsType> = (props) => { export const Uploader: React.FC<PropsType> = (props) => {
Uploader.defaultProps = { Uploader.defaultProps = {
listType: 'text', listType: 'picture-card',
fileSize: 2, fileSize: 2,
fileLength: 1, fileLength: 1,
fileType: [ fileType: [
......
import { InterListType, InterReqType } from '~/api/interface'; import { InterListType, InterReqType } from '~/api/interface';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { Col, Form, Input, message, Modal, Radio, Row, Select } from 'antd'; import { Cascader, Form, Input, message, Modal } 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 { OrderManageAPI } from '~/api'; import { MallManageAPI } from '~/api';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType'; import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import RichText from '~/components/richText';
// 表格数据类型 // 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>; type TableType = InterListType<queryCurriculumInfoListType>;
...@@ -25,8 +26,17 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -25,8 +26,17 @@ const AddEditModal: React.FC<propType> = (props) => {
}; };
// 参数 // 参数
const { title, open, closed, data } = props; const { title, open, closed, data } = props;
// 物流列表 // 课程类型列表
const [expressList, setExpressList] = React.useState<{ label: string; value: string }[]>([]); const [curriculumSkillList, setCurriculumSkillList] = React.useState<
{
value: number;
label: string;
children?: Array<{
value: number;
label: string;
}>;
}[]
>([]);
// 表单钩子 // 表单钩子
const [form] = Form.useForm<ReqType>(); const [form] = Form.useForm<ReqType>();
// 关闭弹窗 // 关闭弹窗
...@@ -52,29 +62,50 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -52,29 +62,50 @@ const AddEditModal: React.FC<propType> = (props) => {
}; };
// 提交事件 // 提交事件
const handleSubmit = async (values: ReqType) => { const handleSubmit = async (values: ReqType) => {
const res = await OrderManageAPI.sendOrderWare({ const res = await MallManageAPI[data?.id ? 'updateCurriculum' : 'addCurriculum']({
...values, ...values,
orderInfoId: Number(data?.id), flightSkills: Number((values?.flightSkills as unknown as number[])?.at(-1)),
id: data?.id ? data?.id : null,
}); });
if (res && res.code === '200') { if (res && res.code === '200') {
message.success('操作成功'); message.success('操作成功');
handleCancel(); handleCancel();
} }
}; };
// 获取物流信息 // 获取课程类型
const getListExpressInfo = async () => { const getCurriculumSkillList = async () => {
const res = await OrderManageAPI.listExpressInfo({}); const res = await MallManageAPI.treeCurriculumSkill({});
if (res && res.code === '200') { if (res && res.code === '200') {
setExpressList(res.result.map((item) => ({ label: item.exName, value: item.exCode }))); setCurriculumSkillList(
res.result?.map((i) => ({
label: i.skillsName,
value: i.id,
children: i.flightSkills?.map((j) => ({ label: j.skillsName, value: j.id })),
})),
);
// console.log(res); // console.log(res);
} }
}; };
// componentDidMount // componentDidMount
useEffect(() => { useEffect(() => {
if (!open) return; if (!open) return;
if (!data) return; // 获取课程类型
getListExpressInfo().then(); getCurriculumSkillList().then(() => {
// console.log('data --->', data); // 加载出数据再操作
if (!data) return;
// 反向找数据回显
const flightSkillsName1 = curriculumSkillList.find(
(i) => i.label === data?.flightSkillsName1,
);
const flightSkillsName2 = flightSkillsName1?.children?.find(
(i) => i.label === data?.flightSkillsName2,
);
// 回显数据
form.setFieldsValue({
...data,
flightSkills: [flightSkillsName1?.value, flightSkillsName2?.value],
});
});
}, [open]); }, [open]);
return ( return (
<Modal <Modal
...@@ -89,160 +120,87 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -89,160 +120,87 @@ const AddEditModal: React.FC<propType> = (props) => {
name='addForm' name='addForm'
form={form} form={form}
labelAlign='right' labelAlign='right'
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
autoComplete='new-password' autoComplete='new-password'
labelCol={{ span: 3 }}
wrapperCol={{ span: 10 }}
> >
<Form.Item label='收货地址' labelCol={{ span: 4 }}> <Form.Item
{data?.receipt?.takeName} {data?.receipt?.takePhone} {data?.receipt?.detailAddress} label='课程类型'
name='flightSkills'
rules={[{ required: true, message: '请选择课程类型' }]}
>
<Cascader placeholder={'请选择课程类型'} options={curriculumSkillList} allowClear />
</Form.Item>
<Form.Item
label='课程名称'
name='curriculumName'
rules={[{ required: true, message: '请输入课程名称' }]}
>
<Input placeholder={'请输入课程名称'} maxLength={20} allowClear />
</Form.Item>
<Form.Item
label='课程描述'
name='curriculumDesc'
rules={[{ required: true, message: '请输入课程描述' }]}
>
<Input.TextArea placeholder={'请输入课程描述'} maxLength={20} allowClear showCount />
</Form.Item>
<Form.Item
label='课程封面'
name='surfaceUrl'
rules={[{ required: true, message: '请上传质检照片' }]}
style={{ marginBottom: '-40px' }}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
onChange={(e) => form.setFieldValue('surfaceUrl', e[0].url)}
defaultFileList={data?.surfaceUrl ? [{ url: data?.surfaceUrl }] : []}
>
<PlusOutlined />
</Uploader>
<div style={{ opacity: '0.68', transform: 'scale(0.86) translate(60px, -68px)' }}>
添加图片
<br />
建议尺寸750*420或比例16:9,小于5M的 JPG、PNG格式图片
</div>
</Form.Item>
<Form.Item
label='课程上传'
name='videoUrl'
rules={[{ required: true, message: '请上传质检视频' }]}
style={{ marginBottom: '-40px' }}
>
<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)}
defaultFileList={data?.videoUrl ? [{ url: data?.videoUrl }] : []}
>
<PlusOutlined />
</Uploader>
<div style={{ opacity: '0.68', transform: 'scale(0.86) translate(60px, -68px)' }}>
从本地上传视频
<br />
支持mp4,avi,wmv,mov,flv, rmvb,3gp,m4v,mkv格式; 文件最大不超过1G。
</div>
</Form.Item> </Form.Item>
<Form.Item label='发货方式' labelCol={{ span: 4 }}> <Form.Item
物流发货 label='课程详情'
name='detailContent'
rules={[{ required: false, message: '请填写详情' }]}
wrapperCol={{ span: 20 }}
>
<RichText
value={form.getFieldValue('detailContent')}
onChange={(e) => form.setFieldValue('detailContent', e)}
height={250}
/>
</Form.Item> </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> </Form>
</Modal> </Modal>
); );
......
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box'; import SearchBox from '~/components/search-box';
import { Button, Table, Image } 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 { InterListType, InterReqType } from '~/api/interface';
...@@ -16,6 +16,7 @@ type ReqType = InterReqType<queryCurriculumInfoListType>; ...@@ -16,6 +16,7 @@ type ReqType = InterReqType<queryCurriculumInfoListType>;
let query: ReqType = {}; let query: ReqType = {};
const CourseManageView = () => { const CourseManageView = () => {
const { confirm } = Modal;
// 是否打开变更弹窗 // 是否打开变更弹窗
const [isAddEditVisModal, setIsAddEditVisModal] = useState<boolean>(false); const [isAddEditVisModal, setIsAddEditVisModal] = useState<boolean>(false);
// 表格分页配置 // 表格分页配置
...@@ -60,6 +61,23 @@ const CourseManageView = () => { ...@@ -60,6 +61,23 @@ const CourseManageView = () => {
query = data; query = data;
getTableList(data).then(); getTableList(data).then();
}; };
// 删除数据
const handleDelete = (value: TableType[0]) => {
confirm({
title: '提示',
content: '是否删除该课程?',
onOk: async () => {
const res = await MallManageAPI.removeCurriculum({ id: value.id });
if (res && res.code === '200') {
message.success('删除成功');
paginationChange(
tableData.length === 1 ? pagination.current - 1 : pagination.current,
pagination.pageSize,
);
}
},
});
};
// 表格结构 // 表格结构
const columns: ColumnsType<TableType[0]> = [ const columns: ColumnsType<TableType[0]> = [
{ {
...@@ -114,7 +132,7 @@ const CourseManageView = () => { ...@@ -114,7 +132,7 @@ const CourseManageView = () => {
> >
编辑 编辑
</Button> </Button>
<Button type={'link'} danger> <Button type={'link'} danger onClick={() => handleDelete(record)}>
删除 删除
</Button> </Button>
</> </>
...@@ -184,6 +202,7 @@ const CourseManageView = () => { ...@@ -184,6 +202,7 @@ const CourseManageView = () => {
<AddEditModal <AddEditModal
open={isAddEditVisModal} open={isAddEditVisModal}
closed={() => { closed={() => {
setEditData(undefined);
setIsAddEditVisModal(false); setIsAddEditVisModal(false);
paginationChange(pagination.current, pagination.pageSize); paginationChange(pagination.current, pagination.pageSize);
}} }}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论