提交 10cebae0 作者: ZhangLingKun

功能:课程管理联调完成

上级 22137be3
......@@ -26,17 +26,50 @@ export type queryCurriculumInfoListType = InterListFunction<
export type addCurriculumType = InterFunction<
{
curriculumDesc?: string;
curriculumName: string;
curriculumName?: string;
detailContent?: string;
flightSkills: number;
flightSkillsName1: string;
flightSkillsName2: string;
free: number;
id: number;
price: number;
supplierName: string;
surfaceUrl: string;
videoUrl: 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 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 { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import {
addCurriculumType,
queryCurriculumInfoListType,
removeCurriculumType,
treeCurriculumSkillType,
updateCurriculumType,
} from '~/api/interface/mallManageType';
export class MallManageAPI {
// V1.0.1课程视频列表
......@@ -8,4 +14,13 @@ export class MallManageAPI {
// V1.0.1新增课程
static addCurriculum: addCurriculumType = (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 {
value: string;
// eslint-disable-next-line react/require-default-props
isDetail?: boolean;
height?: number;
}
const RichText: React.FC<PropsType> = ({ onChange, value, isDetail }) => {
const RichText: React.FC<PropsType> = ({ onChange, value, isDetail, height }) => {
useEffect(() => {
// 注:class写法需要在componentDidMount 创建编辑器
editor = new E('.edit');
editor.config.uploadImgShowBase64 = false;
editor.config.zIndex = 1;
editor.config.height = 550;
editor.config.height = height ? height : 550;
editor.config.uploadImgMaxLength = 5;
editor.config.uploadImgMaxSize = 1024 * 1024 * 3; // 2M
editor.config.customUploadImg = async (resultFiles: any, insertImgFn: any) => {
......
......@@ -22,7 +22,7 @@ interface PropsType {
}
export const Uploader: React.FC<PropsType> = (props) => {
Uploader.defaultProps = {
listType: 'text',
listType: 'picture-card',
fileSize: 2,
fileLength: 1,
fileType: [
......
import { InterListType, InterReqType } from '~/api/interface';
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 { PlusOutlined } from '@ant-design/icons';
import { OrderManageAPI } from '~/api';
import { MallManageAPI } from '~/api';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import RichText from '~/components/richText';
// 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>;
......@@ -25,8 +26,17 @@ const AddEditModal: React.FC<propType> = (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>();
// 关闭弹窗
......@@ -52,29 +62,50 @@ const AddEditModal: React.FC<propType> = (props) => {
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await OrderManageAPI.sendOrderWare({
const res = await MallManageAPI[data?.id ? 'updateCurriculum' : 'addCurriculum']({
...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') {
message.success('操作成功');
handleCancel();
}
};
// 获取物流信息
const getListExpressInfo = async () => {
const res = await OrderManageAPI.listExpressInfo({});
// 获取课程类型
const getCurriculumSkillList = async () => {
const res = await MallManageAPI.treeCurriculumSkill({});
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);
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
getListExpressInfo().then();
// console.log('data --->', data);
// 获取课程类型
getCurriculumSkillList().then(() => {
// 加载出数据再操作
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]);
return (
<Modal
......@@ -89,160 +120,87 @@ const AddEditModal: React.FC<propType> = (props) => {
name='addForm'
form={form}
labelAlign='right'
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
autoComplete='new-password'
labelCol={{ span: 3 }}
wrapperCol={{ span: 10 }}
>
<Form.Item label='收货地址' labelCol={{ span: 4 }}>
{data?.receipt?.takeName} {data?.receipt?.takePhone} {data?.receipt?.detailAddress}
<Form.Item
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 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>
<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>
);
......
import { useEffect, useState } from 'react';
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 { queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import { InterListType, InterReqType } from '~/api/interface';
......@@ -16,6 +16,7 @@ type ReqType = InterReqType<queryCurriculumInfoListType>;
let query: ReqType = {};
const CourseManageView = () => {
const { confirm } = Modal;
// 是否打开变更弹窗
const [isAddEditVisModal, setIsAddEditVisModal] = useState<boolean>(false);
// 表格分页配置
......@@ -60,6 +61,23 @@ const CourseManageView = () => {
query = data;
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]> = [
{
......@@ -114,7 +132,7 @@ const CourseManageView = () => {
>
编辑
</Button>
<Button type={'link'} danger>
<Button type={'link'} danger onClick={() => handleDelete(record)}>
删除
</Button>
</>
......@@ -184,6 +202,7 @@ const CourseManageView = () => {
<AddEditModal
open={isAddEditVisModal}
closed={() => {
setEditData(undefined);
setIsAddEditVisModal(false);
paginationChange(pagination.current, pagination.pageSize);
}}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论