mirror of
https://github.com/PlayEdu/backend
synced 2025-07-29 02:41:52 +08:00
Compare commits
14 Commits
d06214aec0
...
da6fc9639f
Author | SHA1 | Date | |
---|---|---|---|
|
da6fc9639f | ||
|
d2e28b9548 | ||
|
e12c13e5cd | ||
|
b553659a95 | ||
|
f69b432b12 | ||
|
d6a0d2bfec | ||
|
42f5d77e4f | ||
|
aa8e1d88aa | ||
|
f7fe5e35f4 | ||
|
8013964441 | ||
|
caf377eb1a | ||
|
272e9a5d50 | ||
|
7d37329713 | ||
|
e0bd169069 |
@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Row, Col, Empty, Table, Spin } from "antd";
|
||||
import { Row, Col, Empty, Table, Spin, Typography, Input, Button } from "antd";
|
||||
import type { ColumnsType } from "antd/es/table";
|
||||
import { resource } from "../../api";
|
||||
import styles from "./index.module.less";
|
||||
@ -47,6 +47,7 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
|
||||
const [size, setSize] = useState(10);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
|
||||
const [title, setTitle] = useState("");
|
||||
|
||||
// 加载列表
|
||||
useEffect(() => {
|
||||
@ -70,7 +71,7 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
|
||||
size,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
title,
|
||||
"WORD,EXCEL,PPT,PDF,TXT,RAR,ZIP",
|
||||
categoryIds
|
||||
)
|
||||
@ -92,6 +93,7 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
|
||||
const resetVideoList = () => {
|
||||
setPage(1);
|
||||
setVideoList([]);
|
||||
setTitle("");
|
||||
setRefresh(!refresh);
|
||||
};
|
||||
|
||||
@ -178,14 +180,42 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
|
||||
</Col>
|
||||
<Col span={17}>
|
||||
<Row style={{ marginBottom: 24, paddingLeft: 10 }}>
|
||||
<Col span={24}>
|
||||
<div className="float-left j-b-flex">
|
||||
<UploadCoursewareButton
|
||||
categoryIds={category_ids}
|
||||
onUpdate={() => {
|
||||
resetVideoList();
|
||||
}}
|
||||
></UploadCoursewareButton>
|
||||
</Col>
|
||||
<div className="d-flex">
|
||||
<div className="d-flex mr-24">
|
||||
<Typography.Text>名称:</Typography.Text>
|
||||
<Input
|
||||
value={title}
|
||||
onChange={(e) => {
|
||||
setTitle(e.target.value);
|
||||
}}
|
||||
allowClear
|
||||
style={{ width: 160 }}
|
||||
placeholder="请输入名称关键字"
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
<Button className="mr-16" onClick={resetVideoList}>
|
||||
重 置
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setPage(1);
|
||||
setRefresh(!refresh);
|
||||
}}
|
||||
>
|
||||
查 询
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Row>
|
||||
{init && (
|
||||
<div className="float-left text-center mt-30">
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Row, Col, Empty, Table, Spin } from "antd";
|
||||
import { Row, Col, Empty, Table, Spin, Typography, Input, Button } from "antd";
|
||||
import type { ColumnsType } from "antd/es/table";
|
||||
import { resource } from "../../api";
|
||||
import styles from "./index.module.less";
|
||||
@ -48,6 +48,7 @@ export const UploadVideoSub = (props: PropsInterface) => {
|
||||
const [size, setSize] = useState(10);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
|
||||
const [title, setTitle] = useState("");
|
||||
|
||||
// 加载列表
|
||||
useEffect(() => {
|
||||
@ -66,7 +67,7 @@ export const UploadVideoSub = (props: PropsInterface) => {
|
||||
setLoading(true);
|
||||
let categoryIds = category_ids.join(",");
|
||||
resource
|
||||
.resourceList(page, size, "", "", "", "VIDEO", categoryIds)
|
||||
.resourceList(page, size, "", "", title, "VIDEO", categoryIds)
|
||||
.then((res: any) => {
|
||||
setTotal(res.data.result.total);
|
||||
setVideoExtra(res.data.videos_extra);
|
||||
@ -85,6 +86,7 @@ export const UploadVideoSub = (props: PropsInterface) => {
|
||||
const resetVideoList = () => {
|
||||
setPage(1);
|
||||
setVideoList([]);
|
||||
setTitle("");
|
||||
setRefresh(!refresh);
|
||||
};
|
||||
|
||||
@ -170,14 +172,42 @@ export const UploadVideoSub = (props: PropsInterface) => {
|
||||
</Col>
|
||||
<Col span={17}>
|
||||
<Row style={{ marginBottom: 24, paddingLeft: 10 }}>
|
||||
<Col span={24}>
|
||||
<div className="float-left j-b-flex">
|
||||
<UploadVideoButton
|
||||
categoryIds={category_ids}
|
||||
onUpdate={() => {
|
||||
resetVideoList();
|
||||
}}
|
||||
></UploadVideoButton>
|
||||
</Col>
|
||||
<div className="d-flex">
|
||||
<div className="d-flex mr-24">
|
||||
<Typography.Text>名称:</Typography.Text>
|
||||
<Input
|
||||
value={title}
|
||||
onChange={(e) => {
|
||||
setTitle(e.target.value);
|
||||
}}
|
||||
allowClear
|
||||
style={{ width: 160 }}
|
||||
placeholder="请输入名称关键字"
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
<Button className="mr-16" onClick={resetVideoList}>
|
||||
重 置
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setPage(1);
|
||||
setRefresh(!refresh);
|
||||
}}
|
||||
>
|
||||
查 询
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Row>
|
||||
{init && (
|
||||
<div className="float-left text-center mt-30">
|
||||
|
@ -20,6 +20,10 @@ code {
|
||||
monospace;
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-174px {
|
||||
max-width: 134px;
|
||||
overflow: hidden;
|
||||
|
@ -234,7 +234,7 @@ export const CourseHourUpdate: React.FC<PropInterface> = ({
|
||||
const arr = [...chapters];
|
||||
if (arr[index].id) {
|
||||
courseChapter
|
||||
.updateCourseChapter(id, Number(arr[index].id), value, arr.length)
|
||||
.updateCourseChapter(id, Number(arr[index].id), value, index + 1)
|
||||
.then((res: any) => {
|
||||
console.log("ok");
|
||||
getDetail();
|
||||
|
@ -65,6 +65,7 @@ export const TreeHours = (props: PropInterface) => {
|
||||
}
|
||||
props.onRemoveItem(id);
|
||||
};
|
||||
|
||||
const onDrop: TreeProps["onDrop"] = (info) => {
|
||||
const dropKey = info.node.key;
|
||||
const dragKey = info.dragNode.key;
|
||||
@ -96,23 +97,35 @@ export const TreeHours = (props: PropInterface) => {
|
||||
|
||||
// Find dragObject
|
||||
let dragObj: DataNode;
|
||||
loop(data, dragKey, (item, index, arr) => {
|
||||
arr.splice(index, 1);
|
||||
dragObj = item;
|
||||
});
|
||||
let dragLength = (info.dragNode as any).props.pos.split("-").length;
|
||||
let dropLength = (info.node as any).props.pos.split("-").length;
|
||||
|
||||
if (!info.dropToGap) {
|
||||
// Drop on the content
|
||||
loop(data, dropKey, (item) => {
|
||||
item.children = item.children || [];
|
||||
// where to insert 示例添加到头部,可以是随意位置
|
||||
item.children.unshift(dragObj);
|
||||
});
|
||||
if (
|
||||
(dropPosition == 0 && dropPos.length == 3) ||
|
||||
(dropPosition == 0 && dropPos.length == 2 && dragLength == 2)
|
||||
) {
|
||||
} else {
|
||||
loop(data, dragKey, (item, index, arr) => {
|
||||
arr.splice(index, 1);
|
||||
dragObj = item;
|
||||
});
|
||||
loop(data, dropKey, (item) => {
|
||||
item.children = item.children || [];
|
||||
// where to insert 示例添加到头部,可以是随意位置
|
||||
item.children.unshift(dragObj);
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
((info.node as any).props.children || []).length > 0 && // Has children
|
||||
(info.node as any).props.expanded && // Is expanded
|
||||
dropPosition === 1 // On the bottom gap
|
||||
) {
|
||||
loop(data, dragKey, (item, index, arr) => {
|
||||
arr.splice(index, 1);
|
||||
dragObj = item;
|
||||
});
|
||||
loop(data, dropKey, (item) => {
|
||||
item.children = item.children || [];
|
||||
// where to insert 示例添加到头部,可以是随意位置
|
||||
@ -121,6 +134,16 @@ export const TreeHours = (props: PropInterface) => {
|
||||
// item to the tail of the children
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
(dragLength == 3 && dropLength == 2) ||
|
||||
(dragLength == 2 && dropLength == 3)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
loop(data, dragKey, (item, index, arr) => {
|
||||
arr.splice(index, 1);
|
||||
dragObj = item;
|
||||
});
|
||||
let ar: DataNode[] = [];
|
||||
let i: number;
|
||||
loop(data, dropKey, (_item, index, arr) => {
|
||||
|
@ -222,7 +222,7 @@ export const MemberLearnProgressDialog: React.FC<PropInterface> = ({
|
||||
maskClosable={false}
|
||||
footer={null}
|
||||
>
|
||||
<div className="d-flex mt-24">
|
||||
<div className="w-100 d-flex mt-24">
|
||||
<PerButton
|
||||
type="primary"
|
||||
text="重置学习记录"
|
||||
@ -236,7 +236,7 @@ export const MemberLearnProgressDialog: React.FC<PropInterface> = ({
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="d-flex mt-24"
|
||||
className="w-100 d-flex mt-24"
|
||||
style={{ maxHeight: 800, overflowY: "auto" }}
|
||||
>
|
||||
<Table
|
||||
|
@ -57,6 +57,22 @@ type DepartmentsListModel = {
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
type PerCourseRecordsModel = {
|
||||
[key: number]: {
|
||||
course_id: number;
|
||||
created_at: string;
|
||||
finished_at: string;
|
||||
finished_duration: number;
|
||||
hour_id: number;
|
||||
id: number;
|
||||
is_finished: number;
|
||||
real_duration: number;
|
||||
total_duration: number;
|
||||
updated_at: string;
|
||||
user_id: number;
|
||||
};
|
||||
};
|
||||
|
||||
const MemberLearnPage = () => {
|
||||
let chartRef = useRef(null);
|
||||
const navigate = useNavigate();
|
||||
@ -69,6 +85,7 @@ const MemberLearnPage = () => {
|
||||
const [currentCourses, setCurrentCourses] = useState<DataType[]>([]);
|
||||
const [openCourses, setOpenCourses] = useState<CourseModel[]>([]);
|
||||
const [records, setRecords] = useState<UserCourseRecordsModel>({});
|
||||
const [perRecords, setPerRecords] = useState<PerCourseRecordsModel>({});
|
||||
const [hourCount, setHourCount] = useState<HourCountModel>({});
|
||||
const [total2, setTotal2] = useState(0);
|
||||
const [refresh2, setRefresh2] = useState(false);
|
||||
@ -194,6 +211,7 @@ const MemberLearnPage = () => {
|
||||
setOpenCourses(res.data.open_courses);
|
||||
setHourCount(res.data.user_course_hour_count);
|
||||
setRecords(res.data.user_course_records);
|
||||
setPerRecords(res.data.per_course_earliest_records);
|
||||
if (res.data.departments.length > 0) {
|
||||
let box: OptionModel[] = [];
|
||||
res.data.departments.map((item: any) => {
|
||||
@ -247,8 +265,8 @@ const MemberLearnPage = () => {
|
||||
dataIndex: "created_at",
|
||||
render: (_, record: any) => (
|
||||
<>
|
||||
{records[record.id] ? (
|
||||
<span>{dateFormat(records[record.id].created_at)}</span>
|
||||
{perRecords[record.id] ? (
|
||||
<span>{dateFormat(perRecords[record.id].created_at)}</span>
|
||||
) : (
|
||||
<span>-</span>
|
||||
)}
|
||||
|
@ -149,12 +149,12 @@ export const SystemAdministratorCreate: React.FC<PropInterface> = ({
|
||||
<Form.Item
|
||||
label="邮箱"
|
||||
name="email"
|
||||
rules={[{ required: true, message: "请输入学员邮箱!" }]}
|
||||
rules={[{ required: true, message: "请输入管理员邮箱!" }]}
|
||||
>
|
||||
<Input
|
||||
allowClear
|
||||
style={{ width: 200 }}
|
||||
placeholder="请输入学员邮箱"
|
||||
placeholder="请输入管理员邮箱"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
|
@ -111,7 +111,7 @@ export const SystemAdministratorUpdate: React.FC<PropInterface> = ({
|
||||
<>
|
||||
{open ? (
|
||||
<Modal
|
||||
title="编辑管理人员"
|
||||
title="编辑管理员"
|
||||
centered
|
||||
forceRender
|
||||
open={true}
|
||||
@ -168,12 +168,12 @@ export const SystemAdministratorUpdate: React.FC<PropInterface> = ({
|
||||
<Form.Item
|
||||
label="邮箱"
|
||||
name="email"
|
||||
rules={[{ required: true, message: "请输入学员邮箱!" }]}
|
||||
rules={[{ required: true, message: "请输入管理员邮箱!" }]}
|
||||
>
|
||||
<Input
|
||||
allowClear
|
||||
style={{ width: 200 }}
|
||||
placeholder="请输入学员邮箱"
|
||||
placeholder="请输入管理员邮箱"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="密码" name="password">
|
||||
|
Loading…
x
Reference in New Issue
Block a user