Merge pull request !1 from 白书科技/fix/0804
This commit is contained in:
白书科技 2023-08-08 01:35:30 +00:00 committed by Gitee
commit beb5a011f5
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
34 changed files with 913 additions and 534 deletions

View File

@ -34,8 +34,8 @@ export function storeCourse(
isRequired: number, isRequired: number,
depIds: number[], depIds: number[],
categoryIds: number[], categoryIds: number[],
chapters: number[], chapters: any[],
hours: number[], hours: any[],
attachments: any[] attachments: any[]
) { ) {
return client.post("/backend/v1/course/create", { return client.post("/backend/v1/course/create", {

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Row, Modal, Tabs, Spin } from "antd"; import { Row, Modal, Tabs } from "antd";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { UploadCoursewareSub } from "../../compenents"; import { UploadCoursewareSub } from "../../compenents";
import type { TabsProps } from "antd"; import type { TabsProps } from "antd";
@ -11,15 +11,20 @@ interface PropsInterface {
onCancel: () => void; onCancel: () => void;
} }
type selAttachmentModel = {
name: string;
rid: number;
type: string;
};
export const SelectAttachment = (props: PropsInterface) => { export const SelectAttachment = (props: PropsInterface) => {
const [refresh, setRefresh] = useState(true); const [refresh, setRefresh] = useState(true);
const [init, setInit] = useState(true);
const [tabKey, setTabKey] = useState(1); const [tabKey, setTabKey] = useState(1);
const [selectKeys, setSelectKeys] = useState<any>([]); const [selectKeys, setSelectKeys] = useState<number[]>([]);
const [selectVideos, setSelectVideos] = useState<any>([]); const [selectVideos, setSelectVideos] = useState<selAttachmentModel[]>([]);
useEffect(() => { useEffect(() => {
setInit(true);
setRefresh(!refresh); setRefresh(!refresh);
}, [props.open]); }, [props.open]);
@ -28,23 +33,15 @@ export const SelectAttachment = (props: PropsInterface) => {
key: "1", key: "1",
label: `课件`, label: `课件`,
children: ( children: (
<div <UploadCoursewareSub
className="float-left" label="课件"
style={{ display: init ? "none" : "block" }} defaultCheckedList={props.defaultKeys}
> open={refresh}
<UploadCoursewareSub onSelected={(arr: any[], videos: any[]) => {
label="课件" setSelectKeys(arr);
defaultCheckedList={props.defaultKeys} setSelectVideos(videos);
open={refresh} }}
onSelected={(arr: any[], videos: any[]) => { />
setSelectKeys(arr);
setSelectVideos(videos);
}}
onSuccess={() => {
setInit(false);
}}
/>
</div>
), ),
}, },
]; ];
@ -77,11 +74,6 @@ export const SelectAttachment = (props: PropsInterface) => {
<Row> <Row>
<Tabs defaultActiveKey="1" items={items} onChange={onChange} /> <Tabs defaultActiveKey="1" items={items} onChange={onChange} />
</Row> </Row>
{init && (
<div className="float-left text-center mt-30">
<Spin></Spin>
</div>
)}
</Modal> </Modal>
) : null} ) : null}
</> </>

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Row, Modal, Tabs, Spin } from "antd"; import { Row, Modal, Tabs } from "antd";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { UploadVideoSub } from "../../compenents"; import { UploadVideoSub } from "../../compenents";
import type { TabsProps } from "antd"; import type { TabsProps } from "antd";
@ -11,15 +11,20 @@ interface PropsInterface {
onCancel: () => void; onCancel: () => void;
} }
type selVideosModel = {
name: string;
rid: number;
type: string;
duration: number;
};
export const SelectResource = (props: PropsInterface) => { export const SelectResource = (props: PropsInterface) => {
const [refresh, setRefresh] = useState(true); const [refresh, setRefresh] = useState(true);
const [init, setInit] = useState(true);
const [tabKey, setTabKey] = useState(1); const [tabKey, setTabKey] = useState(1);
const [selectKeys, setSelectKeys] = useState<any>([]); const [selectKeys, setSelectKeys] = useState<number[]>([]);
const [selectVideos, setSelectVideos] = useState<any>([]); const [selectVideos, setSelectVideos] = useState<selVideosModel[]>([]);
useEffect(() => { useEffect(() => {
setInit(true);
setRefresh(!refresh); setRefresh(!refresh);
}, [props.open]); }, [props.open]);
@ -28,10 +33,7 @@ export const SelectResource = (props: PropsInterface) => {
key: "1", key: "1",
label: `视频`, label: `视频`,
children: ( children: (
<div <div className="float-left">
className="float-left"
style={{ display: init ? "none" : "block" }}
>
<UploadVideoSub <UploadVideoSub
label="视频" label="视频"
defaultCheckedList={props.defaultKeys} defaultCheckedList={props.defaultKeys}
@ -40,9 +42,6 @@ export const SelectResource = (props: PropsInterface) => {
setSelectKeys(arr); setSelectKeys(arr);
setSelectVideos(videos); setSelectVideos(videos);
}} }}
onSuccess={() => {
setInit(false);
}}
/> />
</div> </div>
), ),
@ -77,11 +76,6 @@ export const SelectResource = (props: PropsInterface) => {
<Row> <Row>
<Tabs defaultActiveKey="1" items={items} onChange={onChange} /> <Tabs defaultActiveKey="1" items={items} onChange={onChange} />
</Row> </Row>
{init && (
<div className="float-left text-center mt-30">
<Spin></Spin>
</div>
)}
</Modal> </Modal>
) : null} ) : null}
</> </>

View File

