Merge pull request #5 from PlayEdu/dev

Dev
This commit is contained in:
Teng 2023-05-10 10:57:43 +08:00 committed by GitHub
commit 24232ef396
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 172 additions and 62 deletions

View File

@ -119,8 +119,16 @@ export const LeftMenu: React.FC = () => {
};
useEffect(() => {
if (location.pathname.indexOf("/course/user") !== -1) {
setSelectedKeys(["/course"]);
setOpenKeys(openKeyMerge("/course"));
} else if (location.pathname.indexOf("/member/learn") !== -1) {
setSelectedKeys(["/member/index"]);
setOpenKeys(openKeyMerge("/member/index"));
} else {
setSelectedKeys([location.pathname]);
setOpenKeys(openKeyMerge(location.pathname));
}
}, [location.pathname]);
return (

View File

@ -0,0 +1,12 @@
import React from "react";
import { getToken } from "../../utils/index";
import { Navigate } from "react-router-dom";
interface PropInterface {
Component: any;
}
const PrivateRoute: React.FC<PropInterface> = ({ Component }) => {
return getToken() ? Component : <Navigate to="/login" replace={true} />;
};
export default PrivateRoute;

View File

@ -30,10 +30,10 @@ export const TreeDepartment = (props: PropInterface) => {
setUserTotal(res.data.user_total);
if (JSON.stringify(departments) !== "{}") {
if (props.showNum) {
const new_arr: any = checkNewArr(departments, 0, departCount);
const new_arr: any[] = checkNewArr(departments, 0, departCount);
setTreeData(new_arr);
} else {
const new_arr: Option[] = checkArr(departments, 0);
const new_arr: any[] = checkArr(departments, 0);
setTreeData(new_arr);
}
} else {
@ -87,13 +87,17 @@ export const TreeDepartment = (props: PropInterface) => {
for (let i = 0; i < departments[id].length; i++) {
if (!departments[departments[id][i].id]) {
arr.push({
title: departments[id][i].name,
title: (
<span className="tree-title-elli">{departments[id][i].name}</span>
),
key: departments[id][i].id,
});
} else {
const new_arr: Option[] = checkArr(departments, departments[id][i].id);
const new_arr: any[] = checkArr(departments, departments[id][i].id);
arr.push({
title: departments[id][i].name,
title: (
<span className="tree-title-elli">{departments[id][i].name}</span>
),
key: departments[id][i].id,
children: new_arr,
});
@ -105,16 +109,18 @@ export const TreeDepartment = (props: PropInterface) => {
const getNewTitle = (title: any, id: number, counts: any) => {
if (counts) {
let value = counts[id] || 0;
return title + "(" + value + ")";
return (
<span className="tree-title-elli">{title + "(" + value + ")"}</span>
);
} else {
return title;
return <span className="tree-title-elli">{title}</span>;
}
};
const onSelect = (selectedKeys: any, info: any) => {
let label = "全部" + props.text;
if (info) {
label = info.node.title;
label = info.node.title.props.children;
}
props.onUpdate(selectedKeys, label);
setSelectKey(selectedKeys);
@ -123,7 +129,7 @@ export const TreeDepartment = (props: PropInterface) => {
const onExpand = (selectedKeys: any, info: any) => {
let label = "全部" + props.text;
if (info) {
label = info.node.title;
label = info.node.title.props.children;
}
props.onUpdate(selectedKeys, label);
setSelectKey(selectedKeys);

View File

@ -23,7 +23,7 @@ code {
}
.w-174px {
max-width: 174px;
max-width: 134px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
@ -457,6 +457,7 @@ textarea.ant-input {
margin-bottom: 8px !important;
display: flex;
align-items: center !important;
&.ant-tree-treenode-selected {
background-color: #fff2f0 !important;
border-radius: 6px !important;
@ -559,9 +560,11 @@ textarea.ant-input {
.tree-title-elli {
width: 100%;
display: -webkit-box;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
.ant-tabs {

View File

@ -10,7 +10,7 @@ import {
message,
Image,
} from "antd";
import { course } from "../../api";
import { course as Course } from "../../api";
import { useParams, useLocation } from "react-router-dom";
import type { ColumnsType } from "antd/es/table";
import { BackBartment } from "../../compenents";
@ -33,7 +33,11 @@ const CourseUserPage = () => {
const params = useParams();
const result = new URLSearchParams(useLocation().search);
const [list, setList] = useState<any>([]);
const [users, setUsers] = useState<any>([]);
const [course, setCourse] = useState<any>({});
const [records, setRecords] = useState<any>({});
const [hourCount, setHourCount] = useState<any>({});
const [userDepIds, setUserDepIds] = useState<any>({});
const [departments, setDepartments] = useState<any>({});
const [refresh, setRefresh] = useState(false);
const [page, setPage] = useState(1);
const [size, setSize] = useState(10);
@ -55,11 +59,30 @@ const CourseUserPage = () => {
preview={false}
width={40}
height={40}
src={users.find((i: any) => i.id === record.user_id).avatar}
src={record.avatar}
></Image>
<span className="ml-8">
{users.find((i: any) => i.id === record.user_id).name}
<span className="ml-8">{record.name}</span>
</div>
),
},
{
title: "邮箱",
render: (_, record: any) => <span>{record.email}</span>,
},
{
title: "部门",
render: (_, record: any) => (
<div className="float-left">
{userDepIds[record.id] &&
userDepIds[record.id].map((item: any, index: number) => {
return (
<span key={index}>
{index === userDepIds[record.id].length - 1
? departments[item]
: departments[item] + "、"}
</span>
);
})}
</div>
),
},
@ -68,27 +91,72 @@ const CourseUserPage = () => {
dataIndex: "progress",
render: (_, record: any) => (
<span>
{record.finished_count} / {record.hour_count}
{(records[record.id] && records[record.id].finished_count) ||
0} /{" "}
{(records[record.id] && records[record.id].hour_count) ||
course.class_hour}
</span>
),
},
{
title: "第一次学习时间",
dataIndex: "created_at",
render: (text: string) => <span>{dateFormat(text)}</span>,
render: (_, record: any) => (
<>
{records[record.id] ? (
<span>{dateFormat(records[record.id].created_at)}</span>
) : hourCount[record.id] ? (
<span>{dateFormat(hourCount[record.id])}</span>
) : (
<span>-</span>
)}
</>
),
},
{
title: "学习完成时间",
dataIndex: "finished_at",
render: (text: string) => <span>{dateFormat(text)}</span>,
render: (_, record: any) => (
<>
{records[record.id] ? (
<span>{dateFormat(records[record.id].finished_at)}</span>
) : (
<span>-</span>
)}
</>
),
},
{
title: "学习进度",
dataIndex: "progress",
render: (progress: number) => (
<span className={progress >= 10000 ? "c-green" : "c-red"}>
{progress / 100}%
render: (_, record: any) => (
<>
{records[record.id] ? (
<span
className={
Math.floor(
(records[record.id].finished_count /
records[record.id].hour_count) *
100
) >= 100
? "c-green"
: "c-red"
}
>
{Math.floor(
(records[record.id].finished_count /
records[record.id].hour_count) *
100
)}
%
</span>
) : hourCount[record.id] ? (
<span className="c-red">1%</span>
) : (
<span className="c-red">0%</span>
)}
</>
),
},
];
@ -99,8 +167,7 @@ const CourseUserPage = () => {
const getList = () => {
setLoading(true);
course
.courseUser(
Course.courseUser(
Number(params.courseId),
page,
size,
@ -113,7 +180,11 @@ const CourseUserPage = () => {
.then((res: any) => {
setTotal(res.data.total);
setList(res.data.data);
setUsers(res.data.users);
setHourCount(res.data.user_course_hour_user_first_at);
setRecords(res.data.user_course_records);
setCourse(res.data.course);
setDepartments(res.data.departments);
setUserDepIds(res.data.user_dep_ids);
setLoading(false);
})
.catch((err: any) => {
@ -160,12 +231,12 @@ const CourseUserPage = () => {
okText: "确认",
cancelText: "取消",
onOk() {
course
.destroyCourseUser(Number(params.courseId), selectedRowKeys)
.then(() => {
Course.destroyCourseUser(Number(params.courseId), selectedRowKeys).then(
() => {
message.success("清除成功");
resetList();
});
}
);
},
onCancel() {
console.log("Cancel");

View File

@ -68,7 +68,7 @@ const DepartmentPage = () => {
arr.push({
title: (
<>
<div className="w-174px mr-24">{departments[id][i].name}</div>
<div className="tree-title-elli">{departments[id][i].name}</div>
<div className="d-flex">
<Tooltip placement="top" title="可拖拽排序">
<i
@ -103,7 +103,7 @@ const DepartmentPage = () => {
arr.push({
title: (
<>
<div className="w-174px mr-24">{departments[id][i].name}</div>
<div className="tree-title-elli">{departments[id][i].name}</div>
<div className="d-flex">
<Tooltip placement="top" title="可拖拽排序">
<i

View File

@ -31,6 +31,7 @@ const MemberLearnPage = () => {
const [currentCourses, setCurrentCourses] = useState<any>([]);
const [openCourses, setOpenCourses] = useState<any>([]);
const [records, setRecords] = useState<any>({});
const [hourCount, setHourCount] = useState<any>({});
const [total2, setTotal2] = useState(0);
const [refresh2, setRefresh2] = useState(false);
const [uid, setUid] = useState(Number(result.get("id")));
@ -153,6 +154,7 @@ const MemberLearnPage = () => {
setList2(res.data.departments);
setCourses(res.data.dep_courses);
setOpenCourses(res.data.open_courses);
setHourCount(res.data.user_course_hour_count);
setRecords(res.data.user_course_records);
if (res.data.departments.length > 0) {
let box: any = [];
@ -252,6 +254,8 @@ const MemberLearnPage = () => {
)}
%
</span>
) : hourCount[record.id] && hourCount[record.id] > 0 ? (
<span className="c-red">1%</span>
) : (
<span className="c-red">0%</span>
)}

View File

@ -66,7 +66,7 @@ const ResourceCategoryPage = () => {
arr.push({
title: (
<>
<div className="w-174px mr-24">{categories[id][i].name}</div>
<div className="tree-title-elli">{categories[id][i].name}</div>
<div className="d-flex">
<Tooltip placement="top" title="可拖拽排序">
<i
@ -101,7 +101,7 @@ const ResourceCategoryPage = () => {
arr.push({
title: (
<>
<div className="w-174px mr-24">{categories[id][i].name}</div>
<div className="tree-title-elli">{categories[id][i].name}</div>
<div className="d-flex">
<Tooltip placement="top" title="可拖拽排序">
<i

View File

@ -25,6 +25,7 @@ import SystemAdminrolesPage from "../pages/system/adminroles";
import DepartmentPage from "../pages/department";
import TestPage from "../pages/test";
import ErrorPage from "../pages/error";
import PrivateRoute from "../compenents/private-route";
// const LoginPage = lazy(() => import("../pages/login"));
@ -63,70 +64,75 @@ const routes: RouteObject[] = [
children: [
{
path: "/",
element: <HomePage />,
element: <PrivateRoute Component={<HomePage />} />,
children: [
{
path: "/",
element: <DashboardPage />,
element: <PrivateRoute Component={<DashboardPage />} />,
},
{
path: "/change-password",
element: <ChangePasswordPage />,
element: <PrivateRoute Component={<ChangePasswordPage />} />,
},
{
path: "/resource-category",
element: <ResourceCategoryPage />,
element: <PrivateRoute Component={<ResourceCategoryPage />} />,
},
{
path: "/images",
element: <ResourceImagesPage />,
element: <PrivateRoute Component={<ResourceImagesPage />} />,
},
{
path: "/videos",
element: <ResourceVideosPage />,
element: <PrivateRoute Component={<ResourceVideosPage />} />,
},
{
path: "/course",
element: <CoursePage />,
element: <PrivateRoute Component={<CoursePage />} />,
},
{
path: "/course/user/:courseId",
element: <CourseUserPage />,
element: <PrivateRoute Component={<CourseUserPage />} />,
},
{
path: "/member",
element: <KeepAlive />,
children: [
{ path: "/member/index", element: <MemberPage /> },
{
path: "/member/index",
element: <PrivateRoute Component={<MemberPage />} />,
},
{
path: "/member/import",
element: <MemberImportPage />,
element: <PrivateRoute Component={<MemberImportPage />} />,
},
{
path: "/member/learn",
element: <MemberLearnPage />,
element: <PrivateRoute Component={<MemberLearnPage />} />,
},
{
path: "/member/departmentUser",
element: <MemberDepartmentProgressPage />,
element: (
<PrivateRoute Component={<MemberDepartmentProgressPage />} />
),
},
],
},
{
path: "/system/config/index",
element: <SystemConfigPage />,
element: <PrivateRoute Component={<SystemConfigPage />} />,
},
{
path: "/system/administrator",
element: <SystemAdministratorPage />,
element: <PrivateRoute Component={<SystemAdministratorPage />} />,
},
{
path: "/system/adminroles",
element: <SystemAdminrolesPage />,
element: <PrivateRoute Component={<SystemAdminrolesPage />} />,
},
{
path: "/department",
element: <DepartmentPage />,
element: <PrivateRoute Component={<DepartmentPage />} />,
},
],
},