线上课新建无章节课时选择逻辑优化

This commit is contained in:
禺狨 2023-03-17 12:18:17 +08:00
parent 60aa433589
commit 0460da6974
6 changed files with 155 additions and 47 deletions

View File

@ -12,8 +12,9 @@ interface VideoItem {
} }
interface PropsInterface { interface PropsInterface {
defaultKeys: any[];
open: boolean; open: boolean;
onSelected: (arr: any[], label: any[]) => void; onSelected: (arr: any[], videos: any[]) => void;
onCancel: () => void; onCancel: () => void;
} }
@ -21,7 +22,7 @@ export const SelectResource = (props: PropsInterface) => {
const [refresh, setRefresh] = useState(true); const [refresh, setRefresh] = useState(true);
const [tabKey, setTabKey] = useState(1); const [tabKey, setTabKey] = useState(1);
const [selectKeys, setSelectKeys] = useState<any>([]); const [selectKeys, setSelectKeys] = useState<any>([]);
const [selectLabel, setSelectLabel] = useState<any>([]); const [selectVideos, setSelectVideos] = useState<any>([]);
const items: TabsProps["items"] = [ const items: TabsProps["items"] = [
{ {
@ -31,11 +32,11 @@ export const SelectResource = (props: PropsInterface) => {
<div className="float-left"> <div className="float-left">
<UploadVideoSub <UploadVideoSub
label="视频" label="视频"
defaultCheckedList={[]} defaultCheckedList={props.defaultKeys}
open={refresh} open={refresh}
onSelected={(arr: any[], label: any[]) => { onSelected={(arr: any[], videos: any[]) => {
setSelectKeys(arr); setSelectKeys(arr);
setSelectLabel(label); setSelectVideos(videos);
}} }}
/> />
</div> </div>
@ -60,7 +61,7 @@ export const SelectResource = (props: PropsInterface) => {
open={props.open} open={props.open}
width={800} width={800}
maskClosable={false} maskClosable={false}
onOk={() => props.onSelected(selectKeys, selectLabel)} onOk={() => props.onSelected(selectKeys, selectVideos)}
> >
<Row> <Row>
<Tabs defaultActiveKey="1" items={items} onChange={onChange} /> <Tabs defaultActiveKey="1" items={items} onChange={onChange} />

View File

@ -20,7 +20,7 @@ interface PropsInterface {
defaultCheckedList: any[]; defaultCheckedList: any[];
label: string; label: string;
open: boolean; open: boolean;
onSelected: (arr: any[], label: any) => void; onSelected: (arr: any[], videos: []) => void;
} }
export const UploadVideoSub = (props: PropsInterface) => { export const UploadVideoSub = (props: PropsInterface) => {
@ -36,9 +36,7 @@ export const UploadVideoSub = (props: PropsInterface) => {
const [categoryCount, setCategoryCount] = useState<any>({}); const [categoryCount, setCategoryCount] = useState<any>({});
const [plainOptions, setPlainOptions] = useState<any>([]); const [plainOptions, setPlainOptions] = useState<any>([]);
const [checkedList, setCheckedList] = useState<CheckboxValueType[]>( const [checkedList, setCheckedList] = useState<CheckboxValueType[]>([]);
props.defaultCheckedList
);
const [indeterminate, setIndeterminate] = useState(false); const [indeterminate, setIndeterminate] = useState(false);
const [checkAll, setCheckAll] = useState(false); const [checkAll, setCheckAll] = useState(false);
@ -89,6 +87,10 @@ export const UploadVideoSub = (props: PropsInterface) => {
setVideoList([]); setVideoList([]);
setRefresh(!refresh); setRefresh(!refresh);
}; };
//重置选中的key
useEffect(() => {
setCheckedList(props.defaultCheckedList);
}, [props.defaultCheckedList]);
// 加载列表 // 加载列表
useEffect(() => { useEffect(() => {
@ -99,16 +101,21 @@ export const UploadVideoSub = (props: PropsInterface) => {
setCheckedList(list); setCheckedList(list);
setIndeterminate(!!list.length && list.length < plainOptions.length); setIndeterminate(!!list.length && list.length < plainOptions.length);
setCheckAll(list.length === plainOptions.length); setCheckAll(list.length === plainOptions.length);
let arrLabel: any = []; let arrVideos: any = [];
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
videoList.map((item: any) => { videoList.map((item: any) => {
if (item.id === list[i]) { if (item.id === list[i]) {
arrLabel.push(item.name); arrVideos.push({
name: item.name,
type: item.type,
rid: item.id,
duration: videosExtra[item.id].duration,
});
} }
}); });
} }
props.onSelected(list, arrLabel); props.onSelected(list, arrVideos);
}; };
const onCheckAllChange = (e: CheckboxChangeEvent) => { const onCheckAllChange = (e: CheckboxChangeEvent) => {
@ -116,9 +123,17 @@ export const UploadVideoSub = (props: PropsInterface) => {
setCheckedList(e.target.checked ? arr : []); setCheckedList(e.target.checked ? arr : []);
setIndeterminate(false); setIndeterminate(false);
setCheckAll(e.target.checked); setCheckAll(e.target.checked);
const arrLabel = videoList.map((item: any) => item.name); let arrVideos: any = [];
videoList.map((item: any) => {
arrVideos.push({
name: item.name,
type: item.type,
rid: item.id,
duration: videosExtra[item.id].duration,
});
});
if (e.target.checked) { if (e.target.checked) {
props.onSelected(arr, arrLabel); props.onSelected(arr, arrVideos);
} else { } else {
props.onSelected([], []); props.onSelected([], []);
} }

View File

@ -526,3 +526,11 @@ textarea.ant-input {
flex-direction: row-reverse; flex-direction: row-reverse;
} }
} }
.tree-video-title {
margin-left: 4px;
width: 346px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@ -32,7 +32,7 @@
/* Firefox */ /* Firefox */
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
/* Safari */ /* Safari */
padding: 16px; padding: 16px 16px 16px 0;
margin-left: 42px; margin-left: 42px;
.no-hours { .no-hours {
height: 24px; height: 24px;
@ -40,5 +40,6 @@
font-weight: 400; font-weight: 400;
color: rgba(0, 0, 0, 0.25); color: rgba(0, 0, 0, 0.25);
line-height: 24px; line-height: 24px;
margin-left: 16px;
} }
} }

View File

@ -16,6 +16,7 @@ import { course, department } from "../../../api/index";
import { UploadImageButton, SelectResource } from "../../../compenents"; import { UploadImageButton, SelectResource } from "../../../compenents";
import { ExclamationCircleFilled } from "@ant-design/icons"; 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;
@ -44,6 +45,7 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
const [chapters, setChapters] = useState<any>([]); const [chapters, setChapters] = useState<any>([]);
const [hours, setHours] = useState<any>([]); const [hours, setHours] = useState<any>([]);
const [videoVisible, setVideoVisible] = useState<boolean>(false); const [videoVisible, setVideoVisible] = useState<boolean>(false);
const [treeData, setTreeData] = useState<any>([]);
useEffect(() => { useEffect(() => {
getParams(); getParams();
@ -61,8 +63,10 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
hasChapter: 0, hasChapter: 0,
}); });
setThumb(defaultThumb1); setThumb(defaultThumb1);
setChapterType(0);
setChapters([]); setChapters([]);
setHours([]); setHours([]);
setTreeData([]);
}, [form, open]); }, [form, open]);
const getParams = () => { const getParams = () => {
@ -107,8 +111,10 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
const onFinish = (values: any) => { const onFinish = (values: any) => {
let dep_ids: any[] = []; let dep_ids: any[] = [];
for (let i = 0; i < values.dep_ids.length; i++) { if (type === "elective") {
dep_ids.push(values.dep_ids[i][values.dep_ids[i].length - 1]); for (let i = 0; i < values.dep_ids.length; i++) {
dep_ids.push(values.dep_ids[i][values.dep_ids[i].length - 1]);
}
} }
let category_ids: any[] = []; let category_ids: any[] = [];
for (let j = 0; j < values.category_ids.length; j++) { for (let j = 0; j < values.category_ids.length; j++) {
@ -117,7 +123,15 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
); );
} }
course course
.storeCourse(values.title, values.thumb, 1, dep_ids, category_ids, [], []) .storeCourse(
values.title,
values.thumb,
1,
dep_ids,
category_ids,
chapters,
treeData
)
.then((res: any) => { .then((res: any) => {
message.success("保存成功!"); message.success("保存成功!");
onCancel(); onCancel();
@ -132,6 +146,12 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
setType(e.target.value); setType(e.target.value);
}; };
const selectData = (arr: any, videos: any) => {
setHours(arr);
setTreeData(videos);
setVideoVisible(false);
};
const getChapterType = (e: any) => { const getChapterType = (e: any) => {
confirm({ confirm({
title: "操作确认", title: "操作确认",
@ -153,6 +173,22 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
}); });
}; };
const delHour = (id: number) => {
const data = [...treeData];
const index = data.findIndex((i: any) => i.id === 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([]);
}
};
return ( return (
<> <>
<Drawer <Drawer
@ -172,13 +208,13 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
> >
<div className="float-left mt-24"> <div className="float-left mt-24">
<SelectResource <SelectResource
defaultKeys={hours}
open={videoVisible} open={videoVisible}
onCancel={() => { onCancel={() => {
setVideoVisible(false); setVideoVisible(false);
}} }}
onSelected={(arr: any, label: any) => { onSelected={(arr: any, videos: any) => {
console.log("sel", arr, label); selectData(arr, videos);
setVideoVisible(false);
}} }}
/> />
<Form <Form
@ -224,24 +260,28 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
<Radio value="elective"></Radio> <Radio value="elective"></Radio>
</Radio.Group> </Radio.Group>
</Form.Item> </Form.Item>
<Form.Item
label="指派部门" {type === "elective" && (
name="dep_ids" <Form.Item
rules={[ label="指派部门"
{ name="dep_ids"
required: type === "elective" ? true : false, rules={[
message: "请选择课程指派部门!", {
}, required: true,
]} message: "请选择课程指派部门!",
> },
<Cascader ]}
style={{ width: 424 }} >
options={departments} <Cascader
multiple style={{ width: 424 }}
maxTagCount="responsive" options={departments}
placeholder="请选择课程指派部门" multiple
/> maxTagCount="responsive"
</Form.Item> placeholder="请选择课程指派部门"
/>
</Form.Item>
)}
<Form.Item <Form.Item
label="课程封面" label="课程封面"
name="thumb" name="thumb"
@ -365,10 +405,17 @@ export const CourseCreate: React.FC<PropInterface> = ({ open, onCancel }) => {
</div> </div>
</Form.Item> </Form.Item>
<div className={styles["hous-box"]}> <div className={styles["hous-box"]}>
{hours.length === 0 && ( {treeData.length === 0 && (
<span className={styles["no-hours"]}></span> <span className={styles["no-hours"]}></span>
)} )}
{hours.length > 0 && 13} {treeData.length > 0 && (
<TreeHours
data={treeData}
onRemoveItem={(id: number) => {
delHour(id);
}}
/>
)}
</div> </div>
</div> </div>
)} )}

View File

@ -1,14 +1,14 @@
import { message, Tree } from "antd"; import { message, Tree, Tooltip } from "antd";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
interface Option { interface Option {
id: string | number; id: number;
name: string; name: string;
} }
interface PropInterface { interface PropInterface {
data: Option[]; data: Option[];
onUpdate: () => void; onRemoveItem: (id: number) => void;
} }
export const TreeHours = (props: PropInterface) => { export const TreeHours = (props: PropInterface) => {
@ -16,18 +16,54 @@ export const TreeHours = (props: PropInterface) => {
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
useEffect(() => { useEffect(() => {
const hours = props.data; const hours = props.data;
if (hours.length === 0) { if (hours.length === 0) {
return; return;
} }
checkTree(hours);
}, [props.data]);
const checkTree = (hours: any) => {
const arr = []; const arr = [];
for (let i = 0; i < hours.length; i++) { for (let i = 0; i < hours.length; i++) {
arr.push({ arr.push({
title: hours[i].name, title: (
<div className="d-flex">
<div className="d-flex">
<i
className="iconfont icon-icon-video"
style={{
fontSize: 16,
color: "rgba(0,0,0,0.3)",
}}
/>
<div className="tree-video-title mr-24">{hours[i].name}</div>
</div>
<Tooltip placement="top" title="可拖拽排序">
<i
className="iconfont icon-icon-drag mr-16"
style={{ fontSize: 24 }}
/>
</Tooltip>
<i
className="iconfont icon-icon-delete"
style={{ fontSize: 24 }}
onClick={() => removeItem(hours[i].id)}
/>
</div>
),
key: hours[i].id, key: hours[i].id,
}); });
} }
setTreeData(arr); setTreeData(arr);
}, [props.data]); };
const removeItem = (id: number) => {
if (id === 0) {
return;
}
props.onRemoveItem(id);
};
return ( return (
<div> <div>