mirror of
https://github.com/PlayEdu/backend
synced 2025-06-17 19:58:33 +08:00
线上课编辑和课时管理初步
This commit is contained in:
parent
9fc6e79b3d
commit
faa03f19e0
@ -1,11 +1,11 @@
|
|||||||
import client from "./internal/httpClient";
|
import client from "./internal/httpClient";
|
||||||
|
|
||||||
export function courseChapterList(courseId: number) {
|
export function courseChapterList(courseId: number) {
|
||||||
return client.get(`/backend/v1/course/${courseId}/course-chapter/index`, {});
|
return client.get(`/backend/v1/course/${courseId}/chapter/index`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCourseChapter(courseId: number) {
|
export function createCourseChapter(courseId: number) {
|
||||||
return client.get(`/backend/v1/course/${courseId}/course-chapter/create`, {});
|
return client.get(`/backend/v1/course/${courseId}/chapter/create`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function storeCourseChapter(
|
export function storeCourseChapter(
|
||||||
@ -13,7 +13,7 @@ export function storeCourseChapter(
|
|||||||
name: string,
|
name: string,
|
||||||
sort: number
|
sort: number
|
||||||
) {
|
) {
|
||||||
return client.post(`/backend/v1/course/${courseId}/course-chapter/create`, {
|
return client.post(`/backend/v1/course/${courseId}/chapter/create`, {
|
||||||
name: name,
|
name: name,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
});
|
});
|
||||||
@ -29,12 +29,18 @@ export function updateCourseChapter(
|
|||||||
name: string,
|
name: string,
|
||||||
sort: number
|
sort: number
|
||||||
) {
|
) {
|
||||||
return client.post(`/backend/v1/course/${courseId}/course-chapter/${id}`, {
|
return client.put(`/backend/v1/course/${courseId}/chapter/${id}`, {
|
||||||
name: name,
|
name: name,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function destroyCourseChapter(courseId: number, id: number) {
|
export function destroyCourseChapter(courseId: number, id: number) {
|
||||||
return client.destroy(`/backend/v1/course/${courseId}/course-chapter/${id}`);
|
return client.destroy(`/backend/v1/course/${courseId}/chapter/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transCourseChapter(courseId: number, ids: number[]) {
|
||||||
|
return client.put(`/backend/v1/course/${courseId}/chapter/update/sort`, {
|
||||||
|
ids: ids,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import client from "./internal/httpClient";
|
import client from "./internal/httpClient";
|
||||||
|
|
||||||
export function courseHourList(courseId: number) {
|
export function courseHourList(courseId: number) {
|
||||||
return client.get(`/backend/v1/course/${courseId}/course-hour/index`, {});
|
return client.get(`/backend/v1/course/${courseId}/hour/index`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCourseHour(courseId: number) {
|
export function createCourseHour(courseId: number) {
|
||||||
return client.get(`/backend/v1/course/${courseId}/course-hour/create`, {});
|
return client.get(`/backend/v1/course/${courseId}/hour/create`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function storeCourseHour(
|
export function storeCourseHour(
|
||||||
@ -14,19 +14,26 @@ export function storeCourseHour(
|
|||||||
title: string,
|
title: string,
|
||||||
type: string,
|
type: string,
|
||||||
druation: number,
|
druation: number,
|
||||||
publishedAt: string
|
rid: number
|
||||||
) {
|
) {
|
||||||
return client.post(`/backend/v1/course/${courseId}/course-hour/create`, {
|
return client.post(`/backend/v1/course/${courseId}/hour/create`, {
|
||||||
chapter_id: chapterId,
|
chapter_id: chapterId,
|
||||||
title,
|
title,
|
||||||
type,
|
type,
|
||||||
druation,
|
druation,
|
||||||
published_at: publishedAt,
|
sort: 0,
|
||||||
|
rid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function storeCourseHourMulti(courseId: number, hours: number[]) {
|
||||||
|
return client.post(`/backend/v1/course/${courseId}/hour/create-batch`, {
|
||||||
|
hours: hours,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function courseHour(courseId: number, id: number) {
|
export function courseHour(courseId: number, id: number) {
|
||||||
return client.get(`/backend/v1/course/${courseId}/course-hour/${id}`, {});
|
return client.get(`/backend/v1/course/${courseId}/hour/${id}`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateCourseHour(
|
export function updateCourseHour(
|
||||||
@ -36,17 +43,24 @@ export function updateCourseHour(
|
|||||||
title: string,
|
title: string,
|
||||||
type: string,
|
type: string,
|
||||||
druation: number,
|
druation: number,
|
||||||
publishedAt: string
|
rid: number
|
||||||
) {
|
) {
|
||||||
return client.post(`/backend/v1/course/${courseId}/course-hour/${id}`, {
|
return client.put(`/backend/v1/course/${courseId}/hour/${id}`, {
|
||||||
chapter_id: chapterId,
|
chapter_id: chapterId,
|
||||||
title,
|
title,
|
||||||
type,
|
type,
|
||||||
druation,
|
druation,
|
||||||
published_at: publishedAt,
|
sort: 0,
|
||||||
|
rid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function destroyCourseHour(courseId: number, id: number) {
|
export function destroyCourseHour(courseId: number, id: number) {
|
||||||
return client.destroy(`/backend/v1/course/${courseId}/course-hour/${id}`);
|
return client.destroy(`/backend/v1/course/${courseId}/hour/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transCourseHour(courseId: number, ids: number[]) {
|
||||||
|
return client.put(`/backend/v1/course/${courseId}/hour/update/sort`, {
|
||||||
|
ids: ids,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 3943555 */
|
font-family: "iconfont"; /* Project id 3943555 */
|
||||||
src: url('iconfont.woff2?t=1679377698528') format('woff2'),
|
src: url('iconfont.woff2?t=1679383201256') format('woff2'),
|
||||||
url('iconfont.woff?t=1679377698528') format('woff'),
|
url('iconfont.woff?t=1679383201256') format('woff'),
|
||||||
url('iconfont.ttf?t=1679377698528') format('truetype');
|
url('iconfont.ttf?t=1679383201256') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@ -13,6 +13,10 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-icon-tips:before {
|
||||||
|
content: "\e74a";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-icon-fold:before {
|
.icon-icon-fold:before {
|
||||||
content: "\e749";
|
content: "\e749";
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -213,14 +213,13 @@ code {
|
|||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
|
||||||
color: rgba(0, 0, 0, 0.88);
|
color: rgba(0, 0, 0, 0.88);
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&.active {
|
&.active {
|
||||||
background: rgba(#ff4d4f, 0.1);
|
background-color: #fff2f0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +168,8 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getChapterType = (e: any) => {
|
const getChapterType = (e: any) => {
|
||||||
|
const arr = [...chapters];
|
||||||
|
if (arr.length > 0) {
|
||||||
confirm({
|
confirm({
|
||||||
title: "操作确认",
|
title: "操作确认",
|
||||||
icon: <ExclamationCircleFilled />,
|
icon: <ExclamationCircleFilled />,
|
||||||
@ -188,6 +190,9 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
setChapterType(e.target.value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const delHour = (id: number) => {
|
const delHour = (id: number) => {
|
||||||
@ -378,7 +383,9 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
|
|||||||
rules={[{ required: true, message: "请选择课程类型!" }]}
|
rules={[{ required: true, message: "请选择课程类型!" }]}
|
||||||
>
|
>
|
||||||
<Radio.Group onChange={getType}>
|
<Radio.Group onChange={getType}>
|
||||||
<Radio value="open">公开课</Radio>
|
<Radio value="open">
|
||||||
|
公开课 <i className="iconfont icon-icon-tips c-gray ml-8" />
|
||||||
|
</Radio>
|
||||||
<Radio value="elective">部门课</Radio>
|
<Radio value="elective">部门课</Radio>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
109
src/pages/course/compenents/hour-update.module.less
Normal file
109
src/pages/course/compenents/hour-update.module.less
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
.top-content {
|
||||||
|
width: 502px;
|
||||||
|
height: 80px;
|
||||||
|
background: rgba(255, 77, 79, 0.1);
|
||||||
|
border-radius: 6px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 0 auto;
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #ff4d4f;
|
||||||
|
line-height: 24px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumb-item {
|
||||||
|
width: 80px;
|
||||||
|
height: 60px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 8px;
|
||||||
|
border-radius: 6px;
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumb-item-avtive {
|
||||||
|
width: 80px;
|
||||||
|
height: 60px;
|
||||||
|
border: 2px solid #ff4d4f;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hous-box {
|
||||||
|
width: 502px;
|
||||||
|
min-height: 56px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
/* Firefox */
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
/* Safari */
|
||||||
|
padding: 16px 16px 16px 0;
|
||||||
|
margin-left: 42px;
|
||||||
|
.no-hours {
|
||||||
|
height: 24px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(0, 0, 0, 0.25);
|
||||||
|
line-height: 24px;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chapter-item {
|
||||||
|
width: 502px;
|
||||||
|
height: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 42px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
.label {
|
||||||
|
width: 78px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
.input {
|
||||||
|
width: 208px;
|
||||||
|
height: 32px;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
.chapter-hous-box {
|
||||||
|
width: 502px;
|
||||||
|
min-height: 56px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
/* Firefox */
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
/* Safari */
|
||||||
|
padding: 16px 16px 16px 0;
|
||||||
|
margin-top: 16px;
|
||||||
|
.no-hours {
|
||||||
|
height: 24px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(0, 0, 0, 0.25);
|
||||||
|
line-height: 24px;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
462
src/pages/course/compenents/hour-update.tsx
Normal file
462
src/pages/course/compenents/hour-update.tsx
Normal file
@ -0,0 +1,462 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { Space, Button, Drawer, Form, Input, Modal, message } from "antd";
|
||||||
|
import styles from "./hour-update.module.less";
|
||||||
|
import { course, courseHour, courseChapter } from "../../../api/index";
|
||||||
|
import { SelectResource } from "../../../compenents";
|
||||||
|
import { ExclamationCircleFilled } from "@ant-design/icons";
|
||||||
|
import { TreeHours } from "./hours";
|
||||||
|
|
||||||
|
const { confirm } = Modal;
|
||||||
|
|
||||||
|
interface PropInterface {
|
||||||
|
id: number;
|
||||||
|
open: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Option {
|
||||||
|
value: string | number;
|
||||||
|
label: string;
|
||||||
|
children?: Option[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CourseHourUpdate: React.FC<PropInterface> = ({
|
||||||
|
id,
|
||||||
|
open,
|
||||||
|
onCancel,
|
||||||
|
}) => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [chapterType, setChapterType] = useState(0);
|
||||||
|
const [chapters, setChapters] = useState<any>([]);
|
||||||
|
const [hours, setHours] = useState<any>([]);
|
||||||
|
const [chapterHours, setChapterHours] = useState<any>([]);
|
||||||
|
const [videoVisible, setVideoVisible] = useState<boolean>(false);
|
||||||
|
const [treeData, setTreeData] = useState<any>([]);
|
||||||
|
const [addvideoCurrent, setAddvideoCurrent] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (id === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getDetail();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
const getDetail = () => {
|
||||||
|
course.course(id).then((res: any) => {
|
||||||
|
let chapterType = res.data.chapters.length > 0 ? 1 : 0;
|
||||||
|
setChapterType(chapterType);
|
||||||
|
if (chapterType === 1) {
|
||||||
|
setTreeData([]);
|
||||||
|
setHours([]);
|
||||||
|
let hours = res.data.hours;
|
||||||
|
let chapters = res.data.chapters;
|
||||||
|
const arr: any = [];
|
||||||
|
const keys: any = [];
|
||||||
|
for (let i = 0; i < chapters.length; i++) {
|
||||||
|
arr.push({
|
||||||
|
id: chapters[i].id,
|
||||||
|
name: chapters[i].name,
|
||||||
|
hours: resetHours(hours[chapters[i].id]).arr,
|
||||||
|
});
|
||||||
|
keys.push(resetHours(hours[chapters[i].id]).keys);
|
||||||
|
}
|
||||||
|
setChapters(arr);
|
||||||
|
setChapterHours(keys);
|
||||||
|
} else {
|
||||||
|
setChapters([]);
|
||||||
|
setChapterHours([]);
|
||||||
|
let hours = res.data.hours;
|
||||||
|
if (JSON.stringify(hours) !== "{}") {
|
||||||
|
const arr: any = resetHours(hours[0]).arr;
|
||||||
|
const keys: any = resetHours(hours[0]).keys;
|
||||||
|
setTreeData(arr);
|
||||||
|
setHours(keys);
|
||||||
|
} else {
|
||||||
|
setTreeData([]);
|
||||||
|
setHours([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetHours = (data: any) => {
|
||||||
|
const arr: any = [];
|
||||||
|
const keys: any = [];
|
||||||
|
if (data) {
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
arr.push({
|
||||||
|
duration: data[i].duration,
|
||||||
|
type: data[i].type,
|
||||||
|
name: data[i].title,
|
||||||
|
rid: data[i].rid,
|
||||||
|
id: data[i].id,
|
||||||
|
});
|
||||||
|
keys.push(data[i].rid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { arr, keys };
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinish = (values: any) => {};
|
||||||
|
|
||||||
|
const onFinishFailed = (errorInfo: any) => {
|
||||||
|
console.log("Failed:", errorInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectData = (arr: any, videos: any) => {
|
||||||
|
const hours: any = [];
|
||||||
|
for (let i = 0; i < videos.length; i++) {
|
||||||
|
hours.push({
|
||||||
|
chapter_id: 0,
|
||||||
|
sort: i,
|
||||||
|
title: videos[i].name,
|
||||||
|
type: videos[i].type,
|
||||||
|
duration: videos[i].duration,
|
||||||
|
rid: videos[i].rid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
courseHour
|
||||||
|
.storeCourseHourMulti(id, hours)
|
||||||
|
.then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
setVideoVisible(false);
|
||||||
|
getDetail();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
message.error(err.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectChapterData = (arr: any, videos: any) => {
|
||||||
|
const data = [...chapters];
|
||||||
|
if (!data[addvideoCurrent].id) {
|
||||||
|
message.error("添加课时失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const hours: any = [];
|
||||||
|
for (let i = 0; i < videos.length; i++) {
|
||||||
|
hours.push({
|
||||||
|
chapter_id: data[addvideoCurrent].id,
|
||||||
|
sort: i,
|
||||||
|
title: videos[i].name,
|
||||||
|
type: videos[i].type,
|
||||||
|
duration: videos[i].duration,
|
||||||
|
rid: videos[i].rid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
courseHour
|
||||||
|
.storeCourseHourMulti(id, hours)
|
||||||
|
.then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
setVideoVisible(false);
|
||||||
|
getDetail();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
message.error(err.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const delHour = (hid: number) => {
|
||||||
|
const data = [...treeData];
|
||||||
|
const index = data.findIndex((i: any) => i.rid === hid);
|
||||||
|
let delId = data[index].id;
|
||||||
|
if (index >= 0) {
|
||||||
|
data.splice(index, 1);
|
||||||
|
}
|
||||||
|
if (data.length > 0) {
|
||||||
|
setTreeData(data);
|
||||||
|
const keys = data.map((item: any) => item.rid);
|
||||||
|
setHours(keys);
|
||||||
|
} else {
|
||||||
|
setTreeData([]);
|
||||||
|
setHours([]);
|
||||||
|
}
|
||||||
|
if (delId) {
|
||||||
|
courseHour.destroyCourseHour(id, delId).then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const transHour = (arr: any) => {
|
||||||
|
setHours(arr);
|
||||||
|
const data = [...treeData];
|
||||||
|
const newArr: any = [];
|
||||||
|
const hourIds: any = [];
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
data.map((item: any) => {
|
||||||
|
if (item.rid === arr[i]) {
|
||||||
|
newArr.push(item);
|
||||||
|
hourIds.push(item.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setTreeData(newArr);
|
||||||
|
courseHour.transCourseHour(id, hourIds).then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const addNewChapter = () => {
|
||||||
|
const arr = [...chapters];
|
||||||
|
const keys = [...chapterHours];
|
||||||
|
arr.push({
|
||||||
|
name: "",
|
||||||
|
hours: [],
|
||||||
|
});
|
||||||
|
keys.push([]);
|
||||||
|
setChapters(arr);
|
||||||
|
setChapterHours(keys);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setChapterName = (index: number, value: string) => {
|
||||||
|
const arr = [...chapters];
|
||||||
|
arr[index].name = value;
|
||||||
|
setChapters(arr);
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveChapterName = (index: number, value: string) => {
|
||||||
|
const arr = [...chapters];
|
||||||
|
if (arr[index].id) {
|
||||||
|
courseChapter
|
||||||
|
.updateCourseChapter(id, arr[index].id, value, arr.length)
|
||||||
|
.then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
getDetail();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
message.error(err.message);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
courseChapter
|
||||||
|
.storeCourseChapter(id, value, arr.length)
|
||||||
|
.then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
getDetail();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
message.error(err.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const delChapter = (index: number) => {
|
||||||
|
const arr = [...chapters];
|
||||||
|
const keys = [...chapterHours];
|
||||||
|
confirm({
|
||||||
|
title: "操作确认",
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
content: "删除章节会清空已添加课时,确认删除?",
|
||||||
|
centered: true,
|
||||||
|
okText: "确认",
|
||||||
|
cancelText: "取消",
|
||||||
|
onOk() {
|
||||||
|
if (arr[index].id) {
|
||||||
|
courseChapter
|
||||||
|
.destroyCourseChapter(id, arr[index].id)
|
||||||
|
.then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
getDetail();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
message.error(err.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel() {},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const delChapterHour = (index: number, hid: number) => {
|
||||||
|
const keys = [...chapterHours];
|
||||||
|
const data = [...chapters];
|
||||||
|
const current = data[index].hours.findIndex((i: any) => i.rid === hid);
|
||||||
|
let delId = data[index].hours.map((item: any) => item.id);
|
||||||
|
if (current >= 0) {
|
||||||
|
data[index].hours.splice(current, 1);
|
||||||
|
}
|
||||||
|
if (data[index].hours.length > 0) {
|
||||||
|
setChapters(data);
|
||||||
|
keys[index] = data[index].hours.map((item: any) => item.rid);
|
||||||
|
setChapterHours(keys);
|
||||||
|
} else {
|
||||||
|
keys[index] = [];
|
||||||
|
data[index].hours = [];
|
||||||
|
setChapters(data);
|
||||||
|
setChapterHours(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delId) {
|
||||||
|
courseHour.destroyCourseHour(id, delId).then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const transChapterHour = (index: number, arr: any) => {
|
||||||
|
const keys = [...chapterHours];
|
||||||
|
keys[index] = arr;
|
||||||
|
setChapterHours(keys);
|
||||||
|
|
||||||
|
const data = [...chapters];
|
||||||
|
const newArr: any = [];
|
||||||
|
const hourIds: any = [];
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
data[index].hours.map((item: any) => {
|
||||||
|
if (item.rid === arr[i]) {
|
||||||
|
newArr.push(item);
|
||||||
|
hourIds.push(item.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
data[index].hours = newArr;
|
||||||
|
setChapters(data);
|
||||||
|
courseHour.transCourseHour(id, hourIds).then((res: any) => {
|
||||||
|
console.log("ok");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Drawer
|
||||||
|
title="课时管理"
|
||||||
|
onClose={onCancel}
|
||||||
|
maskClosable={false}
|
||||||
|
open={open}
|
||||||
|
width={634}
|
||||||
|
>
|
||||||
|
<div className={styles["top-content"]}>
|
||||||
|
<p>1.线上课课时调整及时生效,操作不可逆,请谨慎操作。</p>
|
||||||
|
<p>2.课时调整后,已有学习进度会在学员学习时重新计算。</p>
|
||||||
|
</div>
|
||||||
|
<div className="float-left mt-24">
|
||||||
|
<SelectResource
|
||||||
|
defaultKeys={
|
||||||
|
chapterType == 0 ? hours : chapterHours[addvideoCurrent]
|
||||||
|
}
|
||||||
|
open={videoVisible}
|
||||||
|
onCancel={() => {
|
||||||
|
setVideoVisible(false);
|
||||||
|
}}
|
||||||
|
onSelected={(arr: any, videos: any) => {
|
||||||
|
if (chapterType == 0) {
|
||||||
|
selectData(arr, videos);
|
||||||
|
} else {
|
||||||
|
selectChapterData(arr, videos);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
name="basic"
|
||||||
|
labelCol={{ span: 5 }}
|
||||||
|
wrapperCol={{ span: 19 }}
|
||||||
|
initialValues={{ remember: true }}
|
||||||
|
onFinish={onFinish}
|
||||||
|
onFinishFailed={onFinishFailed}
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
{chapterType === 0 && (
|
||||||
|
<div className="c-flex">
|
||||||
|
<Form.Item>
|
||||||
|
<div className="ml-120">
|
||||||
|
<Button
|
||||||
|
onClick={() => setVideoVisible(true)}
|
||||||
|
type="primary"
|
||||||
|
>
|
||||||
|
添加课时
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
<div className={styles["hous-box"]}>
|
||||||
|
{treeData.length === 0 && (
|
||||||
|
<span className={styles["no-hours"]}>
|
||||||
|
请点击上方按钮添加课时
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{treeData.length > 0 && (
|
||||||
|
<TreeHours
|
||||||
|
data={treeData}
|
||||||
|
onRemoveItem={(id: number) => {
|
||||||
|
delHour(id);
|
||||||
|
}}
|
||||||
|
onUpdate={(arr: any[]) => {
|
||||||
|
transHour(arr);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{chapterType === 1 && (
|
||||||
|
<div className="c-flex">
|
||||||
|
{chapters.length > 0 &&
|
||||||
|
chapters.map((item: any, index: number) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={item.hours.length + "章节" + index}
|
||||||
|
className={styles["chapter-item"]}
|
||||||
|
>
|
||||||
|
<div className="d-flex">
|
||||||
|
<div className={styles["label"]}>
|
||||||
|
章节{index + 1}:
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
value={item.name}
|
||||||
|
className={styles["input"]}
|
||||||
|
onChange={(e) => {
|
||||||
|
setChapterName(index, e.target.value);
|
||||||
|
}}
|
||||||
|
onBlur={(e) => {
|
||||||
|
saveChapterName(index, e.target.value);
|
||||||
|
}}
|
||||||
|
placeholder="请在此处输入章节名称"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
className="mr-16"
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setVideoVisible(true);
|
||||||
|
setAddvideoCurrent(index);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加课时
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => delChapter(index)}>
|
||||||
|
删除章节
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className={styles["chapter-hous-box"]}>
|
||||||
|
{item.hours.length === 0 && (
|
||||||
|
<span className={styles["no-hours"]}>
|
||||||
|
请点击上方按钮添加课时
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{item.hours.length > 0 && (
|
||||||
|
<TreeHours
|
||||||
|
data={item.hours}
|
||||||
|
onRemoveItem={(id: number) => {
|
||||||
|
delChapterHour(index, id);
|
||||||
|
}}
|
||||||
|
onUpdate={(arr: any[]) => {
|
||||||
|
transChapterHour(index, arr);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<Form.Item>
|
||||||
|
<div className="ml-120">
|
||||||
|
<Button onClick={() => addNewChapter()}>添加章节</Button>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -13,10 +13,8 @@ import {
|
|||||||
} from "antd";
|
} from "antd";
|
||||||
import styles from "./update.module.less";
|
import styles from "./update.module.less";
|
||||||
import { course, department } from "../../../api/index";
|
import { course, department } from "../../../api/index";
|
||||||
import { UploadImageButton, SelectResource } from "../../../compenents";
|
import { UploadImageButton } from "../../../compenents";
|
||||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
|
||||||
import { getHost } from "../../../utils/index";
|
import { getHost } from "../../../utils/index";
|
||||||
import { TreeHours } from "./hours";
|
|
||||||
|
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
|
|
||||||
@ -46,13 +44,6 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
|||||||
const [categories, setCategories] = useState<any>([]);
|
const [categories, setCategories] = useState<any>([]);
|
||||||
const [thumb, setThumb] = useState<string>("");
|
const [thumb, setThumb] = useState<string>("");
|
||||||
const [type, setType] = useState<string>("open");
|
const [type, setType] = useState<string>("open");
|
||||||
const [chapterType, setChapterType] = useState(0);
|
|
||||||
const [chapters, setChapters] = useState<any>([]);
|
|
||||||
const [hours, setHours] = useState<any>([]);
|
|
||||||
const [chapterHours, setChapterHours] = useState<any>([]);
|
|
||||||
const [videoVisible, setVideoVisible] = useState<boolean>(false);
|
|
||||||
const [treeData, setTreeData] = useState<any>([]);
|
|
||||||
const [addvideoCurrent, setAddvideoCurrent] = useState(0);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (id === 0) {
|
if (id === 0) {
|
||||||
@ -143,53 +134,7 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
|||||||
});
|
});
|
||||||
setType(type);
|
setType(type);
|
||||||
setThumb(res.data.course.thumb);
|
setThumb(res.data.course.thumb);
|
||||||
setChapterType(chapterType);
|
|
||||||
if (chapterType === 1) {
|
|
||||||
setTreeData([]);
|
|
||||||
setHours([]);
|
|
||||||
let hours = res.data.hours;
|
|
||||||
let chapters = res.data.chapters;
|
|
||||||
const arr: any = [];
|
|
||||||
const keys: any = [];
|
|
||||||
for (let i = 0; i < chapters.length; i++) {
|
|
||||||
arr.push({
|
|
||||||
name: chapters[i].name,
|
|
||||||
hours: resetHours(hours[chapters[i].id]).arr,
|
|
||||||
});
|
});
|
||||||
keys.push(resetHours(hours[chapters[i].id]).keys);
|
|
||||||
}
|
|
||||||
setChapters(arr);
|
|
||||||
setChapterHours(keys);
|
|
||||||
} else {
|
|
||||||
setChapters([]);
|
|
||||||
setChapterHours([]);
|
|
||||||
let hours = res.data.hours;
|
|
||||||
if (JSON.stringify(hours) !== "{}") {
|
|
||||||
const arr: any = resetHours(hours[0]).arr;
|
|
||||||
const keys: any = resetHours(hours[0]).keys;
|
|
||||||
setTreeData(arr);
|
|
||||||
setHours(keys);
|
|
||||||
} else {
|
|
||||||
setTreeData([]);
|
|
||||||
setHours([]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetHours = (data: any) => {
|
|
||||||
const arr: any = [];
|
|
||||||
const keys: any = [];
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
|
||||||
arr.push({
|
|
||||||
duration: data[i].duration,
|
|
||||||
type: data[i].type,
|
|
||||||
name: data[i].title,
|
|
||||||
rid: data[i].rid,
|
|
||||||
});
|
|
||||||
keys.push(data[i].rid);
|
|
||||||
}
|
|
||||||
return { arr, keys };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkChild = (departments: any[], id: number) => {
|
const checkChild = (departments: any[], id: number) => {
|
||||||
@ -247,8 +192,8 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
|||||||
values.isRequired,
|
values.isRequired,
|
||||||
dep_ids,
|
dep_ids,
|
||||||
category_ids,
|
category_ids,
|
||||||
chapters,
|
[],
|
||||||
treeData
|
[]
|
||||||
)
|
)
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
message.success("保存成功!");
|
message.success("保存成功!");
|
||||||
@ -264,150 +209,6 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
|||||||
setType(e.target.value);
|
setType(e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectData = (arr: any, videos: any) => {
|
|
||||||
setHours(arr);
|
|
||||||
setTreeData(videos);
|
|
||||||
setVideoVisible(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectChapterData = (arr: any, videos: any) => {
|
|
||||||
const data = [...chapters];
|
|
||||||
const keys = [...chapterHours];
|
|
||||||
keys[addvideoCurrent] = arr;
|
|
||||||
data[addvideoCurrent].hours = videos;
|
|
||||||
setChapters(data);
|
|
||||||
setChapterHours(keys);
|
|
||||||
setVideoVisible(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getChapterType = (e: any) => {
|
|
||||||
confirm({
|
|
||||||
title: "操作确认",
|
|
||||||
icon: <ExclamationCircleFilled />,
|
|
||||||
content: "切换列表选项会清空已添加课时,确认切换?",
|
|
||||||
centered: true,
|
|
||||||
okText: "确认",
|
|
||||||
cancelText: "取消",
|
|
||||||
onOk() {
|
|
||||||
setChapterType(e.target.value);
|
|
||||||
setChapters([]);
|
|
||||||
setHours([]);
|
|
||||||
setChapterHours([]);
|
|
||||||
setTreeData([]);
|
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
form.setFieldsValue({
|
|
||||||
hasChapter: chapterType,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const delHour = (id: number) => {
|
|
||||||
const data = [...treeData];
|
|
||||||
const index = data.findIndex((i: any) => i.rid === id);
|
|
||||||
if (index >= 0) {
|
|
||||||
data.splice(index, 1);
|
|
||||||
}
|
|
||||||
if (data.length > 0) {
|
|
||||||
setTreeData(data);
|
|
||||||
const keys = data.map((item: any) => item.rid);
|
|
||||||
setHours(keys);
|
|
||||||
} else {
|
|
||||||
setTreeData([]);
|
|
||||||
setHours([]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const transHour = (arr: any) => {
|
|
||||||
setHours(arr);
|
|
||||||
const data = [...treeData];
|
|
||||||
const newArr: any = [];
|
|
||||||
for (let i = 0; i < arr.length; i++) {
|
|
||||||
data.map((item: any) => {
|
|
||||||
if (item.rid === arr[i]) {
|
|
||||||
newArr.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setTreeData(newArr);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addNewChapter = () => {
|
|
||||||
const arr = [...chapters];
|
|
||||||
const keys = [...chapterHours];
|
|
||||||
arr.push({
|
|
||||||
name: "",
|
|
||||||
hours: [],
|
|
||||||
});
|
|
||||||
keys.push([]);
|
|
||||||
setChapters(arr);
|
|
||||||
setChapterHours(keys);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setChapterName = (index: number, value: string) => {
|
|
||||||
const arr = [...chapters];
|
|
||||||
arr[index].name = value;
|
|
||||||
setChapters(arr);
|
|
||||||
};
|
|
||||||
|
|
||||||
const delChapter = (index: number) => {
|
|
||||||
const arr = [...chapters];
|
|
||||||
const keys = [...chapterHours];
|
|
||||||
confirm({
|
|
||||||
title: "操作确认",
|
|
||||||
icon: <ExclamationCircleFilled />,
|
|
||||||
content: "删除章节会清空已添加课时,确认删除?",
|
|
||||||
centered: true,
|
|
||||||
okText: "确认",
|
|
||||||
cancelText: "取消",
|
|
||||||
onOk() {
|
|
||||||
arr.splice(index, 1);
|
|
||||||
keys.splice(index, 1);
|
|
||||||
setChapters(arr);
|
|
||||||
setChapterHours(keys);
|
|
||||||
},
|
|
||||||
onCancel() {},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const delChapterHour = (index: number, id: number) => {
|
|
||||||
const keys = [...chapterHours];
|
|
||||||
const data = [...chapters];
|
|
||||||
const current = data[index].hours.findIndex((i: any) => i.rid === id);
|
|
||||||
if (current >= 0) {
|
|
||||||
data[index].hours.splice(current, 1);
|
|
||||||
}
|
|
||||||
if (data[index].hours.length > 0) {
|
|
||||||
setChapters(data);
|
|
||||||
keys[index] = data[index].hours.map((item: any) => item.rid);
|
|
||||||
setChapterHours(keys);
|
|
||||||
} else {
|
|
||||||
keys[index] = [];
|
|
||||||
data[index].hours = [];
|
|
||||||
setChapters(data);
|
|
||||||
setChapterHours(keys);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const transChapterHour = (index: number, arr: any) => {
|
|
||||||
const keys = [...chapterHours];
|
|
||||||
keys[index] = arr;
|
|
||||||
setChapterHours(keys);
|
|
||||||
|
|
||||||
const data = [...chapters];
|
|
||||||
const newArr: any = [];
|
|
||||||
for (let i = 0; i < arr.length; i++) {
|
|
||||||
data[index].hours.map((item: any) => {
|
|
||||||
if (item.rid === arr[i]) {
|
|
||||||
newArr.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
data[index].hours = newArr;
|
|
||||||
setChapters(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Drawer
|
<Drawer
|
||||||
@ -426,22 +227,6 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
|||||||
width={634}
|
width={634}
|
||||||
>
|
>
|
||||||
<div className="float-left mt-24">
|
<div className="float-left mt-24">
|
||||||
<SelectResource
|
|
||||||
defaultKeys={
|
|
||||||
chapterType == 0 ? hours : chapterHours[addvideoCurrent]
|
|
||||||
}
|
|
||||||
open={videoVisible}
|
|
||||||
onCancel={() => {
|
|
||||||
setVideoVisible(false);
|
|
||||||
}}
|
|
||||||
onSelected={(arr: any, videos: any) => {
|
|
||||||
if (chapterType == 0) {
|
|
||||||
selectData(arr, videos);
|
|
||||||
} else {
|
|
||||||
selectChapterData(arr, videos);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
name="basic"
|
name="basic"
|
||||||
@ -491,7 +276,10 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
|||||||
rules={[{ required: true, message: "请选择课程类型!" }]}
|
rules={[{ required: true, message: "请选择课程类型!" }]}
|
||||||
>
|
>
|
||||||
<Radio.Group onChange={getType}>
|
<Radio.Group onChange={getType}>
|
||||||
<Radio value="open">公开课</Radio>
|
<Radio value="open">
|
||||||
|
公开课
|
||||||
|
<i className="iconfont icon-icon-tips c-gray ml-8" />
|
||||||
|
</Radio>
|
||||||
<Radio value="elective">部门课</Radio>
|
<Radio value="elective">部门课</Radio>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@ -617,111 +405,6 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
|||||||
placeholder="请输入课程简介"
|
placeholder="请输入课程简介"
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label="课时列表"
|
|
||||||
name="hasChapter"
|
|
||||||
rules={[{ required: true, message: "请选择课时列表!" }]}
|
|
||||||
>
|
|
||||||
<Radio.Group onChange={getChapterType}>
|
|
||||||
<Radio value={0}>无章节</Radio>
|
|
||||||
<Radio value={1}>有章节</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
{chapterType === 0 && (
|
|
||||||
<div className="c-flex">
|
|
||||||
<Form.Item>
|
|
||||||
<div className="ml-120">
|
|
||||||
<Button
|
|
||||||
onClick={() => setVideoVisible(true)}
|
|
||||||
type="primary"
|
|
||||||
>
|
|
||||||
添加课时
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Form.Item>
|
|
||||||
<div className={styles["hous-box"]}>
|
|
||||||
{treeData.length === 0 && (
|
|
||||||
<span className={styles["no-hours"]}>
|
|
||||||
请点击上方按钮添加课时
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{treeData.length > 0 && (
|
|
||||||
<TreeHours
|
|
||||||
data={treeData}
|
|
||||||
onRemoveItem={(id: number) => {
|
|
||||||
delHour(id);
|
|
||||||
}}
|
|
||||||
onUpdate={(arr: any[]) => {
|
|
||||||
transHour(arr);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{chapterType === 1 && (
|
|
||||||
<div className="c-flex">
|
|
||||||
{chapters.length > 0 &&
|
|
||||||
chapters.map((item: any, index: number) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={item.hours.length + "章节" + index}
|
|
||||||
className={styles["chapter-item"]}
|
|
||||||
>
|
|
||||||
<div className="d-flex">
|
|
||||||
<div className={styles["label"]}>
|
|
||||||
章节{index + 1}:
|
|
||||||
</div>
|
|
||||||
<Input
|
|
||||||
value={item.name}
|
|
||||||
className={styles["input"]}
|
|
||||||
onChange={(e) => {
|
|
||||||
setChapterName(index, e.target.value);
|
|
||||||
}}
|
|
||||||
placeholder="请在此处输入章节名称"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
className="mr-16"
|
|
||||||
type="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setVideoVisible(true);
|
|
||||||
setAddvideoCurrent(index);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
添加课时
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => delChapter(index)}>
|
|
||||||
删除章节
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className={styles["chapter-hous-box"]}>
|
|
||||||
{item.hours.length === 0 && (
|
|
||||||
<span className={styles["no-hours"]}>
|
|
||||||
请点击上方按钮添加课时
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{item.hours.length > 0 && (
|
|
||||||
<TreeHours
|
|
||||||
data={item.hours}
|
|
||||||
onRemoveItem={(id: number) => {
|
|
||||||
delChapterHour(index, id);
|
|
||||||
}}
|
|
||||||
onUpdate={(arr: any[]) => {
|
|
||||||
transChapterHour(index, arr);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
<Form.Item>
|
|
||||||
<div className="ml-120">
|
|
||||||
<Button onClick={() => addNewChapter()}>添加章节</Button>
|
|
||||||
</div>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
Space,
|
Space,
|
||||||
Tabs,
|
Tabs,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { course, department, resourceCategory } from "../../api";
|
import { course } from "../../api";
|
||||||
import styles from "./index.module.less";
|
import styles from "./index.module.less";
|
||||||
import { PlusOutlined, ExclamationCircleFilled } from "@ant-design/icons";
|
import { PlusOutlined, ExclamationCircleFilled } from "@ant-design/icons";
|
||||||
import type { ColumnsType } from "antd/es/table";
|
import type { ColumnsType } from "antd/es/table";
|
||||||
@ -20,6 +20,7 @@ import { TreeDepartment, TreeCategory, PerButton } from "../../compenents";
|
|||||||
import type { TabsProps } from "antd";
|
import type { TabsProps } from "antd";
|
||||||
import { CourseCreate } from "./compenents/create";
|
import { CourseCreate } from "./compenents/create";
|
||||||
import { CourseUpdate } from "./compenents/update";
|
import { CourseUpdate } from "./compenents/update";
|
||||||
|
import { CourseHourUpdate } from "./compenents/hour-update";
|
||||||
|
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
|
|
||||||
@ -50,6 +51,7 @@ export const CoursePage = () => {
|
|||||||
|
|
||||||
const [createVisible, setCreateVisible] = useState<boolean>(false);
|
const [createVisible, setCreateVisible] = useState<boolean>(false);
|
||||||
const [updateVisible, setUpdateVisible] = useState<boolean>(false);
|
const [updateVisible, setUpdateVisible] = useState<boolean>(false);
|
||||||
|
const [updateHourVisible, setHourUpdateVisible] = useState<boolean>(false);
|
||||||
const [cid, setCid] = useState<number>(0);
|
const [cid, setCid] = useState<number>(0);
|
||||||
|
|
||||||
const items: TabsProps["items"] = [
|
const items: TabsProps["items"] = [
|
||||||
@ -133,9 +135,35 @@ export const CoursePage = () => {
|
|||||||
title: "操作",
|
title: "操作",
|
||||||
key: "action",
|
key: "action",
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
width: 100,
|
width: 210,
|
||||||
render: (_, record: any) => (
|
render: (_, record: any) => (
|
||||||
<Space size="small">
|
<Space size="small">
|
||||||
|
<PerButton
|
||||||
|
type="link"
|
||||||
|
text="学员"
|
||||||
|
class="b-link c-red"
|
||||||
|
icon={null}
|
||||||
|
p="course"
|
||||||
|
onClick={() => {
|
||||||
|
setCid(Number(record.id));
|
||||||
|
console.log("学员" + record.id);
|
||||||
|
}}
|
||||||
|
disabled={null}
|
||||||
|
/>
|
||||||
|
<div className="form-column"></div>
|
||||||
|
<PerButton
|
||||||
|
type="link"
|
||||||
|
text="课时"
|
||||||
|
class="b-link c-red"
|
||||||
|
icon={null}
|
||||||
|
p="course"
|
||||||
|
onClick={() => {
|
||||||
|
setCid(Number(record.id));
|
||||||
|
setHourUpdateVisible(true);
|
||||||
|
}}
|
||||||
|
disabled={null}
|
||||||
|
/>
|
||||||
|
<div className="form-column"></div>
|
||||||
<PerButton
|
<PerButton
|
||||||
type="link"
|
type="link"
|
||||||
text="编辑"
|
text="编辑"
|
||||||
@ -305,6 +333,14 @@ export const CoursePage = () => {
|
|||||||
setRefresh(!refresh);
|
setRefresh(!refresh);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<CourseHourUpdate
|
||||||
|
id={cid}
|
||||||
|
open={updateHourVisible}
|
||||||
|
onCancel={() => {
|
||||||
|
setHourUpdateVisible(false);
|
||||||
|
setRefresh(!refresh);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<CourseUpdate
|
<CourseUpdate
|
||||||
id={cid}
|
id={cid}
|
||||||
open={updateVisible}
|
open={updateVisible}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user