@ -18,7 +18,7 @@ interface PropInterface {
export const TreeCategory = (props: PropInterface) => { export const TreeCategory = (props: PropInterface) => {
const [treeData, setTreeData] = useState<any>([]); const [treeData, setTreeData] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [selectKey, setSelectKey] = useState<any>([]); const [selectKey, setSelectKey] = useState<number[]>([]);
useEffect(() => { useEffect(() => {
if (props.selected && props.selected.length > 0) { if (props.selected && props.selected.length > 0) {
@ -28,7 +28,7 @@ export const TreeCategory = (props: PropInterface) => {
useEffect(() => { useEffect(() => {
resourceCategory.resourceCategoryList().then((res: any) => { resourceCategory.resourceCategoryList().then((res: any) => {
const categories = res.data.categories; const categories: CategoriesBoxModel = res.data.categories;
if (JSON.stringify(categories) !== "{}") { if (JSON.stringify(categories) !== "{}") {
const new_arr: Option[] = checkArr(categories, 0); const new_arr: Option[] = checkArr(categories, 0);
if (props.type === "no-cate") { if (props.type === "no-cate") {
@ -43,7 +43,7 @@ export const TreeCategory = (props: PropInterface) => {
}); });
}, []); }, []);
const checkArr = (categories: any[], id: number) => { const checkArr = (categories: CategoriesBoxModel, id: number) => {
const arr = []; const arr = [];
for (let i = 0; i < categories[id].length; i++) { for (let i = 0; i < categories[id].length; i++) {
if (!categories[categories[id][i].id]) { if (!categories[categories[id][i].id]) {

View File

@ -20,7 +20,7 @@ interface PropInterface {
export const TreeDepartment = (props: PropInterface) => { export const TreeDepartment = (props: PropInterface) => {
const [treeData, setTreeData] = useState<any>([]); const [treeData, setTreeData] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [selectKey, setSelectKey] = useState<any>([]); const [selectKey, setSelectKey] = useState<number[]>([]);
const [userTotal, setUserTotal] = useState(0); const [userTotal, setUserTotal] = useState(0);
useEffect(() => { useEffect(() => {
@ -32,8 +32,8 @@ export const TreeDepartment = (props: PropInterface) => {
useEffect(() => { useEffect(() => {
setLoading(true); setLoading(true);
department.departmentList().then((res: any) => { department.departmentList().then((res: any) => {
const departments = res.data.departments; const departments: DepartmentsBoxModel = res.data.departments;
const departCount = res.data.dep_user_count; const departCount: DepIdsModel = res.data.dep_user_count;
setUserTotal(res.data.user_total); setUserTotal(res.data.user_total);
if (JSON.stringify(departments) !== "{}") { if (JSON.stringify(departments) !== "{}") {
if (props.showNum) { if (props.showNum) {
@ -57,7 +57,11 @@ export const TreeDepartment = (props: PropInterface) => {
}); });
}, [props.refresh]); }, [props.refresh]);
const checkNewArr = (departments: any[], id: number, counts: any) => { const checkNewArr = (
departments: DepartmentsBoxModel,
id: number,
counts: any
) => {
const arr = []; const arr = [];
for (let i = 0; i < departments[id].length; i++) { for (let i = 0; i < departments[id].length; i++) {
if (!departments[departments[id][i].id]) { if (!departments[departments[id][i].id]) {
@ -89,7 +93,7 @@ export const TreeDepartment = (props: PropInterface) => {
return arr; return arr;
}; };
const checkArr = (departments: any[], id: number) => { const checkArr = (departments: DepartmentsBoxModel, id: number) => {
const arr = []; const arr = [];
for (let i = 0; i < departments[id].length; i++) { for (let i = 0; i < departments[id].length; i++) {
if (!departments[departments[id][i].id]) { if (!departments[departments[id][i].id]) {

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Row, Col, Empty, Table } from "antd"; import { Row, Col, Empty, Table, Spin } from "antd";
import type { ColumnsType } from "antd/es/table"; import type { ColumnsType } from "antd/es/table";
import { resource } from "../../api"; import { resource } from "../../api";
import styles from "./index.module.less"; import styles from "./index.module.less";
@ -34,10 +34,10 @@ interface PropsInterface {
label: string; label: string;
open: boolean; open: boolean;
onSelected: (arr: any[], videos: []) => void; onSelected: (arr: any[], videos: []) => void;
onSuccess: () => void;
} }
export const UploadCoursewareSub = (props: PropsInterface) => { export const UploadCoursewareSub = (props: PropsInterface) => {
const [init, setInit] = useState(true);
const [category_ids, setCategoryIds] = useState<any>([]); const [category_ids, setCategoryIds] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [videoList, setVideoList] = useState<VideoItem[]>([]); const [videoList, setVideoList] = useState<VideoItem[]>([]);
@ -50,6 +50,7 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
// 加载列表 // 加载列表
useEffect(() => { useEffect(() => {
setInit(true);
getvideoList(); getvideoList();
}, [props.open, category_ids, refresh, page, size]); }, [props.open, category_ids, refresh, page, size]);
@ -61,6 +62,7 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
// 获取列表 // 获取列表
const getvideoList = () => { const getvideoList = () => {
setLoading(true);
let categoryIds = category_ids.join(","); let categoryIds = category_ids.join(",");
resource resource
.resourceList( .resourceList(
@ -76,9 +78,12 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
setTotal(res.data.result.total); setTotal(res.data.result.total);
setExistingTypes(res.data.existing_types); setExistingTypes(res.data.existing_types);
setVideoList(res.data.result.data); setVideoList(res.data.result.data);
props.onSuccess(); setLoading(false);
setInit(false);
}) })
.catch((err) => { .catch((err) => {
setLoading(false);
setInit(false);
console.log("错误,", err); console.log("错误,", err);
}); });
}; };
@ -154,12 +159,22 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
<> <>
<Row style={{ width: 752, minHeight: 520 }}> <Row style={{ width: 752, minHeight: 520 }}>
<Col span={7}> <Col span={7}>
<TreeCategory {init && (
selected={[]} <div className="float-left text-center mt-30">
type="no-cate" <Spin></Spin>
text={props.label} </div>
onUpdate={(keys: any) => setCategoryIds(keys)} )}
/> <div
className="float-left"
style={{ display: init ? "none" : "block" }}
>
<TreeCategory
selected={[]}
type="no-cate"
text={props.label}
onUpdate={(keys: any) => setCategoryIds(keys)}
/>
</div>
</Col> </Col>
<Col span={17}> <Col span={17}>
<Row style={{ marginBottom: 24, paddingLeft: 10 }}> <Row style={{ marginBottom: 24, paddingLeft: 10 }}>
@ -172,7 +187,15 @@ export const UploadCoursewareSub = (props: PropsInterface) => {
></UploadCoursewareButton> ></UploadCoursewareButton>
</Col> </Col>
</Row> </Row>
<div className={styles["video-list"]}> {init && (
<div className="float-left text-center mt-30">
<Spin></Spin>
</div>
)}
<div
className={styles["video-list"]}
style={{ display: init ? "none" : "block" }}
>
{videoList.length === 0 && ( {videoList.length === 0 && (
<Col span={24} style={{ marginTop: 150 }}> <Col span={24} style={{ marginTop: 150 }}>
<Empty description="暂无课件" /> <Empty description="暂无课件" />

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Row, Col, Empty, Table } from "antd"; import { Row, Col, Empty, Table, Spin } from "antd";
import type { ColumnsType } from "antd/es/table"; import type { ColumnsType } from "antd/es/table";
import { resource } from "../../api"; import { resource } from "../../api";
import styles from "./index.module.less"; import styles from "./index.module.less";
@ -35,10 +35,10 @@ interface PropsInterface {
label: string; label: string;
open: boolean; open: boolean;
onSelected: (arr: any[], videos: []) => void; onSelected: (arr: any[], videos: []) => void;
onSuccess: () => void;
} }
export const UploadVideoSub = (props: PropsInterface) => { export const UploadVideoSub = (props: PropsInterface) => {
const [init, setInit] = useState(true);
const [category_ids, setCategoryIds] = useState<any>([]); const [category_ids, setCategoryIds] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [videoList, setVideoList] = useState<VideoItem[]>([]); const [videoList, setVideoList] = useState<VideoItem[]>([]);
@ -51,6 +51,7 @@ export const UploadVideoSub = (props: PropsInterface) => {
// 加载列表 // 加载列表
useEffect(() => { useEffect(() => {
setInit(true);
getvideoList(); getvideoList();
}, [props.open, category_ids, refresh, page, size]); }, [props.open, category_ids, refresh, page, size]);
@ -62,6 +63,7 @@ export const UploadVideoSub = (props: PropsInterface) => {
// 获取列表 // 获取列表
const getvideoList = () => { const getvideoList = () => {
setLoading(true);
let categoryIds = category_ids.join(","); let categoryIds = category_ids.join(",");
resource resource
.resourceList(page, size, "", "", "", "VIDEO", categoryIds) .resourceList(page, size, "", "", "", "VIDEO", categoryIds)
@ -69,9 +71,12 @@ export const UploadVideoSub = (props: PropsInterface) => {
setTotal(res.data.result.total); setTotal(res.data.result.total);
setVideoExtra(res.data.videos_extra); setVideoExtra(res.data.videos_extra);
setVideoList(res.data.result.data); setVideoList(res.data.result.data);
props.onSuccess(); setLoading(false);
setInit(false);
}) })
.catch((err) => { .catch((err) => {
setLoading(false);
setInit(false);
console.log("错误,", err); console.log("错误,", err);
}); });
}; };
@ -154,12 +159,22 @@ export const UploadVideoSub = (props: PropsInterface) => {
<> <>
<Row style={{ width: 752, minHeight: 520 }}> <Row style={{ width: 752, minHeight: 520 }}>
<Col span={7}> <Col span={7}>
<TreeCategory {init && (
selected={[]} <div className="float-left text-center mt-30">
type="no-cate" <Spin></Spin>
text={props.label} </div>
onUpdate={(keys: any) => setCategoryIds(keys)} )}
/> <div
className="float-left"
style={{ display: init ? "none" : "block" }}
>
<TreeCategory
selected={[]}
type="no-cate"
text={props.label}
onUpdate={(keys: any) => setCategoryIds(keys)}
/>
</div>
</Col> </Col>
<Col span={17}> <Col span={17}>
<Row style={{ marginBottom: 24, paddingLeft: 10 }}> <Row style={{ marginBottom: 24, paddingLeft: 10 }}>
@ -172,7 +187,15 @@ export const UploadVideoSub = (props: PropsInterface) => {
></UploadVideoButton> ></UploadVideoButton>
</Col> </Col>
</Row> </Row>
<div className={styles["video-list"]}> {init && (
<div className="float-left text-center mt-30">
<Spin></Spin>
</div>
)}
<div
className={styles["video-list"]}
style={{ display: init ? "none" : "block" }}
>
{videoList.length === 0 && ( {videoList.length === 0 && (
<Col span={24} style={{ marginTop: 150 }}> <Col span={24} style={{ marginTop: 150 }}>
<Empty description="暂无视频" /> <Empty description="暂无视频" />

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Button, Drawer, Form, Modal, message } from "antd"; import { Button, Drawer, Form, Modal, message, Spin } from "antd";
import styles from "./hour-update.module.less"; import styles from "./hour-update.module.less";
import { course, courseAttachment } from "../../../api/index"; import { course, courseAttachment } from "../../../api/index";
import { SelectAttachment } from "../../../compenents"; import { SelectAttachment } from "../../../compenents";
@ -20,11 +20,15 @@ export const CourseAttachmentUpdate: React.FC<PropInterface> = ({
onCancel, onCancel,
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [init, setInit] = useState(true);
const [attachmentVisible, setAttachmentVisible] = useState<boolean>(false); const [attachmentVisible, setAttachmentVisible] = useState<boolean>(false);
const [attachmentData, setAttachmentData] = useState<any>([]); const [attachmentData, setAttachmentData] = useState<AttachmentDataModel[]>(
const [attachments, setAttachments] = useState<any>([]); []
);
const [attachments, setAttachments] = useState<number[]>([]);
useEffect(() => { useEffect(() => {
setInit(true);
if (id === 0) { if (id === 0) {
return; return;
} }
@ -43,6 +47,7 @@ export const CourseAttachmentUpdate: React.FC<PropInterface> = ({
setAttachmentData(arr); setAttachmentData(arr);
setAttachments(keys); setAttachments(keys);
} }
setInit(false);
}); });
}; };
@ -169,47 +174,57 @@ export const CourseAttachmentUpdate: React.FC<PropInterface> = ({
selectAttachmentData(arr, videos); selectAttachmentData(arr, videos);
}} }}
></SelectAttachment> ></SelectAttachment>
<Form {init && (
form={form} <div className="float-left text-center mt-30">
name="attachment-update-basic" <Spin></Spin>
labelCol={{ span: 5 }}
wrapperCol={{ span: 19 }}
initialValues={{ remember: true }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<div className="c-flex">
<Form.Item>
<div className="ml-42">
<Button
onClick={() => setAttachmentVisible(true)}
type="primary"
>
</Button>
</div>
</Form.Item>
<div className={styles["hous-box"]}>
{attachmentData.length === 0 && (
<span className={styles["no-hours"]}>
</span>
)}
{attachmentData.length > 0 && (
<TreeAttachments
data={attachmentData}
onRemoveItem={(id: number) => {
delAttachments(id);
}}
onUpdate={(arr: any[]) => {
transAttachments(arr);
}}
/>
)}
</div>
</div> </div>
</Form> )}
<div
className="float-left"
style={{ display: init ? "none" : "block" }}
>
<Form
form={form}
name="attachment-update-basic"
labelCol={{ span: 5 }}
wrapperCol={{ span: 19 }}
initialValues={{ remember: true }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<div className="c-flex">
<Form.Item>
<div className="ml-42">
<Button
onClick={() => setAttachmentVisible(true)}
type="primary"
>
</Button>
</div>
</Form.Item>
<div className={styles["hous-box"]}>
{attachmentData.length === 0 && (
<span className={styles["no-hours"]}>
</span>
)}
{attachmentData.length > 0 && (
<TreeAttachments
data={attachmentData}
onRemoveItem={(id: number) => {
delAttachments(id);
}}
onUpdate={(arr: any[]) => {
transAttachments(arr);
}}
/>
)}
</div>
</div>
</Form>
</div>
</div> </div>
</Drawer> </Drawer>
) : null} ) : null}

View File

@ -1,20 +1,20 @@
import { message, Tree, Tooltip } from "antd"; import { Tree, Tooltip } from "antd";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import type { DataNode, TreeProps } from "antd/es/tree"; import type { DataNode, TreeProps } from "antd/es/tree";
interface Option {
id: number;
name: string;
}
interface PropInterface { interface PropInterface {
data: Option[]; data: AttachmentDataModel[];
onRemoveItem: (id: number) => void; onRemoveItem: (id: number) => void;
onUpdate: (arr: any[]) => void; onUpdate: (arr: any[]) => void;
} }
interface Option {
key: string | number;
title: any;
}
export const TreeAttachments = (props: PropInterface) => { export const TreeAttachments = (props: PropInterface) => {
const [treeData, setTreeData] = useState<any>([]); const [treeData, setTreeData] = useState<Option[]>([]);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
useEffect(() => { useEffect(() => {
const hours = props.data; const hours = props.data;

View File

@ -32,6 +32,12 @@ interface PropInterface {
onCancel: () => void; onCancel: () => void;
} }
interface Option {
value: string | number;
title: string;
children?: Option[];
}
export const CourseCreate: React.FC<PropInterface> = ({ export const CourseCreate: React.FC<PropInterface> = ({
cateIds, cateIds,
depIds, depIds,
@ -45,22 +51,24 @@ export const CourseCreate: React.FC<PropInterface> = ({
const defaultThumb1 = courseDefaultThumbs[0]; const defaultThumb1 = courseDefaultThumbs[0];
const defaultThumb2 = courseDefaultThumbs[1]; const defaultThumb2 = courseDefaultThumbs[1];
const defaultThumb3 = courseDefaultThumbs[2]; const defaultThumb3 = courseDefaultThumbs[2];
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [departments, setDepartments] = useState<any>([]); const [departments, setDepartments] = useState<Option[]>([]);
const [categories, setCategories] = useState<any>([]); const [categories, setCategories] = useState<Option[]>([]);
const [thumb, setThumb] = useState<string>(""); const [thumb, setThumb] = useState("");
const [type, setType] = useState<string>("open"); const [type, setType] = useState("open");
const [chapterType, setChapterType] = useState(0); const [chapterType, setChapterType] = useState(0);
const [chapters, setChapters] = useState<any>([]); const [chapters, setChapters] = useState<CourseChaptersModel[]>([]);
const [hours, setHours] = useState<any>([]); const [hours, setHours] = useState<number[]>([]);
const [chapterHours, setChapterHours] = useState<any>([]); const [chapterHours, setChapterHours] = useState<any>([]);
const [videoVisible, setVideoVisible] = useState<boolean>(false); const [videoVisible, setVideoVisible] = useState(false);
const [treeData, setTreeData] = useState<any>([]); const [treeData, setTreeData] = useState<CourseHourModel[]>([]);
const [addvideoCurrent, setAddvideoCurrent] = useState(0); const [addvideoCurrent, setAddvideoCurrent] = useState(0);
const [showDrop, setShowDrop] = useState<boolean>(false); const [showDrop, setShowDrop] = useState(false);
const [attachmentVisible, setAttachmentVisible] = useState<boolean>(false); const [attachmentVisible, setAttachmentVisible] = useState(false);
const [attachmentData, setAttachmentData] = useState<any>([]); const [attachmentData, setAttachmentData] = useState<AttachmentDataModel[]>(
const [attachments, setAttachments] = useState<any>([]); []
);
const [attachments, setAttachments] = useState<number[]>([]);
useEffect(() => { useEffect(() => {
if (open) { if (open) {
@ -91,7 +99,7 @@ export const CourseCreate: React.FC<PropInterface> = ({
const getParams = () => { const getParams = () => {
department.departmentList().then((res: any) => { department.departmentList().then((res: any) => {
const departments = res.data.departments; const departments = res.data.departments;
const departCount = res.data.dep_user_count; const departCount: DepIdsModel = res.data.dep_user_count;
if (JSON.stringify(departments) !== "{}") { if (JSON.stringify(departments) !== "{}") {
const new_arr: any = checkArr(departments, 0, departCount); const new_arr: any = checkArr(departments, 0, departCount);
setDepartments(new_arr); setDepartments(new_arr);
@ -438,7 +446,6 @@ export const CourseCreate: React.FC<PropInterface> = ({
const keys = [...chapterHours]; const keys = [...chapterHours];
keys[index] = arr; keys[index] = arr;
setChapterHours(keys); setChapterHours(keys);
const data = [...chapters]; const data = [...chapters];
const newArr: any = []; const newArr: any = [];
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Button, Drawer, Form, Input, Modal, message } from "antd"; import { Button, Drawer, Form, Input, Modal, message, Spin } from "antd";
import styles from "./hour-update.module.less"; import styles from "./hour-update.module.less";
import { course, courseHour, courseChapter } from "../../../api/index"; import { course, courseHour, courseChapter } from "../../../api/index";
import { SelectResource } from "../../../compenents"; import { SelectResource } from "../../../compenents";
@ -20,15 +20,17 @@ export const CourseHourUpdate: React.FC<PropInterface> = ({
onCancel, onCancel,
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [init, setInit] = useState(true);
const [chapterType, setChapterType] = useState(0); const [chapterType, setChapterType] = useState(0);
const [chapters, setChapters] = useState<any>([]); const [chapters, setChapters] = useState<CourseChaptersModel[]>([]);
const [hours, setHours] = useState<any>([]); const [hours, setHours] = useState<number[]>([]);
const [chapterHours, setChapterHours] = useState<any>([]); const [chapterHours, setChapterHours] = useState<any>([]);
const [videoVisible, setVideoVisible] = useState<boolean>(false); const [videoVisible, setVideoVisible] = useState<boolean>(false);
const [treeData, setTreeData] = useState<any>([]); const [treeData, setTreeData] = useState<CourseHourModel[]>([]);
const [addvideoCurrent, setAddvideoCurrent] = useState(0); const [addvideoCurrent, setAddvideoCurrent] = useState(0);
useEffect(() => { useEffect(() => {
setInit(true);
if (id === 0) { if (id === 0) {
return; return;
} }
@ -77,6 +79,7 @@ export const CourseHourUpdate: React.FC<PropInterface> = ({
setHours([]); setHours([]);
} }
} }
setInit(false);
}); });
}; };
@ -231,7 +234,7 @@ export const CourseHourUpdate: React.FC<PropInterface> = ({
const arr = [...chapters]; const arr = [...chapters];
if (arr[index].id) { if (arr[index].id) {
courseChapter courseChapter
.updateCourseChapter(id, arr[index].id, value, arr.length) .updateCourseChapter(id, Number(arr[index].id), value, arr.length)
.then((res: any) => { .then((res: any) => {
console.log("ok"); console.log("ok");
getDetail(); getDetail();
@ -259,7 +262,7 @@ export const CourseHourUpdate: React.FC<PropInterface> = ({
onOk() { onOk() {
if (arr[index].id) { if (arr[index].id) {
courseChapter courseChapter
.destroyCourseChapter(id, arr[index].id) .destroyCourseChapter(id, Number(arr[index].id))
.then((res: any) => { .then((res: any) => {
console.log("ok"); console.log("ok");
getDetail(); getDetail();
@ -373,117 +376,129 @@ export const CourseHourUpdate: React.FC<PropInterface> = ({
} }
}} }}
/> />
<Form {init && (
form={form} <div className="float-left text-center mt-30">
name="hour-update-basic" <Spin></Spin>
labelCol={{ span: 5 }} </div>
wrapperCol={{ span: 19 }} )}
initialValues={{ remember: true }} <div
onFinish={onFinish} className="float-left"
onFinishFailed={onFinishFailed} style={{ display: init ? "none" : "block" }}
autoComplete="off"
> >
{chapterType === 0 && ( <Form
<div className="c-flex"> form={form}
<Form.Item> name="hour-update-basic"
<div className="ml-42"> labelCol={{ span: 5 }}
<Button wrapperCol={{ span: 19 }}
onClick={() => setVideoVisible(true)} initialValues={{ remember: true }}
type="primary" onFinish={onFinish}
> onFinishFailed={onFinishFailed}
autoComplete="off"
</Button> >
</div> {chapterType === 0 && (
</Form.Item> <div className="c-flex">
<div className={styles["hous-box"]}> <Form.Item>
{treeData.length === 0 && ( <div className="ml-42">
<span className={styles["no-hours"]}> <Button
onClick={() => setVideoVisible(true)}
</span> type="primary"
)}
{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"]}> </Button>
{index + 1} </div>
</div> </Form.Item>
<Input <div className={styles["hous-box"]}>
value={item.name} {treeData.length === 0 && (
className={styles["input"]} <span className={styles["no-hours"]}>
onChange={(e) => {
setChapterName(index, e.target.value); </span>
}} )}
onBlur={(e) => { {treeData.length > 0 && (
saveChapterName(index, e.target.value); <TreeHours
}} data={treeData}
placeholder="请在此处输入章节名称" onRemoveItem={(id: number) => {
allowClear delHour(id);
/> }}
<Button onUpdate={(arr: any[]) => {
disabled={!item.name} transHour(arr);
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-42">
<Button onClick={() => addNewChapter()}></Button>
</div> </div>
</Form.Item> </div>
</div> )}
)} {chapterType === 1 && (
</Form> <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="请在此处输入章节名称"
allowClear
/>
<Button
disabled={!item.name}
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-42">
<Button onClick={() => addNewChapter()}>
</Button>
</div>
</Form.Item>
</div>
)}
</Form>
</div>
</div> </div>
</Drawer> </Drawer>
) : null} ) : null}

View File

@ -3,18 +3,18 @@ import { useState, useEffect } from "react";
import type { DataNode, TreeProps } from "antd/es/tree"; import type { DataNode, TreeProps } from "antd/es/tree";
interface Option { interface Option {
id: number; key: string | number;
name: string; title: any;
} }
interface PropInterface { interface PropInterface {
data: Option[]; data: CourseHourModel[];
onRemoveItem: (id: number) => void; onRemoveItem: (id: number) => void;
onUpdate: (arr: any[]) => void; onUpdate: (arr: any[]) => void;
} }
export const TreeHours = (props: PropInterface) => { export const TreeHours = (props: PropInterface) => {
const [treeData, setTreeData] = useState<any>([]); const [treeData, setTreeData] = useState<Option[]>([]);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
useEffect(() => { useEffect(() => {
const hours = props.data; const hours = props.data;

View File

@ -22,6 +22,12 @@ interface PropInterface {
onCancel: () => void; onCancel: () => void;
} }
interface Option {
value: string | number;
title: string;
children?: Option[];
}
export const CourseUpdate: React.FC<PropInterface> = ({ export const CourseUpdate: React.FC<PropInterface> = ({
id, id,
open, open,
@ -36,10 +42,10 @@ export const CourseUpdate: React.FC<PropInterface> = ({
const defaultThumb2 = courseDefaultThumbs[1]; const defaultThumb2 = courseDefaultThumbs[1];
const defaultThumb3 = courseDefaultThumbs[2]; const defaultThumb3 = courseDefaultThumbs[2];
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [departments, setDepartments] = useState<any>([]); const [departments, setDepartments] = useState<Option[]>([]);
const [categories, setCategories] = useState<any>([]); const [categories, setCategories] = useState<Option[]>([]);
const [thumb, setThumb] = useState<string>(""); const [thumb, setThumb] = useState("");
const [type, setType] = useState<string>("open"); const [type, setType] = useState("open");
useEffect(() => { useEffect(() => {
setInit(true); setInit(true);

View File

@ -12,7 +12,6 @@ import {
Dropdown, Dropdown,
} from "antd"; } from "antd";
import { course } from "../../api"; import { course } from "../../api";
// import styles from "./index.module.less";
import { import {
PlusOutlined, PlusOutlined,
DownOutlined, DownOutlined,
@ -33,43 +32,46 @@ const { confirm } = Modal;
interface DataType { interface DataType {
id: React.Key; id: React.Key;
title: string;
created_at: string;
thumb: string;
charge: number; charge: number;
class_hour: number;
created_at: string;
is_required: number;
is_show: number; is_show: number;
short_desc: string;
thumb: string;
title: string;
} }
const CoursePage = () => { const CoursePage = () => {
const result = new URLSearchParams(useLocation().search); const result = new URLSearchParams(useLocation().search);
const navigate = useNavigate(); const navigate = useNavigate();
const [list, setList] = useState<any>([]); const [list, setList] = useState<DataType[]>([]);
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [size, setSize] = useState(10); const [size, setSize] = useState(10);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [category_ids, setCategoryIds] = useState<any>([]); const [category_ids, setCategoryIds] = useState<number[]>([]);
const [title, setTitle] = useState<string>(""); const [title, setTitle] = useState("");
const [dep_ids, setDepIds] = useState<any>([]); const [dep_ids, setDepIds] = useState<number[]>([]);
const [selLabel, setLabel] = useState<string>( const [selLabel, setLabel] = useState<string>(
result.get("label") ? String(result.get("label")) : "全部分类" result.get("label") ? String(result.get("label")) : "全部分类"
); );
const [selDepLabel, setDepLabel] = useState<string>( const [selDepLabel, setDepLabel] = useState<string>(
result.get("label") ? String(result.get("label")) : "全部部门" result.get("label") ? String(result.get("label")) : "全部部门"
); );
const [course_category_ids, setCourseCategoryIds] = useState<any>({}); const [course_category_ids, setCourseCategoryIds] =
const [course_dep_ids, setCourseDepIds] = useState<any>({}); useState<CategoryIdsModel>({});
const [categories, setCategories] = useState<any>({}); const [course_dep_ids, setCourseDepIds] = useState<DepIdsModel>({});
const [departments, setDepartments] = useState<any>({}); const [categories, setCategories] = useState<CategoriesModel>({});
const [departments, setDepartments] = useState<DepartmentsModel>({});
const [tabKey, setTabKey] = useState(result.get("did") ? "2" : "1"); const [tabKey, setTabKey] = useState(result.get("did") ? "2" : "1");
const [createVisible, setCreateVisible] = useState<boolean>(false); const [createVisible, setCreateVisible] = useState(false);
const [updateVisible, setUpdateVisible] = useState<boolean>(false); const [updateVisible, setUpdateVisible] = useState(false);
const [updateHourVisible, setHourUpdateVisible] = useState<boolean>(false); const [updateHourVisible, setHourUpdateVisible] = useState(false);
const [updateAttachmentVisible, setUpdateAttachmentVisible] = const [updateAttachmentVisible, setUpdateAttachmentVisible] = useState(false);
useState<boolean>(false); const [cid, setCid] = useState(0);
const [cid, setCid] = useState<number>(0);
const [cateId, setCateId] = useState(Number(result.get("cid"))); const [cateId, setCateId] = useState(Number(result.get("cid")));
const [did, setDid] = useState(Number(result.get("did"))); const [did, setDid] = useState(Number(result.get("did")));

View File

@ -22,30 +22,61 @@ const { confirm } = Modal;
interface DataType { interface DataType {
id: React.Key; id: React.Key;
title: string; avatar: string;
created_at: string; create_city?: string;
thumb: string; create_ip?: string;
charge: number; created_at?: string;
is_show: number; credit1?: number;
email: string;
id_card?: string;
is_active?: number;
is_lock?: number;
is_set_password?: number;
is_verify?: number;
login_at?: string;
name: string;
updated_at?: string;
verify_at?: string;
} }
type UserCourseRecordsModel = {
[key: number]: CourseRecordModel;
};
type CourseRecordModel = {
course_id: number;
created_at: string;
finished_at?: string;
finished_count: number;
hour_count: number;
id: number;
is_finished: number;
progress: number;
updated_at: string;
user_id: number;
};
type HourCountModel = {
[key: number]: string;
};
const CourseUserPage = () => { const CourseUserPage = () => {
const params = useParams(); const params = useParams();
const result = new URLSearchParams(useLocation().search); const result = new URLSearchParams(useLocation().search);
const [list, setList] = useState<any>([]); const [list, setList] = useState<DataType[]>([]);
const [course, setCourse] = useState<any>({}); const [course, setCourse] = useState<CourseModel | null>(null);
const [records, setRecords] = useState<any>({}); const [records, setRecords] = useState<UserCourseRecordsModel>({});
const [hourCount, setHourCount] = useState<any>({}); const [hourCount, setHourCount] = useState<HourCountModel>({});
const [userDepIds, setUserDepIds] = useState<any>({}); const [userDepIds, setUserDepIds] = useState<DepIdsModel>({});
const [departments, setDepartments] = useState<any>({}); const [departments, setDepartments] = useState<DepartmentsModel>({});
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [size, setSize] = useState(10); const [size, setSize] = useState(10);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [name, setName] = useState<string>(""); const [name, setName] = useState("");
const [email, setEmail] = useState<string>(""); const [email, setEmail] = useState("");
const [idCard, setIdCard] = useState<string>(""); const [idCard, setIdCard] = useState("");
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
const [title, setTitle] = useState<string>(String(result.get("title"))); const [title, setTitle] = useState<string>(String(result.get("title")));
@ -95,7 +126,7 @@ const CourseUserPage = () => {
{(records[record.id] && records[record.id].finished_count) || {(records[record.id] && records[record.id].finished_count) ||
0} /{" "} 0} /{" "}
{(records[record.id] && records[record.id].hour_count) || {(records[record.id] && records[record.id].hour_count) ||
course.class_hour} course?.class_hour}
</span> </span>
), ),
}, },
@ -116,11 +147,11 @@ const CourseUserPage = () => {
}, },
{ {
title: "学习完成时间", title: "学习完成时间",
dataIndex: "finished_at", dataIndex: "id",
render: (_, record: any) => ( render: (_, record: any) => (
<> <>
{records[record.id] ? ( {records[record.id] ? (
<span>{dateFormat(records[record.id].finished_at)}</span> <span>{dateFormat(String(records[record.id].finished_at))}</span>
) : ( ) : (
<span>-</span> <span>-</span>
)} )}

View File

@ -12,10 +12,38 @@ import { dashboard } from "../../api/index";
import { timeFormat } from "../../utils/index"; import { timeFormat } from "../../utils/index";
import * as echarts from "echarts"; import * as echarts from "echarts";
type BasicDataModel = {
admin_user_total: number;
course_total: number;
department_total: number;
resource_category_total: number;
resource_image_total: number;
resource_video_total: number;
user_learn_today: number;
user_learn_top10?: Top10Model[];
user_learn_top10_users?: Top10UserModel;
user_learn_yesterday: number;
user_today: number;
user_total: number;
user_yesterday: number;
version: string;
};
type Top10Model = {
created_date: string;
duration: number;
id: number;
user_id: number;
};
type Top10UserModel = {
[key: number]: UserModel;
};
const DashboardPage = () => { const DashboardPage = () => {
let chartRef = useRef(null); let chartRef = useRef(null);
const navigate = useNavigate(); const navigate = useNavigate();
const [basicData, setBasicData] = useState<any>([]); const [basicData, setBasicData] = useState<BasicDataModel | null>(null);
const getData = () => { const getData = () => {
dashboard.dashboardList().then((res: any) => { dashboard.dashboardList().then((res: any) => {
@ -164,31 +192,35 @@ const DashboardPage = () => {
<div className={styles["label"]}></div> <div className={styles["label"]}></div>
<div className={styles["info"]}> <div className={styles["info"]}>
<div className={styles["num"]}> <div className={styles["num"]}>
{basicData.user_learn_today} {basicData?.user_learn_today}
</div>
<div className={styles["compare"]}>
<span className="mr-5"></span>
{compareNum(
basicData.user_learn_today,
basicData.user_learn_yesterday
)}
</div> </div>
{basicData && (
<div className={styles["compare"]}>
<span className="mr-5"></span>
{compareNum(
basicData.user_learn_today,
basicData.user_learn_yesterday
)}
</div>
)}
</div> </div>
</div> </div>
<div className={styles["label-item"]}> <div className={styles["label-item"]}>
<div className={styles["label"]}></div> <div className={styles["label"]}></div>
<div className={styles["info"]}> <div className={styles["info"]}>
<div className={styles["num"]}>{basicData.user_total}</div> <div className={styles["num"]}>{basicData?.user_total}</div>
<div className={styles["compare"]}> {basicData && (
<span className="mr-5"></span> <div className={styles["compare"]}>
{compareNum(basicData.user_today, 0)} <span className="mr-5"></span>
</div> {compareNum(basicData.user_today, 0)}
</div>
)}
</div> </div>
</div> </div>
<div className={styles["label-item"]}> <div className={styles["label-item"]}>
<div className={styles["label"]}>线</div> <div className={styles["label"]}>线</div>
<div className={styles["info"]}> <div className={styles["info"]}>
<div className={styles["num"]}>{basicData.course_total}</div> <div className={styles["num"]}>{basicData?.course_total}</div>
</div> </div>
</div> </div>
</div> </div>
@ -249,7 +281,7 @@ const DashboardPage = () => {
<div className="playedu-main-top mt-24" style={{ minHeight: 376 }}> <div className="playedu-main-top mt-24" style={{ minHeight: 376 }}>
<div className={styles["large-title"]}></div> <div className={styles["large-title"]}></div>
<div className={styles["rank-list"]}> <div className={styles["rank-list"]}>
{basicData.user_learn_top10 && ( {basicData?.user_learn_top10 && (
<div className={styles["half-list"]}> <div className={styles["half-list"]}>
<div className={styles["rank-item"]}> <div className={styles["rank-item"]}>
<div className={styles["left-item"]}> <div className={styles["left-item"]}>
@ -258,15 +290,16 @@ const DashboardPage = () => {
src={iconN1} src={iconN1}
alt="" alt=""
/> />
{basicData.user_learn_top10[0] && ( {basicData.user_learn_top10[0] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[0].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[0].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[0] && ( {basicData.user_learn_top10[0] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -283,15 +316,16 @@ const DashboardPage = () => {
src={iconN2} src={iconN2}
alt="" alt=""
/> />
{basicData.user_learn_top10[1] && ( {basicData.user_learn_top10[1] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[1].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[1].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[1] && ( {basicData.user_learn_top10[1] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -308,15 +342,16 @@ const DashboardPage = () => {
src={iconN3} src={iconN3}
alt="" alt=""
/> />
{basicData.user_learn_top10[2] && ( {basicData.user_learn_top10[2] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[2].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[2].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[2] && ( {basicData.user_learn_top10[2] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -329,15 +364,16 @@ const DashboardPage = () => {
<div className={styles["rank-item"]}> <div className={styles["rank-item"]}>
<div className={styles["left-item"]}> <div className={styles["left-item"]}>
<div className={styles["item-num"]}>4</div> <div className={styles["item-num"]}>4</div>
{basicData.user_learn_top10[3] && ( {basicData.user_learn_top10[3] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[3].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[3].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[3] && ( {basicData.user_learn_top10[3] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -350,15 +386,16 @@ const DashboardPage = () => {
<div className={styles["rank-item"]}> <div className={styles["rank-item"]}>
<div className={styles["left-item"]}> <div className={styles["left-item"]}>
<div className={styles["item-num"]}>5</div> <div className={styles["item-num"]}>5</div>
{basicData.user_learn_top10[4] && ( {basicData.user_learn_top10[4] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[4].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[4].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[4] && ( {basicData.user_learn_top10[4] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -370,20 +407,21 @@ const DashboardPage = () => {
</div> </div>
</div> </div>
)} )}
{basicData.user_learn_top10 && ( {basicData?.user_learn_top10 && (
<div className={styles["half-list"]}> <div className={styles["half-list"]}>
<div className={styles["rank-item"]}> <div className={styles["rank-item"]}>
<div className={styles["left-item"]}> <div className={styles["left-item"]}>
<div className={styles["item-num"]}>6</div> <div className={styles["item-num"]}>6</div>
{basicData.user_learn_top10[5] && ( {basicData.user_learn_top10[5] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[5].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[5].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[5] && ( {basicData.user_learn_top10[5] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -396,15 +434,16 @@ const DashboardPage = () => {
<div className={styles["rank-item"]}> <div className={styles["rank-item"]}>
<div className={styles["left-item"]}> <div className={styles["left-item"]}>
<div className={styles["item-num"]}>7</div> <div className={styles["item-num"]}>7</div>
{basicData.user_learn_top10[6] && ( {basicData.user_learn_top10[6] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[6].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[6].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[6] && ( {basicData.user_learn_top10[6] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -417,15 +456,16 @@ const DashboardPage = () => {
<div className={styles["rank-item"]}> <div className={styles["rank-item"]}>
<div className={styles["left-item"]}> <div className={styles["left-item"]}>
<div className={styles["item-num"]}>8</div> <div className={styles["item-num"]}>8</div>
{basicData.user_learn_top10[7] && ( {basicData.user_learn_top10[7] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[7].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[7].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[7] && ( {basicData.user_learn_top10[7] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -438,15 +478,16 @@ const DashboardPage = () => {
<div className={styles["rank-item"]}> <div className={styles["rank-item"]}>
<div className={styles["left-item"]}> <div className={styles["left-item"]}>
<div className={styles["item-num"]}>9</div> <div className={styles["item-num"]}>9</div>
{basicData.user_learn_top10[8] && ( {basicData.user_learn_top10[8] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[8].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[8].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[8] && ( {basicData.user_learn_top10[8] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -459,15 +500,16 @@ const DashboardPage = () => {
<div className={styles["rank-item"]}> <div className={styles["rank-item"]}>
<div className={styles["left-item"]}> <div className={styles["left-item"]}>
<div className={styles["item-num"]}>10</div> <div className={styles["item-num"]}>10</div>
{basicData.user_learn_top10[9] && ( {basicData.user_learn_top10[9] &&
<div className={styles["item-name"]}> basicData.user_learn_top10_users && (
{ <div className={styles["item-name"]}>
basicData.user_learn_top10_users[ {
basicData.user_learn_top10[9].user_id basicData.user_learn_top10_users[
]?.name basicData.user_learn_top10[9].user_id
} ]?.name
</div> }
)} </div>
)}
</div> </div>
{basicData.user_learn_top10[9] && ( {basicData.user_learn_top10[9] && (
<div className={styles["item-time"]}> <div className={styles["item-time"]}>
@ -489,7 +531,7 @@ const DashboardPage = () => {
<div className={styles["label"]}></div> <div className={styles["label"]}></div>
<div className={styles["info"]}> <div className={styles["info"]}>
<div className={styles["num"]}> <div className={styles["num"]}>
{basicData.department_total} {basicData?.department_total}
</div> </div>
</div> </div>
</div> </div>
@ -497,7 +539,7 @@ const DashboardPage = () => {
<div className={styles["label"]}></div> <div className={styles["label"]}></div>
<div className={styles["info"]}> <div className={styles["info"]}>
<div className={styles["num"]}> <div className={styles["num"]}>
{basicData.resource_category_total} {basicData?.resource_category_total}
</div> </div>
</div> </div>
</div> </div>
@ -505,7 +547,7 @@ const DashboardPage = () => {
<div className={styles["label"]}></div> <div className={styles["label"]}></div>
<div className={styles["info"]}> <div className={styles["info"]}>
<div className={styles["num"]}> <div className={styles["num"]}>
{basicData.admin_user_total} {basicData?.admin_user_total}
</div> </div>
</div> </div>
</div> </div>

View File

@ -23,13 +23,13 @@ const DepartmentPage = () => {
const permissions = useSelector( const permissions = useSelector(
(state: any) => state.loginUser.value.permissions (state: any) => state.loginUser.value.permissions
); );
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [treeData, setTreeData] = useState<any>([]); const [treeData, setTreeData] = useState<Option[]>([]);
const [selectKey, setSelectKey] = useState<any>([]); const [selectKey, setSelectKey] = useState<number[]>([]);
const [createVisible, setCreateVisible] = useState<boolean>(false); const [createVisible, setCreateVisible] = useState(false);
const [updateVisible, setUpdateVisible] = useState<boolean>(false); const [updateVisible, setUpdateVisible] = useState(false);
const [did, setDid] = useState<number>(0); const [did, setDid] = useState<number>(0);
const [modal, contextHolder] = Modal.useModal(); const [modal, contextHolder] = Modal.useModal();
@ -51,7 +51,7 @@ const DepartmentPage = () => {
const getData = () => { const getData = () => {
setLoading(true); setLoading(true);
department.departmentList().then((res: any) => { department.departmentList().then((res: any) => {
const departments = res.data.departments; const departments: DepartmentsBoxModel = res.data.departments;
if (JSON.stringify(departments) !== "{}") { if (JSON.stringify(departments) !== "{}") {
const new_arr: Option[] = checkArr(departments, 0); const new_arr: Option[] = checkArr(departments, 0);
setTreeData(new_arr); setTreeData(new_arr);
@ -61,7 +61,7 @@ const DepartmentPage = () => {
}); });
}; };
const checkArr = (departments: any[], id: number) => { const checkArr = (departments: DepartmentsBoxModel, id: number) => {
const arr = []; const arr = [];
for (let i = 0; i < departments[id].length; i++) { for (let i = 0; i < departments[id].length; i++) {
if (!departments[departments[id][i].id]) { if (!departments[departments[id][i].id]) {

View File

@ -28,34 +28,43 @@ const { confirm } = Modal;
interface DataType { interface DataType {
id: React.Key; id: React.Key;
name: string; avatar: string;
create_city?: string;
create_ip?: string;
created_at?: string;
credit1?: number;
email: string; email: string;
created_at: string; id_card?: string;
credit1: number; is_active?: number;
id_card: string; is_lock?: number;
is_lock: number; is_set_password?: number;
is_verify?: number;
login_at?: string;
name: string;
updated_at?: string;
verify_at?: string;
} }
const MemberPage = () => { const MemberPage = () => {
const result = new URLSearchParams(useLocation().search); const result = new URLSearchParams(useLocation().search);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [size, setSize] = useState(10); const [size, setSize] = useState(10);
const [list, setList] = useState<any>([]); const [list, setList] = useState<DataType[]>([]);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [nickname, setNickname] = useState<string>(""); const [nickname, setNickname] = useState("");
const [email, setEmail] = useState<string>(""); const [email, setEmail] = useState("");
const [dep_ids, setDepIds] = useState<any>([]); const [dep_ids, setDepIds] = useState<number[]>([]);
const [selLabel, setLabel] = useState<string>( const [selLabel, setLabel] = useState<string>(
result.get("label") ? String(result.get("label")) : "全部部门" result.get("label") ? String(result.get("label")) : "全部部门"
); );
const [createVisible, setCreateVisible] = useState<boolean>(false); const [createVisible, setCreateVisible] = useState(false);
const [updateVisible, setUpdateVisible] = useState<boolean>(false); const [updateVisible, setUpdateVisible] = useState(false);
const [mid, setMid] = useState<number>(0); const [mid, setMid] = useState(0);
const [user_dep_ids, setUserDepIds] = useState<any>({}); const [user_dep_ids, setUserDepIds] = useState<DepIdsModel>({});
const [departments, setDepartments] = useState<any>({}); const [departments, setDepartments] = useState<DepartmentsModel>({});
const [did, setDid] = useState(Number(result.get("did"))); const [did, setDid] = useState(Number(result.get("did")));
useEffect(() => { useEffect(() => {

View File

@ -11,33 +11,71 @@ import { MemberLearnProgressDialog } from "./compenents/progress";
interface DataType { interface DataType {
id: React.Key; id: React.Key;
title: string; charge: number;
type: string; class_hour: number;
created_at: string; created_at: string;
total_duration: number; is_required: number;
finished_duration: number; is_show: number;
is_finished: boolean; short_desc: string;
thumb: string;
title: string;
} }
type UserCourseRecordsModel = {
[key: number]: UserRecordModel;
};
type UserRecordModel = {
course_id: number;
created_at: string;
finished_at?: string;
finished_count: number;
hour_count: number;
id: number;
is_finished: number;
progress: number;
updated_at: string;
user_id: number;
};
type HourCountModel = {
[key: number]: number;
};
type OptionModel = {
label: string;
value: string;
};
type DepartmentsListModel = {
reated_at: string;
id: number;
name: string;
parent_chain: string;
parent_id: number;
sort: number;
updated_at: string;
};
const MemberLearnPage = () => { const MemberLearnPage = () => {
let chartRef = useRef(null); let chartRef = useRef(null);
const navigate = useNavigate(); const navigate = useNavigate();
const result = new URLSearchParams(useLocation().search); const result = new URLSearchParams(useLocation().search);
const [loading2, setLoading2] = useState<boolean>(false); const [loading2, setLoading2] = useState(false);
const [list2, setList2] = useState<any>([]); const [list2, setList2] = useState<DepartmentsListModel[]>([]);
const [courses, setCourses] = useState<any>({}); const [courses, setCourses] = useState<any>({});
const [deps, setDeps] = useState<any>([]); const [deps, setDeps] = useState<OptionModel[]>([]);
const [depValue, setDepValue] = useState<number>(0); const [depValue, setDepValue] = useState(0);
const [currentCourses, setCurrentCourses] = useState<any>([]); const [currentCourses, setCurrentCourses] = useState<DataType[]>([]);
const [openCourses, setOpenCourses] = useState<any>([]); const [openCourses, setOpenCourses] = useState<CourseModel[]>([]);
const [records, setRecords] = useState<any>({}); const [records, setRecords] = useState<UserCourseRecordsModel>({});
const [hourCount, setHourCount] = useState<any>({}); const [hourCount, setHourCount] = useState<HourCountModel>({});
const [total2, setTotal2] = useState(0); const [total2, setTotal2] = useState(0);
const [refresh2, setRefresh2] = useState(false); const [refresh2, setRefresh2] = useState(false);
const [uid, setUid] = useState(Number(result.get("id"))); const [uid, setUid] = useState(Number(result.get("id")));
const [userName, setUserName] = useState<string>(String(result.get("name"))); const [userName, setUserName] = useState<string>(String(result.get("name")));
const [visiable, setVisiable] = useState(false); const [visiable, setVisiable] = useState(false);
const [courseId, setcourseId] = useState<number>(0); const [courseId, setcourseId] = useState(0);
useEffect(() => { useEffect(() => {
setUid(Number(result.get("id"))); setUid(Number(result.get("id")));
@ -157,7 +195,7 @@ const MemberLearnPage = () => {
setHourCount(res.data.user_course_hour_count); setHourCount(res.data.user_course_hour_count);
setRecords(res.data.user_course_records); setRecords(res.data.user_course_records);
if (res.data.departments.length > 0) { if (res.data.departments.length > 0) {
let box: any = []; let box: OptionModel[] = [];
res.data.departments.map((item: any) => { res.data.departments.map((item: any) => {
box.push({ box.push({
label: item.name, label: item.name,
@ -223,7 +261,7 @@ const MemberLearnPage = () => {
render: (_, record: any) => ( render: (_, record: any) => (
<> <>
{records[record.id] ? ( {records[record.id] ? (
<span>{dateFormat(records[record.id].finished_at)}</span> <span>{dateFormat(String(records[record.id].finished_at))}</span>
) : ( ) : (
<span>-</span> <span>-</span>
)} )}
@ -232,7 +270,6 @@ const MemberLearnPage = () => {
}, },
{ {
title: "学习进度", title: "学习进度",
dataIndex: "is_finished",
render: (_, record: any) => ( render: (_, record: any) => (
<> <>
{records[record.id] ? ( {records[record.id] ? (

View File

@ -9,11 +9,9 @@ import {
Select, Select,
Button, Button,
} from "antd"; } from "antd";
import type { MenuProps } from "antd";
import { resource } from "../../../api"; import { resource } from "../../../api";
// import styles from "./index.module.less";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import { DownOutlined, ExclamationCircleFilled } from "@ant-design/icons"; import { ExclamationCircleFilled } from "@ant-design/icons";
import type { ColumnsType } from "antd/es/table"; import type { ColumnsType } from "antd/es/table";
import { dateFormat } from "../../../utils/index"; import { dateFormat } from "../../../utils/index";
import { TreeCategory, UploadCoursewareButton } from "../../../compenents"; import { TreeCategory, UploadCoursewareButton } from "../../../compenents";
@ -22,34 +20,45 @@ import { CoursewareUpdateDialog } from "./compenents/update-dialog";
const { confirm } = Modal; const { confirm } = Modal;
interface DataType { interface DataType {
admin_id: number;
created_at: string;
disk: string;
extension: string;
file_id: string;
id: React.Key; id: React.Key;
name: string; name: string;
created_at: string; parent_id: number;
path: string;
size: number;
type: string; type: string;
number: number; url: string;
} }
type AdminUsersModel = {
[key: number]: string;
};
const ResourceCoursewarePage = () => { const ResourceCoursewarePage = () => {
const result = new URLSearchParams(useLocation().search); const result = new URLSearchParams(useLocation().search);
const [list, setList] = useState<any>([]); const [list, setList] = useState<DataType[]>([]);
const [adminUsers, setAdminUsers] = useState<any>({}); const [adminUsers, setAdminUsers] = useState<AdminUsersModel>({});
const [existingTypes, setExistingTypes] = useState<any>([]); const [existingTypes, setExistingTypes] = useState<string[]>([]);
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [size, setSize] = useState(10); const [size, setSize] = useState(10);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [category_ids, setCategoryIds] = useState<any>([]); const [category_ids, setCategoryIds] = useState<number[]>([]);
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
const [type, setType] = useState("WORD,EXCEL,PPT,PDF,TXT,RAR,ZIP"); const [type, setType] = useState("WORD,EXCEL,PPT,PDF,TXT,RAR,ZIP");
const [title, setTitle] = useState<string>(""); const [title, setTitle] = useState("");
const [multiConfig, setMultiConfig] = useState<boolean>(false); const [multiConfig, setMultiConfig] = useState(false);
const [selLabel, setLabel] = useState<string>( const [selLabel, setLabel] = useState<string>(
result.get("label") ? String(result.get("label")) : "全部课件" result.get("label") ? String(result.get("label")) : "全部课件"
); );
const [cateId, setCateId] = useState(Number(result.get("cid"))); const [cateId, setCateId] = useState(Number(result.get("cid")));
const [updateId, setUpdateId] = useState(0); const [updateId, setUpdateId] = useState(0);
const [updateVisible, setUpdateVisible] = useState<boolean>(false); const [updateVisible, setUpdateVisible] = useState(false);
const types = [ const types = [
{ label: "全部", value: "WORD,EXCEL,PPT,PDF,TXT,RAR,ZIP" }, { label: "全部", value: "WORD,EXCEL,PPT,PDF,TXT,RAR,ZIP" },
{ label: "WORD", value: "WORD" }, { label: "WORD", value: "WORD" },

View File

@ -14,7 +14,7 @@ import { resource } from "../../../api";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { UploadImageSub } from "../../../compenents/upload-image-button/upload-image-sub"; import { UploadImageSub } from "../../../compenents/upload-image-button/upload-image-sub";
import { TreeCategory, PerButton } from "../../../compenents"; import { TreeCategory } from "../../../compenents";
import { ExclamationCircleFilled, CheckOutlined } from "@ant-design/icons"; import { ExclamationCircleFilled, CheckOutlined } from "@ant-design/icons";
const { confirm } = Modal; const { confirm } = Modal;
@ -39,14 +39,14 @@ const ResourceImagesPage = () => {
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [size, setSize] = useState(32); const [size, setSize] = useState(32);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [category_ids, setCategoryIds] = useState<any>([]); const [category_ids, setCategoryIds] = useState<number[]>([]);
const [selectKey, setSelectKey] = useState<any>([]); const [selectKey, setSelectKey] = useState<number[]>([]);
const [visibleArr, setVisibleArr] = useState<any>([]); const [visibleArr, setVisibleArr] = useState<boolean[]>([]);
const [hoverArr, setHoverArr] = useState<any>([]); const [hoverArr, setHoverArr] = useState<boolean[]>([]);
const [selLabel, setLabel] = useState<string>( const [selLabel, setLabel] = useState<string>(
result.get("label") ? String(result.get("label")) : "全部图片" result.get("label") ? String(result.get("label")) : "全部图片"
); );
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState(false);
const [cateId, setCateId] = useState(Number(result.get("cid"))); const [cateId, setCateId] = useState(Number(result.get("cid")));
useEffect(() => { useEffect(() => {
@ -96,7 +96,7 @@ const ResourceImagesPage = () => {
.then((res: any) => { .then((res: any) => {
setTotal(res.data.result.total); setTotal(res.data.result.total);
setImageList(res.data.result.data); setImageList(res.data.result.data);
let data = res.data.result.data; let data: ImageItem[] = res.data.result.data;
let arr = []; let arr = [];
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
arr.push(false); arr.push(false);

View File

@ -25,8 +25,8 @@ const ResourceCategoryPage = () => {
); );
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [treeData, setTreeData] = useState<any>([]); const [treeData, setTreeData] = useState<Option[]>([]);
const [selectKey, setSelectKey] = useState<any>([]); const [selectKey, setSelectKey] = useState<number[]>([]);
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 [cid, setCid] = useState<number>(0); const [cid, setCid] = useState<number>(0);
@ -50,7 +50,7 @@ const ResourceCategoryPage = () => {
const getData = () => { const getData = () => {
setLoading(true); setLoading(true);
resourceCategory.resourceCategoryList().then((res: any) => { resourceCategory.resourceCategoryList().then((res: any) => {
const categories = res.data.categories; const categories: CategoriesBoxModel = res.data.categories;
if (JSON.stringify(categories) !== "{}") { if (JSON.stringify(categories) !== "{}") {
const new_arr: Option[] = checkArr(categories, 0); const new_arr: Option[] = checkArr(categories, 0);
setTreeData(new_arr); setTreeData(new_arr);
@ -59,7 +59,7 @@ const ResourceCategoryPage = () => {
}); });
}; };
const checkArr = (categories: any[], id: number) => { const checkArr = (categories: CategoriesBoxModel, id: number) => {
const arr = []; const arr = [];
for (let i = 0; i < categories[id].length; i++) { for (let i = 0; i < categories[id].length; i++) {
if (!categories[categories[id][i].id]) { if (!categories[categories[id][i].id]) {

View File

@ -9,6 +9,12 @@ interface PropInterface {
onSuccess: () => void; onSuccess: () => void;
} }
interface Option {
value: string | number;
title: string;
children?: Option[];
}
export const VideosUpdateDialog: React.FC<PropInterface> = ({ export const VideosUpdateDialog: React.FC<PropInterface> = ({
id, id,
open, open,
@ -16,9 +22,9 @@ export const VideosUpdateDialog: React.FC<PropInterface> = ({
onSuccess, onSuccess,
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [init, setInit] = useState(true); const [init, setInit] = useState(true);
const [categories, setCategories] = useState<any>([]); const [categories, setCategories] = useState<Option[]>([]);
useEffect(() => { useEffect(() => {
setInit(true); setInit(true);
@ -33,7 +39,7 @@ export const VideosUpdateDialog: React.FC<PropInterface> = ({
const getCategory = () => { const getCategory = () => {
resourceCategory.resourceCategoryList().then((res: any) => { resourceCategory.resourceCategoryList().then((res: any) => {
const categories = res.data.categories; const categories: CategoriesBoxModel = res.data.categories;
if (JSON.stringify(categories) !== "{}") { if (JSON.stringify(categories) !== "{}") {
const new_arr: any = checkArr(categories, 0, null); const new_arr: any = checkArr(categories, 0, null);
setCategories(new_arr); setCategories(new_arr);
@ -52,7 +58,11 @@ export const VideosUpdateDialog: React.FC<PropInterface> = ({
}); });
}; };
const checkArr = (departments: any[], id: number, counts: any) => { const checkArr = (
departments: CategoriesBoxModel,
id: number,
counts: any
) => {
const arr = []; const arr = [];
for (let i = 0; i < departments[id].length; i++) { for (let i = 0; i < departments[id].length; i++) {
if (!departments[departments[id][i].id]) { if (!departments[departments[id][i].id]) {

View File

@ -17,7 +17,7 @@ export const VideoPlayDialog: React.FC<PropInterface> = ({
open, open,
onCancel, onCancel,
}) => { }) => {
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
useEffect(() => { useEffect(() => {
if (open && url) { if (open && url) {

View File

@ -2,7 +2,6 @@ import { useEffect, useState } from "react";
import { Modal, Table, message, Space, Dropdown, Button } from "antd"; import { Modal, Table, message, Space, Dropdown, Button } from "antd";
import type { MenuProps } from "antd"; import type { MenuProps } from "antd";
import { resource } from "../../../api"; import { resource } from "../../../api";
// import styles from "./index.module.less";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import { DownOutlined, ExclamationCircleFilled } from "@ant-design/icons"; import { DownOutlined, ExclamationCircleFilled } from "@ant-design/icons";
import type { ColumnsType } from "antd/es/table"; import type { ColumnsType } from "antd/es/table";
@ -16,32 +15,54 @@ const { confirm } = Modal;
interface DataType { interface DataType {
id: React.Key; id: React.Key;
name: string; admin_id: number;
created_at: string; created_at: string;
disk: string; disk: string;
extension: string;
file_id: string;
name: string;
parent_id: number;
path: string;
size: number;
type: string;
url: string;
} }
type VideosExtraModel = {
[key: number]: VideoModel;
};
type VideoModel = {
duration: number;
poster: string;
rid: number;
};
type AdminUsersModel = {
[key: number]: string;
};
const ResourceVideosPage = () => { const ResourceVideosPage = () => {
const result = new URLSearchParams(useLocation().search); const result = new URLSearchParams(useLocation().search);
const [videoList, setVideoList] = useState<any>([]); const [videoList, setVideoList] = useState<DataType[]>([]);
const [videosExtra, setVideoExtra] = useState<any>([]); const [videosExtra, setVideoExtra] = useState<VideosExtraModel>({});
const [adminUsers, setAdminUsers] = useState<any>({}); const [adminUsers, setAdminUsers] = useState<AdminUsersModel>({});
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [size, setSize] = useState(10); const [size, setSize] = useState(10);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [category_ids, setCategoryIds] = useState<any>([]); const [category_ids, setCategoryIds] = useState<number[]>([]);
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
const [selLabel, setLabel] = useState<string>( const [selLabel, setLabel] = useState<string>(
result.get("label") ? String(result.get("label")) : "全部视频" result.get("label") ? String(result.get("label")) : "全部视频"
); );
const [cateId, setCateId] = useState(Number(result.get("cid"))); const [cateId, setCateId] = useState(Number(result.get("cid")));
const [updateVisible, setUpdateVisible] = useState<boolean>(false); const [updateVisible, setUpdateVisible] = useState(false);
const [playVisible, setPlayeVisible] = useState<boolean>(false); const [playVisible, setPlayeVisible] = useState(false);
const [multiConfig, setMultiConfig] = useState<boolean>(false); const [multiConfig, setMultiConfig] = useState(false);
const [updateId, setUpdateId] = useState(0); const [updateId, setUpdateId] = useState(0);
const [playUrl, setPlayUrl] = useState<string>(""); const [playUrl, setPlayUrl] = useState("");
useEffect(() => { useEffect(() => {
setCateId(Number(result.get("cid"))); setCateId(Number(result.get("cid")));
@ -72,20 +93,22 @@ const ResourceVideosPage = () => {
{ {
title: "视频时长", title: "视频时长",
dataIndex: "id", dataIndex: "id",
render: (id: string) => ( render: (id: number) => (
<DurationText duration={videosExtra[id].duration}></DurationText> <DurationText duration={videosExtra[id].duration}></DurationText>
), ),
}, },
{ {
title: "创建人", title: "创建人",
dataIndex: "admin_id", dataIndex: "admin_id",
render: (text: number) => render: (admin_id: number) =>
JSON.stringify(adminUsers) !== "{}" && <span>{adminUsers[text]}</span>, JSON.stringify(adminUsers) !== "{}" && (
<span>{adminUsers[admin_id]}</span>
),
}, },
{ {
title: "创建时间", title: "创建时间",
dataIndex: "created_at", dataIndex: "created_at",
render: (text: string) => <span>{dateFormat(text)}</span>, render: (created_at: string) => <span>{dateFormat(created_at)}</span>,
}, },
{ {
title: "操作", title: "操作",

View File

@ -10,6 +10,11 @@ interface PropInterface {
onCancel: () => void; onCancel: () => void;
} }
type selRoleModel = {
label: string;
value: number;
};
export const SystemAdministratorCreate: React.FC<PropInterface> = ({ export const SystemAdministratorCreate: React.FC<PropInterface> = ({
roleId, roleId,
refresh, refresh,
@ -17,8 +22,8 @@ export const SystemAdministratorCreate: React.FC<PropInterface> = ({
onCancel, onCancel,
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [roles, setRoles] = useState<any>([]); const [roles, setRoles] = useState<selRoleModel[]>([]);
useEffect(() => { useEffect(() => {
if (open) { if (open) {
@ -43,7 +48,7 @@ export const SystemAdministratorCreate: React.FC<PropInterface> = ({
const getParams = () => { const getParams = () => {
adminUser.createAdminUser().then((res: any) => { adminUser.createAdminUser().then((res: any) => {
const arr = []; const arr = [];
let roles = res.data.roles; let roles: RoleModel[] = res.data.roles;
for (let i = 0; i < roles.length; i++) { for (let i = 0; i < roles.length; i++) {
arr.push({ arr.push({
label: roles[i].name, label: roles[i].name,

View File

@ -10,6 +10,11 @@ interface PropInterface {
onCancel: () => void; onCancel: () => void;
} }
type selRoleModel = {
label: string;
value: number;
};
export const SystemAdministratorUpdate: React.FC<PropInterface> = ({ export const SystemAdministratorUpdate: React.FC<PropInterface> = ({
id, id,
refresh, refresh,
@ -18,8 +23,8 @@ export const SystemAdministratorUpdate: React.FC<PropInterface> = ({
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [init, setInit] = useState(true); const [init, setInit] = useState(true);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [roles, setRoles] = useState<any>([]); const [roles, setRoles] = useState<selRoleModel[]>([]);
useEffect(() => { useEffect(() => {
if (open) { if (open) {
@ -40,7 +45,7 @@ export const SystemAdministratorUpdate: React.FC<PropInterface> = ({
const getParams = () => { const getParams = () => {
adminUser.createAdminUser().then((res: any) => { adminUser.createAdminUser().then((res: any) => {
const arr = []; const arr = [];
let roles = res.data.roles; let roles: RoleModel[] = res.data.roles;
for (let i = 0; i < roles.length; i++) { for (let i = 0; i < roles.length; i++) {
arr.push({ arr.push({
label: roles[i].name, label: roles[i].name,
@ -53,7 +58,7 @@ export const SystemAdministratorUpdate: React.FC<PropInterface> = ({
const getDetail = () => { const getDetail = () => {
adminUser.AdminUser(id).then((res: any) => { adminUser.AdminUser(id).then((res: any) => {
let user = res.data.user; let user: AdminUserDetailModel = res.data.user;
form.setFieldsValue({ form.setFieldsValue({
email: user.email, email: user.email,
name: user.name, name: user.name,

View File

@ -15,34 +15,36 @@ const { confirm } = Modal;
interface DataType { interface DataType {
id: React.Key; id: React.Key;
name: string; created_at: string;
email: string; email: string;
is_ban_login: number;
login_at: string; login_at: string;
login_ip: string; login_ip: string;
is_ban_login: number; login_times: number;
name: string;
updated_at: string;
} }
const SystemAdministratorPage = () => { const SystemAdministratorPage = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [size, setSize] = useState(10); const [size, setSize] = useState(10);
const [list, setList] = useState<any>([]); const [list, setList] = useState<DataType[]>([]);
const [roles, setRoles] = useState<any>([]); const [roles, setRoles] = useState<RolesModel>({});
const [userRoleIds, setUserRoleIds] = useState<any>({}); const [userRoleIds, setUserRoleIds] = useState<RoleIdsModel>({});
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [createVisible, setCreateVisible] = useState<boolean>(false); const [createVisible, setCreateVisible] = useState(false);
const [updateVisible, setUpdateVisible] = useState<boolean>(false); const [updateVisible, setUpdateVisible] = useState(false);
const [createRoleVisible, setCreateRoleVisible] = useState<boolean>(false); const [createRoleVisible, setCreateRoleVisible] = useState(false);
const [updateRoleVisible, setUpdateRoleVisible] = useState<boolean>(false); const [updateRoleVisible, setUpdateRoleVisible] = useState(false);
const [cid, setCid] = useState<number>(0); const [cid, setCid] = useState(0);
const [role_ids, setRoleIds] = useState<any>([]); const [role_ids, setRoleIds] = useState<number[]>([]);
const [selLabel, setLabel] = useState<string>("全部管理员"); const [selLabel, setLabel] = useState("全部管理员");
const [roleDelSuccess, setRoleDelSuccess] = useState(false); const [roleDelSuccess, setRoleDelSuccess] = useState(false);
const [isSuper, setIsSuper] = useState(false); const [isSuper, setIsSuper] = useState(false);
const [name, setName] = useState("");
const [name, setName] = useState<string>("");
const columns: ColumnsType<DataType> = [ const columns: ColumnsType<DataType> = [
{ {

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react"; import React, { useState } from "react";
import { Modal, Form } from "antd"; import { Modal, Form } from "antd";
interface PropInterface { interface PropInterface {
@ -15,7 +15,7 @@ export const AdminLogDetailDialog: React.FC<PropInterface> = ({
result, result,
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const onFinish = (values: any) => {}; const onFinish = (values: any) => {};

View File

@ -1,7 +1,6 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Table, Typography, Input, Button, DatePicker } from "antd"; import { Table, Typography, Input, Button, DatePicker } from "antd";
import { adminLog } from "../../../api"; import { adminLog } from "../../../api";
// import styles from "./index.module.less";
import type { ColumnsType } from "antd/es/table"; import type { ColumnsType } from "antd/es/table";
import { dateWholeFormat, transUtcTime } from "../../../utils/index"; import { dateWholeFormat, transUtcTime } from "../../../utils/index";
import { AdminLogDetailDialog } from "./compenents/detail-dialog"; import { AdminLogDetailDialog } from "./compenents/detail-dialog";
@ -11,28 +10,32 @@ import moment from "moment";
interface DataType { interface DataType {
id: React.Key; id: React.Key;
admin_id: number; admin_id: number;
ip: string;
opt: string;
admin_name: string; admin_name: string;
module: string;
created_at: string; created_at: string;
title: string; error_msg?: string;
ip: string;
ip_area: string; ip_area: string;
method: string;
module: string;
opt: number;
param: string; param: string;
request_method: string;
result: string; result: string;
title: string;
url: string;
} }
const SystemLogPage = () => { const SystemLogPage = () => {
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [size, setSize] = useState(10); const [size, setSize] = useState(10);
const [list, setList] = useState<any>([]); const [list, setList] = useState<DataType[]>([]);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
const [adminId, setAdminId] = useState(""); const [adminId, setAdminId] = useState("");
const [adminName, setAdminName] = useState(""); const [adminName, setAdminName] = useState("");
const [created_at, setCreatedAt] = useState<any>([]); const [created_at, setCreatedAt] = useState<string[]>([]);
const [createdAts, setCreatedAts] = useState<any>([]); const [createdAts, setCreatedAts] = useState<any>([]);
const [param, setParam] = useState(""); const [param, setParam] = useState("");
const [result, setResult] = useState(""); const [result, setResult] = useState("");

View File

@ -19,9 +19,9 @@ export const SystemAdminrolesCreate: React.FC<PropInterface> = ({
onCancel, onCancel,
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [permissions, setPermissions] = useState<any>([]); const [permissions, setPermissions] = useState<Option[]>([]);
const [actions, setActions] = useState<any>([]); const [actions, setActions] = useState<Option[]>([]);
useEffect(() => { useEffect(() => {
if (open) { if (open) {

View File

@ -31,9 +31,9 @@ export const SystemAdminrolesUpdate: React.FC<PropInterface> = ({
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [init, setInit] = useState(true); const [init, setInit] = useState(true);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState(true);
const [permissions, setPermissions] = useState<any>([]); const [permissions, setPermissions] = useState<Option[]>([]);
const [actions, setActions] = useState<any>([]); const [actions, setActions] = useState<Option[]>([]);
useEffect(() => { useEffect(() => {
if (open) { if (open) {

View File

@ -20,10 +20,10 @@ import type { CheckboxChangeEvent } from "antd/es/checkbox";
const SystemConfigPage = () => { const SystemConfigPage = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState(false);
const [logo, setLogo] = useState<string>(""); const [logo, setLogo] = useState("");
const [thumb, setThumb] = useState<string>(""); const [thumb, setThumb] = useState("");
const [avatar, setAvatar] = useState<string>(""); const [avatar, setAvatar] = useState("");
const [tabKey, setTabKey] = useState(1); const [tabKey, setTabKey] = useState(1);
const [nameChecked, setNameChecked] = useState(false); const [nameChecked, setNameChecked] = useState(false);
const [emailChecked, setEmailChecked] = useState(false); const [emailChecked, setEmailChecked] = useState(false);

122
src/playedu.d.ts vendored
View File

@ -15,6 +15,128 @@ declare global {
poster: string; //视频帧 poster: string; //视频帧
}; };
} }
interface UserModel {
avatar: string;
create_city?: string;
create_ip?: string;
created_at?: string;
credit1?: number;
email: string;
id: number;
id_card?: string;
is_active?: number;
is_lock?: number;
is_set_password?: number;
is_verify?: number;
login_at?: string;
name: string;
updated_at?: string;
verify_at?: string;
}
interface AdminUserDetailModel {
created_at: string;
email: string;
id: number;
is_ban_login: number;
login_at: string;
login_ip: string;
login_times: number;
name: string;
updated_at: string;
}
interface CourseModel {
charge: number;
class_hour: number;
created_at: string;
id: number;
is_required: number;
is_show: number;
short_desc: string;
thumb: string;
title: string;
}
interface CategoriesBoxModel {
[key: number]: CategoriesItemModel[];
}
interface CategoriesItemModel {
id: number;
name: string;
parent_chain: string;
parent_id: number;
sort: number;
}
interface CategoriesModel {
[key: number]: string;
}
interface DepartmentsModel {
[key: number]: string;
}
interface DepIdsModel {
[key: number]: number[];
}
interface CategoryIdsModel {
[key: number]: number[];
}
interface DepartmentsBoxModel {
[key: number]: DepartmentsItemModel[];
}
interface DepartmentsItemModel {
created_at: string;
id: number;
name: string;
parent_chain: string;
parent_id: number;
sort: number;
updated_at: string;
}
interface RolesModel {
[key: number]: RoleModel[];
}
interface RoleModel {
created_at: string;
id: number;
name: string;
slug: string;
updated_at: string;
}
interface RoleIdsModel {
[key: number]: number[];
}
interface CourseChaptersModel {
id?: number;
hours: CourseHourModel[];
name: string;
}
interface CourseHourModel {
id?: number;
duration: number;
name: string;
rid: number;
type: string;
}
interface AttachmentDataModel {
id?: number;
name: string;
rid: number;
type: string;
}
} }
export {}; export {};